diff --git a/screenless/bureau/mailroom.py b/screenless/bureau/mailroom.py deleted file mode 100644 index fd07a3d..0000000 --- a/screenless/bureau/mailroom.py +++ /dev/null @@ -1,50 +0,0 @@ -import twitter - -from bureau import Bureau, add_command, add_api - - -class MailRoom(Bureau): - """ - The Mail Room handles (electronic) post for the other Bureaus of - the Screenless Office. - """ - - name = "Mail Room" - prefix = "PS" - version = 0 - - def __init__(self): - Bureau.__init__(self) - - @add_command("fax", "Send a Document Camera Image via Email") - def fax(self, to_id): - """ - Takes a photograph using the document camera and sends it in an E-mail. - """ - callback = self.prefix + "fax." - args = {"to_id": to_id} - self.send("PXphoto.", {"callback": callback, "cb_args": args}) - - @add_api("tweetpic_cb", "callback for tweet_pic") - def tweetpic_cb(self, data): - """ - This does the actual uploading of the picture. - """ - photo = data["photo"] - auth = twitter.OAuth( - "423391766-bhjHwzD1eJfxB9s7ZvmeHReNVJM0d93kJ8KSrHEZ", - "qSvSYMs4lpSKbZtiuOjB1Gon5rzye8whvadcOdDpFocwa", - "arI4UCnfMeKZwAnyvJJIHVnUN", - "agrtzvh3eqSNlZpmPJZ0otclqSUjLKI3JrqugCPrp1Ch9dqsTl") - t = twitter.Twitter(auth=auth) - - with open(photo, "rb") as imagefile: - imagedata = imagefile.read() - t_up = twitter.Twitter(domain='upload.twitter.com', auth=auth) - id_img1 = str(t_up.media.upload(media=imagedata)["media_id"]) - t.statuses.update(status="PTT ★", media_ids=id_img1) - - -if __name__ == "__main__": - pr = PublicRelations() - pr.run() diff --git a/screenless/bureau/mailroom/__init__.py b/screenless/bureau/mailroom/__init__.py new file mode 100644 index 0000000..76788bf --- /dev/null +++ b/screenless/bureau/mailroom/__init__.py @@ -0,0 +1,4 @@ +from . import mailroom + +def main(): + ihr.main() diff --git a/screenless/bureau/mailroom/mailroom.py b/screenless/bureau/mailroom/mailroom.py new file mode 100644 index 0000000..e904e9d --- /dev/null +++ b/screenless/bureau/mailroom/mailroom.py @@ -0,0 +1,90 @@ +import email.header + +import imapclient + +from bureau import Bureau, add_command, add_api + + +class MailRoom(Bureau): + """ + The Mail Room handles (electronic) post for the other Bureaus of + the Screenless Office. + """ + + name = "Mail Room" + prefix = "PO" + version = 0 + + def __init__(self): + Bureau.__init__(self) + # TODO: multiple accounts / folders + if "user" in self.config: + self.login = self.config["user"]["login"] + self.password = self.config["user"]["password"] + self.host = self.config["user"]["host"] + self.imapserv = imapclient.IMAPClient(self.host, use_uid=True, ssl=True) + self.imapserv.login(self.login, self.password) + self.imapserv.select_folder("INBOX") + else: + print("you need to configure an IMAP account!") + print("add a [user] section to PO.ini with:") + print(" login = mylogin") + print(" password = mypassword") + print(" host = my.imap.server.address.com") + + @add_command("fax", "Send a Document Camera Image via Email") + def fax(self, data): + """ + Takes a photograph using the document camera and sends it in an E-mail. + """ + self.send("PXphoto.") + + @add_command("rd", "Print full email") + def read(self, data): + """ + Prints out the full detailed version of an email. + """ + pass + + @add_command("d", "Delete email") + def delete(self, data): + """ + Deletes an email and moves it to the trash folder. + """ + pass + + @add_command("s", "Mark as spam") + def mark_spam(self, data): + """ + Flags an email as spam, mark as read and move it to the configured SPAM + folder. + """ + pass + + @add_command("re", "Reply with scan") + def reply_scan(self, data): + """ + Reply to the sender of a mail with the PDF currently queued in the + document scanner. + """ + pass + + @add_api("unread", "Get unread mails") + def unread(self): + """ + Polls the currently configured IMAP server and returns a dict + containing unread emails. + """ + messages = self.imapserv.sort("ARRIVAL", ["UNSEEN"]) + print("%d unread messages in INBOX" % len(messages)) + return self.imapserv.fetch(messages, ['FLAGS', 'INTERNALDATE', + 'ENVELOPE', 'RFC822.SIZE']) + + +def main(): + mr = MailRoom() + mr.run() + + +if __name__ == "__main__": + main() diff --git a/screenless/bureau/publications/__init__.py b/screenless/bureau/publications/__init__.py new file mode 100644 index 0000000..d60146d --- /dev/null +++ b/screenless/bureau/publications/__init__.py @@ -0,0 +1,4 @@ +from . import publications + +def main(): + publications.main() diff --git a/screenless/bureau/publications/publications.py b/screenless/bureau/publications/publications.py new file mode 100644 index 0000000..83ae581 --- /dev/null +++ b/screenless/bureau/publications/publications.py @@ -0,0 +1,68 @@ +import json +import os + +import PIL + +from bureau import Bureau, add_command, add_api + + +class Publications(Bureau): + """ + The Publications Office serves as a kind of screenless content management + system. Create, update and organize your sites while doing most of the work + on paper or anything you can photograph. + """ + + name = "Publications Office" + prefix = "PB" + version = 0 + + def __init__(self): + Bureau.__init__(self) + self.db = os.path.expanduser("~/.screenless/PB.data") + if not os.path.exists(self.db): + os.mkdir(self.db) + + + @add_command("new", "Create a new Publication/Site") + def new_site(self): + """ + Create a new Publication/Site, set up config and tace a picture from + the document camera as the index page. Finally, it will print out + the main page with commands for working with the site. + """ + site_dir = os.path.join(self.db, "1") + site_id = 1 + while os.path.exists(site_dir): + site_id += 1 + site_dir = os.path.join(self.db, str(site_id)) + os.mkdir(site_dir) + + root_d = {"template": "default", "id": site_id} + with open(os.path.join(site_dir, "root.json", "w")) as root_json: + root_json.write(json.dumps(root_d)) + + photo = self.send("PX", "photo")["photo"] + + # TODO: come up with a generic set of img form operations for Bureau + # should map regions defined with percentages to names + form_img = PIL.Image.open(photo) + fx, fy = form_img.size + title_region = (0, 0, 0.5 * fx, 0.125 * fy) + title_img = form_img.crop(title_region) + content_region = (0, 0.125 * fy, fx, fy) + content_img = form_img.crop(content_region) + + def _update_page(self, site, page): + pass + + + + +def main(): + pb = Publications() + pb.run() + + +if __name__ == "__main__": + main() diff --git a/screenless/bureau/publicrelations/publicrelations.py b/screenless/bureau/publicrelations/publicrelations.py index df27ecf..4d0501e 100644 --- a/screenless/bureau/publicrelations/publicrelations.py +++ b/screenless/bureau/publicrelations/publicrelations.py @@ -36,8 +36,9 @@ class PublicRelations(Bureau): with open(photo, "rb") as imagefile: imagedata = imagefile.read() t_up = twitter.Twitter(domain='upload.twitter.com', auth=self.auth) - id_img1 = str(t_up.media.upload(media=imagedata)["media_id"]) - self.t.t.statuses.update(status="#screenlessoffice ", media_ids=id_img1) + + id_img1 = t_up.media.upload(media=imagedata)["media_id_string"] + self.t.t.statuses.update(status="#screenless", media_ids=id_img1) @add_command("twtimeline", "Print Recent Tweets") def tw_timeline(self, data=None): diff --git a/screenless/bureau/sales/__init__.py b/screenless/bureau/sales/__init__.py new file mode 100644 index 0000000..ca1a261 --- /dev/null +++ b/screenless/bureau/sales/__init__.py @@ -0,0 +1,4 @@ +from . import sales + +def main(): + sales.main() diff --git a/screenless/bureau/sales/makecodes.py b/screenless/bureau/sales/makecodes.py new file mode 100644 index 0000000..e8db235 --- /dev/null +++ b/screenless/bureau/sales/makecodes.py @@ -0,0 +1,11 @@ +import random +import string + +import code128 + +chars = string.ascii_letters + string.digits +for code in range(30): + code = ''.join(random.choice(chars) for _ in range(5)) + code = "SAp." + code + with open("/tmp/" + code + ".svg", "w") as f: + f.write(code128.svg(code, caption=True)) diff --git a/screenless/bureau/sales/sales.py b/screenless/bureau/sales/sales.py new file mode 100644 index 0000000..dea4538 --- /dev/null +++ b/screenless/bureau/sales/sales.py @@ -0,0 +1,43 @@ +import glob +import os +import subprocess + +from bureau import Bureau, add_command + + +class Sales(Bureau): + """ + The sales department makes presentations to potential customers. + """ + + name = "Sales Office" + prefix = "SA" + version = 0 + + def __init__(self): + Bureau.__init__(self) + try: + self.db = os.mkdir("SA") + except FileExistsError: + pass # we've already got a db folder + + @add_command("p", "Play Media") + def print_fortune(self, data): + """ + Shows media on a connected projector or plays audio. + """ + searchpath = "SA/SAp." + data + "*" + print("looking in ", searchpath) + mediapath = glob.glob(searchpath)[0] + print("playing", mediapath) + cli = ["mplayer", "-fs", mediapath] + jux = subprocess.Popen(cli) + + +def main(): + sa = Sales() + sa.run() + + +if __name__ == "__main__": + main() diff --git a/screenless/bureau/typing.py b/screenless/bureau/typing.py index 53a3729..b4cc961 100644 --- a/screenless/bureau/typing.py +++ b/screenless/bureau/typing.py @@ -8,7 +8,7 @@ KEYS = { 20: u't', 21: u'y', 22: u'u', 23: u'i', 24: u'o', 25: u'p', 26: u'[', 27: u']', 28: u'\n', 29: u'LCTRL', 30: u'a', 31: u's', 32: u'd', 33: u'f', 34: u'g', 35: u'h', 36: u'j', 37: u'k', 38: u'l', 39: u';', 40: u'"', 41: u'`', 42: u'LSHFT', 43: u'\\', 44: u'z', 45: u'x', 46: u'c', 47: u'v', 48: u'b', 49: u'n', - 50: u'm', 51: u',', 52: u'', 53: u'/', 54: u'RSHFT', 56: u'LALT', 100: u'RALT' + 50: u'm', 51: u',', 52: u'.', 53: u'/', 54: u'RSHFT', 56: u'LALT', 100: u'RALT' } @@ -29,13 +29,12 @@ class TypingPool(Bureau): self.devices = [] self.active_devices = [] - # add anything that smells like a keyboard and grab focus + # add anything that smells like a keyboard for dev in devices: try: if evdev.ecodes.KEY_A in dev.capabilities()[evdev.ecodes.EV_KEY]: print(dir(dev)) print(dev.fn) - # dev.grab() self.devices.append(dev) except KeyError as err: print("ignoring non-keyboard device: " + str(dev))