Advertisement
blueshiftlabs

SGS Google Doc drawing script

Aug 22nd, 2012
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.49 KB | None | 0 0
  1. import csv
  2. import random
  3. import sys
  4. import reddit
  5. import re
  6. import time
  7. from urllib2 import HTTPError
  8.  
  9. confirm_thread = 'yip5e'
  10. giveaway_thread = 'yf9q0'
  11.  
  12. #####################################################
  13.  
  14. Games = {}
  15. Users = {}
  16. banlist = None
  17.  
  18. def flush():
  19.     sys.stdout.flush()
  20.     sys.stderr.flush()
  21.  
  22. class Game(object):
  23.     name = ""
  24.     stock = 0
  25.     keys = None
  26.     winners = None
  27.     next_game = None
  28.    
  29.     def __init__(self, line):
  30.         name, stock, next_game, keys = line
  31.         self.winners = set()
  32.         self.name = name.strip()
  33.         self.stock = int(stock)
  34.         self.next_game = next_game.strip() or None
  35.         if keys:
  36.             self.keys = [x.strip() for x in keys.split(',')]
  37.         else:
  38.             self.keys = None
  39.  
  40.     def __repr__(self):
  41.         return "%s (x%d)" % (self.name, self.stock)
  42.  
  43. class User(object):
  44.     name = ""
  45.     steam = ""
  46.     pif_eligible = False
  47.     wants = None
  48.  
  49.     def prune(self):
  50.         global Users
  51.        
  52.         removes = []
  53.         for i in xrange(len(self.wants)):
  54.             if self.wants[i].stock <= 0:
  55.                 removes.append(i)
  56.  
  57.         removes.reverse()
  58.         for i in removes:
  59.             self.wants.pop(i)
  60.  
  61.         if len(self.wants) == 0:
  62.             print "Removing user %s" % self.name
  63.             return True
  64.         else:
  65.             return False
  66.  
  67.     def win(self):
  68.         global Users
  69.  
  70.         if len(self.wants) == 0:
  71.             raise ValueError("User %s doesn't want anything" % self.name)
  72.  
  73.         won = self.wants[0]
  74.         if won.stock <= 0:
  75.             raise ValueError("Oversold game %s" % str(won))
  76.  
  77.         print "%s wins %s" % (self.name, won.name)
  78.  
  79.         Users.remove(self)
  80.  
  81.         won.winners.add(self)
  82.  
  83.         won.stock = won.stock - 1
  84.  
  85.         not_winners = set()
  86.         if won.stock == 0:
  87.             for user in Users:
  88.                 if user.prune():
  89.                     not_winners.add(user)
  90.  
  91.         for u in not_winners:
  92.             Users.remove(u)
  93.  
  94.     def __init__(self, line):
  95.         global Games
  96.        
  97.         self.name = line[1].strip().lower()
  98.         self.steam = line[2].strip()
  99.         games = line[3:12]
  100.  
  101.         self.wants = []
  102.  
  103.         for name in games:
  104.             game = Games.get(name)
  105.             while game:
  106.                 self.wants.append(game)
  107.                 game = Games.get(game.next_game)
  108.  
  109.         print "%s wants %s" % (self.name, ", ".join(x.name for x in self.wants))
  110.  
  111.     def __repr__(self):
  112.         return self.name
  113.  
  114. with open('banlist.txt', 'r') as banfile:
  115.     banlist = set(x.strip().lower() for x in banfile.readlines())
  116.  
  117. print 'Loaded %d banned users' % len(banlist)
  118. flush()
  119.  
  120. r = reddit.Reddit('/u/blueshiftlabs/drawing.py')
  121. r.config.api_request_delay = 0.5
  122.  
  123. print 'Log in to reddit to check users.'
  124. flush()
  125.  
  126. success = False
  127. while not success:
  128.     try:
  129.         r.login('blueshiftlabs')
  130.         success = True
  131.     except reddit.errors.InvalidUserPass:
  132.         print "Invalid password"
  133.         flush()
  134.         pass
  135. confirm = r.info(thing_id='t3_'+confirm_thread).next()
  136. giveaway = r.info(thing_id='t3_'+giveaway_thread).next()
  137. sgs = r.get_subreddit('SteamGameSwap')
  138.  
  139. giveaway_match = re.match(u'\[GIVEAWAY\] (.*)', giveaway.title, re.I)
  140.  
  141. if not giveaway_match:
  142.     raise ValueError("Invalid giveaway thread!")
  143.  
  144. giveaway_title = giveaway_match.group(1)
  145. print 'Giveaway name: %s' % giveaway_title
  146.  
  147. print
  148. print '=================='
  149. print
  150.  
  151. flush()
  152.  
  153. with open('games.csv', 'r') as gamesfile:
  154.     gamesreader = csv.reader(gamesfile)
  155.     gamesreader.next() # skip header
  156.     for gameline in gamesreader:
  157.         game = Game(gameline)
  158.         Games[game.name] = game
  159.         print 'Added %s' % game
  160.         flush()
  161.  
  162. print
  163. print '=================='
  164. print
  165.  
  166. with open('entries.csv', 'r') as entriesfile:
  167.     entryreader = csv.reader(entriesfile)
  168.     entryreader.next()
  169.     for entry in entryreader:
  170.         flush()
  171.         if len(entry) == 0 or not entry[0]:
  172.             continue
  173.  
  174.         user = User(entry)
  175.         if not user.wants:
  176.             print 'User %s does not want anything' % user.name
  177.             continue
  178.         username = user.name.lower()
  179.         if username in banlist:
  180.             print 'User %s is banned' % user.name
  181.         else:
  182.             action = 'Updated' if username in Users else 'Added'
  183.             Users[username] = user
  184.             print '%s entry for %s' % (action, user.name)
  185.             print
  186.  
  187. print
  188. print '=================='
  189. print
  190.  
  191. flush()
  192.  
  193. # Discard the user-lookup capabilities - we don't need them any longer.
  194. # Handle user data lookups now too.
  195. new_users = set()
  196. time_now = time.time()
  197.  
  198. accepted = 0
  199. rejected = 0
  200. invalid = 0
  201.  
  202. for user in Users.values():
  203.     print 'Looking up %s... ' % user.name,
  204.     flush()
  205.     try:
  206.         # userdata = r.get_redditor(user.name)
  207.         info_url = r.config['user_about'] % user.name
  208.         userdata = reddit.objects.RedditContentObject(r, None, True, info_url)
  209.         # Fix case.
  210.         user.name = userdata.name
  211.  
  212.         days = int((time_now - userdata.created) / (24 * 60 * 60)) + 1
  213.         karma = userdata.link_karma + userdata.comment_karma
  214.  
  215.         if days < 60 or karma < 300:
  216.             flair = sgs.get_flair(userdata.name)
  217.             if not flair["flair_css_class"]:
  218.                 print '%s does not meet requirements (%d days, %d karma)' % (user.name, days, karma)
  219.                 rejected = rejected + 1
  220.                 continue
  221.             else:
  222.                 print '%s OK by flair (%s, %d days, %d karma)' % (user.name, flair["flair_css_class"], days, karma)
  223.                 user.pif_eligible = False
  224.  
  225.         else:
  226.             print '%s OK by time/karma (%d days, %d karma)' % (user.name, days, karma)
  227.             user.pif_eligible = True
  228.  
  229.         accepted = accepted + 1
  230.         new_users.add(user)
  231.     except HTTPError:
  232.         print 'Not a valid username!'
  233.         invalid = invalid + 1
  234.         continue
  235.  
  236. print 'Processed %d usernames: %d accepted, %d rejected, %d invalid' % (len(Users), accepted, rejected, invalid)
  237. flush()
  238. Users = new_users
  239.  
  240. print
  241. print '=================='
  242. print
  243.  
  244. # Draw winners
  245. while len(Users) > 0:
  246.     winner = random.sample(Users, 1)[0]
  247.     winner.win()
  248.     flush()
  249.  
  250. print
  251. print '=================='
  252. print
  253.  
  254. # Print results
  255. for game in Games.values():
  256.     print '***'
  257.     print
  258.     print '## %s' % game.name
  259.     print
  260.     print 'Winners: %s' % (', '.join('[%(name)s](/user/%(name)s)' % {'name': x} for x in game.winners))
  261.     print
  262.     if game.stock:
  263.         print 'Stock remaining: %d' % game.stock
  264.         print
  265.     flush()
  266.  
  267. print
  268. print '=================='
  269. print
  270.  
  271. i = 0
  272. print 'PiF eligible winners:'
  273. for game in Games.values():
  274.     for winner in game.winners:
  275.         if winner.pif_eligible:
  276.             print '%s [%s]' % (winner.name, game.name)
  277.             i = i + 1
  278. print '%d total PiF-eligible winners.' % i
  279.  
  280. print
  281. print '=================='
  282. print
  283. flush()
  284.  
  285. raw_input('Press Enter to send messages.')
  286.  
  287. # Send messages
  288.  
  289. confirm_message_template = """
  290. ### Drawing Results: %(giveaway)s
  291.  
  292. [Giveaway thread here.](%(thread)s)
  293.  
  294. Game | Winner | Confirmed
  295. :--- | :----- | :--------
  296. %(results)s"""
  297.  
  298. confirm_result_template = "%s | %s | \n"
  299.  
  300. def generate_confirm_message():
  301.     wins = ((game.name, winner.name) for game in Games.values() for winner in game.winners)
  302.     results = "".join((confirm_result_template % win) for win in wins)
  303.     return confirm_message_template % {'giveaway': giveaway_title, 'thread': giveaway.permalink, 'results': results}
  304.  
  305. confirm_message = generate_confirm_message()
  306.  
  307. confirm_comment = confirm.add_comment(confirm_message)
  308.  
  309. print
  310. print ">>> Confirmation post: " + confirm_comment.permalink
  311. print
  312.  
  313. key_message = """Congratulations!
  314.  
  315. You won: **%(game)s**
  316.  
  317. Your key is: **%(key)s**
  318.  
  319. Once you have activated this key, please [confirm receipt here.](%(link)s)
  320. As a reminder, this key is not to be sold or traded._
  321.  
  322. Thanks,
  323.  
  324. blueshiftlabs (/r/SGS)"""
  325.  
  326. no_key_message = """Congratulations!
  327.  
  328. You won: **%(game)s**
  329.  
  330. Please **[add me on Steam](steam://friends/add/76561197981125077)** to receive your gift.
  331.  
  332. Once you have received your gift, please [confirm receipt here.](%(link)s)
  333.  
  334. _As a reminder, your gift is not to be sold or traded._
  335.  
  336. Thanks,
  337.  
  338. blueshiftlabs (/r/SGS)"""
  339.  
  340. for game in Games.values():
  341.     for winner in game.winners:
  342.         message = None
  343.         if game.keys is None:
  344.             message = no_key_message % { 'game': game.name, 'link': confirm_comment.permalink }
  345.             print '<no key provided> -> %s' % winner.name
  346.         else:
  347.             key = game.keys.pop()
  348.             message = key_message % { 'game': game.name, 'link': confirm_comment.permalink, 'key': key }
  349.             print '%s -> %s' % (key, winner.name)
  350.  
  351.         flush()
  352.         while True:
  353.             try:
  354.                 r.compose_message(winner.name, 'Congratulations!', message)
  355.                 break
  356.             except reddit.errors.ExceptionList as e:
  357.                 print "Error sending: " + str(e)
  358.                 new_username = raw_input("Change username? ")
  359.                 if new_username:
  360.                     winner.name = new_username
  361.                     continue
  362.                 else:
  363.                     print "Message not sent."
  364.                     break
  365.  
  366.  
  367. print
  368. print '=================='
  369. print
  370.  
  371. print 'Remaining keys:'
  372. for game in Games.values():
  373.     if game.keys:
  374.         print '%s: %s' % (game.name, ', '.join(game.keys))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement