Skip to content

Commit b729b73

Browse files
committed
Created class for handling comments with Disqus.
1 parent dcaceea commit b729b73

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

codebender_testing/disqus.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
from codebender_testing.config import get_path
5+
import disqusapi
6+
import requests
7+
import simplejson
8+
import base64
9+
import hashlib
10+
import hmac
11+
import time
12+
import random
13+
import os
14+
import re
15+
16+
17+
FORUM = 'codebender-cc'
18+
AUTHOR_NAME = 'codebender'
19+
AUTHOR_URL = 'https://codebender.cc/user/codebender'
20+
DISQUS_REQUESTS_PER_HOUR = 1000
21+
DISQUS_WAIT = (DISQUS_REQUESTS_PER_HOUR / 60) / 60
22+
CHANGE_LOG = 'examples_compile_log.json'
23+
DISQUS_COMMENTS = 'disqus_comments.json'
24+
EXAMPLES_WITHOUT_LIBRARY_DB = 'examples_without_library.json'
25+
26+
27+
class DisqusWrapper:
28+
def __init__(self, log_time):
29+
self.log_time = log_time
30+
self.DISQUS_API_SECRET = os.getenv('DISQUS_API_SECRET', None)
31+
self.DISQUS_API_PUBLIC = os.getenv('DISQUS_API_PUBLIC', None)
32+
self.DISQUS_ACCESS_TOKEN = os.getenv('DISQUS_ACCESS_TOKEN', None)
33+
self.user = {
34+
'id': os.getenv('DISQUS_SSO_ID', None),
35+
'username': os.getenv('DISQUS_SSO_USERNAME', None),
36+
'email': os.getenv('DISQUS_SSO_EMAIL', None),
37+
}
38+
self.SSO_KEY = self.get_disqus_sso(self.user)
39+
self.disqus = disqusapi.DisqusAPI(api_secret=self.DISQUS_API_SECRET, public_key=self.DISQUS_API_PUBLIC, remote_auth=self.SSO_KEY)
40+
self.change_log = {}
41+
self.last_post = None
42+
self.last_library = None
43+
44+
with open(get_path('data', DISQUS_COMMENTS)) as f:
45+
self.messages = simplejson.loads(f.read())
46+
47+
with open(get_path('data', EXAMPLES_WITHOUT_LIBRARY_DB)) as f:
48+
self.examples_without_library = simplejson.loads(f.read())
49+
50+
def get_disqus_sso(self, user):
51+
# create a JSON packet of our data attributes
52+
data = simplejson.dumps(user)
53+
# encode the data to base64
54+
message = base64.b64encode(data)
55+
# generate a timestamp for signing the message
56+
timestamp = int(time.time())
57+
# generate our hmac signature
58+
sig = hmac.HMAC(self.DISQUS_API_SECRET, '%s %s' % (message, timestamp), hashlib.sha1).hexdigest()
59+
return "{0} {1} {2}".format(message, sig, timestamp)
60+
61+
def update_comment(self, sketch, results, current_date, log_entry, openFailFlag, counter, total_sketches):
62+
# Comment examples
63+
if not openFailFlag:
64+
log_entry = self.handle_example_comment(sketch, results, current_date, log_entry)
65+
66+
# Comment libraries when finished with the examples
67+
library_match = re.match(r'.+\/example\/(.+)\/.+', sketch)
68+
library = None
69+
if library_match:
70+
library = library_match.group(1)
71+
if not self.last_library:
72+
self.last_library = library
73+
if library and library != self.last_library and (library not in self.examples_without_library or counter >= total_sketches-1):
74+
log_entry = self.handle_library_comment(library, current_date, log_entry)
75+
last_library = library
76+
77+
return log_entry
78+
79+
def handle_library_comment(self, library, current_date, log):
80+
url = '/library/' + library
81+
identifier = 'ident:' + url
82+
paginator = disqusapi.Paginator(self.disqus.api.threads.list, forum=FORUM, thread=identifier, method='GET')
83+
if paginator:
84+
for page in paginator:
85+
post_id, existing_message = self.get_posts(page['id'])
86+
if post_id and existing_message:
87+
new_message = self.messages['library'].replace('TEST_DATE', current_date)
88+
if url not in log:
89+
log[url] = {}
90+
log[url]['comment'] = self.update_post(post_id, new_message)
91+
else:
92+
log[url][comment] = False
93+
return log
94+
95+
def handle_example_comment(self, url, results, current_date, log):
96+
identifier = url.replace('https://codebender.cc', '')
97+
identifier = 'ident:' + identifier
98+
paginator = disqusapi.Paginator(self.disqus.api.threads.list, forum=FORUM, thread=identifier, method='GET')
99+
if paginator:
100+
for page in paginator:
101+
post_id, existing_message = self.get_posts(page['id'])
102+
if post_id and existing_message:
103+
boards = []
104+
for result in results:
105+
if result['status'] == 'success':
106+
board = result['board']
107+
if re.match(r'Arduino Mega.+', board):
108+
board = 'Arduino Mega'
109+
boards.append(board)
110+
111+
new_message = self.messages['example_fail'].replace('TEST_DATE', current_date)
112+
if len(boards) > 0:
113+
new_message = self.messages['example_success'].replace('TEST_DATE', current_date).replace('BOARDS_LIST', ', '.join(boards))
114+
log[url]['comment'] = self.update_post(post_id, new_message)
115+
break
116+
else:
117+
log[url]['comment'] = False
118+
return log
119+
120+
def get_posts(self, thread_id):
121+
post_found = False
122+
post_id = None
123+
raw_message = None
124+
paginator = disqusapi.Paginator(self.disqus.api.posts.list, forum=FORUM, thread=thread_id, order='asc', method='GET')
125+
if paginator:
126+
for result in paginator:
127+
if result['author']['name'] == AUTHOR_NAME and result['author']['url'] == AUTHOR_URL:
128+
post_id = result['id']
129+
raw_message = result['raw_message']
130+
break
131+
return post_id, raw_message
132+
133+
def update_post(self, post_id, message):
134+
if not self.last_post:
135+
self.last_post = message
136+
elif re.match(r'^.+\.$', self.last_post):
137+
message = message[:-1]
138+
self.last_post = message
139+
try:
140+
response = self.disqus.posts.update(api_secret=self.DISQUS_API_SECRET, api_key=self.DISQUS_API_PUBLIC, remote_auth=self.SSO_KEY, access_token=self.DISQUS_ACCESS_TOKEN, post=post_id, message=message, method='POST')
141+
if response['raw_message'] == message:
142+
return True
143+
return False
144+
except Exception as error:
145+
print 'Error:', error
146+
return False

0 commit comments

Comments
 (0)