discord: fetch distros at build time (#507728)
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
{
|
||||
pname,
|
||||
version,
|
||||
src,
|
||||
source,
|
||||
meta,
|
||||
stdenv,
|
||||
binaryName,
|
||||
desktopName,
|
||||
self,
|
||||
lib,
|
||||
fetchurl,
|
||||
undmg,
|
||||
makeWrapper,
|
||||
writeScript,
|
||||
@@ -33,6 +33,9 @@ let
|
||||
];
|
||||
enabledDiscordModsCount = builtins.length (lib.filter (x: x) discordMods);
|
||||
|
||||
inherit (source) version;
|
||||
src = fetchurl { inherit (source) url hash; };
|
||||
|
||||
disableBreakingUpdates =
|
||||
runCommand "disable-breaking-updates.py"
|
||||
{
|
||||
@@ -106,6 +109,7 @@ stdenv.mkDerivation {
|
||||
passthru = {
|
||||
# make it possible to run disableBreakingUpdates standalone
|
||||
inherit disableBreakingUpdates;
|
||||
inherit source;
|
||||
updateScript = ./update.py;
|
||||
|
||||
tests = {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
callPackage,
|
||||
fetchurl,
|
||||
lib,
|
||||
stdenv,
|
||||
discord,
|
||||
@@ -101,13 +100,7 @@ lib.genAttrs [ "discord" "discord-ptb" "discord-canary" "discord-development" ]
|
||||
callPackage package (
|
||||
args
|
||||
// {
|
||||
inherit pname;
|
||||
inherit (source) version;
|
||||
|
||||
src = fetchurl {
|
||||
inherit (source) url hash;
|
||||
};
|
||||
|
||||
inherit pname source;
|
||||
meta = meta // {
|
||||
mainProgram = args.binaryName;
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
pname,
|
||||
version,
|
||||
src,
|
||||
source,
|
||||
meta,
|
||||
binaryName,
|
||||
desktopName,
|
||||
self,
|
||||
autoPatchelfHook,
|
||||
fetchurl,
|
||||
makeDesktopItem,
|
||||
lib,
|
||||
stdenv,
|
||||
@@ -44,15 +44,18 @@
|
||||
libxrender,
|
||||
libxtst,
|
||||
libxcb,
|
||||
libxkbcommon,
|
||||
libxshmfence,
|
||||
libgbm,
|
||||
nspr,
|
||||
nss,
|
||||
openssl_1_1,
|
||||
pango,
|
||||
systemdLibs,
|
||||
libappindicator-gtk3,
|
||||
libdbusmenu,
|
||||
writeScript,
|
||||
brotli,
|
||||
writeShellScript,
|
||||
pipewire,
|
||||
python3,
|
||||
runCommand,
|
||||
@@ -85,6 +88,97 @@ let
|
||||
];
|
||||
enabledDiscordModsCount = builtins.length (lib.filter (x: x) discordMods);
|
||||
|
||||
# Starting with discord-development 0.0.235, the linux tarball ships only a
|
||||
# small `updater_bootstrap` ELF that downloads the real app at first launch
|
||||
#
|
||||
# That binary always fetches the latest version from Discord's CDN with no way
|
||||
# to pin, making the build impure and the nix version a lie
|
||||
#
|
||||
# Instead we fetch the app directly from the distributions API at build time:
|
||||
# https://updates.discord.com/distributions/app/manifests/latest?channel=...
|
||||
# The host + module distros are brotli-compressed tars on Discord's CDN at
|
||||
# predictable URLs with SHA256 hashes in the manifest
|
||||
isDistro = source.kind == "distro";
|
||||
|
||||
inherit (source) version;
|
||||
|
||||
src =
|
||||
if isDistro then
|
||||
fetchurl { inherit (source.distro) url hash; }
|
||||
else
|
||||
fetchurl { inherit (source) url hash; };
|
||||
|
||||
moduleSrcs = lib.optionalAttrs isDistro (
|
||||
lib.mapAttrs (_: mod: fetchurl { inherit (mod) url hash; }) source.modules
|
||||
);
|
||||
|
||||
moduleVersions = lib.optionalAttrs isDistro (lib.mapAttrs (_: mod: mod.version) source.modules);
|
||||
|
||||
libPath = lib.makeLibraryPath (
|
||||
[
|
||||
libcxx
|
||||
systemdLibs
|
||||
libpulseaudio
|
||||
libdrm
|
||||
libgbm
|
||||
stdenv.cc.cc
|
||||
alsa-lib
|
||||
atk
|
||||
at-spi2-atk
|
||||
at-spi2-core
|
||||
cairo
|
||||
cups
|
||||
dbus
|
||||
expat
|
||||
fontconfig
|
||||
freetype
|
||||
gdk-pixbuf
|
||||
glib
|
||||
gtk3
|
||||
libglvnd
|
||||
libnotify
|
||||
libx11
|
||||
libxcomposite
|
||||
libunity
|
||||
libuuid
|
||||
libva
|
||||
libxcursor
|
||||
libxdamage
|
||||
libxext
|
||||
libxfixes
|
||||
libxi
|
||||
libxrandr
|
||||
libxrender
|
||||
libxtst
|
||||
nspr
|
||||
nss
|
||||
libxcb
|
||||
libxkbcommon
|
||||
pango
|
||||
pipewire
|
||||
libxscrnsaver
|
||||
libappindicator-gtk3
|
||||
libdbusmenu
|
||||
wayland
|
||||
]
|
||||
++ lib.optionals withTTS [ speechd-minimal ]
|
||||
);
|
||||
|
||||
# Symlink native modules from the nix store into the user config dir
|
||||
# where Discord's JS moduleUpdater expects them.
|
||||
stageModules = writeShellScript "discord-stage-modules" ''
|
||||
store_modules="$1"
|
||||
modules_dir="''${XDG_CONFIG_HOME:-$HOME/.config}/${lib.toLower binaryName}/${version}/modules"
|
||||
if [ ! -f "$modules_dir/installed.json" ]; then
|
||||
mkdir -p "$modules_dir"
|
||||
for m in ${lib.concatStringsSep " " (lib.attrNames moduleSrcs)}; do
|
||||
ln -sfn "$store_modules/$m" "$modules_dir/$m"
|
||||
done
|
||||
echo '${builtins.toJSON (lib.mapAttrs (_: mod: { installedVersion = mod; }) moduleVersions)}' \
|
||||
> "$modules_dir/installed.json"
|
||||
fi
|
||||
'';
|
||||
|
||||
disableBreakingUpdates =
|
||||
runCommand "disable-breaking-updates.py"
|
||||
{
|
||||
@@ -123,7 +217,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
libxshmfence
|
||||
wrapGAppsHook3
|
||||
makeShellWrapper
|
||||
];
|
||||
]
|
||||
++ lib.optionals isDistro [ brotli ];
|
||||
|
||||
dontWrapGApps = true;
|
||||
|
||||
@@ -132,67 +227,59 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
libgbm
|
||||
nspr
|
||||
nss
|
||||
]
|
||||
# The new distro layout ships prebuilt `.node` modules:
|
||||
# discord_dispatch is linked against openssl 1.1, discord_voice against libpulseaudio
|
||||
++ lib.optionals isDistro [
|
||||
openssl_1_1
|
||||
libpulseaudio
|
||||
];
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
libPath = lib.makeLibraryPath (
|
||||
[
|
||||
libcxx
|
||||
systemdLibs
|
||||
libpulseaudio
|
||||
libdrm
|
||||
libgbm
|
||||
stdenv.cc.cc
|
||||
alsa-lib
|
||||
atk
|
||||
at-spi2-atk
|
||||
at-spi2-core
|
||||
cairo
|
||||
cups
|
||||
dbus
|
||||
expat
|
||||
fontconfig
|
||||
freetype
|
||||
gdk-pixbuf
|
||||
glib
|
||||
gtk3
|
||||
libglvnd
|
||||
libnotify
|
||||
libx11
|
||||
libxcomposite
|
||||
libunity
|
||||
libuuid
|
||||
libva
|
||||
libxcursor
|
||||
libxdamage
|
||||
libxext
|
||||
libxfixes
|
||||
libxi
|
||||
libxrandr
|
||||
libxrender
|
||||
libxtst
|
||||
nspr
|
||||
libxcb
|
||||
pango
|
||||
pipewire
|
||||
libxscrnsaver
|
||||
libappindicator-gtk3
|
||||
libdbusmenu
|
||||
wayland
|
||||
]
|
||||
++ lib.optionals withTTS [ speechd-minimal ]
|
||||
);
|
||||
dontUnpack = isDistro;
|
||||
|
||||
inherit libPath;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/{bin,opt/${binaryName},share/icons/hicolor/256x256/apps}
|
||||
mv * $out/opt/${binaryName}
|
||||
''
|
||||
+ (
|
||||
if isDistro then
|
||||
''
|
||||
# Distro layout (currently discord-ptb, discord-canary and discord-development):
|
||||
#
|
||||
# The host distro is a brotli-compressed tar with all files under a `files/`
|
||||
# prefix (the channel binary, libffmpeg.so, resources/, etc). Module distros
|
||||
# follow the same format with module contents under `files/`
|
||||
#
|
||||
# The module directory layout must match what Discord's node runtime
|
||||
# expects: modules/<name>/ (the moduleUpdater extracts zips into
|
||||
# path.join(moduleInstallPath, moduleName) see processUnzipQueue)
|
||||
|
||||
chmod +x $out/opt/${binaryName}/${binaryName}
|
||||
patchelf --set-interpreter ${stdenv.cc.bintools.dynamicLinker} \
|
||||
$out/opt/${binaryName}/${binaryName}
|
||||
brotli -d < $src | tar xf - --strip-components=1 -C $out/opt/${binaryName}
|
||||
chmod +x $out/opt/${binaryName}/${binaryName}
|
||||
|
||||
# Extract native modules
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (name: src: ''
|
||||
mkdir -p $out/opt/${binaryName}/modules/${name}
|
||||
brotli -d < ${src} | tar xf - --strip-components=1 -C $out/opt/${binaryName}/modules/${name}
|
||||
'') moduleSrcs
|
||||
)}
|
||||
|
||||
''
|
||||
else
|
||||
''
|
||||
# Tarball layout (stable): the tarball unpacks into a
|
||||
# directory containing the channel binary directly
|
||||
mv * $out/opt/${binaryName}
|
||||
chmod +x $out/opt/${binaryName}/${binaryName}
|
||||
''
|
||||
)
|
||||
+ ''
|
||||
|
||||
wrapProgramShell $out/opt/${binaryName}/${binaryName} \
|
||||
"''${gappsWrapperArgs[@]}" \
|
||||
@@ -205,6 +292,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
--prefix XDG_DATA_DIRS : "${gtk3}/share/gsettings-schemas/${gtk3.name}/" \
|
||||
--prefix LD_LIBRARY_PATH : ${finalAttrs.libPath}:$out/opt/${binaryName} \
|
||||
${lib.strings.optionalString disableUpdates "--run ${lib.getExe disableBreakingUpdates}"} \
|
||||
${lib.strings.optionalString isDistro ''--run "${stageModules} $out/opt/${binaryName}/modules"''} \
|
||||
--add-flags ${lib.escapeShellArg commandLineArgs}
|
||||
|
||||
ln -s $out/opt/${binaryName}/${binaryName} $out/bin/
|
||||
@@ -258,6 +346,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
passthru = {
|
||||
# make it possible to run disableBreakingUpdates standalone
|
||||
inherit disableBreakingUpdates;
|
||||
# Exposed so reviewers can inspect which distro modules are pinned
|
||||
inherit source moduleVersions;
|
||||
updateScript = ./update.py;
|
||||
|
||||
tests = {
|
||||
|
||||
@@ -1,42 +1,242 @@
|
||||
{
|
||||
"linux-canary": {
|
||||
"hash": "sha256-wTAmrtGcJpI/DIrLQu/++WuVzMr9EcJs+AIFkAilFvk=",
|
||||
"url": "https://canary.dl2.discordapp.net/apps/linux/0.0.927/discord-canary-0.0.927.tar.gz",
|
||||
"version": "0.0.927"
|
||||
"distro": {
|
||||
"hash": "sha256-4xA+Kh6UiwtoUt5A2kPI5rcbSEc/SoZzJbwFdjMNVpE=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/full.distro"
|
||||
},
|
||||
"kind": "distro",
|
||||
"modules": {
|
||||
"discord_cloudsync": {
|
||||
"hash": "sha256-3dcVKm/Sz9bqhEm8xVMtRcWrU6JWtv2Dh8oz/3K489E=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_cloudsync/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_desktop_core": {
|
||||
"hash": "sha256-7zcFkh3f9BVjHlevCkZXUFNdeLCkM2+sysuSUyPcQlA=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_desktop_core/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_dispatch": {
|
||||
"hash": "sha256-TD1vWHt4y3xkAEc/BV2HZe3tNdP0PTZsXhVeeHvRAU4=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_dispatch/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_erlpack": {
|
||||
"hash": "sha256-nv6kKT+ZWfwkH4BvOWtjF8VZoznzYRN0hK8kiTbcX/I=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_erlpack/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_game_utils": {
|
||||
"hash": "sha256-Ru8zXxDGwHrpMnnraAVR0Z7jRA4PRLHX7pBz8jctar8=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_game_utils/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_krisp": {
|
||||
"hash": "sha256-zkhTv+8qzyrZBHpZeCzJX6z8HCK0M4Jt6Kr+InbVT80=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_krisp/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_modules": {
|
||||
"hash": "sha256-j5UE4ZugIF4HTsOgxK3Dfp0WP3Sya1fbDjERxGu2qSM=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_modules/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_rpc": {
|
||||
"hash": "sha256-HaUt+G05Im2uNkUB9Ry1c6X/iadc7xLrcEgJCVgpgsY=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_rpc/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_spellcheck": {
|
||||
"hash": "sha256-8cOwisLqnxGsbqPYStBAaKEaALIM0M5d3RPLtoHxClw=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_spellcheck/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_utils": {
|
||||
"hash": "sha256-hfQu3fT9ON0j8xEAwCRY7/ALYYq/a70W/8HeT3KhZF0=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_utils/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_voice": {
|
||||
"hash": "sha256-JJXt5wHat6AtxW1GIzsPnMHJPzX1DlPgB3kDcg9Bnts=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_voice/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_zstd": {
|
||||
"hash": "sha256-PMlqdAI44AngVh75Eq66zHLEoJkI0262FcFUffPykCk=",
|
||||
"url": "https://canary.dl2.discordapp.net/distro/app/canary/linux/x64/1.0.962/discord_zstd/1/full.distro",
|
||||
"version": 1
|
||||
}
|
||||
},
|
||||
"version": "1.0.962"
|
||||
},
|
||||
"linux-development": {
|
||||
"hash": "sha256-Xe5PjHDWXU+eIAcBID34gjuADmAl1JAQLmXUAi/p4tg=",
|
||||
"url": "https://development.dl2.discordapp.net/apps/linux/0.0.99/discord-development-0.0.99.tar.gz",
|
||||
"version": "0.0.99"
|
||||
"distro": {
|
||||
"hash": "sha256-6MLiRO2GYXkBRQjzOwmKHVqMqGsVjk0E3ocvdYyg8qs=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/full.distro"
|
||||
},
|
||||
"kind": "distro",
|
||||
"modules": {
|
||||
"discord_cloudsync": {
|
||||
"hash": "sha256-6yEFPNHqs5Mk+1V2x4R/ZwFgwb2Z+O9iOrX78/G3ynM=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_cloudsync/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_desktop_core": {
|
||||
"hash": "sha256-Z82Y9I4brUOvGiZhgL5V+wXRFfDH/XazWJG3OMYyo3s=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_desktop_core/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_dispatch": {
|
||||
"hash": "sha256-MTjgc8SfL7i4O+QkYQu0Os04iAM1x85AAZxuooI5Oog=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_dispatch/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_erlpack": {
|
||||
"hash": "sha256-JQAgkIpev2+1dlfPW/bg/Iek/cL3+V92IpZIa8e+Fp8=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_erlpack/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_game_utils": {
|
||||
"hash": "sha256-ixKdUlXhDVmk3P41gFixSpPJCMnd3c/yLQF1J7DYI+M=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_game_utils/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_krisp": {
|
||||
"hash": "sha256-UJmBXQm0SXbCOjtJN72BZJCViULhpJgc0rgqDrhhNR0=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_krisp/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_modules": {
|
||||
"hash": "sha256-+TH9x91upIuX9nwvpF9pX4w58YRqu6+hbF1RSyiykdM=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_modules/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_rpc": {
|
||||
"hash": "sha256-cGK1qN8jUiw2l9KNbb7eucWWPw191AHzh/4C6T8gI44=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_rpc/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_spellcheck": {
|
||||
"hash": "sha256-b/X24WJi2Mi0x7Ynqphmtr6FSYUMSR9dDPPUF/k/TN8=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_spellcheck/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_utils": {
|
||||
"hash": "sha256-+dslIrgHH5r7sz95Ixb+5DDOQA8PEr4BcqkJTchf3WQ=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_utils/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_voice": {
|
||||
"hash": "sha256-7rg5Ct/BPJaOak0HOeTuYMbfdhHBvI4qML1nnYzZ+IE=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_voice/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_zstd": {
|
||||
"hash": "sha256-XKJNd/9l3PJX1GTHT0hvsB9pqI6oDkAvay2L3bOIk/0=",
|
||||
"url": "https://development.dl2.discordapp.net/distro/app/development/linux/x64/1.0.976/discord_zstd/1/full.distro",
|
||||
"version": 1
|
||||
}
|
||||
},
|
||||
"version": "1.0.976"
|
||||
},
|
||||
"linux-ptb": {
|
||||
"hash": "sha256-vnzEamdX8pCzFtYLoWHvxcznHD1FCcgKnwQOx8BkWu0=",
|
||||
"url": "https://ptb.dl2.discordapp.net/apps/linux/0.0.183/discord-ptb-0.0.183.tar.gz",
|
||||
"version": "0.0.183"
|
||||
"distro": {
|
||||
"hash": "sha256-dVLGOL//a1mCw0NyekrCemfu9u7pA9t1+UnQ8zmMCwI=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/full.distro"
|
||||
},
|
||||
"kind": "distro",
|
||||
"modules": {
|
||||
"discord_cloudsync": {
|
||||
"hash": "sha256-cLqmwjFWUnRnBY3iEqpyv2mtuHI4TanGxbI1cT4V9Ic=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_cloudsync/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_desktop_core": {
|
||||
"hash": "sha256-UmAYyAVVwVZINIobQejXSEK01C/oQJBjxBQ1p45AMOg=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_desktop_core/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_dispatch": {
|
||||
"hash": "sha256-/WfqrWgqCXSUodMqlhgiHTQAiRSfg1dfA4c3CxKZuJk=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_dispatch/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_erlpack": {
|
||||
"hash": "sha256-MXBUoaeC1Refb80mqyZQ6vE8lRV04K5yZbhHMN5XuTY=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_erlpack/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_game_utils": {
|
||||
"hash": "sha256-P4s5/5aeLjzaD0HwHlpHCWaiVlsq+TFlfEqfCym4rH0=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_game_utils/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_krisp": {
|
||||
"hash": "sha256-hwLHumM78aJv/OSX1LAxqpUGZmiVWGg2Sc6SmOdg+Oc=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_krisp/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_modules": {
|
||||
"hash": "sha256-UGS9Znl5QWiQ5nG2I2GxUmQ3sRaaXcCyPPzh3AjAyQA=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_modules/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_rpc": {
|
||||
"hash": "sha256-izqFS9ePjv+4VTqrrnwdlNCdpQik5Y7D3pmznP74ULA=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_rpc/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_spellcheck": {
|
||||
"hash": "sha256-ykwur5DajvoAvNyhTb3wbtduv2NgLhrEEKKI2O/CqC8=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_spellcheck/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_utils": {
|
||||
"hash": "sha256-HKHbGqYK8AyJu+PnVaZIv+HJr6pc6LtnnXI29rSFPmI=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_utils/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_voice": {
|
||||
"hash": "sha256-HL/eZQpc0r+5N7LBFZdUVZWQT4nUtX3gBZlOPR1pLfs=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_voice/1/full.distro",
|
||||
"version": 1
|
||||
},
|
||||
"discord_zstd": {
|
||||
"hash": "sha256-P/8cVdak4Sz7SfHzi8DJPgZi9LRu6FWWI9hjoe8LY8o=",
|
||||
"url": "https://ptb.dl2.discordapp.net/distro/app/ptb/linux/x64/1.0.188/discord_zstd/1/full.distro",
|
||||
"version": 1
|
||||
}
|
||||
},
|
||||
"version": "1.0.188"
|
||||
},
|
||||
"linux-stable": {
|
||||
"hash": "sha256-FMIM/CWPk3Kcqp8iIg+gxiCpjD2DNk7dSBqnCBvzn5w=",
|
||||
"url": "https://stable.dl2.discordapp.net/apps/linux/0.0.130/discord-0.0.130.tar.gz",
|
||||
"version": "0.0.130"
|
||||
"hash": "sha256-N4gdcj8LYiXxvkbZhZyiWr375vaXt6JnwcoqLOKMsGg=",
|
||||
"kind": "legacy",
|
||||
"url": "https://stable.dl2.discordapp.net/apps/linux/0.0.134/discord-0.0.134.tar.gz",
|
||||
"version": "0.0.134"
|
||||
},
|
||||
"osx-canary": {
|
||||
"hash": "sha256-9bknJCpZv07BaF5v0g7t+YrGR3+HsYCHl4gjduQsABo=",
|
||||
"url": "https://canary.dl2.discordapp.net/apps/osx/0.0.1040/DiscordCanary.dmg",
|
||||
"version": "0.0.1040"
|
||||
"hash": "sha256-tR52aLUTW5iLzOQnXVS6muqsu44rXplHeXNKsR3u4Sw=",
|
||||
"kind": "legacy",
|
||||
"url": "https://canary.dl2.discordapp.net/apps/osx/0.0.1088/DiscordCanary.dmg",
|
||||
"version": "0.0.1088"
|
||||
},
|
||||
"osx-development": {
|
||||
"hash": "sha256-dCRl0gpxFdnEa81sSymj8Te0+KmmI9uXsmCXSY1EeNw=",
|
||||
"url": "https://development.dl2.discordapp.net/apps/osx/0.0.119/DiscordDevelopment.dmg",
|
||||
"version": "0.0.119"
|
||||
"hash": "sha256-gyZ2H9dsGYRlkPtRSE7hwRfFl6sr4pK2kB6Jq/51dhE=",
|
||||
"kind": "legacy",
|
||||
"url": "https://development.dl2.discordapp.net/apps/osx/1.0.982/DiscordDevelopment.dmg",
|
||||
"version": "1.0.982"
|
||||
},
|
||||
"osx-ptb": {
|
||||
"hash": "sha256-SV6ZdD0CCnNNkSWyIDqCmg9dpdQr4JLbrD3+k8943PQ=",
|
||||
"url": "https://ptb.dl2.discordapp.net/apps/osx/0.0.226/DiscordPTB.dmg",
|
||||
"version": "0.0.226"
|
||||
"hash": "sha256-WlygpcUv+CrmQdZyZ0t3EEb58oopHetbKQbKsLUdI1w=",
|
||||
"kind": "legacy",
|
||||
"url": "https://ptb.dl2.discordapp.net/apps/osx/0.0.231/DiscordPTB.dmg",
|
||||
"version": "0.0.231"
|
||||
},
|
||||
"osx-stable": {
|
||||
"hash": "sha256-vBadXUHrYhvkqzkCvGnKf25A19TKcFs5D0tzC54E0Hk=",
|
||||
"url": "https://stable.dl2.discordapp.net/apps/osx/0.0.382/Discord.dmg",
|
||||
"version": "0.0.382"
|
||||
"hash": "sha256-H+Odwt2Ry3C1+OMhVdr9PjAXOnI8vmsUkSBL8dieakc=",
|
||||
"kind": "legacy",
|
||||
"url": "https://stable.dl2.discordapp.net/apps/osx/0.0.387/Discord.dmg",
|
||||
"version": "0.0.387"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p python3
|
||||
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from enum import StrEnum
|
||||
from typing import List, Tuple
|
||||
from typing import List
|
||||
from subprocess import PIPE, Popen
|
||||
import json
|
||||
import urllib.request
|
||||
@@ -33,18 +34,35 @@ class Branch(StrEnum):
|
||||
DEVELOPMENT = "development"
|
||||
|
||||
|
||||
Variant = Tuple[Platform, Branch]
|
||||
class Kind(StrEnum):
|
||||
# Single tarball or dmg fetched via discord.com/api/download redirect
|
||||
LEGACY = "legacy"
|
||||
# Brotli-compressed host + module distros from the distributions API
|
||||
DISTRO = "distro"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Variant:
|
||||
platform: Platform
|
||||
branch: Branch
|
||||
kind: Kind
|
||||
|
||||
|
||||
# The distributions API rejects requests that don't send a Discord-Updater
|
||||
# User-Agent, so we can't identify ourselves as Nixpkgs here
|
||||
DISTRO_USER_AGENT = "Discord-Updater/1"
|
||||
|
||||
|
||||
def serialize_variant(variant: Variant) -> str:
|
||||
platform, branch = variant
|
||||
return f"{platform}-{branch}"
|
||||
return f"{variant.platform}-{variant.branch}"
|
||||
|
||||
|
||||
def url_for_variant(variant: Variant) -> str:
|
||||
platform, branch = variant
|
||||
return f"https://discord.com/api/download/{variant.branch.value}?platform={variant.platform.value}&format={variant.platform.format_type()}"
|
||||
|
||||
return f"https://discord.com/api/download/{branch.value}?platform={platform.value}&format={platform.format_type()}"
|
||||
|
||||
def distro_manifest_url_for_variant(variant: Variant) -> str:
|
||||
return f"https://updates.discord.com/distributions/app/manifests/latest?channel={variant.branch.value}&platform={variant.platform.value}&arch=x64"
|
||||
|
||||
|
||||
def fetch_redirect_url(url: str) -> str:
|
||||
@@ -75,31 +93,94 @@ def prefetch(url: str) -> str:
|
||||
return sri_hash
|
||||
|
||||
|
||||
@dataclass
|
||||
class LegacySource:
|
||||
version: str
|
||||
url: str
|
||||
hash: str
|
||||
kind: Kind = Kind.LEGACY
|
||||
|
||||
|
||||
@dataclass
|
||||
class DistroRef:
|
||||
url: str
|
||||
hash: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class DistroModule:
|
||||
version: int
|
||||
url: str
|
||||
hash: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class DistroSource:
|
||||
version: str
|
||||
distro: DistroRef
|
||||
modules: dict[str, DistroModule] = field(default_factory=dict)
|
||||
kind: Kind = Kind.DISTRO
|
||||
|
||||
|
||||
def fetch_distro_manifest(variant: Variant) -> dict:
|
||||
url = distro_manifest_url_for_variant(variant)
|
||||
req = urllib.request.Request(url, headers={"User-Agent": DISTRO_USER_AGENT})
|
||||
with urllib.request.urlopen(req) as response:
|
||||
return json.loads(response.read())
|
||||
|
||||
|
||||
def version_triple_to_str(triple: list) -> str:
|
||||
return ".".join(str(x) for x in triple)
|
||||
|
||||
|
||||
def fetch_distro_source(variant: Variant) -> DistroSource:
|
||||
manifest = fetch_distro_manifest(variant)
|
||||
|
||||
distro_url = manifest["full"]["url"]
|
||||
modules = {
|
||||
name: DistroModule(
|
||||
version=mod["full"]["module_version"],
|
||||
url=mod["full"]["url"],
|
||||
hash=prefetch(mod["full"]["url"]),
|
||||
)
|
||||
for name, mod in manifest["modules"].items()
|
||||
}
|
||||
|
||||
return DistroSource(
|
||||
version=version_triple_to_str(manifest["full"]["host_version"]),
|
||||
distro=DistroRef(url=distro_url, hash=prefetch(distro_url)),
|
||||
modules=modules,
|
||||
)
|
||||
|
||||
|
||||
def fetch_legacy_source(variant: Variant) -> LegacySource:
|
||||
url = fetch_redirect_url(url_for_variant(variant))
|
||||
return LegacySource(
|
||||
version=version_from_url(url),
|
||||
url=url,
|
||||
hash=prefetch(url),
|
||||
)
|
||||
|
||||
|
||||
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),
|
||||
Variant(Platform.LINUX, Branch.STABLE, Kind.LEGACY),
|
||||
Variant(Platform.LINUX, Branch.PTB, Kind.DISTRO),
|
||||
Variant(Platform.LINUX, Branch.CANARY, Kind.DISTRO),
|
||||
Variant(Platform.LINUX, Branch.DEVELOPMENT, Kind.DISTRO),
|
||||
Variant(Platform.MACOS, Branch.STABLE, Kind.LEGACY),
|
||||
Variant(Platform.MACOS, Branch.PTB, Kind.LEGACY),
|
||||
Variant(Platform.MACOS, Branch.CANARY, Kind.LEGACY),
|
||||
Variant(Platform.MACOS, Branch.DEVELOPMENT, Kind.LEGACY),
|
||||
]
|
||||
|
||||
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,
|
||||
}
|
||||
source = (
|
||||
fetch_distro_source(v) if v.kind == Kind.DISTRO else fetch_legacy_source(v)
|
||||
)
|
||||
sources[serialize_variant(v)] = asdict(source)
|
||||
|
||||
with open(os.path.join(os.path.dirname(__file__), "sources.json"), "w") as f:
|
||||
json.dump(sources, f, indent=2, sort_keys=True)
|
||||
|
||||
Reference in New Issue
Block a user