1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-03-31 04:04:32 +00:00

streamlink: init module

Streamlink is a CLI utility which pipes video streams from various
services into a video player.
This commit is contained in:
Hoang Nguyen 2024-11-03 00:00:00 +07:00
parent 1efd250317
commit c39110a782
No known key found for this signature in database
GPG key ID: 14F4F683E34C7DDD
9 changed files with 292 additions and 0 deletions

View file

@ -2180,6 +2180,16 @@ in {
scrobbler (e.g. last.fm)
'';
}
{
time = "2025-03-29T04:16:57+00:00";
message = ''
A new module is available: 'programs.streamlink'.
Streamlink is a CLI utility which pipes video streams from various
services into a video player.
'';
}
];
};
}

View file

@ -245,6 +245,7 @@ let
./programs/sqls.nix
./programs/ssh.nix
./programs/starship.nix
./programs/streamlink.nix
./programs/swayimg.nix
./programs/swaylock.nix
./programs/swayr.nix

View file

@ -0,0 +1,189 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.streamlink;
renderSettings =
settings:
lib.concatLines (
lib.remove "" (
lib.mapAttrsToList (
name: value:
if (builtins.isBool value) then
if value then name else ""
else if (builtins.isList value) then
lib.concatStringsSep "\n" (builtins.map (item: "${name}=${builtins.toString item}") value)
else
"${name}=${builtins.toString value}"
) settings
)
);
pluginType = lib.types.submodule {
options = {
src = lib.mkOption {
type = with lib.types; nullOr (either path lines);
default = null;
description = ''
Source of the custom plugin. The value should be a path to the
plugin file, or the text of the plugin code. Will be linked to
{file}`$XDG_DATA_HOME/streamlink/plugins/<name>.py` (linux) or
{file}`Library/Application Support/streamlink/plugins/<name>.py` (darwin).
'';
example = lib.literalExpression "./custom_plugin.py";
};
settings = lib.mkOption {
type =
with lib.types;
attrsOf (oneOf [
bool
int
float
str
(listOf (oneOf [
int
float
str
]))
]);
default = { };
example = lib.literalExpression ''
{
quiet = true;
}
'';
description = ''
Configuration for the specific plugin, written to
{file}`$XDG_CONFIG_HOME/streamlink/config.<name>` (linux) or
{file}`Library/Application Support/streamlink/config.<name>` (darwin).
'';
};
};
};
in
{
meta.maintainers = [ lib.hm.maintainers.folliehiyuki ];
options.programs.streamlink = {
enable = lib.mkEnableOption "streamlink";
package = lib.mkPackageOption pkgs "streamlink" { nullable = true; };
settings = lib.mkOption {
type =
with lib.types;
attrsOf (oneOf [
bool
int
float
str
(listOf (oneOf [
int
float
str
]))
]);
default = { };
example = lib.literalExpression ''
{
player = "''${pkgs.mpv}/bin/mpv";
player-args = "--cache 2048";
player-no-close = true;
}
'';
description = ''
Global configuration options for streamlink. It will be written to
{file}`$XDG_CONFIG_HOME/streamlink/config` (linux) or
{file}`Library/Application Support/streamlink/config` (darwin).
'';
};
plugins = lib.mkOption {
description = ''
Streamlink plugins.
If a source is set, the custom plugin will be linked to the data directory.
Additional configuration specific to the plugin, if defined, will be
written to the config directory, and override global settings.
'';
type = lib.types.attrsOf pluginType;
default = { };
example = lib.literalExpression ''
{
custom_plugin = {
src = ./custom_plugin.py;
settings = {
quiet = true;
};
};
}
'';
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{ home.packages = lib.mkIf (cfg.package != null) [ cfg.package ]; }
(lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
xdg.configFile =
{
"streamlink/config" = lib.mkIf (cfg.settings != { }) {
text = renderSettings cfg.settings;
};
}
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "streamlink/config.${name}" (
lib.mkIf (value.settings != { }) {
text = renderSettings value.settings;
}
)
) cfg.plugins);
xdg.dataFile = lib.mapAttrs' (
name: value:
lib.nameValuePair "streamlink/plugins/${name}.py" (
lib.mkIf (value.src != null) (
if (builtins.isPath value.src) then { source = value.src; } else { text = value.src; }
)
)
) cfg.plugins;
})
(lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
home.file =
{
"Library/Application Support/streamlink/config" = lib.mkIf (cfg.settings != { }) {
text = renderSettings cfg.settings;
};
}
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "Library/Application Support/streamlink/config.${name}" (
lib.mkIf (value.settings != { }) {
text = renderSettings value.settings;
}
)
) cfg.plugins)
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "Library/Application Support/streamlink/plugins/${name}.py" (
lib.mkIf (value.src != null) (
if (builtins.isPath value.src) then { source = value.src; } else { text = value.src; }
)
)
) cfg.plugins);
})
]
);
}

View file

@ -392,6 +392,7 @@ in import nmtSrc {
./modules/programs/spotify-player
./modules/programs/ssh
./modules/programs/starship
./modules/programs/streamlink
./modules/programs/taskwarrior
./modules/programs/tealdeer
./modules/programs/tex-fmt

View file

@ -0,0 +1,5 @@
http-header=User-Agent=Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0
http-header=Accept-Language=en-US
player=mpv
player-args=--cache 2048
player-no-close

View file

@ -0,0 +1,4 @@
{
streamlink-settings = ./streamlink-settings.nix;
streamlink-custom-plugins = ./streamlink-custom-plugins.nix;
}

View file

@ -0,0 +1,9 @@
"""
$description Dummy plugin for testing
"""
from streamlink.plugin import Plugin
class DummyTV(Plugin):
__plugin__ = DummyTV

View file

@ -0,0 +1,45 @@
{ pkgs, ... }:
{
programs.streamlink = {
enable = true;
plugins = {
dummy.src = ./dummy.py;
dummy2.src = builtins.readFile ./dummy.py;
twitch.settings = {
player = "haruna";
quiet = true;
};
};
};
test.stubs.streamlink = { };
nmt.script = let
configDir = if pkgs.stdenv.isDarwin then
"Library/Application Support/streamlink"
else
".config/streamlink";
pluginDir = if pkgs.stdenv.isDarwin then
"Library/Application Support/streamlink/plugins"
else
".local/share/streamlink/plugins";
in ''
assertFileExists home-files/${configDir}/config.twitch
assertFileContent home-files/${configDir}/config.twitch ${
pkgs.writeText "expected" ''
player=haruna
quiet
''
}
assertFileExists home-files/${pluginDir}/dummy.py
assertFileContent home-files/${pluginDir}/dummy.py ${./dummy.py}
assertFileExists home-files/${pluginDir}/dummy2.py
assertFileContent home-files/${pluginDir}/dummy2.py ${./dummy.py}
'';
}

View file

@ -0,0 +1,28 @@
{ pkgs, ... }:
{
programs.streamlink = {
enable = true;
settings = {
player = "mpv";
player-args = "--cache 2048";
player-no-close = true;
http-header = [
"User-Agent=Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0"
"Accept-Language=en-US"
];
};
};
test.stubs.streamlink = { };
nmt.script = let
streamlinkConfig = if pkgs.stdenv.hostPlatform.isDarwin then
"Library/Application Support/streamlink/config"
else
".config/streamlink/config";
in ''
assertFileExists home-files/${streamlinkConfig}
assertFileContent home-files/${streamlinkConfig} ${./config}
'';
}