diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8d19d65..e681382 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,22 +8,29 @@ on: paths-ignore: - ".github/**" - "docs/**" - - "README.md" + - "**.md" - "get_version.py" env: IMAGE_NAME: baidunetdisk-docker + DOCKERHUB_SLUG: crazymax/linguist + GHCR_SLUG: ghcr.io/yucat-ovo/baidunetdisk-docker jobs: Build: name: Build - strategy: - matrix: - arch: [linux/amd64, linux/arm64] + outputs: + matrix: ${{ steps.platforms.outputs.matrix }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@master + + - name: Create matrix + id: platforms + run: | + echo "matrix=$(docker buildx bake image-all --print | jq -cr '.target."image-all".platforms')" >>${GITHUB_OUTPUT} + - name: Set variables id: set-vars run: | diff --git a/.gitignore b/.gitignore index 68bc17f..b745cbd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.vscode/ + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/get_version.py b/get_version.py deleted file mode 100644 index c3bcddd..0000000 --- a/get_version.py +++ /dev/null @@ -1,244 +0,0 @@ -import json -import re -import time - -import requests -from lxml import etree - -GLOBAL_HEADER = { - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" -} - -# 截至2024-03-01最新的版本 -GLOBAL_VERSION = [ - "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/4.11.5/baidunetdisk_4.11.5_amd64.deb", -] - -# 定义需要检测的版本号范围 -max_version = [4, 20, 0] -min_version = [4, 17, 0] - -# 定义请求延时时间(秒) -GLOBAL_REQUEST_DELAY = 0.5 - - -def get_js_url() -> str: - """请求百度网盘下载页,获取存在下载链接的js文件""" - max_attempts = 5 - attempt = 0 - - url = "" - while attempt < max_attempts: - try: - r = requests.get( - "https://pan.baidu.com/download", - headers=GLOBAL_HEADER, - ) - e = etree.HTML(r.text, parser=None) - - # 获取包含链接的js文件 - for i in e.xpath("//script/@src"): - if re.search("https:\\/\\/.*chunk-common.*\\.js", i): - url = i - # print(url) - return url - except Exception as e: - print(f"An error occurred: {e}") - attempt += 1 - time.sleep(1) # 等待1秒再重试 - - if attempt == max_attempts: - print("Failed after several attempts") - return url - - -def append_json(json_file_name: str, add): - """为Json添加元素""" - file = None - try: - with open(json_file_name, "r") as f: - file = json.load(f) - # print("file=", file) - - except FileNotFoundError: - file = json.loads("") - - file.append(add) - - # print("ufile=", u_file) - - with open(json_file_name, "w") as f: - f.write(json.dumps(file, sort_keys=True, indent=4)) - return - - -def parse_url_from_json() -> list: - l = "" - try: - with open("url.json", "r") as f: - l = json.load(f) - except FileNotFoundError: - l = [] - return l - - -def parse_url_from_js(): - """从js文件中提取下载的链接并且去重,写入文件 url.json""" - url = get_js_url() - u_url = [] - - max_attempts = 5 - attempt = 0 - - while attempt < max_attempts: - try: - - d_url = "" - r = requests.get( - url, - headers=GLOBAL_HEADER, - ) - # 过滤链接 - d_url = re.findall( - '(?:link|url(?:_[0-9])?):"https://[a-zA-Z/\\.]*?/netdisk/[a-zA-Z10-9/\\._-]*?(?=")', - r.text, - ) - - # 清理 - for i in range(len(d_url)): - d_url[i] = re.sub('(link|url(?:_[0-9])?):"', "", d_url[i]) - - # 去重 - for i in d_url: - if i not in u_url: - u_url.append(i) - - break - except Exception as e: - print(f"An error occurred: {e}") - attempt += 1 - time.sleep(1) # 等待1秒再重试 - - if attempt == max_attempts: - print("Failed after several attempts,set url to default") - u_url = GLOBAL_VERSION - - with open("url.json", "w") as f: - f.write(json.dumps(u_url, sort_keys=True, indent=4)) - return - - -def make_info_json(urls: list): - """保存为Json文件""" - # print("urls:", urls) - l_url = urls[-3:] - # print(l_url) - j = [] - for i in l_url: - j.append( - { - "version": re.findall("(?<=/)((?:[0-9]{1,2}(?:\\.)?){1,3})(?=/)", i)[0], - "arch": re.findall("(amd64|arm64|x86_64)", i)[0], - "pak": re.findall("(rpm|deb)", i)[0], - "url": i, - }, - ) - # print(j) - with open("info.json", "w") as f: - f.write(json.dumps(j, sort_keys=True, indent=4)) - return - - -def make_url_temple(arch: str): - """按照之前所获取的 url.json,创建模板""" - l = "" - url_temple = "" - try: - with open("url.json", "r") as f: - l = json.load(f) - for i in l: - if re.search("amd64", i) != None and re.search("deb", i) != None: - url_temple = re.sub("amd64", arch, i) - url_temple = re.sub( - "(?<=[_/])((?:[0-9]{1,2}(?:\\.)?){1,3})(?=[_/])", "{0}", url_temple - ) - break - # print(url_temple) - except FileNotFoundError: - url_temple = "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/{0}/baidunetdisk_{0}_arm64.deb" - # print(url_temple) - return url_temple - - -def check_version(version: list, arch: str): - """检测指定版本号是否可用""" - url = make_url_temple(arch).format(".".join(str(v) for v in version)) - # url = "https://httpbin.org/status/200" - # print("Getting {0}".format(url)) - - max_attempts = 5 - attempt = 0 - - while attempt < max_attempts: - try: - response = requests.head( - url, - headers=GLOBAL_HEADER, - ) - if response.status_code == 200: - return True - else: - return False - except Exception as e: - print(f"An error occurred: {e}") - attempt += 1 - time.sleep(1) # 等待1秒再重试 - - if attempt == max_attempts: - print("Failed after several attempts") - - return - - -def find_latest_version(min_version, max_version): - """寻找最新版本号""" - version_list = [ - [x, y, z] - for x in range(max_version[0], min_version[0] - 1, -1) - for y in range(max_version[1], min_version[1] - 1, -1) - for z in range(20, -1, -1) - if not (x == max_version[0] and y == max_version[1] and z > max_version[2]) - if not (x == min_version[0] and y == min_version[1] and z < min_version[2]) - ] - for arch in ["amd64", "arm64"]: - for version in version_list: - # 检测指定版本号是否可用 - if check_version(version, arch): - print( - "arch {0} version {1} is available".format( - arch, ".".join(str(v) for v in version) - ) - ) - append_json( - "url.json", - make_url_temple(arch).format(".".join(str(v) for v in version)), - ) - time.sleep(GLOBAL_REQUEST_DELAY) - break - else: - print( - "arch {0} version {1} is not available".format( - arch, ".".join(str(v) for v in version) - ) - ) - time.sleep(GLOBAL_REQUEST_DELAY) - - # 找不到可用版本号,返回None - return None - - -if __name__ == "__main__": - parse_url_from_js() - find_latest_version(min_version, max_version) - urls = parse_url_from_json() - make_info_json(urls) diff --git a/jsontemplate.json b/jsontemplate.json new file mode 100644 index 0000000..7b428a8 --- /dev/null +++ b/jsontemplate.json @@ -0,0 +1,42 @@ +{ + "platform": { + "linux": { + "latest": { + "version": "4.17.7", + "amd64": "amd64url", + "arm64": "arm64url" + }, + "4.17.7": { + "amd64": "amd64url", + "arm64": "arm64url" + }, + "4.11.5": { + "amd64": "amd64url", + "arm64": "arm64url" + } + }, + "windows": { + "latest": { + "version": "7.19.0.18", + "amd64": "amd64url" + }, + "7.19.0.18": { + "amd64": "amd64url" + }, + "6.9.10.1": { + "amd64": "amd64url" + } + }, + "mac": { + "latest": { + "version": "4.11.0", + "amd64": "amd64url", + "arm64": "arm64url" + }, + "4.11.0": { + "amd64": "amd64url", + "arm64": "arm64url" + } + } + } +} \ No newline at end of file diff --git a/scripts/api_fetcher.py b/scripts/api_fetcher.py new file mode 100644 index 0000000..403ba5d --- /dev/null +++ b/scripts/api_fetcher.py @@ -0,0 +1,81 @@ +import asyncio +import json +import random +import re + +import httpx + + +class APIFetcher: + def __init__(self) -> None: + uas = [ + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", + ] + self.ua = random.choice(uas) + + async def async_fetcher(self, platform: str, max_attempt: int = 5) -> str | None: + url = "https://yun.baidu.com/disk/cmsdata?platform={0}&page=1&num=100".format( + platform + ) + for _ in range(max_attempt): + try: + async with httpx.AsyncClient() as client: + response = await client.get( + url, + headers={ + "User-Agent": self.ua, + "Referer": "https://yun.baidu.com/disk/version?errmsg=Auth+Login+Sucess&errno=0&ssnerror=0&", + }, + timeout=10, + ) + return response.text + except httpx.HTTPError as e: + print(f"An error occurred: {e}") + print(f"Fetch {0} failed after several attempts", url) + return None + + def linux_version(self): + doc = self.linux_json + version = json.loads(doc)["list"][0]["version"] + version = re.search(r"(?P([0-9]{1,2}(\.)?){3,4})", version).group( + "version" + ) + + return version + + def windows_version(self): + doc = self.windows_json + version = json.loads(doc)["list"][0]["version"] + version = re.search(r"(?P([0-9]{1,2}(\.)?){3,4})", version).group( + "version" + ) + return version + + def mac_version(self): + doc = self.mac_json + version = json.loads(doc)["list"][0]["version"] + version = re.search(r"(?P([0-9]{1,2}(\.)?){3,4})", version).group( + "version" + ) + return version + + async def run(self): + L = await asyncio.gather( + self.async_fetcher("linux"), + self.async_fetcher("windows"), + self.async_fetcher("mac"), + ) + # print(L) + self.linux_json, self.windows_json, self.mac_json = L + print(self.linux_json) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + af = APIFetcher() + af.run() diff --git a/scripts/get_version.py b/scripts/get_version.py new file mode 100644 index 0000000..9dcb55b --- /dev/null +++ b/scripts/get_version.py @@ -0,0 +1,146 @@ +import json +import re +import time + +import requests + + +class LinkObj: + def __init__(self, link: str) -> None: + self.link = link + self.version, self.pkg = re.search( + r"(?P([0-9]{1,2}(\.)?){3,4}(?=[\._/])).*(?P(?<=\.)[a-z]{3,4}$)", + link, + ).group("version", "pkg") + arch = re.search( + r"(?Pamd64|arm64)", + link, + ) + if arch: + self.arch = arch.group("arch") + else: + self.arch = "amd64" + + +class Version: + def __init__(self, version, arch_links): + self.version = version + self.arch_links = arch_links + + def to_dict(self): + return self.arch_links.copy() + + +class Platform: + def __init__(self) -> None: + pass + + +def append_json(json_file_name: str, add): + """为Json添加元素""" + file = None + try: + with open(json_file_name, "r") as f: + file = json.load(f) + # print("file=", file) + + except FileNotFoundError: + file = json.loads("") + + file.append(add) + + # print("ufile=", u_file) + + with open(json_file_name, "w") as f: + f.write(json.dumps(file, sort_keys=True, indent=4)) + return + + +def parse_url_from_json() -> list: + link = "" + try: + with open("url.json", "r") as f: + link = json.load(f) + except FileNotFoundError: + link = [] + return link + + +def make_info_json(urls: list): + """保存为Json文件""" + # print("urls:", urls) + l_url = urls[-3:] + # print(l_url) + j = [] + for i in l_url: + j.append( + { + "version": re.findall("(?<=/)((?:[0-9]{1,2}(?:\\.)?){1,3})(?=/)", i)[0], + "arch": re.findall("(amd64|arm64|x86_64)", i)[0], + "pak": re.findall("(rpm|deb)", i)[0], + "url": i, + }, + ) + # print(j) + with open("info.json", "w") as f: + f.write(json.dumps(j, sort_keys=True, indent=4)) + return + + +def make_url_temple(arch: str): + """按照之前所获取的 url.json,创建模板""" + link = "" + url_temple = "" + try: + with open("url.json", "r") as f: + link = json.load(f) + for i in link: + if re.search("amd64", i) is not None and re.search("deb", i) is not None: + url_temple = re.sub("amd64", arch, i) + url_temple = re.sub( + "(?<=[_/])((?:[0-9]{1,2}(?:\\.)?){1,3})(?=[_/])", "{0}", url_temple + ) + break + # print(url_temple) + except FileNotFoundError: + url_temple = "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/{0}/baidunetdisk_{0}_arm64.deb" + # print(url_temple) + return url_temple + + +def check_version(version: list, arch: str): + """检测指定版本号是否可用""" + url = make_url_temple(arch).format(".".join(str(v) for v in version)) + # url = "https://httpbin.org/status/200" + # print("Getting {0}".format(url)) + + max_attempts = 5 + attempt = 0 + + while attempt < max_attempts: + try: + response = requests.head( + url, + headers="", + ) + if response.status_code == 200: + return True + else: + return False + except Exception as e: + print(f"An error occurred: {e}") + attempt += 1 + time.sleep(1) # 等待1秒再重试 + + if attempt == max_attempts: + print("Failed after several attempts") + + return + + +def main(): + pass + + +if __name__ == "__main__": + main() diff --git a/scripts/version_finder b/scripts/version_finder new file mode 100644 index 0000000..7d1d560 --- /dev/null +++ b/scripts/version_finder @@ -0,0 +1,138 @@ +import re + +from api_fetcher import APIFetcher + + +class VersionFinder: + def __init__(self) -> None: + pass + + class TemplateGenerator: + """模板创建类 + + Args: 从网页获取的url数组 + Returns: 模板数组, 版本区域由{0}替代 + """ + + def __init__(self, urls: list) -> list[str]: + self.linux_link = [] + self.windows_link = "" + self.mac_link = [] + + for i in urls: + if re.search("(deb|rpm)", i) is not None: + self.linux_link.append(i) + elif re.search("exe", i) is not None: + if self.windows_link != "": + continue + self.windows_link = i + elif re.search("dmg", i) is not None: + self.mac_link.append(i) + + def linux(self): + arch = ["arm64", "amd64"] + url_template = [] + + for url in self.linux_link: + # print(url) + + version = re.search( + r"(?P(?<=[_/])((?:[0-9]{1,2}(?:\.)?){1,3})(?=[_/])).*(?P(?<=\.)[a-z]{3,4}$)", + url, + ).group("pkg", "version") + + self.linux_version = version[1] + + if version[0] == "rpm": + url_template.append(re.sub(version[1], "{0}", url)) + else: + template = re.sub("amd64", "{0}", url) + url_template += [ + re.sub(version[1], "{0}", template.format(i)) for i in arch + ] + + return url_template + + def windows(self): + self.windows_version = re.search( + r"(?P([0-9]{1,2}(\.)?){3,4}(?=\.|_|\/))", self.windows_link + ).group("version") + return re.sub(self.windows_version, "{0}", self.windows_link) + + def mac(self): + versions = {} + url_template = [] + for url in self.mac_link: + version = re.search( + r"(?P(?<=[_])((?:[0-9]{1,2}(?:\.)?){1,3})(?=[_\.]))", + url, + ).group("version") + if re.search("arm", url): + versions["arm"] = version + url_template.append(re.sub(version, "{0}", url)) + else: + versions["amd"] = version + url_template.append(re.sub(version, "{0}", url)) + self.mac_version = versions + return url_template + + def __version_compear(a: str, b: str): + a_split = a.split(".") + b_split = b.split(".") + flag = False + if len(a) == len(b): + length = len(a_split) + for i in range(length): + if a_split[i] > b_split[i]: + flag = True + if flag: + return a + else: + return b + else: + print("The two version numbers have different lengths.") + return a + + def version_setter(self, api_version): + self.linux_version = self.__version_compear( + self.linux_version, api_version.linux_version() + ) + self.windows_version = self.__version_compear( + self.windows_version, api_version.windows_version() + ) + self.mac_version = self.__version_compear( + self.mac_version, api_version.mac_version() + ) + + def run(self, urls: list): + tg = self.TemplateGenerator(urls) + linux_template = tg.linux() + windows_template = tg.windows() + mac_template = tg.mac() + self.linux_version = tg.linux_version + self.windows_version = tg.windows_version + self.mac_version = tg.mac_version + api = APIFetcher() + api.run() + self.version_setter(api) + + def append_json(self): + pass + + +if __name__ == "__main__": + # import doctest + + # doctest.testmod() + urls = [ + "https://issuepcdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.19.0.18.exe", + "https://issuepcdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_6.9.10.1.exe", + "https://issuepcdn.baidupcs.com/issue/netdisk/MACguanjia/BaiduNetdisk_mac_4.11.0.dmg", + "https://issuepcdn.baidupcs.com/issue/netdisk/MACguanjia/BaiduNetdisk_mac_4.11.0_arm64.dmg", + "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/4.11.5/baidunetdisk-4.11.5.x86_64.rpm", + "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/4.11.5/baidunetdisk_4.11.5_amd64.deb", + ] + vf = VersionFinder() + vf.run(urls) + print(vf.linux_version) + pass diff --git a/scripts/web_fetcher.py b/scripts/web_fetcher.py new file mode 100644 index 0000000..79e9b27 --- /dev/null +++ b/scripts/web_fetcher.py @@ -0,0 +1,148 @@ +import json +import random +import re + +import httpx +from lxml import etree + + +class WebFetcher: + def __init__(self) -> None: + uas = [ + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", + ] + self.ua = random.choice(uas) + + def fetcher(self, url: str, max_attempt: int = 5) -> str | None: + """网址抓取器 + + 从给定 url 抓取对应数据, 失败时重试, 默认重试5次 + + >>> bdnd = WebFetcher() + >>> type(bdnd.fetcher("https://pan.baidu.com/download")) is str + True + >>> type(bdnd.fetcher("https://1.1.1.1", max_attempt=1)) is str + True + >>> bdnd.fetcher("https://172.1.1.1", max_attempt=1) + An error occurred: timed out + + Args: + url: 网址 + max_attempt: 重试次数 + + Returns: + 成功时返回所获取网页的text数据 + 失败时返回None + """ + for _ in range(max_attempt): + try: + response = httpx.get( + url, + headers={ + "User-Agent": self.ua, + "Referer": "https://pan.baidu.com/disk/main", + }, + timeout=10, + ) + return response.text + except httpx.HTTPError as e: + print(f"An error occurred: {e}") + + async def async_fetcher(self, url: str, max_attempt: int = 5) -> str | None: + for attempt in range(max_attempt): + try: + async with httpx.AsyncClient() as client: + response = await client.get( + url, + headers={ + "User-Agent": self.ua, + "Referer": "https://pan.baidu.com/disk/main", + }, + timeout=10, + ) + return response + except httpx.HTTPError as e: + print(f"An error occurred: {e}") + print(f"Fetch {0} failed after several attempts", url) + return None + + def fetch_js_url(self) -> list: + """请求百度网盘下载页,获取存在下载链接的js文件 + + Returns: + 成功时设置self.js_url为所获取网页的text数据 + 失败时设置self.js_url为None + + >>> bdnd = WebFetcher() + >>> bdnd.fetch_js_url() + 'https://nd-static.bdstatic.com/m-static/wp-brand/js/chunk-common.8b953c6c.js' + """ + response = self.fetcher("https://pan.baidu.com/download") + if response is not None: + try: + doc = etree.HTML(response, parser=None) + for i in doc.xpath("//script/@src"): + if re.search(r"https:\/\/.*chunk-common.*\.js", i): + self.js_url = i + return i + except Exception as e: + print(f"An error occurred: {e}, set js_url to default") + self.js_url = "https://nd-static.bdstatic.com/m-static/wp-brand/js/chunk-common.8b953c6c.js" + return self.js_url + else: + print("Fetcher return None, set js_url to default") + self.js_url = "https://nd-static.bdstatic.com/m-static/wp-brand/js/chunk-common.8b953c6c.js" + return self.js_url + + def parse_url_from_js(self) -> list: + """从js文件中提取下载的链接并且去重 + + >>> bdnd = WebFetcher() + >>> bdnd.fetch_js_url() + 'https://nd-static.bdstatic.com/m-static/wp-brand/js/chunk-common.8b953c6c.js' + >>> len(bdnd.parse_url_from_js()) + 6 + """ + # 获取js数据 + js_url = self.js_url + response = self.fetcher(js_url) + + # 过滤链接 + original_url = re.findall( + r'(?:(?:link|url)(?:_[0-9])?:")(?Phttps://[a-zA-Z/\.]*?/netdisk/[a-zA-Z10-9/\._-]*?)(?=")', + response, + ) + + # 去重 + unique_url = [] + for i in original_url: + if i not in unique_url: + unique_url.append(i) + self.link_url = unique_url + return unique_url + + def json_saver(self): + try: + with open("url.json", "w") as f: + f.write(json.dumps(self.link_url, sort_keys=True, indent=4)) + except Exception as e: + print(f"An error occurred: {e}, Please check the permissions.") + + def run(self): + doc = WebFetcher() + doc.fetch_js_url() + doc.parse_url_from_js() + doc.json_saver() + return self.link_url + + def get_urls(self) -> list: + return self.link_url + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/url.json b/url.json index 771552e..12f14c4 100644 --- a/url.json +++ b/url.json @@ -4,7 +4,5 @@ "https://issuepcdn.baidupcs.com/issue/netdisk/MACguanjia/BaiduNetdisk_mac_4.11.0.dmg", "https://issuepcdn.baidupcs.com/issue/netdisk/MACguanjia/BaiduNetdisk_mac_4.11.0_arm64.dmg", "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/4.11.5/baidunetdisk-4.11.5.x86_64.rpm", - "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/4.11.5/baidunetdisk_4.11.5_amd64.deb", - "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/4.17.7/baidunetdisk_4.17.7_amd64.deb", - "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/4.17.7/baidunetdisk_4.17.7_arm64.deb" + "https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/4.11.5/baidunetdisk_4.11.5_amd64.deb" ] \ No newline at end of file