From: Samir Benmendil Date: Tue, 14 May 2024 22:14:58 +0000 (+0000) Subject: weechat: parse_relayed_msg plugin X-Git-Url: https://git.rmz.io/dotfiles.git/commitdiff_plain/51da0693760627755be557d8629dc64d7e3a1792?ds=sidebyside weechat: parse_relayed_msg plugin I believe this fixed some printing of usernames in channels that are bridged with matrix or other. --- diff --git a/weechat/perl/parse_relayed_msg.pl b/weechat/perl/parse_relayed_msg.pl new file mode 100644 index 0000000..3f890c0 --- /dev/null +++ b/weechat/perl/parse_relayed_msg.pl @@ -0,0 +1,930 @@ +# +# 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", ""); diff --git a/weechat/plugins.conf b/weechat/plugins.conf index 8d99d30..7969869 100644 --- a/weechat/plugins.conf +++ b/weechat/plugins.conf @@ -53,6 +53,19 @@ perl.highmon.nick_prefix = "<" perl.highmon.nick_suffix = ">" perl.highmon.output = "buffer" perl.highmon.short_names = "on" +perl.parse_relayed_msg.blacklist = "" +perl.parse_relayed_msg.debug = "off" +perl.parse_relayed_msg.nick_mode = "?" +perl.parse_relayed_msg.nick_mode_color = "yellow" +perl.parse_relayed_msg.relaynet_color = "blue" +perl.parse_relayed_msg.relaynet_to_nicklist = "off" +perl.parse_relayed_msg.servername = "i2p,freenet" +perl.parse_relayed_msg.supported_bot_names = "i2pr,cloudrelay*,MultiRelay*,FLIPRelayBot*,i2pRelay,u2,uuu,RelayBot,lll,iRelay,fox,wolf,hawk,muninn,gribble,vulpine,*GitterBot" +perl.parse_relayed_msg.supported_message_kinds = "irc_privmsg,matrix_message" +perl.parse_relayed_msg.suppress_relaynet = "off" +perl.parse_relayed_msg.suppress_relaynet_channels = "" +perl.parse_relayed_msg.timer = "600" +perl.parse_relayed_msg.unexpected_msg_handling = "unchanged" python.check_license = "off" python.go.auto_jump = "off" python.go.buffer_number = "on" @@ -178,6 +191,19 @@ perl.beep.bell_always = "use $bell on private messages and/or highlights regardl perl.beep.blacklist_nicks = "comma-separated list of "server.nick": if not empty, these nicks will not be able to trigger execution of commands. Cannot be used in conjuction with whitelist (example: "freenode.nick1,freenode.nick2") (default: "")" perl.beep.whitelist_channels = "comma-separated list of "server.#channel": if not empty, only these channels will trigger execution of commands (example: "freenode.#weechat,freenode.#channel2") (default: "")" perl.beep.whitelist_nicks = "comma-separated list of "server.nick": if not empty, only these nicks will trigger execution of commands (example: "freenode.nick1,freenode.nick2") (default: "")" +perl.parse_relayed_msg.blacklist = "Comma-separated list of relayed nicknames to be ignored (similar to /ignore). The format is case-sensitive: ." +perl.parse_relayed_msg.debug = "Enable output of raw IRC messages. This is a developer feature and should generally be turned off. The format is: : (default: off)" +perl.parse_relayed_msg.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." +perl.parse_relayed_msg.nick_mode_color = "Color of the prefix character. (default: yellow)" +perl.parse_relayed_msg.relaynet_color = "Color of nicknames' network part. Leave blank for altering colors. (default: "")" +perl.parse_relayed_msg.relaynet_to_nicklist = "Include relaynets in the nicklist. (default: off)" +perl.parse_relayed_msg.servername = "Comma-separated list of internal servers to enable parse_relayed_msg for. (default: i2p,freenet)" +perl.parse_relayed_msg.supported_bot_names = "Comma-separated list of relay bots." +perl.parse_relayed_msg.supported_message_kinds = "Comma-separated list of message kinds." +perl.parse_relayed_msg.suppress_relaynet = "Hide nicknames' network part (if applicable). (default: off)" +perl.parse_relayed_msg.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))" +perl.parse_relayed_msg.timer = "Time (in s) after which relayed nicknames get removed from the nicklist. (default: 600)" +perl.parse_relayed_msg.unexpected_msg_handling = "Ignore relay bot messages with unexpected syntax (drop/unchanged). (default: unchanged)" python.go.auto_jump = "automatically jump to buffer when it is uniquely selected (default: "off")" python.go.buffer_number = "display buffer number (default: "on")" python.go.color_name = "color for buffer name (not selected) (default: "black,cyan")"