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