]> jfr.im git - z_archive/pyp10.git/blame - pyp10.py
Disallow access to Do by non-opers
[z_archive/pyp10.git] / pyp10.py
CommitLineData
5b0ca097
JR
1#!/usr/bin/python
2
3import socket, time
4
5
6uplink = None
7modules = {}
1a1d9e61 8modcount = 0
5b0ca097
JR
9
10class 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
22b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789[]"
5b0ca097 23
5fc101f1
JR
24class 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
42class 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
185class Account(object):
186 pass
187
188class Client(object):
189 pass
190
94df1338
JR
191uplink = Uplink()
192
193for modu in config.autoload:
194 modules[modu] = (__import__('modules.'+str(modu), globals(), locals(), ['Pseudo'], 0)).Pseudo(uplink)
1a1d9e61 195 modcount += 1
94df1338 196
5b0ca097 197uplink.loop()