summaryrefslogtreecommitdiffstats
path: root/scripts/lastspoke.pl
blob: 32c55f369b9dedf0869cbe2ee39f0bb7e78b357b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!/usr/bin/perl -w
#
# LastSpoke.pl
#
# irssi script
# 
# This script, when loaded into irssi, will monitor and remember everyones
# last action on one or more channels specified in the lastspoke_channels
# setting
#
# [settings]
# lastspoke_channels
#     - Should contain a list of channels that lastspoke should monitor
#       this list can be in any format as long as theres full channelnames
#       in it. For example:
#          "#foo,#bar,#baz" is correct
#          "#foo#bar#baz" is correct
#          "#foo #bar #baz" is correct
#
# Triggers on !lastspoke <nick>, !seen <nick> and !lastseen <nick>
# 
use strict;
use utf8;
use Encode qw/decode encode/;
use Irssi;
use Irssi::Irc;
use CPAN::Meta::YAML;
use vars qw($VERSION %IRSSI);

$VERSION = "0.4";
%IRSSI = (
    authors     => 'Sander Smeenk',
    contact     => 'irssi@freshdot.net',
    name        => 'lastspoke',
	description => 'Remembers what people said last on what channels',
    license     => 'GNU GPLv2 or later',
    url         => 'http://irssi.freshdot.net/',
	modules		=> 'CPAN::Meta::YAML',
);

# Storage for the data.
my %lasthash;

my $filename=Irssi::get_irssi_dir().'/lastspoke.yaml';

# Calculates the difference between two unix times and returns
# a string like '15d 23h 42m 15s ago.'
sub calcDiff {
	my ($when) = @_;

	my $diff = (time() - $when);
	my $day = int($diff / 86400); $diff -= ($day * 86400);
	my $hrs = int($diff / 3600); $diff -= ($hrs * 3600);
	my $min = int($diff / 60); $diff -= ($min * 60);
	my $sec = $diff;

	return "${day}d ${hrs}h ${min}m ${sec}s ago.";
}

# Hook for nick changes
sub on_nick {
	my ($server, $new, $old, $address) = @_;

	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
	my @cl=split(/,/,$server->get_channels());
	my $ok=0;
	foreach (@cl) {
		$ok += index($allowedChans, $_) >= 0;
	}
	if ( $ok >= 0) {
	    $lasthash{lc($old)}{'last'} = time();
	    $lasthash{lc($old)}{'words'} = "$old changed nick to $new";
	    $lasthash{lc($new)}{'last'} = time();
	    $lasthash{lc($new)}{'words'} = "$new changed nick from $old";
	}
}

# Hook for people quitting
sub on_quit {
	my ($server, $nick, $address, $reason) = @_;

	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
	my @cl=split(/,/,$server->get_channels());
	my $ok=0;
	foreach (@cl) {
		$ok += index($allowedChans, $_) >= 0;
	}
	if ( $ok >= 0) {
		$lasthash{lc($nick)}{'last'} = time();
		if (! $reason) {
			$lasthash{lc($nick)}{'words'} = "$nick quit IRC with no reason";
		} else {
			$lasthash{lc($nick)}{'words'} = "$nick quit IRC stating '$reason'";
		}
	}
}

# Hook for people joining
sub on_join {
	my ($server, $channel, $nick, $address) = @_;
	
	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
	if (index($allowedChans, $channel) >= 0) {
    	$lasthash{lc($nick)}{'last'} = time();
		$lasthash{lc($nick)}{'words'} = "$nick joined $channel";	
	}
}

# Hook for people parting
sub on_part {
	my ($server, $channel, $nick, $address, $reason) = @_;

	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";
	if (index($allowedChans, $channel) >= 0) {
		$lasthash{lc($nick)}{'last'} = time();
		if (! $reason) {
			$lasthash{lc($nick)}{'words'} = "$nick left from $channel with no reason";
		} else {
			$lasthash{lc($nick)}{'words'} = "$nick left from $channel stating '$reason'";
		}
	}
}

# Hook for public messages.
# Only act on channels we are supposed to act on (settings_get_str)
sub on_public {
	my ($server, $msg, $nick, $addr, $target) = @_;
	utf8::decode($msg);

	$target = $nick if ( ! $target );
	$nick = $server->{'nick'} if ($nick =~ /^#/);
	$target = lc($target);

	my $allowedChans = lc(Irssi::settings_get_str("lastspoke_channels")) || "(null)";

	# Debug
	# Irssi::active_win()->print("Server: $server");
	# Irssi::active_win()->print("Msg   : $msg");
	# Irssi::active_win()->print("Nick  : $nick");
	# Irssi::active_win()->print("Addr  : $addr");
	# Irssi::active_win()->print("Target: $target");
	# /Debug

	if (index($allowedChans, $target) >= 0) {
		if ( ($msg =~ /^!lastspoke /) || ($msg =~ /^!seen /) || ($msg =~ /^!lastseen /)) {
			my @parts = split(/ /,$msg);

			$lasthash{lc($nick)}{'last'} = time();
			$lasthash{lc($nick)}{'words'} = "$nick last queried information about " . $parts[1] . " on $target";
	
			if (exists $lasthash{lc($parts[1])}) {
				$server->command("MSG $target " . 
					to_term_enc($lasthash{lc($parts[1])}{'words'}) . 
						" " . calcDiff($lasthash{lc($parts[1])}{'last'}));
			} else {
				$server->command("MSG $target I don't know anything about " . $parts[1]);
			}
		} else {
			$lasthash{lc($nick)}{'last'} = time();
			$lasthash{lc($nick)}{'words'} = "$nick last said '$msg' on $target";
		}
	}
}

# encode the words to term_charset
sub to_term_enc {
	my ($words)= @_;
	my $charset= Irssi::settings_get_str('term_charset');
	return encode($charset, $words);
}

# write the memory to disk
sub save {
	my $fa;
	open($fa, '>:utf8', $filename);
	my $yml = CPAN::Meta::YAML->new( \%lasthash );
	print $fa $yml->write_string();
	close($fa);
}

# read form the disk to memory
sub load {
	my $fi;
	if (-e $filename) {
		local $/;
		open($fi, '<:utf8', $filename);
		my $s= <$fi>;
		my $yml= CPAN::Meta::YAML->read_string($s);
		%lasthash = %{ $yml->[0] };
		close($fi);
	}
}

# hook for unload, /quit
sub UNLOAD {
	save();
}

# Put hooks on events
Irssi::signal_add_last("message public", "on_public");
Irssi::signal_add_last("message own_public", "on_public");
Irssi::signal_add_last("message part", "on_part");
Irssi::signal_add_last("message join", "on_join");
Irssi::signal_add_last("message quit", "on_quit");
Irssi::signal_add_last("message nick", "on_nick");

# Add setting
Irssi::settings_add_str("lastspoke", "lastspoke_channels", '%s');

load();