Skip to content

Commit

Permalink
Merge pull request #1 from brandad-group/v1-complete-profile
Browse files Browse the repository at this point in the history
complete v1 of profile
  • Loading branch information
juekr authored Jul 11, 2024
2 parents cbb4c30 + 1080a10 commit 6c9d493
Show file tree
Hide file tree
Showing 27 changed files with 1,187 additions and 21 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/publish-jobs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: "Publish Softgarden Jobs on Website"

on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
types: [ "closed" ]
schedule:
- cron: '1 7 * * *'

jobs:
generate-jobs:
runs-on: ubuntu-latest
environment: brandad.de
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install dependencies
run: pip install python-dotenv
- name: Exec python script
run: python job-api/main.py
163 changes: 163 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
job-api/.env

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# .github
[![](assets/brandad_title_banner.jpg)](profile/README.md)

# Hi. Wir sind BRANDAD. 👋

=> [Read me.](profile/README.md)
Binary file added assets/brandad_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/brandad_title_banner.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/developer-thumb.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/developer.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/natalia-thumb.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/natalia.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/paths.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/recommendation-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/recommendation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/rocket-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/rocket.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions job-api/ftp_uploader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from ftplib import FTP_TLS
import os

class FTPUploader:
user:str = ""
password:str = ""
default_server_address:str = ""

def __init__(self, user = None, password = None, server = None) -> None:
self.user = user if user is not None else os.getenv("FTP_USER", "")
self.password = password if password is not None else os.getenv("FTP_PASSWORD", "")
self.server = server if server is None else os.getenv('FTP_SERVER', '')

def upload(self, file, target_filename = "jobs.csv", server = None)->bool:
if server is None:
server = self.default_server_address
target_filename = os.path.basename(file)
try:
session = FTP_TLS(server,self.user,self.password)
session.prot_p()
binary_file = open(file,'rb') # file to send
session.storbinary(f'STOR {target_filename}', binary_file) # send the file
binary_file.close() # close file and FTP
session.quit()
return True
except Exception as e:
print(e)
return False
75 changes: 75 additions & 0 deletions job-api/job_fetcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import requests
import csv
import os
from dotenv import load_dotenv
from pathlib import Path

class JobFetcher:
def __init__(self, csv_path = None):
load_dotenv()
self.client_id = os.getenv("CLIENT_ID")
self.password = os.getenv("PASSWORD")
self.api_path = os.getenv("API_PATH")
self.base_url = "https://api.softgarden.io"
self.job_or_trainee_mappings = {
"2": "Auszubildendenstelle",
"6": "Festanstellung",
"fe9a669ca70d49a88d972a860742b379": "Aushilfe"
}
self.job_or_trainee_default = "6"
self.job_or_trainee_category_name = "Stellentyp"
self.full_or_parttime_mappings = {
"799eb9d2c0bc4e7490fde05f847b331a": "Teilzeitstelle",
"137caf67764c4b63b0272895af1704b0": "Vollzeitstelle",
"87af1987840d4442b87f2e0ee3344a1f": "Voll- oder Teilzeit"
}
self.full_or_parttime_default = "137caf67764c4b63b0272895af1704b0"
self.full_or_parttime_name = "Arbeitszeit"
self.jobexperience_mappings = {
"1b4f51fe628c4119a2d7a581557d0944": "mit Berufserfahrung"
}

if not all([self.client_id, self.password, self.api_path]):
raise ValueError('Check your .env variables!')

if csv_path is None:
p = Path(__file__).parent.resolve()
csv_path = p / "jobs.csv"
self.csv_path = csv_path

def fetch_jobs(self):
joblist_url = self.base_url + str(self.api_path)
try:
response = requests.get(joblist_url, auth=(self.client_id, self.password))
response.encoding = 'utf-8'
jobs = response.json()["results"]
self.process_jobs(jobs)
except Exception as e:
print(f"API request failed: {e}")
exit(1)

def process_jobs(self, jobs):
csv_keys = list(jobs[0].keys()) + [self.job_or_trainee_category_name, self.full_or_parttime_name]
try:
with open(self.csv_path, "w", encoding='utf8') as file:
dw = csv.DictWriter(file, csv_keys, delimiter=";")
dw.writeheader()
for row in jobs:
row[self.job_or_trainee_category_name] = self.map_values(row, self.job_or_trainee_mappings, self.job_or_trainee_default, self.job_or_trainee_category_name)
row[self.full_or_parttime_name] = self.map_values(row, self.full_or_parttime_mappings, self.full_or_parttime_default, self.full_or_parttime_name)
dw.writerow(row)
except Exception as e:
print(f"Writing CSV failed: {e}")
exit(1)

def map_values(self, row, mapping_dict, default_value, field_name):
try:
values = [mapping_dict[str(val)] for val in row[field_name] if str(val) in mapping_dict]
return ", ".join(values)
except KeyError:
return mapping_dict[default_value]

# Example usage:
if __name__ == '__main__':
job_fetcher = JobFetcher()
job_fetcher.fetch_jobs()
Loading

0 comments on commit 6c9d493

Please sign in to comment.