1POE::Component::IRC::CoUoskebrooCko:n:tSreiebnu(t3e)d PePrOlE:D:oCcoummpeonnteantti:o:nIRC::Cookbook::Seen(3)
2
3
4
6 POE::Component::IRC::Cookbook::Seen - Implement the 'seen' command
7
9 This little bot tracks the whereabouts of users and allows you to
10 retrieve that information on command.
11
12 19:59:51 * seen_bot (n=hinrik@pool-71-164-43-32.chrlwv.east.verizon.net) has joined #test_channel1
13 19:59:55 <foo> bar
14 20:00:16 * seen_bot has quit (Remote closed the connection)
15 20:00:27 * seen_bot (n=hinrik@pool-71-164-43-32.chrlwv.east.verizon.net) has joined #test_channel1
16 20:00:29 <literal> seen_bot: seen seen_bot
17 20:00:29 <seen_bot> literal: I last saw seen_bot at Mon Sep 22 20:00:27 2008 joining #test_channel1
18 20:00:34 <literal> seen_bot: seen foo
19 20:00:40 <seen_bot> literal: I last saw foo at Mon Sep 22 19:59:56 2008 on #test_channel1 saying: bar
20 20:00:45 <literal> seen_bot: seen baz
21 20:00:48 <seen_bot> literal: I haven't seen baz
22
24 #!/usr/bin/env perl
25
26 use strict;
27 use warnings;
28 use IRC::Utils qw(parse_user lc_irc);
29 use POE;
30 use POE::Component::IRC::State;
31 use POE::Component::IRC::Plugin::AutoJoin;
32 use POE::Component::IRC::Plugin::BotCommand;
33 use Storable;
34
35 use constant {
36 USER_DATE => 0,
37 USER_MSG => 1,
38 DATA_FILE => 'seen',
39 SAVE_INTERVAL => 20 * 60, # save state every 20 mins
40 };
41
42 my $seen = { };
43 $seen = retrieve(DATA_FILE) if -s DATA_FILE;
44
45 POE::Session->create(
46 package_states => [
47 main => [ qw(
48 _start
49 irc_botcmd_seen
50 irc_ctcp_action
51 irc_join
52 irc_part
53 irc_public
54 irc_quit
55 save
56 )]
57 ],
58 );
59
60 $poe_kernel->run();
61
62 sub _start {
63 my ($kernel, $heap) = @_[KERNEL, HEAP];
64 my $irc = POE::Component::IRC::State->spawn(
65 Nick => 'seen_bot',
66 Server => 'irc.freenode.net',
67 );
68 $heap->{irc} = $irc;
69
70 $irc->plugin_add('AutoJoin', POE::Component::IRC::Plugin::AutoJoin->new(
71 Channels => [ '#test_channel1', '#test_channel2' ]
72 ));
73
74 $irc->plugin_add('BotCommand', POE::Component::IRC::Plugin::BotCommand->new(
75 Commands => {
76 seen => 'Usage: seen <nick>'
77 }
78 ));
79
80 $irc->yield(register => qw(ctcp_action join part public quit botcmd_seen));
81 $irc->yield('connect');
82 $kernel->delay_set('save', SAVE_INTERVAL);
83 return;
84 }
85
86 sub save {
87 my $kernel = $_[KERNEL];
88 warn "storing\n";
89 store($seen, DATA_FILE) or die "Can't save state";
90 $kernel->delay_set('save', SAVE_INTERVAL);
91 }
92
93 sub irc_ctcp_action {
94 my $nick = parse_user($_[ARG0]);
95 my $chan = $_[ARG1]->[0];
96 my $text = $_[ARG2];
97
98 add_nick($nick, "on $chan doing: * $nick $text");
99 }
100
101 sub irc_join {
102 my $nick = parse_user($_[ARG0]);
103 my $chan = $_[ARG1];
104
105 add_nick($nick, "joining $chan");
106 }
107
108 sub irc_part {
109 my $nick = parse_user($_[ARG0]);
110 my $chan = $_[ARG1];
111 my $text = $_[ARG2];
112
113 my $msg = 'parting $chan';
114 $msg .= " with message '$text'" if defined $text;
115
116 add_nick($nick, $msg);
117 }
118
119 sub irc_public {
120 my $nick = parse_user($_[ARG0]);
121 my $chan = $_[ARG1]->[0];
122 my $text = $_[ARG2];
123
124 add_nick($nick, "on $chan saying: $text");
125 }
126
127 sub irc_quit {
128 my $nick = parse_user($_[ARG0]);
129 my $text = $_[ARG1];
130
131 my $msg = 'quitting';
132 $msg .= " with message '$text'" if defined $text;
133
134 add_nick($nick, $msg);
135 }
136
137 sub add_nick {
138 my ($nick, $msg) = @_;
139 $seen->{lc_irc($nick)} = [time, $msg];
140 }
141
142 sub irc_botcmd_seen {
143 my ($heap, $nick, $channel, $target) = @_[HEAP, ARG0..$#_];
144 $nick = parse_user($nick);
145 my $irc = $heap->{irc};
146
147 if ($seen->{lc_irc($target)}) {
148 my $date = localtime $seen->{lc_irc($target)}->[USER_DATE];
149 my $msg = $seen->{lc_irc($target)}->[USER_MSG];
150 $irc->yield(privmsg => $channel, "$nick: I last saw $target at $date $msg");
151 }
152 else {
153 $irc->yield(privmsg => $channel, "$nick: I haven't seen $target");
154 }
155 }
156
158 Hinrik Örn Sigurðsson, hinrik.sig@gmail.com
159
160
161
162perl v5.32.0 2020-07P-O2E8::Component::IRC::Cookbook::Seen(3)