diff --git a/ci/deploy.sh b/ci/deploy.sh index 5458374fb..1bcb8262f 100755 --- a/ci/deploy.sh +++ b/ci/deploy.sh @@ -50,7 +50,9 @@ git config --global commit.gpgsign true git clone git@github.com:nix-community/nur-combined -result/bin/nur combine nur-combined +result/bin/nur combine \ + --irc-notify nur-bot@chat.freenode.net:6697/nixos-nur \ + nur-combined if [[ -z "$(git diff --exit-code)" ]]; then echo "No changes to the output on this push; exiting." diff --git a/nur/__init__.py b/nur/__init__.py index ff03df55d..fab7ca290 100644 --- a/nur/__init__.py +++ b/nur/__init__.py @@ -28,6 +28,11 @@ def parse_arguments(argv: List[str]) -> argparse.Namespace: subparsers = parser.add_subparsers(description="subcommands") combine = subparsers.add_parser("combine") + combine.add_argument( + "--irc-notify", + type=str, + help="Example nur-bot@chat.freenode.net:6697/nixos-nur", + ) combine.add_argument("directory") combine.set_defaults(func=combine_command) diff --git a/nur/combine.py b/nur/combine.py index a0e43d4d3..f9a299ead 100644 --- a/nur/combine.py +++ b/nur/combine.py @@ -182,4 +182,16 @@ def combine_command(args: Namespace) -> None: with chdir(combined_path): setup_combined() - update_combined(combined_path) + notifications = update_combined(combined_path) + + if args.irc_notify: + try: + from .irc_notify import send + except ImportError as e: + print(f"failed to import irc_notify, skipping notification: {e}") + return + + try: + send(args.irc_notify, notifications) + except Exception as e: + print(f"failed to send irc notifications: {e}") diff --git a/nur/irc_notify.py b/nur/irc_notify.py new file mode 100644 index 000000000..f826bbfb3 --- /dev/null +++ b/nur/irc_notify.py @@ -0,0 +1,86 @@ +import ssl +from typing import List, Optional +from urllib.parse import urlparse + +from irc.client import Connection, Event, Reactor, ServerConnectionError, is_channel +from irc.connection import Factory + + +class Exit(SystemExit): + pass + + +def send(url: str, notifications: List[str]) -> None: + parsed = urlparse(f"http://{url}") + username = parsed.username or "nur-bot" + server = parsed.hostname or "chat.freenode.de" + if parsed.path != "/" or parsed.path == "": + channel = f"#{parsed.path[1:]}" + else: + channel = "#nixos-nur" + port = parsed.port or 6697 + password = parsed.password + if len(notifications) == 0: + return + _send( + notifications=notifications, + nickname=username, + password=password, + server=server, + channel=channel, + port=port, + ) + + +class _send: + def __init__( + self, + notifications: List[str], + server: str, + nickname: str, + port: int, + channel: str, + password: Optional[str] = None, + use_ssl: bool = True, + ) -> None: + self.notifications = notifications + self.channel = channel + + ssl_factory = None + if use_ssl: + ssl_factory = Factory(wrapper=ssl.wrap_socket) + reactor = Reactor() + try: + s = reactor.server() + c = s.connect( + server, port, nickname, password=password, connect_factory=ssl_factory + ) + except ServerConnectionError as e: + print(f"error sending irc notification {e}") + return + + c.add_global_handler("welcome", self.on_connect) + c.add_global_handler("join", self.on_join) + c.add_global_handler("disconnect", self.on_disconnect) + + try: + reactor.process_forever() + except Exit: + pass + + def on_connect(self, connection: Connection, event: Event) -> None: + if is_channel(self.channel): + connection.join(self.channel) + return + self.main_loop(connection) + + def on_join(self, connection: Connection, event: Event) -> None: + self.main_loop(connection) + + def on_disconnect(self, connection: Connection, event: Event) -> None: + raise Exit() + + def main_loop(self, connection: Connection) -> None: + for notification in self.notifications: + connection.privmsg(self.channel, notification) + connection.quit("Bye") diff --git a/release.nix b/release.nix index e5840565b..0fcf5fee9 100644 --- a/release.nix +++ b/release.nix @@ -6,6 +6,8 @@ python3Packages.buildPythonApplication { name = "nur"; src = ./.; + propagatedBuildInputs = [ python3Packages.irc ]; + makeWrapperArgs = [ "--prefix" "PATH" ":" "${stdenv.lib.makeBinPath [ nix-prefetch-git git nix ]}" "--set" "LOCALE_ARCHIVE" "${glibcLocales}/lib/locale/locale-archive" diff --git a/setup.py b/setup.py index 4332d5454..431d30867 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,7 @@ setup( license="MIT", packages=find_packages(), entry_points={"console_scripts": ["nur = nur:main"]}, + install_requires=["irc"], extras_require={"dev": ["mypy", "flake8>=3.5,<3.6", "black"]}, classifiers=[ "Development Status :: 5 - Production/Stable",