]>
Commit | Line | Data |
---|---|---|
5b0ca097 JR |
1 | #!/usr/bin/python |
2 | ||
3 | import socket, time | |
4 | ||
5 | ||
6 | uplink = None | |
7 | modules = {} | |
1a1d9e61 | 8 | modcount = 0 |
5b0ca097 JR |
9 | |
10 | class config(object): | |
11 | name = 'services.p10' | |
12 | numeric = ']S' | |
13 | uplink = { | |
14 | 'address': '127.0.0.1', | |
15 | 'port': 4400, | |
16 | 'name': 'test.p10', | |
17 | 'password': 'password', | |
18 | 'vhost': '', #bind to this ip - empty string '' for auto-select | |
19 | } | |
f30d341c | 20 | autoload = ['q', 'do'] |
94df1338 JR |
21 | |
22 | b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789[]" | |
5b0ca097 | 23 | |
5fc101f1 JR |
24 | class User(object): |
25 | def __init__(self, num, nick, hostmask, modes, account): | |
26 | self.num = num | |
27 | self.nick = nick | |
28 | self.hostmask = hostmask | |
29 | self.modes = modes | |
30 | self.account = account | |
31 | ||
32 | if 'o' in self.modes: | |
33 | self.oper = True | |
34 | else: | |
35 | self.oper = False | |
36 | ||
37 | if self.account is not None: | |
38 | self.authed = True | |
39 | else: | |
40 | self.authed = False | |
5b0ca097 | 41 | |
94df1338 JR |
42 | class Uplink(object): |
43 | def __init__(self): | |
5b0ca097 | 44 | global uplink |
5b0ca097 | 45 | uplink = self |
94df1338 JR |
46 | |
47 | self.lastnum = None # last numeric used, as [int,int,int] | |
48 | self.nicks = {} # 'nick': Pseudo-object | |
5fc101f1 JR |
49 | self.nums = {} # 'num': Pseudo-objecta |
50 | self.users = {} # 'num': User-objects | |
94df1338 | 51 | self.data = "" # receive buffer |
5b0ca097 | 52 | |
1a1d9e61 JR |
53 | self.bursting = True |
54 | self.bursted = 0 | |
55 | self.burstchans = {} | |
56 | ||
5b0ca097 JR |
57 | self.sock = socket.socket() |
58 | self.sock.bind((config.uplink['vhost'], 0)) | |
59 | self.sock.connect((config.uplink['address'], config.uplink['port'])) | |
60 | ||
61 | self._transmit("PASS %s" % (config.uplink['password'])) | |
62 | self._transmit("SERVER %(name)s 1 %(time)s %(time)s J10 %(numeric)s]]] +s :PyP10 Services" % {'name': config.name, 'time': time.time(), 'numeric': config.numeric}) | |
94df1338 JR |
63 | def send(self, line, source=None, **kwargs): |
64 | if source is None: | |
65 | source = config.numeric | |
66 | self._transmit(source+" "+(line % kwargs)) | |
5b0ca097 JR |
67 | def _transmit(self, line): |
68 | print ">", line | |
69 | self.sock.sendall(line+"\r\n") | |
70 | def _receive(self): | |
71 | self.data += self.sock.recv(4096) | |
72 | while "\n" in self.data: | |
73 | pieces = self.data.split("\n", 1) | |
74 | line = pieces[0].strip() | |
75 | print "<", line | |
f30d341c | 76 | self._process(line) |
5b0ca097 JR |
77 | self.data = pieces[1] |
78 | return True | |
79 | def loop(self): | |
80 | keepgoing = True | |
81 | while keepgoing: | |
1a1d9e61 JR |
82 | if self.bursting and self.bursted >= modcount: |
83 | self._burstisdone() | |
5b0ca097 JR |
84 | keepgoing = self._receive() |
85 | ||
f30d341c | 86 | def _process(self, line): |
5fc101f1 JR |
87 | if ' :' in line: |
88 | extrapos = line.find(' :') | |
89 | extra = line[extrapos+2:] | |
90 | line = line[0:extrapos] | |
91 | words = line.split() | |
92 | words.append(extra) | |
93 | else: | |
94 | extrapos = -1 | |
95 | extra = None | |
96 | words = line.split() | |
97 | ||
98 | # words = ['ABACB', 'P', '#p10']; extra = 'Hi there!' | |
f30d341c JR |
99 | if words[1] == "G" or words[1] == "PING": |
100 | self.send("Z %(numeric)s :%(id)s" % {'numeric': config.numeric, 'id': config.uplink['name']}) | |
1a1d9e61 JR |
101 | elif words[1] == "EB": |
102 | self.send("EA") | |
f30d341c JR |
103 | elif words[1] == "P" or words[1] == "PRIVMSG": |
104 | source = words[0] | |
105 | target = words[2] | |
5fc101f1 JR |
106 | if extra is None: |
107 | extra = ' '.join(words[3:]) | |
f30d341c JR |
108 | if '@' in target: |
109 | tonick = target.split('@', 1) | |
110 | self.nicks[tonick].gotmsg(extra, source, target) | |
111 | elif '#' in target: | |
112 | pass # no processing | |
113 | elif '$' in target: | |
114 | pass # no processing | |
115 | else: | |
116 | self.nums[target].gotmsg(extra, source, target) | |
5fc101f1 JR |
117 | elif words[1] == "N" or words[1] == "NICK": |
118 | nick = words[2] | |
119 | hostmask = words[5]+"@"+words[6] | |
120 | if words[7][0] == '+': | |
121 | modes = words[7][1:] | |
122 | if 'r' in modes and 'h' in modes: | |
123 | rpos = modes.find('r') | |
124 | hpos = modes.find('h') | |
125 | if rpos > hpos: | |
126 | account = words[9] | |
127 | else: | |
128 | account = words[8] | |
129 | elif 'r' in modes: | |
130 | account = modes[8] | |
131 | else: | |
132 | account = None | |
133 | num = words[-2] | |
134 | print repr((num, nick, hostmask, modes, account, extra)) | |
135 | self.users[num] = User(num, nick, hostmask, modes, account) | |
136 | def _newnum(self): #FIXME increment only one value, not all! | |
94df1338 JR |
137 | if self.lastnum is None: |
138 | self.lastnum = [0,0,0] | |
139 | else: | |
f30d341c | 140 | self.lastnum = [i+1 for i in self.lastnum] |
94df1338 JR |
141 | num = config.numeric |
142 | num += b64[self.lastnum[2]] | |
143 | num += b64[self.lastnum[1]] | |
144 | num += b64[self.lastnum[0]] | |
145 | return num | |
146 | ||
147 | def makenick(self, obj, nick, ident, realname): | |
148 | newnum = self._newnum() | |
f30d341c JR |
149 | self.send("N %(nick)s 1 %(time)s %(ident)s %(host)s +doknXr pyp10 DAqAAB %(num)s :%(name)s", nick=nick, ident=ident, name=realname, time=time.time(), host=config.name, num=newnum) |
150 | self.nums[newnum] = obj | |
94df1338 JR |
151 | self.nicks[nick] = obj |
152 | return newnum | |
5fc101f1 JR |
153 | def getuser(self, num): |
154 | return self.users[num] | |
1a1d9e61 JR |
155 | def join(self, chan, source, op=False): |
156 | # if self.bursting: | |
157 | # if chan not in self.burstchans: | |
158 | # self.burstchans[chan] = {'ops':[], 'regs':[]} | |
159 | # | |
160 | # if op: | |
161 | # self.burstchans[chan]['ops'].append(source) | |
162 | # else: | |
163 | # self.burtschans[chan]['regs'].append(source) | |
164 | # else: # not bursting | |
165 | self.send("J %(chan)s %(time)s", source, chan=chan, time=time.time()+3600) | |
166 | if op: | |
167 | self.send("OM %(chan)s +nto %(num)s", source, chan=chan, num=source) | |
168 | def endburst(self, module): | |
169 | self.bursted += 1 | |
170 | print module.num, self.bursted, modcount | |
171 | def _burstisdone(self): | |
172 | self.bursting = False | |
173 | for chname, chan in self.burstchans.iteritems(): | |
174 | users = chan['regs'] | |
175 | ||
176 | if len(chan['ops']) != 0: | |
177 | chan['ops'][0] += ':o' | |
178 | users.extend(chan['ops']) | |
179 | ||
180 | mems = ','.join(users) | |
181 | self.send("B %(chan)s 780000001 +nt %(members)s", chan=chname, members=mems) | |
182 | self.send("EB") | |
183 | self.burtchans = {} | |
5b0ca097 JR |
184 | |
185 | class Account(object): | |
186 | pass | |
187 | ||
188 | class Client(object): | |
189 | pass | |
190 | ||
94df1338 JR |
191 | uplink = Uplink() |
192 | ||
193 | for modu in config.autoload: | |
194 | modules[modu] = (__import__('modules.'+str(modu), globals(), locals(), ['Pseudo'], 0)).Pseudo(uplink) | |
1a1d9e61 | 195 | modcount += 1 |
94df1338 | 196 | |
5b0ca097 | 197 | uplink.loop() |