Repository: Winneon/makeswordclouds Branch: master Commit: 40baa8123258 Files: 7 Total size: 9.0 KB Directory structure: gitextract_trafy89f/ ├── .gitignore ├── README.md ├── common/ │ ├── __main__.py │ ├── cloud.py │ ├── config.py │ └── reddit.py └── requirements.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ praw.ini *.json *.pyc *.ttf *.otf ================================================ FILE: README.md ================================================ makeswordclouds --------------- A word cloud bot, currently running under /u/makeswordcloudsagain. The current version is v2.0.1. ================================================ FILE: common/__main__.py ================================================ import os import sys import time import traceback import praw import config import reddit import cloud class Main: def __init__(self): self.version = "2.0.1" self.c = config.Config("config.json", { "id": "", "min": 100 } ) self.d = config.Config("database.json", { "banned": [], "replied": [] } ) print "> Started makeswordclouds, version " + self.version self.r = reddit.Reddit(self.c, self.d, praw.Reddit("makeswordclouds: running under version " + self.version)) def legwork(self, submission, requester=None): prepend = "" text = self.r.flatten(submission) cloud.generate(text) upload = cloud.upload(self.c.get()["id"]) if requester != None: prepend = "**Summoned by /u/" + requester + ".** \n" content = ( prepend + "Here is a word cloud of every comment in this thread, as of this time: " + upload ) return self.r.comment(submission, content) def loop(self): try: while True: print "> Beginning mailbox check." for mail in self.r.mailbox(): try: url = self.legwork(mail.submission.id, requester=mail.message.author.name) self.r.message( mail.message.author.name, "Your word cloud has been created.", "Congratulations! Your word cloud can be found here: " + url ) except reddit.BannedSubredditError as e: try: raise reddit.BannedSubredditError( resp=reddit.ErrorResponse(self.r, mail.message.author.name), log=False ) except: pass except Exception as e: self.r.message( mail.message.author.name, "A problem arose creating your word cloud.", "An internal error occured. I am unable to furthur explain the issue. Contact the developer if you want to know the full cause." ) print "> An error occrred while creating the word cloud." print "> Beginning post check." for post in self.r.posts(): try: self.legwork(post) except reddit.BannedSubredditError: pass print "> Sleeping." self.d.save() time.sleep(120) except KeyboardInterrupt: print "> Terminated." self.d.save() except: print "> An error occured. Restarting." traceback.print_exc(file=sys.stdout) self.loop() if __name__ == "__main__": Main().loop() ================================================ FILE: common/cloud.py ================================================ import os import random import numpy import pyimgur from PIL import Image from wordcloud import WordCloud, ImageColorGenerator """ mask = numpy.array(Image.open(path.join(path.dirname(path.dirname(__file__)), "resources") + "/earth.png")) cloud = WordCloud(font_path=path.join(path.dirname(path.dirname(__file__)), "resources") + "/fonts/quartzo.ttf", background_color="#1A1A1A", mask=mask, scale=2, max_words=None, relative_scaling=0.5, prefer_horizontal=1.0) cloud.generate(r.flatten("4d1yv4")) image_colors = ImageColorGenerator(mask) cloud.recolor(color_func=image_colors) cloud.to_file("cloud.png") """ def generate(text): resources = os.path.join(os.path.dirname(os.path.dirname(__file__)), "resources") masks = os.path.join(resources, "masks") fonts = os.path.join(resources, "fonts") mask = numpy.array(Image.open(os.path.join(masks, random.choice(os.listdir(masks))))) cloud = WordCloud( font_path=os.path.join(fonts, random.choice(os.listdir(fonts))), background_color="#1A1A1A", mask=mask, scale=2, max_words=None, relative_scaling=0.5, prefer_horizontal=1.0 ) cloud.generate(text) image_colors = ImageColorGenerator(mask) cloud.recolor(color_func=image_colors) cloud.to_file("cloud.png") def upload(client): imgur = pyimgur.Imgur(client) upload = imgur.upload_image("cloud.png") os.remove("cloud.png") return upload.link ================================================ FILE: common/config.py ================================================ import json import re from os import path class Config: def __init__(self, name, template): self.config_path = path.dirname(path.dirname(__file__)) + name if not path.isfile(self.config_path): self._write(self.config_path, template) self.config = json.loads(open(self.config_path).read()) def _write(self, filepath, template): with open(filepath, "w") as w: w.write(json.dumps(template, indent=4, sort_keys=True)) def get(self): return self.config def save(self): self._write(self.config_path, self.config) ================================================ FILE: common/reddit.py ================================================ import sys import re import traceback import praw class ErrorResponse: def __init__(self, reddit, recipient): self.reddit = reddit self.recipient = recipient class MakesWordCloudsErrorDummy(Exception): def __init__(self, resp, message, log): Exception.__init__(self, message) if resp == None: self.makeswordclouds_cont = True else: resp.reddit.message( resp.recipient, "A problem arose creating your word cloud.", message ) if log: print "> " + message class InvalidPermalinkError(MakesWordCloudsErrorDummy): def __init__(self, resp=None, message="The permalink is invalid.", log=True): MakesWordCloudsErrorDummy.__init__(self, resp, message, log) class PreexistingCloudError(MakesWordCloudsErrorDummy): def __init__(self, resp=None, message="The permalink already has a word cloud in its comments.", log=True): MakesWordCloudsErrorDummy.__init__(self, resp, message, log) class BannedSubredditError(MakesWordCloudsErrorDummy): def __init__(self, resp=None, message="The subreddit is on the blacklist.", log=True): MakesWordCloudsErrorDummy.__init__(self, resp, message, log) class ValidMail: def __init__(self, submission, message): self.submission = submission self.message = message class Reddit: def __init__(self, config, database, reddit): self.config = config self.database = database self.reddit = reddit self.reddit.refresh_access_information() self.footer = ( "---\n\n" "[^[source ^code]](https://github.com/Winneon/makeswordclouds) " "[^[contact ^developer]](https://reddit.com/user/WinneonSword) " "[^[request ^word ^cloud]](https://www.reddit.com/message/compose/?to=makeswordcloudsagain&subject=Requesting%20word%20cloud.&message=%2Bcreate%20REPLACE_THIS_WITH_A_REDDIT_POST_PERMALINK)" ) print "> Authenticated as /u/" + self.reddit.get_me().name def _format_comment(self, text): return text + "\n\n" + self.footer def flatten(self, submission): submission = self.reddit.get_submission(submission_id=submission, comment_limit=None) flattened = praw.helpers.flatten_tree(submission.comments) text_mass = "" for comment in flattened: if isinstance(comment, praw.objects.Comment): # i hate these 3 lines of code but i'm too lazy to redo them body = re.sub(r"https?://(?:www\.)?[A-z0-9-]+\.[A-z\.]+[\?A-z0-9&=/]*", "", comment.body, flags=re.IGNORECASE) body = re.sub(r"<.*?>|&.*?;|/.+?(?= )|/.*", "", body) text_mass = text_mass + body + "\n" return text_mass def mailbox(self): collected = [] for message in self.reddit.get_unread(limit=None): if "+create " in message.body: submission = None try: permalink = message.body.replace("+create ", "") if "redd.it" in permalink: short = permalink.replace("http://redd.it/", "").replace("https://redd.it/", "") submission = self.reddit.get_submission(submission_id=short) else: submission = self.reddit.get_submission(url=permalink) except: pass try: if submission == None: raise InvalidPermalinkError(resp=ErrorResponse(self, message.author.name)) elif submission.id in self.database.get()["replied"]: raise PreexistingCloudError(resp=ErrorResponse(self, message.author.name)) elif submission.subreddit.display_name.lower() in self.database.get()["banned"]: raise BannedSubredditError(resp=ErrorResponse(self, message.author.name)) else: collected.append(ValidMail(submission, message)) except MakesWordCloudsErrorDummy: pass message.mark_as_read() return collected def posts(self): collected = [] for post in self.reddit.get_subreddit("all").get_hot(limit=200): subreddit = post.subreddit.display_name limit = int(self.config.get()["min"]) banned = self.database.get()["banned"] replied = self.database.get()["replied"] if subreddit.lower() not in banned and post.id not in replied and post.num_comments >= limit: collected.append(post.id) return collected def comment(self, submission, message): submission = self.reddit.get_submission(submission_id=submission) try: url = submission.add_comment(self._format_comment(message)).permalink self.database.get()["replied"].append(submission.id) print "> Comment posted. " print "> " + url return url except praw.errors.Forbidden as e: subreddit = submission.subreddit.display_name.lower() banned = self.database.get()["banned"] if subreddit not in banned: banned.append(subreddit) raise BannedSubredditError() except: print "> Failed to post comment." self.database.get()["replied"].append(submission.id) traceback.print_exc(file=sys.stdout) def message(self, recipient, subject, message): self.reddit.send_message(recipient, subject, self._format_comment(message)) ================================================ FILE: requirements.txt ================================================ image numpy pyimgur praw wordcloud