<s> import csv <EOL> import time <EOL> import datetime <EOL> import supybot . log as log <EOL> import supybot . conf as conf <EOL> import supybot . utils as utils <EOL> from supybot . commands import * <EOL> import supybot . ircmsgs as ircmsgs <EOL> import supybot . ircutils as ircutils <EOL> import supybot . callbacks as callbacks <EOL> from supybot . i18n import PluginInternationalization , internationalizeDocstring <EOL> _ = PluginInternationalization ( '<STR_LIT>' ) <EOL> class QueueIsFull ( Exception ) : <EOL> pass <EOL> class Later ( callbacks . Plugin ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , irc ) : <EOL> self . __parent = super ( Later , self ) <EOL> self . __parent . __init__ ( irc ) <EOL> self . _notes = ircutils . IrcDict ( ) <EOL> self . wildcards = [ ] <EOL> self . filename = conf . supybot . directories . data . dirize ( '<STR_LIT>' ) <EOL> self . _openNotes ( ) <EOL> def die ( self ) : <EOL> self . _flushNotes ( ) <EOL> def _flushNotes ( self ) : <EOL> fd = utils . file . AtomicFile ( self . filename ) <EOL> writer = csv . writer ( fd ) <EOL> for ( nick , notes ) in self . _notes . items ( ) : <EOL> for ( time , whence , text ) in notes : <EOL> writer . writerow ( [ nick , time , whence , text ] ) <EOL> fd . close ( ) <EOL> def _openNotes ( self ) : <EOL> try : <EOL> fd = open ( self . filename ) <EOL> except EnvironmentError as e : <EOL> self . log . warning ( '<STR_LIT>' , self . filename , e ) <EOL> return <EOL> reader = csv . reader ( fd ) <EOL> for ( nick , time , whence , text ) in reader : <EOL> self . _addNote ( nick , whence , text , at = float ( time ) , maximum = <NUM_LIT:0> ) <EOL> fd . close ( ) <EOL> def _timestamp ( self , when ) : <EOL> diff = when - time . time ( ) <EOL> try : <EOL> return utils . timeElapsed ( diff , seconds = False ) <EOL> except ValueError : <EOL> return _ ( '<STR_LIT>' ) <EOL> def _addNote ( self , nick , whence , text , at = None , maximum = None ) : <EOL> if at is None : <EOL> at = time . time ( ) <EOL> if maximum is None : <EOL> maximum = self . registryValue ( '<STR_LIT>' ) <EOL> try : <EOL> notes = self . _notes [ nick ] <EOL> if maximum and len ( notes ) >= maximum : <EOL> raise QueueIsFull ( ) <EOL> else : <EOL> notes . append ( ( at , whence , text ) ) <EOL> except KeyError : <EOL> self . _notes [ nick ] = [ ( at , whence , text ) ] <EOL> if '<STR_LIT:?>' in nick or '<STR_LIT:*>' in nick and nick not in self . wildcards : <EOL> self . wildcards . append ( nick ) <EOL> self . _flushNotes ( ) <EOL> def _validateNick ( self , irc , nick ) : <EOL> """<STR_LIT>""" <EOL> if not irc . isNick ( nick ) : <EOL> if not irc . isNick ( nick [ : - <NUM_LIT:1> ] ) : <EOL> return False <EOL> else : <EOL> return nick [ : - <NUM_LIT:1> ] <EOL> return nick <EOL> def _deleteExpired ( self ) : <EOL> expiry = self . registryValue ( '<STR_LIT>' ) <EOL> curtime = time . time ( ) <EOL> nickremovals = [ ] <EOL> for ( nick , notes ) in self . _notes . items ( ) : <EOL> removals = [ ] <EOL> for ( notetime , whence , text ) in notes : <EOL> td = datetime . timedelta ( seconds = ( curtime - notetime ) ) <EOL> if td . days > expiry : <EOL> removals . append ( ( notetime , whence , text ) ) <EOL> for note in removals : <EOL> notes . remove ( note ) <EOL> if len ( notes ) == <NUM_LIT:0> : <EOL> nickremovals . append ( nick ) <EOL> for nick in nickremovals : <EOL> del self . _notes [ nick ] <EOL> self . _flushNotes ( ) <EOL> @ internationalizeDocstring <EOL> def tell ( self , irc , msg , args , nicks , text ) : <EOL> """<STR_LIT>""" <EOL> self . _deleteExpired ( ) <EOL> validnicks = [ ] <EOL> for nick in nicks : <EOL> if ircutils . strEqual ( nick , irc . nick ) : <EOL> irc . error ( _ ( '<STR_LIT>' ) ) <EOL> return <EOL> validnick = self . _validateNick ( irc , nick ) <EOL> if validnick is False : <EOL> irc . error ( _ ( '<STR_LIT>' <EOL> '<STR_LIT>' % nick ) ) <EOL> return <EOL> validnicks . append ( validnick ) <EOL> full_queues = [ ] <EOL> for validnick in validnicks : <EOL> try : <EOL> self . _addNote ( validnick , msg . nick , text ) <EOL> except QueueIsFull : <EOL> full_queues . append ( validnick ) <EOL> if full_queues : <EOL> irc . error ( format ( <EOL> _ ( '<STR_LIT>' ) , <EOL> full_queues ) ) <EOL> else : <EOL> irc . replySuccess ( ) <EOL> tell = wrap ( tell , [ commalist ( '<STR_LIT>' ) , '<STR_LIT:text>' ] ) <EOL> @ internationalizeDocstring <EOL> def notes ( self , irc , msg , args , nick ) : <EOL> """<STR_LIT>""" <EOL> if nick : <EOL> if nick in self . _notes : <EOL> notes = [ self . _formatNote ( when , whence , note ) <EOL> for ( when , whence , note ) in self . _notes [ nick ] ] <EOL> irc . reply ( format ( '<STR_LIT>' , notes ) ) <EOL> else : <EOL> irc . error ( _ ( '<STR_LIT>' ) ) <EOL> else : <EOL> nicks = self . _notes . keys ( ) <EOL> if nicks : <EOL> utils . sortBy ( ircutils . toLower , nicks ) <EOL> irc . reply ( format ( _ ( '<STR_LIT>' ) , <EOL> nicks ) ) <EOL> else : <EOL> irc . error ( _ ( '<STR_LIT>' ) ) <EOL> notes = wrap ( notes , [ additional ( '<STR_LIT>' ) ] ) <EOL> @ internationalizeDocstring <EOL> def remove ( self , irc , msg , args , nick ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> del self . _notes [ nick ] <EOL> self . _flushNotes ( ) <EOL> irc . replySuccess ( ) <EOL> except KeyError : <EOL> irc . error ( _ ( '<STR_LIT>' ) % nick ) <EOL> remove = wrap ( remove , [ ( '<STR_LIT>' , '<STR_LIT>' ) , '<STR_LIT>' ] ) <EOL> @ internationalizeDocstring <EOL> def undo ( self , irc , msg , args , nick ) : <EOL> """<STR_LIT>""" <EOL> if nick not in self . _notes : <EOL> irc . error ( _ ( '<STR_LIT>' ) % nick ) <EOL> return <EOL> self . _notes [ nick ] . reverse ( ) <EOL> for note in self . _notes [ nick ] : <EOL> if note [ <NUM_LIT:1> ] == msg . nick : <EOL> self . _notes [ nick ] . remove ( note ) <EOL> if len ( self . _notes [ nick ] ) == <NUM_LIT:0> : <EOL> del self . _notes [ nick ] <EOL> self . _flushNotes ( ) <EOL> irc . replySuccess ( ) <EOL> return <EOL> irc . error ( _ ( '<STR_LIT>' ) % nick ) <EOL> undo = wrap ( undo , [ '<STR_LIT>' ] ) <EOL> def doPrivmsg ( self , irc , msg ) : <EOL> if ircmsgs . isCtcp ( msg ) and not ircmsgs . isAction ( msg ) : <EOL> return <EOL> notes = self . _notes . pop ( msg . nick , [ ] ) <EOL> removals = [ ] <EOL> for wildcard in self . wildcards : <EOL> if ircutils . hostmaskPatternEqual ( wildcard , msg . nick ) : <EOL> removals . append ( wildcard ) <EOL> notes . extend ( self . _notes . pop ( wildcard ) ) <EOL> for removal in removals : <EOL> self . wildcards . remove ( removal ) <EOL> if notes : <EOL> old_repliedto = msg . repliedTo <EOL> irc = callbacks . SimpleProxy ( irc , msg ) <EOL> private = self . registryValue ( '<STR_LIT>' ) <EOL> for ( when , whence , note ) in notes : <EOL> s = self . _formatNote ( when , whence , note ) <EOL> irc . reply ( s , private = private , prefixNick = not private ) <EOL> self . _flushNotes ( ) <EOL> msg . tag ( '<STR_LIT>' , old_repliedto ) <EOL> def _formatNote ( self , when , whence , note ) : <EOL> return _ ( '<STR_LIT>' ) % ( self . _timestamp ( when ) , whence , note ) <EOL> def doJoin ( self , irc , msg ) : <EOL> if self . registryValue ( '<STR_LIT>' ) : <EOL> self . doPrivmsg ( irc , msg ) <EOL> Later = internationalizeDocstring ( Later ) <EOL> Class = Later </s>
