Compare commits
4 commits
7c5e429ae0
...
1f182df473
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f182df473 | ||
|
|
800c4c2ee3 | ||
|
|
8e7fcc6ed2 | ||
|
|
11c3103e3b |
2 changed files with 72 additions and 41 deletions
72
config.py
72
config.py
|
|
@ -14,19 +14,40 @@ from issue_generator import FeedReader, GithubReader, GithubTagReader, PIPYReade
|
||||||
TIMEOUT
|
TIMEOUT
|
||||||
import _secrets
|
import _secrets
|
||||||
|
|
||||||
|
class AlpinePackageReader(FeedReader):
|
||||||
|
'''Custom feed reader for Alpine packages'''
|
||||||
|
def __init__(self, package: str, targets: IssuePoster):
|
||||||
|
super().__init__(package, "https://gitlab.alpinelinux.org/alpine/aports/-/commits/master.atom", targets)
|
||||||
|
self.regex = r'community/([^:]+): upgrade to (.+)'
|
||||||
|
self.package = package
|
||||||
|
|
||||||
|
def is_valid_item(self, entry) -> bool:
|
||||||
|
match = re.search(self.regex, entry.title)
|
||||||
|
return match and match.groups(1) == self.package
|
||||||
|
|
||||||
|
def entry_get_version(self, entry: dict[str, Any]) -> tuple[str, str]:
|
||||||
|
match = re.search(self.regex, entry.title)
|
||||||
|
if match and match.groups(1) == self.package:
|
||||||
|
return (match.groups(2),) * 2
|
||||||
|
raise RuntimeError(f"Checking version for package {self.package} in invalid entry titled: {entry.title}")
|
||||||
|
|
||||||
|
def entry_get_link(self, entry: dict[str, Any]) -> str:
|
||||||
|
return entry.id
|
||||||
|
|
||||||
|
|
||||||
class UDSClientReader(FeedReader):
|
class UDSClientReader(FeedReader):
|
||||||
'''Custom feed reader for UDSClient, whose version number appears in a .js file.'''
|
'''Custom feed reader for UDSClient, whose version number appears in a .js file.'''
|
||||||
|
|
||||||
def __init__(self, target: IssuePoster):
|
def __init__(self, targets: IssuePoster):
|
||||||
'''Creates a new UDSClient Reader.'''
|
'''Creates a new UDSClient Reader.'''
|
||||||
super().__init__("udsclient", "https://polilabs.upv.es/uds/utility/uds.js", target)
|
super().__init__("udsclient", "https://polilabs.upv.es/uds/utility/uds.js", targets)
|
||||||
|
|
||||||
def read_feed(self) -> bool | None:
|
def read_feed(self) -> bool | None:
|
||||||
'''Checks for a new version of udsclient, by checking a .js file.'''
|
'''Checks for a new version of udsclient, by checking a .js file.'''
|
||||||
get = requests.get(self.url, timeout = TIMEOUT)
|
get = requests.get(self.url, timeout = TIMEOUT)
|
||||||
if not self.target.check_req(get, self.name):
|
for target in self.targets:
|
||||||
return None
|
if not target.check_req(get, self.name):
|
||||||
|
return None
|
||||||
match = re.search(r"[/a-zA-Z_-]+udsclient\d+-(\d+\.\d+\.\d+)\.tar\.gz", get.text)
|
match = re.search(r"[/a-zA-Z_-]+udsclient\d+-(\d+\.\d+\.\d+)\.tar\.gz", get.text)
|
||||||
if not match:
|
if not match:
|
||||||
return None
|
return None
|
||||||
|
|
@ -55,7 +76,7 @@ class NCAppReader(GithubReader):
|
||||||
'''All GitHub releases readers that must alert Forgejo's `archpkgs`.'''
|
'''All GitHub releases readers that must alert Forgejo's `archpkgs`.'''
|
||||||
def __init__(self, app, project):
|
def __init__(self, app, project):
|
||||||
super().__init__(name = app, project = project,
|
super().__init__(name = app, project = project,
|
||||||
target = CGJForgejoPoster("archpkgs/" + app))
|
targets = CGJForgejoPoster("archpkgs/" + app))
|
||||||
|
|
||||||
|
|
||||||
# Issue Posters
|
# Issue Posters
|
||||||
|
|
@ -70,20 +91,18 @@ FEED_READERS = [
|
||||||
# Name FeedType Project TargetProject
|
# Name FeedType Project TargetProject
|
||||||
################################ Software used in MIST (Gitlab) ###################################
|
################################ Software used in MIST (Gitlab) ###################################
|
||||||
# LanguageTool GHTags languagetool-org/languagetool 36 (sysadmin/boira)
|
# LanguageTool GHTags languagetool-org/languagetool 36 (sysadmin/boira)
|
||||||
GithubTagReader(name = "LanguageTool", project = "languagetool-org/languagetool",
|
GithubTagReader(name = "LanguageTool", project = "languagetool-org/languagetool",
|
||||||
target = GITLAB_BOIRA_CARGAJI),
|
targets = GITLAB_BOIRA_CARGAJI),
|
||||||
# meshcentral GHReleases Ylianst/MeshCentral 36 (sysadmin/boira)
|
# meshcentral GHReleases Ylianst/MeshCentral 36 (sysadmin/boira)
|
||||||
GithubReader(name = "meshcentral", project = "Ylianst/MeshCentral",
|
# meshcentral GHReleases Ylianst/MeshCentral archpkgs/meshcentral
|
||||||
target = GITLAB_BOIRA_CARGAJI),
|
GithubReader(name = "meshcentral", project = "Ylianst/MeshCentral",
|
||||||
|
targets = [GITLAB_BOIRA_CARGAJI, CGJForgejoPoster("archpkgs/meshcentral")]),
|
||||||
# python3-snakes PIPY snakes 37 (packages/python3-snakes)
|
# python3-snakes PIPY snakes 37 (packages/python3-snakes)
|
||||||
PIPYReader(name = "python3-snakes", package = "snakes",
|
PIPYReader(name = "python3-snakes", package = "snakes",
|
||||||
target = GITLAB_SNAKES_CARGAJI),
|
targets = GITLAB_SNAKES_CARGAJI),
|
||||||
################################ Software that I package (Forgejo) ################################
|
################################ Software that I package (Forgejo) ################################
|
||||||
# pdfbooklet GHReleases Averell7/PdfBooklet archpkgs/pdfbooklet
|
# pdfbooklet GHReleases Averell7/PdfBooklet archpkgs/pdfbooklet
|
||||||
NCAppReader(app = "pdfbooklet", project = "Averell7/PdfBooklet"),
|
NCAppReader(app = "pdfbooklet", project = "Averell7/PdfBooklet"),
|
||||||
# meshcentral GHReleases Ylianst/MeshCentral archpkgs/meshcentral
|
|
||||||
GithubReader(name = "meshcentral", project = "Ylianst/MeshCentral",
|
|
||||||
target = CGJForgejoPoster("archpkgs/meshcentral")),
|
|
||||||
# nc-cospend GHReleases eneiluj/cospend-nc archpkgs/nextcloud-app-cospend
|
# nc-cospend GHReleases eneiluj/cospend-nc archpkgs/nextcloud-app-cospend
|
||||||
NCAppReader(app = "nextcloud-app-cospend", project = "eneiluj/cospend-nc"),
|
NCAppReader(app = "nextcloud-app-cospend", project = "eneiluj/cospend-nc"),
|
||||||
# nc-f_autotagging GHReleases
|
# nc-f_autotagging GHReleases
|
||||||
|
|
@ -94,32 +113,41 @@ FEED_READERS = [
|
||||||
NCAppReader(app = "nextcloud-app-forms", project = "nextcloud/forms"),
|
NCAppReader(app = "nextcloud-app-forms", project = "nextcloud/forms"),
|
||||||
# nc-maps GHReleases nextcloud/maps archpkgs/nextcloud-app-maps
|
# nc-maps GHReleases nextcloud/maps archpkgs/nextcloud-app-maps
|
||||||
NCAppReader(app = "nextcloud-app-maps", project = "nextcloud/maps"),
|
NCAppReader(app = "nextcloud-app-maps", project = "nextcloud/maps"),
|
||||||
# nc-music GHReleases owncloud/music archpkgs/nextcloud-app-music
|
# nc-music GHReleases nc-music/music archpkgs/nextcloud-app-music
|
||||||
NCAppReader(app = "nextcloud-app-music", project = "owncloud/music"),
|
NCAppReader(app = "nextcloud-app-music", project = "nc-music/music"),
|
||||||
# nc-onlyoffice GHReleases ONLYOFFICE/onlyoffice-nextcloud archpkgs/nextcloud-app-onlyoffice
|
# nc-onlyoffice GHReleases ONLYOFFICE/onlyoffice-nextcloud archpkgs/nextcloud-app-onlyoffice
|
||||||
NCAppReader(app = "nextcloud-app-onlyoffice", project = "ONLYOFFICE/onlyoffice-nextcloud"),
|
# NCAppReader(app = "nextcloud-app-onlyoffice", project = "ONLYOFFICE/onlyoffice-nextcloud"),
|
||||||
|
# nc-phonetrack GHReleases julien-nc/phonetrack archpkgs/nextcloud-app-phonetrack
|
||||||
|
NCAppReader(app = "nextcloud-app-phonetrack", project = "julien-nc/phonetrack"),
|
||||||
# nc-polls GHReleases nextcloud/polls archpkgs/nextcloud-app-polls
|
# nc-polls GHReleases nextcloud/polls archpkgs/nextcloud-app-polls
|
||||||
NCAppReader(app = "nextcloud-app-polls", project = "nextcloud/polls"),
|
NCAppReader(app = "nextcloud-app-polls", project = "nextcloud/polls"),
|
||||||
# nc-socialsharing GHReleases nextcloud/socialsharing archpkgs/nextcloud-app-socialsharing
|
# nc-socialsharing GHReleases nextcloud/socialsharing archpkgs/nextcloud-app-socialsharing
|
||||||
NCAppReader(app = "nextcloud-app-socialsharing", project = "nextcloud/socialsharing"),
|
NCAppReader(app = "nextcloud-app-socialsharing", project = "nextcloud/socialsharing"),
|
||||||
# udsclient Custom --- archpkgs/udsclient
|
# udsclient Custom --- archpkgs/udsclient
|
||||||
UDSClientReader(target = CGJForgejoPoster(project="archpkgs/udsclient")),
|
UDSClientReader(targets = CGJForgejoPoster(project="archpkgs/udsclient")),
|
||||||
# vigil GHReleases valeriansaliou/vigil archpkgs/vigil
|
# vigil GHReleases valeriansaliou/vigil archpkgs/vigil
|
||||||
NCAppReader(app = "vigil", project = "valeriansaliou/vigil"),
|
NCAppReader(app = "vigil", project = "valeriansaliou/vigil"),
|
||||||
# vigil-local GHReleases valeriansaliou/vigil-local archpkgs/vigil-local
|
# vigil-local GHReleases valeriansaliou/vigil-local archpkgs/vigil-local
|
||||||
NCAppReader(app = "vigil-local", project = "valeriansaliou/vigil-local"),
|
NCAppReader(app = "vigil-local", project = "valeriansaliou/vigil-local"),
|
||||||
# yourls GHReleases YOURLS/YOURLS archpkgs/yourls
|
# yourls GHReleases YOURLS/YOURLS archpkgs/yourls
|
||||||
NCAppReader(app = "yourls", project = "YOURLS/YOURLS"),
|
NCAppReader(app = "yourls", project = "YOURLS/YOURLS"),
|
||||||
|
|
||||||
|
################################ Critical software in servers ################################
|
||||||
|
# zfs
|
||||||
|
GithubReader(name = "zfs-dkms", project = "openzfs/zfs",
|
||||||
|
targets = CGJForgejoPoster("kauron/solaris-packages")),
|
||||||
|
# yay GHReleases Jguer/yay aur?
|
||||||
|
GithubReader(name = "yay", project = "Jguer/yay",
|
||||||
|
targets = CGJForgejoPoster("kauron/solaris-packages")),
|
||||||
|
# qbittorrent-alpine
|
||||||
|
AlpinePackageReader(package = "qbittorrent",
|
||||||
|
targets = CGJForgejoPoster("kauron/solaris-packages")),
|
||||||
]
|
]
|
||||||
|
|
||||||
## PENDING:
|
## PENDING:
|
||||||
# Software that I use exposed to the Internet
|
# Software that I use exposed to the Internet
|
||||||
# Name FeedType Project
|
# Name FeedType Project
|
||||||
# gad GHReleases brianreumere/gandi-automatic-dns aur?
|
# gad GHReleases brianreumere/gandi-automatic-dns aur?
|
||||||
# nextcloud GHReleases nextcloud/server pacman?
|
|
||||||
# peertube GHReleases Chocobozzz/PeerTube aur?
|
# peertube GHReleases Chocobozzz/PeerTube aur?
|
||||||
# vaultwarden GHReleases dani-garcia/vaultwarden pacman?
|
|
||||||
# wallabag GHReleases wallabag/wallabag pacman?
|
|
||||||
# yay GHReleases Jguer/yay aur?
|
|
||||||
# Others?
|
# Others?
|
||||||
# duplicati ???
|
# duplicati ???
|
||||||
|
|
|
||||||
|
|
@ -157,15 +157,19 @@ class ForgejoPoster(IssuePoster):
|
||||||
class FeedReader:
|
class FeedReader:
|
||||||
'''Class to read an RSS/Atom feed and post an issue if a new version is found.'''
|
'''Class to read an RSS/Atom feed and post an issue if a new version is found.'''
|
||||||
|
|
||||||
def __init__(self, name: str, url: str, target: IssuePoster):
|
def __init__(self, name: str, url: str, targets: list[IssuePoster]):
|
||||||
'''Create a new feed reader'''
|
'''Create a new feed reader'''
|
||||||
self.name = name
|
self.name = name
|
||||||
self.url = url
|
self.url = url
|
||||||
self.target = target
|
self.targets = targets if type(targets) == list else [targets]
|
||||||
self.version_file = CONFIG_DIR + self.name
|
self.version_file = CONFIG_DIR + self.name
|
||||||
self.etag_file = CONFIG_DIR + self.name + ".etag"
|
self.etag_file = CONFIG_DIR + self.name + ".etag"
|
||||||
self.beta_strings = [ "nightly", "beta", "alpha", "rc", "pr" ]
|
self.beta_strings = [ "nightly", "beta", "alpha", "rc", "pr" ]
|
||||||
|
|
||||||
|
def is_valid_item(self, entry) -> bool:
|
||||||
|
version = self.entry_get_version(entry)[0]
|
||||||
|
return all([beta not in version for beta in self.beta_strings])
|
||||||
|
|
||||||
def first_item(self) -> dict[str, Any] | None | int:
|
def first_item(self) -> dict[str, Any] | None | int:
|
||||||
'''Get the first item of the feed (newest)'''
|
'''Get the first item of the feed (newest)'''
|
||||||
if os.path.isfile(self.etag_file):
|
if os.path.isfile(self.etag_file):
|
||||||
|
|
@ -173,7 +177,7 @@ class FeedReader:
|
||||||
etag = file.readline()
|
etag = file.readline()
|
||||||
else: etag = None
|
else: etag = None
|
||||||
feed = feedparser.parse(self.url, etag=etag)
|
feed = feedparser.parse(self.url, etag=etag)
|
||||||
if feed.etag and feed.etag != etag:
|
if feed.etag and feed.etag != etag and feed.status // 100 in [2, 3]:
|
||||||
if not os.path.isdir(CONFIG_DIR):
|
if not os.path.isdir(CONFIG_DIR):
|
||||||
os.mkdir(CONFIG_DIR)
|
os.mkdir(CONFIG_DIR)
|
||||||
with open(self.etag_file, mode='w', encoding="UTF-8") as file:
|
with open(self.etag_file, mode='w', encoding="UTF-8") as file:
|
||||||
|
|
@ -183,12 +187,7 @@ class FeedReader:
|
||||||
if len(feed.entries) == 0:
|
if len(feed.entries) == 0:
|
||||||
return None
|
return None
|
||||||
for entry in feed.entries:
|
for entry in feed.entries:
|
||||||
skip = False
|
if self.is_valid_item(entry):
|
||||||
for beta in self.beta_strings:
|
|
||||||
if beta in self.entry_get_version(entry)[0]:
|
|
||||||
skip = True
|
|
||||||
break
|
|
||||||
if not skip:
|
|
||||||
return entry
|
return entry
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
@ -223,10 +222,14 @@ class FeedReader:
|
||||||
if match:
|
if match:
|
||||||
return False
|
return False
|
||||||
# Match 2: with repository issues
|
# Match 2: with repository issues
|
||||||
if not self.target.issue_exists(self.name, version):
|
issues_posted = True
|
||||||
# Post the issue
|
for target in self.targets:
|
||||||
if not self.target.post_issue(self.name, version, link):
|
if not target.issue_exists(self.name, version):
|
||||||
return False
|
# Post the issue
|
||||||
|
if not target.post_issue(self.name, version, link):
|
||||||
|
issues_posted = False
|
||||||
|
if not issues_posted:
|
||||||
|
return False
|
||||||
# Save to disk
|
# Save to disk
|
||||||
if not os.path.isdir(CONFIG_DIR):
|
if not os.path.isdir(CONFIG_DIR):
|
||||||
os.makedirs(CONFIG_DIR)
|
os.makedirs(CONFIG_DIR)
|
||||||
|
|
@ -238,9 +241,9 @@ class FeedReader:
|
||||||
class PIPYReader(FeedReader):
|
class PIPYReader(FeedReader):
|
||||||
'''Reader specialized in the PIPY repository.'''
|
'''Reader specialized in the PIPY repository.'''
|
||||||
|
|
||||||
def __init__(self, name: str, package: str, target: IssuePoster):
|
def __init__(self, name: str, package: str, targets: IssuePoster):
|
||||||
'''Create a new PIPY reader for the given package.'''
|
'''Create a new PIPY reader for the given package.'''
|
||||||
super().__init__(name, f"https://pypi.org/rss/project/{package}/releases.xml", target)
|
super().__init__(name, f"https://pypi.org/rss/project/{package}/releases.xml", targets)
|
||||||
|
|
||||||
def entry_get_version(self, entry: dict[str, Any]) -> tuple[str, str]:
|
def entry_get_version(self, entry: dict[str, Any]) -> tuple[str, str]:
|
||||||
return entry.title, entry.title
|
return entry.title, entry.title
|
||||||
|
|
@ -252,9 +255,9 @@ class PIPYReader(FeedReader):
|
||||||
class GithubTagReader(FeedReader):
|
class GithubTagReader(FeedReader):
|
||||||
'''Reader specialized in GitHub Tags Atom feed.'''
|
'''Reader specialized in GitHub Tags Atom feed.'''
|
||||||
|
|
||||||
def __init__(self, name: str, project: str, target: IssuePoster):
|
def __init__(self, name: str, project: str, targets: IssuePoster):
|
||||||
'''Create a new GitHub Tags reader for the given project.'''
|
'''Create a new GitHub Tags reader for the given project.'''
|
||||||
super().__init__(name, f"https://github.com/{project}/tags.atom", target)
|
super().__init__(name, f"https://github.com/{project}/tags.atom", targets)
|
||||||
|
|
||||||
def entry_get_version(self, entry: dict[str, Any]) -> tuple[str, str]:
|
def entry_get_version(self, entry: dict[str, Any]) -> tuple[str, str]:
|
||||||
return entry.title, str(entry.id)
|
return entry.title, str(entry.id)
|
||||||
|
|
@ -266,8 +269,8 @@ class GithubTagReader(FeedReader):
|
||||||
class GithubReader(GithubTagReader):
|
class GithubReader(GithubTagReader):
|
||||||
'''Reader specialized in GitHub releases' Atom feed.'''
|
'''Reader specialized in GitHub releases' Atom feed.'''
|
||||||
|
|
||||||
def __init__(self, name: str, project: str, target: IssuePoster):
|
def __init__(self, name: str, project: str, targets: IssuePoster):
|
||||||
super().__init__(name, project, target)
|
super().__init__(name, project, targets)
|
||||||
self.url = f"https://github.com/{project}/releases.atom"
|
self.url = f"https://github.com/{project}/releases.atom"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue