From ec1d2d44e684a32ed9c444a8b9dadcefbfc8ab0a Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 23 Nov 2025 23:35:03 +0100 Subject: [PATCH] discord: rework sources and update script Signed-off-by: Sefa Eyeoglu --- .../instant-messengers/discord/darwin.nix | 12 +- .../instant-messengers/discord/default.nix | 71 ++--------- .../instant-messengers/discord/linux.nix | 9 +- .../instant-messengers/discord/sources.json | 42 +++++++ .../instant-messengers/discord/update.py | 110 ++++++++++++++++++ 5 files changed, 166 insertions(+), 78 deletions(-) create mode 100644 pkgs/applications/networking/instant-messengers/discord/sources.json create mode 100755 pkgs/applications/networking/instant-messengers/discord/update.py diff --git a/pkgs/applications/networking/instant-messengers/discord/darwin.nix b/pkgs/applications/networking/instant-messengers/discord/darwin.nix index 1f1422371640..0c8a22e54022 100644 --- a/pkgs/applications/networking/instant-messengers/discord/darwin.nix +++ b/pkgs/applications/networking/instant-messengers/discord/darwin.nix @@ -106,17 +106,7 @@ stdenv.mkDerivation { passthru = { # make it possible to run disableBreakingUpdates standalone inherit disableBreakingUpdates; - updateScript = writeScript "discord-update-script" '' - #!/usr/bin/env nix-shell - #!nix-shell -i bash -p curl gnugrep common-updater-scripts - set -x - set -eou pipefail; - url=$(curl -sI -o /dev/null -w '%header{location}' "https://discord.com/api/download/${branch}?platform=osx&format=dmg") - version=$(echo $url | grep -oP '/\K(\d+\.){2}\d+') - update-source-version ${ - lib.optionalString (!stdenv.buildPlatform.isDarwin) "pkgsCross.aarch64-darwin." - }${pname} "$version" --file=./pkgs/applications/networking/instant-messengers/discord/default.nix --version-key=${branch} - ''; + updateScript = ./update.py; tests = { withVencord = self.override { diff --git a/pkgs/applications/networking/instant-messengers/discord/default.nix b/pkgs/applications/networking/instant-messengers/discord/default.nix index 56824c642ca4..182394149aa8 100644 --- a/pkgs/applications/networking/instant-messengers/discord/default.nix +++ b/pkgs/applications/networking/instant-messengers/discord/default.nix @@ -12,52 +12,24 @@ let variants = rec { x86_64-linux = { discord = rec { - version = "0.0.115"; - - src = fetchurl { - url = "https://stable.dl2.discordapp.net/apps/linux/${version}/discord-${version}.tar.gz"; - hash = "sha256-DXGlo9qdmJTqm6ResvspauQ0awIFSuYalcpVXEfTxK4="; - }; - branch = "stable"; binaryName = desktopName; desktopName = "Discord"; self = discord; }; - discord-ptb = rec { - version = "0.0.167"; - - src = fetchurl { - url = "https://ptb.dl2.discordapp.net/apps/linux/${version}/discord-ptb-${version}.tar.gz"; - hash = "sha256-Q4IrmvoP//49GN2L9kRQ/zG28XjicJEXZpVG6RklFB8="; - }; - + discord-ptb = { branch = "ptb"; binaryName = "DiscordPTB"; desktopName = "Discord PTB"; self = discord-ptb; }; - discord-canary = rec { - version = "0.0.811"; - - src = fetchurl { - url = "https://canary.dl2.discordapp.net/apps/linux/${version}/discord-canary-${version}.tar.gz"; - hash = "sha256-kg0o5KyBohmnk/czUQLVsA1GV2P6DUQLy0KhMaj80Sk="; - }; - + discord-canary = { branch = "canary"; binaryName = "DiscordCanary"; desktopName = "Discord Canary"; self = discord-canary; }; - discord-development = rec { - version = "0.0.92"; - - src = fetchurl { - url = "https://development.dl2.discordapp.net/apps/linux/${version}/discord-development-${version}.tar.gz"; - hash = "sha256-oG50YrXQUCnbn+rO0EeRjixeqvXYBdnyqdomdPfxfos="; - }; - + discord-development = { branch = "development"; binaryName = "DiscordDevelopment"; desktopName = "Discord Development"; @@ -66,52 +38,24 @@ let }; x86_64-darwin = { discord = rec { - version = "0.0.362"; - - src = fetchurl { - url = "https://stable.dl2.discordapp.net/apps/osx/${version}/Discord.dmg"; - hash = "sha256-DHe0WwJOB3mm1HbQwEOJ9NWqxzhOBQynhjJXYSNvA/k="; - }; - branch = "stable"; binaryName = desktopName; desktopName = "Discord"; self = discord; }; discord-ptb = rec { - version = "0.0.192"; - - src = fetchurl { - url = "https://ptb.dl2.discordapp.net/apps/osx/${version}/DiscordPTB.dmg"; - hash = "sha256-AZ9enKJf6WZLELFLKrzeyAR/Q/pzD8SGvCPcInS8vsk="; - }; - branch = "ptb"; binaryName = desktopName; desktopName = "Discord PTB"; self = discord-ptb; }; discord-canary = rec { - version = "0.0.867"; - - src = fetchurl { - url = "https://canary.dl2.discordapp.net/apps/osx/${version}/DiscordCanary.dmg"; - hash = "sha256-67B2wZRZEOKutMPsrRlc96UZWShYLAgwOoF2/QzBgzE="; - }; - branch = "canary"; binaryName = desktopName; desktopName = "Discord Canary"; self = discord-canary; }; discord-development = rec { - version = "0.0.100"; - - src = fetchurl { - url = "https://development.dl2.discordapp.net/apps/osx/${version}/DiscordDevelopment.dmg"; - hash = "sha256-PknNHr9txxp3+nO7FgHH7n04qx6p6Jzbs92/Hcfh13Y="; - }; - branch = "development"; binaryName = desktopName; desktopName = "Discord Development"; @@ -144,16 +88,25 @@ let sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; }; package = if stdenv.hostPlatform.isLinux then ./linux.nix else ./darwin.nix; + + sources = lib.importJSON ./sources.json; in lib.genAttrs [ "discord" "discord-ptb" "discord-canary" "discord-development" ] ( pname: let args = (variants.${stdenv.hostPlatform.system} or variants.default).${pname}; + platformName = if stdenv.hostPlatform.isDarwin then "osx" else "linux"; + source = sources."${platformName}-${args.branch}"; in callPackage package ( args // { inherit pname; + inherit (source) version; + + src = fetchurl { + inherit (source) url hash; + }; meta = meta // { mainProgram = args.binaryName; diff --git a/pkgs/applications/networking/instant-messengers/discord/linux.nix b/pkgs/applications/networking/instant-messengers/discord/linux.nix index fe876a5154f6..272e68447aed 100644 --- a/pkgs/applications/networking/instant-messengers/discord/linux.nix +++ b/pkgs/applications/networking/instant-messengers/discord/linux.nix @@ -253,14 +253,7 @@ stdenv.mkDerivation (finalAttrs: { passthru = { # make it possible to run disableBreakingUpdates standalone inherit disableBreakingUpdates; - updateScript = writeScript "discord-update-script" '' - #!/usr/bin/env nix-shell - #!nix-shell -i bash -p curl gnugrep common-updater-scripts - set -eou pipefail; - url=$(curl -sI -o /dev/null -w '%header{location}' "https://discord.com/api/download/${branch}?platform=linux&format=tar.gz") - version=$(echo $url | grep -oP '/\K(\d+\.){2}\d+') - update-source-version ${pname} "$version" --file=./pkgs/applications/networking/instant-messengers/discord/default.nix --version-key=${branch} - ''; + updateScript = ./update.py; tests = { withVencord = self.override { diff --git a/pkgs/applications/networking/instant-messengers/discord/sources.json b/pkgs/applications/networking/instant-messengers/discord/sources.json new file mode 100644 index 000000000000..580ba91c80ce --- /dev/null +++ b/pkgs/applications/networking/instant-messengers/discord/sources.json @@ -0,0 +1,42 @@ +{ + "linux-canary": { + "hash": "sha256-kg0o5KyBohmnk/czUQLVsA1GV2P6DUQLy0KhMaj80Sk=", + "url": "https://canary.dl2.discordapp.net/apps/linux/0.0.811/discord-canary-0.0.811.tar.gz", + "version": "0.0.811" + }, + "linux-development": { + "hash": "sha256-oG50YrXQUCnbn+rO0EeRjixeqvXYBdnyqdomdPfxfos=", + "url": "https://development.dl2.discordapp.net/apps/linux/0.0.92/discord-development-0.0.92.tar.gz", + "version": "0.0.92" + }, + "linux-ptb": { + "hash": "sha256-Q4IrmvoP//49GN2L9kRQ/zG28XjicJEXZpVG6RklFB8=", + "url": "https://ptb.dl2.discordapp.net/apps/linux/0.0.167/discord-ptb-0.0.167.tar.gz", + "version": "0.0.167" + }, + "linux-stable": { + "hash": "sha256-DXGlo9qdmJTqm6ResvspauQ0awIFSuYalcpVXEfTxK4=", + "url": "https://stable.dl2.discordapp.net/apps/linux/0.0.115/discord-0.0.115.tar.gz", + "version": "0.0.115" + }, + "osx-canary": { + "hash": "sha256-67B2wZRZEOKutMPsrRlc96UZWShYLAgwOoF2/QzBgzE=", + "url": "https://canary.dl2.discordapp.net/apps/osx/0.0.867/DiscordCanary.dmg", + "version": "0.0.867" + }, + "osx-development": { + "hash": "sha256-PknNHr9txxp3+nO7FgHH7n04qx6p6Jzbs92/Hcfh13Y=", + "url": "https://development.dl2.discordapp.net/apps/osx/0.0.100/DiscordDevelopment.dmg", + "version": "0.0.100" + }, + "osx-ptb": { + "hash": "sha256-AZ9enKJf6WZLELFLKrzeyAR/Q/pzD8SGvCPcInS8vsk=", + "url": "https://ptb.dl2.discordapp.net/apps/osx/0.0.192/DiscordPTB.dmg", + "version": "0.0.192" + }, + "osx-stable": { + "hash": "sha256-DHe0WwJOB3mm1HbQwEOJ9NWqxzhOBQynhjJXYSNvA/k=", + "url": "https://stable.dl2.discordapp.net/apps/osx/0.0.362/Discord.dmg", + "version": "0.0.362" + } +} diff --git a/pkgs/applications/networking/instant-messengers/discord/update.py b/pkgs/applications/networking/instant-messengers/discord/update.py new file mode 100755 index 000000000000..d2577eab8c91 --- /dev/null +++ b/pkgs/applications/networking/instant-messengers/discord/update.py @@ -0,0 +1,110 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i python3 -p python3 + +from enum import StrEnum +from typing import List, Tuple +from subprocess import PIPE, Popen +import json +import urllib.request +import re +import os.path + +SRC_NAME = "source" + +VERSION_REGEX = re.compile(r"\/([\d.]+)\/") + + +class Platform(StrEnum): + LINUX = "linux" + MACOS = "osx" + + def format_type(self): + if self.value == Platform.LINUX.value: + return "tar.gz" + elif self.value == Platform.MACOS.value: + return "dmg" + raise RuntimeError("Invalid platform") + + +class Branch(StrEnum): + STABLE = "stable" + PTB = "ptb" + CANARY = "canary" + DEVELOPMENT = "development" + + +Variant = Tuple[Platform, Branch] + + +def serialize_variant(variant: Variant) -> str: + platform, branch = variant + return f"{platform}-{branch}" + + +def url_for_variant(variant: Variant) -> str: + platform, branch = variant + + return f"https://discord.com/api/download/{branch.value}?platform={platform.value}&format={platform.format_type()}" + + +def fetch_redirect_url(url: str) -> str: + headers = {"user-agent": "Nixpkgs-Discord-Update-Script/0.0.0"} + # note that urllib follows redirects by default. So we can extract the final url from the response object + req = urllib.request.Request(url, headers=headers) + with urllib.request.urlopen(req) as response: + return response.url + + +def version_from_url(url: str) -> str: + matches = VERSION_REGEX.search(url) + assert matches, f"Url {url} must contain version number" + version = matches.group(1) + assert version + return version + + +def prefetch(url: str) -> str: + with Popen(["nix-prefetch-url", "--name", "source", url], stdout=PIPE) as p: + assert p.stdout + b32_hash = p.stdout.read().decode("utf-8").strip() + with Popen( + ["nix-hash", "--to-sri", "--type", "sha256", b32_hash], stdout=PIPE + ) as p: + assert p.stdout + sri_hash = p.stdout.read().decode("utf-8").strip() + return sri_hash + + +def main(): + variants: List[Variant] = [ + (Platform.LINUX, Branch.STABLE), + (Platform.LINUX, Branch.PTB), + (Platform.LINUX, Branch.CANARY), + (Platform.LINUX, Branch.DEVELOPMENT), + (Platform.MACOS, Branch.STABLE), + (Platform.MACOS, Branch.PTB), + (Platform.MACOS, Branch.CANARY), + (Platform.MACOS, Branch.DEVELOPMENT), + ] + + sources = {} + + for v in variants: + url = url_for_variant(v) + url = fetch_redirect_url(url) + version = version_from_url(url) + sri_hash = prefetch(url) + + sources[serialize_variant(v)] = { + "url": url, + "version": version, + "hash": sri_hash, + } + + with open(os.path.join(os.path.dirname(__file__), "sources.json"), "w") as f: + json.dump(sources, f, indent=2, sort_keys=True) + f.write("\n") + + +if __name__ == "__main__": + main()