Skip to content

Instantly share code, notes, and snippets.

@koo5
Created March 11, 2012 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save koo5/2016586 to your computer and use it in GitHub Desktop.
Save koo5/2016586 to your computer and use it in GitHub Desktop.
whisperbot
server = "server.themanaworld.org"
port = 6901
account = ""
password = ""
character = 0#slot character is in, 0 for first, 1 for second, 2 for third
charactername = ""
master = "" #character bot will direct public chat to
sit = 0 # become inconspicuous
color_replacement_regex = '' #r'\1 ' to keep em
http://forums.themanaworld.org/viewtopic.php?f=12&t=11712
# all copyrights probably infringed..
rename config to config.py
#!/usr/bin/python
file = open("wlog.txt", "a")
from config import *
import string
import select
import socket
import struct
import time
import sys
import re
import os
from time import strftime as date
# http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python
console_width = int(os.popen('stty size', 'r').read().split()[1])
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
if sit:
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)
file.write("[" + date('%H:%M:%S') + "] " + "!!! " + nick + ": " + message + "\n")
print "[" + date('%H:%M:%S') + "] " + "!!! " + nick + ": " + message
#mapserv.sendall(whisper(nick, "Please talk to %s." % master))
time.sleep(0.5)
elif packet.startswith("\x8e\0"): # server speech
message = packet[4:]
print "[" + date('%H:%M:%S') + "] " + message
if "automaticly banned for spam" in message:
time.sleep(3)
elif packet.startswith("\x8d\0"): # char speech
message = re.sub(r'(##[0-9])',color_replacement_regex,packet[8:-1])
print "[" + date('%H:%M:%S') + "] " + message
if len(message) > console_width:
print ""
# mapserv.sendall(whisper(master, message))
file.write("[" + date('%H:%M:%S') + "] " + message + "\n")
file.flush()
time.sleep(0.1)
si,so,se = select.select([sys.stdin],[],[], 0.01)
for s in si:
if s == sys.stdin:
message = sys.stdin.readline()[:-1]
if len(message) > 0:
if message[0] == '/':
if len(message) > 1:
if (message[1] == 'q') or (message[1] == 'w'):
nick = string.split(message)[1]
text = string.join(string.split(message)[2:])
mapserv.sendall(whisper(nick, text))
break
data = "%s : %s" % (charactername, message)
mapserv.sendall("\x8c\0%s%s" % (struct.pack("<H", len(data)+4), data))
file.write("[" + date('%H:%M:%S') + "] " + "Me: " + message + "\n")
# time.sleep(0.5)
if __name__ == '__main__':
main()
file.close()
@o11c
Copy link

o11c commented Jun 30, 2012

at the top, add:

import shlex

then, change:

nick = string.split(message)[1]
text = string.join(string.split(message)[2:])

to:

splitted = shlex.split(message)
nick = splitted[1]
text = ' '.join(splitted[2:])

@o11c
Copy link

o11c commented Jun 30, 2012

On second thought, that will strip all quotes, and throw an exception if they don't match.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment