Created
August 4, 2012 17:37
-
-
Save sbp/3258877 to your computer and use it in GitHub Desktop.
WhitsBot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sys, os.path, re, json, time, shutil, cgi | |
from htmlentitydefs import name2codepoint | |
sys.path.append( | |
os.path.expanduser("~/usr/opt/python-packages") | |
) | |
from twitter import Twitter, OAuth | |
now = time.gmtime() | |
year = time.strftime("%Y", now) | |
whits = os.path.expanduser("~/inamidst.com/whits") | |
config = os.path.expanduser("~/.whitsbot") | |
def get_auth_data(): | |
with open(config) as f: | |
config_data = json.load(f) | |
return ( | |
config_data["access_token"], | |
config_data["access_secret"], | |
config_data["consumer_key"], | |
config_data["consumer_secret"] | |
) | |
def error(msg): | |
print >> sys.stderr, msg | |
sys.exit(1) | |
def get_entry_data(): | |
data = {} | |
if not len(sys.argv) == 2: | |
error("Expected one filename argument") | |
data["filename"] = sys.argv[1] | |
data["name"] = os.path.basename(data["filename"]).split('.', 1)[0] | |
if not os.path.exists(data["filename"]): | |
error("No such file: %s" % data["filename"]) | |
if not os.path.exists(config): | |
error("Can't find a ~/.whitsbot for Twitter authentication data") | |
with open(data["filename"]) as f: | |
bytes = f.read() | |
r_title = re.compile(r"<title>(.*?)</title>") | |
r_description = re.compile(r'content="(.*?)"') | |
m = r_title.search(bytes) | |
if m: data["title"] = m.group(1) | |
else: error("No title found in %s" % data["filename"]) | |
m = r_description.search(bytes) | |
if m: data["description"] = m.group(1) | |
else: error("No description found in %s" % data["filename"]) | |
if len(data["description"]) > 119: | |
error("Description is longer than maximum length of 119 characters") | |
if not "\n\n" in bytes: | |
error("No content found in %s" % data["filename"]) | |
data["content"] = bytes.split('\n\n', 1).pop() | |
return data | |
r_entity = re.compile(r'&([^;\s]+);') | |
def entity(match): | |
value = match.group(1).lower() | |
if value.startswith('#x'): | |
return unichr(int(value[2:], 16)) | |
elif value.startswith('#'): | |
return unichr(int(value[1:])) | |
elif name2codepoint.has_key(value): | |
return unichr(name2codepoint[value]) | |
return '[' + value + ']' | |
def decode(html): | |
return r_entity.sub(entity, html) | |
def publish_to_whits(entry): | |
destination = os.path.join(whits, year, entry["name"] + ".html") | |
shutil.move(entry["filename"], destination) | |
print "Published to", destination | |
def publish_to_feed(entry): | |
from StringIO import StringIO | |
s = StringIO() | |
print >> s, '<feed xmlns="http://www.w3.org/2005/Atom">' | |
print >> s, ' <title>Gallimaufry of Whits</title>' | |
print >> s, ' <link href="http://inamidst.com/whits/"/>' | |
print >> s, ' <id>tag:sbp.so,2011:inamidst.com/whits</id>' | |
print >> s, ' <author><name>Sean B. Palmer</name></author>' | |
updated = time.strftime("%Y-%m-%dT%H:%M:%SZ", now) | |
print >> s, ' <updated>%s</updated>' % updated | |
path = "/whits/%s/%s" % (year, entry["name"]) | |
print >> s, ' <entry xml:base="http://inamidst.com%s">' % path | |
print >> s, ' <id>tag:sbp.so,2011:inamidst.com%s</id>' % path | |
print >> s, ' <title>%s</title>' % entry["title"].replace('<', '<') | |
print >> s, ' <updated>%s</updated>' % updated | |
print >> s, ' <link href="http://inamidst.com%s"/>' % path | |
print >> s, ' <content type="html">%s</content>' % cgi.escape(entry["content"]) | |
print >> s, ' </entry>' | |
r_entry = re.compile(r"(?ims)(<entry.*?</entry>)") | |
feed = os.path.join(whits, "feed.atom") | |
with open(feed) as f: | |
entries = r_entry.findall(f.read()) | |
for entry in entries[:9]: | |
print >> s, ' ' + entry | |
print >> s, '</feed>' | |
s.seek(0) | |
with open(feed, "w") as w: | |
w.write(s.read()) | |
print "Updated", feed | |
def publish_to_twitter(entry): | |
description = decode(entry["description"]) | |
link = "http://inamidst.com/whits/%s/%s" % (year, entry["name"]) | |
status = description + " " + link | |
authentication = get_auth_data() | |
t = Twitter(auth=OAuth(*authentication)) | |
t.statuses.update(status=status) | |
print "Posted to @OfWhits:", status | |
def publish_entry(): | |
entry = get_entry_data() | |
publish_to_whits(entry) | |
publish_to_feed(entry) | |
publish_to_twitter(entry) | |
if __name__ == '__main__': | |
publish_entry() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment