copyright headers fixed
[dakbot.git] / Dak / plugin.py
1 ###
2 # Copyright (c) 2008, Joerg Jaspert <joerg@debian.org>
3 # GPL v2 (not later)
4 ###
5
6 import time
7 import config
8 import re
9
10 import supybot.log as log
11 from supybot.commands import *
12 import supybot.plugins as plugins
13 import supybot.ircmsgs as ircmsgs
14 import supybot.callbacks as callbacks
15 import supybot.schedule as schedule
16 import supybot.conf as conf
17
18 class Dak(callbacks.Plugin):
19 """Little FTPMaster tools. Tells about dinstall times, warns if you have a lock set,
20 and lets people set/unset locks.
21 Possible commands are "lock", "unlock", "forceunlock", "locked", "setlastnew".
22 """
23 pass
24
25 def __init__(self, irc):
26 self.__parent = super(Dak, self)
27 self.__parent.__init__(irc)
28 self.irc = irc
29 self.fname = "dinstallcheck"
30 self.dinstallhour = [1, 7, 13, 19]
31 self.dinstallmin = self.registryValue('dinstallminute')
32 warntime=10
33 self.warnframe = [i%60 for i in range(self.dinstallmin-warntime, self.dinstallmin+warntime+1, 1)]
34 self.dinstallframe = [i%60 for i in range(self.dinstallmin, self.dinstallmin+5, 1)]
35 self.channel = self.registryValue('channel')
36 self.locks = {}
37
38 def checktime():
39 (undef, undef, undef, hour, minute, undef, undef, undef, undef) = time.gmtime()
40 log.debug("DAK: Regular dinstall time check")
41 if hour in self.dinstallhour:
42 log.debug("DAK: It is DINSTALL hour")
43 if minute in self.warnframe:
44 log.debug("DAK: In Dinstall Warnframe")
45 msgMaker = ircmsgs.privmsg
46 if minute in self.dinstallframe:
47 log.debug("DAK: In Dinstall timeframe")
48 # No longer time to warn only, now is time to act, if we haven't already
49 if self.registryValue('dinstall') == True:
50 log.debug("DAK: Already done once, dinstall flag is %s" %(self.registryValue('dinstall')))
51 return
52 log.debug("DAK: Not yet done, dinstall flag %s" % (self.registryValue('dinstall')))
53 conf.supybot.plugins.Dak.get('dinstall').setValue(True)
54 conf.supybot.plugins.Dak.get('warned').setValue(True)
55 irc.queueMsg(msgMaker(self.channel, "It is DINSTALL time"))
56 if len(self.locks) >= 1:
57 for key in self.locks:
58 irc.queueMsg(msgMaker(self.channel, "%s: DINSTALL time, stop working, unlocking %s" % (self.locks[key], key)))
59 self.locks={}
60 return
61 else: # if minute in self.dinstallframe
62 # Not dinstall as far as we know, but we want to warn people if they have locks, dinstall is soon.
63 # We only want to warn once about locks people have, or we would do it every 30 seconds, which wouldnt be nice.
64 # Also, with warnframe larger than dinstallframe, this might warn in case the bot somehow misses dinstallframe.
65 # Like if it comes up late, or so. Or?
66 log.debug("DAK: Not in Dinstall timeframe")
67 if self.registryValue('warned') == True:
68 log.debug("DAK: We already warned once, warn flag %s" % (self.registryValue('warned')))
69 return
70 log.debug("DAK: Not yet warned about upcoming Dinstall run, flag is %s." % (self.registryValue('warned')))
71
72 if len(self.locks) >= 1:
73 conf.supybot.plugins.Dak.get('warned').setValue(True)
74 for key in self.locks:
75 log.debug("DAK: Warning %s, has %s locked." % (self.locks[key], key))
76 irc.queueMsg(msgMaker(self.channel, "%s: DINSTALL soon, hurry up" % (self.locks[key]) ))
77 if key == "ALL":
78 irc.queueMsg(msgMaker(self.channel, "%s: ALL locked. If you want to keep that, remember turning off cron" % (self.locks[key]) ))
79 else: # if minute in self.warnframe
80 # Outside our warnframe.
81 log.debug("DAK: Not in warnframe")
82 conf.supybot.plugins.Dak.get('dinstall').setValue(False)
83 conf.supybot.plugins.Dak.get('warned').setValue(False)
84
85 else: # if hour in self.dinstallhour
86 # We are far outside a dinstall start
87 log.debug("DAK: Not even dinstall hour")
88 conf.supybot.plugins.Dak.get('dinstall').setValue(False)
89 conf.supybot.plugins.Dak.get('warned').setValue(False)
90
91 # end def checktime
92 log.info("DAK: Setting periodic scheduler for checktime")
93 try:
94 schedule.removePeriodicEvent(self.fname)
95 except KeyError:
96 pass
97 schedule.addPeriodicEvent(checktime, 30, self.fname, now=False)
98 schedule.addEvent(checktime, time.time()+1)
99 log.info("DAK: Plugin loaded")
100
101 def die(self):
102 try:
103 log.info("DAK: We should die, removing periodic scheduler")
104 schedule.removePeriodicEvent(self.fname)
105 except KeyError:
106 pass
107
108
109 def dinstall(self, irc, msg, args):
110 """takes no arguments
111
112 Returns the time until next dinstall
113 """
114
115 def deltatime(start, stop):
116 def toSeconds(timeString):
117 hour, min, sec = map(int, timeString.split(':'))
118 return (hour * 60 + min) * 60 + sec
119 d_time_min, d_time_sec = divmod(toSeconds(stop) - toSeconds(start), 60)
120 d_time_hr, d_time_min = divmod(d_time_min, 60)
121 return '%dhr %dmin %ssec' % (d_time_hr % 24, d_time_min, d_time_sec)
122
123 (year, month, day, hour, minute, second, undef, undef, undef) = time.gmtime()
124
125 log.debug("The latest run is at %s:%s" % (self.dinstallhour[-1], self.dinstallmin))
126 log.debug("I think we now have %s:%s" % (hour, minute))
127
128 newhour = hour
129 if minute >= self.dinstallmin and newhour in self.dinstallhour:
130 # If we already passed dinstallminute, we are running and want the next runtime.
131 log.debug("We are past this hours dinstall already")
132 newhour+=1
133
134 if newhour > self.dinstallhour[-1]:
135 log.debug("We are also past the last dinstall run for today")
136 # We are past the last dinstall today, so next one must be the first tomorrow, start searching at midnight
137 newhour = self.dinstallhour[0]
138 else:
139 while newhour not in self.dinstallhour:
140 newhour+=1
141 log.debug("Looking at possible hour %s" % (newhour))
142 if newhour > 23:
143 newhour=0
144
145 log.debug("I found that next dinstall will be at %s:%s" % (newhour, self.dinstallmin))
146
147 start="%s:%s:%s" % (hour, minute, second)
148 stop="%s:%s:00" % (newhour, 52)
149 difference=deltatime(start, stop)
150 irc.reply("I guess the next dinstall will be in %s" % (difference))
151 dinstall = wrap(dinstall)
152
153 def locked(self, irc, msg, args):
154 """takes no arguments
155
156 Returns the currently set locks
157 """
158
159 if len(self.locks) == 0:
160 irc.reply("Nothing locked")
161 else:
162 text="Current self.locks: "
163 for key in self.locks:
164 text += "[%s, by %s] " % (key, self.locks[key])
165 irc.reply(text)
166 locked = wrap(locked)
167
168 def dakinfo(self, irc, msg, what):
169 """takes no arguments
170
171 Returns a little info about this plugins status"""
172
173 text=[]
174 text.append("Dak plugin for the FTPMaster channel %s." % (self.channel))
175 text.append("Dinstall hour: %s, minute: %s" % (self.dinstallhour, self.dinstallmin))
176 if len(self.locks) > 1:
177 text.append("Current locks: %d (%s)" % (len(self.locks), self.locks))
178 text.append("Warnframe: %s" % (self.warnframe))
179 text.append("Dinstallframe: %s" % (self.dinstallframe))
180 text.append("Dinstall flag: %s, Warnflag: %s" % (conf.supybot.plugins.Dak.get('dinstall'), conf.supybot.plugins.Dak.get('warned')))
181 for key in text:
182 irc.reply(key)
183 dakinfo = wrap(dakinfo)
184
185 def lock(self, irc, msg, args, what):
186 """<lock>
187
188 Locks <lock>.
189 """
190 if self.locks.has_key("ALL"):
191 irc.error("No, %s has an ALL lock" % (self.locks["ALL"]))
192 return
193 if what == "ALL" and len(self.locks) > 0:
194 irc.error("Can't lock all, there are existing locks")
195 return
196 if self.locks.has_key(what):
197 if self.locks[what] == msg.nick:
198 irc.reply("Loser, you already locked %s" % (what) )
199 else:
200 irc.reply("You suck, this is already locked by %s" % (self.locks[what]) )
201 else:
202 self.locks[what]=msg.nick
203 irc.reply("locked %s" % (what) )
204 lock = wrap(lock, ['text'])
205
206 def unlock(self, irc, msg, args, what):
207 """[lock]
208
209 Unlocks [lock] or everything locked from you.
210 """
211 if len(self.locks) == 0:
212 irc.reply("Nothing locked")
213 return
214
215 unlocked="unlocked: "
216 if self.locks.has_key(what):
217 if self.locks[what] == msg.nick:
218 del(self.locks[what])
219 irc.reply("unlocked %s" % (what) )
220 else:
221 irc.reply("%s is locked by %s, not by you. Not unlocked." % (what, self.locks[what]) )
222 else:
223 keys=[]
224 for key in self.locks:
225 if self.locks[key] == msg.nick:
226 keys.append(key)
227 for key in keys:
228 del(self.locks[key])
229 unlocked += ", ".join(keys)
230 irc.reply(unlocked)
231 unlock = wrap(unlock, [optional('text')])
232
233 def forceunlock(self, irc, msg, args, what):
234 """<lock>
235
236 Force-Unlocks [lock] or everything locked from you.
237 """
238 if len(self.locks) == 0:
239 irc.reply("Nothing locked")
240 return
241
242 if self.locks.has_key(what):
243 msgMaker = ircmsgs.privmsg
244 irc.queueMsg(msgMaker(self.channel, "%s: Careful, %s just forceunlocked %s from you!" % (self.locks[what], msg.nick, what)))
245 del(self.locks[what])
246 irc.reply("unlocked %s" % (what))
247 forceunlock = wrap(forceunlock, ['text'])
248
249 def setlastnew(self, irc, msg, args):
250 """
251
252 setlastnew takes no parameter"""
253
254 re_topic = re.compile(r"(.*)\s+\|\| last NEW ended:\s+\w{3} \d\d \d\d:\d\d UTC \d{4}(?:\s+\|\|\s+(.*))?")
255 topic = irc.state.channels[self.channel].topic
256 m = re_topic.match(topic)
257 newtopic = ""
258 if m:
259 newtopic = "%s || %s" % (m.group(1),
260 time.strftime("last NEW ended: %b %d %H:%M UTC %Y", time.gmtime()))
261 if m.group(2):
262 newtopic += " || %s" % (m.group(2))
263 else:
264 # Woot, looks we never had this part in the topic yet
265 newtopic = "%s || %s" % (topic,
266 time.strftime("last NEW ended: %b %d %H:%M UTC %Y", time.gmtime()))
267 irc.queueMsg(ircmsgs.topic(self.channel, newtopic))
268 irc.reply("Ok master")
269
270 setlastnew = wrap(setlastnew)
271
272 Class = Dak
273
274 # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: