Advertisement
Guest User

Untitled

a guest
Oct 28th, 2024
40
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.63 KB | None | 0 0
  1. {
  2. config,
  3. lib,
  4. pkgs,
  5. ...
  6. }:
  7. let
  8. cfg = config.programs.nixcord;
  9.  
  10. inherit (lib)
  11. mkEnableOption
  12. mkOption
  13. types
  14. mkIf
  15. mkMerge
  16. attrsets
  17. lists
  18. ;
  19.  
  20. dop = with types; coercedTo package (a: a.outPath) pathInStore;
  21.  
  22. # Define regular expressions for GitHub and Git URLs
  23. regexGithub = "github:([[:alnum:].-]+)/([[:alnum:]/-]+)/([0-9a-f]{40})";
  24. regexGit = "git[+]file:///([^/]+/)*([^/?]+)(\\?ref=[a-f0-9]{40})?$";
  25.  
  26. # Define coercion functions for GitHub and Git
  27. coerceGithub = value: let
  28. matches = builtins.match regexGithub value;
  29. owner = builtins.elemAt matches 0;
  30. repo = builtins.elemAt matches 1;
  31. rev = builtins.elemAt matches 2;
  32. in builtins.fetchGit {
  33. url = "https://github.com/${owner}/${repo}";
  34. inherit rev;
  35. };
  36.  
  37. coerceGit = value: let
  38. # Match using regex, assuming regexGit is defined and captures groups correctly
  39. matches = builtins.match regexGit value;
  40.  
  41. # Set rev only if matches are found
  42. rev = if matches != null then
  43. let
  44. rawRev = builtins.elemAt matches 2;
  45. in
  46. if rawRev != null && builtins.substring 0 5 rawRev == "?ref="
  47. then builtins.substring 5 (builtins.stringLength rawRev) rawRev
  48. else null
  49. else null;
  50.  
  51. # Set filepath only if matches are found
  52. filepath = if matches != null then
  53. let
  54. startOffset = 4; # Remove 4 characters from the beginning
  55. endOffset = 45; # Remove 45 characters from the end
  56. fullLength = builtins.stringLength value;
  57. adjustedPathLength = fullLength - startOffset - endOffset;
  58. in
  59. builtins.substring startOffset adjustedPathLength value
  60. else null;
  61.  
  62. in if filepath != null then
  63. # Call fetchGit only if filepath is valid
  64. builtins.fetchGit (
  65. let
  66. # Only include rev if it's non-null and non-empty
  67. revCondition = if rev != null && rev != "" then { rev = rev; } else {};
  68. in {
  69. url = filepath;
  70. ref = "main";
  71. # Use revCondition directly without trying to inherit rev
  72. # This will prevent the missing rev error
  73. # If revCondition is empty, it won't add the rev key
  74. } // revCondition # Combine the base attributes with revCondition
  75. )
  76. else
  77. throw "Failed to extract a valid filepath from the given value";
  78. #in coerceGit
  79.  
  80.  
  81. # Mapper function that applies coercion based on the regex match
  82. pluginMapper = plugin:
  83. if builtins.match regexGithub plugin != null then
  84. coerceGithub plugin
  85. else if builtins.match regexGit plugin != null then
  86. coerceGit plugin
  87. else
  88. plugin; # Leave it as-is if it's already a package or path
  89.  
  90.  
  91. recursiveUpdateAttrsList = list:
  92. if (builtins.length list <= 1) then (builtins.elemAt list 0) else
  93. recursiveUpdateAttrsList ([
  94. (attrsets.recursiveUpdate (builtins.elemAt list 0) (builtins.elemAt list 1))
  95. ] ++ (lists.drop 2 list));
  96.  
  97. pluginDerivations = lib.mapAttrs (_: plugin: pluginMapper plugin) cfg.userPlugins;
  98.  
  99. #pluginOutputs = lib.attrValues pluginDerivations;
  100.  
  101. userPluginsDirectory = pkgs.linkFarm "userPlugins" pluginDerivations;
  102. #userPluginsDirectory = lib.traceSeqN 1 (builtins.toString pluginDerivations) pkgs.linkFarm "userPlugins" pluginDerivations;
  103. #userPluginsDirectory = let
  104. # debugInfo = lib.concatMapStringsSep "\n" (name:
  105. # "${name}: ${builtins.toJSON (pluginDerivations.${name})}"
  106. # ) (lib.attrNames pluginDerivations);
  107. #in lib.traceSeqN 1 debugInfo pkgs.linkFarm "userPlugins" pluginDerivations;
  108.  
  109. # "userPlugins" {
  110. # inherit pluginOutputs;
  111. # name = "user-plugins";
  112. #};
  113. # userPluginsDirectory = pkgs.runCommand "user-plugins-directory" { } ''
  114. # mkdir -p $out
  115. # for plugin in ${lib.concatStringsSep " " (lib.attrNames config.userPlugins)}; do
  116. # plugin_value=${config.userPlugins.${plugin}}
  117. # pluginMapper "${plugin_value}" > $out/${plugin}
  118. # done
  119. #'';
  120.  
  121. in {
  122. options.programs.nixcord = {
  123. enable = mkEnableOption "Enables Discord with Vencord";
  124. discord = {
  125. enable = mkOption {
  126. type = types.bool;
  127. default = true;
  128. description = ''
  129. Whether to enable discord
  130. Disable to only install Vesktop
  131. '';
  132. };
  133. package = mkOption {
  134. type = types.package;
  135. default = pkgs.discord;
  136. description = ''
  137. The Discord package to use
  138. '';
  139. };
  140. configDir = mkOption {
  141. type = types.path;
  142. default = "${if pkgs.stdenvNoCC.isLinux then config.xdg.configHome else "${config.home.homeDirectory}/Library/Application Support"}/discord";
  143. description = "Config path for Discord";
  144. };
  145. vencord.enable = mkOption {
  146. type = types.bool;
  147. default = true;
  148. description = "Enable Vencord (for non-vesktop)";
  149. };
  150. openASAR.enable = mkOption {
  151. type = types.bool;
  152. default = true;
  153. description = "Enable OpenASAR (for non-vesktop)";
  154. };
  155. settings = mkOption {
  156. type = types.attrs;
  157. default = {};
  158. description = ''
  159. Settings to be placed in discordConfigDir/settings.json
  160. '';
  161. };
  162. };
  163. vesktop = {
  164. enable = mkEnableOption ''
  165. Whether to enable Vesktop
  166. '';
  167. package = mkOption {
  168. type = types.package;
  169. default = pkgs.vesktop;
  170. description = ''
  171. The Vesktop package to use
  172. '';
  173. };
  174. configDir = mkOption {
  175. type = types.path;
  176. default = "${if pkgs.stdenvNoCC.isLinux then config.xdg.configHome else "${config.home.homeDirectory}/Library/Application Support"}/vesktop";
  177. description = "Config path for Vesktop";
  178. };
  179. settings = mkOption {
  180. type = types.attrs;
  181. default = {};
  182. description = ''
  183. Settings to be placed in vesktop.configDir/settings.json
  184. '';
  185. };
  186. state = mkOption {
  187. type = types.attrs;
  188. default = {};
  189. description = ''
  190. Settings to be placed in vesktop.configDir/state.json
  191. '';
  192. };
  193. };
  194. package = mkOption {
  195. type = with types; nullOr package;
  196. default = null;
  197. description = ''
  198. Deprecated
  199. The Discord package to use
  200. '';
  201. };
  202. vesktopPackage = mkOption {
  203. type = with types; nullOr package;
  204. default = null;
  205. description = ''
  206. The Vesktop package to use
  207. '';
  208. };
  209. configDir = mkOption {
  210. type = types.path;
  211. default = "${if pkgs.stdenvNoCC.isLinux then config.xdg.configHome else "${config.home.homeDirectory}/Library/Application Support"}/Vencord";
  212. description = "Vencord config directory";
  213. };
  214. vesktopConfigDir = mkOption {
  215. type = with types; nullOr path;
  216. default = null;
  217. description = "Config path for Vesktop";
  218. };
  219. vencord.enable = mkOption {
  220. type = with types; nullOr bool;
  221. default = null;
  222. description = "Enable Vencord (for non-vesktop)";
  223. };
  224. openASAR.enable = mkOption {
  225. type = with types; nullOr bool;
  226. default = null;
  227. description = "Enable OpenASAR (for non-vesktop)";
  228. };
  229. quickCss = mkOption {
  230. type = types.str;
  231. default = "";
  232. description = "Vencord quick CSS";
  233. };
  234. config = {
  235. notifyAboutUpdates = mkEnableOption "Notify when updates are available";
  236. autoUpdate = mkEnableOption "Automaticall update Vencord";
  237. autoUpdateNotification = mkEnableOption "Notify user about auto updates";
  238. useQuickCss = mkEnableOption "Enable quick CSS file";
  239. themeLinks = mkOption {
  240. type = with types; listOf str;
  241. default = [ ];
  242. description = "A list of links to online vencord themes";
  243. example = [ "https://raw.githubusercontent.com/rose-pine/discord/main/rose-pine.theme.css" ];
  244. };
  245. enabledThemes = mkOption {
  246. type = with types; listOf str;
  247. default = [ ];
  248. description = "A list of themes to enable from themes directory";
  249. };
  250. enableReactDevtools = mkEnableOption "Enable React developer tools";
  251. frameless = mkEnableOption "Make client frameless";
  252. transparent = mkEnableOption "Enable client transparency";
  253. disableMinSize = mkEnableOption "Disable minimum window size for client";
  254. plugins = import ./plugins.nix { inherit lib; };
  255. };
  256. vesktopConfig = mkOption {
  257. type = types.attrs;
  258. default = {};
  259. description = ''
  260. additional config to be added to programs.nixcord.config
  261. for vesktop only
  262. '';
  263. };
  264. vencordConfig = mkOption {
  265. type = types.attrs;
  266. default = {};
  267. description = ''
  268. additional config to be added to programs.nixcord.config
  269. for vencord only
  270. '';
  271. };
  272. extraConfig = mkOption {
  273. type = types.attrs;
  274. default = {};
  275. description = ''
  276. additional config to be added to programs.nixcord.config
  277. for both vencord and vesktop
  278. '';
  279. };
  280. userPlugins = lib.mkOption {
  281. description = "User plugin to fetch and install. Note that any JSON required must be enabled in extraConfig.";
  282.  
  283. # Define the type of userPlugins with validation
  284. type = types.attrsOf (types.oneOf [
  285. (types.strMatching regexGithub) # GitHub URL pattern
  286. (types.strMatching regexGit) # Git URL pattern
  287. types.package # Nix packages
  288. types.path # Nix paths
  289. ]);
  290.  
  291. # Set default values by mapping the userPlugins with the pluginMapper
  292. #default = lib.mapAttrs (_: plugin: pluginMapper plugin) cfg.userPlugins;
  293.  
  294. # Example usage of the userPlugins option
  295. example = {
  296. someCoolPlugin = "github:someUser/someCoolPlugin/someHashHere"; # GitHub example
  297. anotherCoolPlugin = "git+file:///path/to/repo?rev=abcdef1234567890abcdef1234567890abcdef12"; # File path example
  298. };
  299. };
  300.  
  301. parseRules = {
  302. upperNames = mkOption {
  303. type = with types; listOf str;
  304. description = "option names to become UPPER_SNAKE_CASE";
  305. default = [];
  306. };
  307. lowerPluginTitles = mkOption {
  308. type = with types; listOf str;
  309. description = "plugins with lowercase names in json";
  310. default = [];
  311. example = [ "petpet" ];
  312. };
  313. fakeEnums = {
  314. zero = mkOption {
  315. type = with types; listOf str;
  316. description = "strings to evaluate to 0 in JSON";
  317. default = [];
  318. };
  319. one = mkOption {
  320. type = with types; listOf str;
  321. description = "strings to evaluate to 1 in JSON";
  322. default = [];
  323. };
  324. two = mkOption {
  325. type = with types; listOf str;
  326. description = "strings to evaluate to 2 in JSON";
  327. default = [];
  328. };
  329. three = mkOption {
  330. type = with types; listOf str;
  331. description = "strings to evaluate to 3 in JSON";
  332. default = [];
  333. };
  334. four = mkOption {
  335. type = with types; listOf str;
  336. description = "string to evalueate to 4 in JSON";
  337. default = [];
  338. };
  339. # I've never seen a plugin with more than 5 options for 1 setting
  340. };
  341. };
  342. };
  343.  
  344. config = let
  345. parseRules = cfg.parseRules;
  346. inherit (pkgs.callPackage ./lib.nix { inherit lib parseRules; })
  347. mkVencordCfg;
  348. #srcOutPath
  349. vencordPkgs = pkgs.callPackage ./vencord.nix {
  350. inherit (pkgs)
  351. curl
  352. esbuild
  353. fetchFromGitHub
  354. git
  355. jq
  356. lib
  357. nix-update
  358. nodejs
  359. pnpm
  360. stdenv
  361. writeShellScript
  362. ;
  363. buildWebExtension = false;
  364. };
  365.  
  366. applyPostPatch = pkg: lib.trace "Applying overrideAttrs to package: ${pkg.src}" (
  367. pkg.overrideAttrs (oldAttrs: {
  368. postPatch = ''
  369. echo "Current build directory (PWD): $(pwd)"
  370. ln -s ${lib.escapeShellArg userPluginsDirectory} src/userplugins
  371. '';
  372. })
  373. );
  374.  
  375. # nixpkgs is always really far behind
  376. # so instead we maintain our own vencord package
  377.  
  378. # Custom trace function to log outPath only
  379. traceOutPath = drv: lib.debug.traceVal (drv.outPath);
  380.  
  381. # Apply post-patch and trace only the outPath
  382. vencord = traceOutPath (applyPostPatch vencordPkgs);
  383.  
  384. isQuickCssUsed = appConfig: (cfg.config.useQuickCss || appConfig ? "useQuickCss" && appConfig.useQuickCss) && cfg.quickCss != "";
  385. in mkIf cfg.enable (mkMerge [
  386. {
  387. home.packages = [
  388. (mkIf cfg.discord.enable (cfg.discord.package.override {
  389. withVencord = cfg.discord.vencord.enable;
  390. withOpenASAR = cfg.discord.openASAR.enable;
  391. inherit vencord;
  392. }))
  393. (mkIf cfg.vesktop.enable (cfg.vesktop.package.override {
  394. withSystemVencord = true;
  395. inherit vencord;
  396. }))
  397. ];
  398. }
  399. (mkIf cfg.discord.enable (mkMerge [
  400. # QuickCSS
  401. (mkIf (isQuickCssUsed cfg.vencordConfig) {
  402. home.file."${cfg.configDir}/settings/quickCss.css".text = cfg.quickCss;
  403. })
  404. # Vencord Settings
  405. {
  406. home.file."${cfg.configDir}/settings/settings.json".text =
  407. builtins.toJSON (mkVencordCfg (
  408. recursiveUpdateAttrsList [ cfg.config cfg.extraConfig cfg.vencordConfig ]
  409. ));
  410. }
  411. # Client Settings
  412. (mkIf (cfg.discord.settings != {}) {
  413. home.file."${cfg.discord.configDir}/settings.json".text =
  414. builtins.toJSON mkVencordCfg cfg.discord.settings;
  415. })
  416. ]))
  417. (mkIf cfg.vesktop.enable (mkMerge [
  418. # QuickCSS
  419. (mkIf (isQuickCssUsed cfg.vesktopConfig) {
  420. home.file."${cfg.vesktop.configDir}/settings/quickCss.css".text = cfg.quickCss;
  421. })
  422. # Vencord Settings
  423. {
  424. home.file."${cfg.vesktop.configDir}/settings/settings.json".text =
  425. builtins.toJSON (mkVencordCfg (
  426. recursiveUpdateAttrsList [ cfg.config cfg.extraConfig cfg.vesktopConfig ]
  427. ));
  428. }
  429. # Vesktop Client Settings
  430. (mkIf (cfg.vesktop.settings != {}) {
  431. home.file."${cfg.vesktop.configDir}/settings.json".text =
  432. builtins.toJSON mkVencordCfg cfg.vesktopSettings;
  433. })
  434. # Vesktop Client State
  435. (mkIf (cfg.vesktop.state != {}) {
  436. home.file."${cfg.vesktop.configDir}/state.json".text =
  437. builtins.toJSON mkVencordCfg cfg.vesktopState;
  438. })
  439. ]))
  440. # Warnings
  441. {
  442. warnings = import ./warnings.nix { inherit cfg mkIf; };
  443. }
  444. ]);
  445. }
  446.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement