2012-04-09 02:19:39 +00:00
# coding=utf-8
import re
2012-04-11 15:33:57 +00:00
import sys
2012-04-09 02:19:39 +00:00
from datetime import timedelta
from datetime import datetime
from datetime import date
2012-04-30 16:22:10 +00:00
import time
2012-05-14 15:50:11 +00:00
import threading
2012-04-09 02:19:39 +00:00
from xml . dom . minidom import parse
from xml . dom . minidom import parseString
from xml . dom . minidom import getDOMImplementation
2012-05-20 07:44:07 +00:00
import imodule
2012-05-14 15:50:11 +00:00
class Manager ( threading . Thread ) :
def __init__ ( self , servers ) :
self . servers = servers
self . stop = False
threading . Thread . __init__ ( self )
def run ( self ) :
global STREND
while not self . stop :
newStrendEvt . clear ( )
closer = None
#Gets the closer event
for evt in STREND . keys ( ) :
if ( ( closer is None or closer . end is None ) or ( STREND [ evt ] . end is not None and STREND [ evt ] . end < closer . end ) ) and STREND [ evt ] . end is not None and STREND [ evt ] . end > datetime . now ( ) :
closer = STREND [ evt ]
if closer is not None and closer . end is not None :
#print ("Closer: %s à %s"%(closer.name, closer.end))
timeleft = ( closer . end - datetime . now ( ) ) . seconds
timer = threading . Timer ( timeleft , closer . alertEnd , ( self . servers , ) )
timer . start ( )
#print ("Start timer (%ds)"%timeleft)
newStrendEvt . wait ( )
if closer is not None and closer . end is not None and closer . end > datetime . now ( ) :
timer . cancel ( )
2012-04-30 16:22:10 +00:00
class Strend :
def __init__ ( self , item ) :
if item is not None :
self . name = item . getAttribute ( " name " )
self . start = datetime . fromtimestamp ( time . mktime ( time . strptime ( item . getAttribute ( " start " ) [ : 19 ] , " % Y- % m- %d % H: % M: % S " ) ) )
self . proprio = item . getAttribute ( " proprio " )
2012-05-14 15:50:11 +00:00
self . server = item . getAttribute ( " server " )
self . channel = item . getAttribute ( " channel " )
if item . getAttribute ( " end " ) is not None and item . getAttribute ( " end " ) != " " :
try :
self . end = datetime . fromtimestamp ( time . mktime ( time . strptime ( item . getAttribute ( " end " ) [ : 19 ] , " % Y- % m- %d % H: % M: % S " ) ) )
except :
self . end = None
else :
self . end = None
2012-04-30 16:22:10 +00:00
else :
self . start = datetime . now ( )
2012-05-14 15:50:11 +00:00
self . end = None
2012-04-30 16:22:10 +00:00
2012-05-14 15:50:11 +00:00
def alertEnd ( self , SRVS ) :
for server in SRVS . keys ( ) :
if server == self . server :
if self . channel == SRVS [ server ] . nick :
SRVS [ server ] . send_msg_usr ( self . proprio , " %s : %s arrivé à échéance. " % ( self . proprio , self . name ) )
else :
SRVS [ server ] . send_msg ( self . channel , " %s : %s arrivé à échéance. " % ( self . proprio , self . name ) )
del STREND [ self . name ]
newStrendEvt . set ( )
2012-04-09 02:19:39 +00:00
2012-04-30 16:22:10 +00:00
2012-04-09 02:19:39 +00:00
2012-05-20 07:44:07 +00:00
class Nemodule ( imodule . ModuleBase ) :
filename = " "
events = dict ( )
strend = dict ( )
threadManager = None
newStrendEvt = threading . Event ( )
def launch ( self , servers ) :
self . stop ( )
self . threadManager = Manager ( servers )
self . threadManager . start ( )
def stop ( self ) :
if self . threadManager is not None :
self . threadManager . stop = True
self . newStrendEvt . set ( )
def xmlparse ( self , node ) :
""" Parse the given node and add events to the global list. """
for item in node . getElementsByTagName ( " strend " ) :
strend [ item . getAttribute ( " name " ) ] = Strend ( item )
for item in node . getElementsByTagName ( " event " ) :
if ( item . hasAttribute ( " year " ) ) :
year = int ( item . getAttribute ( " year " ) )
else :
year = 0
if ( item . hasAttribute ( " month " ) ) :
month = int ( item . getAttribute ( " month " ) )
else :
month = 0
if ( item . hasAttribute ( " day " ) ) :
day = int ( item . getAttribute ( " day " ) )
else :
day = 0
if ( item . hasAttribute ( " hour " ) ) :
hour = int ( item . getAttribute ( " hour " ) )
else :
hour = 0
if ( item . hasAttribute ( " minute " ) ) :
minute = int ( item . getAttribute ( " minute " ) )
else :
minute = 0
if ( item . hasAttribute ( " second " ) ) :
second = int ( item . getAttribute ( " second " ) )
else :
second = 0
if year == month == day == hour == minute == second == 0 :
events [ item . getAttribute ( " name " ) ] = ( None , item . getAttribute ( " before_after " ) , None )
else :
events [ item . getAttribute ( " name " ) ] = ( datetime ( year , month , day , hour , minute , second ) , item . getAttribute ( " msg_before " ) , item . getAttribute ( " msg_after " ) )
2012-04-09 02:19:39 +00:00
def load_module ( datas_path ) :
""" Load this module """
2012-04-30 16:22:10 +00:00
global EVENTS , STREND , filename
2012-04-09 02:19:39 +00:00
EVENTS = { }
2012-04-30 16:22:10 +00:00
STREND = { }
2012-04-09 02:19:39 +00:00
filename = datas_path + " /events.xml "
2012-04-11 15:33:57 +00:00
sys . stdout . write ( " Loading events ... " )
2012-04-09 02:19:39 +00:00
dom = parse ( filename )
xmlparse ( dom . getElementsByTagName ( ' events ' ) [ 0 ] )
print ( " done ( %d loaded) " % len ( EVENTS ) )
def save_module ( ) :
""" Save the dates """
global filename
2012-04-11 15:33:57 +00:00
sys . stdout . write ( " Saving events ... " )
2012-04-09 02:19:39 +00:00
impl = getDOMImplementation ( )
newdoc = impl . createDocument ( None , ' events ' , None )
top = newdoc . documentElement
2012-04-30 16:22:10 +00:00
for name in STREND . keys ( ) :
2012-05-14 15:50:11 +00:00
iend = " "
if STREND [ name ] . end is not None :
iend = ' end= " %s " ' % STREND [ name ] . end
item = parseString ( ' <strend name= " %s " start= " %s " proprio= " %s " server= " %s " channel= " %s " %s /> ' % ( name , STREND [ name ] . start , STREND [ name ] . proprio , STREND [ name ] . server , STREND [ name ] . channel , iend ) ) . documentElement
2012-04-30 16:22:10 +00:00
top . appendChild ( item ) ;
2012-04-09 02:19:39 +00:00
for name in EVENTS . keys ( ) :
( day , msg_before , msg_after ) = EVENTS [ name ]
bonus = " "
if day is None :
item = parseString ( ' <event name= " %s " msg_before= " %s " /> ' % ( name , msg_before ) ) . documentElement
else :
if day . hour != 0 :
bonus + = ' hour= " %s " ' % day . hour
if day . minute != 0 :
bonus + = ' minute= " %s " ' % day . minute
if day . second != 1 :
bonus + = ' second= " %s " ' % day . second
item = parseString ( ' <event name= " %s " year= " %d " month= " %d " day= " %d " %s msg_after= " %s " msg_before= " %s " /> ' % ( name , day . year , day . month , day . day , bonus , msg_after , msg_before ) ) . documentElement
top . appendChild ( item ) ;
with open ( filename , " w " ) as f :
newdoc . writexml ( f )
print ( " done " )
def help_tiny ( ) :
""" Line inserted in the response to the command !help """
2012-04-18 21:35:58 +00:00
return " events manager "
2012-04-09 02:19:39 +00:00
def help_full ( ) :
2012-05-14 15:50:11 +00:00
return " This module store a lot of events: ny, we, vacs, " + ( " , " . join ( EVENTS . keys ( ) ) ) + " \n !eventslist: gets list of timer \n !start /something/: launch a timer "
2012-04-09 02:19:39 +00:00
def parseanswer ( msg ) :
2012-04-30 16:22:10 +00:00
global STREND
2012-04-09 02:19:39 +00:00
if msg . cmd [ 0 ] == " we " or msg . cmd [ 0 ] == " week-end " or msg . cmd [ 0 ] == " weekend " :
ndate = datetime . today ( ) + timedelta ( 5 - datetime . today ( ) . weekday ( ) )
ndate = datetime ( ndate . year , ndate . month , ndate . day , 0 , 0 , 1 )
msg . send_chn (
msg . countdown_format ( ndate ,
" Il reste %s avant le week-end, courrage ;) " ,
" Youhou, on est en week-end depuis %s . " ) )
return True
elif msg . cmd [ 0 ] == " new-year " or msg . cmd [ 0 ] == " newyear " or msg . cmd [ 0 ] == " ny " :
msg . send_chn (
msg . countdown_format ( datetime ( datetime . today ( ) . year + 1 , 1 , 1 , 0 , 0 , 1 ) ,
" Il reste %s avant la nouvelle année. " ,
" Nous faisons déjà la fête depuis %s ! " ) )
return True
elif msg . cmd [ 0 ] == " vacances " or msg . cmd [ 0 ] == " vacs " or msg . cmd [ 0 ] == " holiday " or msg . cmd [ 0 ] == " holidays " :
msg . send_chn (
msg . countdown_format ( datetime ( 2012 , 7 , 30 , 18 , 0 , 1 ) ,
" Il reste %s avant les vacances :) " ,
" Profitons, c ' est les vacances depuis %s . " ) )
return True
2012-04-30 16:22:10 +00:00
elif msg . cmd [ 0 ] == " start " and len ( msg . cmd ) > 1 :
if msg . cmd [ 1 ] not in STREND :
STREND [ msg . cmd [ 1 ] ] = Strend ( None )
2012-05-14 15:50:11 +00:00
STREND [ msg . cmd [ 1 ] ] . server = msg . srv . id
STREND [ msg . cmd [ 1 ] ] . channel = msg . channel
2012-04-30 16:22:10 +00:00
STREND [ msg . cmd [ 1 ] ] . proprio = msg . sender
STREND [ msg . cmd [ 1 ] ] . name = msg . cmd [ 1 ]
2012-05-14 15:50:11 +00:00
if len ( msg . cmd ) > 2 :
result = re . match ( " ([0-9]+)([smhdjSMHDJ])? " , msg . cmd [ 2 ] )
if result is not None :
try :
if result . group ( 2 ) is not None and ( result . group ( 2 ) == " m " or result . group ( 2 ) == " M " ) :
STREND [ msg . cmd [ 1 ] ] . end = datetime . now ( ) + timedelta ( minutes = int ( result . group ( 1 ) ) )
elif result . group ( 2 ) is not None and ( result . group ( 2 ) == " h " or result . group ( 2 ) == " H " ) :
STREND [ msg . cmd [ 1 ] ] . end = datetime . now ( ) + timedelta ( hours = int ( result . group ( 1 ) ) )
elif result . group ( 2 ) is not None and ( result . group ( 2 ) == " d " or result . group ( 2 ) == " D " or result . group ( 2 ) == " j " or result . group ( 2 ) == " J " ) :
STREND [ msg . cmd [ 1 ] ] . end = datetime . now ( ) + timedelta ( days = int ( result . group ( 1 ) ) )
else :
STREND [ msg . cmd [ 1 ] ] . end = datetime . now ( ) + timedelta ( seconds = int ( result . group ( 1 ) ) )
newStrendEvt . set ( )
msg . send_snd ( " %s commencé le %s et se terminera le %s . " % ( msg . cmd [ 1 ] , datetime . now ( ) , STREND [ msg . cmd [ 1 ] ] . end ) )
except :
msg . send_snd ( " Impossible de définir la fin de %s . " % ( msg . cmd [ 1 ] ) )
msg . send_snd ( " %s commencé le %s . " % ( msg . cmd [ 1 ] , datetime . now ( ) ) )
else :
msg . send_snd ( " %s commencé le %s " % ( msg . cmd [ 1 ] , datetime . now ( ) ) )
2012-04-30 16:22:10 +00:00
else :
msg . send_snd ( " %s existe déjà. " % ( msg . cmd [ 1 ] ) )
2012-05-14 15:50:11 +00:00
elif ( msg . cmd [ 0 ] == " end " or msg . cmd [ 0 ] == " forceend " ) and len ( msg . cmd ) > 1 :
2012-04-30 16:22:10 +00:00
if msg . cmd [ 1 ] in STREND :
msg . send_chn ( " %s a duré %s . " % ( msg . cmd [ 1 ] , msg . just_countdown ( datetime . now ( ) - STREND [ msg . cmd [ 1 ] ] . start ) ) )
2012-05-14 15:50:11 +00:00
if STREND [ msg . cmd [ 1 ] ] . proprio == msg . sender or ( msg . cmd [ 0 ] == " forceend " and msg . sender == msg . srv . owner ) :
2012-04-30 16:22:10 +00:00
del STREND [ msg . cmd [ 1 ] ]
2012-05-14 15:50:11 +00:00
newStrendEvt . set ( )
2012-04-30 16:22:10 +00:00
else :
msg . send_snd ( " Vous ne pouvez pas terminer le compteur %s , créé par %s . " % ( msg . cmd [ 1 ] , STREND [ msg . cmd [ 1 ] ] . proprio ) )
else :
msg . send_snd ( " %s n ' est pas un compteur connu. " % ( msg . cmd [ 1 ] ) )
elif msg . cmd [ 0 ] == " eventslist " or msg . cmd [ 0 ] == " eventlist " or msg . cmd [ 0 ] == " eventsliste " or msg . cmd [ 0 ] == " eventliste " :
msg . send_snd ( " Compteurs connus : %s . " % " , " . join ( STREND . keys ( ) ) )
elif msg . cmd [ 0 ] in STREND :
msg . send_chn ( " %s commencé il y a %s . " % ( msg . cmd [ 0 ] , msg . just_countdown ( datetime . now ( ) - STREND [ msg . cmd [ 0 ] ] . start ) ) )
2012-04-09 02:19:39 +00:00
elif msg . cmd [ 0 ] in EVENTS :
( day , msg_before , msg_after ) = EVENTS [ msg . cmd [ 0 ] ]
if day is None :
msg . send_chn ( msg_before )
else :
msg . send_chn ( msg . countdown_format ( day , msg_before , msg_after ) )
return True
else :
return False
def parseask ( msg ) :
msgl = msg . content . lower ( )
if re . match ( " ^.*((create|new) +(a|an|a +new|an *other)? *(events?|commande?)|(nouvel(le)?|ajoute|cr[ée] { 1,3}) +(un)? *([eé]v[ée]nements?|commande?)).*$ " , msgl ) is not None :
name = re . match ( " ^.*!([^ \" ' @!]+).*$ " , msg . content )
if name is not None and name . group ( 1 ) not in EVENTS :
texts = re . match ( " ^[^ \" ]*(avant|après|apres|before|after)?[^ \" ]* \" ([^ \" ]+) \" [^ \" ]*((avant|après|apres|before|after)?.* \" ([^ \" ]+) \" .*)?$ " , msg . content )
if texts is not None and texts . group ( 3 ) is not None :
extDate = msg . extractDate ( )
if extDate is None or extDate == " " :
msg . send_snd ( " La date de l ' événement est invalide... " )
else :
if texts . group ( 1 ) is not None and ( texts . group ( 1 ) == " après " or texts . group ( 1 ) == " apres " or texts . group ( 1 ) == " after " ) :
msg_after = texts . group ( 2 )
msg_before = texts . group ( 5 )
if ( texts . group ( 4 ) is not None and ( texts . group ( 4 ) == " après " or texts . group ( 4 ) == " apres " or texts . group ( 4 ) == " after " ) ) or texts . group ( 1 ) is None :
msg_before = texts . group ( 2 )
msg_after = texts . group ( 5 )
if msg_before . find ( " %s " ) != - 1 and msg_after . find ( " %s " ) != - 1 :
EVENTS [ name . group ( 1 ) ] = ( extDate , msg_before , msg_after )
save_module ( )
msg . send_snd ( " Nouvel événement ! %s ajouté avec succès. " % name . group ( 1 ) )
else :
msg . send_snd ( " Pour que l ' événement soit valide, ajouter %s à l ' endroit où vous voulez que soit ajouté le compte à rebours. " )
elif texts is not None and texts . group ( 2 ) is not None :
EVENTS [ name . group ( 1 ) ] = ( None , texts . group ( 2 ) , None )
save_module ( )
msg . send_snd ( " Nouvelle commande ! %s ajoutée avec succès. " % name . group ( 1 ) )
else :
msg . send_snd ( " Veuillez indiquez les messages d ' attente et d ' après événement entre guillemets. " )
elif name is None :
msg . send_snd ( " Veuillez attribuer une commande à l ' événement. " )
else :
msg . send_snd ( " Un événement portant ce nom existe déjà. " )
return False
def parselisten ( msg ) :
return False