Advertisement
Guest User

Untitled

a guest
Jun 21st, 2017
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.21 KB | None | 0 0
  1. #Most normal chat commands like /timeout, /ban, /clear are sent with periods
  2. #in place of the forward slash. For example, to ban the user "xangold", you
  3. #would send ".ban xangold" to the server (minus the quotes).
  4.  
  5. """
  6. subscribers - tier 1 1000, tier 2 2500 tier 3 5000 / semaine
  7. DONE !gamble X : d100 50 -> x/2 gagnés
  8. !versus
  9. !contest
  10. DONE !makeitrain
  11. DONE !doubletrouble
  12. DONE !kekettes pour voir les kekettes
  13. cheer = 1000 points par 100 bits
  14. !addquote
  15. !quotelist
  16. cooldown sur les commandes
  17. DONE check pour pas dépasser 100 messages/15 minutes
  18. DONE methode pour print sur le chat p(pour la lisibilité et la convenience)
  19.  
  20. pseudo 1: !vs "pseudo2" "montant"
  21. bot: pseudo2 vous êtes challengé par "pseudo1"
  22. pseudo2: !vs pseudo1 "montant"
  23. plus on parie plus on a de chances de gagner base montant1=montant2 : 50/50
  24. montant1/(montant1+2)*100 %
  25. """
  26.  
  27. """
  28. Erreurs : List index is out of range sur les JOIN
  29. <class 'requests.exceptions.HTTPError'> : 400 Client Error: Bad Request for url: https://api.twitch.tv/kraken/users?login=: JOIN, problème d'API ?
  30. le bot ne distribue plus de kekettes
  31. !makeitrain : action quand même accomplie même si pas assez de points
  32. subscribers : problème d'authentification
  33.  
  34. erreur ?? JOIN ??
  35.     <class 'ValueError'> : invalid literal for int() with base 10:
  36.     "{'display_name': 'I', 'id': '51474635', 'name': 'i', 'type': 'user', 'bio': None, 'created_at': datetime.datetime(2013, 11, 13, 16, 2, 49, 71386), 'updated_at': datetime.datetime(2017, 5, 24, 18, 0,
  37. """
  38.  
  39. BOT_SECRET = 'xxx'
  40. BOT_OAUTH = 'oauth:xxx'
  41. TARGET_OAUTH = 'xxx'
  42. BOT_CLIENT_ID = 'xxx'
  43.  
  44. #########IMPORTS#########
  45. import socket
  46. import twitch #Not in standard libraries
  47. from twitch import TwitchClient #Not in standard libraries
  48. from twitch.api.streams import Streams #Not in standard libraries
  49. import csv
  50. import datetime
  51. import time
  52. from threading import Thread, RLock
  53. import random as rd
  54. import math
  55.  
  56. #########DEFINES##########
  57. lock = RLock()
  58.  
  59. BOT_HAS_STARTED = "KekettesBot est désormais lancé !"
  60. NOT_ENOUGH_POINTS = "{} n'a pas assez de kekettes pour cette action."
  61. DISPLAY_POINTS = "{} a {} kekettes."
  62. USER_CHALLENGED_YOU = "{0}, {1} t'as défié ! !versus {1} *montant* pour accepter, !versus deny pour refuser."
  63. DISPLAY_CHALLENGE_ODDS = "{0} has put {1} on the table. {2} has put {3} on the table. {0} has {4}% chances of winning !"
  64. VS_WIN = "You won your duel versus {0}, you win {} kekettes."
  65. VS_LOST = "You lost your duel versus {0}, you lose {} kekettes."
  66. GAMBLE_WON = "{} a tiré {} et a gagné {} kekettes !"
  67. GAMBLE_LOST = "{} a tiré {} et a perdu {} kekettes !"
  68. VALUE_ERROR_EXCEPTION = "Vous avez entré une valeur incorrecte"
  69. BOT_LEAVING_CHAT = "KekettesBot a quitté le chat, au revoir !"
  70. MADE_IT_RAIN = "Woohoo, {} fait pleuvoir des kekettes !"
  71. DOUBLE_TROUBLE_STARTED = "{} a lancé les double points ! Tout le monde gagne le double pendant 10 minutes !"
  72. DOUBLE_TROUBLE_ENDED = "Double points terminé !"
  73. SOURCE_CODE_MESSAGE = "Voilà le code source pour le bot : <link>"
  74.  
  75. QUOTES = []
  76. with open("quotes.txt", "r") as f:
  77.     for line in f:
  78.         QUOTES.append(line.rstrip("\n"))
  79.  
  80. next_call = time.time()
  81.  
  82. ########FUNCTION HANDLES FOR CMDS###########
  83. def sourcecode(users, text, user):
  84.     return SOURCE_CODE_MESSAGE, users
  85.  
  86. def quote(users, text, user):
  87.     return rd.choice(QUOTES), users
  88.  
  89. def denisbrogniart(users, text, user):
  90.     return "AH !", users
  91.  
  92. def helpkekettes(users, text, user):
  93.     return HELP_MESSAGE, users
  94.  
  95. def kekettes(users, text, user):
  96.     return DISPLAY_POINTS.format(user.username.capitalize(), user.current), users
  97.     pass
  98.  
  99. def gamble(users, text, user):
  100.     balance = user.current
  101.     try:
  102.         message = text.split(":")[-1]
  103.         gmbl = message.split()[-1]
  104.         gmbl = int(gmbl)
  105.         assert gmbl>0, "Amount supposed to be positive"
  106.     except ValueError:
  107.         return VALUE_ERROR_EXCEPTION, users
  108.     except AssertionError:
  109.         return VALUE_ERROR_EXCEPTION, users
  110.     if user.may_perform_action(gmbl):
  111.         user.add_points(-gmbl)
  112.     else:
  113.         return NOT_ENOUGH_POINTS.format(user.username.capitalize()), users
  114.     rng = rd.randint(1, 100)
  115.     if rng <50:
  116.         return GAMBLE_LOST.format(user.username.capitalize(), rng, gmbl), users
  117.     else:
  118.         winnings = gmbl*(math.ceil((rng-50)/50*4)+1)
  119.         user.add_points(winnings)
  120.         return GAMBLE_WON.format(user.username.capitalize(), rng, winnings-gmbl), users
  121.     pass
  122.  
  123. def doubletrouble(users, text, user):
  124.     username = username = text.split(":")[1].split("!")[0]
  125.     now = datetime.datetime.now().time()
  126.     then = addSecs(now, 600)
  127.     if user.may_perform_action(2000):
  128.         user.add_points(-2000)
  129.     else:
  130.         return NOT_ENOUGH_POINTS.format(user.username.capitalize()), users
  131.     return (then, DOUBLE_TROUBLE_STARTED.format(user.username.capitalize())), users
  132.     pass
  133.  
  134. def versus(users, text, user):
  135.     pass
  136.  
  137. def makeitrain(users, text, user):
  138.     if user.may_perform_action(3000):
  139.         user.add_points(-3000)
  140.     else:
  141.         return NOT_ENOUGH_POINTS.format(user.username.capitalize()), users
  142.     for u in users:
  143.         u.add_points(30)
  144.     return MADE_IT_RAIN.format(user.username.capitalize()), users
  145.     pass
  146.  
  147. ##########FUNCTIONS#########
  148. def addSecs(tm, secs):
  149.     fulldate = datetime.datetime(100, 1, 1, tm.hour, tm.minute, tm.second)
  150.     fulldate = fulldate + datetime.timedelta(seconds=secs)
  151.     return fulldate.time()
  152.  
  153. #########USER CLASS###########
  154. class User():
  155.     """
  156.     User class for bot users.
  157.     Each user is reprensented as an instance of this class. See self.users in KekettesBot class.
  158.    
  159.     ---
  160.     attributes :    username
  161.                     user_id
  162.                     current
  163.                     all_time
  164.                    
  165.     methods :       add_points(amount)          amount is either positive or negative, check may_perform_action if amount is negative
  166.                     may_perform_action(cost) cost is expected positive
  167.                     __repr__ : represents the class as username:id, current/all_time
  168.     """
  169.     def __init__(self, row):
  170.         self.fieldnames = ['username', 'user_id', 'current', 'all_time']
  171.         self.row = row
  172.         self._username = row["username"]
  173.         self._user_id = int(row["user_id"])
  174.         self._current = int(row["current"])
  175.         self._all_time = int(row['all_time'])
  176.        
  177.     def _get_username(self):
  178.         return self._username
  179.     def _set_username(self, new_username):
  180.         self._username = str(new_username)
  181.     def _get_user_id(self):
  182.         return self._user_id
  183.     def _set_user_id(self, id_):
  184.         self._user_id = id_
  185.     def _get_current(self):
  186.         return self._current
  187.     def _set_current(self, new_current):
  188.         delta = int(new_current) - int(self._current)
  189.         if delta >0:
  190.             self._all_time = int(self._all_time) + int(delta)
  191.         self._current = int(new_current)
  192.     def _get_all_time(self):
  193.         return int(self._all_time)
  194.     def _set_all_time(self, new_all_time):
  195.         self._all_time = int(new_all_time)
  196.     username = property(_get_username, _set_username)
  197.     user_id = property(_get_user_id, _set_user_id)
  198.     current = property(_get_current, _set_current)
  199.     all_time = property(_get_all_time, _set_all_time)
  200.    
  201.     def add_points(self, points_to_add):
  202.         self.current += points_to_add
  203.     def may_perform_action(self, cost):
  204.         return self.current-cost >=0
  205.     def __repr__(self):
  206.         return "{}:{}, {}/{}".format(self.username, self.user_id, self.current, self.all_time)
  207.  
  208. class KeketteBot(Thread):
  209.     def __init__(self, commands):
  210.         Thread.__init__(self)
  211.         self.stop = False
  212.         #CONFIG
  213.         self.channel_name = 'misterteamot'
  214.         self.channel_id = 89287341
  215.         self.channel_oauth = TARGET_OAUTH #teamot oauth
  216.         self.number_of_messages_sent = 0
  217.         self.max_messages = 100 #/30 sec
  218.         self.max_joins = 50 #/15 sec
  219.         self.base_drop_rate = 2 #per minute
  220.         self.points_multiplier = 1
  221.         self.csv_filename = "points.csv"
  222.         #IRC CONFIG
  223.         self.server = 'irc.chat.twitch.tv'
  224.         self.port = 6667
  225.         self.nickname = 'kekettesbot'
  226.         self.password = BOT_OAUTH #oauth token for the bot
  227.         self.commands = commands
  228.         self.given_to_subs = False
  229.         self.end_doubletrouble = datetime.datetime.now().time()
  230.         self.doubletroublechanged = False
  231.         self.time_start_daemon = time.time()
  232.         self.points_not_given = True
  233.         self.joined_users = []
  234.        
  235.         #Loader for csv data
  236.         fields = ['username', 'user_id', 'current', 'all_time']
  237.         #self.users = {'username':[], 'user_id':[], 'current':[], 'all_time':[]}
  238.         self.users = []
  239.         with open(self.csv_filename, "r") as csvfile:
  240.             reader = csv.DictReader(csvfile, fieldnames=fields)
  241.             i = 0
  242.             for row in reader:
  243.                 i+=1
  244.                 if i>1:
  245.                     self.users.append(User(row))
  246.                     #for f in fields:
  247.                     #   self.users[f].append(row[f])
  248.         print(self.users)
  249.         #IRC STUFF
  250.         self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #defines the socket
  251.         # Connect
  252.         #self.irc.bind((self.server, self.port))
  253.         self.irc.connect((self.server, self.port))
  254.         self.irc.setblocking(False)
  255.         self.irc.send("PASS {}\n".format(self.password).encode())
  256.         self.irc.send("NICK {}\n".format(self.nickname).encode())
  257.         self.irc.send("JOIN #{}\n".format(self.channel_name).encode())
  258.         self.irc.send("PRIVMSG #{} :{}\n".format(self.channel_name, BOT_HAS_STARTED).encode("UTF-8"))
  259.         self.irc.send("CAP REQ :twitch.tv/membership\n".encode())
  260.         self.irc.send("CAP REQ :twitch.tv/tags\n".encode())
  261.         #TWITCH API STUFF
  262.         self.client_id = BOT_CLIENT_ID
  263.         self.client = TwitchClient(self.client_id, self.channel_oauth)
  264.         print(self.client._oauth_token)
  265.         #self.channel = self.client.channels.get()
  266.         current_offset = 0
  267.         self.subscribers = []
  268.         self.subscribers_twitch = []
  269.         #while self.client.channels.get_subscribers(self.channel_id, limit=100, offset=current_offset):
  270.         #   self.subscribers_twitch.extend(self.get_subscribers.get_subscribers(self.channel_id, limit=100, offset=current_offset))
  271.         #   current_offset += 100
  272.  
  273.     def run(self):
  274.         while not self.stop:
  275.             with lock:
  276.                 if int(time.time()-self.time_start_daemon)%30==0:
  277.                     self.number_of_messages_sent = 0
  278.                 if datetime.datetime.now().time() > self.end_doubletrouble and self.doubletroublechanged:
  279.                     self.points_multiplier = 1
  280.                     self.irc_print(DOUBLE_TROUBLE_ENDED)
  281.                     self.doubletroublechanged = False
  282.                 if int(time.time()-self.time_start_daemon)%120==0 and self.points_not_given:#datetime.now().minute%2 == 0 and datetime.now().second == 1: #donne des kekettes toutes les 2 minutes
  283.                     self.points_not_given = False
  284.                     for user in self.joined_users: #TODO: les viewers qui n'ont pas encore de kekettes (les nouveaux)
  285.                         user.add_points(self.base_drop_rate*self.points_multiplier)
  286.                 if not self.points_not_given and int(time.time()-self.time_start_daemon)%121==0:
  287.                     self.points_not_given = True
  288.                 if datetime.datetime.now().weekday() == 0 and not self.given_to_subs: #Monday #Donne 1000 kekettes aux subs par semaine
  289.                     self.given_to_subs = True
  290.                     for sub in self.subscribers:
  291.                         sub.add_points(1000)
  292.                         #i = self.users["user_id"].index(str(sub.id_))
  293.                         #self.users["current"][i] += 1000
  294.                 try:
  295.                     text=self.irc.recv(4096).decode()
  296.                     print(text)
  297.                     # Prevent Timeout
  298.                     if text.find('PING') != -1:
  299.                         self.irc.send('PONG {}\r\n'.format(text.split()[1]).encode())
  300.                         print('PONG {}\r\n'.format(text.split()[1]))
  301.                     elif text.find("JOIN") != -1:
  302.                         username = text[1:].split("!")[0]
  303.                         user_id = int(self.client.users.translate_usernames_to_ids(list(username))[0].id)
  304.                         if user_id not in [x.user_id for x in self.users]:
  305.                             row={'username':username, 'user_id':user_id, 'current':0, 'all_time':0}
  306.                             u = User(row)
  307.                             self.users.append(u)
  308.                             self.joined_users.append(u)
  309.                         else:
  310.                             i = [x.user_id for x in self.users].index(user_id)
  311.                             self.joined_users.append(self.users[i])
  312.                     elif text.find("PART") != -1:
  313.                         username = text[1:].split("!")[0]
  314.                         user_id = int(self.client.users.translate_usernames_to_ids(list(username))[0].id)
  315.                         i = [x.user_id for x in self.joined_users].index(user_id)
  316.                         self.joined_users.pop(i)
  317.                     #If message received
  318.                     elif text.find('PRIVMSG') != -1:
  319.                         if "!quit" in text and "mod" in text.split("user-type=")[1].split(":")[0]:
  320.                             self.quit()
  321.                         for command, handle in self.commands.items():
  322.                             if text.find(command) != -1:
  323.                                 print("Command found !")
  324.                                 username = text.split(":")[1].split("!")[0]
  325.                                 user_id = text.split("user-id=")[1].split(";")[0]
  326.                                 index = [x.user_id for x in self.users].index(int(user_id))
  327.                                 user = self.users[index]
  328.                                 print((username, user_id))
  329.                                 output, self.users = handle(self.users, text, user)
  330.                                 print(output)
  331.                                 if type(output) == type(str()):
  332.                                     self.irc_print(output)
  333.                                 elif type(output) == type(tuple()):
  334.                                     self.points_multiplier += 1
  335.                                     self.end_doubletrouble = output[0]
  336.                                     self.doubletroublechanged = True
  337.                                     self.irc_print(output[1])
  338.                 except Exception as e:
  339.                     if "10035" not in repr(e):
  340.                         print("{} : {}".format(type(e), e))
  341.                     continue
  342.  
  343.     def quit(self):
  344.         self.irc_print(BOT_LEAVING_CHAT)
  345.         self.irc.send('PART'.encode())
  346.         self.irc.close()
  347.         self.stop = True
  348.         with open(self.csv_filename, 'w') as csvfile:
  349.             fieldnames = ['username', 'user_id', 'current', 'all_time']
  350.             writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
  351.             writer.writeheader()
  352.             for user in self.users:
  353.                 writer.writerow({
  354.                 'username': user.username,
  355.                 'user_id': user.user_id,
  356.                 'current': user.current,
  357.                 'all_time': user.all_time
  358.                 })
  359.     def irc_print(self, message):
  360.         if self.number_of_messages_sent<self.max_messages:
  361.             self.irc.send('PRIVMSG #{} :{}\n'.format(self.channel_name, str(message)).encode("UTF-8"))
  362.             self.number_of_messages_sent +=1
  363.  
  364. def main():
  365.     commands = {'!kekettes':kekettes, #displays the amount of points the user has
  366.                 '!gamble':gamble, #gamble a set amount of points
  367.                 '!makeitrain':makeitrain, #gives each user 30 points
  368.                 '!doubletrouble':doubletrouble, #double the drop-rate of points for 30 minutes
  369.                 '!versus':versus, # challenge un autre viewer a un versus
  370.                 '!help':helpkekettes, #Affiche l'aide
  371.                 '!quote':quote, #affiche une quote de teamot
  372.                 '!denisbrogniart': denisbrogniart, #AH !
  373.                 '!sourcecode':sourcecode #Affiche le lien vers le code source du bot
  374.                 }
  375.     cmds = [str(k) for k in commands.keys()]
  376.     cmd_str = ""
  377.     for i in cmds:
  378.         cmd_str += i+", "
  379.     cmd_str.rstrip(",")
  380.     global HELP_MESSAGE
  381.     HELP_MESSAGE = "Available Commands : {}".format(cmd_str)
  382.     bot = KeketteBot(commands)
  383.     print('KekettesBot is now running !')
  384.     bot.start()
  385.  
  386. if __name__ == '__main__':
  387.     main()
  388.     pass
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement