]> git.rmz.io Git - dotfiles.git/blob - weechat/ruby/samechannel.rb
lazyvim: absorb/update neotest
[dotfiles.git] / weechat / ruby / samechannel.rb
1 # coding: utf-8
2 #
3 # (c) 2013 Hendrik 'henk' Jaeger <weechat@henk.geekmail.org>
4 # (c) 2015 arza <arza@arza.us>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #
19
20 # Changelog:
21 # 2013-10-19 0.0.1 henk:
22 # - initial release
23 # 2015-09-24 0.1 arza:
24 # - option -m/--minimum for minimum count of mutual channels
25 # - fixed completion
26 # 2021-11-06 0.2 Sébastien Helleu:
27 # - make script compatible with WeeChat >= 3.4
28 # (new parameters in function hdata_search)
29
30 def weechat_init
31 Weechat.register(
32 "samechannel",
33 "henk",
34 "0.2",
35 "GPL3",
36 "Lists multiple occurences of the same nick(s) in a set of channels.",
37 "",
38 ""
39 )
40
41 Weechat.hook_command(
42 "samechannel",
43 "Lists multiple occurences of the same nick(s) in a set of channels.",
44 "[-s/--servers servername[,...]] [-c/--channels channelname[,...]] [-n/--nicks nickname[,...]] [-m/--minimum minimum]",
45 "--servers servername[,servername],...]
46 --channels channelname[@servername][,channelname[@servername],...]
47 --nicks nickname[,nickname,...]
48 --minimum minimum (default: 2)
49
50 Options used to set filters. All given names are treated as regular expressions. If no names are given, no filters are set.
51
52 NOTE: Only nicknames from channels the client is joined to are available for comparison!
53
54 EXAMPLES:
55
56 /samechannel -m 5 -s freenode,IRCnet
57 Lists nicks found on at least five channels in freenode and IRCnet combined.
58
59 /samechannel --channels foo
60 Lists nicks found on at least two channels that include 'foo' on all servers.
61
62 /samechannel --nicks barbaz,hons --servers example,foobarbaz
63 Lists channels from the servers example and foobarbaz for each given nick.
64
65 /samechannel --nicks foo --channels ^#example.*@.*free.*$
66 Lists channels you share with nick foo that begin with 'example' from every server with 'free' in their names.",
67 "--minimum" +
68 "|| --servers %(irc_servers) --minimum --channels %(irc_channels)" +
69 "|| --channels %(irc_channels) --servers %(irc_servers)" +
70 "|| --nicks %(irc_server_nicks) --servers %(irc_servers)",
71 "samechannel_cb",
72 ""
73 )
74
75 require 'shellwords'
76 require 'optparse'
77
78 $hdata_ircserver = Weechat.hdata_get('irc_server')
79 $hdata_ircchannel = Weechat.hdata_get('irc_channel')
80 $hdata_ircnick = Weechat.hdata_get('irc_nick')
81
82 return Weechat::WEECHAT_RC_OK
83 end
84
85 def samechannel_cb( data, buffer, args )
86 options = get_options( args.shellsplit )
87
88 serverchannelptrs = Hash.new
89 nickcount = Hash.new
90
91 serverptrs = find_servers(options[:serverfilter])
92
93 serverptrs.each do |serverptr|
94 serverchannelptrs[serverptr] = find_channels(options[:channelfilter], serverptr)
95 end
96
97 serverchannelptrs.each_pair do |serverptr, channelptrs|
98 servername = Weechat.hdata_string($hdata_ircserver, serverptr, 'name')
99 own_nick = Weechat.hdata_string($hdata_ircserver, serverptr, 'nick')
100
101 channelptrs.each do |channelptr|
102 channelname = Weechat.hdata_string($hdata_ircchannel, channelptr, 'name')
103
104 find_nicks(options[:nickfilter], channelptr).each do |nickptr|
105 nickname = Weechat.hdata_string($hdata_ircnick, nickptr, 'name')
106 next if nickname == own_nick
107 (nickcount[nickname] ||= Array.new) << [channelname, servername].join('@')
108 end
109 end
110 end
111
112 minimum = options[:minimumfilter].to_i
113 minimum = 2 if minimum==0
114
115 duplicate_nicks = nickcount.delete_if do |nickname, nickpaths|
116 nickpaths.length < minimum
117 end
118 duplicate_nicks_sorted = duplicate_nicks.sort do |a, b|
119 a[1].length <=> b[1].length
120 end
121 duplicate_nicks_sorted.each do |nickname, nickpaths|
122 Weechat.print("", "#{Weechat.color('yellow')}#{nickname}#{Weechat.color('chat')} appeared #{nickpaths.length} times: #{nickpaths.join(', ')}")
123 end
124
125 return Weechat::WEECHAT_RC_OK
126 end
127
128 def find_nicks( names, channelptr )
129 all_nicks = hhh_get_ptrarray($hdata_ircnick, Weechat.hdata_pointer($hdata_ircchannel, channelptr, 'nicks'))
130 if names
131 all_nicks.find_all do |nickptr|
132 nickname = Weechat.hdata_string($hdata_ircnick, nickptr, 'name')
133 foundnames = names.any? do |name|
134 Regexp.new(name).match(nickname)
135 end
136 end
137 else
138 return all_nicks
139 end
140 end
141
142 def find_channels( names, serverptr )
143 servername = Weechat.hdata_string($hdata_ircserver, serverptr, 'name')
144 all_channels = hhh_get_ptrarray($hdata_ircchannel, Weechat.hdata_pointer($hdata_ircserver, serverptr, 'channels'))
145 if names
146 all_channels.find_all do |channelptr|
147 channelname = Weechat.hdata_string($hdata_ircchannel, channelptr, 'name')
148 foundnames = names.any? do |name|
149 name_re = Regexp.new(name)
150 if /.*@.*/.match(name)
151 name_re.match(channelname + '@' + servername)
152 else
153 name_re.match(channelname)
154 end
155 end
156 end
157 else
158 return all_channels
159 end
160 end
161
162 def find_servers( names )
163 weechat_version = Weechat.info_get('version_number', '').to_i
164 serverptrlist = Weechat.hdata_get_list($hdata_ircserver, 'irc_servers')
165 if names
166 matching_servers = names.map do |name|
167 if weechat_version >= 0x03040000
168 foundserverptr = Weechat.hdata_search($hdata_ircserver, serverptrlist,
169 '${irc_server.name} =~ ${name}',
170 {}, {'name' => name}, {}, 1)
171 else
172 foundserverptr = Weechat.hdata_search($hdata_ircserver, serverptrlist, '${irc_server.name} =~ ' + name, 1)
173 end
174 end
175 else
176 return hhh_get_ptrarray($hdata_ircserver, serverptrlist)
177 end
178 end
179
180 def hhh_get_ptrarray( hdata, pointer )
181 pointers = Array.new
182 begin
183 pointers << pointer unless pointer.empty?
184 end until (pointer = Weechat.hdata_move(hdata, pointer, 1)).empty?
185 return pointers
186 end
187
188 def get_options( args )
189 options = Hash.new
190
191 opt_parser = OptionParser.new do |opts|
192
193 opts.on("-c", "--channels channelname[,channelname,...]",
194 "Only channels matching the given (partial) channelname(s) will be considered.)") do |channels|
195 options[:channelfilter] = channels.split(',')
196 end
197
198 opts.on("-n", "--nicks nickname[,nickname,...]",
199 "Only nicks matching the given (partial) nickname(s) will be considered.)") do |nicks|
200 options[:nickfilter] = nicks.split(',')
201 end
202
203 opts.on("-s", "--servers servername[,servername,...]",
204 "Only servers matching the given (partial) servername(s) will be considered.)") do |servers|
205 options[:serverfilter] = servers.split(',')
206 end
207
208 opts.on("-m", "--minimum minimum",
209 "Only nicks with at least this many matches will be considered.") do |minimum|
210 options[:minimumfilter] = minimum
211 end
212
213 end
214
215 opt_parser.parse(args)
216
217 return options
218 end