Merge pull request #196488 from SuperSandro2000/changedetectionio
This commit is contained in:
commit
89e49d87d3
|
@ -1072,6 +1072,7 @@
|
||||||
./services/web-apps/calibre-web.nix
|
./services/web-apps/calibre-web.nix
|
||||||
./services/web-apps/code-server.nix
|
./services/web-apps/code-server.nix
|
||||||
./services/web-apps/baget.nix
|
./services/web-apps/baget.nix
|
||||||
|
./services/web-apps/changedetection-io.nix
|
||||||
./services/web-apps/convos.nix
|
./services/web-apps/convos.nix
|
||||||
./services/web-apps/dex.nix
|
./services/web-apps/dex.nix
|
||||||
./services/web-apps/discourse.nix
|
./services/web-apps/discourse.nix
|
||||||
|
|
218
nixos/modules/services/web-apps/changedetection-io.nix
Normal file
218
nixos/modules/services/web-apps/changedetection-io.nix
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.changedetection-io;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.changedetection-io = {
|
||||||
|
enable = mkEnableOption (lib.mdDoc "changedetection-io");
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
default = "changedetection-io";
|
||||||
|
type = types.str;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
User account under which changedetection-io runs.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
default = "changedetection-io";
|
||||||
|
type = types.str;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Group account under which changedetection-io runs.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
listenAddress = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "localhost";
|
||||||
|
description = lib.mdDoc "Address the server will listen on.";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 5000;
|
||||||
|
description = lib.mdDoc "Port the server will listen on.";
|
||||||
|
};
|
||||||
|
|
||||||
|
datastorePath = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "/var/lib/changedetection-io";
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
The directory used to store all data for changedetection-io.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
baseURL = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
example = "https://changedetection-io.example";
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
The base url used in notifications and `{base_url}` token.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
behindProxy = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Enable this option when changedetection-io runs behind a reverse proxy, so that it trusts X-* headers.
|
||||||
|
It is recommend to run changedetection-io behind a TLS reverse proxy.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
environmentFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
example = "/run/secrets/changedetection-io.env";
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Securely pass environment variabels to changedetection-io.
|
||||||
|
|
||||||
|
This can be used to set for example a frontend password reproducible via `SALTED_PASS`
|
||||||
|
which convinetly also deactivates nags about the hosted version.
|
||||||
|
`SALTED_PASS` should be 64 characters long while the first 32 are the salt and the second the frontend password.
|
||||||
|
It can easily be retrieved from the settings file when first set via the frontend with the following command:
|
||||||
|
``jq -r .settings.application.password /var/lib/changedetection-io/url-watches.json``
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
webDriverSupport = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Enable support for fetching web pages using WebDriver and Chromium.
|
||||||
|
This starts a headless chromium controlled by puppeteer in an oci container.
|
||||||
|
|
||||||
|
::: {.note}
|
||||||
|
Playwright can currently leak memory.
|
||||||
|
See https://github.com/dgtlmoon/changedetection.io/wiki/Playwright-content-fetcher#playwright-memory-leak
|
||||||
|
:::
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
playwrightSupport = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Enable support for fetching web pages using playwright and Chromium.
|
||||||
|
This starts a headless Chromium controlled by puppeteer in an oci container.
|
||||||
|
|
||||||
|
::: {.note}
|
||||||
|
Playwright can currently leak memory.
|
||||||
|
See https://github.com/dgtlmoon/changedetection.io/wiki/Playwright-content-fetcher#playwright-memory-leak
|
||||||
|
:::
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
chromePort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 4444;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
A free port on which webDriverSupport or playwrightSupport listen on localhost.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = !((cfg.webDriverSupport == true) && (cfg.playwrightSupport == true));
|
||||||
|
message = "'services.changedetection-io.webDriverSupport' and 'services.changedetion-io.playwrightSupport' cannot be used together.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd = let
|
||||||
|
defaultStateDir = cfg.datastorePath == "/var/lib/changedetection-io";
|
||||||
|
in {
|
||||||
|
services.changedetection-io = {
|
||||||
|
wantedBy = [ "mutli-user.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
preStart = ''
|
||||||
|
mkdir -p ${cfg.datastorePath}
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
User = cfg.user;
|
||||||
|
Group = cfg.group;
|
||||||
|
StateDirectory = mkIf defaultStateDir "changedetion-io";
|
||||||
|
StateDirectoryMode = mkIf defaultStateDir "0750";
|
||||||
|
WorkingDirectory = cfg.datastorePath;
|
||||||
|
Environment = lib.optional (cfg.baseURL != null) "BASE_URL=${cfg.baseURL}"
|
||||||
|
++ lib.optional cfg.behindProxy "USE_X_SETTINGS=1"
|
||||||
|
++ lib.optional cfg.webDriverSupport "WEBDRIVER_URL=http://127.0.0.1:${toString cfg.chromePort}/wd/hub"
|
||||||
|
++ lib.optional cfg.playwrightSupport "PLAYWRIGHT_DRIVER_URL=ws://127.0.0.1:${toString cfg.chromePort}/?stealth=1&--disable-web-security=true";
|
||||||
|
EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
||||||
|
ExecStart = ''
|
||||||
|
${pkgs.changedetection-io}/bin/changedetection.py \
|
||||||
|
-h ${cfg.listenAddress} -p ${toString cfg.port} -d ${cfg.datastorePath}
|
||||||
|
'';
|
||||||
|
ProtectHome = true;
|
||||||
|
ProtectSystem = true;
|
||||||
|
Restart = "on-failure";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
tmpfiles.rules = mkIf defaultStateDir [
|
||||||
|
"d ${cfg.datastorePath} 0750 ${cfg.user} ${cfg.group} - -"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
users = {
|
||||||
|
users = optionalAttrs (cfg.user == "changedetection-io") {
|
||||||
|
"changedetection-io" = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "changedetection-io";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
groups = optionalAttrs (cfg.group == "changedetection-io") {
|
||||||
|
"changedetection-io" = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation = {
|
||||||
|
oci-containers.containers = lib.mkMerge [
|
||||||
|
(mkIf cfg.webDriverSupport {
|
||||||
|
changedetection-io-webdriver = {
|
||||||
|
image = "selenium/standalone-chrome";
|
||||||
|
environment = {
|
||||||
|
VNC_NO_PASSWORD = "1";
|
||||||
|
SCREEN_WIDTH = "1920";
|
||||||
|
SCREEN_HEIGHT = "1080";
|
||||||
|
SCREEN_DEPTH = "24";
|
||||||
|
};
|
||||||
|
ports = [
|
||||||
|
"127.0.0.1:${toString cfg.chromePort}:4444"
|
||||||
|
];
|
||||||
|
volumes = [
|
||||||
|
"/dev/shm:/dev/shm"
|
||||||
|
];
|
||||||
|
extraOptions = [ "--network=bridge" ];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
(mkIf cfg.playwrightSupport {
|
||||||
|
changedetection-io-playwright = {
|
||||||
|
image = "browserless/chrome";
|
||||||
|
environment = {
|
||||||
|
SCREEN_WIDTH = "1920";
|
||||||
|
SCREEN_HEIGHT = "1024";
|
||||||
|
SCREEN_DEPTH = "16";
|
||||||
|
ENABLE_DEBUGGER = "false";
|
||||||
|
PREBOOT_CHROME = "true";
|
||||||
|
CONNECTION_TIMEOUT = "300000";
|
||||||
|
MAX_CONCURRENT_SESSIONS = "10";
|
||||||
|
CHROME_REFRESH_TIME = "600000";
|
||||||
|
DEFAULT_BLOCK_ADS = "true";
|
||||||
|
DEFAULT_STEALTH = "true";
|
||||||
|
};
|
||||||
|
ports = [
|
||||||
|
"127.0.0.1:${toString cfg.chromePort}:3000"
|
||||||
|
];
|
||||||
|
extraOptions = [ "--network=bridge" ];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ buildPythonApplication rec {
|
||||||
click-plugins
|
click-plugins
|
||||||
elasticsearch
|
elasticsearch
|
||||||
flask-compress
|
flask-compress
|
||||||
flask_login
|
flask-login
|
||||||
flask-wtf
|
flask-wtf
|
||||||
html2text
|
html2text
|
||||||
python-dotenv
|
python-dotenv
|
||||||
|
|
|
@ -95,7 +95,7 @@ let
|
||||||
flask
|
flask
|
||||||
flask-babel
|
flask-babel
|
||||||
flask_assets
|
flask_assets
|
||||||
flask_login
|
flask-login
|
||||||
flask-limiter
|
flask-limiter
|
||||||
frozendict
|
frozendict
|
||||||
future
|
future
|
||||||
|
|
|
@ -60,7 +60,7 @@ python3Packages.buildPythonApplication rec {
|
||||||
cherrypy
|
cherrypy
|
||||||
flask-compress
|
flask-compress
|
||||||
flask-cors
|
flask-cors
|
||||||
flask_login
|
flask-login
|
||||||
flask-restful
|
flask-restful
|
||||||
flask-restx
|
flask-restx
|
||||||
flask
|
flask
|
||||||
|
|
|
@ -18,7 +18,7 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
pythonDeps = with python.pkgs; [
|
pythonDeps = with python.pkgs; [
|
||||||
flask flask_assets flask_login flask-sqlalchemy flask_migrate flask-seasurf flask_mail flask-session flask-sslify
|
flask flask_assets flask-login flask-sqlalchemy flask_migrate flask-seasurf flask_mail flask-session flask-sslify
|
||||||
mysqlclient psycopg2 sqlalchemy
|
mysqlclient psycopg2 sqlalchemy
|
||||||
cffi configobj cryptography bcrypt requests python-ldap pyotp qrcode dnspython
|
cffi configobj cryptography bcrypt requests python-ldap pyotp qrcode dnspython
|
||||||
gunicorn python3-saml pytz cssmin rjsmin authlib bravado-core
|
gunicorn python3-saml pytz cssmin rjsmin authlib bravado-core
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
, deprecated
|
, deprecated
|
||||||
, dill
|
, dill
|
||||||
, flask
|
, flask
|
||||||
, flask_login
|
, flask-login
|
||||||
, flask-appbuilder
|
, flask-appbuilder
|
||||||
, flask-caching
|
, flask-caching
|
||||||
, flask-session
|
, flask-session
|
||||||
|
@ -159,7 +159,7 @@ buildPythonPackage rec {
|
||||||
flask-caching
|
flask-caching
|
||||||
flask-session
|
flask-session
|
||||||
flask-wtf
|
flask-wtf
|
||||||
flask_login
|
flask-login
|
||||||
GitPython
|
GitPython
|
||||||
graphviz
|
graphviz
|
||||||
gunicorn
|
gunicorn
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
, email-validator
|
, email-validator
|
||||||
, flask
|
, flask
|
||||||
, flask-babel
|
, flask-babel
|
||||||
, flask_login
|
, flask-login
|
||||||
, flask-openid
|
, flask-openid
|
||||||
, flask-sqlalchemy
|
, flask-sqlalchemy
|
||||||
, flask-wtf
|
, flask-wtf
|
||||||
|
@ -59,7 +59,7 @@ buildPythonPackage rec {
|
||||||
email-validator
|
email-validator
|
||||||
flask
|
flask
|
||||||
flask-babel
|
flask-babel
|
||||||
flask_login
|
flask-login
|
||||||
flask-openid
|
flask-openid
|
||||||
flask-sqlalchemy
|
flask-sqlalchemy
|
||||||
flask-wtf
|
flask-wtf
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
, blinker
|
, blinker
|
||||||
, email-validator
|
, email-validator
|
||||||
, flask
|
, flask
|
||||||
, flask_login
|
, flask-login
|
||||||
, flask_principal
|
, flask_principal
|
||||||
, flask-wtf
|
, flask-wtf
|
||||||
, itsdangerous
|
, itsdangerous
|
||||||
|
@ -57,7 +57,7 @@ buildPythonPackage rec {
|
||||||
blinker
|
blinker
|
||||||
email-validator
|
email-validator
|
||||||
flask
|
flask
|
||||||
flask_login
|
flask-login
|
||||||
flask_principal
|
flask_principal
|
||||||
flask-wtf
|
flask-wtf
|
||||||
itsdangerous
|
itsdangerous
|
||||||
|
|
38
pkgs/development/python-modules/inscriptis/default.nix
Normal file
38
pkgs/development/python-modules/inscriptis/default.nix
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{ lib
|
||||||
|
, buildPythonPackage
|
||||||
|
, fetchFromGitHub
|
||||||
|
, lxml
|
||||||
|
, pytestCheckHook
|
||||||
|
, requests
|
||||||
|
}:
|
||||||
|
|
||||||
|
buildPythonPackage rec {
|
||||||
|
pname = "inscriptis";
|
||||||
|
version = "2.3.1";
|
||||||
|
format = "setuptools";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "weblyzard";
|
||||||
|
repo = "inscriptis";
|
||||||
|
rev = version;
|
||||||
|
sha256 = "sha256-an/FTbujN2VnTYa0wngM8ugV1LNHJWM32RVqIbaW0KY=";
|
||||||
|
};
|
||||||
|
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
lxml
|
||||||
|
requests
|
||||||
|
];
|
||||||
|
|
||||||
|
checkInputs = [
|
||||||
|
pytestCheckHook
|
||||||
|
];
|
||||||
|
|
||||||
|
pythonImportsCheck = [ "inscriptis" ];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "inscriptis - HTML to text converter";
|
||||||
|
homepage = "https://github.com/weblyzard/inscriptis";
|
||||||
|
license = licenses.asl20;
|
||||||
|
maintainers = with maintainers; [ SuperSandro2000 ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -9,13 +9,14 @@
|
||||||
|
|
||||||
buildPythonPackage rec {
|
buildPythonPackage rec {
|
||||||
pname = "jsonpath-ng";
|
pname = "jsonpath-ng";
|
||||||
version = "1.5.2";
|
version = "1.5.3";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "h2non";
|
owner = "h2non";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
# missing tag https://github.com/h2non/jsonpath-ng/issues/114
|
||||||
sha256 = "1cxjwhx0nj85a3awnl7j6afnk07awzv45qfwxl5jqbbc9cxh5bd6";
|
rev = "cce4a3d4063ac8af928795acc53beb27a2bfd101";
|
||||||
|
sha256 = "sha256-+9iQHQs5TQhZFeIqMlsa3FFPfZEktAWy1lSdJU7kZrc=";
|
||||||
};
|
};
|
||||||
|
|
||||||
propagatedBuildInputs = [
|
propagatedBuildInputs = [
|
||||||
|
|
221
pkgs/development/python-modules/playwright/default.nix
Normal file
221
pkgs/development/python-modules/playwright/default.nix
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, buildPythonPackage
|
||||||
|
, chromium
|
||||||
|
, ffmpeg
|
||||||
|
, firefox
|
||||||
|
, git
|
||||||
|
, greenlet
|
||||||
|
, jq
|
||||||
|
, nodejs
|
||||||
|
, fetchFromGitHub
|
||||||
|
, fetchurl
|
||||||
|
, makeFontsConf
|
||||||
|
, makeWrapper
|
||||||
|
, pyee
|
||||||
|
, python
|
||||||
|
, pythonOlder
|
||||||
|
, runCommand
|
||||||
|
, setuptools-scm
|
||||||
|
, unzip
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (stdenv.hostPlatform) system;
|
||||||
|
throwSystem = throw "Unsupported system: ${system}";
|
||||||
|
|
||||||
|
driverVersion = "1.27.1";
|
||||||
|
|
||||||
|
driver = let
|
||||||
|
suffix = {
|
||||||
|
x86_64-linux = "linux";
|
||||||
|
aarch64-linux = "linux-arm64";
|
||||||
|
x86_64-darwin = "mac";
|
||||||
|
aarch64-darwin = "mac-arm64";
|
||||||
|
}.${system} or throwSystem;
|
||||||
|
filename = "playwright-${driverVersion}-${suffix}.zip";
|
||||||
|
in stdenv.mkDerivation {
|
||||||
|
pname = "playwright-driver";
|
||||||
|
version = driverVersion;
|
||||||
|
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://playwright.azureedge.net/builds/driver/${filename}";
|
||||||
|
sha256 = {
|
||||||
|
x86_64-linux = "0x71b4kb8hlyacixipgfbgjgrbmhckxpbmrs2xk8iis7n5kg7539";
|
||||||
|
aarch64-linux = "125lih7g2gj91k7j196wy5a5746wyfr8idj3ng369yh5wl7lfcfv";
|
||||||
|
x86_64-darwin = "0z2kww4iby1izkwn6z2ai94y87bkjvwak8awdmjm8sgg00pa9l1a";
|
||||||
|
aarch64-darwin = "0qajh4ac5lr1sznb2c471r5c5g2r0dk2pyqz8vhvnbk36r524h1h";
|
||||||
|
}.${system} or throwSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
sourceRoot = ".";
|
||||||
|
|
||||||
|
nativeBuildInputs = [ unzip ];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
# Use Nix's NodeJS instead of the bundled one.
|
||||||
|
substituteInPlace playwright.sh --replace '"$SCRIPT_PATH/node"' '"${nodejs}/bin/node"'
|
||||||
|
rm node
|
||||||
|
|
||||||
|
# Hard-code the script path to $out directory to avoid a dependency on coreutils
|
||||||
|
substituteInPlace playwright.sh \
|
||||||
|
--replace 'SCRIPT_PATH="$(cd "$(dirname "$0")" ; pwd -P)"' "SCRIPT_PATH=$out"
|
||||||
|
|
||||||
|
patchShebangs playwright.sh package/bin/*.sh
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mkdir -p $out/bin
|
||||||
|
mv playwright.sh $out/bin/playwright
|
||||||
|
mv package $out/
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
inherit filename;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
browsers-mac = stdenv.mkDerivation {
|
||||||
|
pname = "playwright-browsers";
|
||||||
|
version = driverVersion;
|
||||||
|
|
||||||
|
src = runCommand "playwright-browsers-base" {
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHashAlgo = "sha256";
|
||||||
|
outputHash = {
|
||||||
|
x86_64-darwin = "0z2kww4iby1izkwn6z2ai94y87bkjvwak8awdmjm8sgg00pa9l1a";
|
||||||
|
}.${system} or throwSystem;
|
||||||
|
} ''
|
||||||
|
export PLAYWRIGHT_BROWSERS_PATH=$out
|
||||||
|
${driver}/bin/playwright install
|
||||||
|
rm -r $out/.links
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir $out
|
||||||
|
cp -r * $out/
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
browsers-linux = { withFirefox ? true, withChromium ? true }: let
|
||||||
|
fontconfig = makeFontsConf {
|
||||||
|
fontDirectories = [];
|
||||||
|
};
|
||||||
|
in runCommand ("playwright-browsers"
|
||||||
|
+ lib.optionalString (withFirefox && !withChromium) "-firefox"
|
||||||
|
+ lib.optionalString (!withFirefox && withChromium) "-chromium")
|
||||||
|
{
|
||||||
|
nativeBuildInputs = [
|
||||||
|
makeWrapper
|
||||||
|
jq
|
||||||
|
];
|
||||||
|
} (''
|
||||||
|
BROWSERS_JSON=${driver}/share/playwright-driver/package/browsers.json
|
||||||
|
'' + lib.optionalString withChromium ''
|
||||||
|
CHROMIUM_REVISION=$(jq -r '.browsers[] | select(.name == "chromium").revision' $BROWSERS_JSON)
|
||||||
|
mkdir -p $out/chromium-$CHROMIUM_REVISION/chrome-linux
|
||||||
|
|
||||||
|
# See here for the Chrome options:
|
||||||
|
# https://github.com/NixOS/nixpkgs/issues/136207#issuecomment-908637738
|
||||||
|
makeWrapper ${chromium}/bin/chromium $out/chromium-$CHROMIUM_REVISION/chrome-linux/chrome \
|
||||||
|
--set SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt \
|
||||||
|
--set FONTCONFIG_FILE ${fontconfig}
|
||||||
|
'' + lib.optionalString withFirefox ''
|
||||||
|
FIREFOX_REVISION=$(jq -r '.browsers[] | select(.name == "firefox").revision' $BROWSERS_JSON)
|
||||||
|
mkdir -p $out/firefox-$FIREFOX_REVISION
|
||||||
|
ln -s ${firefox}/bin/firefox $out/firefox-$FIREFOX_REVISION/firefox
|
||||||
|
'' + ''
|
||||||
|
FFMPEG_REVISION=$(jq -r '.browsers[] | select(.name == "ffmpeg").revision' $BROWSERS_JSON)
|
||||||
|
mkdir -p $out/ffmpeg-$FFMPEG_REVISION
|
||||||
|
ln -s ${ffmpeg}/bin/ffmpeg $out/ffmpeg-$FFMPEG_REVISION/ffmpeg-linux
|
||||||
|
'');
|
||||||
|
in
|
||||||
|
buildPythonPackage rec {
|
||||||
|
pname = "playwright";
|
||||||
|
version = "1.27.1";
|
||||||
|
format = "setuptools";
|
||||||
|
disabled = pythonOlder "3.7";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "microsoft";
|
||||||
|
repo = "playwright-python";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-cI/4GdkmTikoP9O0Skh/0jCxxRypRua0231iKcxtBcY=";
|
||||||
|
};
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
# This patches two things:
|
||||||
|
# - The driver location, which is now a static package in the Nix store.
|
||||||
|
# - The setup script, which would try to download the driver package from
|
||||||
|
# a CDN and patch wheels so that they include it. We don't want this
|
||||||
|
# we have our own driver build.
|
||||||
|
./driver-location.patch
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
# if setuptools_scm is not listing files via git almost all python files are excluded
|
||||||
|
export HOME=$(mktemp -d)
|
||||||
|
git init .
|
||||||
|
git add -A .
|
||||||
|
git config --global user.email "nixpkgs"
|
||||||
|
git config --global user.name "nixpkgs"
|
||||||
|
git commit -m "workaround setuptools-scm"
|
||||||
|
|
||||||
|
substituteInPlace setup.py \
|
||||||
|
--replace "greenlet==1.1.3" "greenlet>=1.1.3" \
|
||||||
|
--replace "pyee==8.1.0" "pyee>=8.1.0" \
|
||||||
|
--replace "setuptools-scm==7.0.5" "setuptools-scm>=7.0.5" \
|
||||||
|
--replace "wheel==0.37.1" "wheel>=0.37.1"
|
||||||
|
|
||||||
|
# Skip trying to download and extract the driver.
|
||||||
|
# This is done manually in postInstall instead.
|
||||||
|
substituteInPlace setup.py \
|
||||||
|
--replace "self._download_and_extract_local_driver(base_wheel_bundles)" ""
|
||||||
|
|
||||||
|
# Set the correct driver path with the help of a patch in patches
|
||||||
|
substituteInPlace playwright/_impl/_driver.py \
|
||||||
|
--replace "@driver@" "${driver}/bin/playwright"
|
||||||
|
'';
|
||||||
|
|
||||||
|
|
||||||
|
nativeBuildInputs = [ git setuptools-scm ];
|
||||||
|
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
greenlet
|
||||||
|
pyee
|
||||||
|
];
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
ln -s ${driver} $out/${python.sitePackages}/playwright/driver
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Skip tests because they require network access.
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
pythonImportsCheck = [
|
||||||
|
"playwright"
|
||||||
|
];
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
inherit driver;
|
||||||
|
browsers = {
|
||||||
|
x86_64-linux = browsers-linux { };
|
||||||
|
aarch64-linux = browsers-linux { };
|
||||||
|
x86_64-darwin = browsers-mac;
|
||||||
|
aarch64-darwin = browsers-mac;
|
||||||
|
}.${system} or throwSystem;
|
||||||
|
browsers-chromium = browsers-linux { withFirefox = false; };
|
||||||
|
browsers-firefox = browsers-linux { withChromium = false; };
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Python version of the Playwright testing and automation library";
|
||||||
|
homepage = "https://github.com/microsoft/playwright-python";
|
||||||
|
license = licenses.asl20;
|
||||||
|
maintainers = with maintainers; [ techknowlogick yrd SuperSandro2000 ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
diff --git a/playwright/_impl/_driver.py b/playwright/_impl/_driver.py
|
||||||
|
index f3b911f..d00e509 100644
|
||||||
|
--- a/playwright/_impl/_driver.py
|
||||||
|
+++ b/playwright/_impl/_driver.py
|
||||||
|
@@ -23,11 +23,7 @@ from playwright._repo_version import version
|
||||||
|
|
||||||
|
|
||||||
|
def compute_driver_executable() -> Path:
|
||||||
|
- package_path = Path(inspect.getfile(playwright)).parent
|
||||||
|
- platform = sys.platform
|
||||||
|
- if platform == "win32":
|
||||||
|
- return package_path / "driver" / "playwright.cmd"
|
||||||
|
- return package_path / "driver" / "playwright.sh"
|
||||||
|
+ return Path("@driver@")
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info.major == 3 and sys.version_info.minor == 7:
|
||||||
|
diff --git a/setup.py b/setup.py
|
||||||
|
index 3487a6a..05112c2 100644
|
||||||
|
--- a/setup.py
|
||||||
|
+++ b/setup.py
|
||||||
|
@@ -141,25 +141,8 @@ class PlaywrightBDistWheelCommand(BDistWheelCommand):
|
||||||
|
base_wheel_location: str = glob.glob(os.path.join(self.dist_dir, "*.whl"))[0]
|
||||||
|
without_platform = base_wheel_location[:-7]
|
||||||
|
for wheel_bundle in wheels:
|
||||||
|
- download_driver(wheel_bundle["zip_name"])
|
||||||
|
- zip_file = (
|
||||||
|
- f"driver/playwright-{driver_version}-{wheel_bundle['zip_name']}.zip"
|
||||||
|
- )
|
||||||
|
- with zipfile.ZipFile(zip_file, "r") as zip:
|
||||||
|
- extractall(zip, f"driver/{wheel_bundle['zip_name']}")
|
||||||
|
wheel_location = without_platform + wheel_bundle["wheel"]
|
||||||
|
shutil.copy(base_wheel_location, wheel_location)
|
||||||
|
- with zipfile.ZipFile(wheel_location, "a") as zip:
|
||||||
|
- driver_root = os.path.abspath(f"driver/{wheel_bundle['zip_name']}")
|
||||||
|
- for dir_path, _, files in os.walk(driver_root):
|
||||||
|
- for file in files:
|
||||||
|
- from_path = os.path.join(dir_path, file)
|
||||||
|
- to_path = os.path.relpath(from_path, driver_root)
|
||||||
|
- zip.write(from_path, f"playwright/driver/{to_path}")
|
||||||
|
- zip.writestr(
|
||||||
|
- "playwright/driver/README.md",
|
||||||
|
- f"{wheel_bundle['wheel']} driver package",
|
||||||
|
- )
|
||||||
|
os.remove(base_wheel_location)
|
||||||
|
if InWheel:
|
||||||
|
for whlfile in glob.glob(os.path.join(self.dist_dir, "*.whl")):
|
31
pkgs/development/python-modules/playwright/update.sh
Executable file
31
pkgs/development/python-modules/playwright/update.sh
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#!nix-shell -i bash -p curl gnused nix-prefetch common-updater-scripts
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
root="$(dirname "$(readlink -f "$0")")"
|
||||||
|
|
||||||
|
version=$(curl ${GITHUB_TOKEN:+" -u \":$GITHUB_TOKEN\""} -s https://api.github.com/repos/microsoft/playwright-python/releases/latest | jq -r '.tag_name | sub("^v"; "")')
|
||||||
|
|
||||||
|
# Most of the time, this should be the latest stable release of the Node-based
|
||||||
|
# Playwright version, but that isn't a guarantee, so this needs to be specified
|
||||||
|
# as well:
|
||||||
|
setup_py_url="https://github.com/microsoft/playwright-python/raw/v${version}/setup.py"
|
||||||
|
driver_version=$(curl -Ls "$setup_py_url" | grep '^driver_version =' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')
|
||||||
|
|
||||||
|
fetch_driver_arch() {
|
||||||
|
nix-prefetch-url "https://playwright.azureedge.net/builds/driver/playwright-${version}-${1}.zip"
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_sha() {
|
||||||
|
sed -i "s|$1 = \".\{44,52\}\"|$1 = \"$2\"|" "$root/default.nix"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Replace SHAs for the driver downloads
|
||||||
|
replace_sha "x86_64-linux" "$(fetch_driver_arch "linux")"
|
||||||
|
replace_sha "x86_64-darwin" "$(fetch_driver_arch "mac")"
|
||||||
|
replace_sha "aarch64-linux" "$(fetch_driver_arch "linux-arm64")"
|
||||||
|
replace_sha "aarch64-darwin" "$(fetch_driver_arch "mac-arm64")"
|
||||||
|
|
||||||
|
# Update the version stamps
|
||||||
|
sed -i "s/driverVersion = \"[^\$]*\"/driverVersion = \"$driver_version\"/" "$root/default.nix"
|
||||||
|
update-source-version playwright "$version" --rev="v$version"
|
|
@ -12,14 +12,15 @@
|
||||||
|
|
||||||
buildPythonPackage rec {
|
buildPythonPackage rec {
|
||||||
pname = "selenium";
|
pname = "selenium";
|
||||||
version = "4.4.2";
|
version = "4.5.0";
|
||||||
disabled = pythonOlder "3.7";
|
disabled = pythonOlder "3.7";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "SeleniumHQ";
|
owner = "SeleniumHQ";
|
||||||
repo = "selenium";
|
repo = "selenium";
|
||||||
rev = "refs/tags/selenium-${version}-python"; # check if there is a newer tag with -python suffix
|
# check if there is a newer tag with or without -python suffix
|
||||||
hash = "sha256-sJJ3i4mnGp5fDgo64p6B2vRCqp/Wm99VoyRLyy4nBH8=";
|
rev = "refs/tags/selenium-${version}";
|
||||||
|
hash = "sha256-K90CQYTeX9GKpP0ahxLx2HO5HG0P6MN7jeWmHtfiOns=";
|
||||||
};
|
};
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
|
@ -50,6 +51,6 @@ buildPythonPackage rec {
|
||||||
description = "Bindings for Selenium WebDriver";
|
description = "Bindings for Selenium WebDriver";
|
||||||
homepage = "https://selenium.dev/";
|
homepage = "https://selenium.dev/";
|
||||||
license = licenses.asl20;
|
license = licenses.asl20;
|
||||||
maintainers = with maintainers; [ jraygauthier ];
|
maintainers = with maintainers; [ jraygauthier SuperSandro2000 ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
, django
|
, django
|
||||||
, falcon
|
, falcon
|
||||||
, flask
|
, flask
|
||||||
, flask_login
|
, flask-login
|
||||||
, httpx
|
, httpx
|
||||||
, pure-eval
|
, pure-eval
|
||||||
, pyramid
|
, pyramid
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
, fetchPypi
|
, fetchPypi
|
||||||
, buildPythonPackage
|
, buildPythonPackage
|
||||||
, flask
|
, flask
|
||||||
, flask_login
|
, flask-login
|
||||||
, flask-sqlalchemy
|
, flask-sqlalchemy
|
||||||
, flexmock
|
, flexmock
|
||||||
, pytestCheckHook
|
, pytestCheckHook
|
||||||
|
@ -32,7 +32,7 @@ buildPythonPackage rec {
|
||||||
pytestCheckHook
|
pytestCheckHook
|
||||||
sqlalchemy-i18n
|
sqlalchemy-i18n
|
||||||
flask
|
flask
|
||||||
flask_login
|
flask-login
|
||||||
flask-sqlalchemy
|
flask-sqlalchemy
|
||||||
flexmock
|
flexmock
|
||||||
];
|
];
|
||||||
|
|
92
pkgs/servers/web-apps/changedetection-io/default.nix
Normal file
92
pkgs/servers/web-apps/changedetection-io/default.nix
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
{ lib
|
||||||
|
, fetchFromGitHub
|
||||||
|
, python3
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
py = python3.override {
|
||||||
|
packageOverrides = final: prev: {
|
||||||
|
flask = prev.flask.overridePythonAttrs (old: rec {
|
||||||
|
version = "2.1.3";
|
||||||
|
src = old.src.override {
|
||||||
|
inherit version;
|
||||||
|
sha256 = "sha256-FZcuUBffBXXD1sCQuhaLbbkCWeYgrI1+qBOjlrrVtss=";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
flask-restful = prev.flask-restful.overridePythonAttrs (old: rec {
|
||||||
|
disabledTests = old.disabledTests or [ ] ++ [
|
||||||
|
# fails because of flask or werkzeug downgrade
|
||||||
|
"test_redirect"
|
||||||
|
];
|
||||||
|
});
|
||||||
|
werkzeug = prev.werkzeug.overridePythonAttrs (old: rec {
|
||||||
|
version = "2.0.3";
|
||||||
|
src = old.src.override {
|
||||||
|
inherit version;
|
||||||
|
sha256 = "sha256-uGP4/wV8UiFktgZ8niiwQRYbS+W6TQ2s7qpQoWOCLTw=";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
py.pkgs.buildPythonApplication rec {
|
||||||
|
pname = "changedetection-io";
|
||||||
|
version = "0.39.20.3";
|
||||||
|
format = "setuptools";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "dgtlmoon";
|
||||||
|
repo = "changedetection.io";
|
||||||
|
rev = version;
|
||||||
|
sha256 = "sha256-0Sv/1YoZuSnslQgMOu+uHTxb9QewXPC0tLAvzJA4Aa8=";
|
||||||
|
};
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace requirements.txt \
|
||||||
|
--replace "bs4" "beautifulsoup4" \
|
||||||
|
--replace "cryptography ~= 3.4" "cryptography" \
|
||||||
|
--replace "selenium ~= 4.1.0" "selenium"
|
||||||
|
'';
|
||||||
|
|
||||||
|
propagatedBuildInputs = with py.pkgs; [
|
||||||
|
flask
|
||||||
|
flask-wtf
|
||||||
|
eventlet
|
||||||
|
validators
|
||||||
|
timeago
|
||||||
|
inscriptis
|
||||||
|
feedgen
|
||||||
|
flask-login
|
||||||
|
flask-restful
|
||||||
|
pytz
|
||||||
|
brotli
|
||||||
|
requests
|
||||||
|
urllib3
|
||||||
|
chardet
|
||||||
|
wtforms
|
||||||
|
jsonpath-ng
|
||||||
|
jq
|
||||||
|
apprise
|
||||||
|
paho-mqtt
|
||||||
|
cryptography
|
||||||
|
beautifulsoup4
|
||||||
|
lxml
|
||||||
|
selenium
|
||||||
|
werkzeug
|
||||||
|
playwright
|
||||||
|
] ++ requests.optional-dependencies.socks;
|
||||||
|
|
||||||
|
# tests can currently not be run in one pytest invocation and without docker
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
checkInputs = with py.pkgs; [
|
||||||
|
pytest-flask
|
||||||
|
pytestCheckHook
|
||||||
|
];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://github.com/dgtlmoon/changedetection.io";
|
||||||
|
description = "Simplest self-hosted free open source website change detection tracking, monitoring and notification service";
|
||||||
|
license = licenses.asl20;
|
||||||
|
maintainers = with maintainers; [ SuperSandro2000 ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ let
|
||||||
buildDeps = with pythonPackages; [
|
buildDeps = with pythonPackages; [
|
||||||
flask
|
flask
|
||||||
flask-gravatar
|
flask-gravatar
|
||||||
flask_login
|
flask-login
|
||||||
flask_mail
|
flask_mail
|
||||||
flask_migrate
|
flask_migrate
|
||||||
flask-sqlalchemy
|
flask-sqlalchemy
|
||||||
|
|
|
@ -3558,6 +3558,8 @@ with pkgs;
|
||||||
|
|
||||||
cambalache = callPackage ../development/tools/cambalache { };
|
cambalache = callPackage ../development/tools/cambalache { };
|
||||||
|
|
||||||
|
changedetection-io = callPackage ../servers/web-apps/changedetection-io { };
|
||||||
|
|
||||||
clipster = callPackage ../tools/misc/clipster { };
|
clipster = callPackage ../tools/misc/clipster { };
|
||||||
|
|
||||||
clockify = callPackage ../applications/office/clockify {
|
clockify = callPackage ../applications/office/clockify {
|
||||||
|
@ -10290,6 +10292,8 @@ with pkgs;
|
||||||
|
|
||||||
playbar2 = libsForQt5.callPackage ../applications/audio/playbar2 { };
|
playbar2 = libsForQt5.callPackage ../applications/audio/playbar2 { };
|
||||||
|
|
||||||
|
playwright = with python3Packages; toPythonApplication playwright;
|
||||||
|
|
||||||
please = callPackage ../tools/security/please { };
|
please = callPackage ../tools/security/please { };
|
||||||
|
|
||||||
plecost = callPackage ../tools/security/plecost { };
|
plecost = callPackage ../tools/security/plecost { };
|
||||||
|
|
|
@ -75,6 +75,7 @@ mapAliases ({
|
||||||
face_recognition_models = face-recognition-models; # added 2022-10-15
|
face_recognition_models = face-recognition-models; # added 2022-10-15
|
||||||
fake_factory = throw "fake_factory has been removed because it is unused and deprecated by upstream since 2016."; # added 2022-05-30
|
fake_factory = throw "fake_factory has been removed because it is unused and deprecated by upstream since 2016."; # added 2022-05-30
|
||||||
faulthandler = throw "faulthandler is built into ${python.executable}"; # added 2021-07-12
|
faulthandler = throw "faulthandler is built into ${python.executable}"; # added 2021-07-12
|
||||||
|
flask_login = flask-login; # added 2022-10-17
|
||||||
flask_sqlalchemy = flask-sqlalchemy; # added 2022-07-20
|
flask_sqlalchemy = flask-sqlalchemy; # added 2022-07-20
|
||||||
flask_testing = flask-testing; # added 2022-04-25
|
flask_testing = flask-testing; # added 2022-04-25
|
||||||
flask_wtf = flask-wtf; # added 2022-05-24
|
flask_wtf = flask-wtf; # added 2022-05-24
|
||||||
|
|
|
@ -3441,7 +3441,7 @@ in {
|
||||||
|
|
||||||
flask-limiter = callPackage ../development/python-modules/flask-limiter { };
|
flask-limiter = callPackage ../development/python-modules/flask-limiter { };
|
||||||
|
|
||||||
flask_login = callPackage ../development/python-modules/flask-login { };
|
flask-login = callPackage ../development/python-modules/flask-login { };
|
||||||
|
|
||||||
flask_mail = callPackage ../development/python-modules/flask-mail { };
|
flask_mail = callPackage ../development/python-modules/flask-mail { };
|
||||||
|
|
||||||
|
@ -4614,6 +4614,8 @@ in {
|
||||||
|
|
||||||
inquirer = callPackage ../development/python-modules/inquirer { };
|
inquirer = callPackage ../development/python-modules/inquirer { };
|
||||||
|
|
||||||
|
inscriptis = callPackage ../development/python-modules/inscriptis { };
|
||||||
|
|
||||||
insegel = callPackage ../development/python-modules/insegel { };
|
insegel = callPackage ../development/python-modules/insegel { };
|
||||||
|
|
||||||
installer = callPackage ../development/python-modules/installer { };
|
installer = callPackage ../development/python-modules/installer { };
|
||||||
|
@ -7038,6 +7040,10 @@ in {
|
||||||
|
|
||||||
pkuseg = callPackage ../development/python-modules/pkuseg { };
|
pkuseg = callPackage ../development/python-modules/pkuseg { };
|
||||||
|
|
||||||
|
playwright = callPackage ../development/python-modules/playwright {
|
||||||
|
inherit (pkgs) jq;
|
||||||
|
};
|
||||||
|
|
||||||
pmsensor = callPackage ../development/python-modules/pmsensor { };
|
pmsensor = callPackage ../development/python-modules/pmsensor { };
|
||||||
|
|
||||||
ppdeep = callPackage ../development/python-modules/ppdeep { };
|
ppdeep = callPackage ../development/python-modules/ppdeep { };
|
||||||
|
|
Loading…
Reference in a new issue