1#!/usr/local/bin/perl -w
2#
3# LastSpoke.pl
4#
5# irssi script
6#
7# This script, when loaded into irssi, will monitor and remember everyones
8# last action on one or more channels specified in the lastspoke_channels
9# setting
10#
11# [settings]
12# lastspoke_channels
13#     - Should contain a list of channels that lastspoke should monitor
14#       this list can be in any format as long as theres full channelnames
15#       in it. For example:
16#          "#foo,#bar,#baz" is correct
17#          "#foo#bar#baz" is correct
18#          "#foo #bar #baz" is correct
19#          "foo bar baz" is incorrect
20#
21# Triggers on !lastspoke <nick>, !seen <nick> and !lastseen <nick>
22#
23use strict;
24use Irssi;
25use Irssi::Irc;
26use vars qw($VERSION %IRSSI);
27
28$VERSION = "0.2";
29%IRSSI = (
30    authors     => 'Sander Smeenk',
31    contact     => 'irssi@freshdot.net',
32    name        => 'lastspoke',
33	description => 'Remembers what people said last on what channels',
34    license     => 'GNU GPLv2 or later',
35    url         => 'http://irssi.freshdot.net/',
36);
37
38my $target;
39
40# Storage for the data.
41my %lasthash;
42
43# Calculates the difference between two unix times and returns
44# a string like '15d 23h 42m 15s ago.'
45sub calcDiff {
46	my ($when) = @_;
47
48	my $diff = (time() - $when);
49	my $day = int($diff / 86400); $diff -= ($day * 86400);
50	my $hrs = int($diff / 3600); $diff -= ($hrs * 3600);
51	my $min = int($diff / 60); $diff -= ($min * 60);
52	my $sec = $diff;
53
54	return "${day}d ${hrs}h ${min}m ${sec}s ago.";
55}
56
57# Hook for nick changes
58sub on_nick {
59	my ($server, $new, $old, $address) = @_;
60
61	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
62	if (index($allowedChans, $target) >= 0) {
63	    $lasthash{lc($old)}{'last'} = time();
64	    $lasthash{lc($old)}{'words'} = "$old changed nick to $new";
65	    $lasthash{lc($new)}{'last'} = time();
66	    $lasthash{lc($new)}{'words'} = "$new changed nick from $old";
67	}
68}
69
70# Hook for people quitting
71sub on_quit {
72	my ($server, $nick, $address, $reason) = @_;
73
74	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
75	if (index($allowedChans, $target) >= 0) {
76		$lasthash{lc($nick)}{'last'} = time();
77		if (! $reason) {
78			$lasthash{lc($nick)}{'words'} = "$nick quit IRC with no reason";
79		} else {
80			$lasthash{lc($nick)}{'words'} = "$nick quit IRC stating '$reason'";
81		}
82	}
83}
84
85# Hook for people joining
86sub on_join {
87	my ($server, $channel, $nick, $address) = @_;
88
89	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
90	if (index($allowedChans, $channel) >= 0) {
91    	$lasthash{lc($nick)}{'last'} = time();
92		$lasthash{lc($nick)}{'words'} = "$nick joined $channel";
93	}
94}
95
96# Hook for people parting
97sub on_part {
98	my ($server, $channel, $nick, $address, $reason) = @_;
99
100	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
101	if (index($allowedChans, $channel) >= 0) {
102		$lasthash{lc($nick)}{'last'} = time();
103		if (! $reason) {
104			$lasthash{lc($nick)}{'words'} = "$nick left from $channel with no reason";
105		} else {
106			$lasthash{lc($nick)}{'words'} = "$nick left from $channel stating '$reason'";
107		}
108	}
109}
110
111# Hook for public messages.
112# Only act on channels we are supposed to act on (settings_get_str)
113sub on_public {
114	my ($server, $msg, $nick, $addr, $_target) = @_;
115
116	$_target = $nick if ( ! $_target );
117	$nick = $server->{'nick'} if ($nick =~ /^#/);
118	$target = lc($target);
119
120	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
121
122	# Debug
123	# Irssi::active_win()->print("Server: $server");
124	# Irssi::active_win()->print("Msg   : $msg");
125	# Irssi::active_win()->print("Nick  : $nick");
126	# Irssi::active_win()->print("Addr  : $addr");
127	# Irssi::active_win()->print("Target: $target");
128	# /Debug
129
130	if (index($allowedChans, $target) >= 0) {
131		if ( ($msg =~ /^!lastspoke /) || ($msg =~ /^!seen /) || ($msg =~ /^!lastseen /)) {
132			my @parts = split(/ /,$msg);
133
134			$lasthash{lc($nick)}{'last'} = time();
135			$lasthash{lc($nick)}{'words'} = "$nick last queried information about " . $parts[1] . " on $target";
136
137			if (exists $lasthash{lc($parts[1])}) {
138				$server->command("MSG $target " . $lasthash{lc($parts[1])}{'words'} . " " . calcDiff($lasthash{lc($parts[1])}{'last'}));
139			} else {
140				$server->command("MSG $target I don't know anything about " . $parts[1]);
141			}
142		} else {
143			$lasthash{lc($nick)}{'last'} = time();
144			$lasthash{lc($nick)}{'words'} = "$nick last said '$msg' on $target";
145		}
146	}
147}
148
149# Put hooks on events
150Irssi::signal_add_last("message public", "on_public");
151Irssi::signal_add_last("message own_public", "on_public");
152Irssi::signal_add_last("message part", "on_part");
153Irssi::signal_add_last("message join", "on_join");
154Irssi::signal_add_last("message quit", "on_quit");
155Irssi::signal_add_last("message nick", "on_nick");
156
157# Add setting
158Irssi::settings_add_str("lastspoke", "lastspoke_channels", '%s');
159