Advertisement
MegaLoler

Tinychat Library revision 4

May 15th, 2012
285
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import rtmp_protocol
  2. import httplib
  3. from xml.dom.minidom import parseString
  4. import thread
  5. import time
  6. import random
  7. import socket
  8.  
  9. # Tinychat Library by MegaLoler
  10.  
  11. DEBUG = False
  12.  
  13. def httpRequest(server, resource, body="", headers={}, method="GET"):
  14.     connection = httplib.HTTPConnection(server)
  15.     connection.request(method, resource, body, headers)
  16.     response = connection.getresponse()
  17.     headers = response.getheaders()
  18.     data = response.read()
  19.     connection.close()
  20.     return (headers, data)
  21.    
  22. class TinychatMessage():
  23.     def __init__(self, msg, nick, user=None, recipient=None, color=None, pm=False):
  24.         self.msg = msg
  25.         self.nick = nick
  26.         self.user = user
  27.         self.recipient = recipient
  28.         self.color = color
  29.         self.pm = pm
  30.    
  31.     def printFormatted(self):
  32.         if self.pm:
  33.             pm = "(PM) "
  34.         else:
  35.             pm = ""
  36.         print(pm + self.recipient + ": " + self.nick + ": " + self.msg)
  37.  
  38. class TinychatUser():
  39.     def __init__(self, nick, id=None, color=None, lastMsg=None):
  40.         self.nick = nick
  41.         self.id = id
  42.         self.color = color
  43.         self.lastMsg = lastMsg
  44.  
  45. TINYCHAT_COLORS = ["#7db257", "#a78901", "#9d5bb5", "#5c1a7a", "#c53332", "#821615", "#a08f23", "#487d21", "#c356a3", "#1d82eb", "#919104", "#a990", "#b9807f", "#7bb224", "#1965b6", "#32a5d9"]
  46.  
  47. class TinychatRoom():
  48.     # Manages a single room connection 
  49.     def __init__(self, room, nick=None, passwd=None):
  50.         self.room = room
  51.         self.tcUrl = self._getTcUrl()
  52.         parts = self.tcUrl.split("/")
  53.         server = parts[2].split(":")
  54.         self.server = server[0]
  55.         self.port = int(server[1])
  56.         self.app = parts[3]
  57.         self.url = "http://tinychat.com/" + room
  58.         self.connected = False
  59.         self.queue = []
  60.         self.color = TINYCHAT_COLORS[random.randint(0, len(TINYCHAT_COLORS) - 1)]
  61.         self.nick = nick
  62.         self.passwd = passwd
  63.         if self.nick == "": self.nick = None
  64.         if self.passwd == "": self.passwd = None
  65.         self.topic = None
  66.         self.users = {}
  67.         self.echo = __name__ == "__main__"
  68.         self.stack = False
  69.  
  70.     def connect(self):
  71.         if not self.connected:
  72.             self.connection = rtmp_protocol.RtmpClient(self.server, self.port, self.tcUrl, self.url, '', self.app)
  73.             if self.nick:
  74.                 n = self.nick.lower()
  75.             else:
  76.                 n = ""
  77.             self.connection.connect([self.room, self._getAutoOp(), u'show', u'tinychat', n])
  78.             self.connected = True
  79.             self._listen()
  80.    
  81.     def disconnect(self):
  82.         if self.connected:
  83.             self.connected = False
  84.             try:
  85.                 self.connection.socket.shutdown(socket.SHUT_RDWR)
  86.             except:
  87.                 pass
  88.             self.onDisconnect()
  89.    
  90.     def poll(self):
  91.         q = self.queue
  92.         self.queue = []
  93.         return q
  94.        
  95.     # Commands
  96.     def say(self, msg):
  97.         if len(msg) > 152: return
  98.         self._sendCommand("privmsg", [u"" + self._encodeMessage(msg), u"" + self.color + ",en"])
  99.        
  100.     def pm(self, msg, recipient):
  101.         if len(msg) > 152: return
  102.         self._sendCommand("privmsg", [u"" + self._encodeMessage("/msg " + recipient + " " + msg), u"" + self.color + ",en", u"n" + self._getUser(recipient).id + "-" + recipient])
  103.        
  104.     def setNick(self, nick=None):
  105.         if not nick: nick = self.nick
  106.         self.nick = nick
  107.         self._sendCommand("nick", [u"" + nick])
  108.    
  109.     def cycleColor(self):
  110.         try:
  111.             i = TINYCHAT_COLORS.index(self.color)
  112.         except:
  113.             i = TINYCHAT_COLORS[random.randint(0, len(TINYCHAT_COLORS) - 1)]
  114.         i = (i + 1) % len(TINYCHAT_COLORS)
  115.         self.color = TINYCHAT_COLORS[i]
  116.    
  117.     def ban(self, nick):
  118.         self._sendCommand("kick", [u"" + nick, self._getUser(nick).id])
  119.    
  120.     # Events
  121.     def onMessage(self, user, message):
  122.         if self.echo: message.printFormatted()
  123.        
  124.     def onPM(self, user, message):
  125.         if self.echo: message.printFormatted()
  126.    
  127.     def onQuit(self, user):
  128.         if self.echo: print(self.room + ": " + user.nick + " left the room.")
  129.    
  130.     def onBan(self, user):
  131.         if self.echo: print(self.room + ": " + user.nick + " was banned.")
  132.    
  133.     def onJoin(self, user):
  134.         if self.echo: print(self.room + ": " + user.nick + " entered the room.")
  135.    
  136.     def onRegister(self, user):
  137.         if self.echo: print("You have connected to " + self.room + ".")
  138.    
  139.     def onNickChange(self, new, old, user):
  140.         if self.echo: print(self.room + ": " + old + " changed nickname to " + new + ".")
  141.    
  142.     def onTopic(self, topic):
  143.         if self.echo: print(self.room + ": Topic set to \"" + topic + "\".")
  144.    
  145.     def onUserList(self, users):
  146.         pass
  147.    
  148.     def onDisconnect(self):
  149.         if self.echo: print("You have disconnected from " + self.room + ".")
  150.    
  151.     # Helper methods
  152.     def _listen(self):
  153.         while self.connected:
  154.             try:
  155.                 msg = self.connection.reader.next()
  156.                 if DEBUG: print("SERVER: " + str(msg))
  157.                 if msg['msg'] == rtmp_protocol.DataTypes.COMMAND:
  158.                     pars = msg['command']
  159.                     cmd = pars[0].encode("ascii", "ignore").lower()
  160.                     if len(pars) > 3:
  161.                         pars = pars[3:]
  162.                     else:
  163.                         pars = []
  164.                     for i in range(len(pars)):
  165.                         if type(pars[i]) == str: pars[i] = pars[i].encode("ascii", "ignore")
  166.                     if cmd == "privmsg":
  167.                         recipient = pars[0]
  168.                         message = pars[1]
  169.                         color = pars[2].lower().split(",")[0]
  170.                         nick = pars[3]
  171.                         if recipient[0] == "#":
  172.                             recipient = "^".join(recipient.split("^")[1:])
  173.                         else:
  174.                             recipient = "-".join(recipient.split("-")[1:])
  175.                         user = self._getUser(nick)
  176.                         message = TinychatMessage(self._decodeMessage(message), nick, user, recipient, color)
  177.                         user.lastMsg = message
  178.                         user.color = color
  179.                         if self.stack: self.queue.append(message)
  180.                         if recipient.lower() == self.nick.lower():
  181.                             message.pm = True
  182.                             if message.msg.startswith("/msg ") and len(message.msg.split(" ")) >= 2: message.msg = " ".join(message.msg.split(" ")[2:])
  183.                             self.onPM(user, message)
  184.                         else:
  185.                             self.onMessage(user, message)
  186.                     elif cmd == "registered":
  187.                         if self.nick: self.setNick()
  188.                         user = self._getUser(pars[0])
  189.                         user.id = pars[1]
  190.                         self.onRegister(user)
  191.                     elif cmd == "topic":
  192.                         self.topic = pars[0]
  193.                         self.onTopic(self.topic)
  194.                     elif cmd == "nick":
  195.                         user = self._getUser(pars[0])
  196.                         old = user.nick
  197.                         user.nick = pars[1]
  198.                         if old.lower() in self.users.keys():
  199.                             del self.users[old.lower()]
  200.                             self.users[user.nick.lower()] = user
  201.                         self.onNickChange(user.nick, old, user)
  202.                     elif cmd == "quit":
  203.                         user = self.users[pars[0].lower()]
  204.                         del self.users[pars[0].lower()]
  205.                         self.onQuit(user)
  206.                     elif cmd == "kick":
  207.                         self.onBan(user = self.users[pars[1].lower()])
  208.                     elif cmd == "join":
  209.                         user = self._getUser(pars[1])
  210.                         user.id = pars[0]
  211.                         self.onJoin(user)
  212.                     elif cmd == "joins":
  213.                         for i in range((len(pars) - 1) / 2):
  214.                             user = self._getUser(pars[i*2 + 2])
  215.                             user.id = pars[i*2 + 1]
  216.                     elif cmd == "joinsdone":
  217.                         self.onUserList(self.users)
  218.             except:
  219.                 self.disconnect()
  220.                    
  221.     def _getUser(self, nick):
  222.         if not nick.lower() in self.users.keys(): self.users[nick.lower()] = TinychatUser(nick)
  223.         return self.users[nick.lower()]
  224.    
  225.     def _decodeMessage(self, msg):
  226.         chars = msg.split(",")
  227.         msg = ""
  228.         for i in chars:
  229.             msg += chr(int(i))
  230.         return msg
  231.        
  232.     def _encodeMessage(self, msg):
  233.         msg2 = []
  234.         for i in msg:
  235.             msg2.append(str(ord(i)))
  236.         return ",".join(msg2)
  237.    
  238.     def _sendCommand(self, cmd, pars=[]):
  239.         msg = {"msg": rtmp_protocol.DataTypes.COMMAND, "command": [u"" + cmd, 0, None] + pars}
  240.         if DEBUG: print("CLIENT: " + str(msg))
  241.         self.connection.writer.write(msg)
  242.         self.connection.writer.flush()
  243.    
  244.     def _getTcUrl(self):   
  245.         return parseString(httpRequest("tinychat.com", "/api/find.room/" + self.room)[1]).getElementsByTagName("response")[0].getAttribute("rtmp")
  246.        
  247.     def _getAutoOp(self):
  248.         if self.nick and self.passwd:
  249.             headers = httpRequest("tinychat.com", "/login", "form_sent=1&referer=&next=&username=" + self.nick + "&password=" + self.passwd + "&passwordfake=Password&remember=1", {"Content-Type": "application/x-www-form-urlencoded"}, "POST")[0]
  250.             cookies = []
  251.             for header in headers:
  252.                 if header[0].lower() == "set-cookie":
  253.                     parts = header[1].split(", ")
  254.                     for i in range(len(parts)):
  255.                         part = parts[i]
  256.                         part2 = part.split(";")[0]
  257.                         if "=" in part2:
  258.                             if "," in part2:
  259.                                 part2 = part2.split(", ")[1]
  260.                             cookies.append(part2)
  261.                     break
  262.             if len(cookies) > 0:
  263.                 html = httpRequest("tinychat.com", "/" + self.room, "", {"Content-Type": "application/x-www-form-urlencoded", "Cookie": "; ".join(cookies)})[1]
  264.                 if ", autoop: \"" in html:
  265.                     return html.split(", autoop: \"")[1].split("\"")[0]
  266.         return u"none"
  267.  
  268. if __name__ == "__main__":
  269.     room = TinychatRoom(raw_input("Enter room name: "), raw_input("Enter username (optional): "), raw_input("Enter password (optional): "))
  270.     thread.start_new_thread(room.connect, ())
  271.     while not room.connected: time.sleep(1)
  272.     while room.connected: room.say(raw_input())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement