Advertisement
Abahbob

Bot Source Code

Mar 2nd, 2015
517
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.85 KB | None | 0 0
  1. import sys
  2. import socket
  3. import string
  4. import urllib2
  5. import json
  6. import threading
  7. import time
  8. import random
  9. import select
  10. import re
  11. import quotelib
  12. import os
  13. import linecache
  14. from datetime import datetime, timedelta
  15.  
  16. RAW_CHATTERS = 'http://tmi.twitch.tv/group/user/%s/chatters'
  17. STREAM_API = 'https://api.twitch.tv/kraken/channels/abahbob'
  18. WORLD_RECORDS_API = 'http://www.speedrun.com/api_records.php?game='
  19. HOST="irc.twitch.tv"
  20. PORT=6667
  21. OWNER="Abahbob"
  22. NICK="Abahbot"
  23. PASS="***"
  24. BOTMODS=["Abahbob", "stuff"]
  25. channelfile="channels.txt"
  26. userlists={}
  27. readbuffer=""
  28. listcount=0
  29. CHANNELS={}
  30. spamlimit=[0]
  31. RUN=[1]
  32. PING = [0]
  33. chan_rights = ""
  34. bot_rights = ""
  35. log = open("log.txt", "a+")
  36. threshold = 60
  37. is_alive = [0]
  38. t = ""
  39. stream_info = ""
  40. FAQs = ""
  41. FAQs = json.load(open('FAQs.json', 'r'))
  42. quotes = quotelib.quotelib("quotes.json")
  43. msg_count = 0
  44. msg_threshold = 0
  45. last_notif = 0
  46. notif_number = 0
  47.  
  48. os.system ("echo '\e[0;32;40m'")
  49.  
  50. class start_new_thread(threading.Thread):
  51.     def __init__(self, callback, *args, **kwargs):
  52.         threading.Thread.__init__(self)
  53.         self.callback = lambda: callback(*args, **kwargs)
  54.         self.start()
  55.  
  56.     def run(self):
  57.         self.callback()
  58.  
  59. def send_data(command):
  60.     try:
  61.         print "+ "+command
  62.         s.send(command + "\r\n")
  63.     except (socket.error, socket.timeout):
  64.         print "- INFO - \"%s\" wasn't sent"
  65.  
  66. def receive_data(command):
  67.     print "- "+command
  68.  
  69. def send_msg(chan, msg):
  70.     send_data("PRIVMSG %s :%s" % (chan, msg))
  71.     print "%s[%s] %s: %s" % (t, chan, NICK, msg)
  72.     log.write("%s[%s] %s: %s\n" % (t, chan, NICK, msg))
  73.  
  74. def parsemsg(s):
  75.     prefix = ''
  76.     trailing = []
  77.     if s[0] == ':':
  78.         prefix, s = s[1:].split(' ', 1)
  79.     if s.find(' :') != -1:
  80.         s, trailing = s.split(' :', 1)
  81.         args = s.split()
  82.         args.append(trailing)
  83.     else:
  84.         args = s.split()
  85.     command = args.pop(0)
  86.     return prefix, command, args
  87.  
  88. def get_list(chan):
  89.     while (chan in CHANNELS):
  90.         try:
  91.             data = urllib2.urlopen(RAW_CHATTERS % chan[1:])
  92.         except:
  93.             time.sleep(5)
  94.             continue
  95.         userlist = json.load(data)['chatters']
  96.         userlists[hash(chan)] = userlist
  97.         time.sleep(10)
  98.     print "XXXX userlist update thread for %s is dead XXXX\n" % chan
  99.  
  100. def update_chans(chans):
  101.     f = open(channelfile, "w")
  102.     for line in chans:
  103.         f.write(line+"\n")
  104.     f.close()
  105.  
  106. def is_chatmod(chan, nick):
  107.     if(nick in userlists[hash(chan)]["moderators"]):
  108.         return 1
  109.     return 0
  110.  
  111. def is_mod(chan, nick):
  112.     if(nick in userlists[hash(chan)]["moderators"]):
  113.         return 1
  114.     return is_botmod(nick)
  115.  
  116. def is_viewer(chan, nick):
  117.     if(nick in userlists[hash(chan)]["viewers"]):
  118.         return 1
  119.     return 0
  120.  
  121. def is_botmod(nick):
  122.     if(nick in BOTMODS):
  123.         return 1
  124.     return 0
  125.  
  126. def is_owner(nick):
  127.     if(nick.lower()==OWNER.lower()):
  128.         return 1
  129.     return 0
  130.  
  131. def is_me(nick):
  132.     if(nick.lower()==NICK.lower()):
  133.         return 1
  134.     return 0
  135.  
  136. def make_chan(word):
  137.     return word if (word[0] == "#") else "#" + word
  138.  
  139. def make_not_chan(word):
  140.     return word if (word[0] != "#") else word[1:]
  141.  
  142. def bot(chan, nick, line):
  143.     global stream_info, msg_count, last_notif, notif_number
  144.     line = line.lower()
  145.     msg = string.split(line, " ")
  146.     msg_count+=1
  147.     chan = chan.lower()
  148.     nick = nick.lower()
  149.     if(msg[0]=="!color" and is_botmod(nick) and len(msg) > 1):
  150.         send_msg(chan, "/color %s" % msg[1])
  151.         spamlimit[0] += 1
  152.     elif(msg[0]=="!title"):
  153.         send_msg(chan, stream_info["status"])
  154.         spamlimit[0] += 1
  155.     elif(msg[0]=="!game"):
  156.         send_msg(chan, stream_info["game"])
  157.         spamlimit[0] += 1
  158.     elif(msg[0]=="!wr"):
  159.         if(len(msg) <= 1):
  160.             send_msg(chan, getWR(stream_info["game"], "Any%"))
  161.         if(len(msg) == 2):
  162.             send_msg(chan, getWR(stream_info["game"], msg[1]))
  163.         if(len(msg) >= 3):
  164.             count = 0
  165.             game = ""
  166.             for word in msg:
  167.                 if(count > 0 and count < len(msg) - 1):
  168.                     game += msg[count] + " "
  169.                 count += 1
  170.             send_msg(chan, getWR(game, msg[-1]))
  171.     elif(msg[0]=="!faq"):
  172.         try:
  173.             FAQ = FAQs[stream_info["game"]]
  174.             send_msg(chan, stream_info["game"] + " FAQ: " + FAQ)
  175.         except:
  176.             title = str.lower(str(stream_info["status"]))
  177.             if("%" in title or "speedrun" in title):
  178.                 send_msg(chan, "Speedrunning FAQ: " + FAQs["Speedrun"])
  179.             elif(("glitch" in title) or ("break" in title)):
  180.                 send_msg(chan, "Glitch Hunting FAQ: " + FAQs["GlitchHunt"])
  181.         spamlimit[0] += 1
  182.     elif(msg[0]=="!pat"):
  183.         nick = nick.rstrip("0123456789")
  184.         if(is_owner(nick)):
  185.             send_msg(chan, "%s-senpai <3" % OWNER)
  186.         spamlimit[0] += 1
  187.     elif(msg[0]=="!ask"):
  188.         rng = random.randint(0,899)
  189.         rng /= 100
  190.         if(rng>=5):
  191.             rng-=4
  192.             if(rng == 1):
  193.                 send_msg(chan, "I suppose yes... but it's not like I agree or anything! Baka...")
  194.             if(rng == 2):
  195.                 send_msg(chan, "Yes... I just happened to know the answer, it has nothing to do with you, o-okay!")
  196.             if(rng == 3):
  197.                 send_msg(chan, "Yes. Consider yourself lucky that I answered you!")
  198.             if(rng == 4):
  199.                 send_msg(chan, "Yes... probably... Not that I wanted to tell you b-baka!")
  200.         elif(rng>=1):
  201.             if(rng == 1):
  202.                 send_msg(chan, "No, now go die you freak")
  203.             if(rng == 2):
  204.                 send_msg(chan, "N-No... okay!?")
  205.             if(rng == 3):
  206.                 send_msg(chan, "No, not that I care or anything...")
  207.             if(rng == 4):
  208.                 send_msg(chan, "It is no and it is obvious! Are you stupid %s?" % nick)
  209.         else:
  210.             send_msg(chan, "Why are you asking me, does it turn you on to ask a girl things like that? P-pervert!")
  211.         spamlimit[0] += 1
  212.     elif(msg[0]=="!shoot" and is_mod(chan, nick) and len(msg) >= 2):
  213.         send_msg(chan, "/me fires a bullet at %s." % msg[1])
  214.         send_msg(chan, "/timeout %s 1" % msg[1])
  215.         spamlimit[0] += 1
  216.     elif(msg[0]=="!shootrand" and is_mod(chan, nick)):
  217.         if (len(userlists[hash(chan)]["viewers"]) > 0):
  218.             rand = random.randint(0, len(userlists[hash(chan)]["viewers"]))
  219.             if (rand == len(userlists[hash(chan)]["viewers"])):
  220.                 send_msg(chan, "/me fires a bullet randomly but fortunately nobody receives damage")
  221.             else:
  222.                 user = userlists[hash(chan)]["viewers"][rand]
  223.                 send_msg(chan, "/me fires a bullet randomly and %s gets shot" % user)
  224.                 send_msg(chan, "/timeout %s 1" % user)
  225.                 spamlimit[0] += 1
  226.         else:
  227.             send_msg(chan, "There's nobody to shoot!")
  228.         spamlimit[0] += 1
  229.     elif(msg[0]=="!quote"):
  230.         if len(msg) >= 3 and re.match("^\d*$",msg[2]):
  231.             send_msg(chan, quotes.quote(msg[1], int(msg[2])))
  232.         elif len(msg) >= 2:
  233.             send_msg(chan, quotes.quote(msg[1]))
  234.         else:
  235.             send_msg(chan, quotes.quote())
  236.     if(msg_count >= msg_threshold + random.randint(5, 10) and time.time() - last_notif > 1200):
  237.         time.sleep(1)
  238.         msg_count = 0
  239.         last_notif = time.time()
  240.         if(notif_number == 0):
  241.             try:
  242.                 FAQ = FAQs[stream_info["game"]]
  243.                 send_msg(chan, stream_info["game"] + " FAQ: " + FAQ)
  244.             except:
  245.                 title = str.lower(str(stream_info["status"]))
  246.                 if("%" in title or "speedrun" in title):
  247.                     send_msg(chan, "Speedrunning FAQ: " + FAQs["Speedrun"])
  248.                 elif(("glitch" in title) or ("break" in title)):
  249.                     send_msg(chan, "Glitch Hunting FAQ: " + FAQs["GlitchHunt"])
  250.             notif_number += 1
  251.         elif(notif_number == 1):
  252.             send_msg(chan, "Like the stream? Be sure to follow!")
  253.             notif_number = 0
  254.    
  255. def getWR(game, category):
  256.     try:
  257.         url = (WORLD_RECORDS_API + game).replace(' ',"%20")
  258.         result = json.load(urllib2.urlopen(url))
  259.         times = result[result.keys()[0]]
  260.         time = -1
  261.         for key in times.keys():
  262.             if(str.lower(category) in str.lower(str(key))):
  263.                 if(time == -1 or time > times[key]["time"]):
  264.                     important_time = times[key]
  265.                     cate = key
  266.                     time = int(times[key]["time"])
  267.         return cate + " in " + str(timedelta(seconds=time)) + " by " + important_time["player"]
  268.     except:
  269.         return "Record not found"
  270.            
  271. def cmd(chan, nick, line):
  272.     line = line.lower()
  273.     msg = string.split(line, " ")
  274.     chan = chan.lower()
  275.     nick = nick.lower()
  276.     if(msg[0]=="!join" and is_botmod(nick) and len(msg) > 1):
  277.         chan2 = make_chan(msg[1])
  278.         if(not chan2 in CHANNELS):
  279.             send_data("JOIN %s" % chan2)
  280.             CHANNELS.append(chan2)
  281.             update_chans(CHANNELS)
  282.             start_new_thread(get_list,chan2)
  283.     elif(msg[0]=="!quit" and is_botmod(nick) and ((chan!="#"+OWNER.lower() and chan!="#"+NICK.lower()) or len(msg)!=1)):
  284.         if(len(msg) == 1):
  285.             if(chan in CHANNELS):
  286.                 send_data("PART %s" % chan)
  287.                 CHANNELS.remove(chan)
  288.                 update_chans(CHANNELS)
  289.         else:
  290.             chan2 = make_chan(msg[1])
  291.             if(chan2 in CHANNELS and chan2!="#"+OWNER.lower() and chan2!="#"+NICK.lower()):
  292.                 send_data("PART %s" % chan2)
  293.                 CHANNELS.remove(chan2)
  294.                 update_chans(CHANNELS)
  295.     elif(msg[0]=="!list" and is_owner(nick)):
  296.         if(len(msg) > 1):
  297.             chan = make_chan(msg[1])
  298.         if (chan in CHANNELS):
  299.             print "staff:"
  300.             print userlists[hash(chan)]["staff"]
  301.             print "admins:"
  302.             print userlists[hash(chan)]["admins"]
  303.             print "moderators:"
  304.             print userlists[hash(chan)]["moderators"]
  305.             print "viewers:"
  306.             print userlists[hash(chan)]["viewers"]
  307.     elif(msg[0]=="!exit" and is_owner(nick)):
  308.         for chan in CHANNELS:
  309.             send_data("PART %s" % chan)
  310.         while(len(CHANNELS) > 0):
  311.             CHANNELS.pop()
  312.         RUN[0] = 0
  313.         log.close()
  314.         send_data("QUIT leavin'~")
  315.         sys.exit()
  316.     elif(msg[0]=="!chans" and is_owner(nick)):
  317.         print "channels:"
  318.         for chans in CHANNELS:
  319.             print " "+chans
  320.     elif(msg[0]=="!test" and is_owner(nick)):
  321.         send_data("WHO %s" % chan)
  322.  
  323.  
  324. def spam_block():
  325.     while(RUN[0]):
  326.         time.sleep(5)
  327.         if(spamlimit[0] > 0):
  328.             spamlimit[0] -= 1
  329.     print "XXXX Spam block is dead XXXX\n"
  330.  
  331. def update_info():
  332.     global stream_info
  333.     while 1:
  334.         try:
  335.             result = urllib2.urlopen(STREAM_API)
  336.             stream_info = json.load(result)
  337.         except urllib2.URLError, e:
  338.             print("Error loading stream info")
  339.         time.sleep(2)
  340.    
  341. def check_connection ():
  342.     while is_alive[0] == 0:
  343.         continue
  344.     connected = 1
  345.     while (connected and is_alive[0]):
  346.         time.sleep(60)
  347.         ping_time = time.time()
  348.         print "atashi no pingu~"
  349.         try:
  350.             s.send("PING tsundere\r\n")
  351.         except (socket.error, socket.timeout):
  352.             print "ping failed"
  353.             break
  354.         while (time.time() - ping_time < threshold and is_alive[0]):
  355.             connected = 0
  356.             if PING[0]:
  357.                 pong_time= time.time() - ping_time
  358.                 print "response time %fs" % pong_time
  359.                 PING[0] = 0
  360.                 connected = 1
  361.                 break
  362.     connected = 0
  363.     is_alive[0] = 0
  364.     start_new_thread(check_connection)
  365.    
  366. start_new_thread(spam_block)
  367. start_new_thread(update_info)
  368.  
  369. with open(channelfile) as f:
  370.     CHANNELS = f.read().splitlines()
  371. f.close()
  372.  
  373. while is_alive[0] == 0:
  374.     s=socket.socket()
  375.     try:
  376.         s.connect((HOST, PORT))
  377.         send_data("PASS %s" % PASS)
  378.         send_data("NICK %s" % NICK)
  379.         send_data("USER %s 0 * :%s" % (NICK, OWNER))
  380.         for chan in CHANNELS:
  381.             send_data("JOIN %s" % chan)
  382.         is_alive[0] = 1
  383.     except (socket.error, socket.timeout):
  384.         s.close()
  385.         os.system ("echo '\e[0;37;44m'")
  386.         print "++++++++++++++ connection failed, retrying in 5s"
  387.         time.sleep(5)
  388.         continue
  389.  
  390. for chan in CHANNELS:
  391.     start_new_thread(get_list, chan)
  392.  
  393. os.system ("echo '\e[0;32;40m'")
  394. print "-------------- connected"
  395. t = datetime.now().strftime("%H:%M:%S on %B %d, %Y")
  396. print "session start at %s" % (t)
  397. #start_new_thread(check_connection)
  398.  
  399. while 1:
  400.     try:
  401.         readbuffer=readbuffer+s.recv(1024)
  402.         #if is_alive[0] == 0:
  403.             #raise socket.timeout("missing pong")
  404.     except (socket.error, socket.timeout):
  405.         os.system ("echo '\e[0;37;44m'")
  406.         readbuffer=""
  407.         print "\n++++++++++++++ disconnected"
  408.         s.close()
  409.         print "-------------- reconnection"
  410.         s=socket.socket()
  411.         try:
  412.             s.connect((HOST, PORT))
  413.             send_data("PASS %s" % PASS)
  414.             send_data("NICK %s" % NICK)
  415.             send_data("USER %s 0 * :%s" % (NICK, OWNER))
  416.             for chan in CHANNELS:
  417.                 send_data("JOIN %s" % chan)
  418.             print "-------------- reconnected\n"
  419.             #is_alive[0] = 1
  420.             os.system ("echo '\e[0;32;40m'")
  421.         except (socket.error, socket.timeout):
  422.             print "++++++++++++++ reconnection failed retrying in 5s"
  423.             time.sleep(5)
  424.             continue
  425.         continue
  426.     except Exception, e:
  427.         print e
  428.         time.sleep(5)
  429.         continue
  430.     temp=string.split(readbuffer, "\r\n")
  431.     readbuffer=temp.pop()
  432.     t = datetime.now().strftime("[%H:%M:%S]")
  433.  
  434.     for line in temp:
  435.         prefix, command, params = parsemsg(line)
  436.         nick = string.split(prefix,"!")
  437.        
  438.         if(command=="PING"):
  439.             print t
  440.             print "anata no pingu~"
  441.             data = params.pop(0)
  442.             print "atashi no pongu~"
  443.             try:
  444.                 s.send("PONG :%s\r\n" % data)
  445.             except socket.error, socket.timeout:
  446.                 print "- INFO - \"atashi no pongu~\" wasn't sent"
  447.         elif(command=="PONG"):
  448.             print "anata no pongu~"
  449.             #PING[0] = 1
  450.         elif(command=="PRIVMSG"):
  451.             chan = params.pop(0)
  452.             msg = params.pop(0)
  453.             msg = msg.rstrip()
  454.             if (nick[0]!="jtv"):
  455.                 chan_rights = "@" if is_chatmod(chan, nick[0]) else ""
  456.                 bot_rights = "$" if is_botmod(nick[0]) else ""
  457.             print "%s[%s] %s%s%s: %s" % (t, chan, bot_rights, chan_rights, nick[0], msg)
  458.             log.write("%s[%s] %s%s%s: %s\n" % (t, chan, bot_rights, chan_rights, nick[0], msg))
  459.             if(spamlimit[0] < 10):
  460.                 bot(chan, nick[0], msg)
  461.             cmd(chan, nick[0], msg)
  462.         elif(command=="JOIN"):
  463.             chan = params.pop(0)
  464.             print "%s joined [%s]" % (nick[0], chan)
  465.         elif(command=="PART"):
  466.             chan = params.pop(0)
  467.             print "%s left [%s]" % (nick[0], chan)
  468.         elif(command=="MODE"):
  469.             chan = params.pop(0)
  470.             nick = params.pop(1)
  471.             mode = params.pop(0)
  472.             print "[%s] gives %s to %s" % (chan, mode, nick)
  473.         elif(command=="001"):
  474.             print "welcome: %s" % params[1]
  475.         elif(command=="002"):
  476.             print "host: %s" % params[1]
  477.         elif(command=="003"):
  478.             print "creation date: %s" % params[1]
  479.         elif(command=="004"):
  480.             print "my info: %s" % params[1]
  481.         elif(command=="375"):
  482.             print "______________________________"
  483.             print params[1]
  484.         elif(command=="376"):
  485.             print params[1]
  486.             print "______________________________"
  487.         elif(command=="372"):
  488.             print "%s" % params[1]
  489.         elif(command=="315"):
  490.             print "end of /WHO for [%s]" % params[1]
  491.         elif(command=="353"):
  492.             print "receiving /NAMES for [%s]: %s" % (params[2],params[3])
  493.         elif(command=="366"):
  494.             print "end of /NAMES for [%s]" % params[1]
  495.         elif(command=="421"):
  496.             print "unknown command: %s" % params[1]
  497.         else:
  498.             receive_data(line)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement