]> andersk Git - jira-zephyrbot.git/blob - jirabot.py
9d36e910f01bacb6cc2e11d96fc2203e1e20dbda
[jira-zephyrbot.git] / jirabot.py
1 #!/usr/bin/python
2 import cStringIO
3 import calendar
4 import feedparser
5 import formatter
6 import htmllib
7 import mechanize
8 import os
9 import random
10 import string
11 import time
12 import traceback
13 import urlparse
14 import zephyr
15
16 zephyr_sender = 'jira'
17 zephyr_class = 'andersk-test'
18 time_file = 'jirabot.time'
19
20 def jira_init():
21     b = mechanize.Browser()
22     b.set_handle_robots(False)
23     b.add_client_certificate("https://idp.mit.edu:9443", "cert.pem", "cert.pem")
24     b.addheaders = [("Accept-Language", "en-us,en;q=0.5"),]
25     return b
26
27 def jira_login(b):
28     b.open("https://jira.mit.edu/jira/secure/Dashboard.jspa")
29     b.follow_link(text="MIT Touchstone")
30     b.select_form("wayfForm1")
31     b.submit()
32     b.select_form(predicate=lambda f: any(c.name == 'login_certificate'
33                                           for c in f.controls))
34     b.submit()
35     b.select_form(nr=0)
36     b.submit()
37
38 def parse_issue(e):
39     issue = urlparse.urlparse(e.id)[2].rsplit('/', 1)[1]
40     url = e.id
41     msg = e.id + "\nThis issue was updated."
42
43     return zephyr.ZNotice(
44         sender=zephyr_sender,
45         auth=False,
46         cls=zephyr_class,
47         instance=issue,
48         fields=[e.title, msg],
49     )
50
51 def parse_comment(e):
52     url = urlparse.urlunsplit(urlparse.urlparse(e.id)[0:3] + (None,None))
53     issue = url.rsplit('/', 1)[1]
54
55     s = cStringIO.StringIO()
56     parser = htmllib.HTMLParser(formatter.AbstractFormatter(formatter.DumbWriter(s)))
57     parser.feed(e.summary.rsplit('<table>', 1)[0])
58     parser.close()
59     s.seek(0)
60     comment = s.read()
61
62     msg = e.author + " added a comment:\n" + comment.rstrip()
63
64     return zephyr.ZNotice(
65         sender=zephyr_sender,
66         auth=False,
67         cls=zephyr_class,
68         instance=issue,
69         fields=[e.title, msg],
70     )
71
72 def zerror(msg):
73     return zephyr.ZNotice(
74         sender=zephyr_sender,
75         auth=False,
76         cls=zephyr_class,
77         instance='jira-error',
78         fields=['Jira bot error', msg]
79     )
80
81 b = jira_init()
82
83 jira_login(b)
84 b.open("https://jira.mit.edu/jira/sr/jira.issueviews:searchrequest-rss/temp/SearchRequest.xml?&pid=10185&updated%3Aprevious=-1w&sorter/field=updated&sorter/order=DESC&tempMax=1000")
85 issues_rss = b.response().read()
86 b.open("https://jira.mit.edu/jira/sr/jira.issueviews:searchrequest-comments-rss/temp/SearchRequest.xml?&pid=10185&updated%3Aprevious=-1w&sorter/field=updated&sorter/order=DESC&tempMax=1000")
87 comments_rss = b.response().read()
88
89 time_file_new = time_file + '.' + ''.join(random.sample(string.letters, 8))
90
91 try:
92     os.rename(time_file, time_file_new)
93 except OSError:
94     exit()
95
96 old_time = int(open(time_file_new).read())
97 new_time = old_time
98
99 zephyr.init()
100 zephyrs = []
101
102 for (thing, rss, parse) in [('issue', issues_rss, parse_issue),
103                             ('comment', comments_rss, parse_comment)]:
104     try:
105         feed = feedparser.parse(rss)
106         for e in feed.entries:
107             t = int(calendar.timegm(e.date_parsed))
108             if t <= old_time:
109                 continue
110             if t > new_time:
111                 new_time = t
112             try:
113                 z = parse(e)
114             except:
115                 z = zerror("Error parsing " + thing + ":\n" + e.id + "\n" + traceback.format_exc())
116             zephyrs.append((t, z))
117     except:
118         zephyrs.append((0, zerror("Error parsing " + thing + "s feed:\n" + traceback.format_exc())))
119
120 open(time_file_new, 'w').write(str(new_time))
121
122 os.rename(time_file_new, time_file)
123
124 zephyrs.sort(key=lambda tz: tz[0])
125 for (t, z) in zephyrs:
126     z.send()
This page took 0.031224 seconds and 3 git commands to generate.