]> jfr.im git - irc/rizon/acid.git/blob - pyva/pyva/src/main/python/moo/moo.py
Split pyva plugin into pyva.core and pyva.pyva
[irc/rizon/acid.git] / pyva / pyva / src / main / python / moo / moo.py
1 #!/usr/bin/python pseudoserver.py
2 # psm_moo.py
3 # module for pypseudoserver
4 # written by ElChE <elche@rizon.net>, martin <martin@rizon.net>
5 #
6 # vHost module
7
8 import traceback
9 import logging
10 import sys
11 import re
12
13 from utils import format_ascii_irc
14 from pseudoclient import sys_log
15 from datetime import datetime
16
17 from pyva import *
18 from core import *
19 from plugin import *
20
21 import cmd_user, requests
22
23 class moo(AcidPlugin):
24 # Regexes for HostServ messages because 1.8/2.0 duality.
25 req_regexes = {'req18': re.compile('^New vHost (.+?) requested by (.+?) \((.+)\)$'),
26 'req19': re.compile('^COMMAND: (.+?)!.+?@.+? (.+?) used REQUEST to request new vhost (.+)$'),
27 'rejacc18': re.compile('^Host Request for (.+?) (.+?) by (.+)$'),
28 'acc19': re.compile('^COMMAND: (.+?)!.+?@.+? .+? used ACTIVATE for (.+?) for vhost .+$'),
29 'rej19': re.compile('^COMMAND: (.+?)!.+?@.+? .+? used REJECT to reject vhost for (.+?) \(.*\)$'),
30 'wait18': re.compile("^#\d+ Nick:\002(.+?)\002, vhost:\002(.+?)\002 \(.+\)$"),
31 'wait19': re.compile('^\d+ +([^ ]+) +([^ ]+) +([^ ]+) +.+$')
32 }
33
34
35 def __init__(self):
36 AcidPlugin.__init__(self)
37
38 self.name = "moo"
39 self.log = logging.getLogger(__name__)
40
41 try:
42 self.client = istring(self.config.get('vhost', 'nick'))
43 self.chan = istring(self.config.get('vhost', 'channel'))
44 self.logchan = istring(self.config.get('vhost', 'logchan'))
45 except Exception, err:
46 self.log.exception("Error reading vhost configuration options: %s" % err)
47 raise
48
49 def start(self):
50 try:
51 self.elog = sys_log.LogManager(self)
52 self.commands_user = cmd_user.UserCommandManager()
53 self.requests = requests.RequestManager(self)
54 except Exception, err:
55 self.log.exception('Error initializing core subsystems for vhost module (%s)' % err)
56 raise
57
58 self.elog.debug('Started core subsystems.')
59 self.initialized = True
60
61 self.msg('HostServ', 'WAITING') # Check if we missed requests while down
62
63 return True
64
65 def msg(self, target, message):
66 if message != '':
67 self.inter.privmsg(self.client, target, format_ascii_irc(message))
68
69 def notice(self, target, message):
70 if message != '':
71 self.inter.notice(self.client, target, format_ascii_irc(message))
72
73 def execute(self, manager, command, argument, channel, sender):
74 full_command = '%s%s' % (command, ' %s' % argument if len(argument) else '')
75 cmd = manager.get_command(command)
76
77 if not cmd:
78 return
79
80 try:
81 cmd[0](self, manager, channel, sender, argument)
82 except Exception, e:
83 tb = traceback.extract_tb(sys.exc_info()[2])
84 longest = 0
85
86 for entry in tb:
87 length = len(entry[2])
88
89 if length > longest:
90 longest = length
91
92 self.elog.exception(e)
93 self.log.exception("moo error!")
94
95 for entry in tb:
96 self.elog.traceback('@b%-*s@b : %d %s' % (longest, entry[2], entry[1], entry[3]))
97
98
99 def onSync(self):
100 self.msg('HostServ', 'WAITING') # Check if we missed requests while down
101
102 def onNotice(self, source, target, message):
103 msg = message.strip()
104
105 if msg.startswith('[#'): #It's a channel welcome message. Let's ignore it.
106 return
107
108 user = self.inter.findUser(target)
109 userinfo = self.inter.findUser(source)
110
111 if not user or user.getNick() != self.client:
112 return
113
114 if userinfo.getNick() != 'HostServ':
115 return
116
117 # Check for 1.8 or 1.9 requests.
118 # 1.8:waiting: #$num Nick:\002$nick\002, vhost:\002$vhost\002 ($display - $date)
119 # 1.9:waiting: $num $nick $display $vhost $date
120 sp = msg.split(' ')
121
122 # Regex. Because it solves the problem in the easiest way.
123 match = self.req_regexes['wait18'].match(msg)
124 if match == None:
125 match = self.req_regexes['wait19'].match(msg)
126 if match == None or match.groups(0) == 'Number':
127 return
128
129 if len(match.groups()) == 3:
130 (nick, vhost, display) = match.groups()
131 elif len(match.groups()) == 2:
132 (nick, vhost) = match.groups()
133 display = None # self.requests.add can handle None for display nick
134 else:
135 return
136
137 if not nick or not vhost:
138 return
139
140 try:
141 self.requests.add(vhost, nick, display)
142 except Exception, e:
143 tb = traceback.extract_tb(sys.exc_info()[2])
144 longest = 0
145
146 for entry in tb:
147 length = len(entry[2])
148
149 if length > longest:
150 longest = length
151
152 self.elog.exception(e)
153 self.log.exception("moo error!")
154
155 for entry in tb:
156 self.elog.traceback('@b%-*s@b : %d %s' % (longest, entry[2], entry[1], entry[3]))
157
158 def onPrivmsg(self, source, target, message):
159 userinfo = self.inter.findUser(source)
160
161 sender = userinfo.getNick()
162 channel = target
163 msg = message.strip()
164 index = msg.find(' ')
165
166 if index == -1:
167 command = msg
168 argument = ''
169 else:
170 command = msg[:index]
171 argument = msg[index + 1:]
172
173 if channel == self.client: # XXX uid
174 pass #private message
175 elif channel == self.chan and command.startswith('!'):
176 self.execute(self.commands_user, command, argument, channel, sender)
177 elif channel == self.logchan and (sender == 'Global' or sender == 'HostServ'):
178 match = self.req_regexes['req18'].match(msg)
179 if match != None:
180 try:
181 self.requests.add(match.group(1), match.group(2), match.group(3))
182 except Exception, e:
183 self.print_traceback(e)
184 return
185
186 match = self.req_regexes['req19'].match(msg)
187 if match != None:
188 try:
189 self.requests.add(match.group(3), match.group(1), match.group(2))
190 except Exception, e:
191 self.print_traceback(e)
192 return
193
194 match = self.req_regexes['rejacc18'].match(msg)
195 if match != None:
196 (nick, action, by) = match.groups()
197 by = by.split(' ')[0] # In case there's a reject reason
198 if by == self.client:
199 return
200
201 try:
202 if action == 'rejected':
203 self.requests.delete(nick)
204 self.msg(self.chan, 'vHost for @b%s@b was manually %s by @b%s@b' % (nick, action, by))
205 elif action == 'activated':
206 self.requests.approve(nick, by, silent=True)
207 self.msg(self.chan, 'vHost for @b%s@b was manually %s by @b%s@b' % (nick, action, by))
208 except Exception, e:
209 self.print_traceback(e)
210 return
211
212 match = self.req_regexes['acc19'].match(msg)
213 if match != None:
214 (by, nick) = match.groups()
215 if by == self.client:
216 return
217
218 try:
219 self.requests.delete(nick)
220 self.msg(self.chan, 'vHost for @b%s@b was manually activated by @b%s@b' % (nick, by))
221 except Exception, e:
222 self.print_traceback(e)
223 return
224
225 match = self.req_regexes['rej19'].match(msg)
226 if match != None:
227 (by, nick) = match.groups()
228 if by == self.client:
229 return
230
231 try:
232 self.requests.delete(nick)
233 self.msg(self.chan, 'vHost for @b%s@b was manually rejected by @b%s@b' % (nick, by))
234 except Exception, e:
235 self.print_traceback(e)
236 return
237
238 def print_traceback(self, e):
239 tb = traceback.extract_tb(sys.exc_info()[2])
240 longest = 0
241
242 for entry in tb:
243 length = len(entry[2])
244
245 if length > longest:
246 longest = length
247
248 self.elog.exception(e)
249 self.log.exception("moo error!")
250
251 for entry in tb:
252 self.elog.traceback('@b%-*s@b : %d %s' % (longest, entry[2], entry[1], entry[3]))