Created
May 1, 2017 22:58
-
-
Save miou-gh/cc531b6ba6772a9eaec696652d336b26 to your computer and use it in GitHub Desktop.
This file contains 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
import os | |
import re | |
import time | |
import json | |
import hashlib | |
import calendar | |
import requests | |
import threading | |
import html2text | |
from datetime import datetime, date | |
from slackclient import SlackClient | |
from BeautifulSoup import BeautifulSoup as Soup | |
from BeautifulSoup import NavigableString | |
SLACK_BOT_TOKEN = 'CHANGE_THIS' | |
BOT_ID = 'CHANGE_THIS' | |
# constants | |
AT_BOT = "<@" + BOT_ID + ">" | |
COMMANDS = [ 'silence', 'listen', 'ping' ] | |
SILENCED = False | |
# instantiate Slack & Twilio clients | |
slack_client = SlackClient(SLACK_BOT_TOKEN) | |
def handle_command(command, channel): | |
response = "No such command found. For a list of commands, use 'commands'." | |
if command.startswith('commands') or command.startswith('help'): | |
response = "Available commands: " + ', '.join(COMMANDS) | |
elif command.startswith('silence'): | |
SILENCED = True | |
response = "Silence mode is now enabled." | |
elif command.startswith('listen'): | |
SILENCED = False | |
response = "Silence mode is now disabled." | |
elif command.startswith('ping'): | |
response = "Pong." | |
slack_client.api_call("chat.postMessage", channel=channel, | |
text=response, as_user=True) | |
def parse_slack_output(slack_rtm_output): | |
output_list = slack_rtm_output | |
if output_list and len(output_list) > 0: | |
for output in output_list: | |
if output and 'text' in output and AT_BOT in output['text']: | |
# return text after the @ mention, whitespace removed | |
return output['text'].split(AT_BOT)[1].strip().lower(), \ | |
output['channel'] | |
return None, None | |
def strip_html(html): | |
soup = Soup(html) | |
[div.extract() for div in soup.findAll('div')] | |
[span.extract() for span in soup.findAll('span')] | |
[br.extract() for br in soup.findAll('br')] | |
result = '' | |
try: | |
result = html2text.html2text(str(soup)) | |
except: | |
result = str(soup) | |
re.sub(r'(\r\n){2,}','\r\n', result) | |
return result | |
def parse_forums(): | |
READ_FORUM_FEED_DELAY = 10 | |
PREVIOUS_POSTS = [] | |
FULLY_PARSED = False | |
while True: | |
req = requests.request('GET', 'http://forums.everybodyedits.com/extern.php?action=feed&type=xml') | |
soup = Soup(req.content) | |
posts = [] | |
for message in soup.findAll('topic'): | |
post_id = message.attrs[0][1] | |
title = message.find('title').text | |
author_name = message.find('author').find('name').text | |
author_profile = message.find('author').find('uri').text | |
timestamp = datetime.strptime(message.find('posted').text, "%a, %d %b %Y %H:%M:%S +0000") | |
content = strip_html(message.find('content').text) | |
digest = hashlib.sha1(str.format('{}{}{}', post_id, author_profile, timestamp)).hexdigest() | |
post = { 'post_id': post_id, 'title': title, 'author_name': author_name, 'author_profile': author_profile, | |
'timestamp': timestamp, 'content': content, 'digest': digest } | |
posts.append(post) | |
if FULLY_PARSED: | |
found_posts = [] | |
for first in posts: | |
found = False | |
for second in PREVIOUS_POSTS: | |
if first['digest'] == second['digest']: | |
found = True | |
break | |
if not found: | |
found_posts.append(first) | |
for post in found_posts: | |
print(post) | |
channel_list = slack_client.api_call( | |
"channels.list", | |
exclude_archived=1 | |
) | |
attachment = { | |
"fallback": str.format('[EEForums] {} replied to {}...', post['title'], | |
str.format("http://forums.everybodyedits.com/viewtopic.php?id={}&action=new", post['post_id'])), | |
"color": "#36a64f", | |
"author_name": post['author_name'], | |
"author_link": post['author_profile'], | |
"author_icon": str.format("http://forums.everybodyedits.com/img/avatars/{}.png", post['author_profile'].split("?id=",1)[1]), | |
"title": post['title'], | |
"title_link": str.format("http://forums.everybodyedits.com/viewtopic.php?id={}&action=new", post['post_id']), | |
"text": post['content'][:150] + (post['content'][150:] and '..'), | |
"footer": "Everybody Edits Forums", | |
"footer_icon": "https://forums.everybodyedits.com/favicon.png", | |
"ts": int(calendar.timegm(post['timestamp'].timetuple())) | |
} | |
for channel in channel_list['channels']: | |
if channel['is_member'] and not SILENCED: | |
slack_client.api_call("chat.postMessage", channel=channel['id'], attachments=json.dumps( [attachment] ), as_user=True) | |
PREVIOUS_POSTS = posts | |
else: | |
PREVIOUS_POSTS = posts | |
FULLY_PARSED = True | |
time.sleep(READ_FORUM_FEED_DELAY) | |
if __name__ == "__main__": | |
READ_WEBSOCKET_DELAY = 1 | |
forum_parse_thread = threading.Thread(target=parse_forums, args=()) | |
forum_parse_thread.daemon = True | |
forum_parse_thread.start() | |
if slack_client.rtm_connect(): | |
print("BeefBot connected and running!") | |
while True: | |
command, channel = parse_slack_output(slack_client.rtm_read()) | |
if command and channel: | |
handle_command(command, channel) | |
time.sleep(READ_WEBSOCKET_DELAY) | |
else: | |
print("Connection failed. Invalid Slack token or bot ID?") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment