#!/usr/bin/perl ## ## Pidgin "Office Hours" plugin by Kev 'Kyrian' Green. ## $Id: pidgin-office-hours.pl,v 1.1 2009-10-03 15:23:12 kyrian Exp $ use Getopt::Long; use Purple; # Script barfs if this is not installed, and I can't see how to allow 'help' to work even if it is not installed??? use POSIX; # Needed for mktime() else nothing works. my $help = undef; my $rv = GetOptions( 'help|h' => \$help ); # To show status info, because it seemed like a good idea. my $tt = 1; my %tick_tock = ( 0 => 'tick', 1 => 'tock' ); ## First add a help option to find out what the file does if it's called ## directly. It shouldn't be, but it'd be helpful to have such a thing. if ($help) { print qq| This is a plugin for Pidgin. Install it in your ~/.pidgin/plugins/ directory and restart Pidgin. Don't run this directly, there is no point ;-) |; exit; } ## Our information structure. %PLUGIN_INFO = ( perl_api_version => 2, name => 'Office Hours', ## Plugin version => '$Revision: 1.1 $', summary => 'Perl plugin to make you logout when you\'re not there', description => 'It makes you log out when you are not there, hopefully.', author => 'Kev \'Kyrian\' Green ', url => 'http://www.orenet.co.uk/', load => 'plugin_load', unload => 'plugin_unload', prefs_info => 'plugin_prefs_cb' ); ## How often we 'tick' into active state, not too often, but not too seldom, ## I hope. #$tick_int_secs = 900; # 15 minutes. #my $tick_int_secs = 60; # 1 minute, while testing. my $tick_int_secs = 300; # 5 minutes, while testing. #$tick_int = $tick_int_secs * 1000; # wtf. is it seconds, miliseconds or what, I can't Google a straight answer! my $tick_int = $tick_int_secs; # It *is* in seconds. ## Start callback. sub plugin_init { return %PLUGIN_INFO; } ## Close callback. ## Timed/idle callback. It seems this may need to be defined before "plugin_load" (?) sub plugin_periodic { my $plugin = shift; #Purple::Debug::info("officehours", "plugin_periodic() called.\n"); ## Did we get woken up when we should not be in the office? my ($sec, $min, $h, $d, $m, $y, $wday, $yday, $isdist) = localtime(); #Purple::Debug::info("officehours", "plugin_periodic() has fetched time ".$h.":".$min.":".$sec." and weekday ".$wday.".\n"); ## We should do type casting here, but I'll rely on perl's internals ## for now. if (plugin_prefs_vrfy()) { #Purple::Debug::info("officehours", "plugin_periodic() has verified prefs.\n"); my $str_min_end = Purple::Prefs::get_string("/plugins/core/perl_office_hours/string_min_end"); my $str_hr_end = Purple::Prefs::get_string("/plugins/core/perl_office_hours/string_hr_end"); my $str_min_start = Purple::Prefs::get_string("/plugins/core/perl_office_hours/string_min_start"); my $str_hr_start = Purple::Prefs::get_string("/plugins/core/perl_office_hours/string_hr_start"); #Purple::Debug::info("officehours", "plugin_periodic() has fetched prefs for comparison.\n"); ## Create utility reference times. my $end_ux = mktime(0, $str_min_end, $str_hr_end, $d, $m, $y, $wday, $yday); #Purple::Debug::info("officehours", "plugin_periodic() has created utility end time for comparison.\n"); my $start_ux = mktime(0, $str_min_start, $str_hr_start, $d, $m, $y, $wday, $yday); #Purple::Debug::info("officehours", "plugin_periodic() has created utility start time for comparison.\n"); ## Perhaps we should check that $end_ux, and $start_ux came out ## valid here? ## Only on weekdays?? if ($wday > 0 && $wday < 6) { ## Erm.. Is sunday 0, or 7, etc?? ## Then check the time. if (($h > $str_hr_end && $min > $str_min_end) || ($h < $str_hr_start && $min < $str_min_start)) { Purple::Debug::info("officehours","Running disconnect_all() due to current time ".$h.":".$min.":".$sec." and office hours being ".$str_hr_start.":".$str_min_start.":00 to ".$str_hr_end.":".$str_min_end.":00\n"); ## If so, log out any logged-in accounts... disconnect_all(); } } ## Do our stuff here to calculate the next 'wake up' time #my $next_secs = 10 * $to_secs_multi; ## We need to calculate this from the timestamp etc. my $next_tick = $tick_int; do_tick_tock(); ## Wake ourselves up then (timeout/$next_secs is measured in seconds) #Purple::Debug::info("officehours","Scheduled next tick with interval ".$tick_int.".\n"); Purple::timeout_add($plugin, $next_tick, \&plugin_periodic, $plugin); } else { Purple::Debug::info("officehours","Deactivated Office Hours Plugin due to invalid configuration.\n"); } } ## "Load me" callback. We check config and set up the initial callback here. sub plugin_load { my $plugin = shift; # It doesn't work without a root node for your plugin prefs?? Purple::Prefs::add_none("/plugins/core/perl_office_hours"); # Start and end hour/min of your office hours. Purple::Prefs::add_string("/plugins/core/perl_office_hours/string_hr_start","9"); Purple::Prefs::add_string("/plugins/core/perl_office_hours/string_min_start", "00"); Purple::Prefs::add_string("/plugins/core/perl_office_hours/string_hr_end","17"); Purple::Prefs::add_string("/plugins/core/perl_office_hours/string_min_end", "00"); if (plugin_prefs_vrfy()) { ## We must set our initial tick call, or we will never actually do anything ;-) ## (timeout/$next_secs is measured in seconds from the current time) do_tick_tock(); Purple::timeout_add($plugin, $tick_int, \&plugin_periodic, $plugin); Purple::Debug::info("officehours","Loaded and Activated Office Hours Plugin with interval ".$tick_int.".\n"); } else { Purple::Debug::info("officehours","Did not activate Office Hours Plugin due to invalid configuration"); } } # Function to generate the Pidgin preferences screen/tab. # # Note: If you save a preference as eg. a boolean, the pref will remain a # boolean every time it's reloaded even if the type has changed here, and # you have to edit .purple/prefs.xml or similar to change the type manually. sub plugin_prefs_cb { #Purple::Debug::info("officehours","Office Hours Plugin: Prefs Start\n"); $frame = Purple::PluginPref::Frame->new(); # @todo verify that re-use of $ppref is OK and doesn't screw things up. # @todo a dropdown for the hour is probably better, not sure about minute? $ppref = Purple::PluginPref->new_with_name_and_label( "/plugins/core/perl_office_hours/string_hr_start", "Office Start Hour (0-23)"); $ppref->set_type(2); $ppref->set_max_length(2); $frame->add($ppref); $ppref = Purple::PluginPref->new_with_name_and_label( "/plugins/core/perl_office_hours/string_min_start", "Office Start Minute (0-59)"); $ppref->set_type(2); $ppref->set_max_length(2); $frame->add($ppref); $ppref = Purple::PluginPref->new_with_name_and_label( "/plugins/core/perl_office_hours/string_hr_end", "Office End Hour (0-23)"); $ppref->set_type(2); $ppref->set_max_length(2); $frame->add($ppref); $ppref = Purple::PluginPref->new_with_name_and_label( "/plugins/core/perl_office_hours/string_min_end", "Office End Minute (0-59)"); $ppref->set_type(2); $ppref->set_max_length(2); $frame->add($ppref); #Purple::Debug::info("officehours","Office Hours Plugin: Prefs End\n"); return $frame; } ## Validate the times input, and check that the start hour/min are earlier in ## the day than end hour/min by at least twice our tick interval, otherwise ## strange things might start to happen. sub plugin_prefs_vrfy { my $plugin = shift; ## First check validity. my $str_min_end = Purple::Prefs::get_string("/plugins/core/perl_office_hours/string_min_end"); my $str_hr_end = Purple::Prefs::get_string("/plugins/core/perl_office_hours/string_hr_end"); my $str_min_start = Purple::Prefs::get_string("/plugins/core/perl_office_hours/string_min_start"); my $str_hr_start = Purple::Prefs::get_string("/plugins/core/perl_office_hours/string_hr_start"); if ($str_min_start < 0 || $str_min_start > 59) { Purple::Debug::info("officehours","Office Hours Plugin - Invalid minute-start value in config.\n"); return; } if ($str_min_end < 0 || $str_min_end > 59) { Purple::Debug::info("officehours","Office Hours Plugin - Invalid minute-end value in config.\n"); return; } if ($str_hr_start < 0 || $str_hr_start > 23) { Purple::Debug::info("officehours","Office Hours Plugin - Invalid hour-start value in config.\n"); return; } if ($str_hr_end < 0 || $str_hr_end > 23) { Purple::Debug::info("officehours","Office Hours Plugin - Invalid hour-end value in config.\n"); return; } ## Then check end is after start. return true; } ## "Unload me" callback. Shouldn't we do more here to prevent memory leaks etc? sub plugin_unload { my $plugin = shift; Purple::Debug::info("officehours","Removed Office Hours Plugin.\n"); } ## The actual function to perform disconnection of all live accounts, if the callback ## thinks we should. sub disconnect_all { #@accounts = Purple::accounts() # Returns a list of all accounts, online or offline. my @accounts = Purple::Accounts::get_all(); # Or this? # Verify if the user is connected (assumption here that disabled accounts # cannot be connected??) foreach $account (@accounts) { #Purple::Debug::info("officehours", "Testing: Purple::Account::is_connected() for ".$account->get_username()); if ($account->is_connected()) { my $status = $account->get_active_status(); my $statusName = $status->get_name(); if ($statusName eq "Away") { Purple::Debug::info("officehours", $account->get_username()."... Connected + Away. Disconnecting...\n"); $account->set_status("offline", TRUE); } else { Purple::Debug::info("officehours", $account->get_username()."... Connected + " . $statusName. ". NOT Disconnecting...\n"); } } else { Purple::Debug::info("officehours", $account->get_username()."... Disconnected. Doing nothing.\n"); } } } # Debugging function mainly, hence it does nothing right at the moment. sub do_tick_tock { $tt = 1 - $tt; #Purple::Debug::info("officehours",$tick_tock{$tt}."\n"); }