1# vim:syntax=perl
2# vim:tabstop=4
3# vim:shiftwidth=4
4# vim:foldmethod=marker
5# vim:foldenable
6# vim:enc=utf-8
7########################################################################################################
8## WARNING!! BAD ENGLISH BELOW :P
9##
10## This script is designed for those who have been using muh irc bouncer.
11## Basicly this script just monitors the proxy module and if new client
12## connects it sets you automatically back from away state and when client
13## disconnects it sets you automatically away if you arent allready away.
14##
15## Other hand if you dont use irssi-proxy you still have a good reason to
16## use this if you want to forward messages that come to you while
17## you are away to email box.
18## This is usefull for forwarding messages to an SMS-gateway ;)
19##
20## btw.. if you find any bugs or have any ideas for development of this
21## script dont hesitate to send msg to BCOW@IrcNET
22## or send email to anttip@n0-life.com
23##
24#### Version history:
25# 0.1
26#  * basic functionality
27# 0.2b
28#  * a patch from Wulf that gives a user ability to change the autoaway reason.
29#  * Added away_level parameter that gives you ability to control how many
30#    clients there can be connected to the irssi_proxy module before you are
31#    set away.
32#  * You arent set away when disconnecting from the irssi_proxy if you already
33#    are away. This means that your current away reason isn't changed.
34#  * Sends cumulated away messages back to the client when it connects to the
35#    irssi_proxy module.
36# 0.2c
37#  * Fixes bug where cummulated messages weren't sent.
38#  * Code cleanup.
39#  * Text wrapping to standart 80x24 text console.
40#  * Added debug mode.
41#  * Added script modes.
42#  * Got rid of crappy irssi setings system.
43#  * New logging expansion capability, either time or line based.
44# 0.2d
45#  * Micro fix to get back only when needed
46# 0.2e
47#  * Changed default values for $config{script_mode} and $config{emailto} for IRC-only and a non-existing placeholder respectively.
48#### To come / planned / wanted:
49#  * Make expansion system log several channels at once.
50#  * Make this script server based.
51########################################################################################################
52
53use strict;
54use warnings;
55
56# irssi imports
57use Irssi;
58use Irssi::Irc;
59use vars qw($VERSION %IRSSI %config);
60
61$VERSION = "0.2e";
62%IRSSI = (
63	authors => "BCOW",
64	contact => "anttip\@n0-life.com",
65	name => "awayproxy",
66	description => "Sets nick away when client discconects from the "
67		. "irssi-proxy. If away gathers messages targeted to nick and forwards "
68		. "them to an email address.",
69	license => "GPLv2",
70	url => "http://www.n0-life.com",
71);
72
73# After how much seconds we can check if there are any messages to send?
74$config{check_interval} = 45;
75# this setting controls that when this amout of clients are connected to the
76# proxy module script sets you away. If you set this to 0 you are set away when
77# no clients are connected to the proxy module. If you set this to lets say 5
78# then you will be set away allways when the amount of clients connected to the
79# proxy module is 5 or under.
80$config{away_level} = 0;
81# Controls expansion mode. This mode records pub msgs that come after one with
82# your nick in it. you can use line counting or time counting.
83#  0 - off
84#  line - line counting
85#  time - time counting
86$config{expansion_mode} = 'time';
87# How many lines include after start line?
88$config{expansion_lines} = 12;
89# After how many seconds stop gathering msgs?
90$config{expansion_timeout} = 90;
91# script operation mode:
92#  0 - to send messages both to email and when you get back to proxy
93#  1 - only email
94#  2 - only irc
95#  3 - off
96$config{script_mode} = 2;
97# email address where to send the email
98$config{emailto} = 'recipient@domain.tld';
99# sendmail location
100$config{sendmail} = '/usr/sbin/sendmail';
101# who is the sender of the email
102$config{emailfrom} = 'sender@domain.tld';
103# Subject of email
104$config{emailsubject} = '[irssi-proxy]';
105# and the awayreason setting (Thanx Wulf)
106$config{awayreason} = 'Auto-away because client has disconnected from proxy.';
107# Debugging mode
108$config{debug} = 0;
109
110# -- Don't change anything below this line if you don't know Perl. --
111# number of clients connected
112$config{clientcount} = 0;
113# number of lines recorded
114$config{expansion_lines_count} = 0;
115
116$config{expansion_started} = 0;
117# the small list and archive list
118$config{awaymsglist} = [];
119$config{awaymsglist2} = [];
120
121if ( $config{script_mode} == 0 || $config{script_mode} == 1 ) { # {{{
122	# timeouts for check loop
123	debug('Timer on, timeout: ' . $config{check_interval});
124	Irssi::timeout_add($config{check_interval} * 1000, 'msgsend_check', '');
125} # }}}
126
127sub debug { # {{{
128	if ($config{debug}) {
129		my $text = shift;
130		my $caller = caller;
131		Irssi::print('From ' . $caller . ":\n" . $text);
132	}
133} # }}}
134sub msgsend_check { # {{{
135	# If there are any messages to send
136	my $count = @{$config{awaymsglist}};
137	debug("Checking for messages: $count");
138	# Check if we didn't grep msgs right now
139	if ($count > 0 && !$config{expansion_started}) {
140		# Concentate messages into one text.
141		my $text = join "\n", @{$config{awaymsglist}};
142		# Then empty list.
143		$config{awaymsglist} = [];
144		# Finally send email
145		debug("Concentated msgs: $text");
146		send_mail($text);
147	}
148} # }}}
149sub send_mail { # {{{
150	my $text = shift;
151	debug("Sending mail");
152	open MAIL, q{|-}, $config{sendmail} . " -t";
153	print MAIL "To: $config{emailto}\n";
154	print MAIL "From: $config{emailfrom}\n";
155	print MAIL "Subject: $config{emailsubject}\n";
156	print MAIL "$text";
157	close MAIL;
158} # }}}
159sub client_connect { # {{{
160	my (@servers) = Irssi::servers;
161
162	$config{clientcount}++;
163	debug("Client connected, current script mode: $config{script_mode}");
164
165	# setback
166	foreach my $server (@servers) {
167		# if you're away on that server send yourself back
168		if ($server->{usermode_away} == 1) {
169			$server->send_raw('AWAY :');
170			# and then send the current contents of archive list as notify's to
171			# your self ;)
172			# .. weird huh? :)
173			# This sends all the away messages to ALL the servers where you are
174			# connected... this is somewhat weird i know
175			# but if someone wants to make a patch to this i would really
176			# appreciate it.
177			if ($config{script_mode} == 0 || $config{script_mode} == 2) {
178				debug('Sending notices');
179				$server->send_raw('NOTICE ' . $server->{nick} . " :$_")
180					for @{$config{awaymsglist2}};
181			}
182		}
183	}
184	# and "clear" the awaymessage list
185	$config{awaymsglist2} = []
186		if $config{script_mode} == 0 || $config{script_mode} == 2;
187} # }}}
188sub client_disconnect { # {{{
189	my (@servers) = Irssi::servers;
190	debug('Client Disconnectted');
191
192	$config{clientcount}-- unless $config{clientcount} == 0;
193
194	# setaway
195	if ($config{clientcount} <= $config{away_level}) {
196		# ok.. we have the away_level of clients connected or less.
197		foreach my $server (@servers) {
198			if ($server->{usermode_away} == "0") {
199				# we are not away on this server allready.. set the autoaway
200				# reason
201				$server->send_raw(
202					'AWAY :' . $config{awayreason}
203				);
204			}
205		}
206	}
207} # }}}
208sub msg_pub { # {{{
209	my ($server, $data, $nick, $mask, $target) = @_;
210
211	sub push_into_archive { # {{{
212		my ($nick, $mask, $target, $data) = @_;
213		# simple list that is emptied on the email run
214		push @{$config{awaymsglist}}, "<$nick!$mask\@$target> $data"
215			if $config{script_mode} == 0 || $config{script_mode} == 1;
216		# archive list that is emptied only on the client connect run
217		push @{$config{awaymsglist2}}, "<$nick!$mask\@$target> $data"
218			if $config{script_mode} == 0 || $config{script_mode} == 2;
219	} # }}}
220
221	if ($config{expansion_started}) {
222		if ($config{expansion_mode} eq 'line') {
223			if ($config{expansion_lines_count} <= $config{expansion_lines} -1) {
224				if ($config{expansion_chan} eq $target) {
225					debug("In effect from line expansion, pushing on. Cnt: "
226						. $config{expansion_lines_count});
227					push_into_archive($nick, $mask, $target, $data);
228					$config{expansion_lines_count}++;
229				}
230			}
231			else {
232				debug("Line counter reached max, stopping expansion");
233				$config{expansion_lines_count} = 0;
234				$config{expansion_started} = 0;
235				$config{expansion_chan} = '';
236			}
237		}
238		elsif ($config{expansion_mode} eq 'time') {
239			if ($config{expansion_chan} eq $target) {
240				debug("Time expansion in effect, pushing on.");
241				push_into_archive($nick, $mask, $target, $data);
242			}
243		}
244	}
245	elsif ($server->{usermode_away} == "1" && $data =~ /$server->{nick}/i) {
246		debug("Got pub msg with my name");
247		push_into_archive($nick, $mask, $target, $data);
248		if ($config{expansion_mode}) {
249			debug("Starting expansion in mode: " . $config{expansion_mode});
250			$config{expansion_started} = 1;
251			$config{expansion_chan} = $target;
252			$config{expansion_time_out} = Irssi::timeout_add(
253				$config{expansion_timeout} * 1000, 'expansion_stop', ''
254			) if $config{expansion_mode} eq 'time';
255		}
256	}
257} # }}}
258sub expansion_stop { # {{{
259	debug("Stopping expansion from timer");
260	$config{expansion_started} = 0;
261	$config{expansion_chan} = '';
262} # }}}
263sub msg_pri { # {{{
264	my ($server, $data, $nick, $address) = @_;
265	if ($server->{usermode_away} == "1") {
266		debug("Got priv msg");
267		# simple list that is emptied on the email run
268		push @{$config{awaymsglist}}, "<$nick!$address> $data"
269			if $config{script_mode} == 0 || $config{script_mode} == 1;
270		# archive list that is emptied only on the client connect run
271		push @{$config{awaymsglist2}}, "<$nick!$address> $data"
272			if $config{script_mode} == 0 || $config{script_mode} == 2;
273	}
274} # }}}
275
276Irssi::signal_add_last('proxy client connected', 'client_connect');
277Irssi::signal_add_last('proxy client disconnected', 'client_disconnect');
278Irssi::signal_add_last('message public', 'msg_pub');
279Irssi::signal_add_last('message private', 'msg_pri');
280