diff options
author | jwansek <37976823+jwansek@users.noreply.github.com> | 2020-11-24 00:22:06 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-24 00:22:06 +0000 |
commit | 5a0b6637975d430dfd1be5894df89d56df215b09 (patch) | |
tree | abc405c6a636a0b42b91c52fb5ac9be07338078a /subreddit.py | |
parent | 7677d95c729ab88080d742461fcb3b07c8b421f7 (diff) | |
parent | e2b1386a53c34812d1f8919a5c0ba67f9781a131 (diff) | |
download | SmallYTChannelBot-5a0b6637975d430dfd1be5894df89d56df215b09.tar.gz SmallYTChannelBot-5a0b6637975d430dfd1be5894df89d56df215b09.zip |
Merge pull request #1 from jwansek/MySQLdev
merge MySQL branch
Diffstat (limited to 'subreddit.py')
-rwxr-xr-x | subreddit.py | 322 |
1 files changed, 119 insertions, 203 deletions
diff --git a/subreddit.py b/subreddit.py index 205995b..4be5c20 100755 --- a/subreddit.py +++ b/subreddit.py @@ -1,10 +1,10 @@ from imgurpython import ImgurClient from operator import itemgetter -from database import Database +import database import datetime import logging import ytapi -import graph +# import graph import time import praw import json @@ -15,16 +15,15 @@ with open("config.json", "r") as f: CONFIG = json.load(f) REDDIT = praw.Reddit(**CONFIG["redditapi"]) +REDDIT.validate_on_submit = True SUBREDDIT = REDDIT.subreddit(CONFIG["subreddit"]) COMMENT_TAIL = CONFIG["comment_tail"] FREE_FLAIRS = CONFIG["free_flairs"] IMGUR = ImgurClient(**CONFIG["imgurapi"]) -db = Database() - logging.basicConfig( - format = "[%(asctime)s] %(message)s", + format = "%(process)s\t[%(asctime)s]\t%(message)s", level = logging.INFO, handlers=[ logging.FileHandler("actions.log"), @@ -32,12 +31,16 @@ logging.basicConfig( ]) def get_time(): - #this is not the correct way to do this but I don't care return time.strftime("%b %d %Y %H:%M:%S", time.gmtime()) -def display(message): +def display(message, concerning = None): logging.info(message) + #yes it'd be prettier to do this with a logging.Handler, but alas + #due to `concerning` it'd be more complicated than doing it like this + with database.Database() as db: + db.append_log("%d\t[%s]\t%s" % (os.getpid(), get_time(), message), concerning) + def get_lambda_from_flair(s): result = re.search("\[(.*)\]", s) if result is not None and "λ" in result.group(1): @@ -61,101 +64,31 @@ def get_medal(actualscore): else: return "" -def update_users_flair(username): - flairtext = next(SUBREDDIT.flair(redditor=username))["flair_text"] +def update_users_flair(username, reddit): + flairtext = next(reddit.flair(redditor=username))["flair_text"] if flairtext is None: flairtext = "" else: flairscore = get_lambda_from_flair(flairtext) flairtext = str(flairtext.replace("[%s] " % flairscore, "")) - if username in get_mods(): + if username in get_mods(reddit): newflair = "[🏆 ∞λ] %s" % (flairtext) else: - actualscore = db.get_lambda(username)[0] + with database.Database() as db: + actualscore = db.get_lambda(username)[0] newflair = "[%s%iλ] %s" % (get_medal(actualscore), actualscore, flairtext) logging.info("/u/%s had their flair updated" % username) - SUBREDDIT.flair.set(redditor = username, text = newflair) - -def get_mods(): - return [str(i) for i in SUBREDDIT.moderator()] + ["AutoModerator"] - -def update_tables(scores, data): - content = "" - date = str(datetime.date.today()) - mods = get_mods() - imagepath = graph.make_graph(data) - imageurl = upload_image(imagepath, date) - bylambda = [i for i in sorted(scores, key = itemgetter(1), reverse = True) if i[0] not in mods][:10] - byhelps = sorted(scores, key = itemgetter(2), reverse = True)[:10] - - SUBREDDIT.stylesheet.upload("wikigraph", imagepath) - - content += "\n\n##/r/SmallYTChannel lambda tables: %s" % date - - content += "\n\n###By lambda:" - content += "\n\nUsername|Lambda|Help given\n:--|:--|:--" - for line in bylambda: - content += "\n/u/%s|%i|%i" % (line[0], line[1], line[2]) - - content += "\n\n###By Help given:" - content += "\n\nUsername|Lambda|Help given\n:--|:--|:--" - for line in byhelps: - λ = str(line[1]) - if line[0] in mods: - λ = "∞" - content += "\n/u/%s|%s|%i" % (line[0], λ, line[2]) - - content += "\n\n##Statistics from %s:\n\nIf you're looking at this through the wiki, not through the bot's profile, then" % (date) - content += "the most up-to-date graph will be shown below. To see the graph at this date, follow [this link.](%s)" % (imageurl) - content += "\n\n\n\nTotal λ in circulation|Useful advice given|Unique users\n:--|:--|:--\n%i|%i|%i" % (data[-1][1], data[-1][2], data[-1][3]) - - REDDIT.subreddit("u_SmallYTChannelBot").submit("/r/SmallYTChannel Statistics: %s" % date, url = imageurl).reply(content).mod.distinguish(sticky = True) - - SUBREDDIT.wiki["lambdatables"].edit(content, reason = "Update: %s" % date) - SUBREDDIT.wiki[date].edit(content, reason = "Update: %s" % date) - - currentdata = SUBREDDIT.wiki["index"].content_md - currentdata += "\n\n* [%s](/r/SmallYTChannel/wiki/%s)" % (date, date) - - SUBREDDIT.wiki["index"].edit(currentdata, reason = "Update: %s" % date) - -def upload_image(path, date): - config = { - 'album': None, - 'name': 'SmallYTChannelBot Statistics graph: %s' % date, - 'title': 'SmallYTChannelBot Statistics graph: %s' % date, - 'description': 'SmallYTChannelBot Statistics graph: %s' % date - } - - image = IMGUR.upload_from_path(path, config = config) - - return "https://i.imgur.com/%s.png" % image["id"] - -def every_day(): - display("Starting every day program...") - display("Updating database statistics...") - db.update_stats() - display("Posting and updating wiki...") - update_tables(db.get_scores(), db.get_stats()) - display("Formatting leaderboard...") - leaderboard = format_monthly_leaderboard() - display("Updating sidebar...") - #it'd be cool to find a way to access this directly without iteration - for widget in SUBREDDIT.widgets.sidebar: - if widget.shortName == "Monthly Lambda Leaderboard": - widget.mod.update(text = leaderboard) - display("Updated in new reddit...") - sidebar = SUBREDDIT.mod.settings()["description"] - oldtable = sidebar.split("------")[-1] - SUBREDDIT.mod.update(description = sidebar.replace(oldtable, "\n\n## Monthly Lambda Leaderboard\n\n" + leaderboard)) - display("Updated in old reddit...") - display("Completed.") - -def handle_mylambda(comment): + reddit.flair.set(redditor = username, text = newflair) + +def get_mods(reddit): + return [str(i) for i in reddit.subreddit(CONFIG["subreddit"]).moderator()] + ["AutoModerator"] + +def handle_mylambda(comment, reddit): author = str(comment.author) - λ, links = db.get_lambda(author) - if author in get_mods(): + with database.Database() as db: + λ, links = db.get_lambda(author) + if author in get_mods(reddit): text = "/u/%s is a moderator, and therefore has ∞λ." % author else: text = "/u/%s currently has %iλ, and has helped helping the following posts:" % (author, λ) @@ -175,34 +108,40 @@ def handle_mylambda(comment): update_users_flair_from_comment(comment) return text -def handle_givelambda(comment): +def handle_givelambda(comment, reddit): submission = comment.submission parentauthour = str(comment.parent().author) op = str(comment.author) - if op == parentauthour: - text = "You cannot give yourself λ." - elif parentauthour == "SmallYTChannelBot": - text = "Please only give lambda to humans." - elif str(comment.author) in get_mods(): - text = "The moderator /u/%s has given /u/%s 1λ. /u/%s now has %iλ." % (str(comment.author), parentauthour, parentauthour, db.get_lambda(parentauthour)[0] + 1) - db.give_lambda(parentauthour, submission.permalink, timestamp = int(submission.created_utc)) - display(text) - elif submission.link_flair_text in FREE_FLAIRS: - text = "You cannot give lambda in free posts anymore." - elif op != str(submission.author): - text = "Only the OP can give λ." - elif db.user_given_lambda(parentauthour, str(submission.permalink)): - text = "You have already given /u/%s λ for this submission. Why not give λ to another user instead?" % parentauthour - else: - display("'/u/%s' has given '/u/%s' lambda!" % (op, parentauthour)) - text = "You have given /u/%s 1λ. /u/%s now has %iλ" % (parentauthour, parentauthour, db.get_lambda(parentauthour)[0] + 1) + with database.Database() as db: + if op == parentauthour: + text = "You cannot give yourself λ." + elif parentauthour == "SmallYTChannelBot": + text = "Please only give lambda to humans." + elif str(comment.author) in get_mods(reddit): + text = "The moderator /u/%s has given /u/%s 1λ. /u/%s now has %iλ." % (str(comment.author), parentauthour, parentauthour, db.get_lambda(parentauthour)[0] + 1) + db.give_lambda(parentauthour, submission.permalink, timestamp = int(submission.created_utc)) + display(text, concerning=comment.permalink) + elif submission.link_flair_text in FREE_FLAIRS: + text = "You cannot give lambda in free posts anymore." + display("Giving lambda was rejected due to being a free post", concerning=comment.permalink) + elif op != str(submission.author): + text = "Only the OP can give λ." + elif db.user_given_lambda(parentauthour, str(submission.permalink)): + text = "You have already given /u/%s λ for this submission. Why not give λ to another user instead?" % parentauthour + display("Giving lambda was rejected for being the same user", concerning=comment.permalink) + elif len(comment.parent().body) < CONFIG["min_comment_len"]: + text = "You can no longer give λ to comments that are fewer than %i characters in length. This is to encourage specific, detailed feedback." % CONFIG["min_comment_len"] + display("Giving lambda was rejected due to insufficient length", concerning=comment.permalink) + else: + display("'/u/%s' has given '/u/%s' lambda!" % (op, parentauthour), concerning=comment.permalink) + text = "You have given /u/%s 1λ. /u/%s now has %iλ" % (parentauthour, parentauthour, db.get_lambda(parentauthour)[0] + 1) - #bonus lambda giving was removed - # if not db.link_in_db(submission.permalink) or not db.link_in_db(submission.permalink.replace("https://www.reddit.com", "")): - # db.give_lambda(parentauthour, submission.permalink, op) - # display("The OP received lambda too!") - # else: - db.give_lambda(parentauthour, submission.permalink, timestamp = int(submission.created_utc)) + #bonus lambda giving was removed + # if not db.link_in_db(submission.permalink) or not db.link_in_db(submission.permalink.replace("https://www.reddit.com", "")): + # db.give_lambda(parentauthour, submission.permalink, op) + # display("The OP received lambda too!") + # else: + db.give_lambda(parentauthour, submission.permalink, timestamp = int(submission.created_utc)) # update_users_flair_from_comment(comment) update_users_flair_from_comment(comment.parent()) @@ -211,15 +150,16 @@ def handle_givelambda(comment): def handle_takelambda(comment): try: splitted = comment.body.split() - user = splitted[1].replace("/u/", "") + user = splitted[1].replace("/u/", "").replace("u/", "") toremove = int(splitted[2].replace("\\", "")) reason = " ".join(splitted[3:]) - text = "/u/%s has had %iλ taken away from them for the reason '%s'. /u/%s now has %iλ" % (user, toremove, reason, user, db.get_lambda(user)[0] - toremove) - db.change_lambda(user, -toremove) - display("A moderator removed %i lambda from /u/%s for the reason '%s'" % (toremove, user, reason)) + with database.Database() as db: + text = "/u/%s has had %iλ taken away from them for the reason '%s'. /u/%s now has %iλ" % (user, toremove, reason, user, db.get_lambda(user)[0] - toremove) + db.change_lambda(user, -toremove) + display("A moderator removed %i lambda from /u/%s for the reason '%s'" % (toremove, user, reason), concerning=comment.permalink) except Exception as e: - display("{ERROR while removing λ} %s" % e) + display("{ERROR while removing λ} %s" % e, concerning=comment.permalink) text = r"An error was encountered. Please use the syntax `!takelambda [user] [how much to remove {integer}] [reason]`" + "\n\nThe error was:\n\n" + str(e) update_users_flair(user) @@ -228,27 +168,29 @@ def handle_takelambda(comment): def handle_refundlambda(comment): try: splitted = comment.body.split() - user = splitted[1].replace("/u/", "") + user = splitted[1].replace("/u/", "").replace("u/", "") toadd = int(splitted[2].replace("\\", "")) reason = " ".join(splitted[3:]) - text = "/u/%s has had %iλ refunded for the reason '%s'. /u/%s now has %iλ" % (user, toadd, reason, user, db.get_lambda(user)[0] + toadd) - db.change_lambda(user, toadd) - display("A moderator refunded %i lambda from /u/%s for the reason '%s'" % (toadd, user, reason)) + with database.Database() as db: + text = "/u/%s has had %iλ refunded for the reason '%s'. /u/%s now has %iλ" % (user, toadd, reason, user, db.get_lambda(user)[0] + toadd) + db.change_lambda(user, toadd) + display("A moderator refunded %i lambda from /u/%s for the reason '%s'" % (toadd, user, reason), concerning=comment.permalink) except Exception as e: - display("{ERROR while refunding λ} %s" % e) + display("{ERROR while refunding λ} %s" % e, concerning=comment.permalink) text = r"An error was encountered. Please use the syntax `!refundlambda [user] [how much to add {integer}] [reason]`" + "\n\nThe error was:\n\n" + str(e) update_users_flair(user) return text def handle_submission(submission): - score = db.get_lambda(str(submission.author))[0] + with database.Database() as db: + score = db.get_lambda(str(submission.author))[0] if submission.link_flair_text in FREE_FLAIRS: if "youtube.com" in str(submission.url) or "youtu.be" in str(submission.url): text = "Your post has been removed because it has the wrong flair. [Discussion], [Meta] and [Collab] flairs are only for text submissions." submission.mod.remove() - display("/u/%s had their submission removed for using the wrong flair." % submission.author) + display("/u/%s had their submission removed for using the wrong flair." % submission.author, concerning=submission.permalink) else: text = "Your post is a discussion, meta or collab post so it costs 0λ." else: @@ -256,12 +198,13 @@ def handle_submission(submission): text = """Thank you for submitting to /r/SmallYTChannel. Unfortunally, you submission has been removed since you do not have enough λ. You need 3λ to post. You currently have %iλ. For more information, read the [FAQ.](https://www.reddit.com/user/SmallYTChannelBot/comments/a4u7qj/smallytchannelbot_faq/)""" % score submission.mod.remove() - display("/u/%s had their submission removed for insufficient lambda." % submission.author) + display("/u/%s had their submission removed for insufficient lambda." % submission.author, concerning=submission.permalink) else: text = """Thank you for submitting to /r/SmallYTChannel. You have spent 3λ to submit here, making your current balance %iλ. /u/%s, please comment `!givelambda` to the most helpful advice you are given. For more information, read the [FAQ.](https://www.reddit.com/user/SmallYTChannelBot/comments/a4u7qj/smallytchannelbot_faq/)""" % (score - 3, str(submission.author)) - db.change_lambda(str(submission.author), -3) + with database.Database() as db: + db.change_lambda(str(submission.author), -3) try: ytid = ytapi.get_videoId_from_url(submission.url) @@ -317,83 +260,56 @@ Views|%s update_users_flair(str(submission.author)) return text +def handle_comment(comment, reddit): + response = None + if "!mylambda" in comment.body.lower() and str(comment.author) != "SmallYTChannelBot": + response = handle_mylambda(comment, reddit) + + if "!givelambda" in comment.body.lower() and str(comment.author) != "SmallYTChannelBot": + response = handle_givelambda(comment, reddit) + + if comment.body.startswith("!takelambda") and str(comment.author) in get_mods(): + response = handle_takelambda(comment) + + if comment.body.startswith("!refundlambda") and str(comment.author) in get_mods(): + response = handle_refundlambda(comment) + + if response is not None: + reply = comment.reply(response + COMMENT_TAIL) + reply.mod.distinguish(sticky = False) + +def stream(reddit): + subreddit = reddit.subreddit(CONFIG["subreddit"]) + streams = [subreddit.stream.comments(pause_after=-1), subreddit.stream.submissions(pause_after=-1)] + with database.Database() as db: + while True: + for stream in streams: + for item in stream: + if item is None: + break + + if db.id_in_blacklist(item.id): + continue + + db.add_to_blacklist(item.id) + if type(item) is praw.models.reddit.comment.Comment: + handle_comment(item, reddit) + + elif type(item) is praw.models.reddit.submission.Submission: + display("There has been a new submission: '%s', with flair '%s'" % (item.title, item.link_flair_text), concerning=item.permalink) + + if str(item.author) not in get_mods(reddit): + reply = item.reply(handle_submission(item) + COMMENT_TAIL) + reply.mod.distinguish(sticky = True) + reply.mod.approve() + def main(): - comment_stream = SUBREDDIT.stream.comments(pause_after=-1) - submission_stream = SUBREDDIT.stream.submissions(pause_after=-1) - - while True: - try: - for comment in comment_stream: - if comment is None: - break - if not db.id_in_blacklist(comment.id): - db.add_to_blacklist(comment.id) - - response = None - if "!mylambda" in comment.body.lower() and str(comment.author) != "SmallYTChannelBot": - response = handle_mylambda(comment) - - if "!givelambda" in comment.body.lower() and str(comment.author) != "SmallYTChannelBot": - response = handle_givelambda(comment) - - if comment.body.startswith("!takelambda") and str(comment.author) in get_mods(): - response = handle_takelambda(comment) - - if comment.body.startswith("!refundlambda") and str(comment.author) in get_mods(): - response = handle_refundlambda(comment) - - if response is not None: - reply = comment.reply(response + COMMENT_TAIL) - reply.mod.distinguish(sticky = False) - - for submission in submission_stream: - if submission is None: - break - if not db.id_in_blacklist(submission.id): - db.add_to_blacklist(submission.id) - display("There has been a new submission: '%s', with flair '%s'" % (submission.title, submission.link_flair_text)) - - response = None - if str(submission.author) not in get_mods(): - response = handle_submission(submission) - reply = submission.reply(response + COMMENT_TAIL) - reply.mod.distinguish(sticky = True) - reply.mod.approve() - - except Exception as e: - display("{ERROR} %s" % e) - continue - -def get_submission_times(permalink): - if not permalink.startswith("https://www.reddit.com"): - permalink = "https://www.reddit.com" + permalink - - submission = REDDIT.submission(url = permalink) - return submission.created_utc - -def add_times_to_lambdas(): - updated_permalinks = [] - for id_, permalink, user, created in db.get_all_lambdas(): - if created is None and permalink not in updated_permalinks: - db.add_date_to_permalink(permalink, get_submission_times(permalink)) - updated_permalinks.append(permalink) - logging.info("Added date for permalink %s" % permalink) - - -def format_monthly_leaderboard(): - leaderboard = db.get_lambda_leaderboard() - out = "**Username**|**Medal**|**Times Helped**|**Lambda**\n:-|:-|:-|:-\n" - for username, times_helped, λ in leaderboard: - out += "/u/%s|%1s|%s|%sλ\n" % (username, get_medal(λ)[:-1], times_helped, λ) - return out + "\nLast updated: %s" % get_time() + reddit = praw.Reddit(**CONFIG["redditapi"]) + reddit.validate_on_submit = True + stream(reddit) - -if __name__ == "__main__": - file = open("pid.txt", "w") - file.write(str(os.getpid())) - file.close() - display("\n####################\n[%s] RESTARTED\n####################\n" % get_time()) +if __name__ == "__main__": main() |