Example #1
0
def twitter_context(arg):
   import json
   import urllib
   from util import rfc3339
   import datetime

   import twitter
   from twitter import format_tweet

   if "arg" not in arg["qs"] and arg["oauth"] == False:
      err(noarg)

   _default(arg, "oauth", False)
   _default(arg, "token_name", None)
   _default(arg, "infinite_retries", True)
   _default(arg, "source_filter", False)

   p = twitter.Twitter(db=arg["cursor"], oauth=arg["oauth"], token_name=arg["token_name"], infinite_retries=arg["infinite_retries"])

   if "mentions" in arg and arg["mentions"] == True:
      tweets = p.mentions()
      uname = p.me().screen_name
   else:
      uname = arg["qs"]["arg"]
      tweets = p.user_timeline(uname)

   tweet_cache = {}
   for tweet in tweets:
      tweet_cache[tweet.id] = tweet

   rval = {"id": "http://twitter.com/%s#atom_maker_context_feed" % uname,
           "link": "http://twitter.com/%s" % uname,
           "title": "Twitter / %s / context" % uname,
           "author": tweets[0].user.name,
           "entries": []}

   if 'lang' in arg["qs"]:
      rval["lang"] = arg["qs"]['lang']

   parent_skip_list = set()
   for tweet in tweets:
      if tweet.id in parent_skip_list:
         continue
      if arg["source_filter"] and tweet.source in arg["source_filter"]:
         continue

      content = []
      tweet_url = "http://twitter.com/%s/status/%s" % (tweet.user.screen_name, tweet.id_str)

      entry = {"id": tweet_url,
               "title": "%s: " % tweet.user.screen_name + tweet.text,
               "content_type": "html",
               "updated": rfc3339(tweet.created_at),
               "link": tweet_url}
      content.append(format_tweet(tweet.user.screen_name, tweet.user.name, tweet.text, tweet_url, tweet.created_at))
      parent_id = tweet.in_reply_to_status_id
      while parent_id:
         if parent_id in tweet_cache:
            parent_tweet = tweet_cache[parent_id]
         else:
            try:
               parent_tweet = p.get_tweet(parent_id)
            except:
               break
            tweet_cache[parent_id] = parent_tweet

         # don't make a new RSS entry for tweets in a conversation chain
         if parent_tweet.user.id == tweet.user.id:
            parent_skip_list.add(parent_tweet.id)

         content.append(format_tweet(parent_tweet.user.screen_name, parent_tweet.user.name, parent_tweet.text, "http://twitter.com/%s/status/%s" % (parent_tweet.user.screen_name, parent_id), parent_tweet.created_at))

         # continue to next parent or terminate
         parent_id = parent_tweet.in_reply_to_status_id
      entry["content"] = "".join(reversed(content))
      rval["entries"].append(entry)
   rval["updated"] = rval["entries"][0]["updated"] # first tweet is newest
   return rval
Example #2
0
def create_atom(feed):
   """Validates the generator output and creates the ATOM feed"""
   root = etree.Element("feed", attrib={"xmlns": "http://www.w3.org/2005/Atom"})

   esc = cgi.escape

   ts = rfc3339(now)

   if not isinstance(feed, dict):
      err("Your generator forgot to return a dict.")
   if not "title" in feed:
      err("The feed lacks a title.")
   if not "id" in feed:
      err("The feed lacks a UUID.")
   if not "updated" in feed:
      feed["updated"] = ts
   if not "entries" in feed:
      err("The feed lacks entries.")

   if 'lang' in feed:
      root.set(etree.QName("{http://www.w3.org/XML/1998/namespace}lang"), feed["lang"])

   child_tag(root, "title", text=feed["title"])
   child_tag(root, "id", text=feed["id"])
   child_tag(root, "updated", text=feed["updated"])
   if "author" in feed:
      author = child_tag(root, "author")
      child_tag(author, "name", text=feed["author"])
      if "author_uri" in feed:
         child_tag(author, "uri", feed["author_uri"])
   if "subtitle" in feed:
      child_tag(root, "subtitle", text=feed["subtitle"])
   if "link" in feed:
      child_tag(root, "link", attrib={'href': feed["link"]})
   child_tag(root, "generator", attrib={"uri": "https://github.com/dgilman/atom_maker", "version": str(VERSION)}, text="atom_maker")
   child_tag(root, "link", attrib={"rel": "self", "href": self_url()})

   #validate individual entries.

   check_for_authors = False
   if not "author" in feed:
      check_for_authors = True

   for entry in feed["entries"]:
      if check_for_authors and not "author" in entry:
         err("One of the feed entries lacks an author.  If there is no global author set each feed needs its own author.")
      if not "id" in entry:
         err("An entry lacks a UUID.")
      if not "title" in entry:
         err("An entry lacks a title.")
      if not "content" in entry:
         err("An entry lacks content.")
      if not "content_type" in entry:
         err("All entries need a content_type.")
      if entry["content_type"] not in ["html", "text", "xhtml"]:
         err("content_type must be one of html, text, or html.")
      if not "updated" in entry:
         entry["updated"] = ts

      e = child_tag(root, "entry")
      if "lang" in entry:
         e.set(etree.QName("{http://www.w3.org/XML/1998/namespace}lang"), feed["lang"])
      child_tag(e, "id", text=entry["id"])
      child_tag(e, "title", text=entry["title"])
      child_tag(e, "content", attrib={"type": entry["content_type"]}, text=entry["content"])
      child_tag(e, "updated", text=entry["updated"])

      if "author" in entry:
         author = child_tag(e, "author")
         child_tag(author, "name", text=entry["author"])
         if "author_uri" in entry:
            child_tag(author, "uri", text=entry["author_uri"])
      if "published" in entry:
         child_tag(e, "published", text=entry["published"])
      if "link" in entry:
         child_tag(e, "link", attrib={"href": entry["link"]})
   rval = cStringIO.StringIO()
   tree = etree.ElementTree(element=root)
   if sys.version_info < (2, 7):
      tree.write(rval, encoding="UTF-8")
   else:
      tree.write(rval, encoding="UTF-8", xml_declaration=True)
   return rval.getvalue()
Example #3
0
def _bz_xmlrpc(arg):
   """arg: bug id as string
   url: path to bugzilla installation
   history: put history changes in feed (optional, default true)
   ccs: include cc changes in history (optional, default false)"""
   import xmlrpclib
   import sqlite3
   import datetime
   import re
   now = datetime.datetime.utcnow()
   from util import rfc3339
   from util import warn_old

   if "arg" not in arg["qs"]:
      err(noarg)

   try:
      int(arg['qs']['arg'])
   except:
      err("Bug IDs must be numerical.")

   if not "history" in arg["qs"]: # the default
      history = True
   else:
      if arg["qs"]["history"][0] in "Ff0":
         history = False
      else:
         history = True

   if not "ccs" in arg["qs"]:
      ccs = False
   else:
      if arg["qs"]["ccs"][0] in "Ff0":
         ccs = False
      else:
         ccs = True

   _default(arg, 'warn_old', True)

   url = arg["url"]
   bugid = arg["qs"]["arg"]
   p = xmlrpclib.ServerProxy(url + "/xmlrpc.cgi", use_datetime=True)

   try:
      bugdata = p.Bug.get({"ids":[bugid], "permissive": True})
   except:
      err(badfetch)
   if len(bugdata['faults']) > 0: err(bugdata['faults'][0]['faultString'])
   bugdata = bugdata["bugs"][0]

   guid = '%s/show_bug.cgi?id=%s' % (url, str(bugdata['id'])) # get the ID in case the query string used the bug alias
   rval = {"id": guid,
           "link": guid,
           "updated": rfc3339(bugdata['last_change_time']),
           "title": "Bug %s - " % bugid + bugdata['summary'],
           "entries": []}

   if "lang" in  arg["qs"]:
      rval["lang"] = arg["qs"]["lang"]

   try:
      bugcomments = p.Bug.comments({"ids":[bugid]})["bugs"][bugid]['comments']
   except:
      err(badfetch)

   commenting_users = [x['author'] for x in bugcomments]
   if history:
      try:
         bug_history = p.Bug.history({"ids":[bugid]})['bugs'][0]['history']
      except:
         err(badfetch)
      commenting_users.extend([h['who'] for h in bug_history])

   c = arg["cursor"]
   c.executescript("""pragma temp_store = MEMORY;
create temp table email_queries (email text unique);""")
   c.execute("insert or ignore into bugzillas (id, url) values (NULL, ?)", (url,))
   bz_id = c.execute("select id from bugzillas where url = ?", (url,)).fetchall()[0][0]
   c.execute("delete from bugzilla_users where ts <= ?", (now.year*100 + now.month - 1,))

   c.executemany("insert or ignore into email_queries (email) values (?)", ((e,) for e in commenting_users))
   cache_misses = c.execute("select email from email_queries where not exists (select 1 from bugzilla_users where bugzilla_users.bz = ? and bugzilla_users.email = email_queries.email)", (bz_id,)).fetchall()
   if len(cache_misses) > 0:
      try:
         real_names = p.User.get({"names": [e[0] for e in cache_misses]})["users"]
      except:
         err(badfetch)
      for user in real_names:
         if len(user['real_name']) != 0:
            rn = user['real_name']
         else:
            rn = user['name']
         c.execute("insert into bugzilla_users (email, name, ts, bz) values (?, ?, ?, ?)", (user['name'], rn, now.year*100 + now.month, bz_id))

   rn = lambda x: c.execute("select name from bugzilla_users where bz = ? and email = ?", (bz_id, x)).fetchall()[0][0]

   if history:
      for bug_history_change_no, bug_history_change in enumerate(bug_history):
          # don't even create an rss entry if cc is the only thing that's changed and we're ignoring ccs
          if len(bug_history_change['changes']) == 1 and bug_history_change['changes'][0]['field_name'] == 'cc' and ccs == False:
             continue
          history_id = guid + "#h" + str(bug_history_change_no)

          content = ['<pre style="white-space:pre-wrap">']
          for field_change in bug_history_change['changes']:
             if field_change['field_name'] == 'cc' and ccs == False:
                continue
             content.append("Field <b>%s</b>:\n" % field_change['field_name'])
             if field_change['field_name'] == 'attachments.isobsolete':
                content.append('<a href="%s/attachment.cgi?id=%d">Attachment #%d</a> is obsolete\n' % (url, field_change['attachment_id'], field_change['attachment_id']))
             if field_change['field_name'] in ['dependson', 'blocked']:
                sub = lambda f: re.sub("(\d+)", lambda m: '<a href="%s/show_bug.cgi?id=%s">%s</a>' % (url, m.group(1), "Bug " + m.group(1)), f)
                if 'added' in field_change:
                   field_change['added'] = sub(field_change['added'])
                if 'removed' in field_change:
                   field_change['removed'] = sub(field_change['removed'])
             content.append("Removed:\n")
             content.append("     %s\n" % field_change['removed'])
             content.append("Added:\n")
             content.append("     %s\n\n" % field_change['added'])
          content.append("</pre>")

          real_name = rn(bug_history_change['who'])
          when = rfc3339(bug_history_change['when'])
          entry = {"id": history_id,
                   "title": "%s changed at %s" % (real_name, when),
                   "author": real_name,
                   "updated":  when,
                   "published": bug_history_change['when'], # keep for sorting
                   "link": history_id,
                   "content": "".join(content),
                   "content_type": "html"}
          rval["entries"].append(entry)

   linkbugs = lambda x: re.sub("([Bb])ug (\d+)", lambda m: '<a href="%s/show_bug.cgi?id=%s">%s</a>' % (url, m.group(2), m.group(1) + "ug " + m.group(2)), x)
   for comment_no, comment in enumerate(bugcomments):
      comment_id = guid + "#c" + str(comment_no)
      real_name = rn(comment['author'])
      comment_time_str = rfc3339(comment['time'])
      entry = {"id": comment_id,
               "title": u"Comment %s - %s - %s" % (str(comment_no), real_name, comment_time_str),
               "content": '<pre style="white-space:pre-wrap">' + linkbugs(comment['text']) + "</pre>",
               "content_type": "html",
               "author": real_name,
               "updated": comment_time_str,
               "published": comment['time'], # keep for sorting
               "link": comment_id}
      rval["entries"].append(entry)

   rval["entries"].sort(key=lambda e: e["published"])
   for entry in rval["entries"]:
      entry["published"] = rfc3339(entry["published"])

   if arg["warn_old"] and bugdata['last_change_time'] < (now - datetime.timedelta(days=365)):
      rval["entries"].append(warn_old(guid, bugid))

   return rval