Advertisement
CVSoft

Stickybot IRC Framework

Jun 22nd, 2015
277
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.31 KB | None | 0 0
  1. import msvcrt
  2. import Queue
  3. import random
  4. import socket
  5. import string
  6. import sys
  7. import threading
  8. import time
  9.  
  10. irc = socket.socket()
  11.  
  12. #these get changed by user
  13. ch = "#flood"
  14. server = "irc.efnet.pl"
  15. port = "6667"
  16. event = ''
  17. nickname = "stickybot"
  18. send_queue = Queue.Queue(50)
  19. ctcp_version = "Stickybot IRC Framework, running on Python 2.7"
  20.  
  21. def send(arg):
  22.     irc.send(arg+"\r\n")
  23.     time.sleep(0.55)
  24.  
  25. def get_line_content(inp):
  26.     try:
  27.         if string.find(inp, ':', 2) > 0:
  28.             return inp[string.find(inp, ':', 2)+1:]
  29.         else:
  30.             return ''
  31.     except:
  32.         return "--- DEBUG Error in getLineContent"
  33.  
  34. def check_buffer(inp):
  35.     try:
  36.         return (True if inp[-1] in "\r\n" else False)
  37.     except:
  38.         return False
  39.  
  40. def strip_color(s):
  41.     k = string.split(s, '\x03')
  42.     o = ''
  43.     for x in k:
  44.         q = list(x)
  45.         l = 2
  46.         t = 0
  47.         while t < l:
  48.             if len(q) > 0:
  49.                 if q[0] == ',':
  50.                     l = 5
  51.                 if q[0] in "0123456789," and t != 3:
  52.                     q.pop(0)
  53.             t += 1
  54.         o += string.join(q, sep='')
  55.     for x in '\x02\x03\x1d\x1f\x0f':
  56.         o = string.replace(o, x, '')
  57.     return o
  58.  
  59. def split_ctcp(inp):
  60.     msgEnd = [0]
  61.     inp = string.rstrip(inp) + ' '
  62.     msgStart = string.find(inp, '\x01')
  63.     msgEnd[0] = string.find(inp, ' ', msgStart)
  64.     while msgEnd[len(msgEnd)-1] > 2:
  65.         msgEnd.append(string.find(inp, ' ', msgEnd[len(msgEnd)-1]+1))
  66.     msgEnd.pop()
  67.     msgEnd[len(msgEnd)-1] = (string.find(inp, '\x01') \
  68.                              if string.find(inp, '\x01') > msgStart + 1 \
  69.                              else msgEnd[len(msgEnd)-1]-1)
  70.     out = []
  71.     msgEnd.insert(0, msgStart)
  72.     i = 0
  73.     while msgEnd[i] > 2 and i < len(msgEnd)-1:
  74.         out.append(inp[msgEnd[i]+1:msgEnd[i+1]])
  75.         i += 1
  76.     #find sender
  77.     sender = inp[1:string.find(inp, '!', 2)]
  78.     out.insert(1, sender)
  79.     out[0] = string.upper(out[0])
  80.     for i in range(len(out)-1, 0, -1):
  81.         if out[i] == '':
  82.             out.pop(i)
  83.     return out
  84.  
  85. def reply_ctcp(target, req):
  86.     send("NOTICE "+target+" :\x01"+req+"\x01")
  87.  
  88. def send_ctcp(target, req):
  89.     send("PRIVMSG "+target+" :\x01"+req+"\x01")
  90.  
  91. def generate_lines(inp, lc):
  92.     doReset = False
  93.     inter = string.split(inp, "\r")
  94.     out = inter[lc]
  95.     lc += 1
  96.     if lc >= len(inter):
  97.         lc = 0
  98.         doReset = True
  99.     return [out, lc, doReset]
  100.  
  101. def privmsg(target, message):
  102.     send("PRIVMSG "+target+" :"+message)
  103.  
  104. def get_command(inp, command):
  105.     """boolean repr. if inp contains command"""
  106.     try:
  107.         return string.lower((getLine(inp)[2]+' '*(len(command)+3))\
  108.                             [:len(command)]) == command
  109.     except:
  110.         return False
  111.  
  112. # [channel, sender, text]
  113. def get_line(inp):
  114.     try:
  115.         out = [0,0,0,0]
  116.         out[1] = (string.split(inp, ' ')[0])[1:]
  117.         if "!" in out[1]:
  118.             out[1] = (string.split(out[1], '!'))[0]
  119.         out[0] = (string.split(inp, ' ')[2])
  120.         out[2] = inp[string.find(inp,':', 2)+1:]
  121.         out[3] = string.upper(inp[string.find(inp," ")+1:\
  122.                                   string.find(inp," ",string.find(inp," ")+1)])
  123.     except:
  124.         out = ['','error','','']
  125.     return out
  126.  
  127. def format_mode(inp):
  128.     try:
  129.         out = [0,0,0,0]
  130.         out[1] = (string.split(inp, ' ')[0])[1:]
  131.         if "!" in out[1]:
  132.             out[1] = (string.split(out[1], '!'))[0]
  133.         out[0] = (string.split(inp, ' ')[2])
  134.         out[2] = inp[string.find(inp,out[0])+len(out[0])+1:]
  135.         out[3] = string.upper(inp[string.find(inp," ")+1:\
  136.                                   string.find(inp," ",string.find(inp," ")+1)])
  137.     except:
  138.         return ['','','','']
  139.     return out
  140.  
  141. def hostmask(inp):
  142.     out = ['','--- DEBUG Error in hostmask()','']
  143.     if '!' not in inp or '@' not in inp:
  144.         return ['','--- DEBUG Error in hostmask(), missing trigger character',
  145.                 '']
  146.     out[0] = (string.split(inp,"!"))[0]
  147.     out[1] = inp[string.find(inp, '!')+1:string.find(inp, '@')]
  148.     out[2] = (inp[string.find(inp,'@')+1:]).split(' ')[0]
  149.     return out
  150.  
  151. def ping(inp):
  152.     inter = string.split(inp, ' ')
  153.     if string.lower(inter[0]) == "ping":
  154.         send(string.replace(inp, "PING", "PONG", 1))\
  155.  
  156. def connect(nick = "Python0", realname = "Real name", server = "localhost",
  157.             port = 6667):
  158.     if type(port) == str:
  159.         port = int(port)
  160.     tries = 0
  161.     while tries < 3:
  162.         try:
  163.             global irc
  164.             irc = socket.socket()
  165.             irc.setblocking(0)
  166.             irc.settimeout(0.5)
  167.             irc.connect((server, port))
  168.             time.sleep(0.5)
  169.             set_nick(nick)
  170.             send("USER "+nick+" localhost "+server+" :"+realname)
  171.             return True
  172.         except:
  173.             tries += 1
  174.             time.sleep(4)
  175.             if tries == 4:
  176.                 return False
  177.  
  178. def disconnect(partmsg = "Connection closed"):
  179.     global irc
  180.     #print "Closing..."
  181.     send("QUIT :"+partmsg)
  182.     irc.close()
  183.  
  184. ### general IRC features
  185.  
  186. def join(channel):
  187.     send("JOIN :"+channel)
  188.  
  189. def part(channel, message = ""):
  190.     send("PART :"+channel+" :"+message)
  191.  
  192. def set_nick(nick):
  193.     send("NICK "+nick)
  194.  
  195. def receive():
  196.     try:
  197.         return irc.recv(2048)
  198.     except:
  199.         return ''
  200.  
  201. ## END StickybotLayer
  202.    
  203. def handle_ctcp(inp):
  204.     if (string.find(inp, '\x01') > 2) and (string.find(inp, "PRIVMSG") > 2):
  205.         ctcp = split_ctcp(inp)
  206.         if "PING" in string.upper(ctcp[0]):
  207.             reply_ctcp(ctcp[1], "PING "+ctcp[2])
  208.         if "VERSION" in string.upper(ctcp[0]):
  209.             reply_ctcp(ctcp[1], "VERSION "+ctcp_version)
  210.  
  211. def check_error():
  212.     if (buff+' '*19)[0:19] == "ERROR :Closing Link: "[0:19]:
  213.         doExit = True
  214.  
  215. def check_nick():
  216.     if string.find(buff, ':', 2) > 11:
  217.         i = string.find(buff, ':', 2)+1
  218.         if (buff+' '*16)[i:i+15] == "Nickname is alr":
  219.             nick = "acarsdcl"+['`','_','^'][random.randrange(3)]
  220.             set_nick(nick)
  221.  
  222. def dt(inp):
  223.     return int(time.time()-inp)
  224.  
  225. def handle_motd(inp):
  226.     """this handles the MOTD, setting flag wasMOTD to true if it has passed.
  227.       input is the line to check if it is the end of a MOTD"""
  228.     global wasMOTD
  229.     if "End of /MOTD" in inp:
  230.         wasMOTD = True
  231.         join(ch)
  232.  
  233. def build_line_buffer():
  234.     """this code translates buffull into a line"""
  235.     global buff, buffull, lineCounter, doReset
  236.     bufftemp = '\x02'
  237.     while not (check_buffer(buffull)):
  238.         bufftemp = receive()
  239.         if bufftemp == '':
  240.             break
  241.         buffull = buffull+bufftemp
  242.     temp = generate_lines(buffull, lineCounter)
  243.     # generateLines returns [a line, lineCounter, doReset]
  244.     buff = string.strip(temp[0], "\r\n")
  245.     lineCounter = temp[1]
  246.     doReset = temp[2]
  247.     return (buff, doReset)
  248.  
  249. def handle_buffer():
  250.     try:
  251.         commands = ["killbot", "&nickchange"]
  252.         global doExit
  253.         r = irc_queue.get(False)
  254.         irc_queue.task_done()
  255.         if len(r) > 0 and r not in commands and "&nickchange" not in r:
  256.             privmsg(ch, r)
  257.         elif r == "&killbot":
  258.             doExit = True
  259.         #elif "&nickchange " in r and len(r) > 13:
  260.         #    set_nick(r.split(' ')[1])
  261.     except Queue.Empty:
  262.         return ''
  263.     except:
  264.         return "ERROR "+sys.exc_info()[1]
  265.         raise
  266.  
  267. def handle_send():
  268.     """sends a raw IRC line from send_queue Queue"""
  269.     # this should be the only code here that sends IRC lines
  270.     try:
  271.         l = send_queue.get(False)
  272.         send(l)
  273.         send_queue.task_done()
  274.         return True
  275.     except:
  276.         return False
  277.  
  278. def handler(buff, doReset):
  279.     global buffull
  280.     handle_motd(buff)
  281.     ping(buff)
  282.     check_nick()
  283.     handle_ctcp(buff)
  284.     handle_send()
  285.     time.sleep(0.01)
  286.     line_queue.put(buff)
  287.     if doReset:
  288.         buffull = ''
  289.         return False
  290.     return doReset
  291.  
  292. # connect to IRC
  293. def main():
  294.     connect(nickname, "acarsdbot", server, port)
  295.     global buff, buffull, ch, doExit, irc_queue, lineCounter, wasMOTD
  296.     buff, buffull = '', ''
  297.     doExit, doReset, wasMOTD = False, False, False
  298.     lineCounter = 0
  299.     while not (doExit):
  300.         buff, doReset = build_line_buffer()
  301.         #code goes from here to doReset's redefinition
  302.         if wasMOTD and len(buff)>0:
  303.             pass #print buff
  304.         if wasMOTD:
  305.             handle_buffer()
  306.         doReset = handler(buff, doReset)
  307.     disconnect()
  308.  
  309. # threading stuff previously done by calling code
  310. def start_thread():
  311.     global irc_thread, thread_running
  312.     try:
  313.         thread_running = True
  314.         irc_thread.start()
  315.     except:
  316.         thread_running = False
  317.  
  318. def kill_thread():
  319.     global doExit, thread_running
  320.     doExit = True
  321.     thread_running = False
  322.  
  323. def get_rline():
  324.     """Raw IRC from line queue"""
  325.     try:
  326.         l = line_queue.get(False)
  327.         line_queue.task_done()
  328.     except:
  329.         return ""
  330.     return l
  331.  
  332. def get_fline():
  333.     """Formatted text from line queue"""
  334.     pass # because this is not implemented
  335.  
  336. #these get changed by code
  337. thread_running = False
  338. line_queue = Queue.Queue(50)
  339. irc_queue = Queue.Queue(50)
  340. irc_thread = threading.Thread(target=main)
  341. irc_thread.daemon = True
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement