Skip to content

Commit

Permalink
Add initial implementation of "po".
Browse files Browse the repository at this point in the history
Add initial implementation of "po", an application for sending
notifications using Pushover.
  • Loading branch information
damiendart committed Oct 13, 2024
1 parent 4d2638e commit 22b1ee9
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[{git-hometime,install,markdown-tidy,rpncalc,timeshit,*.py}]
[{git-hometime,install,markdown-tidy,po,rpncalc,timeshit,*.py}]
indent_size = 4

[toolbox.txt]
Expand Down
4 changes: 2 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ tasks:

lint:python:black:
cmds:
- '.venv/bin/black --check --diff install bin/git-hometime bin/markdown-tidy bin/rpncalc bin/timeshit'
- '.venv/bin/black --check --diff install bin/git-hometime bin/markdown-tidy bin/po bin/rpncalc bin/timeshit'
desc: 'Lint Python scripts with Black'

lint:python:flake8:
cmds:
- '.venv/bin/flake8 install bin/git-hometime bin/markdown-tidy bin/rpncalc bin/timeshit'
- '.venv/bin/flake8 install bin/git-hometime bin/markdown-tidy bin/po bin/rpncalc bin/timeshit'
desc: 'Lint Python scripts with Flake8'

lint:python:mypy:
Expand Down
111 changes: 111 additions & 0 deletions bin/po
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env python3
"""
A simple notification sender, using Pushover.
A configuration file at "$HOME/.config/toolbox/po.ini" is used to
provide Pushover API tokens:
[pushover]
application_key=APPLICATION_KEY_GOES_HERE
user_key=USER_KEY_GOES_HERE
"""

# This file was written by Damien Dart, <[email protected]>. This is
# free and unencumbered software released into the public domain. For
# more information, please refer to the accompanying "UNLICENCE" file.

import argparse
import configparser
import http.client
import os
import pathlib
import sys
import typing
import urllib.parse


CONFIG_DEFAULT = "{}/.config/toolbox/po.ini".format(pathlib.Path.home())


def fatal_error(message: str) -> None:
print(
"{}: error: {}".format(os.path.basename(sys.argv[0]), message),
file=sys.stderr,
)

raise SystemExit(1)


def main(arguments: argparse.Namespace, config: typing.List) -> None:
connection = http.client.HTTPSConnection("api.pushover.net:443")
connection.request(
"POST",
"/1/messages.json",
urllib.parse.urlencode(
{
"message": " ".join(arguments.message),
"title": arguments.title,
"token": config["application_key"],
"user": config["user_key"],
},
),
{"Content-Type": "application/x-www-form-urlencoded"},
)

response = connection.getresponse()
if response.status == 200:
return
else:
fatal_error('Pushover API responded with "{}"'.format(response.reason))


def parse_arguments(arguments: typing.List[str]) -> argparse.Namespace:
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
"message",
help="notification body",
nargs="*",
type=str,
default=sys.stdin,
)
parser.add_argument(
"--title",
help="notification title",
nargs="?",
type=str,
default="Wild notification appeared!",
)

return parser.parse_args(arguments)


def parse_config(config_file: str):
if not (os.path.isfile(config_file) and os.access(config_file, os.R_OK)):
fatal_error('unable to read config file "{}"'.format(config_file))

with open(config_file, "r") as f:
config_file = f.read()

config = configparser.ConfigParser()
config.read_string(config_file)

if not config.has_option("pushover", "application_key"):
fatal_error('missing "pushover.application_key" option in config file')

if not config.has_option("pushover", "user_key"):
fatal_error('missing "pushover.user_key" option in config file')

return {
"application_key": config.get("pushover", "application_key"),
"user_key": config.get("pushover", "user_key"),
}


if __name__ == "__main__":
arguments = parse_arguments(sys.argv[1:])
config = parse_config(CONFIG_DEFAULT)

main(arguments, config)

0 comments on commit 22b1ee9

Please sign in to comment.