forked from Mirroring/github-release-notifier
API to manage subscription
Adapt docker part Improve log Add a just target
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
FROM python:3.10-alpine3.18
|
FROM python:3.10-alpine3.18
|
||||||
|
|
||||||
RUN pip install requests
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
COPY requirements.txt /app/requirements.txt
|
||||||
|
RUN pip install --no-cache-dir --upgrade --requirement requirements.txt
|
||||||
COPY notifier.py template.html /app/
|
COPY notifier.py template.html /app/
|
||||||
|
|
||||||
# TODO Dev purporse
|
# TODO Dev purporse
|
||||||
COPY conf.ini /app/conf.ini
|
COPY conf.ini /app/conf.ini
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
ENTRYPOINT ["python3", "/app/notifier.py"]
|
ENTRYPOINT ["python3", "/app/notifier.py"]
|
||||||
|
CMD ["uvicorn", "notifier:app", "--host", "0.0.0.0", "--port", "80"]
|
||||||
|
|||||||
4
Justfile
4
Justfile
@@ -12,6 +12,10 @@ remote_build_image := remote_image_name + ":" + last_commit_sha1
|
|||||||
run: _ensure_venv_is_ok
|
run: _ensure_venv_is_ok
|
||||||
{{ python }} notifier.py
|
{{ python }} notifier.py
|
||||||
|
|
||||||
|
# Launch the API
|
||||||
|
api: _ensure_venv_is_ok
|
||||||
|
{{ venv }}/bin/uvicorn notifier:app --reload
|
||||||
|
|
||||||
# Init python virtual env
|
# Init python virtual env
|
||||||
init:
|
init:
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ services:
|
|||||||
image: github-release-notifier
|
image: github-release-notifier
|
||||||
container_name: github-release-notifier
|
container_name: github-release-notifier
|
||||||
volumes:
|
volumes:
|
||||||
- ./conf.ini:/app/conf.ini
|
- ./conf.ini:/app/conf.ini
|
||||||
|
ports:
|
||||||
|
- 8000:80
|
||||||
|
|
||||||
mailpit:
|
mailpit:
|
||||||
image: axllent/mailpit
|
image: axllent/mailpit
|
||||||
ports:
|
ports:
|
||||||
- "8025:8025"
|
- 8025:8025
|
||||||
- "1025:1025"
|
- 1025:1025
|
||||||
|
|
||||||
ofelia:
|
ofelia:
|
||||||
image: mcuadros/ofelia:latest
|
image: mcuadros/ofelia:latest
|
||||||
|
|||||||
58
notifier.py
58
notifier.py
@@ -8,6 +8,11 @@ from email.mime.multipart import MIMEMultipart
|
|||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
SCRIPT_DIR = os.path.dirname(__file__)
|
||||||
|
CONF_FILE = os.path.join(SCRIPT_DIR, "conf.ini")
|
||||||
|
TEMPLATE_FILE = os.path.join(SCRIPT_DIR, "template.html")
|
||||||
|
|
||||||
|
|
||||||
class EnvInjection(configparser.Interpolation):
|
class EnvInjection(configparser.Interpolation):
|
||||||
@@ -26,15 +31,51 @@ class EnvInjection(configparser.Interpolation):
|
|||||||
return env_value if env_value else file_value
|
return env_value if env_value else file_value
|
||||||
|
|
||||||
|
|
||||||
def main():
|
#
|
||||||
script_dir = os.path.dirname(__file__)
|
# API PARTS
|
||||||
conf_file = os.path.join(script_dir, "conf.ini")
|
#
|
||||||
template_file = os.path.join(script_dir, "template.html")
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/subscriptions")
|
||||||
|
def get_projects():
|
||||||
|
parser = load_conf()
|
||||||
|
projects = json.loads(parser["projects"].get("projects"))
|
||||||
|
return projects
|
||||||
|
|
||||||
|
|
||||||
|
@app.put("/subscriptions")
|
||||||
|
def put_projects(project: str, author: str | None = None):
|
||||||
|
# TODO Check if project really exist?
|
||||||
|
parser = load_conf()
|
||||||
|
projects = json.loads(parser.get("projects", "projects"))
|
||||||
|
|
||||||
|
if author:
|
||||||
|
project = f"{author}/{project}"
|
||||||
|
projects.append(project)
|
||||||
|
|
||||||
|
# TODO Watch a converter for list: https://stackoverflow.com/a/53274707/1346391
|
||||||
|
parser.set("projects", "projects", json.dumps(projects, indent=0))
|
||||||
|
|
||||||
|
with open("conf.ini", "w", encoding="utf-8") as configfile:
|
||||||
|
parser.write(configfile)
|
||||||
|
|
||||||
|
return project
|
||||||
|
|
||||||
|
|
||||||
|
def load_conf(conf_file=CONF_FILE) -> configparser.ConfigParser:
|
||||||
parser = configparser.ConfigParser(
|
parser = configparser.ConfigParser(
|
||||||
default_section="config", interpolation=EnvInjection()
|
default_section="config", interpolation=EnvInjection()
|
||||||
)
|
)
|
||||||
parser.read(conf_file)
|
parser.read(conf_file)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# SCRIPT PART
|
||||||
|
#
|
||||||
|
def main():
|
||||||
|
parser = load_conf()
|
||||||
default_config = parser["config"]
|
default_config = parser["config"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -67,8 +108,10 @@ def main():
|
|||||||
return
|
return
|
||||||
|
|
||||||
content = ""
|
content = ""
|
||||||
|
news = []
|
||||||
|
|
||||||
for new_r in new_releases:
|
for new_r in new_releases:
|
||||||
|
news.append(new_r["project_name"])
|
||||||
content += f"""
|
content += f"""
|
||||||
<li>{get_html_project_link(new_r)}
|
<li>{get_html_project_link(new_r)}
|
||||||
: new release
|
: new release
|
||||||
@@ -77,6 +120,7 @@ def main():
|
|||||||
(published {convert_date(new_r["published_date"])})</li>"""
|
(published {convert_date(new_r["published_date"])})</li>"""
|
||||||
|
|
||||||
for new_p in new_projects:
|
for new_p in new_projects:
|
||||||
|
news.append(new_p["project_name"])
|
||||||
content += f"""
|
content += f"""
|
||||||
<li>{get_html_project_link(new_p)}
|
<li>{get_html_project_link(new_p)}
|
||||||
was added to your configuration.
|
was added to your configuration.
|
||||||
@@ -84,10 +128,11 @@ def main():
|
|||||||
{get_html_release_link(new_p)}
|
{get_html_release_link(new_p)}
|
||||||
(published {convert_date(new_p["published_date"])})</li>"""
|
(published {convert_date(new_p["published_date"])})</li>"""
|
||||||
|
|
||||||
with open(template_file, "r", encoding="utf-8") as f_template:
|
with open(TEMPLATE_FILE, "r", encoding="utf-8") as f_template:
|
||||||
template = f_template.read()
|
template = f_template.read()
|
||||||
|
|
||||||
send_mail(template.replace("{{content}}", content), default_config)
|
send_mail(template.replace("{{content}}", content), default_config)
|
||||||
|
print(f"Send a mail for new releases and projects on: {', '.join(news)}")
|
||||||
|
|
||||||
with open("conf.ini", "w", encoding="utf-8") as configfile:
|
with open("conf.ini", "w", encoding="utf-8") as configfile:
|
||||||
parser.write(configfile)
|
parser.write(configfile)
|
||||||
@@ -97,8 +142,7 @@ def get_last_release(project):
|
|||||||
url = f"https://api.github.com/repos/{project}/releases/latest"
|
url = f"https://api.github.com/repos/{project}/releases/latest"
|
||||||
result = requests.get(url, timeout=10)
|
result = requests.get(url, timeout=10)
|
||||||
|
|
||||||
print(project)
|
print(f"Check {project} - {url}")
|
||||||
print(url)
|
|
||||||
release = result.json()
|
release = result.json()
|
||||||
release_tag = release["tag_name"]
|
release_tag = release["tag_name"]
|
||||||
published_date = release["published_at"]
|
published_date = release["published_at"]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
requests
|
|
||||||
pre-commit
|
|
||||||
black
|
black
|
||||||
|
fastapi
|
||||||
|
pre-commit
|
||||||
|
requests
|
||||||
|
uvicorn[standard]
|
||||||
|
|||||||
Reference in New Issue
Block a user