html/modelist.pl
1 # modelist.pl v 0.7.2 by Marcin Rozycki (derwan@irssi.pl) changed at Sat Jun 5 22:38:59 CEST 2004
2 #
3 # Usage:
4 # /se
5 # /si
6 # /unexcept [index] ( ex. /unexcept 1 5 17)
7 # /uninvite [index] ( ex. /uninvite 3 8)
8 #
9
10 use strict;
11 use Irssi 20020600 ();
12 use Irssi::Irc;
13
14 use vars qw($VERSION %IRSSI);
15
16 $VERSION = "0.7.2";
17 %IRSSI = (
18 authors => 'Marcin Rozycki',
19 contact => 'derwan@irssi.pl',
20 name => 'modelist',
21 description => 'Cache of invites and ban exceptions in channel. Usage: /si, /se, '.
22 '/unexcept [indexes], /uninvite [indexes]',
23 license => 'GNU GPL v2',
24 url => 'http://derwan.irssi.pl',
25 changed => 'Sat Jun 5 22:38:59 CEST 2004'
26 );
27
28 Irssi::theme_register([
29 'modelist', '$0 - {hilight $1}: $2 %c$3%n $4'
30 ]);
31
32 my %modelist = ();
33
34 sub channel_create
35 {
36 my ($server, $channel) = (@_[0], lc($_[1]));
37 delete $modelist{lc($server->{tag})}{$channel};
38
39 $server->redirect_event("mode I", 1, "$channel", 0, undef, {
40 'event 346' => 'redir modelist invite',
41 '' => 'event empty' });
42 $server->send_raw("MODE $channel I");
43
44 $server->redirect_event("mode e", 1, "$channel", 0, undef, {
45 'event 348' => 'redir modelist except',
46 '' => 'event empty' });
47 $server->send_raw("MODE $channel e");
48 }
49
50 sub sig_channel_created
51 {
52 channel_create($_[0]->{server}, $_[0]->{name}) unless ($_[0]->{no_modes});
53 }
54
55
56 sub sig_redir_modelist_invite
57 {
58 my ($nick, $chan, $mode) = split(/ +/, $_[1], 3);
59 message_irc_mode($_[0], $chan, undef, undef, "+I $mode");
60 }
61
62 sub sig_redir_modelist_except
63 {
64 my ($nick, $chan, $mode) = split(/ +/, $_[1], 3);
65 message_irc_mode($_[0], $chan, undef, undef, "+e $mode");
66 }
67
68 sub message_irc_mode
69 {
70 my ($mode, @args) = split(/ +/, $_[4]);
71 return unless $_[0]->ischannel($_[1]);
72 my ($tag, $chan, $mod) = (lc($_[0]->{tag}), lc($_[0]->channel_find($_[1])->{name}), "+");
73 foreach ( split //, $mode )
74 {
75 /([+-])/ and $mod = $_, next;
76 my $arg = ( $mod eq '+' && $_ =~ m/[beIkloRvh]/ or $mod eq '-' && $_ =~ m/[beIkoRvh]/ ) ? shift(@args) : undef;
77 next unless ( $_ =~ m/[eI]/ );
78 ( $mod eq '+' ) and push(@{$modelist{$tag}{$chan}{$_}}, [$arg, $_[2], time]), next;
79 for (my $idx = 0; $idx <= $#{$modelist{$tag}{$chan}{$_}}; $idx++) {
80 splice(@{$modelist{$tag}{$chan}{$_}}, $idx, 1) if ($modelist{$tag}{$chan}{$_}[$idx][0] eq $arg);
81 }
82 }
83 }
84
85 sub proc_modelist_show
86 {
87 my ($arg, $server, $channel, $list, $mode) = @_;
88
89 Irssi::print("You\'re not connected to server"), return unless ($server and $server->{connected});
90
91 $arg =~ s/\s.*//;
92 if ($arg) {
93 Irssi::print("Bad channel name: $arg"), return unless ($server->ischannel($arg));
94 unless ($channel = $server->channel_find($arg)) {
95 Irssi::print("You\'re not in channel $arg --> sending request to server");
96 $server->send_raw("MODE $arg $list");
97 return;
98 }
99 }
100
101 Irssi::print("Not joined to any channel"), return unless ($channel and $channel->{type} eq "CHANNEL");
102 Irssi::print("Channel not fully synchronized yet, try again after a while"), return unless ($channel->{synced});
103 Irssi::print("Channel doesn\'t support modes"), return if ($channel->{no_modes});
104
105 my ($tag, $name) = (lc($server->{tag}), $channel->{name});
106 my $chan = lc($name);
107 my $items = $#{$modelist{$tag}{$chan}{$list}};
108
109 Irssi::print("No $mode\s in channel %_$name%_"), return if ($items < 0);
110
111 for (my $idx = 0; $idx <= $items; $idx++)
112 {
113 my ($mask, $who) = ($modelist{$tag}{$chan}{$list}[$idx]->[0], $modelist{$tag}{$chan}{$list}[$idx]->[1]);
114 $mask =~ tr/\240\002\003\037\026/\206\202\203\237\226/;
115 my $setby = ($who) ? "\00314[\003by \002$who\002, ".(time - $modelist{$tag}{$chan}{$list}[$idx]->[2])." secs ago\00314]\003" : undef;
116 $channel->printformat(MSGLEVEL_CRAP, 'modelist', ($idx+1), $name, $mode, $mask, $setby);
117 }
118 }
119
120 sub cmd_si { proc_modelist_show @_, "I", "invite"; }
121 sub cmd_se { proc_modelist_show @_, "e", "ban exception"; }
122
123 sub cmd_modelist {
124 my ( $type, $data, $server, $witem) = @_;
125 Irssi::print("You\'re not connected to server"), return unless ($server and $server->{connected});
126 Irssi::print("Not joined to any channel"), return unless ( $witem and $witem->{type} eq "CHANNEL" );
127 my ($tag, $chan, @masks) = (lc($server->{tag}), lc($server->channel_find($witem->{name})->{name}));
128 while ( $data =~ m/(\d+)/g ) {
129 my $idx = $1 - 1;
130 next unless ( exists $modelist{$tag}{$chan}{$type}[$idx] );
131 push(@masks, $modelist{$tag}{$chan}{$type}[$idx]->[0]);
132 }
133 return unless ( $#masks >= 0 );
134 $witem->command(sprintf("MODE %s -%s %s", $chan, $type x scalar(@masks), join(" ", @masks)));
135 }
136
137 Irssi::signal_add("channel created", "sig_channel_created");
138 Irssi::signal_add("redir modelist invite", "sig_redir_modelist_invite");
139 Irssi::signal_add("redir modelist except", "sig_redir_modelist_except");
140 Irssi::signal_add("message irc mode", "message_irc_mode");
141
142 Irssi::command_bind("si", "cmd_si");
143 Irssi::command_bind("se", "cmd_se");
144 Irssi::command_bind("uninvite" => sub { cmd_modelist("I", @_); });
145 Irssi::command_bind("unexcept" => sub { cmd_modelist("e", @_); });
146
147 foreach my $server (Irssi::servers)
148 {
149 foreach my $channel ($server->channels())
150 {
151 channel_create($server, $channel->{name}) unless ($channel->{no_modes});
152 }
153 }