From e7688433effb624bf0c7e5fb61308ba236afb120 Mon Sep 17 00:00:00 2001 From: AuxXxilium Date: Mon, 3 Feb 2025 19:10:33 +0100 Subject: [PATCH] tree: cleanup Signed-off-by: AuxXxilium --- .github/workflows/build.yml | 2 +- .github/workflows/custom.yml | 2 +- .github/workflows/data.yml | 10 +- img-gen.sh | 2 +- scripts/functions.py | 373 ------------------------------ scripts/{func.sh => functions.sh} | 0 scripts/random.sh | 7 - 7 files changed, 8 insertions(+), 388 deletions(-) delete mode 100644 scripts/functions.py rename scripts/{func.sh => functions.sh} (100%) delete mode 100755 scripts/random.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7fcb6ba7..c381b6a8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,7 +75,7 @@ jobs: # Get extractor, LKM, Addons, Modules, Theme and Configs - name: Get Dependencies for all Image run: | - . scripts/func.sh "${{ secrets.BUILD_TOKEN }}" + . scripts/functions.sh "${{ secrets.BUILD_TOKEN }}" echo "Get Dependencies" getAddons "files/p3/addons" diff --git a/.github/workflows/custom.yml b/.github/workflows/custom.yml index d1567eb0..6841a56e 100644 --- a/.github/workflows/custom.yml +++ b/.github/workflows/custom.yml @@ -93,7 +93,7 @@ jobs: # Build incremental - name: Build image run: | - . scripts/func.sh + . scripts/functions.sh function writeConfigKey() { [ "${2}" = "{}" ] && sudo yq eval '.'${1}' = {}' --inplace "${3}" 2>/dev/null || sudo yq eval '.'${1}' = "'"${2}"'"' --inplace "${3}" 2>/dev/null diff --git a/.github/workflows/data.yml b/.github/workflows/data.yml index a195835b..4b0d0d41 100644 --- a/.github/workflows/data.yml +++ b/.github/workflows/data.yml @@ -1,5 +1,5 @@ # -# Copyright (C) 2023 AuxXxilium and Ing +# Copyright (C) 2025 AuxXxilium # # This is free software, licensed under the MIT License. # See /LICENSE for more information. @@ -67,10 +67,10 @@ jobs: - name: Get data run: | pip install -r scripts/requirements.txt - python scripts/func.py getmodels -w "arc/ws" -j "docs/models.json" - python scripts/func.py getaddons -w "arc/ws" -j "docs/addons.json" - python scripts/func.py getmodules -w "arc/ws" -j "docs/modules.json" - python scripts/func.py getpats -w "arc/ws" -j "docs/pats.json" + python scripts/functions.py getmodels -j "docs/models.json" + python scripts/functions.py getaddons -j "docs/addons.json" + python scripts/functions.py getmodules -j "docs/modules.json" + python scripts/functions.py getpats -j "docs/pats.json" - name: Upload to Artifacts if: success() diff --git a/img-gen.sh b/img-gen.sh index b6a499ef..c7d35f55 100755 --- a/img-gen.sh +++ b/img-gen.sh @@ -11,7 +11,7 @@ set -e # Clean cached Files sudo git clean -fdx -. scripts/func.sh "${AUX_TOKEN}" +. scripts/functions.sh "${AUX_TOKEN}" # Unmount Image File sudo umount "/tmp/p1" 2>/dev/null || true diff --git a/scripts/functions.py b/scripts/functions.py deleted file mode 100644 index f41e5cfe..00000000 --- a/scripts/functions.py +++ /dev/null @@ -1,373 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2023 AuxXxilium and Ing -# -# This is free software, licensed under the MIT License. -# See /LICENSE for more information. -# - -import os, click - -WORK_PATH = os.path.abspath(os.path.dirname(__file__)) - - -@click.group() -def cli(): - """ - The CLI is a commands to Arc. - """ - pass - - -def mutually_exclusive_options(ctx, param, value): - other_option = "file" if param.name == "data" else "data" - if value is not None and ctx.params.get(other_option) is not None: - raise click.UsageError(f"Illegal usage: `{param.name}` is mutually exclusive with `{other_option}`.") - return value - - -def validate_required_param(ctx, param, value): - if not value and "file" not in ctx.params and "data" not in ctx.params: - raise click.MissingParameter(param_decls=[param.name]) - return value - -def __fullversion(ver): - out = ver - arr = ver.split('-') - if len(arr) > 0: - a = arr[0].split('.')[0] if len(arr[0].split('.')) > 0 else '0' - b = arr[0].split('.')[1] if len(arr[0].split('.')) > 1 else '0' - c = arr[0].split('.')[2] if len(arr[0].split('.')) > 2 else '0' - d = arr[1] if len(arr) > 1 else '00000' - e = arr[2] if len(arr) > 2 else '0' - out = '{}.{}.{}-{}-{}'.format(a,b,c,d,e) - return out - - -@cli.command() -@click.option("-d", "--data", type=str, callback=mutually_exclusive_options, is_eager=True, help="The data of QRCode.") -@click.option("-f", "--file", type=str, callback=mutually_exclusive_options, is_eager=True, help="The file of QRCode.") -@click.option("--validate", is_flag=True, callback=validate_required_param, expose_value=False, is_eager=True) -@click.option("-l", "--location", type=click.IntRange(0, 7), required=True, help="The location of QRCode. (range 0<=x<=7)") -@click.option("-o", "--output", type=str, required=True, help="The output file of QRCode.") -def makeqr(data, file, location, output): - """ - Generate a QRCode. - """ - try: - import fcntl, struct - import qrcode - from PIL import Image - - FBIOGET_VSCREENINFO = 0x4600 - FBIOPUT_VSCREENINFO = 0x4601 - FBIOGET_FSCREENINFO = 0x4602 - FBDEV = "/dev/fb0" - if data is not None: - qr = qrcode.QRCode(version=1, box_size=10, error_correction=qrcode.constants.ERROR_CORRECT_H, border=4,) - qr.add_data(data) - qr.make(fit=True) - img = qr.make_image(fill_color="grey", back_color="black") - img = img.convert("RGBA") - pixels = img.load() - for i in range(img.size[0]): - for j in range(img.size[1]): - if pixels[i, j] == (255, 255, 255, 255): - pixels[i, j] = (255, 255, 255, 0) - - if os.path.exists(os.path.join(WORK_PATH, "logo.png")): - icon = Image.open(os.path.join(WORK_PATH, "logo.png")) - icon = icon.convert("RGBA") - img.paste(icon.resize((int(img.size[0] / 5), int(img.size[1] / 5))), (int((img.size[0] - int(img.size[0] / 5)) / 2), int((img.size[1] - int(img.size[1] / 5)) / 2),),) - - if file is not None: - img = Image.open(file) - # img = img.convert("RGBA") - # pixels = img.load() - # for i in range(img.size[0]): - # for j in range(img.size[1]): - # if pixels[i, j] == (255, 255, 255, 255): - # pixels[i, j] = (255, 255, 255, 0) - - (xres, yres) = (1920, 1080) - with open(FBDEV, "rb") as fb: - vi = fcntl.ioctl(fb, FBIOGET_VSCREENINFO, bytes(160)) - res = struct.unpack("I" * 40, vi) - if res[0] != 0 and res[1] != 0: - (xres, yres) = (res[0], res[1]) - xqr, yqr = (int(xres / 8), int(xres / 8)) - img = img.resize((xqr, yqr)) - - alpha = Image.new("RGBA", (xres, yres), (0, 0, 0, 0)) - if int(location) not in range(0, 8): - location = 0 - loc = (img.size[0] * int(location), alpha.size[1] - img.size[1]) - alpha.paste(img, loc) - alpha.save(output) - - except: - pass - - -@cli.command() -@click.option("-p", "--platforms", type=str, help="The platforms of Syno.") -def getmodels(platforms=None): - """ - Get Syno Models. - """ - import json, requests, urllib3 - from requests.adapters import HTTPAdapter - from requests.packages.urllib3.util.retry import Retry # type: ignore - - adapter = HTTPAdapter(max_retries=Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])) - session = requests.Session() - session.mount("http://", adapter) - session.mount("https://", adapter) - urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - - if platforms is not None and platforms != "": - PS = platforms.lower().replace(",", " ").split() - else: - PS = [] - - models = [] - try: - req = session.get("https://autoupdate.synology.com/os/v2", timeout=10, verify=False) - req.encoding = "utf-8" - data = json.loads(req.text) - - for I in data["channel"]["item"]: - if not I["title"].startswith("DSM"): - continue - for J in I["model"]: - arch = J["mUnique"].split("_")[1] - name = J["mLink"].split("/")[-1].split("_")[1].replace("%2B", "+") - if len(PS) > 0 and arch.lower() not in PS: - continue - if any(name == B["name"] for B in models): - continue - models.append({"name": name, "arch": arch}) - - models = sorted(models, key=lambda k: (k["arch"], k["name"])) - - except: - pass - - models.sort(key=lambda x: (x["arch"], x["name"])) - print(json.dumps(models, indent=4)) - -@cli.command() -@click.option("-p", "--platforms", type=str, help="The platforms of Syno.") -def getmodelsbykb(platforms=None): - """ - Get Syno Models. - """ - import json, requests, urllib3 - from requests.adapters import HTTPAdapter - from requests.packages.urllib3.util.retry import Retry # type: ignore - - adapter = HTTPAdapter(max_retries=Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])) - session = requests.Session() - session.mount("http://", adapter) - session.mount("https://", adapter) - urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - - if platforms is not None and platforms != "": - PS = platforms.lower().replace(",", " ").split() - else: - PS = [] - - models = [] - try: - import re - from bs4 import BeautifulSoup - - url="https://kb.synology.com/en-us/DSM/tutorial/What_kind_of_CPU_does_my_NAS_have" - #url = "https://kb.synology.cn/zh-cn/DSM/tutorial/What_kind_of_CPU_does_my_NAS_have" - req = session.get(url, timeout=10, verify=False) - req.encoding = "utf-8" - bs = BeautifulSoup(req.text, "html.parser") - p = re.compile(r"data: (.*?),$", re.MULTILINE | re.DOTALL) - data = json.loads(p.search(bs.find("script", string=p).prettify()).group(1)) - model = "(.*?)" # (.*?): all, FS6400: one - p = re.compile(r"{}<\/td>(.*?)<\/td>(.*?)<\/td>(.*?)<\/td>(.*?)<\/td>(.*?)<\/td>(.*?)<\/td>".format(model), re.MULTILINE | re.DOTALL,) - it = p.finditer(data["preload"]["content"].replace("\n", "").replace("\t", "")) - for i in it: - d = i.groups() - if len(d) == 6: - d = model + d - if len(PS) > 0 and d[5].lower() not in PS: - continue - models.append({"name": d[0].split(" 0 else "" - minor = "&minor={}".format(version.split('.')[1]) if len(version.split('.')) > 1 else "" - req = session.get("{}&product={}{}{}".format(urlInfo, model.replace("+", "%2B"), major, minor), timeout=10, verify=False) - req.encoding = "utf-8" - data = json.loads(req.text) - - build_ver = data['info']['system']['detail'][0]['items'][0]['build_ver'] - build_num = data['info']['system']['detail'][0]['items'][0]['build_num'] - buildnano = data['info']['system']['detail'][0]['items'][0]['nano'] - V=__fullversion("{}-{}-{}".format(build_ver, build_num, buildnano)) - if not V in pats: - pats[V]={} - pats[V]['url'] = data['info']['system']['detail'][0]['items'][0]['files'][0]['url'].split('?')[0] - pats[V]['sum'] = data['info']['system']['detail'][0]['items'][0]['files'][0]['checksum'] - - from_ver=0 - for I in data['info']['pubVers']: - if from_ver == 0 or I['build'] < from_ver: from_ver = I['build'] - - for I in data['info']['productVers']: - if not I['version'].startswith(version): continue - if major == "" or minor == "": - majorTmp = "&major={}".format(I['version'].split('.')[0]) if len(I['version'].split('.')) > 0 else "" - minorTmp = "&minor={}".format(I['version'].split('.')[1]) if len(I['version'].split('.')) > 1 else "" - reqTmp = session.get("{}&product={}{}{}".format(urlInfo, model.replace("+", "%2B"), majorTmp, minorTmp), timeout=10, verify=False) - reqTmp.encoding = "utf-8" - dataTmp = json.loads(reqTmp.text) - - build_ver = dataTmp['info']['system']['detail'][0]['items'][0]['build_ver'] - build_num = dataTmp['info']['system']['detail'][0]['items'][0]['build_num'] - buildnano = dataTmp['info']['system']['detail'][0]['items'][0]['nano'] - V=__fullversion("{}-{}-{}".format(build_ver, build_num, buildnano)) - if not V in pats: - pats[V]={} - pats[V]['url'] = dataTmp['info']['system']['detail'][0]['items'][0]['files'][0]['url'].split('?')[0] - pats[V]['sum'] = dataTmp['info']['system']['detail'][0]['items'][0]['files'][0]['checksum'] - - for J in I['versions']: - to_ver=J['build'] - reqSteps = session.get("{}&product={}&from_ver={}&to_ver={}".format(urlSteps, model.replace("+", "%2B"), from_ver, to_ver), timeout=10, verify=False) - if reqSteps.status_code != 200: continue - reqSteps.encoding = "utf-8" - dataSteps = json.loads(reqSteps.text) - for S in dataSteps['upgrade_steps']: - if not 'full_patch' in S or S['full_patch'] is False: continue - if not 'build_ver' in S or not S['build_ver'].startswith(version): continue - V=__fullversion("{}-{}-{}".format(S['build_ver'], S['build_num'], S['nano'])) - if not V in pats: - pats[V] = {} - pats[V]['url'] = S['files'][0]['url'].split('?')[0] - pats[V]['sum'] = S['files'][0]['checksum'] - except: - pass - - pats = {k: pats[k] for k in sorted(pats.keys(), reverse=True)} - print(json.dumps(pats, indent=4)) - - -@cli.command() -@click.option("-p", "--models", type=str, help="The models of Syno.") -def getpats(models=None): - import json, requests, urllib3, re - from bs4 import BeautifulSoup - from requests.adapters import HTTPAdapter - from requests.packages.urllib3.util.retry import Retry # type: ignore - - adapter = HTTPAdapter(max_retries=Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])) - session = requests.Session() - session.mount("http://", adapter) - session.mount("https://", adapter) - urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - - if models is not None and models != "": - MS = models.lower().replace(",", " ").split() - else: - MS = [] - - pats = {} - try: - req = session.get('https://archive.synology.com/download/Os/DSM', timeout=10, verify=False) - req.encoding = 'utf-8' - bs=BeautifulSoup(req.text, 'html.parser') - p = re.compile(r"(.*?)-(.*?)", re.MULTILINE | re.DOTALL) - l = bs.find_all('a', string=p) - for i in l: - ver = i.attrs['href'].split('/')[-1] - if not ver.startswith('7'): continue - req = session.get('https://archive.synology.com{}'.format(i.attrs['href']), timeout=10, verify=False) - req.encoding = 'utf-8' - bs=BeautifulSoup(req.text, 'html.parser') - p = re.compile(r"^(.*?)_(.*?)_(.*?).pat$", re.MULTILINE | re.DOTALL) - data = bs.find_all('a', string=p) - for item in data: - p = re.compile(r"DSM_(.*?)_(.*?).pat", re.MULTILINE | re.DOTALL) - rels = p.search(item.attrs['href']) - if rels != None: - info = p.search(item.attrs['href']).groups() - model = info[0].replace('%2B', '+') - if len(MS) > 0 and model.lower() not in MS: - continue - if model not in pats.keys(): - pats[model]={} - pats[model][__fullversion(ver)] = item.attrs['href'] - except: - pass - - print(json.dumps(pats, indent=4)) - -@cli.command() -@click.option("-p", "--platforms", type=str, help="The platforms of Syno.") -def getmodelsoffline(platforms=None): - """ - Get Syno Models. - """ - import re, json - import requests - import fcntl, struct - - if platforms is not None and platforms != "": - PS = platforms.lower().replace(",", " ").split() - else: - PS = [] - - models = [] - with open(os.path.join('/mnt/p3/configs', "offline.json")) as user_file: - data = json.load(user_file) - - for I in data["channel"]["item"]: - if not I["title"].startswith("DSM"): - continue - for J in I["model"]: - arch = J["mUnique"].split("_")[1] - name = J["mLink"].split("/")[-1].split("_")[1].replace("%2B", "+") - if len(PS) > 0 and arch.lower() not in PS: - continue - if any(name == B["name"] for B in models): - continue - models.append({"name": name, "arch": arch}) - - models = sorted(models, key=lambda k: (k["arch"], k["name"])) - print(json.dumps(models, indent=4)) - -if __name__ == "__main__": - cli() \ No newline at end of file diff --git a/scripts/func.sh b/scripts/functions.sh similarity index 100% rename from scripts/func.sh rename to scripts/functions.sh diff --git a/scripts/random.sh b/scripts/random.sh deleted file mode 100755 index 6fcc4407..00000000 --- a/scripts/random.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -function genRandomValue() { - for i in 0 1 2 3 4 5 6 7 8 9 A B C D E F G H J K L M N P Q R S T V W X Y Z; do - echo ${i} - done | sort -R | tail -1 -} \ No newline at end of file