You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
5.2 KiB
Python

import json
import os
import signal
import socket
import subprocess
import code128
from lxml import etree
from bureau import Bureau, add_command, add_api
def clean_svg(svg):
"""
This is a little hack that removes the height and width attributes from
SVG strings as they confuse Firefox. Sigh... hopefully this can go away
some day.
"""
utf8_parser = etree.XMLParser(encoding='utf-8')
svg = svg.encode("utf-8")
otree = etree.fromstring(svg, utf8_parser)
del otree.attrib["height"]
del otree.attrib["width"]
clean_svg = etree.tostring(otree)
return clean_svg.decode("utf-8")
class InhumanResources(Bureau):
"""
This is a core functional bureau of the Screenless office it keeps track
of all published methods provided by all other bureaus and can print
the menu for the whole system or an individual item
"""
name = "Inhuman Resources"
prefix = "IR"
version = 0
def __init__(self):
Bureau.__init__(self)
self.menu = {}
# update_commands(self)
@add_api("addbureau", "Register Bureau")
def add_bureau(self, data):
"""
Register Bureau with Inhuman Resources
data = { prefix: "IR",
name: "Inhuman Resources",
desc: "Keep track of public resources provided by bureaus"
}
"""
try:
name = data["name"]
prefix = data["prefix"]
desc = data["desc"]
except KeyError as e:
print("cannot add invalid bureau:", str(e))
return str(e)
print("added menu")
self.menu[prefix] = {"name": name,
"desc": desc,
"commands": {},
"apis": {}}
@add_api("addcommand", "Register Command")
def add_cmd(self, data):
try:
prefix = data["prefix"]
cmd = data["cmd"]
cmdname = data["cmdname"]
desc = data["desc"]
cmd_code = prefix + cmd + "."
barcode = clean_svg(code128.svg(prefix + cmd + "."))
barcode_png = os.path.join(self.datadir, cmd_code + "png")
code128.image(cmd_code).save(barcode_png)
barcode_png = str(barcode_png)
except KeyError as e:
print("cannot add invalid command:", str(e))
return
if prefix not in self.menu:
# TODO: this should throw some kind of error message/log
print("error: cannot add command ", cmd, "to non-existent prefix",
prefix)
else:
self.menu[prefix]["commands"][cmd] = {"name": cmdname,
"desc": desc,
"barcode": barcode,
"barcode_png": barcode_png}
@add_api("addapi", "Register API Method")
def add_api_method(self, data):
try:
prefix = data["prefix"]
cmd = data["api"]
cmdname = data["apiname"]
desc = data["desc"]
except KeyError as e:
print("cannot add invalid command:", str(e))
return
if prefix not in self.menu:
# TODO: this should throw some kind of error message/log
print("error: cannot add command ", cmd, "to non-existent prefix",
prefix)
else:
self.menu[prefix]["apis"][cmd] = {"name": cmdname,
"desc": desc}
@add_command("menu", "Print Menu")
def print_menu(self):
"""
Prints the menu of commands for all operational bureaus.
"""
self.print_full("menu.html", menu=self.menu)
@add_command("getmyip", "Print Office IP Address")
def print_my_ip(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect(("8.8.8.8", 80))
self.print_small("This Screenless Office currently resides at:\r\n" +
sock.getsockname()[0] + "\r\n")
sock.close()
@add_command("update", "Restructure Organization")
def update(self):
"""
Restructure the organization. This may include firing, hiring,
refinancing and organizational changes. This will update the
Office to the latest software but it may be disruptive to your
current personal and social situation. After pulling the latest
updates, all bureaus other than management will be restarted.
"""
subprocess.call("git pull")
self.restart()
@add_command("restart", "Furlough")
def restart(self):
"""
Send the entire organization on a very short unpaid vacation. This
will restart all bureaus, so it may cause disruption, loss of work
and other psycho-social side effects of a loss of state. It may
also help restore a messed up office to normal operation.
"""
# TODO: find the PID of mgmt and send it a HUP signal
with open("mgmt.pid") as pfile:
pid = int(pfile.read())
os.kill(pid, signal.SIGHUP)
def main():
hr = InhumanResources()
hr.run()
if __name__ == "__main__":
hr = InhumanResources()
hr.run()