2021-02-09 12:59:11 +01:00
|
|
|
{ config, pkgs, lib, ... }:
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
|
|
|
|
let
|
|
|
|
cfg = config.programs.hexchat;
|
|
|
|
|
|
|
|
channelOptions = with types;
|
|
|
|
submodule {
|
|
|
|
options = {
|
|
|
|
autoconnect = mkOption {
|
|
|
|
type = nullOr bool;
|
|
|
|
default = false;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Autoconnect to network.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
connectToSelectedServerOnly = mkOption {
|
|
|
|
type = nullOr bool;
|
|
|
|
default = true;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Connect to selected server only.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
bypassProxy = mkOption {
|
|
|
|
type = nullOr bool;
|
|
|
|
default = true;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Bypass proxy.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
forceSSL = mkOption {
|
|
|
|
type = nullOr bool;
|
|
|
|
default = false;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Use SSL for all servers.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
acceptInvalidSSLCertificates = mkOption {
|
|
|
|
type = nullOr bool;
|
|
|
|
default = false;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Accept invalid SSL certificates.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
useGlobalUserInformation = mkOption {
|
|
|
|
type = nullOr bool;
|
|
|
|
default = false;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Use global user information.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
modChannelOption = with types;
|
|
|
|
submodule {
|
|
|
|
options = {
|
|
|
|
autojoin = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
|
|
|
example = [ "#home-manager" "#linux" "#nix" ];
|
2023-07-01 01:30:13 +02:00
|
|
|
description =
|
|
|
|
lib.mdDoc "Channels list to autojoin on connecting to server.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
charset = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
default = null;
|
|
|
|
example = "UTF-8 (Unicode)";
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Character set.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
commands = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
2021-10-25 02:59:22 +02:00
|
|
|
example = literalExpression ''[ "ECHO Greetings fellow Nixer! ]'';
|
2023-07-01 01:30:13 +02:00
|
|
|
description =
|
|
|
|
lib.mdDoc "Commands to be executed on connecting to server.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
loginMethod = mkOption {
|
|
|
|
type = nullOr (enum (attrNames loginMethodMap));
|
|
|
|
default = null;
|
2023-07-01 02:40:42 +02:00
|
|
|
description = lib.mdDoc ''
|
2021-02-09 12:59:11 +01:00
|
|
|
The login method. The allowed options are:
|
2023-07-01 02:40:42 +02:00
|
|
|
|
|
|
|
`null`
|
|
|
|
: Default
|
|
|
|
|
|
|
|
`"nickServMsg"`
|
|
|
|
: NickServ (`/MSG NickServ` + password)
|
|
|
|
|
|
|
|
`"nickServ"`
|
|
|
|
: NickServ (`/NICKSERV` + password)
|
|
|
|
|
|
|
|
`"challengeAuth"`
|
|
|
|
: Challenge Auth (username + password)
|
|
|
|
|
|
|
|
`"sasl"`
|
|
|
|
: SASL (username + password)
|
|
|
|
|
|
|
|
`"serverPassword"`
|
|
|
|
: Server password (`/PASS` password)
|
|
|
|
|
|
|
|
`"saslExternal"`
|
|
|
|
: SASL EXTERNAL (cert)
|
|
|
|
|
|
|
|
`"customCommands"`
|
|
|
|
: Use "commands" field for auth. For example
|
|
|
|
```nix
|
|
|
|
commands = [ "/msg NickServ IDENTIFY my_password" ]
|
|
|
|
```
|
2021-02-09 12:59:11 +01:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
nickname = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
default = null;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Primary nickname.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
nickname2 = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
default = null;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Secondary nickname.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
options = mkOption {
|
|
|
|
type = nullOr channelOptions;
|
|
|
|
default = null;
|
|
|
|
example = {
|
|
|
|
autoconnect = true;
|
|
|
|
useGlobalUserInformation = true;
|
|
|
|
};
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Channel options.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
password = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
default = null;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2021-02-09 12:59:11 +01:00
|
|
|
Password to use. Note this password will be readable by all user's
|
|
|
|
in the Nix store.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
realName = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
default = null;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2021-02-09 12:59:11 +01:00
|
|
|
Real name. Is used to populate the real name field that appears when
|
2023-07-01 01:30:13 +02:00
|
|
|
someone uses the `WHOIS` command on your nick.
|
2021-02-09 12:59:11 +01:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
userName = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
default = null;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
|
|
|
User name. Part of your `user@host` hostmask that
|
2021-02-09 12:59:11 +01:00
|
|
|
appears to other on IRC.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
servers = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
2022-12-03 05:20:00 +01:00
|
|
|
example = [ "irc.oftc.net" ];
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "IRC Server Address List.";
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
transformField = k: v: if (v != null) then "${k}=${v}" else null;
|
|
|
|
|
|
|
|
listChar = c: l:
|
|
|
|
if l != [ ] then concatMapStringsSep "\n" (transformField c) l else null;
|
|
|
|
|
|
|
|
computeFieldsValue = channel:
|
|
|
|
let
|
|
|
|
ifTrue = p: n: if p then n else 0;
|
|
|
|
result = with channel.options;
|
|
|
|
foldl' (a: b: a + b) 0 [
|
|
|
|
(ifTrue (!connectToSelectedServerOnly) 1)
|
|
|
|
(ifTrue useGlobalUserInformation 2)
|
|
|
|
(ifTrue forceSSL 4)
|
|
|
|
(ifTrue autoconnect 8)
|
|
|
|
(ifTrue (!bypassProxy) 16)
|
|
|
|
(ifTrue acceptInvalidSSLCertificates 32)
|
|
|
|
];
|
|
|
|
in toString (if channel.options == null then 0 else result);
|
|
|
|
|
|
|
|
loginMethodMap = {
|
|
|
|
nickServMsg = 1;
|
|
|
|
nickServ = 2;
|
|
|
|
challengeAuth = 4;
|
|
|
|
sasl = 6;
|
|
|
|
serverPassword = 7;
|
|
|
|
customCommands = 9;
|
|
|
|
saslExternal = 10;
|
|
|
|
};
|
|
|
|
|
|
|
|
loginMethod = channel:
|
|
|
|
transformField "L" (optionalString (channel.loginMethod != null)
|
|
|
|
(toString loginMethodMap.${channel.loginMethod}));
|
|
|
|
|
|
|
|
# Note: Missing option `D=`.
|
|
|
|
transformChannel = channelName:
|
|
|
|
let channel = cfg.channels.${channelName};
|
2021-12-27 09:03:18 +01:00
|
|
|
in concatStringsSep "\n" (remove null [
|
2021-02-09 12:59:11 +01:00
|
|
|
"" # leave a space between one server and another
|
|
|
|
(transformField "N" channelName)
|
|
|
|
(loginMethod channel)
|
|
|
|
(transformField "E" channel.charset)
|
|
|
|
(transformField "F" (computeFieldsValue channel))
|
|
|
|
(transformField "I" channel.nickname)
|
|
|
|
(transformField "i" channel.nickname2)
|
|
|
|
(transformField "R" channel.realName)
|
|
|
|
(transformField "U" channel.userName)
|
|
|
|
(transformField "P" channel.password)
|
|
|
|
(listChar "S" channel.servers)
|
|
|
|
(listChar "J" channel.autojoin)
|
|
|
|
(listChar "C" channel.commands)
|
|
|
|
]);
|
|
|
|
|
|
|
|
in {
|
2021-12-25 19:28:14 +01:00
|
|
|
meta.maintainers = with maintainers; [ thiagokokada ];
|
2021-02-09 12:59:11 +01:00
|
|
|
|
|
|
|
options.programs.hexchat = with types; {
|
2023-07-01 01:30:13 +02:00
|
|
|
enable = mkEnableOption (lib.mdDoc "HexChat, a graphical IRC client");
|
2021-02-09 12:59:11 +01:00
|
|
|
|
|
|
|
channels = mkOption {
|
|
|
|
type = attrsOf modChannelOption;
|
|
|
|
default = { };
|
2021-10-25 02:59:22 +02:00
|
|
|
example = literalExpression ''
|
2021-02-09 12:59:11 +01:00
|
|
|
{
|
2022-12-03 05:20:00 +01:00
|
|
|
oftc = {
|
2021-02-09 12:59:11 +01:00
|
|
|
autojoin = [
|
|
|
|
"#home-manager"
|
|
|
|
"#linux"
|
|
|
|
];
|
|
|
|
charset = "UTF-8 (Unicode)";
|
|
|
|
commands = [
|
|
|
|
"ECHO Buzz Lightyear sent you a message: 'To Infinity... and Beyond!'"
|
|
|
|
];
|
|
|
|
loginMethod = sasl;
|
|
|
|
nickname = "my_nickname";
|
|
|
|
nickname2 = "my_secondchoice";
|
|
|
|
options = {
|
|
|
|
acceptInvalidSSLCertificates = false;
|
|
|
|
autoconnect = true;
|
|
|
|
bypassProxy = true;
|
|
|
|
connectToSelectedServerOnly = true;
|
|
|
|
useGlobalUserInformation = false;
|
|
|
|
forceSSL = false;
|
|
|
|
};
|
|
|
|
password = "my_password";
|
|
|
|
realName = "my_realname";
|
|
|
|
servers = [
|
2022-12-03 05:20:00 +01:00
|
|
|
"irc.oftc.net"
|
2021-02-09 12:59:11 +01:00
|
|
|
];
|
|
|
|
userName = "my_username";
|
|
|
|
};
|
|
|
|
}'';
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
|
|
|
Configures {file}`$XDG_CONFIG_HOME/hexchat/servlist.conf`.
|
2021-02-09 12:59:11 +01:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
settings = mkOption {
|
|
|
|
default = null;
|
|
|
|
type = nullOr (attrsOf str);
|
2021-10-25 02:59:22 +02:00
|
|
|
example = literalExpression ''
|
2021-02-09 12:59:11 +01:00
|
|
|
{
|
|
|
|
irc_nick1 = "mynick";
|
|
|
|
irc_username = "bob";
|
|
|
|
irc_realname = "Bart Simpson";
|
|
|
|
text_font = "Monospace 14";
|
|
|
|
};
|
|
|
|
'';
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
|
|
|
Configuration for {file}`$XDG_CONFIG_HOME/hexchat/hexchat.conf`, see
|
|
|
|
<https://hexchat.readthedocs.io/en/latest/settings.html#list-of-settings>
|
2021-02-09 12:59:11 +01:00
|
|
|
for supported values.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
overwriteConfigFiles = mkOption {
|
|
|
|
type = nullOr bool;
|
|
|
|
default = false;
|
2023-07-01 02:40:42 +02:00
|
|
|
description = lib.mdDoc ''
|
2021-02-09 12:59:11 +01:00
|
|
|
Enables overwriting HexChat configuration files
|
2023-07-01 02:40:42 +02:00
|
|
|
({file}`hexchat.conf`, {file}`servlist.conf`).
|
|
|
|
Any existing HexChat configuration will be lost. Make sure to back up
|
|
|
|
any previous configuration before enabling this.
|
|
|
|
|
2021-02-09 12:59:11 +01:00
|
|
|
Enabling this setting is recommended, because everytime HexChat
|
|
|
|
application is closed it overwrites Nix/Home Manager provided
|
|
|
|
configuration files, causing:
|
2023-07-01 02:40:42 +02:00
|
|
|
|
|
|
|
1. Nix/Home Manager provided configuration to be out of sync with
|
|
|
|
actual active HexChat configuration.
|
|
|
|
2. Nix/Home Manager updates to be blocked until configuration files are
|
|
|
|
manually removed.
|
2021-02-09 12:59:11 +01:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
theme = mkOption {
|
|
|
|
type = nullOr package;
|
|
|
|
default = null;
|
2021-10-25 02:59:22 +02:00
|
|
|
example = literalExpression ''
|
2021-10-29 06:44:27 +02:00
|
|
|
source = pkgs.fetchzip {
|
|
|
|
url = "https://dl.hexchat.net/themes/Monokai.hct#Monokai.zip";
|
|
|
|
sha256 = "sha256-WCdgEr8PwKSZvBMs0fN7E2gOjNM0c2DscZGSKSmdID0=";
|
|
|
|
stripRoot = false;
|
2021-02-09 12:59:11 +01:00
|
|
|
};
|
|
|
|
'';
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2021-02-09 12:59:11 +01:00
|
|
|
Theme package for HexChat. Expects a derivation containing decompressed
|
2023-07-01 01:30:13 +02:00
|
|
|
theme files. Note, `.hct` files are actually ZIP files,
|
2021-10-29 06:44:27 +02:00
|
|
|
as seen in example.
|
2021-02-09 12:59:11 +01:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
assertions = [
|
|
|
|
(hm.assertions.assertPlatform "programs.hexchat" pkgs platforms.linux)
|
|
|
|
];
|
|
|
|
|
|
|
|
home.packages = [ pkgs.hexchat ];
|
|
|
|
|
|
|
|
xdg.configFile."hexchat" = mkIf (cfg.theme != null) {
|
|
|
|
source = cfg.theme;
|
|
|
|
recursive = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
xdg.configFile."hexchat/hexchat.conf" = mkIf (cfg.settings != null) {
|
|
|
|
force = cfg.overwriteConfigFiles;
|
|
|
|
text = concatMapStringsSep "\n" (x: x + " = " + cfg.settings.${x})
|
|
|
|
(attrNames cfg.settings);
|
|
|
|
};
|
|
|
|
|
|
|
|
xdg.configFile."hexchat/servlist.conf" = mkIf (cfg.channels != { }) {
|
|
|
|
force = cfg.overwriteConfigFiles;
|
|
|
|
# Final line breaks is required to avoid cropping last field value.
|
|
|
|
text = concatMapStringsSep "\n" transformChannel (attrNames cfg.channels)
|
|
|
|
+ "\n\n";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|