daily pastebin goal
31%
SHARE
TWEET

VirtueTron9000 v0.2.7f

CrashARuntimeToday Jun 30th, 2018 96 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. LICENCE = "WTFPL", "http://www.wtfpl.net/about/"
  3. VERSION = "v0.2.7f"
  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. from random import randint
  14.  
  15. log = logging.getLogger("VirtueTron")
  16. log.setLevel(logging.DEBUG)
  17. formatter = logging.Formatter(fmt="%(asctime)s - %(levelname)s - %(message)s", datefmt="%Y/%m/%d %I:%M:%S%p")
  18. file_log = logging.FileHandler(filename="VirtueTron.log", mode="a")
  19. file_log.setLevel(logging.INFO)
  20. file_log.setFormatter(formatter)
  21. log.addHandler(file_log)
  22. console_log = logging.StreamHandler(stream=sys.stdout)
  23. console_log.setLevel(logging.DEBUG)
  24. console_log.setFormatter(formatter)
  25. log.addHandler(console_log)
  26.  
  27. log.info("Hello, Reddit!")
  28. log.info("VirtueTron® 9000™ {0} © CrashARuntimeToday@outlook.com".format(VERSION))
  29.  
  30. credentials = pickle.load(open("credentials.pickle", "rb")) # {client_id:"VirtueTron9000", client_secret:"🤖🤡🍆💯™", username:"SignalAVirtueToday", password:"https://youtu.be/RCVJ7bujnSc"}
  31. credentials["user_agent"] = "VirtueTron 9000 {0}".format(VERSION)
  32. reddit = praw.Reddit(**credentials)
  33. tbp = reddit.subreddit("TheBluePill")
  34.  
  35.  
  36. class Tracker:
  37.     def __init__(self, name, good_karma=0, bad_karma=0, new_user=True, scan_count=0, next_refresh=None, is_approved=False, is_purged=False, current_flair=None, warned=None, comments_eaten=[]):
  38.         self.name = name
  39.         self.smv = 0
  40.         self.scan_count = scan_count
  41.         self.next_refresh = next_refresh
  42.         self.is_approved = is_approved
  43.         self.is_purged = is_purged
  44.         self.current_flair = None
  45.         self.warned = warned
  46.         self.comments_eaten = comments_eaten
  47.         if new_user:
  48.             self.update(good_karma, bad_karma)
  49.         else:
  50.             self.good_karma = good_karma
  51.             self.bad_karma = bad_karma
  52.    
  53.     def update(self, good_karma, bad_karma):
  54.         self.good_karma = good_karma
  55.         self.bad_karma = bad_karma
  56.         self.scan_count += 1
  57.         self.next_refresh = datetime.now() + timedelta(minutes=15)
  58.  
  59.  
  60. delay = 2
  61. last_fuckup = None
  62. def praw_fucked_up():
  63.     global delay
  64.     global last_fuckup
  65.     log.warning("Reddit API errored: waiting {0} seconds".format(delay))
  66.     try:
  67.         if delay > 128 or datetime.now() > last_fuckup + timedelta(minutes=2): delay = 2
  68.     except TypeError:
  69.         delay = 2
  70.     sleep(delay)
  71.     delay *= 2
  72.     last_fuckup = datetime.now()
  73.  
  74. NICE_LIST = []
  75. NAUGHTY_LIST = "TheRedPill", "MarriedRedPill", "ChristianRedPill", "MGTOW", "Braincels", "AskTRP", "AskMRP", "RedPillWomen", "RedPillWives", "CringeAnarchy", "The_Donald", "RPChristians", "PussyPassDenied", "MensRights", "MillionDollarExtreme"
  76. def calc_score(name):
  77.     good_karma, bad_karma, good_count, bad_count = 0, 0, 0, 0
  78.    
  79.     for comment in reddit.redditor(name).comments.new(limit=100):
  80.         sub = comment.subreddit.display_name
  81.         karma = comment.score
  82.         if sub == "TheBluePill":
  83.             good_karma += karma - 1
  84.             good_count += 1
  85.         elif sub in NICE_LIST:
  86.             good_karma += (karma - 1) / 2
  87.         elif sub in NAUGHTY_LIST and karma > 1:
  88.             bad_karma -= karma - 1
  89.             bad_count += 1
  90.    
  91.     if good_count > 0:
  92.         good_karma /= good_count
  93.    
  94.     if bad_count > 0:
  95.         bad_karma /= bad_count
  96.         if bad_count > 5 and not any(tbp.banned(redditor=name)):
  97.             log.info("User: {0} is vexatious ({1} posts in NAUGHTY_LIST)".format(name, bad_count))
  98.             tbp.flair.set(name, "VEXATIOUS LITIGANT", "vexatious")
  99.  
  100.     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))
  101.     return good_karma, bad_karma
  102.  
  103. IMMUTABLE_FLAIRS = "vanguard", "vexatious", "endorsedflair", "alpha", "betaasfuck", "feeemale", "purged"
  104. def update_flairs():
  105.     log.info("Recalculating SMV")
  106.     i = 0
  107.     total = len(users)
  108.     for user in sorted(users.values(), key=lambda x: x.good_karma + x.bad_karma):
  109.         i += 1
  110.         user.smv = ceil((i / total) * 10)
  111.        
  112.         # Not sure why Reddit doesn't like this bit and too lazy to run Wireshark
  113.         if user.current_flair == None:
  114.             log.debug("No cached flair for user: {0}, checking Reddit".format(user.name))
  115.             try:      
  116.                 for flair in tbp.flair(redditor=user.name):
  117.                     user.current_flair = flair["flair_css_class"]
  118.             except prawcore.PrawcoreException:
  119.                 praw_fucked_up()
  120.                 pass
  121.  
  122.         if not user.is_purged and any(tbp.banned(redditor=user.name)):
  123.             if user.current_flair != "purged":
  124.                 log.info("Marking user: {0} purged".format(user.name))
  125.                 tbp.flair.set(user.name, "PURGED", "purged")
  126.                 user.current_flair = "purged"
  127.                 user.is_approved = True
  128.             else:
  129.                 log.info("User: {0} is purged".format(user.name))
  130.                 if not user.is_purged: #Only needed for format update, since I wasn't tracking that locally before
  131.                     user.is_purged = True
  132.                     log.debug("User: {0} is purged and flaired, but not marked locally".format(user.name))
  133.         else:
  134.             log.debug("User: {0}, SMV: {1}, score: {2} (current flair {3})".format(user.name, user.smv, user.good_karma + user.bad_karma, user.current_flair))
  135.  
  136.             if user.current_flair in IMMUTABLE_FLAIRS:
  137.                 log.debug("Not changing user: {0} (immutable flair {1})".format(user.name, user.current_flair))
  138.             elif user.current_flair != "hb{0}".format(user.smv):
  139.                 log.info("Updating user: {0} flair to hb{1}".format(user.name, user.smv))
  140.                 tbp.flair.set(user.name, "Hβ{0}".format(user.smv), "hb{0}".format(user.smv))
  141.                 user.current_flair = "hb{0}".format(user.smv)
  142.                
  143.                 if user.smv > 7 and not user.is_approved:
  144.                     if user.name not in tbp.contributor():
  145.                         log.info("Adding approved contributor: {0}".format(user.name))
  146.                         tbp.contributor.add(user.name)
  147.                         user.is_approved = True
  148.                     if not user.is_approved: #Only needed for format update, since I wasn't tracking that locally before
  149.                         user.is_approved = True
  150.                         log.debug("User: {0} is approved, but not marked locally".format(user.name))
  151.                 elif user.smv < 4 and user.is_approved:
  152.                     log.info("Removing approved contributor: {0}".format(user.name))
  153.                     tbp.contributor.remove(user.name)
  154.                        
  155.  
  156.             else:
  157.                 log.debug("User: {0} still an HB{1}".format(user.name, user.smv))
  158.    
  159.     pickle.dump(users, open("users.pickle", "wb"))
  160.  
  161. BAD_FLAIRS = ["purged", "vexatious"]
  162. TODAYS_THREAT_LEVEL = {"tlsevere":"Severe", "tlhigh":"High", "tlelevated":"Elevated"}
  163. threat_matrix = {"tllow": BAD_FLAIRS + ["hb{0}".format(x) for x in range(1,7)],
  164.                  "tlguarded": BAD_FLAIRS + ["hb{0}".format(x) for x in range(1,5)],
  165.                  "tlelevated": BAD_FLAIRS + ["hb{0}".format(x) for x in range(1,3)],
  166.                  "tlhigh": BAD_FLAIRS }
  167. def botloop(first_recalc):
  168.     next_recalc = first_recalc
  169.    
  170.     for comment in tbp.stream.comments():
  171.         threat_level = comment.submission.link_flair_css_class
  172.  
  173.         if threat_level == None or comment.submission.link_flair_text == None:
  174.             threat_level = list(TODAYS_THREAT_LEVEL.keys())[randint(0, len(TODAYS_THREAT_LEVEL) - 1)]
  175.             log.info("Setting threat level for Submission '{0}' [{1}] to {2}".format(comment.submission.title, comment.submission.id, TODAYS_THREAT_LEVEL[threat_level]))
  176.             comment.submission.mod.flair(css_class=threat_level, text=TODAYS_THREAT_LEVEL[threat_level])
  177.         author_rank = comment.author_flair_css_class
  178.        
  179.         try:
  180.             if author_rank in threat_matrix["threat_level"]:
  181.                 #comment.remove()
  182.                 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))
  183.         except KeyError:
  184.             pass
  185.        
  186.         if datetime.now() > next_recalc:
  187.             update_flairs()
  188.             next_recalc = datetime.now() + timedelta(minutes=10)
  189.             log.debug("Next refresh: {0}".format(next_recalc))
  190.        
  191.         if comment.author != None:
  192.             name = comment.author.name
  193.            
  194.             if not name in users.keys():
  195.                 good_karma, bad_karma = calc_score(name)
  196.                 users[name] = Tracker(name, good_karma, bad_karma)
  197.                 log.info("New user: {0}".format(name))
  198.             elif datetime.now() > users[name].next_refresh:
  199.                 good_karma, bad_karma = calc_score(name)
  200.                 users[name].update(good_karma, bad_karma)
  201.                 log.debug("User: {0} scanned {1} times".format(name, users[name].scan_count))
  202.             else:
  203.                 log.debug("Skipping user: {0}, next refresh {1}".format(name, users[name].next_refresh))
  204.        
  205.         flair = comment.author_flair_css_class
  206.         if  user.current_flair != flair: user.current_flair = flair
  207.  
  208.         #if comment.author_flair_css_class == None:
  209.             #if users[comment.author].warned:
  210.             #   if TimeDelta(users[comment.author].warned_on, datetime.now()) > TimeDelta(days=1):
  211.             #       users[comment.author].comments_eaten.append(comment.id)
  212.             #       comment.remove()
  213.             #else:
  214.             #   Send PM to comment.author:
  215.             #       "To whom it may concern:
  216.             #  
  217.             #           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!
  218.             #    
  219.             #       etc. etc.
  220.             #       -Management"
  221.             #   users[comment.author].warned = datetime.now()
  222.         #else:
  223.             #if users[comment.author].warned = True and len(users[comment.author].comments_eaten) > 0:
  224.             #   for comment in users[comment.author].comments_eaten:
  225.             #       reddit.comment(id=comment).approve()        <-- might be pseudocode
  226.             #       users[comment.author].comments_eaten = []
  227.  
  228. NEED_TO_UPDATE_OBJCLASS = False
  229. try:
  230.     users = pickle.load(open("users.pickle", "rb"))
  231.     log.info("Re-loading database")
  232.     if NEED_TO_UPDATE_OBJCLASS:
  233.         log.debug("Updating object format")
  234.         for user in users.values():
  235.             users[user.name] = Tracker(user.name, user.good_karma, user.bad_karma, False, user.scan_count, user.next_refresh, user.is_approved, user.is_purged, user.current_flair, user.warned, user.comments_eaten)
  236.        
  237.  
  238. except IOError:
  239.     users = {}
  240.     log.info("I/O error accessing database, starting fresh")
  241.  
  242.  
  243. try:
  244.     botloop(datetime.now())
  245.  
  246. except prawcore.PrawcoreException:
  247.     praw_fucked_up()
  248.     botloop(datetime.now())
  249.  
  250. except KeyboardInterrupt:
  251.     log.info("VirtuteTron going off-line")
  252.     pickle.dump(users, open("users.pickle", "wb"))
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top