<s> import datetime <EOL> import functools <EOL> from email . mime . text import MIMEText <EOL> from twisted . internet import reactor <EOL> from harold . plugins . http import ProtectedResource <EOL> from harold . conf import PluginConfig , Option , tup <EOL> from harold . utils import pretty_time_span <EOL> from harold . plugins import watchdog <EOL> def make_short_name ( jid ) : <EOL> short_name = jid . split ( '<STR_LIT:@>' ) [ <NUM_LIT:0> ] <EOL> return short_name <EOL> def strip_resource_id ( jid ) : <EOL> return jid . partition ( "<STR_LIT:/>" ) [ <NUM_LIT:0> ] <EOL> class AlertsConfig ( PluginConfig ) : <EOL> recipients = Option ( tup , default = [ ] ) <EOL> ttl = Option ( int , default = <NUM_LIT> ) <EOL> max_mute_duration = Option ( int , default = <NUM_LIT> ) <EOL> class BroadcastAlertListener ( ProtectedResource ) : <EOL> isLeaf = True <EOL> def __init__ ( self , http , alerter ) : <EOL> ProtectedResource . __init__ ( self , http ) <EOL> self . alerter = alerter <EOL> def _handle_request ( self , request ) : <EOL> tag = request . args [ '<STR_LIT>' ] [ <NUM_LIT:0> ] <EOL> message = request . args [ '<STR_LIT:message>' ] [ <NUM_LIT:0> ] <EOL> self . alerter . alert ( tag , message ) <EOL> class Alert ( object ) : <EOL> pass <EOL> class Quiet ( object ) : <EOL> pass <EOL> class Alerter ( object ) : <EOL> def __init__ ( self , config , jabber , smtp ) : <EOL> self . config = config <EOL> self . alerts = { } <EOL> self . quiets = { } <EOL> self . maintenance = None <EOL> senders = { } <EOL> if jabber : <EOL> self . jabber_bot = jabber . bot <EOL> senders [ "<STR_LIT>" ] = self . _send_jabber <EOL> if smtp : <EOL> self . smtp = smtp <EOL> senders [ "<STR_LIT>" ] = self . _send_smtp <EOL> self . recipients = [ ] <EOL> for recipient in self . config . recipients : <EOL> medium , id = recipient . split ( '<STR_LIT::>' , <NUM_LIT:1> ) <EOL> sender = functools . partial ( senders [ medium ] , id ) <EOL> self . recipients . append ( sender ) <EOL> def _send_smtp ( self , recipient , message ) : <EOL> email = MIMEText ( message ) <EOL> self . smtp . sendmail ( <EOL> self . smtp . username , <EOL> [ recipient ] , <EOL> email <EOL> ) <EOL> def _send_jabber ( self , recipient , message ) : <EOL> if recipient not in self . quiets : <EOL> self . jabber_bot . sendMessage ( recipient , message ) <EOL> def broadcast ( self , message ) : <EOL> for recipient in self . recipients : <EOL> recipient ( message ) <EOL> def alert ( self , tag , message ) : <EOL> alert = self . _register_alert ( tag ) <EOL> if not self . maintenance and not alert . muted : <EOL> self . broadcast ( "<STR_LIT>" % ( tag , message ) ) <EOL> def _register_alert ( self , tag ) : <EOL> alert = self . alerts . get ( tag ) <EOL> if not alert : <EOL> alert = Alert ( ) <EOL> alert . first_seen = datetime . datetime . now ( ) <EOL> alert . count = <NUM_LIT:0> <EOL> alert . muted = False <EOL> alert . expirator = None <EOL> self . alerts [ tag ] = alert <EOL> if alert . expirator : <EOL> alert . expirator . cancel ( ) <EOL> alert . count += <NUM_LIT:1> <EOL> alert . last_seen = datetime . datetime . now ( ) <EOL> alert . expirator = reactor . callLater ( <EOL> self . config . ttl , <EOL> self . _deregister_alert , <EOL> tag <EOL> ) <EOL> return alert <EOL> def _deregister_alert ( self , tag ) : <EOL> alert = self . alerts [ tag ] <EOL> if alert . muted : <EOL> alert . mute_expirator . cancel ( ) <EOL> del self . alerts [ tag ] <EOL> def _register_mute ( self , tag , sender ) : <EOL> alert = self . alerts [ tag ] <EOL> alert . muted = make_short_name ( sender ) <EOL> alert . mute_expirator = reactor . callLater ( <EOL> self . config . max_mute_duration , <EOL> self . _deregister_mute , <EOL> tag <EOL> ) <EOL> def _deregister_mute ( self , tag ) : <EOL> alert = self . alerts [ tag ] <EOL> alert . muted = False <EOL> def broadcast_from ( self , sender , message ) : <EOL> short_name = make_short_name ( sender ) <EOL> self . broadcast ( "<STR_LIT>" % ( short_name , message ) ) <EOL> def wall ( self , bot , sender , * message ) : <EOL> "<STR_LIT>" <EOL> self . broadcast_from ( sender , '<STR_LIT:U+0020>' . join ( message ) ) <EOL> def ack ( self , bot , sender , tag ) : <EOL> """<STR_LIT>""" <EOL> alert = self . alerts . get ( tag ) <EOL> if tag == '<STR_LIT>' : <EOL> self . broadcast_from ( sender , "<STR_LIT>" ) <EOL> for alert_tag in self . alerts . iterkeys ( ) : <EOL> self . _register_mute ( alert_tag , sender ) <EOL> return <EOL> if not alert : <EOL> matching_tags = [ alert_tag <EOL> for alert_tag in self . alerts . iterkeys ( ) <EOL> if alert_tag . startswith ( tag ) ] <EOL> if len ( matching_tags ) == <NUM_LIT:1> : <EOL> tag = matching_tags [ <NUM_LIT:0> ] <EOL> alert = self . alerts . get ( tag ) <EOL> elif not matching_tags : <EOL> bot . sendMessage ( sender , <EOL> "<STR_LIT>" % tag ) <EOL> return <EOL> else : <EOL> bot . sendMessage ( sender , <EOL> "<STR_LIT>" + <EOL> "<STR_LIT:U+002CU+0020>" . join ( '<STR_LIT>' % s for s in matching_tags ) + <EOL> "<STR_LIT>" ) <EOL> return <EOL> if not alert . muted : <EOL> self . broadcast_from ( sender , "<STR_LIT>" % tag ) <EOL> self . _register_mute ( tag , sender ) <EOL> else : <EOL> bot . sendMessage ( sender , "<STR_LIT>" <EOL> % tag ) <EOL> def status ( self , bot , sender ) : <EOL> "<STR_LIT>" <EOL> if not self . alerts : <EOL> with bot . message ( sender ) as m : <EOL> if self . maintenance : <EOL> print >> m , "<STR_LIT>" <EOL> print >> m , "<STR_LIT>" <EOL> return <EOL> now = datetime . datetime . now ( ) <EOL> with bot . message ( sender ) as m : <EOL> if self . maintenance : <EOL> print >> m , "<STR_LIT>" <EOL> print >> m , "<STR_LIT>" <EOL> for tag , alert in self . alerts . iteritems ( ) : <EOL> print >> m , ( "<STR_LIT>" <EOL> "<STR_LIT>" ) % ( <EOL> tag , <EOL> "<STR_LIT>" % alert . muted if alert . muted else "<STR_LIT>" , <EOL> alert . count , <EOL> pretty_time_span ( now - alert . first_seen ) , <EOL> pretty_time_span ( now - alert . last_seen ) , <EOL> ) <EOL> def _register_quiet ( self , sender , duration ) : <EOL> quiet = Quiet ( ) <EOL> quiet . user = make_short_name ( sender ) <EOL> quiet . expirator = reactor . callLater ( <EOL> duration , <EOL> self . _deregister_quiet , <EOL> sender <EOL> ) <EOL> quiet . expiration = ( datetime . datetime . now ( ) + <EOL> datetime . timedelta ( seconds = duration ) ) <EOL> self . quiets [ sender ] = quiet <EOL> def _deregister_quiet ( self , sender ) : <EOL> if sender in self . quiets : <EOL> del self . quiets [ sender ] <EOL> def stfu ( self , bot , sender , hours ) : <EOL> "<STR_LIT>" <EOL> hours = int ( hours ) <EOL> self . _register_quiet ( strip_resource_id ( sender ) , hours * <NUM_LIT> ) <EOL> bot . sendMessage ( sender , <EOL> "<STR_LIT>" <EOL> '<STR_LIT>' <EOL> "<STR_LIT>" % hours ) <EOL> def back ( self , bot , sender ) : <EOL> "<STR_LIT>" <EOL> sender = strip_resource_id ( sender ) <EOL> if sender in self . quiets : <EOL> self . _deregister_quiet ( sender ) <EOL> bot . sendMessage ( sender , "<STR_LIT>" ) <EOL> else : <EOL> bot . sendMessage ( sender , "<STR_LIT>" ) <EOL> def who ( self , bot , sender ) : <EOL> "<STR_LIT>" <EOL> if not self . quiets : <EOL> bot . sendMessage ( sender , "<STR_LIT>" ) <EOL> else : <EOL> with bot . message ( sender ) as m : <EOL> print >> m , "<STR_LIT>" <EOL> for quiet in self . quiets . itervalues ( ) : <EOL> print >> m , "<STR_LIT>" % ( quiet . user , <EOL> quiet . expiration . strftime ( "<STR_LIT>" ) ) <EOL> def maint ( self , bot , sender , minutes ) : <EOL> "<STR_LIT>" <EOL> if not self . maintenance : <EOL> minutes = int ( minutes ) <EOL> self . maintenance = reactor . callLater ( <EOL> minutes * <NUM_LIT> , <EOL> self . _end_maintenance , <EOL> ) <EOL> bot . sendMessage ( <EOL> sender , <EOL> "<STR_LIT>" <EOL> '<STR_LIT>' % minutes , <EOL> ) <EOL> else : <EOL> bot . sendMessage ( sender , "<STR_LIT>" ) <EOL> def _end_maintenance ( self ) : <EOL> if self . maintenance and self . maintenance . active ( ) : <EOL> self . maintenance . cancel ( ) <EOL> self . maintenance = None <EOL> def endmaint ( self , bot , sender ) : <EOL> "<STR_LIT>" <EOL> if self . maintenance : <EOL> self . _end_maintenance ( ) <EOL> bot . sendMessage ( sender , "<STR_LIT>" ) <EOL> else : <EOL> bot . sendMessage ( sender , "<STR_LIT>" ) <EOL> def make_plugin ( config , http , jabber = None , smtp = None ) : <EOL> alerts_config = AlertsConfig ( config ) <EOL> alerter = Alerter ( alerts_config , jabber , smtp ) <EOL> http . root . putChild ( "<STR_LIT>" , BroadcastAlertListener ( http , alerter ) ) <EOL> if jabber : <EOL> jabber . register_command ( alerter . wall ) <EOL> jabber . register_command ( alerter . ack ) <EOL> jabber . register_command ( alerter . status ) <EOL> jabber . register_command ( alerter . stfu ) <EOL> jabber . register_command ( alerter . back ) <EOL> jabber . register_command ( alerter . who ) <EOL> jabber . register_command ( alerter . maint ) <EOL> jabber . register_command ( alerter . endmaint ) <EOL> watchdog . initialize ( http , jabber , alerter ) </s>
