#!/usr/bin/env python3 """ simple client for que.run """ import argparse import configparser import http.client import os import subprocess import sys import time import urllib.parse import urllib.request as request MAX_TIMEOUT = 99999999 # basically never timeout def auth(): conf_file = os.path.expanduser("~/.config/que.conf") if not os.path.exists(conf_file): sys.exit("you need a ~/.config/que.conf") cfg = configparser.ConfigParser() cfg.read(conf_file) return cfg def send(args): "Send a message to the que." ns = args.target.split("/")[0] key = auth()[ns]["key"] data = args.infile.read().encode("utf-8").strip() req = request.Request(f"{args.host}/{args.target}") req.add_header("User-AgenT", "Que/Client") if key: req.add_header("Authorization", key) if args.serve: while not time.sleep(1): request.urlopen(req, data=data, timeout=MAX_TIMEOUT) else: request.urlopen(req, data=data, timeout=MAX_TIMEOUT) def recv(args): "Receive a message from the que." ns = args.target.split("/")[0] key = auth()[ns]["key"] def _recv(_req): msg = _req.readline().decode("utf-8").strip() print(msg) if args.then: subprocess.run( args.then.replace("\msg", msg).replace("\que", args.target), shell=True ) params = urllib.parse.urlencode({"poll": args.poll}) req = request.Request(f"{args.host}/{args.target}?{params}") req.add_header("User-Agent", "Que/Client") if key: req.add_header("Authorization", key) with request.urlopen(req) as _req: if args.poll: while not time.sleep(1): _recv(_req) else: _recv(_req) def get_args(): cli = argparse.ArgumentParser(description=__doc__) cli.add_argument( "--host", default="http://que.run", help="where que-server is running" ) cli.add_argument( "--poll", default=False, action="store_true", help="stream data from the que" ) cli.add_argument( "--then", help=" ".join( [ "when polling, run this shell command after each response,", "presumably for side effects," "replacing '\que' with the target and '\msg' with the body of the response", ] ), ) cli.add_argument( "--serve", default=False, action="store_true", help=" ".join( [ "when posting to the que, do so continuously in a loop.", "this can be used for serving a webpage or other file continuously", ] ), ) cli.add_argument( "target", help="namespace and path of the que, like 'ns/path/subpath'" ) cli.add_argument( "infile", nargs="?", type=argparse.FileType("r"), help="data to put on the que. Use '-' for stdin, otherwise should be a readable file", ) return cli.parse_args() if __name__ == "__main__": args = get_args() try: if args.infile: send(args) else: recv(args) except KeyboardInterrupt: sys.exit(0) except urllib.error.HTTPError as e: print(e) sys.exit(1) except http.client.RemoteDisconnected as e: print("disconnected... retrying in 5 seconds") time.sleep(5) if args.infile: send(args) else: recv(args)