#!/usr/bin/perl # # Simple event change notification plugin. # # Hacked by Silver. # Ported to PogoBOT by Tim Retout. use strict; use warnings; use POSIX qw/floor strftime/; use IO::Socket::INET; my $dataFile = '/home/webmaster/var/events.data'; my $dataFileStat = 0; my $maxLength = 400; # Data file format: # "" "" "|" "" # Event states: # - Doesn't need signups. # S Needs signups, not open. # SN Open for non-guest signups. # SO Open for all signups. # R Currnetly runnings. # X Finished. # C Cancelled. my @message = ( qq(To get help on this command, please use \x02HELP EVENT\x02.), qq(Unknown command; please use the command \x02EVENT HELP\x02 to find out more.), qq(Unknown event ID; please use the command \x02EVENT LIST\x02 to find the right event ID.), qq(No commands or events matched; please use the commands \x02EVENT HELP\x02 and \x02EVENT LIST\x02 to get more information or to find the right event ID.) ); my $STATE_NOSIGNUP = '-'; my $STATE_SIGNUPSCLOSED = 'S'; my $STATE_SIGNUPSMEMBERS = 'SN'; my $STATE_SIGNUPSALL = 'SO'; my $STATE_ONNOW = 'R'; my $STATE_FINISHED = 'X'; my $STATE_CANCELLED = 'C'; # Just tell Perl we meant to not use lexical scoping on these. my ($JBconn, $JBevent, $message); # URL links to events' details and signups. #my $eventChan = '#lug'; my $eventURLbase = 'http://www.warwickcompsoc.co.uk/events/'; my $eventURLdetails = 'http://www.warwickcompsoc.co.uk/events/details/?id=%'; my $eventURLoptions = 'http://www.warwickcompsoc.co.uk/events/details/options?id=%'; my $eventURLsignup = 'http://www.warwickcompsoc.co.uk/events/details/options?id=%&action=signup'; # An ordered list of event IDs. Ordered by event start date/time. my @events; # A hash of event data, jey is the event ID. my %events; # How many times we've checked and not found any updates. my $idle = 0; my $socket = IO::Socket::INET->new( PeerAddr => 'localhost', PeerPort => 3009, Proto => 'tcp', ) or die "Couldn't open socket: $!"; my %handler; # Register a command handler. sub registerHandler { my ($cmd, $coderef) = @_; $handler{$cmd} = $coderef; print $socket "REG $cmd\r\n"; print "Registering $cmd.\n"; } #registerHandler("even", \&on_event); registerHandler("event", \&on_event); registerHandler("events", \&on_event_events); registerHandler("signup", \&on_event_signup); registerHandler("signups", \&on_event_signups); registerHandler("timeleft", \&on_timeleft); #registerTimer(10, \&on_checkEvents); &updateEventData(); # Now load the initial event list... while (<$socket>) { s/\r\n$// || s/\n$//; print "Received: $_\n"; # Check that the line specifies a known command. next unless ( (my $cmd) = /^([^ \t]*)/gc ); next unless ($handler{$cmd}); (my $args) = /\G ([^\t]*)/g; my $reply = &{$handler{$cmd}}($args); # Put the reply after the second field, removing the first field. s/^([^\t]*\t)([^\t]*)/$2 $reply/ || next; print "Replying:", $_, "\n"; print $socket $_, "\n"; } ################### # updateEventDate # ################### sub updateEventData() { my @sInfo = stat($dataFile); if (@sInfo && ($sInfo[9] == $dataFileStat)) { # File hasn't changed, so just return existing data. $idle++; return 0; } $idle = 0; if (@sInfo) { $dataFileStat = $sInfo[9]; } unless (open(EVENTFILE, $dataFile)) { @events = (); %events = (); return "0E0"; } my $IDs = ; my @newEventData = ; close(EVENTFILE); my %newEvents; foreach my $line (@newEventData) { # Format: # "" "" "" if ($line =~ /^(\d+) "([^"]*)" ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) "([^"]*)" "((?:\\"|\\\\|[^"])*)" "((?:\\"|\\\\|[^"])*)"/) { my %eventData = ( id => $1, name => $2, start => $3, end => ($4 eq '-' ? 0 : $4), state => $5, signupLimit => $6, signupCurrent => $7, signupList => [split(/\s*,\s*/, $8)], commentShort => $9, commentLong => '', location => $10 ); $eventData{commentShort} =~ s/\\"/"/gi; $eventData{commentShort} =~ s/<\/?b>/\x02/gi; $eventData{commentShort} =~ s/<\/?u>/\x1f/gi; if ($eventData{commentShort} =~ /^(.*?)\|(.*)$/) { $eventData{commentShort} = $1; $eventData{commentLong} = $2; } else { $eventData{commentLong} = $eventData{commentShort}; } if ($eventData{state} eq $STATE_NOSIGNUP) { $eventData{signupLimit} = 0; $eventData{signupCurrent} = 0; $eventData{signupList} = []; } $newEvents{$eventData{id}} = \%eventData; } } @events = split(/\s+/, $IDs); print join(' ', sort @events), "\n"; %events = %newEvents; print join(' ', sort keys %events), "\n"; return 1; } ################ # splitMessage # ################ sub splitMessage() { my ($message) = @_; my @list = ($message); my $maxLine = $maxLength - 20; while (length($list[$#list]) > $maxLength) { if ($list[$#list] =~ /^(.{$maxLine,$maxLength}) (.*)$/) { $list[$#list] = $1; push @list, "(cont.) " . $2; } else { $list[$#list] =~ /^(.{$maxLength})(.*)$/; $list[$#list] = $1 . "..."; push @list, "..." . $2; } } return @list; } ############################ # getNiceDateString($date) # ############################ # Accepts an epoch-style date as argument, and # returns a fuzzy date string. sub getNiceDateString() { my $date = shift; my @eventdate = localtime($date); my @nowdate = localtime(); if ($nowdate[]) { ## Today ## # 12am <- morning -> 12pm <- day -> 7pm <- tonight -> 12am if ( $eventdate[2] < 12) { return "this morning"; } elsif ( $eventdate[2] < 19 ) { return "today"; } else { return "tonight"; } } elsif ($dNow+1 == $dEvent) { ## Tomorrow ## # 12am <- morning -> 12pm <- day -> 7pm <- tonight -> 12am if ( $eventdate[2] < 12 ) { return "tomorrow morning"; } elsif ( $eventdate[2] < 19 )) { return "tomorrow"; } else { return "tomorrow night"; } } elsif (($dNow <= $dEvent) && ($dNow+7 > $dEvent)) { ## This week ## return strftime('this %A', @eventdate); # If the year of 'now' and the event time are equal, don't include it. } elsif (strftime('%Y', @eventdate) eq strftime('%Y', localtime())) { my $str = strftime('%A %e %B', @eventdate); $str =~ s/ / /g; return $str; } else { # Otherwise, just format a nice DDD D MMM YYYY string. my $str = strftime('%A %e %B %Y', @eventdate); $str =~ s/ / /g; return $str; } } ##################### # getNiceTimeString # ##################### sub getNiceTimeString() { my $str = ''; if (($_[0] % 3600) == 0) { # If it's an o-clock time, just do number followed by am/pm. $str = strftime('%l%P', localtime($_[0])); } elsif (($_[0] % 60) == 0) { # If it's an exact minute time, do HH:MMam/pm. $str = strftime('%l:%M%P', localtime($_[0])); } else { # Otherwise do HH:MM:SSam/pm. $str = strftime('%l:%M:%S%P', localtime($_[0])); } $str =~ s/^ //g; return $str; } ################### # getEventDetails # ################### sub getEventDetails() { my ($id) = @_; print STDERR "Getting details of event id $id.\n"; return (id => -1) unless (defined $events{$id}); return %{$events{$id}}; } # Format event data into a string. # # Signup data: # {S1} [X/Y] # {S2} (Y places) # {S3} Currently X of Y signups (no guests), no limit. # # Short name: # {SN1} Social # # Location: # {L1} at Loc (X) # {L2} at Loc (X) at Y on Y # # Name of event: # {N1} Social at Loc (X) # {N2} Social at Loc (X) at Y on Z # {N3} Event {N2}. # # Name with details: # {FN1} Social at Loc (info) (X) # {FN2} Social at Loc (info) (X) from Y on Z to A on B # {FN3} Event {FN2}. # # Delay to event: # {IN1} [4h23m] # {IN2} in four hours # {IN3} Event {IN2}. # # Event status: # {ES1} (on right now) # {ES2} Event on right now. sub getEventDisplayString() { my %eventInfo = %{$_[0]}; my $format = $_[1]; my %data = (); $data{S1} = ''; $data{S2} = ''; $data{S3} = ''; if ($eventInfo{state} eq $STATE_NOSIGNUP) { $data{S3} = qq(Signups not required.); } elsif ($eventInfo{state} eq $STATE_SIGNUPSCLOSED) { if ($eventInfo{signupLimit} == 0) { $data{S1} = qq([$eventInfo{signupCurrent}]); $data{S2} = qq((unlimited places)); } else { $data{S1} = qq([$eventInfo{signupCurrent}/$eventInfo{signupLimit}]); $data{S2} = qq(($eventInfo{signupLimit} places)); } $data{S3} = qq(Signups not open yet $data{S2}.); } elsif (($eventInfo{state} =~ /^($STATE_SIGNUPSMEMBERS|$STATE_SIGNUPSALL)$/) || (($eventInfo{state} =~ /^($STATE_ONNOW|$STATE_FINISHED)$/) && ($eventInfo{signupCurrent} + $eventInfo{signupLimit} > 0))) { if ($eventInfo{signupLimit} == 0) { $data{S1} = qq([$eventInfo{signupCurrent}]); $data{S2} = qq((unlimited places)); } else { $data{S1} = qq([$eventInfo{signupCurrent}/$eventInfo{signupLimit}]); $data{S2} = qq(($eventInfo{signupLimit} places)); } $data{S3} = 'Currently ' . $eventInfo{signupCurrent}; $data{S3} .= ' signup' . ($eventInfo{signupCurrent}==1 ? '':'s'); if ($eventInfo{state} eq $STATE_SIGNUPSMEMBERS) { $data{S3} .= ' (guests not allowed)'; } if ($eventInfo{signupLimit} == 0) { $data{S3} .= ', no limit.'; } else { $data{S3} .= ' out of ' . $eventInfo{signupLimit} . '.'; } } my $loc = ''; if ($eventInfo{location} =~ /^([A-Z](?:\d|x)\.?(?:\d|x)(?:\d|x)+(?:\W|$)|lib.?(?:\d|x))/i) { $loc = qq( in $eventInfo{location}); } elsif ($eventInfo{location}) { $loc = qq( at $eventInfo{location}); } $data{SN1} = qq(\x02$eventInfo{name}\x02); $data{L1} = qq($loc ($eventInfo{id})); $data{L2} = qq($loc ($eventInfo{id}) at ) . &getNiceTimeString($eventInfo{start}) . q( ) . &getNiceDateString($eventInfo{start}); $data{N1} = qq($data{SN1}$data{L1}); $data{N2} = qq($data{SN1}$data{L2}); $data{N3} = qq(Event $data{N2}.); $data{FN1} = $data{N1}; $data{FN2} = $data{N2}; $data{FN3} = $data{N3}; if ($eventInfo{commentShort}) { $data{FN1} = qq(\x02$eventInfo{name}\x02$loc ($eventInfo{commentShort}) ($eventInfo{id})); } if ($eventInfo{end}) { if (floor($eventInfo{start} / 86400) == floor($eventInfo{end} / 86400)) { $data{FN2} = qq($data{FN1} from ) . &getNiceTimeString($eventInfo{start}) . q( to ) . &getNiceTimeString($eventInfo{end}) . q( ) . &getNiceDateString($eventInfo{end}); } else { $data{FN2} = qq($data{FN1} from ) . &getNiceTimeString($eventInfo{start}) . q( ) . &getNiceDateString($eventInfo{start}) . q( to ) . &getNiceTimeString($eventInfo{end}) . q( ) . &getNiceDateString($eventInfo{end}); } } else { $data{FN2} = qq($data{FN1} at ) . &getNiceTimeString($eventInfo{start}) . q( ) . &getNiceDateString($eventInfo{start}); } $data{FN3} = qq(Event $data{FN2}.); $data{IN1} = ''; $data{IN2} = ''; $data{IN3} = ''; if (($eventInfo{state} =~ /^$STATE_SIGNUPSCLOSED/) || ($eventInfo{state} eq $STATE_NOSIGNUP)) { my $delay = $eventInfo{start} - time(); my @names = ('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', 'twenty one', 'twenty two', 'twenty three'); sub f() { my ($num, $word) = @_; my $ans = ''; if (($num >= 0) && ($num <= $#names)) { $ans .= $names[$num]; } else { $ans .= $num; } if ($num == 1) { $ans .= $word; } else { $ans .= $word . 's'; } return $ans; } my $TIME_MIN = 60; my $TIME_HOUR = 60 * $TIME_MIN; my $TIME_DAY = 24 * $TIME_HOUR; my $TIME_WEEK = 7 * $TIME_DAY; my $TIME_MON = 30.436666 * $TIME_DAY; if ($delay > (10000000)) { } elsif ($delay > $TIME_MON) { # That last number == average days per month. # Months. $delay += 0.25 * $TIME_DAY; my $mon = floor($delay / $TIME_MON); my $day = floor(($delay - $mon * $TIME_MON) / $TIME_DAY); $data{IN1} = q([) . $mon . q[mon] . $day . q(d]); $data{IN2} = qq[ in \x02] . &f($mon, ' month') . q[ and ] . &f($day, ' day') . qq[\x02]; } elsif ($delay > (60 * 60 * 24 * 7)) { # Weeks. $delay += 0.25 * $TIME_DAY; my $week = floor($delay / $TIME_WEEK); my $day = floor(($delay - $week * $TIME_WEEK) / $TIME_DAY); $data{IN1} = q([) . $week . q[w] . $day . q(d]); $data{IN2} = qq[ in \x02] . &f($week, ' week') . q[ and ] . &f($day, ' day') . qq[\x02]; } elsif ($delay > (60 * 60 * 24)) { # Days. $delay += 0.25 * $TIME_HOUR; my $day = floor($delay / $TIME_DAY); my $hr = floor(($delay - $day * $TIME_DAY) / $TIME_HOUR); $data{IN1} = q([) . $day . q[d] . $hr . q(h]); $data{IN2} = qq[ in \x02] . &f($day, ' day') . q[ and ] . &f($hr, ' hour') . qq[\x02]; } elsif ($delay > (60 * 60)) { # Hours. $delay += 0.25 * $TIME_MIN; my $hr = floor($delay / $TIME_HOUR); my $min = floor(($delay - $hr * $TIME_HOUR) / $TIME_MIN); $data{IN1} = q([) . $hr . q[h] . $min . q(m]); $data{IN2} = qq[ in \x02] . &f($hr, ' hour') . q[ and ] . &f($min, ' minute') . qq[\x02]; } elsif ($delay > (60)) { # Minutes. $delay += 0.25 * $TIME_MIN; my $min = floor($delay / $TIME_MIN); $data{IN1} = q([) . $min . q(m]); $data{IN2} = qq[ in \x02] . &f($min, ' minute') . qq[\x02]; } else { } if ($data{IN2}) { $data{IN3} = qq[Event $data{IN2}.]; } } $data{ES1} = ''; $data{ES2} = ''; if ($eventInfo{state} eq $STATE_ONNOW) { $data{ES1} = qq((\x02on right now\x02)); $data{ES2} = qq(\x02Event on right now!\x02); } elsif ($eventInfo{state} eq $STATE_FINISHED) { if ($eventInfo{end}) { $data{ES1} = qq((finished)); $data{ES2} = qq(Event is over.); } else { $data{ES1} = qq((past)); $data{ES2} = qq(Event has passed.); } } elsif ($eventInfo{state} eq $STATE_CANCELLED) { $data{ES1} = qq((\x02cancelled\x02)); $data{ES2} = qq(\x02Event has been cancelled.\x02); } # Actually 'fill in' the placeholders. $format =~ s/\{([A-Z0-9]+)\}/$data{$1}/ige; # Collapse spaces. $format =~ s/ +/ /g; # Remove spaces before punctuation. $format =~ s/ ([.,:;)])/$1/g; # Remove spaces at the start and end. $format =~ s/(^ | $)//g; return $format; } ###################### # getSignupStrings() # ###################### sub getSignupStrings() { my ($count, @signups) = @_; for (@signups) { if (/[a-z] ?[A-Z0-9]/) { s/([a-z]) ?([A-Z0-9])/$1'$2/; } elsif (/\w[^a-zA-Z0-9]\w]/) { s/(\w)([^a-zA-Z0-9]\w)/$1'$2/; } else { s/^(.)(.)/$1'$2/; } } if (($count == 0) || (scalar(@signups) < $count)) { return join(', ', @signups); } return (join(', ', @signups[0..$count-1]), join(', ', @signups[$count..$#signups]) ); } #################### # doEventCommand() # #################### sub doEventCommand() { my ($id, $wordList) = @_; my @word = @{$wordList}; my %eventInfo = &getEventDetails($id); if ($eventInfo{id} == -1) { return($message[2]); } if ($word[0] && ($word[0] =~ /^signups$/)) { if ($eventInfo{state} eq $STATE_NOSIGNUP) { return(qq(Signups not required for ) . &getEventDisplayString(\%eventInfo, '{N1} {IN2} {S2}') . qq(.)); } elsif ($eventInfo{state} =~ /^S/) { if ($eventInfo{signupCurrent} == 0) { return(qq(No signups for ) . &getEventDisplayString(\%eventInfo, '{N1} {IN2} {S2}') . qq(.)); } else { my @signups = &getSignupStrings($eventInfo{signupLimit}, @{$eventInfo{signupList}}); my $msg = qq(Signups for ) . &getEventDisplayString(\%eventInfo, '{N1} {IN1} {S1}') . qq(: $signups[0].); $msg .= qq( \x02Reserves\x02: $signups[1].) if ($signups[1]); return($msg); } } } elsif ($word[0] && ($word[0] =~ /^(link|url)$/)) { my $url = $eventURLdetails; $url =~ s/%/$eventInfo{id}/ge; return(&getEventDisplayString(\%eventInfo, qq(Details for {FN1} at $url.))); } elsif ($word[0] && ($word[0] =~ /^(details)$/)) { my $url = $eventURLdetails; $url =~ s/%/$eventInfo{id}/ge; return(&getEventDisplayString(\%eventInfo, qq(Details for {FN1} at $url. {S3}))); } elsif ($word[0] && ($word[0] =~ /^(in)$/)) { my $url = $eventURLdetails; $url =~ s/%/$eventInfo{id}/ge; return(&getEventDisplayString(\%eventInfo, qq(Event {N1} {IN2}.))); } elsif ($word[0] && ($word[0] =~ /^signup$/)) { my $url = $eventURLsignup; $url =~ s/%/$eventInfo{id}/ge; return(qq(Please use $url.)); } elsif ($word[0]) { return($message[1]); } else { return(&getEventDisplayString(\%eventInfo, '{FN3} {IN3} {S3} {ES2}')); } } #################### # Command Handlers # #################### # Handles `signup' command. sub on_event_signup { my $message = shift; &on_event($message . " signup"); } # Handles `signups' command. sub on_event_signups { my $message = shift; &on_event($message . " signups"); } # Handles `events' command. sub on_event_events { my $message = shift; if ($message) { &on_event($message); } else { &on_event("list"); } } # Handles `timeleft' command. sub on_timeleft { my ($message) = shift; $message =~ /^\s*(.*?)\s*$/; my $text = $1; $text =~ s/[^a-z0-9-_"',.]//gi; for my $id (@events) { my %details = &getEventDetails($id); # Skip finished and cancelled events. next if ($details{state} =~ /^[XC]$/); next unless (($text eq '') || ($details{name} =~ /\b$text\b/i) || ($details{location} =~ /\b$text\b/i) || ($details{commentShort} =~ /\b$text\b/i) || ($details{commentLong} =~ /\b$text\b/i)); my $text = &getEventDisplayString(\%details, "{IN2} it's time for {FN1}. {ES2} {S3}"); $text =~ s/^(.)/uc($1)/e; return($text); return; } if ($text eq '') { return('There are no events. :-('); } else { return(qq(Sorry, no events matched '$text'!)); } } # Handles `event' command. sub on_event { my ($message) = shift; my @word = split(/\s+/, $message); # Help if (!(@word) || ($word[0] =~ /^help$/)) { return($message[0]); # Link } elsif ($word[0] =~ /^link$/i) { return(qq(Details of all events at $eventURLbase.)); # List } elsif ($word[0] =~ /^list$/i) { my @list = (); for my $id (@events) { my %details = &getEventDetails($id); push @list, &getEventDisplayString(\%details, '{SN1} {ES1} {L1} {IN1} {S1}'); } if (@list) { return(q(Events: ) . join(', ', @list) . q(.)); } else { return('There are no events. :-('); } ## Summary #} elsif ($word[0] =~ /^summary$/i) { # unless ($JinglyBOT::Private) { # return(q(Replying via Private Message.)); # } # # # Do summary here. # for my $id (@events) { # my %eI = &getEventDetails($id); # return(&getEventDisplayString(\%eI, '{FN3} {IN3} {S3} {ES2}')); # if ($eI{signupCurrent} != 0) { # my @signups = &getSignupStrings($eI{signupLimit}, @{$eI{signupList}}); # my $msg = qq( \x02- Signups:\x02 $signups[0].); # $msg .= qq( \x02Reserves:\x02 $signups[1].) if ($signups[1]); # return($msg); # } # } # Event number. } elsif ($word[0] =~ /[^\d]/) { my $match = $word[0]; $match =~ s/[^a-z0-9 ]//gi; # Do summary here. my @list = (); my @listLong = (); my $requireSignups = 0; if ($word[1] =~ /^signups?$/i) { $requireSignups = 1; } for my $id (@events) { my %details = &getEventDetails($id); if (($details{name} =~ /\b$match\b/i) || ($details{location} =~ /\b$match\b/i) || ($details{commentShort} =~ /\b$match\b/i) || ($details{commentLong} =~ /\b$match\b/i)) { if ($requireSignups) { if (($details{state} eq $STATE_NOSIGNUP) || ($details{signupLimit} + $details{signupCurrent} == 0)) { next; } } push @list, $id; push @listLong, &getEventDisplayString(\%details, '{N1}'); } } if (scalar(@list) == 0) { return($message[3]); } else { shift @word; for (1..2) { last if (scalar(@list) == 0); &doEventCommand($list[0], \@word); shift @list; shift @listLong; } if (scalar(@list) > 0) { return(q(Other events that matched: ) . join(', ', @listLong) . q(.)); } } # Do event command. } else { my $id = 1 * $word[0]; shift @word; return &doEventCommand($id, \@word); } } ################## # on_checkEvents # ################## #sub on_checkEvents { # my ($JBconn) = @_; # # my %oldEvents = %events; # &updateEventData(); # # sub handleEventNew() { # my ($newEventInfo) = @_; # my %eventInfo = %{$newEventInfo}; # # my $signups = ''; # if ($eventInfo{signupLimit} == 0) { # $signups = 'Unlimited signup places.'; # } elsif ($eventInfo{state} =~ /^S/) { # $signups = $eventInfo{signupLimit} . ' signup places.'; # } # my $url = $eventURLdetails; # $url =~ s/%/$eventInfo{id}/ge; # &mySay($eventChan, &getEventDisplayString(\%eventInfo, "New event! {FN3} {S3} Full details: $url.")); # } # # sub handleEventOld() { # my ($oldEventInfo) = @_; # my %eventInfo = %{$oldEventInfo}; # # # Only bother announcing the loss of the event if it was NOT presiously running or canceled. # # (i.e. it was still in the build-up to a happening event) # unless (($eventInfo{state} eq $STATE_FINISHED) || ($eventInfo{state} eq $STATE_CANCELLED)) { # &mySay($eventChan, qq(Event ) . &getEventDisplayString(\%eventInfo, '{FN2}') . q( now gone.)); # } # } # # sub handleEventChange() { # my ($oldEventInfo, $newEventInfo) = @_; # my %oldEventInfo = %{$oldEventInfo}; # my %newEventInfo = %{$newEventInfo}; # # # Event state has changed. # if ($oldEventInfo{state} ne $newEventInfo{state}) { # if ($newEventInfo{state} eq $STATE_NOSIGNUP) { # &mySay($eventChan, &getEventDisplayString(\%newEventInfo, "Event {N2} now doesn't require signups.")); # # } elsif ($newEventInfo{state} eq $STATE_SIGNUPSCLOSED) { # &mySay($eventChan, &getEventDisplayString(\%newEventInfo, "Event {N2} now requires signups {S2}.")); # # } elsif ($newEventInfo{state} eq $STATE_SIGNUPSMEMBERS) { # my $url = $eventURLoptions; # $url =~ s/%/$newEventInfo{id}/ge; # &mySay($eventChan, &getEventDisplayString(\%newEventInfo, "Event {N2} is now open to non-guest signups {S2}, signup here: $url.")); # # } elsif ($newEventInfo{state} eq $STATE_SIGNUPSALL) { # my $url = $eventURLoptions; # $url =~ s/%/$newEventInfo{id}/ge; # &mySay($eventChan, &getEventDisplayString(\%newEventInfo, "Event {N2} is now open to all signups {S2}, signup here $url.")); # # } elsif ((($oldEventInfo{state} =~ /^($STATE_NOSIGNUP|$STATE_SIGNUPSCLOSED|$STATE_SIGNUPSMEMBERS|$STATE_SIGNUPSALL)$/) && ($newEventInfo{state} eq $STATE_FINISHED)) || ($newEventInfo{state} eq $STATE_ONNOW)) { # &mySay($eventChan, &getEventDisplayString(\%newEventInfo, "Event {N1} now happening!")); # # } elsif ($newEventInfo{state} eq $STATE_FINISHED) { # &mySay($eventChan, &getEventDisplayString(\%newEventInfo, "Event {N2} is now over.")); # # } elsif ($newEventInfo{state} eq $STATE_CANCELLED) { # &mySay($eventChan, &getEventDisplayString(\%newEventInfo, "Event {N2} has been cancelled!")); # } # # } # # Event signup count. # if (($oldEventInfo{signupCurrent} != $newEventInfo{signupCurrent}) || (join(";", @{$oldEventInfo{signupList}}) ne join(";", @{$newEventInfo{signupList}}))) { # my $signups = $newEventInfo{signupCurrent}; # $signups .= ' signup' . ($newEventInfo{signupCurrent}==1 ? '':'s'); # if ($newEventInfo{signupLimit} == 0) { # $signups .= ', no limit'; # } else { # $signups .= ' out of ' . $newEventInfo{signupLimit}; # } # # my @oldSignups = @{$oldEventInfo{signupList}}; # my @newSignups = @{$newEventInfo{signupList}}; # # my @changes; # # foreach my $m (@newSignups) { # push @changes, qq(+$m) unless (grep { $_ eq $m } @oldSignups); # } # foreach my $m (@oldSignups) { # push @changes, qq(-$m) unless (grep { $_ eq $m } @newSignups); # } # # if (@changes) { # my $changes = join(', ', @changes); # &mySay($eventChan, qq(Event ) . &getEventDisplayString(\%newEventInfo, '{N2}') . qq( now has $signups ($changes).)); # } else { # &mySay($eventChan, qq(Event ) . &getEventDisplayString(\%newEventInfo, '{N2}') . qq( has had its signup list re-ordered!)); # } # } # } # # for my $id (sort { $events{$a}->{start} <=> $events{$b}->{end} } keys %events) { # unless (defined $oldEvents{$id}) { # &handleEventNew($events{$id}); # } else { # &handleEventChange($oldEvents{$id}, $events{$id}); # } # } # # for my $id (keys %oldEvents) { # unless (defined $events{$id}) { # &handleEventOld($oldEvents{$id}); # } # } #}