Advertisement
Guest User

VirtueTron9000 v0.2.3b

a guest
Jun 29th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.65 KB | None | 0 0
  1. #!/usr/bin/python
  2. LICENCE = "WTFPL", "http://www.wtfpl.net/about/"
  3. VERSION = "v0.2.3b"
  4.  
  5. import logging
  6. import pickle
  7. import praw
  8. import prawcore
  9. import sys
  10. from datetime import datetime, timedelta
  11. from math import ceil
  12. from time import sleep
  13.  
  14. log = logging.getLogger("VirtueTron")
  15. log.setLevel(logging.DEBUG)
  16. formatter = logging.Formatter(fmt="%(asctime)s - %(levelname)s - %(message)s", datefmt="%Y/%m/%d %I:%M:%S%p")
  17. file_log = logging.FileHandler(filename="VirtueTron.log", mode="a")
  18. file_log.setLevel(logging.INFO)
  19. file_log.setFormatter(formatter)
  20. log.addHandler(file_log)
  21. console_log = logging.StreamHandler(stream=sys.stdout)
  22. console_log.setLevel(logging.DEBUG)
  23. console_log.setFormatter(formatter)
  24. log.addHandler(console_log)
  25.  
  26. log.info("Hello, Reddit!")
  27. log.info("VirtueTron® 9000™ {0} © CrashARuntimeToday@outlook.com".format(VERSION))
  28.  
  29. credentials = pickle.load(open("credentials.pickle", "rb")) # {client_id:"VirtueTron9000", client_secret:"🤖🤡🍆💯™", username:"SignalAVirtueToday", password:"https://youtu.be/RCVJ7bujnSc" }
  30. credentials["user_agent"] = "VirtueTron 9000 {0}".format(VERSION)
  31. reddit = praw.Reddit(**credentials)
  32. tbp = reddit.subreddit("TheBluePill")
  33.  
  34.  
  35. class Tracker:
  36.     def __init__(self, name, good_karma, bad_karma):
  37.         self.name = name
  38.         self.smv = None
  39.         self.scan_count = 0
  40.         self.next_refresh = None
  41.         self.update(good_karma, bad_karma)
  42.         self.is_approved = False
  43.         self.is_purged = False
  44.    
  45.     def update(self, good_karma, bad_karma):
  46.         self.good_karma = good_karma
  47.         self.bad_karma = bad_karma
  48.         self.scan_count += 1
  49.         self.next_refresh = datetime.now() + timedelta(minutes=15)
  50.  
  51.  
  52. delay = 2
  53. def praw_fucked_up():
  54.     global delay
  55.     log.warning("Reddit API errored: waiting {0} seconds".format(delay))
  56.     if delay > 128: delay = 2
  57.     sleep(delay)
  58.     delay *= 2
  59.  
  60. NICE_LIST = []
  61. NAUGHTY_LIST = "TheRedPill", "MarriedRedPill", "ChristianRedPill", "MGTOW", "Braincels", "AskTRP", "AskMRP", "RedPillWomen", "RedPillWives", "CringeAnarchy", "The_Donald", "RPChristians"
  62. def calc_score(name):
  63.     good_karma, bad_karma, good_count, bad_count = 0, 0, 0, 0
  64.    
  65.     for comment in reddit.redditor(name).comments.new(limit=100):
  66.         sub = comment.subreddit.display_name
  67.         karma = comment.score
  68.         if sub == "TheBluePill":
  69.             good_karma += karma - 1
  70.             good_count += 1
  71.         elif sub in NICE_LIST:
  72.             good_karma += (karma - 1) / 2
  73.         elif sub in NAUGHTY_LIST and karma > 1:
  74.             bad_karma -= karma - 1
  75.             bad_count += 1
  76.    
  77.     if good_count > 0:
  78.         good_karma /= good_count
  79.    
  80.     if bad_count > 0:
  81.         bad_karma /= bad_count
  82.         if bad_count > 5 and not any(tbp.banned(redditor=name)):
  83.             log.info("User: {0} is vexatious ({1} posts in NAUGHTY_LIST)".format(name, bad_count))
  84.             tbp.flair.set(name, "VEXATIOUS LITIGANT", "vexatious")
  85.  
  86.     log.info("Scanned user: {0}, good_karma: {1} ({2} comments), bad_karma: {3} ({4} comments)".format(name, good_karma, good_count, bad_karma, bad_count))
  87.     return good_karma, bad_karma
  88.  
  89. IMMUTABLE_FLAIRS = "vanguard", "vexatious", "endorsedflair", "alpha", "betaasfuck", "feeemale", "purged"
  90. def update_flairs():
  91.     log.info("Recalculating SMV")
  92.     i = 0
  93.     total = len(users)
  94.     for user in sorted(users.values(), key=lambda x: x.good_karma + x.bad_karma):
  95.         i += 1
  96.         user.smv = ceil((i / total) * 10)
  97.         current_flair = None
  98.        
  99.         # Not sure why Reddit doesn't like this bit and too lazy to run Wireshark
  100.         try:      
  101.             for flair in tbp.flair(redditor=user.name):
  102.                 current_flair = flair["flair_css_class"]
  103.         except prawcore.PrawcoreException:
  104.             praw_fucked_up()
  105.             pass
  106.  
  107.         if not user.is_purged and any(tbp.banned(redditor=user.name)):
  108.             if current_flair != "purged":
  109.                 log.info("Marking user: {0} purged".format(user.name))
  110.                 tbp.flair.set(user.name, "PURGED", "purged")
  111.                 user.is_approved = True
  112.             else:
  113.                 log.info("User: {0} is purged".format(user.name))
  114.                 if not user.is_purged: user.is_purged = True #Only needed for format update, since I wasn't tracking that locally before
  115.                 log.debug("User: {0} is banned and flaired, but not marked purged locally")
  116.         else:
  117.             log.info("User: {0}, SMV: {1}, score: {2} (current flair {3})".format(user.name, user.smv, user.good_karma + user.bad_karma, current_flair))
  118.  
  119.             if current_flair in IMMUTABLE_FLAIRS:
  120.                 log.info("Not changing user: {0} (immutable flair {1})".format(user.name, current_flair))
  121.             elif current_flair != "hb{0}".format(user.smv):
  122.                 log.info("Updating user: {0} flair to hb{1}".format(user.name, user.smv))
  123.                 tbp.flair.set(user.name, "Hβ{0}".format(user.smv), "hb{0}".format(user.smv))
  124.                
  125.                 if user.smv > 7 and not user.is_approved:
  126.                     if user.name not in tbp.contributor():
  127.                         log.info("Adding approved contributor: {0}".format(user.name))
  128.                         tbp.contributor.add(user.name)
  129.                         user.is_approved = True
  130.                 elif user.smv < 4 and user.is_approved:
  131.                     if user.name in tbp.contributor():
  132.                         log.info("Removing approved contributor: {0}".format(user.name))
  133.                         tbp.contributor.remove(user.name)
  134.            
  135.             else:
  136.                 log.info("User: {0} still an HB{1}".format(user.name, user.smv))
  137.    
  138.     pickle.dump(users, open("users.pickle", "wb"))
  139.  
  140. BAD_FLAIRS = ["purged", "vexatious"]
  141. threat_matrix = {"tllow": BAD_FLAIRS + ["hb{0}".format(x) for x in range(1,7)],
  142.                  "tlguarded": BAD_FLAIRS + ["hb{0}".format(x) for x in range(1,5)],
  143.                  "tlelevated": BAD_FLAIRS + ["hb{0}".format(x) for x in range(1,3)],
  144.                  "tlhigh": BAD_FLAIRS }
  145. def botloop(first_recalc):
  146.     next_recalc = first_recalc
  147.    
  148.     for comment in tbp.stream.comments():
  149.         threat_level = comment.submission.link_flair_css_class
  150.         author_rank = comment.author_flair_css_class
  151.        
  152.         try:
  153.             if author_rank in threat_matrix["threat_level"]:
  154.                 #comment.remove()
  155.                 log.info("Removing comment by {0} ({1}) on post '{2}' ({3}), SMV too low!".format(comment.author.name, comment.author_css_class, comment.submission.title, threat_level))
  156.         except KeyError:
  157.             pass
  158.        
  159.         if datetime.now() > next_recalc:
  160.             update_flairs()
  161.             next_recalc = datetime.now() + timedelta(minutes=20)
  162.             log.info("Next refresh: {0}".format(next_recalc))
  163.        
  164.         if comment.author != None:
  165.             name = comment.author.name
  166.            
  167.             if not name in users.keys():
  168.                 good_karma, bad_karma = calc_score(name)
  169.                 users[name] = Tracker(name, good_karma, bad_karma)
  170.                 log.info("New user: {0}".format(name))
  171.             elif datetime.now() > users[name].next_refresh:
  172.                 good_karma, bad_karma = calc_score(name)
  173.                 users[name].update(good_karma, bad_karma)
  174.                 log.info("User: {0} scanned {1} times".format(name, users[name].scan_count))
  175.             else:
  176.                 log.info("Skipping user: {0}, next refresh {1}".format(name, users[name].next_refresh))
  177.         #if comment.author_flair_css_class == None:
  178.             #if users[comment.author].warned:
  179.             #   if TimeDelta(users[comment.author].warned_on, datetime.now()) > TimeDelta(days=1):
  180.             #       users[comment.author].comments_eaten.append(comment.id)
  181.             #       comment.remove()
  182.             #else:
  183.             #   Send PM to comment.author:
  184.             #       "To whom it may concern:
  185.             #  
  186.             #           Apologies for the inconvenience, but user flairs are mandatory on r/TheBluePill. Please disable the subreddit's CSS, and toggle your user flair back on. You have 24 hours to comply. After which, all of your posts will be automatically removed (posts automatically removed will be restored when you have re-enabled your flair.) This action was performed automatically, but this account is also attached to a human operator if you have any concerns. We appreciate your continued business!
  187.             #    
  188.             #       etc. etc.
  189.             #       -Management"
  190.             #   users[comment.author].warned = True
  191.             #   users[comment.author].warned_on = datetime.now()
  192.         #else:
  193.             #if users[comment.author].warned = True and len(users[comment.author].comments_eaten) > 0:
  194.             #   for comment in users[comment.author].comments_eaten:
  195.             #       reddit.comment(id=comment).approve()        <-- might be pseudocode
  196.  
  197. NEED_TO_UPDATE_OBJCLASS = False
  198. try:
  199.     users = pickle.load(open("users.pickle", "rb"))
  200.     log.info("Re-loading database")
  201.     if NEED_TO_UPDATE_OBJCLASS:
  202.         log.debug("Updating object format")
  203.         for user in users.values():
  204.             users[user.name] = Tracker(user.name, user.good_karma, user.bad_karma)
  205.        
  206.  
  207. except IOError:
  208.     users = {}
  209.     log.info("I/O error accessing database, starting fresh")
  210.  
  211.  
  212. try:
  213.     botloop(datetime.now() + timedelta(minutes=20))
  214.  
  215. except prawcore.PrawcoreException:
  216.     praw_fucked_up()
  217.     botloop(datetime.now() + timedelta(minutes=20))
  218.  
  219. except KeyboardInterrupt:
  220.     log.info("VirtuteTron going off-line")
  221.     pickle.dump(users, open("users.pickle", "wb"))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement