diff options
author | Martin Fischer <martin@push-f.com> | 2025-03-09 13:48:00 +0100 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2025-03-09 21:36:04 +0100 |
commit | 232f1499bb9a2cc85a63abcc1c22776ef77781fb (patch) | |
tree | 50b9b429140e6d597090e5d1264496555fd0edf7 | |
parent | 42c737aa1a7731170e8369482f96b557a1bd7a36 (diff) |
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | README.md | 16 | ||||
-rw-r--r-- | default.nix | 27 | ||||
-rw-r--r-- | deps/pywikiapi.nix | 16 | ||||
-rwxr-xr-x | osm_proposals/archived_without_template.py (renamed from find_archived_proposals_without_template.py) | 4 | ||||
-rwxr-xr-x | osm_proposals/proposals.py (renamed from proposals.py) | 14 | ||||
-rw-r--r-- | pyproject.toml | 10 | ||||
-rw-r--r-- | service.nix | 52 | ||||
-rw-r--r-- | static/index.html (renamed from index.html) | 0 | ||||
-rw-r--r-- | static/script.js (renamed from script.js) | 0 | ||||
-rw-r--r-- | static/style.css (renamed from style.css) | 0 |
12 files changed, 126 insertions, 16 deletions
diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 204a590..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -proposals.json diff --git a/Makefile b/Makefile deleted file mode 100644 index 31de770..0000000 --- a/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - ./proposals.py > proposals.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..eb4eab7 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# osm-proposals + +An autogenerated web page listing [OpenStreetMap proposals]. + +Hosted under https://osm-proposals.push-f.com/. + +# Local development + + python -m venv venv + . venv/bin/activate + pip install -r requirements.txt + pip install -e . + osm-proposals static/proposals.json + python -m http.server --directory static + +[OpenStreetMap proposals]: https://wiki.openstreetmap.org/wiki/Proposal diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..d923d2e --- /dev/null +++ b/default.nix @@ -0,0 +1,27 @@ +{ pkgs ? import <nixpkgs> {} }: +with pkgs.python310Packages; + +let + pywikiapi = import ./deps/pywikiapi.nix { inherit pkgs; }; +in +buildPythonApplication rec { + pname = "osm-proposals"; + version = "git"; + src = ./.; + pyproject = true; + + build-system = [ + setuptools + ]; + + dependencies = [ + requests + mwparserfromhell + pywikiapi + ]; + + postInstall = '' + mkdir -p $out/share/osm-proposals + cp -r ${./static}/. $out/share/osm-proposals/ + ''; +} diff --git a/deps/pywikiapi.nix b/deps/pywikiapi.nix new file mode 100644 index 0000000..856f0f0 --- /dev/null +++ b/deps/pywikiapi.nix @@ -0,0 +1,16 @@ +{ pkgs }: +with pkgs.python310Packages; + +buildPythonPackage rec { + pname = "pywikiapi"; + version = "4.3.0"; + src = pkgs.fetchPypi { + inherit pname; + inherit version; + hash = "sha256-gynkx98y8Vx/N3i6xoQ7x9MgTW6qACoYcDwy71FDYIE="; + }; + + dependencies = [ + requests + ]; +} diff --git a/find_archived_proposals_without_template.py b/osm_proposals/archived_without_template.py index 6424745..ea026d3 100755 --- a/find_archived_proposals_without_template.py +++ b/osm_proposals/archived_without_template.py @@ -32,7 +32,3 @@ def run(): ): if not 'templates' in page: print(page['title']) - - -if __name__ == "__main__": - run() diff --git a/proposals.py b/osm_proposals/proposals.py index e16412f..c111699 100755 --- a/proposals.py +++ b/osm_proposals/proposals.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Queries wiki.openstreetmap.org for proposals and outputs a JSON list of them to stdout.""" +"""Queries wiki.openstreetmap.org for proposals and writes a JSON list of them to the given file.""" import argparse import html import json @@ -17,7 +17,8 @@ OSMWIKI_ENDPOINT = 'https://wiki.openstreetmap.org/w/api.php' def run(): arg_parser = argparse.ArgumentParser(description=__doc__) - arg_parser.parse_args() + arg_parser.add_argument("out_file") + args = arg_parser.parse_args() res = requests.get( OSMWIKI_ENDPOINT, @@ -47,9 +48,8 @@ def run(): proposals.sort(key=sort_key, reverse=True) - json.dump( - [{k: v for k, v in p.items() if v is not None} for p in proposals], sys.stdout - ) + with open(args.out_file, 'w') as f: + json.dump([{k: v for k, v in p.items() if v is not None} for p in proposals], f) def get_template_val(tpl, name): @@ -185,7 +185,3 @@ def sort_key(proposal): date = proposal['draft_start'] or '' return (-STATUSES.get(proposal['status'], 10), date) - - -if __name__ == "__main__": - run() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..1bad629 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "osm-proposals" +version = "0.0.0" + +[tool.setuptools.packages.find] +where = ["."] + +[project.scripts] +osm-proposals = "osm_proposals.proposals:run" +osm-proposals-archived-without-template = "osm_proposals.archived_without_template:run" diff --git a/service.nix b/service.nix new file mode 100644 index 0000000..fcd665e --- /dev/null +++ b/service.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +let + osm_proposals = pkgs.callPackage ./default.nix {}; + cfg = config.services.osm_proposals; +in +{ + options.services.osm_proposals = { + enable = lib.mkEnableOption "osm_proposals"; + + virtualHost = lib.mkOption { + type = lib.types.str; + description = "Name of the nginx virtualhost to set up."; + }; + + nginx = lib.mkOption { + type = lib.types.submodule (import <nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix>); + default = {}; + }; + }; + + config = lib.mkIf cfg.enable { + services.nginx = { + enable = true; + + virtualHosts.${cfg.virtualHost} = lib.mkMerge [ + cfg.nginx + { + locations."/" = { + root = "${osm_proposals}/share/osm-proposals"; + }; + locations."=/proposals.json" = { + extraConfig = '' + alias /var/lib/osm-proposals/proposals.json; + ''; + }; + } + ]; + }; + + systemd.services.osm-proposals = { + serviceConfig = { + Type = "oneshot"; + StateDirectory = "osm-proposals"; # creates /var/lib/osm-proposals + ExecStart = "${osm_proposals}/bin/osm-proposals /var/lib/osm-proposals/proposals.json"; + # Not using DynamicUser because then the StateDirectory becomes unreadable + # by other users, even when setting StateDirectoryMode for some reason. + }; + startAt = "hourly"; + }; + }; +} diff --git a/index.html b/static/index.html index 8d7bd7a..8d7bd7a 100644 --- a/index.html +++ b/static/index.html diff --git a/script.js b/static/script.js index 35aa43e..35aa43e 100644 --- a/script.js +++ b/static/script.js diff --git a/style.css b/static/style.css index 66fe28f..66fe28f 100644 --- a/style.css +++ b/static/style.css |