View difference between Paste ID: CBZVeXhW and TvJp0Gcx
SHOW: | | - or go back to the newest paste.
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-
			self.connection.socket.shutdown(socket.SHUT_RDWR)
84+
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())