# # Copyright (c) 2011-2019 by w8rabbit (w8rabbit[at]mail[dot]i2p) # or from outside i2p: w8rabbit[at]i2pmail[dot]org # # Script is under GPL3. # # Script is inspired by NullPointerException's xchat script # # thanks to darrob for hard beta-testing # # 1.9.7: fix: a warning about declaration in same scope # remove: unnecessary callback function # 1.9.6: fix: nick parsing with messages containing @ and > # 1.9.5: add compatibility with matrix-appservice-irc # 1.9.4: add compatibility with other kind of messages than irc # 1.9.3: add compatibility with new weechat_print modifier data (WeeChat >= 2.9) # 1.9.2: add: i2pr-support # 1.9.1: fix: uninitialized value (by arza) # fix: indentation # 1.9: add: Gitter support # 1.8: fix: regex on tags # 1.7: add: support of colors with format "${color:xxx}" (>= WeeChat 0.4.2) # 1.6: add: wildcard "*" for supported_bot_names. # 1.5: cleaned up code and make it more readable # 1.4: fix: problem with tag "prefix_nick_ccc" # improved: Nicks will be displayed the same way in Nicklist like in channel buffer. # 1.3: fix: action message (/me) was printed twice for some remote server # 1.2.1: fix: add_relay_nick_to_nicklist() # 1.2: add: a warning will be displayed if a wrecked message was received # add: debug mode (especially for darrob :-) # improved: whitespaces will be removed in front of message-text # 1.1: cleaned up code and made it more readable!!! # add: ACTION messages for "uuu" will be displayed now # improved: relaynet_color option (read online help) # fix: quoted "relaynet/relaynick" in cloudc2sd # 1.0.1: add: new option "relaynet_color" and "relaynet_to_nicklist" # fix: network for cloudc2sd relaybot wasn't displayed # 1.0: add: cloudc2sd relaybot. (thanks to killyourtv for beta-testing) # 0.9: improved: tag-regex for latest weechat version (v0.3.8) # add: option "blacklist" to ignore relaynicks (suggested by darrob) # fix: regex for FLIP (by operhiem1) # improved: nick-modes from relaynicks will not be displayed in nicklist/nickname anymore (for nick auto-completion) # NOTE: weechat can handle more than one nick-mode internally, but it will only display the highest rated nick-mode in nicklist. # 0.8: improved: regex for FLIP bot (reported by user) # fix: problem with nicks in nicklist (thanks to KillYourTV and user) # fix: weechat crash when closing buffer with relay nicks in nicklist # fix: problem with not displaying first relay nick in nicklist # improved: support of colorize_lines script. # 0.7: relay nicks will be displayed in nicklist (in its own group) # new option "unexpected_msg_handling". # 0.6: FLIPRelayBot implemented (suggested by darrob) # 0.5: relay indicator for actions added # 0.4: hardcoded code removed (weechat 0.3.4 and higher required) # 0.3: option suppress_relaynet and suppress_relaynet_channels added. # multi-server support added. # 0.2: scriptname changed from parse_bot_msg to parse_relayed_msg (suggested by darrob) # added version check to use prio for hook_modifier() # 0.1: - initial release - # http://w8rabbit.i2p/parse_relayed_msg.html # http://h4pf2ydu43jadhckgzign5u4m4gfesbjt3uyne575adx7lh7xeuq.b32.i2p/ # ^(:)(\S+)(!\S+@\S+ )(PRIVMSG #thechannel :)<(\S+)> (.*) # /rmodifier add relay irc_in_privmsg 1,5,3,4,6 ^(:)(\S+)(!\S+@\S+ )(PRIVMSG #thechannel :)<(\S+)> (.*) # replace the first \S+ with the bot's nick # flip bot: # :FLIPRelayBot!RelayBot@irc2p PRIVMSG #flip-bridge :[nickname] here comes the message # uuu bot: # :u!u@public.chat.cloud PRIVMSG #anonet :\0305/IcannNet/Name\0308\0308> \0FWell it doesn't work on windows ... use strict; my $SCRIPT_NAME = "parse_relayed_msg"; my $SCRIPT_VERSION = "1.9.7"; my $SCRIPT_DESCR = "proper integration of remote users' nicknames in channel and nicklist"; my $SCRIPT_AUTHOR = "w8rabbit"; my $SCRIPT_LICENCE = "GPL3"; # =============== options =============== my %option = ( "supported_bot_names" => "i2pr,cloudrelay*,MultiRelay*,FLIPRelayBot*,i2pRelay,u2,uuu,RelayBot,lll,iRelay,fox,wolf,hawk,muninn,gribble,vulpine,*GitterBot", "supported_message_kinds" => "irc_privmsg,matrix_message", "debug" => "off", "blacklist" => "", "servername" => "i2p,freenet", "nick_mode" => "⇅", "nick_mode_color" => "yellow", "suppress_relaynet" => "off", "relaynet_color" => "blue", "relaynet_to_nicklist" => "off", "suppress_relaynet_channels" => "", "timer" => "600", "unexpected_msg_handling" => "unchanged", # drop, decrease notification level, unchanged ); my %script_desc = ( "blacklist" => "Comma-separated list of relayed nicknames to be ignored (similar to /ignore). The format is case-sensitive: .", "supported_bot_names" => "Comma-separated list of relay bots.", "supported_message_kinds" => "Comma-separated list of message kinds.", "debug" => "Enable output of raw IRC messages. This is a developer feature and should generally be turned off. The format is: : (default: off)", "servername" => "Comma-separated list of internal servers to enable $SCRIPT_NAME for. (default: i2p,freenet)", "nick_mode" => "Prefix character used to mark relayed nicknames. (default: ⇅). Since WeeChat 0.4.2 you can use format \${color:xxx} but this doesn't affect nicklist.", "nick_mode_color" => "Color of the prefix character. (default: yellow)", "suppress_relaynet" => "Hide nicknames' network part (if applicable). (default: off)", "suppress_relaynet_channels" => "Comma-separated list of channels to activate suppress_relaynet in. Format: \"servername.channel\", e.g. \"i2p.#i2p-dev,freenode.#weechat\". (default: \"\" (i.e. global))", "relaynet_color" => "Color of nicknames' network part. Leave blank for altering colors. (default: \"\")", "relaynet_to_nicklist" => "Include relaynets in the nicklist. (default: off)", "timer" => "Time (in s) after which relayed nicknames get removed from the nicklist. (default: 600)", "unexpected_msg_handling" => "Ignore relay bot messages with unexpected syntax (drop/unchanged). (default: unchanged)", ); # =============== internal values =============== my $weechat_version = ""; my @bot_nicks = ""; my @message_kinds = ""; my @list_of_server = ""; my @suppress_relaynet_channels = ""; my @blacklist = ""; my $group_name = "relay_nicks"; # group name for nicklist my %nick_timer = (); my %Hooks = (); # =============== callback from hook_print() =============== sub parse_relayed_msg_cb { my ( $data, $modifier, $modifier_data, $string ) = @_; # its neither a channel nor a query buffer my $result = should_handle_modifier($modifier_data); return $string unless ($result); my $buffer = ""; my $tags = ""; if ($modifier_data =~ /0x/) { # WeeChat >= 2.9 $modifier_data =~ m/([^;]*);(.*)/; $buffer = $1; $tags = $2; } else { # WeeChat <= 2.8 $modifier_data =~ m/([^;]*);([^;]*);(.*)/; $buffer = weechat::buffer_search($1, $2); $tags = $3; } my $servername = weechat::buffer_get_string($buffer, "localvar_server"); my $channelname = weechat::buffer_get_string($buffer, "localvar_channel"); return $string if ($servername eq "" or $channelname eq ""); return $string if ( !grep /^$servername$/, @list_of_server ); # does server exists? my $buf_ptr = $buffer; $string =~ m/^(.*)\t(.*)/; # nick[tab]string my $nick = $1; # get the nick name (with prefix!) my $line = $2; # get written text # $nick = weechat::string_remove_color($nick,""); # remove color-codes from nick $line = weechat::string_remove_color($line,""); # remove color-codes from line $modifier_data =~ m/(^|,)nick_([^,]*)(,|$)/; # get the nick name from modifier_data (without nick_mode and color codes!) $nick = $2; # display_mode : 0 = /, 1 = @ my $result_smtr = string_mask_to_regex($nick); if ($result_smtr) # if ( grep /^$nick$/, @bot_nicks ) # does a bot exists? { my $blacklist_raw = weechat::config_get_plugin("blacklist"); @blacklist = split( /,/,$blacklist_raw); # message from muninn bot! if ( $line =~ m/^<([^@>]+)@([^>]+)\>\s(.+)$/ ) { my ($relaynick, $relaynet, $relaymsg) = ($1,$2,$3); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ''; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,$relaynet,1); (undef,$relaymsg) = colorize_lines($modifier_data,$relaynick,$relaymsg); $string = create_string_with_relaynet($servername,$channelname,$relaynick,$relaynet,$nick_mode,$relaymsg,1); $modifier_data = change_tags_for_message($buf_ptr,$relaynick,$relaynet,$modifier_data,1); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # message from fox, wolf, hawk bot! elsif ( $line =~ m/^<([^\s]+)\>\s(.+)$/ ) { my ($relaynick, $relaymsg) = ($1,$2); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ''; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,""); (undef,$relaymsg) = colorize_lines($modifier_data,$relaynick,$relaymsg); $string = create_string_without_relaynet($servername,$channelname,$relaynick,$nick_mode,$relaymsg); $modifier_data = change_tags_for_message( $buf_ptr,$relaynick,"",$modifier_data, "" ); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # PRIVMSG #i2p :[Freenode/nickname] here is the message. elsif ( $line =~ m/^[\(\[`](.+?)\/(.+?)[\)\]`] (.+)$/ ) { my ($relayserver,$relaynick,$relaymsg) = ($1,$2,$3); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ''; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,""); (undef, $relaymsg) = colorize_lines($modifier_data,$relaynick, $relaymsg); $string = create_string_without_relaynet($servername,$channelname,$relaynick,$nick_mode,$relaymsg); $modifier_data = change_tags_for_message( $buf_ptr,$relaynick,"",$modifier_data,"" ); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # message from matrix-appservice-irc elsif ( $line =~ m/^\[\w\] <@([^>]+)> (.+)$/ ) { my ($relaynick,$relaymsg) = ($1,$2); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ''; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,""); (undef, $relaymsg) = colorize_lines($modifier_data,$relaynick, $relaymsg); $string = create_string_without_relaynet($servername,$channelname,$relaynick,$nick_mode,$relaymsg); $modifier_data = change_tags_for_message( $buf_ptr,$relaynick,"",$modifier_data,"" ); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # message from FLIP & Gitter elsif ( $line =~ m/^[\(\[`](.+?)[\)\]`] (.+)$/ ) { my ($relaynick,$relaymsg) = ($1,$2); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ''; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,""); (undef, $relaymsg) = colorize_lines($modifier_data,$relaynick, $relaymsg); $string = create_string_without_relaynet($servername,$channelname,$relaynick,$nick_mode,$relaymsg); $modifier_data = change_tags_for_message( $buf_ptr,$relaynick,"",$modifier_data,"" ); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # message from cloudc2sd # :u2!u@irc2p PRIVMSG #relaytest :/botname/nickname> here comes the message elsif ( $line =~ m/^([^\/]+)\/([^\>]+)\>\s(.+)$/ ) { my ($relaynet,$relaynick,$relaymsg) = ($1,$2,$3); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ""; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,$relaynet,0); (undef, $relaymsg) = colorize_lines($modifier_data,$relaynick, $relaymsg); $string = create_string_with_relaynet($servername,$channelname,$relaynick,$relaynet,$nick_mode,$relaymsg,0); $modifier_data = change_tags_for_message( $buf_ptr,$relaynick,$relaynet,$modifier_data,0 ); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # =============== ACTION (/me) messages =============== # from gribble elsif ( $line =~ /\*\s(.+)@([^\s]+)\s(.+)/ ) { my ($relaynick, $relaynet, $relaymsg) = ($1,$2,$3); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ''; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,$relaynet,1); (undef, $relaymsg) = colorize_lines($modifier_data,$relaynick, $relaymsg); $string = create_action_string_with_relaynet($servername,$channelname,$relaynick,$relaynet,$nick_mode,$relaymsg,1); return "" if ( $string eq ""); $modifier_data = change_tags_for_message( $buf_ptr,$relaynick,$relaynet,$modifier_data,1 ); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # from fox, wolf, hawk bot elsif ( $line =~ /\*\s([^\s]+)\s(.+)/ ) { my ($relaynick, $relaymsg) = ($1,$2); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ""; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,""); (undef, $relaymsg) = colorize_lines($modifier_data,$relaynick, $relaymsg); $string = create_action_string_without_relaynet($servername,$channelname,$relaynick,$nick_mode,$relaymsg); $modifier_data = change_tags_for_message( $buf_ptr,$relaynick,"",$modifier_data,"" ); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # from uuu #:u!u@public.chat.cloud PRIVMSG #relaytest :\0305/irc2p2/KillYourTV\0308\0308> \0F\01ACTION tests...again\01 elsif ( $line =~ m/^\/(.+)\/(.+)>\sACTION\s(.*)/ ) { my ($relaynet,$relaynick,$relaymsg) = ($1,$2,$3); if ( grep /^$servername.$relaynick$/, @blacklist ) # check for ignored relay nicks { return ""; # delete message from ignored relaynick } my $nick_mode = ""; ($relaynick,$nick_mode) = check_nick_mode($buf_ptr,$relaynick); add_relay_nick_to_nicklist($buf_ptr,$relaynick,$relaynet,0); (undef, $relaymsg) = colorize_lines($modifier_data,$relaynick, $relaymsg); $string = create_action_string_with_relaynet($servername,$channelname,$relaynick,$relaynet,$nick_mode,$relaymsg,0); $modifier_data = change_tags_for_message( $buf_ptr,$relaynick,$relaynet,$modifier_data,0 ); weechat::print_date_tags($buf_ptr,0,$modifier_data,$string); return ""; } # drop, decrease notification level, unchanged return "" if ( $option{unexpected_msg_handling} eq "drop"); } # end of BOT return $string; } # =============== create string to display in weechat =============== sub create_string_without_relaynet { my ($servername,$channelname,$relaynick,$nick_mode,$relaymsg) = @_; my $string; $relaymsg =~ s/^\s+//; # kill leading space if ($relaymsg eq "") { $string = wrecked_msg($servername,$channelname,$relaynick,"",""); return $string; } my $nick_color = weechat::info_get('irc_nick_color', $relaynick);# get nick-color $string = _color_str( $option{nick_mode_color}, $option{nick_mode} ) . $nick_mode . $nick_color . $relaynick . "\t" . $relaymsg; return $string; } sub create_string_with_relaynet { my ($servername,$channelname,$relaynick,$relaynet,$nick_mode,$relaymsg,$display_mode) = @_; my $string; $relaymsg =~ s/^\s+//; # kill leading space if ($relaymsg eq "") { $string = wrecked_msg($servername,$channelname,$relaynick,$relaynet,$display_mode); return $string; } my $nick_color = weechat::info_get('irc_nick_color', $relaynick);# get nick-color if ( $option{suppress_relaynet} eq "on" and $option{suppress_relaynet_channels} eq "" or ( grep /^$servername.$channelname$/, @suppress_relaynet_channels) ){ # suppress relaynet $string = _color_str( $option{nick_mode_color}, $option{nick_mode} ) . $nick_mode . $nick_color . $relaynick . "\t" . $relaymsg; }else { # show relaynet my $relay_and_nick = relay_and_nick($relaynet,$relaynick,$display_mode); $string = _color_str( $option{nick_mode_color}, $option{nick_mode} ) . $nick_mode . $relay_and_nick. "\t" . $relaymsg; } return $string; } sub create_action_string_without_relaynet { my ($servername,$channelname,$relaynick,$nick_mode,$relaymsg) = @_; my $string; $relaymsg =~ s/^\s+//; # kill leading space if ($relaymsg eq "") { $string = wrecked_msg($servername,$channelname,$relaynick,"",""); return $string; } my $nick_color = weechat::info_get('irc_nick_color', $relaynick);# get nick-color my $prefix_action = weechat::config_string(weechat::config_get("weechat.look.prefix_action")); my $prefix_color = weechat::color(weechat::config_color(weechat::config_get("weechat.color.chat_prefix_action"))); $string = _color_str($prefix_color, $prefix_action) . $nick_mode . "\t" . _color_str( $option{nick_mode_color}, $option{nick_mode} ) . $nick_color . $relaynick . weechat::color("default") . " " . $relaymsg; return $string; } sub create_action_string_with_relaynet { my ($servername,$channelname,$relaynick,$relaynet,$nick_mode,$relaymsg,$display_mode) = @_; my $string; $relaymsg =~ s/^\s+//; # kill leading space if ($relaymsg eq "") { $string = wrecked_msg($servername,$channelname,$relaynick,$relaynet,$display_mode); return $string; } my $nick_color = weechat::info_get('irc_nick_color', $relaynick); my $prefix_action = weechat::config_string(weechat::config_get("weechat.look.prefix_action")); my $prefix_color = weechat::color(weechat::config_color(weechat::config_get("weechat.color.chat_prefix_action"))); if ( $option{suppress_relaynet} eq "on" and $option{suppress_relaynet_channels} eq "" or ( grep /^$servername.$channelname$/, @suppress_relaynet_channels) ) { $string = _color_str($prefix_color, $prefix_action) . $nick_mode . "\t" . _color_str( $option{nick_mode_color}, $option{nick_mode} ) . $nick_color . $relaynick . weechat::color("default") . " " . $relaymsg; }else { # show relaynet my $relay_and_nick = relay_and_nick($relaynet,$relaynick,$display_mode); $string = _color_str($prefix_color, $prefix_action) . $nick_mode . "\t" . _color_str( $option{nick_mode_color}, $option{nick_mode} ) . $relay_and_nick . weechat::color("default") . " " . $relaymsg; } return $string; } sub wrecked_msg { my ($servername,$channelname,$relaynick,$relaynet,$display_mode) = @_; return "" if ( $option{unexpected_msg_handling} eq "drop"); my $string; my $nick_color = weechat::info_get('irc_nick_color', $relaynick); my $relay_and_nick; if (not defined $relaynet or $relaynet eq "") { $relay_and_nick = $nick_color . $relaynick; }else { if ( $option{suppress_relaynet} eq "off" ) { $relay_and_nick = relay_and_nick($relaynet,$relaynick,$display_mode); }elsif ( $option{suppress_relaynet} eq "on" ) { unless ( $option{suppress_relaynet_channels} eq "" or ( grep /^$servername.$channelname$/, @suppress_relaynet_channels) ){ $relay_and_nick = relay_and_nick($relaynet,$relaynick,$display_mode); }else { return ""; } } } my $prefix_error = weechat::config_string(weechat::config_get("weechat.look.prefix_error")); my $prefix_color = weechat::color(weechat::config_color(weechat::config_get("weechat.color.chat_prefix_error"))); $string = _color_str($prefix_color, $prefix_error) . "\t" . "wrecked message from: ". $relay_and_nick; return $string; } sub relay_and_nick { my ($relaynet,$relaynick,$display_mode) = @_; my $nick_color = weechat::info_get('irc_nick_color', $relaynick); my $relaynet_color; if ( $option{relaynet_color} eq "") { $relaynet_color = weechat::color(weechat::info_get('irc_nick_color_name', $relaynet)); }else { $relaynet_color = weechat::color($option{relaynet_color}); } my $relay_and_nick; if ($display_mode eq 0) { $relay_and_nick = $relaynet_color . $relaynet . weechat::color("default") . "/". $nick_color . $relaynick; }elsif ($display_mode eq 1) { $relay_and_nick = $nick_color . $relaynick . weechat::color("default") . "@" . $relaynet_color . $relaynet; } return $relay_and_nick; } # =============== check for a nick mode and extract it =============== sub check_nick_mode { my ($buf_ptr, $relaynick) = @_; $relaynick = weechat::string_remove_color($relaynick,""); # remove color-codes from nick my $nick_mode = ""; if ($relaynick =~ m/^\@|^\%|^\+|^\~|^\*|^\&|^\!|^\-/) # check for nick modes (@%+~*&!-) in nickname (without color) { $nick_mode = substr($relaynick,0,1); # get original nick_mode $relaynick = substr($relaynick,1,length($relaynick)-1); # remove original nick-mode } return $relaynick,$nick_mode; } # =============== change message tags() =============== sub change_tags_for_message { my ( $buf_ptr,$relaynick, $relaynet, $modifier_data, $display_mode ) = @_; my $servername = weechat::buffer_get_string($buf_ptr,"localvar_server"); my $channelname = weechat::buffer_get_string($buf_ptr,"localvar_channel"); if (not defined $relaynet or $relaynet eq "") { $relaynick = $relaynick; }elsif ( $option{suppress_relaynet} eq "off" and $option{relaynet_to_nicklist} eq "on" ) { $relaynick = $relaynick . "/" . $relaynet if ($display_mode eq 0); $relaynick = $relaynick . "@" . $relaynet if ($display_mode eq 1); }elsif ( $option{suppress_relaynet} eq "on" and $option{relaynet_to_nicklist} eq "on") { unless ( $option{suppress_relaynet_channels} eq "" or ( grep /^$servername.$channelname$/, @suppress_relaynet_channels) ){ $relaynick = $relaynick . "/" . $relaynet if ($display_mode eq 0); $relaynick = $relaynick . "@" . $relaynet if ($display_mode eq 1); } } my $nick_color = weechat::info_get('irc_nick_color_name', $relaynick); if (($weechat_version ne "") && ($weechat_version >= 0x00030800)) { $modifier_data =~ s/(^|,)prefix_nick_(.*),/,prefix_nick_$nick_color,nick_$relaynick,/; } else { $modifier_data =~ s/(^|,)nick_(.*),/nick_$relaynick,/; } return $modifier_data; } # =============== nicklist =============== sub add_relay_nick_to_nicklist { my ( $buf_ptr, $relaynick , $relaynet ,$display_mode ) = @_; return if ($buf_ptr eq ""); return if ($relaynick eq ""); my $current_time = time(); # search for group. my $ptr_group = ""; $ptr_group = weechat::nicklist_search_group($buf_ptr,"",$group_name); # create group if it does not exists. if ( $ptr_group eq "") { $ptr_group = weechat::nicklist_add_group($buf_ptr,"",$group_name,"weechat.color.nicklist_group",1); } return if ( $ptr_group eq ""); my $servername = weechat::buffer_get_string($buf_ptr,"localvar_server"); my $channelname = weechat::buffer_get_string($buf_ptr,"localvar_channel"); if (not defined $relaynet or $relaynet eq ""){ $relaynick = $relaynick; }elsif ( $option{suppress_relaynet} eq "off" and $option{relaynet_to_nicklist} eq "on" ) { if (defined $display_mode and $display_mode eq 0) { $relaynick = $relaynick . "/" . $relaynet; }elsif (defined $display_mode and $display_mode eq 1) { $relaynick = $relaynick . "@" . $relaynet; } }elsif ( $option{suppress_relaynet} eq "on" and $option{relaynet_to_nicklist} eq "on") { unless ( $option{suppress_relaynet_channels} eq "" or ( grep /^$servername.$channelname$/, @suppress_relaynet_channels) ) { if (defined $display_mode and $display_mode eq 0) { $relaynick = $relaynick . "/" . $relaynet; }elsif (defined $display_mode and $display_mode eq 1) { $relaynick = $relaynick . "@" . $relaynet; } } } $nick_timer{$buf_ptr.".".$relaynick} = $current_time; # set new timer # get nick color my $nick_color = weechat::info_get('irc_nick_color_name', $relaynick); # nick already exists in group? my $ptr_nick_gui = weechat::nicklist_search_nick($buf_ptr,$ptr_group,$relaynick); # add nick to nicklist, if my $group exists if ( $ptr_nick_gui eq "" ) { my $test = weechat::string_remove_color( _color_str($option{nick_mode_color},$option{nick_mode}),"" ); weechat::nicklist_add_nick($buf_ptr,$ptr_group,$relaynick,$nick_color,$test,$option{nick_mode_color},1); # weechat::nicklist_add_nick($buf_ptr,$ptr_group,$relaynick,$nick_color,$option{nick_mode},$option{nick_mode_color},1); weechat::nicklist_nick_set($buf_ptr,$ptr_nick_gui,"prefix",$option{nick_mode}); weechat::nicklist_nick_set($buf_ptr,$ptr_nick_gui,"prefix_color",$option{nick_mode_color}); } } # check out every x minutes if nick is not too old sub check_own_nicklist { my $current_time = time(); my $timer = $option{"timer"}; while (my ($name, $time) = each %nick_timer) { if ( $current_time - $time >= $timer ) { # delete nick from %hash and from nicklist my ($buf_ptr, $relaynick) = split( /\./, $name ); my $ptr_group = weechat::nicklist_search_group($buf_ptr,"",$group_name); next if ( $ptr_group eq "" ); my $ptr_nick_gui = weechat::nicklist_search_nick($buf_ptr, $ptr_group, $relaynick); if ( $ptr_nick_gui ne "" ) { weechat::nicklist_remove_nick($buf_ptr,$ptr_nick_gui); delete $nick_timer{$name}; } } } } sub _color_str { my ($color_name, $string) = @_; # use eval for colors-codes (${color:red} eg in weechat.look.prefix_error) $string = weechat::string_eval_expression($string, {}, {},{}) if ($weechat_version >= 0x00040200); return weechat::color($color_name) . $string . weechat::color('reset'); } # =============== config =============== sub init_config { foreach my $opt (keys %option) { if (!weechat::config_is_set_plugin($opt)) { weechat::config_set_plugin($opt, $option{$opt}); }else { $option{$opt} = weechat::config_get_plugin($opt); } } @bot_nicks = split( /,/, $option{supported_bot_names} ); # read bot names @message_kinds = split( /,/, $option{supported_message_kinds} ); # read supported_message_kinds @list_of_server = split( /,/, $option{servername} ); # read server @suppress_relaynet_channels = split( /,/, $option{suppress_relaynet_channels} ); # read channels @blacklist = split( /,/, $option{blacklist} ); # read blacklist of relay nicks if (($weechat_version ne "") && ($weechat_version >= 0x00030500)) { foreach my $option ( keys %script_desc ) { weechat::config_set_desc_plugin( $option,$script_desc{$option} ); } } } # =============== hooks() and shutdown =============== sub toggle_config_by_set { my ( $pointer, $name, $value ) = @_; $name = substr($name,length("plugins.var.perl.".$SCRIPT_NAME."."),length($name)); # don't forget the "." $option{$name} = $value; if ( $name eq "supported_bot_names" ) { @bot_nicks = ""; @bot_nicks = split( /,/, $option{supported_bot_names} ); } if ( $name eq "supported_message_kinds" ) { @message_kinds = ""; @message_kinds = split( /,/, $option{supported_message_kinds} ); } if ( $name eq "servername" ) { @list_of_server = ""; @list_of_server = split( /,/, $option{servername} ); } if ( $name eq "suppress_relaynet_channels" ) { @suppress_relaynet_channels = ""; @suppress_relaynet_channels = split( /,/, $option{suppress_relaynet_channels} ); } if ( $name eq "timer" ) { hook_timer($value); } if ( $name eq "debug" ) { hook_debug($value); } return weechat::WEECHAT_RC_OK; } sub hook_timer { my $value = $_[0]; if ( $value eq 0 ) { weechat::unhook($Hooks{timer}) if $Hooks{timer}; $Hooks{timer} = ""; } else { weechat::unhook($Hooks{timer}) if $Hooks{timer}; $Hooks{timer} = weechat::hook_timer( $value * 1000, 60, 0, "check_own_nicklist", ""); } return weechat::WEECHAT_RC_OK; } sub hook_debug { my $value = $_[0]; if ( lc($value) eq "off" or $value eq "") { weechat::unhook($Hooks{debug}) if $Hooks{debug}; $Hooks{debug} = ""; }else { weechat::unhook($Hooks{debug}) if $Hooks{debug}; my ($server, $nick) = split(/\:/,$option{"debug"}); $Hooks{debug} = weechat::hook_signal( $server . ",irc_raw_in_PRIVMSG","debug_cb","") if (defined $server and $server ne ""); } return weechat::WEECHAT_RC_OK; } sub buffer_closing { my ($signal, $callback, $callback_data) = @_; while (my ($name, $time) = each %nick_timer) { my ($buf_ptr, $relaynick) = split( /\./, $name ); my $ptr_group = weechat::nicklist_search_group($buf_ptr,"",$group_name); # remove nicks before closing buffer delete $nick_timer{$name} if ($buf_ptr eq $callback_data); if ($buf_ptr eq $callback_data and $ptr_group ne "") { weechat::nicklist_remove_group($buf_ptr,$ptr_group); } } return weechat::WEECHAT_RC_OK; } # shutting down script will remove the relay nicks from nicklist sub shutdown { while (my ($name, $time) = each %nick_timer) { my ($buf_ptr, $relaynick) = split( /\./, $name ); my $ptr_group = weechat::nicklist_search_group($buf_ptr,"",$group_name); next if ( $ptr_group eq "" ); my $ptr_nick_gui = weechat::nicklist_search_nick($buf_ptr, $ptr_group, $relaynick); weechat::nicklist_remove_nick($buf_ptr,$ptr_nick_gui); } return weechat::WEECHAT_RC_OK; } sub should_handle_modifier { my ($modifier_data) = @_; foreach ( @message_kinds ){ my $message_kind = weechat::string_mask_to_regex($_); if (index( $modifier_data,$message_kind ) != -1) { return 1; } } return 0; } # ========= string_mask_to_regex() ========= sub string_mask_to_regex { my ($nick) = @_; foreach ( @bot_nicks ){ my $bot_nick = weechat::string_mask_to_regex($_); if ($nick =~ /^$bot_nick$/i) { return 1; } } return 0; } # ========= colorize_lines ========= sub colorize_lines { my ( $modifier_data, $nick, $string ) = @_; # change nick name in modifier_data! Take care of tag "prefix_nick_ccc" if (($weechat_version ne "") && ($weechat_version >= 0x00030800)) { $modifier_data =~ s/(^|,)nick_(.*),/,nick_$nick,/; } else { $modifier_data =~ s/(^|,)nick_(.*),/nick_$nick,/; } my $infolist = weechat::infolist_get("perl_script","","colorize_lines"); weechat::infolist_next($infolist); if ( "colorize_lines" eq weechat::infolist_string($infolist,"name") ) { $string = weechat::hook_modifier_exec( "colorize_lines",$modifier_data,"$nick\t$string"); if ($string ne "") { $string =~ m/^(.*)\t(.*)/; # get the nick name: nick[tab]string $nick = $1; # nick $string = $2; # message } # my @array = ""; # my $color_code_reset = weechat::color('reset'); # @array=split(/$color_code_reset/,$line); # my $new_line = ""; # foreach (@array){ # $new_line .= $nick_color . $_ . weechat::color('reset'); # } # $new_line =~ s/\s+$//g; # remove space at end # $line = $new_line; } weechat::infolist_free($infolist); return ($nick,$string); } sub debug_cb { my ($signal, $callback, $callback_data) = @_; # "nick": nick # "host": host # "command": command # "channel": channel # "arguments": arguments (includes channel) if (($weechat_version eq "") or ($weechat_version < 0x00030400)) { weechat::print("",weechat::prefix("error"). "$SCRIPT_NAME: Debug mode needs WeeChat >= 0.3.4"); return weechat::WEECHAT_RC_OK; } my $hashtable = weechat::info_get_hashtable("irc_message_parse" => + { "message" => $callback_data }); my ($server, $nick) = split(/\:/,$option{"debug"}); my @split = split(/\,/,$callback); if (defined $server and $server eq $split[0]){ if ( not defined $nick or $nick eq ""){ weechat::print("","raw message: $callback_data"); }elsif ($nick eq $hashtable->{nick}){ weechat::print("","raw message: $callback_data"); } } return weechat::WEECHAT_RC_OK; } # ========= main ========= weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION, $SCRIPT_LICENCE, $SCRIPT_DESCR, "shutdown", "") || return; $weechat_version = weechat::info_get("version_number", ""); init_config(); weechat::hook_config( "plugins.var.perl.$SCRIPT_NAME.*", "toggle_config_by_set", "" ); weechat::hook_signal("buffer_closing", "buffer_closing", ""); if (($weechat_version ne "") && ($weechat_version >= 0x00030400)){ # v0.3.4 weechat::hook_modifier("500|weechat_print","parse_relayed_msg_cb", ""); # use lower prio (standard: 1000) } else { weechat::hook_modifier("weechat_print","parse_relayed_msg_cb", ""); } $Hooks{timer} = weechat::hook_timer( $option{"timer"} * 1000, 60, 0, "check_own_nicklist", "");