4 Commits

Author SHA1 Message Date
08d27d3183 Ofelia & Docker update 2023-12-30 01:19:42 +01:00
9d5e50c635 Update README 2023-12-30 01:19:24 +01:00
eea62d8685 Use a configurable TOTP protection 2023-12-30 01:19:24 +01:00
9a8a7042b3 API to manage subscription
Adapt docker part
Improve log
Add a just target
2023-12-30 01:19:24 +01:00
13 changed files with 178 additions and 864 deletions

2
.gitattributes vendored
View File

@@ -1,2 +0,0 @@
# GitHub syntax highlighting
pixi.lock linguist-language=YAML

4
.gitignore vendored
View File

@@ -1,4 +0,0 @@
# pixi environments
.pixi
mailpit
.bin

View File

@@ -1,10 +1,12 @@
FROM python:3.10-alpine3.18
RUN pip install requests
WORKDIR /app
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade --requirement requirements.txt
COPY notifier.py template.html /app/
# TODO Dev purporse
COPY conf.ini /app/conf.ini
ENTRYPOINT ["python3", "/app/notifier.py"]
EXPOSE 80
CMD ["uvicorn", "notifier:app", "--host", "0.0.0.0", "--port", "80"]

View File

@@ -1,21 +1,41 @@
# https://github.com/casey/just
python := "pixi run python"
venv := "./venv"
pip := venv / "bin/pip"
python := venv / "bin/python"
last_commit_sha1 := `git rev-parse --short HEAD`
remote_image_name := "gitea.gdemontauzan.fr/maxenceg2m/github-release-notifier"
remote_build_image := remote_image_name + ":" + last_commit_sha1
# Run the script
run: init
run: _ensure_venv_is_ok
{{ python }} notifier.py
# Init python env with pixi
init:
pixi install
# Launch the API
api: _ensure_venv_is_ok
{{ venv }}/bin/uvicorn notifier:app --reload
# Remove virtual env (pixi)
# Init python virtual env
init:
python3 -m venv venv
{{ pip }} install --requirement requirements.txt
sha256sum requirements.txt > {{ venv }}/requirements.sha
# Inspiration: https://github.com/behave/behave/blob/afb6b6716cd0f3e028829416475312db804a6aa9/justfile
_ensure_venv_is_ok:
#!/usr/bin/env python3
from subprocess import run
from os import path
if run("sha256sum -c {{ venv }}/requirements.sha", shell=True).returncode != 0:
run("just init", shell=True)
# Clean workspace - remove venv - and init
reinit: hclean init
# Remove virtual env (venv)
hclean:
rm -fr .pixi
rm -fr venv
# Run docker compose then show logs
dup: dbuild
@@ -49,14 +69,3 @@ release version: dbuild
docker push {{ remote_image_name }}:{{ version }}
git tag -a v{{ version }} -m ""
git push --tags
# MAILPIT PART
mailpit_version := "v1.11.0"
mailpit_archi := "linux-amd64"
mailpit_output := "mailpit-" + mailpit_version + "-" + mailpit_archi + ".tar.gz"
# Retrive mailpit bin
get-mail-wrapper:
echo {{mailpit_output}}
curl -L https://github.com/axllent/mailpit/releases/download/{{mailpit_version}}/mailpit-{{mailpit_archi}}.tar.gz --output {{mailpit_output}}
tar xf {{mailpit_output}} mailpit

View File

@@ -1,32 +0,0 @@
ARCH ?= x86_64-unknown-linux-musl
JUST_VERSION ?= 1.16.0
JUST_TGZ ?= just-$(JUST_VERSION)-$(ARCH).tar.gz
PIXI_VERSION ?= 0.10.0
PIXI_TGZ ?= pixi-$(PIXI_VERSION)-$(ARCH).tar.gz
all: just pixi
@echo "You can add .bin folder in your path to enjoy pixi and just:" 'export PATH=$$PATH:$$(pwd)/.bin'
PATH=$$PATH:$(pwd)/.bin just
just: .bin/just
.bin/just: init .bin/$(JUST_TGZ)
tar xf ./.bin/$(JUST_TGZ) -C ./.bin just
@echo "just downloaded. Run './.bin/just' command to exec"
.bin/$(JUST_TGZ):
curl -L https://github.com/casey/just/releases/download/$(JUST_VERSION)/just-$(JUST_VERSION)-$(ARCH).tar.gz -o ./.bin/$(JUST_TGZ)
pixi: .bin/pixi
.bin/pixi: init .bin/$(PIXI_TGZ)
tar xf ./.bin/$(PIXI_TGZ) -C ./.bin ./pixi
@echo "pixi downloaded. Run './.bin/pixi' command to exec"
.bin/$(PIXI_TGZ):
curl -L https://github.com/prefix-dev/pixi/releases/download/v$(PIXI_VERSION)/pixi-$(ARCH).tar.gz -o ./.bin/$(PIXI_TGZ)
init:
mkdir -p .bin

View File

@@ -12,33 +12,71 @@ Why using configuration?...
------------------------
...instead use stared project of your Github account?
Cause I've got about 80 "stared" projects and I don't wan't to be alerted for new releases of each of these project.
But, perhaps I'll add such a feature later on...
And, Github API limits is at 60 requests by seconds, and I want to write this script really quickly in a first time.
But, perhaps I'll add such a feature later on...
How to use?
-----------
Really simple!
* Edit conf.ini file to set `[config]` section
* Install dependances: `pip install -r requirements.txt`
* Edit conf.ini file to set `[config]` section:
* your SMTP server configuration (host and port)
* sender mail
* receiver mail (:warning: not tested with more than 1 receiver)
* Add the projects you want to follow in the section `[project]`
* ...or use environment variable - same name but in upper case e.g. `SMTP_PORT`
* Add projects you want to follow in the section `[project]`
* Be careful to follow a JSON valid syntax as in the provided file, i.e. coma after each `autor/project` except the last one.
Execute the script: `python notifier.py`
After first execution, the `conf.ini` file will be filled with last release tag found by the script, as you can see in the provided file.
Hope you like, and have fun to read your mail!
Hey, what is this API?
--------------------------
Since it's not really conveniant to go on a VM and edit the config.ini every time I find a cool new project whose new versions I want to keep track of, there is an API to do this.
This is a really simple thing with no verification: you can add everything that you want!
Just one endpoint: `subscription`, and two method: GET and PUT.
PUT take three parameters:
* `project`: full project name e.g. `MaxenceG2M/github-release-notifier` or "short" name (without author) e.g. `github-release-notifier`
* (optionnal) `author`: the author of the repository
* (optionnal) `credentials`: just the TOTP check code.
Indeed, to have a minimal better-than-nothing protection, I opted for a simple TOTP code. No user/password or wathever.
You can disable-it in the `config.ini`, or specify a custom key.
If you don't specify a key, information will be displayed at startup (URL and the actual code. Be quick to check if it's ok!).
To start the API:
```sh
$ uvicorn notifier:app
TOTP enabled.
Information: otpauth://totp/Secret?secret=mysuperkey
TOTP check: 377826
INFO: Started server process [28264]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Cron-it with [ofelia](https://github.com/mcuadros/ofelia)
---------------------------------------------------------
Ofelia is very conveniant for croning the verification part while letting the API run continuously.
So the `docker-compose.yml` use it to do this :)
<3
Problems I have to solve really quickly
---------------------------------------
I wrote this script really quickly, certainly faster than this README. So I already have two big proglems:
* The script sends mail even if no new projets or release has been detected
* The biggest, you have to edit script to specify absolute path...
* A lot of other little problems, like the code that's disgusting and so on.
One script to do all things.
For who's asking: yes, it's normal that I have put all code in one main function [like a blind gunner.](https://media.giphy.com/media/1yMexL5rkwYhuiVEmZ/giphy.gif). Really quickly I said!
For who's asking: yes, it's normal that I have put all code in ~~one main function~~ one main script [like a blind gunner.](https://media.giphy.com/media/1yMexL5rkwYhuiVEmZ/giphy.gif).
I want to keep this script as simple as possible.
But overall, the script works and sends mail!
@@ -47,35 +85,3 @@ Hey boy, what is the `pit.db` file?
Oh, just for fun, and because I love this project, I use [pit by michaeldv](https://github.com/michaeldv/pit) to follow my task etc.
It makes me think I should push my python version of this project on occasion when I will take the time to do...
How to build it?
----------------
This project use two very cool projets to handle env & build:
- [**just**](https://github.com/casey/just) as an alternative to [GNU Make](https://www.gnu.org/software/make/manual/make.html)
- [**pixi**](https://github.com/prefix-dev/pixi) to manage python & dependancies environnment without question
You can install these two software by your way, or use the Makefile to do it: `$ make`.
This command will download & untar `just` and `pixie` into a hidden `.bin` folder and launch just target to do the rest.
> Don't forget to set a valid SMTP host/port in `config.ini`. Otherwise, notifier execution will fail. See below if you want to get a wrapper
Just's targets permit to:
- just run the script
- build a docker image
- create a release
- etc.
Use `.bin/just --list` to list all available target.
### Use mailpit to wrap mails
If you don't want to really send and receive mail, e.g. to test... things! I recommand [**mailpit**](https://github.com/axllent/mailpit).
You can quickly get it with just: `.bin/just get-mail-wrapper`.
Then execute-it: `./mailpit`.
By default, SMTP port is `1025`, and HTTP port to access to interface is `8025`.

View File

@@ -5,6 +5,10 @@ smtp_server = mailpit
sender_email = sender@host.eu
receiver_email = receiver@anotherhost.eu
[api.totp]
enabled = true
key = mysuperkey
[projects]
projects = [
"borgbackup/borg",

View File

@@ -6,13 +6,15 @@ services:
image: github-release-notifier
container_name: github-release-notifier
volumes:
- ./conf.ini:/app/conf.ini
- ./conf.ini:/app/conf.ini
ports:
- 8000:80
mailpit:
image: axllent/mailpit
ports:
- "8025:8025"
- "1025:1025"
- 8025:8025
- 1025:1025
ofelia:
image: mcuadros/ofelia:latest

View File

@@ -7,7 +7,17 @@ import sys
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import pyotp
import requests
from fastapi import FastAPI, status
from fastapi.responses import JSONResponse
#
# CONF PART
#
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):
@@ -26,15 +36,79 @@ class EnvInjection(configparser.Interpolation):
return env_value if env_value else file_value
def main():
script_dir = os.path.dirname(__file__)
conf_file = os.path.join(script_dir, "conf.ini")
template_file = os.path.join(script_dir, "template.html")
def load_conf(conf_file=CONF_FILE) -> configparser.ConfigParser:
parser = configparser.ConfigParser(
default_section="config", interpolation=EnvInjection()
)
parser.read(conf_file)
return parser
def load_totp():
parser = load_conf()
if parser.getboolean("api.totp", "enabled", fallback=True):
totp = pyotp.TOTP(parser.get("api.totp", "key", fallback=pyotp.random_base32()))
# TODO Catch totp.now() error
print(
f"""TOTP enabled.
Information: {totp.provisioning_uri()}
TOTP check: {totp.now()}"""
)
return totp
else:
print("WARNING: Api is open without security")
return type("totp", (object,), {"verify": lambda str: True})
#
# API PARTS
#
app = FastAPI()
TOTP = load_totp()
@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, credentials: str | None = None
):
if not TOTP.verify(credentials):
return JSONResponse(
status_code=status.HTTP_401_UNAUTHORIZED, content="Unauthorized"
)
# TODO Check if project really exist?
parser = load_conf()
projects = json.loads(parser.get("projects", "projects"))
if author:
project = f"{author}/{project}"
if project in projects:
return 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 JSONResponse(status_code=status.HTTP_201_CREATED, content=project)
#
# SCRIPT PART
#
def main():
parser = load_conf()
default_config = parser["config"]
try:
@@ -67,8 +141,10 @@ def main():
return
content = ""
news = []
for new_r in new_releases:
news.append(new_r["project_name"])
content += f"""
<li>{get_html_project_link(new_r)}
: new release
@@ -77,6 +153,7 @@ def main():
(published {convert_date(new_r["published_date"])})</li>"""
for new_p in new_projects:
news.append(new_p["project_name"])
content += f"""
<li>{get_html_project_link(new_p)}
was added to your configuration.
@@ -84,10 +161,11 @@ def main():
{get_html_release_link(new_p)}
(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()
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:
parser.write(configfile)
@@ -97,8 +175,7 @@ def get_last_release(project):
url = f"https://api.github.com/repos/{project}/releases/latest"
result = requests.get(url, timeout=10)
print(project)
print(url)
print(f"Check {project} - {url}")
release = result.json()
release_tag = release["tag_name"]
published_date = release["published_at"]

View File

@@ -4,6 +4,7 @@ smtp-port = 1025
email-to = max@ence.fr
email-from = ofelia@container.sh
[job-run "notifier"]
[job-exec "notifier"]
schedule = @every 30s
container = github-release-notifier
command = python3 /app/notifier.py

735
pixi.lock
View File

@@ -1,735 +0,0 @@
version: 3
metadata:
content_hash:
linux-64: e90c2ee71ad70fc0a1c8302029533a7d1498f2bffcd0eaa8d2934700e775dc1d
channels:
- url: https://conda.anaconda.org/conda-forge/
used_env_vars: []
platforms:
- linux-64
sources: []
time_metadata: null
git_metadata: null
inputs_metadata: null
custom_metadata: null
package:
- platform: linux-64
name: _libgcc_mutex
version: '0.1'
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
hash:
md5: d7c89558ba9fa0495403155b64376d81
sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726
build: conda_forge
arch: x86_64
subdir: linux-64
build_number: 0
license: None
size: 2562
timestamp: 1578324546067
- platform: linux-64
name: _openmp_mutex
version: '4.5'
category: main
manager: conda
dependencies:
- _libgcc_mutex 0.1 conda_forge
- libgomp >=7.5.0
url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
hash:
md5: 73aaf86a425cc6e73fcf236a5a46396d
sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22
build: 2_gnu
arch: x86_64
subdir: linux-64
build_number: 16
constrains:
- openmp_impl 9999
license: BSD-3-Clause
license_family: BSD
size: 23621
timestamp: 1650670423406
- platform: linux-64
name: black
version: 23.11.0
category: main
manager: conda
dependencies:
- click >=8.0.0
- mypy_extensions >=0.4.3
- packaging >=22.0
- pathspec >=0.9
- platformdirs >=2
- python >=3.12,<3.13.0a0
- python_abi 3.12.* *_cp312
url: https://conda.anaconda.org/conda-forge/linux-64/black-23.11.0-py312h7900ff3_0.conda
hash:
md5: a0b80edb299377d3fa8233d43a19f11e
sha256: 1b6cd73fb6d39d45e2010a8cf2c2b82ab6d36323f4f9717f1550e80ca802f986
build: py312h7900ff3_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
size: 366103
timestamp: 1701335795851
- platform: linux-64
name: brotli-python
version: 1.1.0
category: main
manager: conda
dependencies:
- libgcc-ng >=12
- libstdcxx-ng >=12
- python >=3.12.0rc3,<3.13.0a0
- python_abi 3.12.* *_cp312
url: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h30efb56_1.conda
hash:
md5: 45801a89533d3336a365284d93298e36
sha256: b68706698b6ac0d31196a8bcb061f0d1f35264bcd967ea45e03e108149a74c6f
build: py312h30efb56_1
arch: x86_64
subdir: linux-64
build_number: 1
constrains:
- libbrotlicommon 1.1.0 hd590300_1
license: MIT
license_family: MIT
size: 350604
timestamp: 1695990206327
- platform: linux-64
name: bzip2
version: 1.0.8
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda
hash:
md5: 69b8b6202a07720f448be700e300ccf4
sha256: 242c0c324507ee172c0e0dd2045814e746bb303d1eb78870d182ceb0abc726a8
build: hd590300_5
arch: x86_64
subdir: linux-64
build_number: 5
license: bzip2-1.0.6
license_family: BSD
size: 254228
timestamp: 1699279927352
- platform: linux-64
name: ca-certificates
version: 2023.11.17
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.11.17-hbcca054_0.conda
hash:
md5: 01ffc8d36f9eba0ce0b3c1955fa780ee
sha256: fb4b9f4b7d885002db0b93e22f44b5b03791ef3d4efdc9d0662185a0faafd6b6
build: hbcca054_0
arch: x86_64
subdir: linux-64
build_number: 0
license: ISC
size: 154117
timestamp: 1700280881924
- platform: linux-64
name: certifi
version: 2023.11.17
category: main
manager: conda
dependencies:
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/certifi-2023.11.17-pyhd8ed1ab_0.conda
hash:
md5: 2011bcf45376341dd1d690263fdbc789
sha256: afa22b77128a812cb57bc707c297d926561bd225a3d9dd74205d87a3b2d14a96
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: ISC
noarch: python
size: 158939
timestamp: 1700303562512
- platform: linux-64
name: charset-normalizer
version: 3.3.2
category: main
manager: conda
dependencies:
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda
hash:
md5: 7f4a9e3fcff3f6356ae99244a014da6a
sha256: 20cae47d31fdd58d99c4d2e65fbdcefa0b0de0c84e455ba9d6356a4bdbc4b5b9
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
noarch: python
size: 46597
timestamp: 1698833765762
- platform: linux-64
name: click
version: 8.1.7
category: main
manager: conda
dependencies:
- __unix
- python >=3.8
url: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda
hash:
md5: f3ad426304898027fc619827ff428eca
sha256: f0016cbab6ac4138a429e28dbcb904a90305b34b3fe41a9b89d697c90401caec
build: unix_pyh707e725_0
arch: x86_64
subdir: linux-64
build_number: 0
license: BSD-3-Clause
license_family: BSD
noarch: python
size: 84437
timestamp: 1692311973840
- platform: linux-64
name: idna
version: '3.6'
category: main
manager: conda
dependencies:
- python >=3.6
url: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda
hash:
md5: 1a76f09108576397c41c0b0c5bd84134
sha256: 6ee4c986d69ce61e60a20b2459b6f2027baeba153f0a64995fd3cb47c2cc7e07
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: BSD-3-Clause
license_family: BSD
noarch: python
size: 50124
timestamp: 1701027126206
- platform: linux-64
name: ld_impl_linux-64
version: '2.40'
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda
hash:
md5: 7aca3059a1729aa76c597603f10b0dd3
sha256: f6cc89d887555912d6c61b295d398cff9ec982a3417d38025c45d5dd9b9e79cd
build: h41732ed_0
arch: x86_64
subdir: linux-64
build_number: 0
constrains:
- binutils_impl_linux-64 2.40
license: GPL-3.0-only
license_family: GPL
size: 704696
timestamp: 1674833944779
- platform: linux-64
name: libexpat
version: 2.5.0
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda
hash:
md5: 6305a3dd2752c76335295da4e581f2fd
sha256: 74c98a563777ae2ad71f1f74d458a8ab043cee4a513467c159ccf159d0e461f3
build: hcb278e6_1
arch: x86_64
subdir: linux-64
build_number: 1
constrains:
- expat 2.5.0.*
license: MIT
license_family: MIT
size: 77980
timestamp: 1680190528313
- platform: linux-64
name: libffi
version: 3.4.2
category: main
manager: conda
dependencies:
- libgcc-ng >=9.4.0
url: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2
hash:
md5: d645c6d2ac96843a2bfaccd2d62b3ac3
sha256: ab6e9856c21709b7b517e940ae7028ae0737546122f83c2aa5d692860c3b149e
build: h7f98852_5
arch: x86_64
subdir: linux-64
build_number: 5
license: MIT
license_family: MIT
size: 58292
timestamp: 1636488182923
- platform: linux-64
name: libgcc-ng
version: 13.2.0
category: main
manager: conda
dependencies:
- _libgcc_mutex 0.1 conda_forge
- _openmp_mutex >=4.5
url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_3.conda
hash:
md5: 23fdf1fef05baeb7eadc2aed5fb0011f
sha256: 5e88f658e07a30ab41b154b42c59f079b168acfa9551a75bdc972099453f4105
build: h807b86a_3
arch: x86_64
subdir: linux-64
build_number: 3
constrains:
- libgomp 13.2.0 h807b86a_3
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
size: 773629
timestamp: 1699753612541
- platform: linux-64
name: libgomp
version: 13.2.0
category: main
manager: conda
dependencies:
- _libgcc_mutex 0.1 conda_forge
url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_3.conda
hash:
md5: 7124cbb46b13d395bdde68f2d215c989
sha256: 6ebedee39b6bbbc969715d0d7fa4b381cce67e1139862604ffa393f821c08e81
build: h807b86a_3
arch: x86_64
subdir: linux-64
build_number: 3
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
size: 421834
timestamp: 1699753531479
- platform: linux-64
name: libnsl
version: 2.0.1
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda
hash:
md5: 30fd6e37fe21f86f4bd26d6ee73eeec7
sha256: 26d77a3bb4dceeedc2a41bd688564fe71bf2d149fdcf117049970bc02ff1add6
build: hd590300_0
arch: x86_64
subdir: linux-64
build_number: 0
license: LGPL-2.1-only
license_family: GPL
size: 33408
timestamp: 1697359010159
- platform: linux-64
name: libsqlite
version: 3.44.2
category: main
manager: conda
dependencies:
- libgcc-ng >=12
- libzlib >=1.2.13,<1.3.0a0
url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.44.2-h2797004_0.conda
hash:
md5: 3b6a9f225c3dbe0d24f4fedd4625c5bf
sha256: ee2c4d724a3ed60d5b458864d66122fb84c6ce1df62f735f90d8db17b66cd88a
build: h2797004_0
arch: x86_64
subdir: linux-64
build_number: 0
license: Unlicense
size: 845830
timestamp: 1700863204572
- platform: linux-64
name: libstdcxx-ng
version: 13.2.0
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_3.conda
hash:
md5: 937eaed008f6bf2191c5fe76f87755e9
sha256: 6c6c49efedcc5709a66f19fb6b26b69c6a5245310fd1d9a901fd5e38aaf7f882
build: h7e041cc_3
arch: x86_64
subdir: linux-64
build_number: 3
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
size: 3842940
timestamp: 1699753676253
- platform: linux-64
name: libuuid
version: 2.38.1
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda
hash:
md5: 40b61aab5c7ba9ff276c41cfffe6b80b
sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18
build: h0b41bf4_0
arch: x86_64
subdir: linux-64
build_number: 0
license: BSD-3-Clause
license_family: BSD
size: 33601
timestamp: 1680112270483
- platform: linux-64
name: libzlib
version: 1.2.13
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda
hash:
md5: f36c115f1ee199da648e0597ec2047ad
sha256: 370c7c5893b737596fd6ca0d9190c9715d89d888b8c88537ae1ef168c25e82e4
build: hd590300_5
arch: x86_64
subdir: linux-64
build_number: 5
constrains:
- zlib 1.2.13 *_5
license: Zlib
license_family: Other
size: 61588
timestamp: 1686575217516
- platform: linux-64
name: mypy_extensions
version: 1.0.0
category: main
manager: conda
dependencies:
- python >=3.5
url: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda
hash:
md5: 4eccaeba205f0aed9ac3a9ea58568ca3
sha256: f240217476e148e825420c6bc3a0c0efb08c0718b7042fae960400c02af858a3
build: pyha770c72_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
noarch: python
size: 10492
timestamp: 1675543414256
- platform: linux-64
name: ncurses
version: '6.4'
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda
hash:
md5: 7dbaa197d7ba6032caf7ae7f32c1efa0
sha256: 91cc03f14caf96243cead96c76fe91ab5925a695d892e83285461fb927dece5e
build: h59595ed_2
arch: x86_64
subdir: linux-64
build_number: 2
license: X11 AND BSD-3-Clause
size: 884434
timestamp: 1698751260967
- platform: linux-64
name: openssl
version: 3.2.0
category: main
manager: conda
dependencies:
- ca-certificates
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.0-hd590300_1.conda
hash:
md5: 603827b39ea2b835268adb8c821b8570
sha256: 80efc6f429bd8e622d999652e5cba2ca56fcdb9c16a439d2ce9b4313116e4a87
build: hd590300_1
arch: x86_64
subdir: linux-64
build_number: 1
constrains:
- pyopenssl >=22.1
license: Apache-2.0
license_family: Apache
size: 2854103
timestamp: 1701162437033
- platform: linux-64
name: packaging
version: '23.2'
category: main
manager: conda
dependencies:
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda
hash:
md5: 79002079284aa895f883c6b7f3f88fd6
sha256: 69b3ace6cca2dab9047b2c24926077d81d236bef45329d264b394001e3c3e52f
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: Apache-2.0
license_family: APACHE
noarch: python
size: 49452
timestamp: 1696202521121
- platform: linux-64
name: pathspec
version: 0.12.1
category: main
manager: conda
dependencies:
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda
hash:
md5: 17064acba08d3686f1135b5ec1b32b12
sha256: 4e534e66bfe8b1e035d2169d0e5b185450546b17e36764272863e22e0370be4d
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MPL-2.0
license_family: MOZILLA
noarch: python
size: 41173
timestamp: 1702250135032
- platform: linux-64
name: platformdirs
version: 4.1.0
category: main
manager: conda
dependencies:
- python >=3.8
url: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.1.0-pyhd8ed1ab_0.conda
hash:
md5: 45a5065664da0d1dfa8f8cd2eaf05ab9
sha256: 9e4ff17ce802159ed31344eb913eaa877688226765b77947b102b42255a53853
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
noarch: python
size: 20058
timestamp: 1701708396900
- platform: linux-64
name: pysocks
version: 1.7.1
category: main
manager: conda
dependencies:
- __unix
- python >=3.8
url: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2
hash:
md5: 2a7de29fb590ca14b5243c4c812c8025
sha256: a42f826e958a8d22e65b3394f437af7332610e43ee313393d1cf143f0a2d274b
build: pyha2e5f31_6
arch: x86_64
subdir: linux-64
build_number: 6
license: BSD-3-Clause
license_family: BSD
noarch: python
size: 18981
timestamp: 1661604969727
- platform: linux-64
name: python
version: 3.12.0
category: main
manager: conda
dependencies:
- bzip2 >=1.0.8,<2.0a0
- ld_impl_linux-64 >=2.36.1
- libexpat >=2.5.0,<3.0a0
- libffi >=3.4,<4.0a0
- libgcc-ng >=12
- libnsl >=2.0.0,<2.1.0a0
- libsqlite >=3.43.0,<4.0a0
- libuuid >=2.38.1,<3.0a0
- libzlib >=1.2.13,<1.3.0a0
- ncurses >=6.4,<7.0a0
- openssl >=3.1.3,<4.0a0
- readline >=8.2,<9.0a0
- tk >=8.6.13,<8.7.0a0
- tzdata
- xz >=5.2.6,<6.0a0
url: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.0-hab00c5b_0_cpython.conda
hash:
md5: 7f97faab5bebcc2580f4f299285323da
sha256: 5398ebae6a1ccbfd3f76361eac75f3ac071527a8072627c4bf9008c689034f48
build: hab00c5b_0_cpython
arch: x86_64
subdir: linux-64
build_number: 0
constrains:
- python_abi 3.12.* *_cp312
license: Python-2.0
size: 32123473
timestamp: 1696324522323
- platform: linux-64
name: python_abi
version: '3.12'
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda
hash:
md5: dccc2d142812964fcc6abdc97b672dff
sha256: 182a329de10a4165f6e8a3804caf751f918f6ea6176dd4e5abcdae1ed3095bf6
build: 4_cp312
arch: x86_64
subdir: linux-64
build_number: 4
constrains:
- python 3.12.* *_cpython
license: BSD-3-Clause
license_family: BSD
size: 6385
timestamp: 1695147396604
- platform: linux-64
name: readline
version: '8.2'
category: main
manager: conda
dependencies:
- libgcc-ng >=12
- ncurses >=6.3,<7.0a0
url: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda
hash:
md5: 47d31b792659ce70f470b5c82fdfb7a4
sha256: 5435cf39d039387fbdc977b0a762357ea909a7694d9528ab40f005e9208744d7
build: h8228510_1
arch: x86_64
subdir: linux-64
build_number: 1
license: GPL-3.0-only
license_family: GPL
size: 281456
timestamp: 1679532220005
- platform: linux-64
name: requests
version: 2.31.0
category: main
manager: conda
dependencies:
- certifi >=2017.4.17
- charset-normalizer >=2,<4
- idna >=2.5,<4
- python >=3.7
- urllib3 >=1.21.1,<3
url: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda
hash:
md5: a30144e4156cdbb236f99ebb49828f8b
sha256: 9f629d6fd3c8ac5f2a198639fe7af87c4db2ac9235279164bfe0fcb49d8c4bad
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
constrains:
- chardet >=3.0.2,<6
license: Apache-2.0
license_family: APACHE
noarch: python
size: 56690
timestamp: 1684774408600
- platform: linux-64
name: tk
version: 8.6.13
category: main
manager: conda
dependencies:
- libgcc-ng >=12
- libzlib >=1.2.13,<1.3.0a0
url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda
hash:
md5: d453b98d9c83e71da0741bb0ff4d76bc
sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e
build: noxft_h4845f30_101
arch: x86_64
subdir: linux-64
build_number: 101
license: TCL
license_family: BSD
size: 3318875
timestamp: 1699202167581
- platform: linux-64
name: tzdata
version: 2023c
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/noarch/tzdata-2023c-h71feb2d_0.conda
hash:
md5: 939e3e74d8be4dac89ce83b20de2492a
sha256: 0449138224adfa125b220154408419ec37c06b0b49f63c5954724325903ecf55
build: h71feb2d_0
arch: x86_64
subdir: linux-64
build_number: 0
license: LicenseRef-Public-Domain
noarch: generic
size: 117580
timestamp: 1680041306008
- platform: linux-64
name: urllib3
version: 2.1.0
category: main
manager: conda
dependencies:
- brotli-python >=1.0.9
- pysocks >=1.5.6,<2.0,!=1.5.7
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.1.0-pyhd8ed1ab_0.conda
hash:
md5: f8ced8ee63830dec7ecc1be048d1470a
sha256: eff5029820b4eaeab3a291a39854a6cd8fc8c4216264087f68c2d8d59822c869
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
noarch: python
size: 85324
timestamp: 1699933655057
- platform: linux-64
name: xz
version: 5.2.6
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2
hash:
md5: 2161070d867d1b1204ea749c8eec4ef0
sha256: 03a6d28ded42af8a347345f82f3eebdd6807a08526d47899a42d62d319609162
build: h166bdaf_0
arch: x86_64
subdir: linux-64
build_number: 0
license: LGPL-2.1 and GPL-2.0
size: 418368
timestamp: 1660346797927

View File

@@ -1,17 +0,0 @@
[project]
name = "github-release-notifier"
version = "1"
description = "Send mail notification on new released versions of Github projects"
authors = ["Maxence G. de Montauzan <maxence@gdemontauzan.fr>"]
channels = ["conda-forge"]
platforms = ["linux-64"]
repository = "https://github.com/MaxenceG2M/github-release-notifier"
[tasks]
[dependencies]
python = ">=3.12.0,<3.13"
requests = ">=2.31.0,<2.32"
[build-dependencies]
black = ">=23.11.0,<23.12"

View File

@@ -1,3 +1,6 @@
requests
pre-commit
black
fastapi
pre-commit
pyotp
requests
uvicorn[standard]