Created
March 20, 2013 06:52
-
-
Save stefanbeller/5202811 to your computer and use it in GitHub Desktop.
TMW Whisperbot by gnurfk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
""" | |
Python Whisperbot | |
Copyright (C) 2010 Gnurfk | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
""" | |
server = "server.themanaworld.org" | |
port = 6901 | |
account = "accountname" | |
password = "password" | |
character = 0 #slot character is in, 0 for first, 1 for second, 2 for third | |
charactername = "" # change if it differs | |
master = "maincharacter" #character bot will direct public chat to | |
import socket | |
import struct | |
import time | |
packet_lengths = [ | |
10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
#0x0040 | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 50, 3, -1, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2, | |
3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6, | |
#0x0080 | |
7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0, | |
7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6, | |
23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6, | |
8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3, | |
#0x00C0 | |
7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27, | |
3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1, | |
30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2, | |
3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10, | |
#0x0100 | |
2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1, | |
10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16, | |
6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1, | |
6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26, | |
#0x0140 | |
22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6, | |
110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42, | |
-1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182, | |
14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1, | |
#0x0180 | |
6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6, | |
90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, 4, 6, 2, 6, | |
3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4, | |
11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3, | |
#0x01C0 | |
2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 29, 6, 28, | |
8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6, | |
30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1, | |
-1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10, | |
#0x2000 | |
26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
] | |
class PacketBuffer: | |
def __init__(self): | |
self.buff = "" | |
def feed(self, data): | |
self.buff += data | |
def drop(self, count): | |
self.buff = self.buff[count:] | |
def __iter__(self): | |
return self | |
def next(self): | |
if len(self.buff) < 2: | |
raise StopIteration | |
pkttype = struct.unpack("<H", self.buff[:2])[0] | |
assert pkttype < len(packet_lengths) | |
assert packet_lengths[pkttype] != 0 | |
if packet_lengths[pkttype] < 0: | |
if len(self.buff) < 4: | |
raise StopIteration | |
pktlen = struct.unpack("<H", self.buff[2:4])[0] | |
assert pktlen >= 4 | |
else: | |
pktlen = packet_lengths[pkttype] | |
if len(self.buff) < pktlen: | |
raise StopIteration | |
packet = self.buff[:pktlen] | |
self.buff = self.buff[pktlen:] | |
return packet | |
def parse_ip(s): | |
return ".".join(map(str, map(ord, s))) | |
def whisper(nick, message): | |
return "\x96\0%s%s%s" % (struct.pack("<H", len(message)+28), nick.ljust(24, '\0'), message) | |
def main(): | |
login = socket.socket() | |
login.connect((server, port)) | |
print("login connected") | |
login.sendall("\x64\0\0\0\0\0%s%s\0" % | |
(account.ljust(24, '\0'), password.ljust(24, '\0'))) | |
pb = PacketBuffer() | |
id1 = accid = id2 = sex = 0 | |
charip = "" | |
charport = 0 | |
while True: | |
data = login.recv(1500) | |
if not data: | |
break | |
pb.feed(data) | |
for packet in pb: | |
if packet.startswith("\x69\0"): # login succeeded | |
id1, accid, id2 = struct.unpack("<LLL", packet[4:16]) | |
sex = ord(packet[46]) | |
packet = packet[47:] | |
charip = parse_ip(packet[:4]) | |
charport = struct.unpack("<H", packet[4:6])[0] | |
login.close() | |
break | |
if charip: | |
break | |
assert charport | |
char = socket.socket() | |
char.connect((charip, charport)) | |
print("char connected") | |
char.sendall("\x65\0%s\0\0%s" % (struct.pack("<LLL", accid, id1, id2), chr(sex))) | |
char.recv(4) | |
pb = PacketBuffer() | |
mapip = "" | |
mapport = 0 | |
charid = 0 | |
while True: | |
data = char.recv(1500) | |
if not data: | |
break | |
pb.feed(data) | |
for packet in pb: | |
if packet.startswith("\x6b\0"): | |
char.sendall("\x66\0%s" % chr(character)) | |
elif packet.startswith("\x71\0"): | |
charid = struct.unpack("<L", packet[2:6])[0] | |
mapip = parse_ip(packet[22:26]) | |
mapport = struct.unpack("<H", packet[26:28])[0] | |
char.close() | |
break | |
if mapip: | |
break | |
assert mapport | |
mapserv = socket.socket() | |
mapserv.connect((mapip, mapport)) | |
print("map connected") | |
mapserv.sendall("\x72\0%s" % struct.pack("<LLLLB", accid, charid, id1, id2, sex)) | |
mapserv.recv(4) | |
pb = PacketBuffer() | |
gotresponse = set() | |
while True: | |
data = mapserv.recv(1500) | |
if not data: | |
break | |
pb.feed(data) | |
for packet in pb: | |
if packet.startswith("\x73\0"): # connected | |
mapserv.sendall("\x7d\0") # map loaded | |
mapserv.sendall("\x89\0\0\0\0\0\x02") # sit | |
elif packet.startswith("\x97\0"): | |
nick = packet[4:28].rstrip("\0") | |
message = packet[28:] | |
if nick == master: | |
data = "%s : %s" % (charactername, message) | |
mapserv.sendall("\x8c\0%s%s" % (struct.pack("<H", len(data)+4), data)) | |
time.sleep(0.5) | |
elif nick not in gotresponse: | |
gotresponse.add(nick) | |
mapserv.sendall(whisper(nick, "Please talk to %s." % master)) | |
time.sleep(0.5) | |
elif packet.startswith("\x8e\0"): # server speech | |
message = packet[4:] | |
if "automaticly banned for spam" in message: | |
time.sleep(3) | |
elif packet.startswith("\x8d\0"): # char speech | |
message = packet[8:] | |
mapserv.sendall(whisper(master, message)) | |
time.sleep(0.5) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment