]> andersk Git - jira-zephyrbot.git/blame - jirabot.py
Decrease interval to 20 seconds.
[jira-zephyrbot.git] / jirabot.py
CommitLineData
c3e3cdd9 1#!/usr/bin/python
c3e3cdd9
AK
2import calendar
3import feedparser
4import formatter
6a32ccab 5import htmlentitydefs
c3e3cdd9 6import htmllib
a41187bd 7import mechanize
c3e3cdd9
AK
8import os
9import random
10import string
6a32ccab 11import StringIO
c3e3cdd9
AK
12import time
13import traceback
14import urlparse
15import zephyr
16
17zephyr_sender = 'jira'
18zephyr_class = 'andersk-test'
19time_file = 'jirabot.time'
a41187bd 20
6a32ccab
AK
21class UnicodeHTMLParser(htmllib.HTMLParser):
22 entitydefs = dict((k, unichr(v)) for (k, v) in htmlentitydefs.name2codepoint.items())
23
24 def convert_charref(self, name):
25 try:
26 n = int(name)
27 except ValueError:
28 return
29 return self.convert_codepoint(n)
30
31 def convert_codepoint(self, codepoint):
32 return unichr(codepoint)
33
8b8cecc4
AK
34def jira_init():
35 b = mechanize.Browser()
36 b.set_handle_robots(False)
37 b.add_client_certificate("https://idp.mit.edu:9443", "cert.pem", "cert.pem")
38 b.addheaders = [("Accept-Language", "en-us,en;q=0.5"),]
39 return b
40
41def jira_login(b):
42 b.open("https://jira.mit.edu/jira/secure/Dashboard.jspa")
0ebeacca
AK
43 try:
44 b.follow_link(text="MIT Touchstone")
45 except mechanize.LinkNotFoundError:
46 return
47 if (urlparse.urlparse(b.geturl())[1] == "jira.mit.edu"):
48 return
8b8cecc4
AK
49 b.select_form("wayfForm1")
50 b.submit()
51 b.select_form(predicate=lambda f: any(c.name == 'login_certificate'
52 for c in f.controls))
53 b.submit()
54 b.select_form(nr=0)
55 b.submit()
c3e3cdd9 56
0344134a
AK
57def feed_to_zephyrs(thing, rss, parse):
58 zephyrs = []
59 try:
60 feed = feedparser.parse(rss)
61 for e in feed.entries:
62 global old_time, new_time
63 t = int(calendar.timegm(e.date_parsed))
64 if t <= old_time:
65 continue
66 if t > new_time:
67 new_time = t
68 try:
69 z = parse(e)
70 except:
71 z = zerror("Error parsing " + thing + ":\n" + e.id + "\n" + traceback.format_exc())
72 zephyrs.append((t, z))
73 except:
74 zephyrs.append((0, zerror("Error parsing " + thing + "s feed:\n" + traceback.format_exc())))
75 return zephyrs
76
c3e3cdd9
AK
77def parse_issue(e):
78 issue = urlparse.urlparse(e.id)[2].rsplit('/', 1)[1]
79 url = e.id
80 msg = e.id + "\nThis issue was updated."
81
82 return zephyr.ZNotice(
83 sender=zephyr_sender,
84 auth=False,
278c5c28 85 opcode='auto',
c3e3cdd9
AK
86 cls=zephyr_class,
87 instance=issue,
7f50f108 88 fields=[e.title, msg],
c3e3cdd9
AK
89 )
90
91def parse_comment(e):
92 url = urlparse.urlunsplit(urlparse.urlparse(e.id)[0:3] + (None,None))
93 issue = url.rsplit('/', 1)[1]
94
6a32ccab
AK
95 s = StringIO.StringIO()
96 parser = UnicodeHTMLParser(formatter.AbstractFormatter(formatter.DumbWriter(s)))
c3e3cdd9
AK
97 parser.feed(e.summary.rsplit('<table>', 1)[0])
98 parser.close()
6a32ccab 99 comment = s.getvalue()
c3e3cdd9
AK
100
101 msg = e.author + " added a comment:\n" + comment.rstrip()
102
103 return zephyr.ZNotice(
104 sender=zephyr_sender,
105 auth=False,
278c5c28 106 opcode='auto',
c3e3cdd9
AK
107 cls=zephyr_class,
108 instance=issue,
7f50f108 109 fields=[e.title, msg],
c3e3cdd9
AK
110 )
111
112def zerror(msg):
113 return zephyr.ZNotice(
114 sender=zephyr_sender,
115 auth=False,
278c5c28 116 opcode='auto',
c3e3cdd9
AK
117 cls=zephyr_class,
118 instance='jira-error',
7f50f108 119 fields=['Jira bot error', msg]
c3e3cdd9
AK
120 )
121
8b8cecc4 122b = jira_init()
8bf2b029 123zephyr.init()
8b8cecc4 124
a75c8c0f
AK
125count = 0
126
8bf2b029 127while True:
8bf2b029 128 time_file_new = time_file + '.' + ''.join(random.sample(string.letters, 8))
c3e3cdd9 129
8bf2b029
AK
130 try:
131 os.rename(time_file, time_file_new)
132 except OSError:
4311bd26
AK
133 print "warning: could not acquire timestamp lock"
134 time.sleep(17)
135 continue
c3e3cdd9 136
a75c8c0f
AK
137 if (count >= 200):
138 b = jira_init()
139 count = 0
140 count += 1
141
f719e433
AK
142 jira_login(b)
143 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")
144 issues_rss = b.response().read()
145 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")
146 comments_rss = b.response().read()
a75c8c0f 147 b.clear_history()
f719e433 148
8bf2b029
AK
149 old_time = int(open(time_file_new).read())
150 new_time = old_time
c3e3cdd9 151
8bf2b029
AK
152 zephyrs = (feed_to_zephyrs('issue', issues_rss, parse_issue) +
153 feed_to_zephyrs('comment', comments_rss, parse_comment))
8bf2b029
AK
154 zephyrs.sort(key=lambda tz: tz[0])
155 for (t, z) in zephyrs:
156 z.send()
f719e433 157
776fe303 158 open(time_file_new, 'w').write(str(new_time))
f719e433
AK
159 os.rename(time_file_new, time_file)
160
8a49ed8a 161 time.sleep(20)
This page took 0.660055 seconds and 5 git commands to generate.