2014-08-08 17:45:41 +00:00
# coding=utf-8
2014-08-27 23:39:31 +00:00
""" Create countdowns and reminders """
2014-08-08 17:45:41 +00:00
import imp
import re
import sys
2014-09-30 21:51:14 +00:00
from datetime import datetime , timedelta , timezone
2014-08-08 17:45:41 +00:00
import time
import threading
import traceback
2015-02-11 17:12:39 +00:00
from nemubot import context
2015-01-04 22:57:09 +00:00
from nemubot . exception import IRCException
2015-01-03 19:34:44 +00:00
from nemubot . event import ModuleEvent
from nemubot . hooks import hook
from nemubot . tools . countdown import countdown_format , countdown
2015-01-05 09:18:40 +00:00
from nemubot . tools . date import extractDate
from nemubot . tools . xmlparser . node import ModuleState
2014-08-08 17:45:41 +00:00
2014-09-26 16:00:22 +00:00
nemubotversion = 3.4
from more import Response
2014-08-08 17:45:41 +00:00
def help_full ( ) :
2015-02-11 17:12:39 +00:00
return " This module store a lot of events: ny, we, " + ( " , " . join ( context . datas . index . keys ( ) ) ) + " \n !eventslist: gets list of timer \n !start /something/: launch a timer "
2014-08-08 17:45:41 +00:00
def load ( context ) :
#Define the index
2015-02-11 17:12:39 +00:00
context . data . setIndex ( " name " )
for evt in context . data . index . keys ( ) :
if context . data . index [ evt ] . hasAttribute ( " end " ) :
event = ModuleEvent ( call = fini , call_data = dict ( strend = context . data . index [ evt ] ) )
event . _end = context . data . index [ evt ] . getDate ( " end " )
idt = context . add_event ( event )
2014-08-08 17:45:41 +00:00
if idt is not None :
2015-02-11 17:12:39 +00:00
context . data . index [ evt ] [ " _id " ] = idt
2014-08-08 17:45:41 +00:00
def fini ( d , strend ) :
2015-02-11 17:12:39 +00:00
context . send_response ( strend [ " server " ] , Response ( " %s arrivé à échéance. " % strend [ " name " ] , channel = strend [ " channel " ] , nick = strend [ " proprio " ] ) )
context . data . delChild ( context . data . index [ strend [ " name " ] ] )
context . save ( )
2014-08-08 17:45:41 +00:00
2014-08-12 18:10:19 +00:00
@hook ( " cmd_hook " , " goûter " )
2014-08-08 17:45:41 +00:00
def cmd_gouter ( msg ) :
2014-09-30 21:51:14 +00:00
ndate = datetime . now ( timezone . utc )
ndate = datetime ( ndate . year , ndate . month , ndate . day , 16 , 42 , 0 , 0 , timezone . utc )
2014-09-18 05:57:06 +00:00
return Response ( countdown_format ( ndate ,
2014-08-08 17:45:41 +00:00
" Le goûter aura lieu dans %s , préparez vos biscuits ! " ,
" Nous avons %s de retard pour le goûter :( " ) ,
channel = msg . channel )
2014-08-12 18:10:19 +00:00
@hook ( " cmd_hook " , " week-end " )
2014-08-08 17:45:41 +00:00
def cmd_we ( msg ) :
2014-09-30 21:51:14 +00:00
ndate = datetime . now ( timezone . utc ) + timedelta ( 5 - datetime . today ( ) . weekday ( ) )
ndate = datetime ( ndate . year , ndate . month , ndate . day , 0 , 0 , 1 , 0 , timezone . utc )
2014-09-18 05:57:06 +00:00
return Response ( countdown_format ( ndate ,
2014-08-08 17:45:41 +00:00
" Il reste %s avant le week-end, courage ;) " ,
" Youhou, on est en week-end depuis %s . " ) ,
channel = msg . channel )
2014-09-11 19:20:56 +00:00
@hook ( " cmd_hook " , " start " )
2014-08-08 17:45:41 +00:00
def start_countdown ( msg ) :
2014-09-11 19:20:56 +00:00
""" !start /something/: launch a timer """
2015-07-10 21:09:54 +00:00
if len ( msg . args ) < 1 :
2014-08-08 17:45:41 +00:00
raise IRCException ( " indique le nom d ' un événement à chronométrer " )
2015-07-10 21:09:54 +00:00
if msg . args [ 0 ] in context . data . index :
raise IRCException ( " %s existe déjà. " % msg . args [ 0 ] )
2014-08-08 17:45:41 +00:00
strnd = ModuleState ( " strend " )
strnd [ " server " ] = msg . server
strnd [ " channel " ] = msg . channel
strnd [ " proprio " ] = msg . nick
2014-10-05 16:19:20 +00:00
strnd [ " start " ] = msg . date
2015-07-10 21:09:54 +00:00
strnd [ " name " ] = msg . args [ 0 ]
2015-02-11 17:12:39 +00:00
context . data . addChild ( strnd )
2014-08-08 17:45:41 +00:00
evt = ModuleEvent ( call = fini , call_data = dict ( strend = strnd ) )
2015-07-10 21:09:54 +00:00
if len ( msg . args ) > 1 :
result1 = re . findall ( " ([0-9]+)([smhdjwyaSMHDJWYA])? " , msg . args [ 1 ] )
result2 = re . match ( " (.*[^0-9])?([0-3]?[0-9])/([0-1]?[0-9])/((19|20)?[01239][0-9]) " , msg . args [ 1 ] )
result3 = re . match ( " (.*[^0-9])?([0-2]?[0-9]):([0-5]?[0-9])(:([0-5]?[0-9]))? " , msg . args [ 1 ] )
2014-08-08 17:45:41 +00:00
if result2 is not None or result3 is not None :
try :
2014-10-05 16:19:20 +00:00
now = msg . date
2014-08-08 17:45:41 +00:00
if result3 is None or result3 . group ( 5 ) is None : sec = 0
else : sec = int ( result3 . group ( 5 ) )
if result3 is None or result3 . group ( 3 ) is None : minu = 0
else : minu = int ( result3 . group ( 3 ) )
if result3 is None or result3 . group ( 2 ) is None : hou = 0
else : hou = int ( result3 . group ( 2 ) )
if result2 is None or result2 . group ( 4 ) is None : yea = now . year
else : yea = int ( result2 . group ( 4 ) )
if result2 is not None and result3 is not None :
2014-09-30 21:51:14 +00:00
strnd [ " end " ] = datetime ( yea , int ( result2 . group ( 3 ) ) , int ( result2 . group ( 2 ) ) , hou , minu , sec , timezone . utc )
2014-08-08 17:45:41 +00:00
elif result2 is not None :
2014-09-30 21:51:14 +00:00
strnd [ " end " ] = datetime ( int ( result2 . group ( 4 ) ) , int ( result2 . group ( 3 ) ) , int ( result2 . group ( 2 ) ) , 0 , 0 , 0 , timezone . utc )
2014-08-08 17:45:41 +00:00
elif result3 is not None :
if hou * 3600 + minu * 60 + sec > now . hour * 3600 + now . minute * 60 + now . second :
2014-09-30 21:51:14 +00:00
strnd [ " end " ] = datetime ( now . year , now . month , now . day , hou , minu , sec , timezone . utc )
2014-08-08 17:45:41 +00:00
else :
2014-09-30 21:51:14 +00:00
strnd [ " end " ] = datetime ( now . year , now . month , now . day + 1 , hou , minu , sec , timezone . utc )
2014-09-23 20:27:53 +00:00
evt . _end = strnd . getDate ( " end " )
2015-02-11 17:12:39 +00:00
strnd [ " _id " ] = context . add_event ( evt )
2014-08-08 17:45:41 +00:00
except :
2015-02-11 17:12:39 +00:00
context . data . delChild ( strnd )
2015-07-10 21:09:54 +00:00
raise IRCException ( " Mauvais format de date pour l ' événement %s . Il n ' a pas été créé. " % msg . args [ 0 ] )
2014-08-08 17:45:41 +00:00
elif result1 is not None and len ( result1 ) > 0 :
2014-10-05 16:19:20 +00:00
strnd [ " end " ] = msg . date
2014-08-08 17:45:41 +00:00
for ( t , g ) in result1 :
if g is None or g == " " or g == " m " or g == " M " :
strnd [ " end " ] + = timedelta ( minutes = int ( t ) )
elif g == " h " or g == " H " :
strnd [ " end " ] + = timedelta ( hours = int ( t ) )
elif g == " d " or g == " D " or g == " j " or g == " J " :
strnd [ " end " ] + = timedelta ( days = int ( t ) )
elif g == " w " or g == " W " :
strnd [ " end " ] + = timedelta ( days = int ( t ) * 7 )
elif g == " y " or g == " Y " or g == " a " or g == " A " :
strnd [ " end " ] + = timedelta ( days = int ( t ) * 365 )
else :
strnd [ " end " ] + = timedelta ( seconds = int ( t ) )
2014-09-23 20:27:53 +00:00
evt . _end = strnd . getDate ( " end " )
2015-02-11 17:12:39 +00:00
eid = context . add_event ( evt )
2014-09-23 20:27:53 +00:00
if eid is not None :
2014-12-30 20:22:56 +00:00
strnd [ " _id " ] = eid
2014-08-08 17:45:41 +00:00
2015-02-11 17:12:39 +00:00
context . save ( )
2014-08-08 17:45:41 +00:00
if " end " in strnd :
2014-09-18 05:57:06 +00:00
return Response ( " %s commencé le %s et se terminera le %s . " %
2015-07-10 21:09:54 +00:00
( msg . args [ 0 ] , msg . date . strftime ( " % A %d % B % Y à % H: % M: % S " ) ,
2014-10-05 16:19:20 +00:00
strnd . getDate ( " end " ) . strftime ( " % A %d % B % Y à % H: % M: % S " ) ) ,
nick = msg . frm )
2014-08-08 17:45:41 +00:00
else :
2015-07-10 21:09:54 +00:00
return Response ( " %s commencé le %s " % ( msg . args [ 0 ] ,
2014-10-05 16:19:20 +00:00
msg . date . strftime ( " % A %d % B % Y à % H: % M: % S " ) ) ,
nick = msg . frm )
2014-08-08 17:45:41 +00:00
2014-08-12 18:10:19 +00:00
@hook ( " cmd_hook " , " end " )
@hook ( " cmd_hook " , " forceend " )
2014-08-08 17:45:41 +00:00
def end_countdown ( msg ) :
2015-07-10 21:09:54 +00:00
if len ( msg . args ) < 1 :
2014-08-08 17:45:41 +00:00
raise IRCException ( " quel événement terminer ? " )
2015-07-10 21:09:54 +00:00
if msg . args [ 0 ] in context . data . index :
if context . data . index [ msg . args [ 0 ] ] [ " proprio " ] == msg . nick or ( msg . cmd == " forceend " and msg . frm_owner ) :
duration = countdown ( msg . date - context . data . index [ msg . args [ 0 ] ] . getDate ( " start " ) )
context . del_event ( context . data . index [ msg . args [ 0 ] ] [ " _id " ] )
context . data . delChild ( context . data . index [ msg . args [ 0 ] ] )
2015-02-11 17:12:39 +00:00
context . save ( )
2015-07-10 21:09:54 +00:00
return Response ( " %s a duré %s . " % ( msg . args [ 0 ] , duration ) ,
2014-08-08 17:45:41 +00:00
channel = msg . channel , nick = msg . nick )
else :
2015-07-10 21:09:54 +00:00
raise IRCException ( " Vous ne pouvez pas terminer le compteur %s , créé par %s . " % ( msg . args [ 0 ] , context . data . index [ msg . args [ 0 ] ] [ " proprio " ] ) )
2014-08-08 17:45:41 +00:00
else :
2015-07-10 21:09:54 +00:00
return Response ( " %s n ' est pas un compteur connu. " % ( msg . args [ 0 ] ) , channel = msg . channel , nick = msg . nick )
2014-08-08 17:45:41 +00:00
2014-09-11 19:20:56 +00:00
@hook ( " cmd_hook " , " eventslist " )
2014-08-08 17:45:41 +00:00
def liste ( msg ) :
2014-09-11 19:20:56 +00:00
""" !eventslist: gets list of timer """
2015-07-10 21:09:54 +00:00
if len ( msg . args ) :
2014-08-08 17:45:41 +00:00
res = list ( )
2015-07-10 21:09:54 +00:00
for user in msg . args :
2015-02-11 17:12:39 +00:00
cmptr = [ x [ " name " ] for x in context . data . index . values ( ) if x [ " proprio " ] == user ]
2014-08-08 17:45:41 +00:00
if len ( cmptr ) > 0 :
res . append ( " Compteurs créés par %s : %s " % ( user , " , " . join ( cmptr ) ) )
else :
res . append ( " %s n ' a pas créé de compteur " % user )
2014-09-18 05:57:06 +00:00
return Response ( " ; " . join ( res ) , channel = msg . channel )
2014-08-08 17:45:41 +00:00
else :
2015-02-11 17:12:39 +00:00
return Response ( " Compteurs connus : %s . " % " , " . join ( context . data . index . keys ( ) ) , channel = msg . channel )
2014-08-08 17:45:41 +00:00
2014-08-28 16:05:21 +00:00
@hook ( " cmd_default " )
2014-08-08 17:45:41 +00:00
def parseanswer ( msg ) :
2015-07-10 21:09:54 +00:00
if msg . cmd in context . data . index :
2014-09-18 05:57:06 +00:00
res = Response ( channel = msg . channel )
2014-08-08 17:45:41 +00:00
# Avoid message starting by ! which can be interpreted as command by other bots
2015-07-10 21:09:54 +00:00
if msg . cmd [ 0 ] == " ! " :
2014-08-08 17:45:41 +00:00
res . nick = msg . nick
2015-07-10 21:09:54 +00:00
if context . data . index [ msg . cmd ] . name == " strend " :
if context . data . index [ msg . cmd ] . hasAttribute ( " end " ) :
res . append_message ( " %s commencé il y a %s et se terminera dans %s . " % ( msg . cmd , countdown ( msg . date - context . data . index [ msg . cmd ] . getDate ( " start " ) ) , countdown ( context . data . index [ msg . cmd ] . getDate ( " end " ) - msg . date ) ) )
2014-08-08 17:45:41 +00:00
else :
2015-07-10 21:09:54 +00:00
res . append_message ( " %s commencé il y a %s . " % ( msg . cmd , countdown ( msg . date - context . data . index [ msg . cmd ] . getDate ( " start " ) ) ) )
2014-08-08 17:45:41 +00:00
else :
2015-07-10 21:09:54 +00:00
res . append_message ( countdown_format ( context . data . index [ msg . cmd ] . getDate ( " start " ) , context . data . index [ msg . cmd ] [ " msg_before " ] , context . data . index [ msg . cmd ] [ " msg_after " ] ) )
2014-08-08 17:45:41 +00:00
return res
RGXP_ask = re . compile ( r " ^.*((create|new) \ s+(a|an|a \ s*new|an \ s*other)? \ s*(events?|commande?)|(nouvel(le)?|ajoute|cr[ée] { 1,3}) \ s+(un)? \ s*([eé]v[ée]nements?|commande?)).*$ " , re . I )
2014-08-28 16:05:21 +00:00
@hook ( " ask_default " )
2014-08-08 17:45:41 +00:00
def parseask ( msg ) :
2014-08-29 14:33:45 +00:00
if RGXP_ask . match ( msg . text ) is not None :
name = re . match ( " ^.*!([^ \" ' @!]+).*$ " , msg . text )
2014-08-08 17:45:41 +00:00
if name is None :
raise IRCException ( " il faut que tu attribues une commande à l ' événement. " )
2015-02-11 17:12:39 +00:00
if name . group ( 1 ) in context . data . index :
2014-08-08 17:45:41 +00:00
raise IRCException ( " un événement portant ce nom existe déjà. " )
2014-08-29 14:33:45 +00:00
texts = re . match ( " ^[^ \" ]*(avant|après|apres|before|after)?[^ \" ]* \" ([^ \" ]+) \" [^ \" ]*((avant|après|apres|before|after)?.* \" ([^ \" ]+) \" .*)?$ " , msg . text , re . I )
2014-08-08 17:45:41 +00:00
if texts is not None and texts . group ( 3 ) is not None :
2014-09-08 00:25:26 +00:00
extDate = extractDate ( msg . text )
2014-08-08 17:45:41 +00:00
if extDate is None or extDate == " " :
raise IRCException ( " la date de l ' événement est invalide ! " )
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 or msg_after . find ( " %s " ) == - 1 :
raise IRCException ( " Pour que l ' événement soit valide, ajouter %s à "
" l ' endroit où vous voulez que soit ajouté le "
" compte à rebours. " )
evt = ModuleState ( " event " )
evt [ " server " ] = msg . server
evt [ " channel " ] = msg . channel
evt [ " proprio " ] = msg . nick
evt [ " name " ] = name . group ( 1 )
evt [ " start " ] = extDate
evt [ " msg_after " ] = msg_after
evt [ " msg_before " ] = msg_before
2015-02-11 17:12:39 +00:00
context . data . addChild ( evt )
context . save ( )
2014-09-18 05:57:06 +00:00
return Response ( " Nouvel événement ! %s ajouté avec succès. " % name . group ( 1 ) ,
2014-08-08 17:45:41 +00:00
channel = msg . channel )
elif texts is not None and texts . group ( 2 ) is not None :
evt = ModuleState ( " event " )
evt [ " server " ] = msg . server
evt [ " channel " ] = msg . channel
evt [ " proprio " ] = msg . nick
evt [ " name " ] = name . group ( 1 )
evt [ " msg_before " ] = texts . group ( 2 )
2015-02-11 17:12:39 +00:00
context . data . addChild ( evt )
context . save ( )
2014-10-05 16:19:20 +00:00
return Response ( " Nouvelle commande ! %s ajoutée avec succès. " % name . group ( 1 ) ,
channel = msg . channel )
2014-08-08 17:45:41 +00:00
else :
raise IRCException ( " Veuillez indiquez les messages d ' attente et d ' après événement entre guillemets. " )