ircinch 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.standard.yml +3 -0
  3. data/CHANGELOG.md +298 -0
  4. data/CODE_OF_CONDUCT.md +84 -0
  5. data/Gemfile +5 -0
  6. data/LICENSE.txt +23 -0
  7. data/README.md +195 -0
  8. data/Rakefile +14 -0
  9. data/docs/bot_options.md +454 -0
  10. data/docs/changes.md +541 -0
  11. data/docs/common_mistakes.md +60 -0
  12. data/docs/common_tasks.md +57 -0
  13. data/docs/encodings.md +69 -0
  14. data/docs/events.md +273 -0
  15. data/docs/getting_started.md +184 -0
  16. data/docs/logging.md +90 -0
  17. data/docs/migrating.md +267 -0
  18. data/docs/plugins.md +4 -0
  19. data/docs/readme.md +20 -0
  20. data/examples/basic/autovoice.rb +32 -0
  21. data/examples/basic/google.rb +35 -0
  22. data/examples/basic/hello.rb +14 -0
  23. data/examples/basic/join_part.rb +35 -0
  24. data/examples/basic/memo.rb +39 -0
  25. data/examples/basic/msg.rb +15 -0
  26. data/examples/basic/seen.rb +37 -0
  27. data/examples/basic/urban_dict.rb +36 -0
  28. data/examples/basic/url_shorten.rb +36 -0
  29. data/examples/plugins/autovoice.rb +37 -0
  30. data/examples/plugins/custom_prefix.rb +22 -0
  31. data/examples/plugins/dice_roll.rb +38 -0
  32. data/examples/plugins/google.rb +36 -0
  33. data/examples/plugins/hello.rb +21 -0
  34. data/examples/plugins/hooks.rb +34 -0
  35. data/examples/plugins/join_part.rb +41 -0
  36. data/examples/plugins/lambdas.rb +35 -0
  37. data/examples/plugins/last_nick.rb +24 -0
  38. data/examples/plugins/msg.rb +21 -0
  39. data/examples/plugins/multiple_matches.rb +32 -0
  40. data/examples/plugins/own_events.rb +37 -0
  41. data/examples/plugins/seen.rb +44 -0
  42. data/examples/plugins/timer.rb +22 -0
  43. data/examples/plugins/url_shorten.rb +34 -0
  44. data/ircinch.gemspec +43 -0
  45. data/lib/cinch/ban.rb +53 -0
  46. data/lib/cinch/bot.rb +476 -0
  47. data/lib/cinch/cached_list.rb +21 -0
  48. data/lib/cinch/callback.rb +22 -0
  49. data/lib/cinch/channel.rb +465 -0
  50. data/lib/cinch/channel_list.rb +31 -0
  51. data/lib/cinch/configuration/bot.rb +50 -0
  52. data/lib/cinch/configuration/dcc.rb +18 -0
  53. data/lib/cinch/configuration/plugins.rb +43 -0
  54. data/lib/cinch/configuration/sasl.rb +21 -0
  55. data/lib/cinch/configuration/ssl.rb +21 -0
  56. data/lib/cinch/configuration/timeouts.rb +16 -0
  57. data/lib/cinch/configuration.rb +75 -0
  58. data/lib/cinch/constants.rb +535 -0
  59. data/lib/cinch/dcc/dccable_object.rb +39 -0
  60. data/lib/cinch/dcc/incoming/send.rb +149 -0
  61. data/lib/cinch/dcc/incoming.rb +3 -0
  62. data/lib/cinch/dcc/outgoing/send.rb +123 -0
  63. data/lib/cinch/dcc/outgoing.rb +3 -0
  64. data/lib/cinch/dcc.rb +14 -0
  65. data/lib/cinch/exceptions.rb +48 -0
  66. data/lib/cinch/formatting.rb +127 -0
  67. data/lib/cinch/handler.rb +120 -0
  68. data/lib/cinch/handler_list.rb +92 -0
  69. data/lib/cinch/helpers.rb +230 -0
  70. data/lib/cinch/i_support.rb +100 -0
  71. data/lib/cinch/irc.rb +924 -0
  72. data/lib/cinch/log_filter.rb +23 -0
  73. data/lib/cinch/logger/formatted_logger.rb +100 -0
  74. data/lib/cinch/logger/zcbot_logger.rb +26 -0
  75. data/lib/cinch/logger.rb +171 -0
  76. data/lib/cinch/logger_list.rb +88 -0
  77. data/lib/cinch/mask.rb +69 -0
  78. data/lib/cinch/message.rb +397 -0
  79. data/lib/cinch/message_queue.rb +104 -0
  80. data/lib/cinch/mode_parser.rb +78 -0
  81. data/lib/cinch/network.rb +106 -0
  82. data/lib/cinch/open_ended_queue.rb +26 -0
  83. data/lib/cinch/pattern.rb +66 -0
  84. data/lib/cinch/plugin.rb +517 -0
  85. data/lib/cinch/plugin_list.rb +40 -0
  86. data/lib/cinch/rubyext/float.rb +5 -0
  87. data/lib/cinch/rubyext/module.rb +28 -0
  88. data/lib/cinch/rubyext/string.rb +35 -0
  89. data/lib/cinch/sasl/dh_blowfish.rb +73 -0
  90. data/lib/cinch/sasl/diffie_hellman.rb +50 -0
  91. data/lib/cinch/sasl/mechanism.rb +8 -0
  92. data/lib/cinch/sasl/plain.rb +29 -0
  93. data/lib/cinch/sasl.rb +36 -0
  94. data/lib/cinch/syncable.rb +83 -0
  95. data/lib/cinch/target.rb +199 -0
  96. data/lib/cinch/timer.rb +147 -0
  97. data/lib/cinch/user.rb +489 -0
  98. data/lib/cinch/user_list.rb +89 -0
  99. data/lib/cinch/utilities/deprecation.rb +18 -0
  100. data/lib/cinch/utilities/encoding.rb +39 -0
  101. data/lib/cinch/utilities/kernel.rb +15 -0
  102. data/lib/cinch/version.rb +6 -0
  103. data/lib/cinch.rb +7 -0
  104. data/lib/ircinch.rb +7 -0
  105. metadata +205 -0
data/docs/migrating.md ADDED
@@ -0,0 +1,267 @@
1
+ # @title Migration Guide
2
+ # @markup kramdown
3
+
4
+ # Migration Guide
5
+
6
+ This document explains how to migrate between API incompatible
7
+ versions of Cinch.
8
+
9
+ ## Migrating from 1.x to 2.x
10
+
11
+ ## Plugins
12
+
13
+ ### New methods
14
+
15
+ Plugins have the following (new) instance and class methods, which you
16
+ shouldn't and usually mustn't overwrite:
17
+
18
+ - `#bot`
19
+ - `#config`
20
+ - `#handlers`
21
+ - `#synchronize`
22
+ - `#timers`
23
+ - `#unregister`
24
+ - `::call_hooks`
25
+ - `::check_for_missing_options`
26
+ - `::ctcp`
27
+ - `::ctcps`
28
+ - `::help=`
29
+ - `::help`
30
+ - `::hook`
31
+ - `::hooks`
32
+ - `::listen_to`
33
+ - `::listeners`
34
+ - `::match`
35
+ - `::matchers`
36
+ - `::plugin_name=`
37
+ - `::plugin_name`
38
+ - `::prefix=`
39
+ - `::prefix`
40
+ - `::react_on=`
41
+ - `::react_on`
42
+ - `::required_options=`
43
+ - `::required_options`
44
+ - `::set`
45
+ - `::suffix=`
46
+ - `::suffix`
47
+ - `::timer`
48
+ - `::timers`
49
+
50
+ Note: The list does also include methods from prior versions.
51
+
52
+
53
+ ### Plugin options
54
+
55
+ Previously, plugins used a DSL-like way of setting options like the
56
+ plugin prefix. This contradicts with the general idea of plugins being
57
+ ordinary Ruby classes and also caused a lot of code and documentation
58
+ smell.
59
+
60
+ Instead of having methods like `#prefix` double as both attribute
61
+ getter and setter, options can now be set in two different ways: Using
62
+ ordinary attribute setters or using the
63
+ {Cinch::Plugin::ClassMethods#set #set} method.
64
+
65
+ #### Cinch 1.x
66
+
67
+ class MyPlugin
68
+ include Cinch::Plugin
69
+
70
+ prefix /^!/
71
+ help "some help message"
72
+ match /foo/
73
+ def execute(m)
74
+ # ...
75
+ end
76
+ end
77
+
78
+ #### Cinch 2.x, attribute setters
79
+
80
+ class MyPlugin
81
+ include Cinch::Plugin
82
+
83
+ self.prefix = /^!/
84
+ self.help = "some help message"
85
+ match /foo/
86
+ def execute(m)
87
+ # ...
88
+ end
89
+ end
90
+
91
+ #### Cinch 2.x, `#set` method
92
+
93
+ class MyPlugin
94
+ include Cinch::Plugin
95
+
96
+ set :prefix, /^!/
97
+ set :help, "some help message"
98
+ match /foo/
99
+ def execute(m)
100
+ # ...
101
+ end
102
+ end
103
+
104
+ #### Cinch 2.x, `#set` method, alternative syntax
105
+
106
+ class MyPlugin
107
+ include Cinch::Plugin
108
+
109
+ set prefix: /^!/,
110
+ help: "some help message"
111
+ match /foo/
112
+ def execute(m)
113
+ # ...
114
+ end
115
+ end
116
+
117
+
118
+ ### No more automatic matcher with the plugin's name
119
+
120
+ Cinch does not add a default matcher with the plugin's name anymore.
121
+ If you've been relying on the following to work
122
+
123
+ class Footastic
124
+ include Cinch::Plugin
125
+
126
+ def execute(m)
127
+ # this will triger on "!footastic"
128
+ end
129
+ end
130
+
131
+ you will have to rewrite it using an explicit matcher:
132
+
133
+ class Footastic
134
+ include Cinch::Plugin
135
+
136
+ match "footastic"
137
+ def execute(m)
138
+ # ...
139
+ end
140
+ end
141
+
142
+ ### No more default `#execute` and `#listen` methods
143
+
144
+ Plugins do not come with default `#execute` and `#listen` methods
145
+ anymore, which means that specifying a matcher or listener without
146
+ providing the required methods will always result in an exception.
147
+
148
+ ### Programmatically registering plugins
149
+
150
+ If you're using the API to register plugins on your own, you will have
151
+ to use the new {Cinch::PluginList} class and its methods, instead of
152
+ using `Cinch::Bot#register_plugin` or `Cinch::Bot#register_plugins`,
153
+ which have been removed.
154
+
155
+ The PluginList instance is available via {Cinch::Bot#plugins}.
156
+
157
+ ## Logging
158
+
159
+ Logging in Cinch 2.x has been greatly improved. Instead of only
160
+ supporting one logger and having all logging-relevant methods in
161
+ {Cinch::Bot}, we've introduced the {Cinch::LoggerList} class, which
162
+ manages an infinite number of loggers. Included with Cinch are the
163
+ {Cinch::Logger::FormattedLogger formatted logger}, known from Cinch
164
+ 1.x, and a new {Cinch::Logger::ZcbotLogger Zcbot logger}, a logger
165
+ emulating the log output of Zcbot, a format which can be parsed by
166
+ {http://pisg.sourceforge.net/ pisg}.
167
+
168
+ ### Log levels
169
+
170
+ The old `@config.verbose` option has been replaced with a finely
171
+ tunable log level system. Each logger has {Cinch::Logger#level its own
172
+ level}, but it is also possible to {Cinch::LoggerList#level= set the
173
+ level for all loggers at once}.
174
+
175
+ The available levels, in ascending order of verbosity, are:
176
+
177
+ - fatal
178
+ - error
179
+ - warn
180
+ - info
181
+ - log
182
+ - debug
183
+
184
+ ### Methods
185
+
186
+ All logging related methods (`Cinch::Bot#debug` et al) have been
187
+ removed from the Bot class and instead moved to the loggers and the
188
+ {Cinch::LoggerList LoggerList}. If you want to log messages from your
189
+ plugins or handlers, you should use {Cinch::Bot#loggers} to access the
190
+ {Cinch::LoggerList LoggerList} and then call the right methods on
191
+ that. Alterntively you can also use the logging-related helper methods
192
+ provided by {Cinch::Helpers}.
193
+
194
+ For more information on the logging architecture as well as examples
195
+ on how to use it, check the {file:docs/logging.md Logging readme}.
196
+
197
+ ## Prefix/suffix + string semantics
198
+
199
+ Behaviour of string prefixes and suffixes has been adapted to match
200
+ that of matchers.
201
+
202
+ That means that if the prefix or suffix are strings, the ^ or $ anchor
203
+ will be prepended/appened.
204
+
205
+ ## Hooks and their return value
206
+
207
+ Hooks now behave as filters. If a hook returns `false`, the message
208
+ will not further be processed in a particular plugin.
209
+
210
+ ## Constants
211
+
212
+ All constants for numeric replies (e.g. `RPL_INFO`) have been moved from
213
+ {Cinch} to {Cinch::Constants}. Thus `Cinch::RPL_INFO` becomes
214
+ {Cinch::Constants::RPL_INFO}, same for all other numeric constants.
215
+
216
+ ## Bot configuration
217
+
218
+ Bot configuration now uses {Cinch::Configuration special classes}
219
+ instead of OpenStructs. Thus, assignments like
220
+
221
+ configure do |c|
222
+ c.timeouts = OpenStruct.new({:read => 240, :connect => 10})
223
+ end
224
+
225
+ are not possible anymore and have to be written as either
226
+
227
+ configure do |c|
228
+ c.timeouts.read = 240
229
+ c.timeouts.connect = 10
230
+ end
231
+
232
+ or
233
+
234
+ configure do |c|
235
+ c.timeouts.load({:read => 240, :connect => 10})
236
+ end
237
+
238
+ The second version is especially interesting to tools like
239
+ {https://github.com/netfeed/cinchize Cinchize}, which load the
240
+ configuration from a YAML file. For more information see
241
+ {file:docs/bot_options.md Bot options}.
242
+
243
+
244
+ ## Various removed methods
245
+
246
+ See {file:docs/changes.md#removedrenamed-methods What's changed}
247
+
248
+
249
+ ## `on`-handlers now only accepts one pattern
250
+
251
+ In previous versions, {Cinch::Bot#on} accepted a variable amount of patterns
252
+ to match against. This feature was rarely used and has hence been
253
+ removed. If you've been using constructs like
254
+
255
+ on :message, [/this/, /that/] do |m|
256
+ # ...
257
+ end
258
+
259
+ you will have to rewrite them as follows:
260
+
261
+ b = lambda { |m|
262
+ # ...
263
+ }
264
+
265
+ [/this/, /that/].each do |pattern|
266
+ on :message, pattern, &b
267
+ end
data/docs/plugins.md ADDED
@@ -0,0 +1,4 @@
1
+ # @title Plugins
2
+ # @markup kramdown
3
+
4
+ Content will follow soon…
data/docs/readme.md ADDED
@@ -0,0 +1,20 @@
1
+ # @title README
2
+ # @markup kramdown
3
+
4
+
5
+ - {file:docs/changes.md Changelog}
6
+ - {file:docs/migrating.md Migration guides}
7
+
8
+ # Important documents
9
+
10
+ The following is a list of important documents to read.
11
+
12
+ - {file:docs/bot_options.md Bot options}
13
+ - {file:docs/common_tasks.md Common Tasks}
14
+ - {file:docs/common_mistakes.md Common mistakes}
15
+ - {Cinch::DCC DCC}
16
+ - {file:docs/encodings.md Encodings}
17
+ - {file:docs/logging.md Logging}
18
+ - {Cinch::SASL SASL}
19
+ - {Cinch::Formatting Formatting messages}
20
+ - {file:docs/events.md Events}
@@ -0,0 +1,32 @@
1
+ require "ircinch"
2
+
3
+ # Give this bot ops in a channel and it'll auto voice
4
+ # visitors
5
+ #
6
+ # Enable with !autovoice on
7
+ # Disable with !autovoice off
8
+ #
9
+ # It starts out disabled.
10
+
11
+ bot = Cinch::Bot.new do
12
+ configure do |c|
13
+ c.nick = "ircinch_autovoice"
14
+ c.server = "irc.libera.chat"
15
+ c.verbose = true
16
+ c.channels = ["#ircinch-bots"]
17
+ end
18
+
19
+ on :join do |m|
20
+ unless m.user.nick == bot.nick # We shouldn't attempt to voice ourselves
21
+ m.channel.voice(m.user) if @autovoice
22
+ end
23
+ end
24
+
25
+ on :channel, /^!autovoice (on|off)$/ do |m, option|
26
+ @autovoice = option == "on"
27
+
28
+ m.reply "Autovoice is now #{@autovoice ? "enabled" : "disabled"}"
29
+ end
30
+ end
31
+
32
+ bot.start
@@ -0,0 +1,35 @@
1
+ require "cgi"
2
+ require "ircinch"
3
+ require "nokogiri"
4
+ require "open-uri"
5
+
6
+ bot = Cinch::Bot.new do
7
+ configure do |c|
8
+ c.server = "irc.libera.chat"
9
+ c.nick = "MrIrCinch"
10
+ c.channels = ["#ircinch-bots"]
11
+ end
12
+
13
+ helpers do
14
+ # Extremely basic method, grabs the first result returned by Google
15
+ # or "No results found" otherwise
16
+ def google(query)
17
+ url = "http://www.google.com/search?q=#{CGI.escape(query)}"
18
+ res = Nokogiri.HTML(URI.parse(url).open).at("h3.r")
19
+
20
+ title = res.text
21
+ link = res.at("a")[:href]
22
+ desc = res.at("./following::div").children.first.text
23
+ rescue
24
+ "No results found"
25
+ else
26
+ CGI.unescape_html "#{title} - #{desc} (#{link})"
27
+ end
28
+ end
29
+
30
+ on :message, /^!google (.+)/ do |m, query|
31
+ m.reply google(query)
32
+ end
33
+ end
34
+
35
+ bot.start
@@ -0,0 +1,14 @@
1
+ require "ircinch"
2
+
3
+ bot = Cinch::Bot.new do
4
+ configure do |c|
5
+ c.server = "irc.libera.chat"
6
+ c.channels = ["#ircinch-bots"]
7
+ end
8
+
9
+ on :message, "hello" do |m|
10
+ m.reply "Hello, #{m.user.nick}"
11
+ end
12
+ end
13
+
14
+ bot.start
@@ -0,0 +1,35 @@
1
+ require "ircinch"
2
+
3
+ bot = Cinch::Bot.new do
4
+ configure do |c|
5
+ c.server = "irc.libera.chat"
6
+ c.nick = "IrCinchBot"
7
+ c.channels = ["#cinch-bots"]
8
+ end
9
+
10
+ # Who should be able to access these plugins
11
+ def admin
12
+ "injekt"
13
+ end
14
+
15
+ helpers do
16
+ def is_admin?(user)
17
+ true if user.nick == admin
18
+ end
19
+ end
20
+
21
+ on :message, /^!join (.+)/ do |m, channel|
22
+ bot.join(channel) if is_admin?(m.user)
23
+ end
24
+
25
+ on :message, /^!part(?: (.+))?/ do |m, channel|
26
+ # Part current channel if none is given
27
+ channel ||= m.channel
28
+
29
+ if channel
30
+ bot.part(channel) if is_admin?(m.user)
31
+ end
32
+ end
33
+ end
34
+
35
+ bot.start
@@ -0,0 +1,39 @@
1
+ require "ircinch"
2
+
3
+ class Memo < Struct.new(:nick, :channel, :text, :time)
4
+ def to_s
5
+ "[#{time.asctime}] <#{channel}/#{nick}> #{text}"
6
+ end
7
+ end
8
+
9
+ bot = Cinch::Bot.new do
10
+ configure do |c|
11
+ c.server = "irc.libera.chat"
12
+ c.channels = ["#ircinch-bots"]
13
+ end
14
+
15
+ def memos
16
+ {}
17
+ end
18
+
19
+ on :message do |m|
20
+ if memos.has_key?(m.user.nick)
21
+ m.user.send memos.delete(m.user.nick).to_s
22
+ end
23
+ end
24
+
25
+ on :message, /^!memo (.+?) (.+)/ do |m, nick, message|
26
+ if memos.key?(nick)
27
+ m.reply "There's already a memo for #{nick}. You can only store one right now"
28
+ elsif nick == m.user.nick
29
+ m.reply "You can't leave memos for yourself.."
30
+ elsif nick == bot.nick
31
+ m.reply "You can't leave memos for me.."
32
+ else
33
+ memos[nick] = Memo.new(m.user.nick, m.channel, message, Time.now)
34
+ m.reply "Added memo for #{nick}"
35
+ end
36
+ end
37
+ end
38
+
39
+ bot.start
@@ -0,0 +1,15 @@
1
+ require "ircinch"
2
+
3
+ bot = Cinch::Bot.new do
4
+ configure do |c|
5
+ c.server = "irc.libera.chat"
6
+ c.nick = "IrCinchBot"
7
+ c.channels = ["#ircinch-bots"]
8
+ end
9
+
10
+ on :message, /^!msg (.+?) (.+)/ do |m, who, text|
11
+ User(who).send text
12
+ end
13
+ end
14
+
15
+ bot.start
@@ -0,0 +1,37 @@
1
+ require "ircinch"
2
+
3
+ class Seen < Struct.new(:who, :where, :what, :time)
4
+ def to_s
5
+ "[#{time.asctime}] #{who} was seen in #{where} saying #{what}"
6
+ end
7
+ end
8
+
9
+ bot = Cinch::Bot.new do
10
+ configure do |c|
11
+ c.server = "irc.libera.chat"
12
+ c.channels = ["#ircinch-bots"]
13
+ end
14
+
15
+ def users
16
+ {}
17
+ end
18
+
19
+ # Only log channel messages
20
+ on :channel do |m|
21
+ users[m.user.nick] = Seen.new(m.user.nick, m.channel, m.message, Time.new)
22
+ end
23
+
24
+ on :channel, /^!seen (.+)/ do |m, nick|
25
+ if nick == bot.nick
26
+ m.reply "That's me!"
27
+ elsif nick == m.user.nick
28
+ m.reply "That's you!"
29
+ elsif users.key?(nick)
30
+ m.reply users[nick].to_s
31
+ else
32
+ m.reply "I haven't seen #{nick}"
33
+ end
34
+ end
35
+ end
36
+
37
+ bot.start
@@ -0,0 +1,36 @@
1
+ require "cgi"
2
+ require "ircinch"
3
+ require "nokogiri"
4
+ require "open-uri"
5
+
6
+ # This bot connects to urban dictionary and returns the first result
7
+ # for a given query, replying with the result directly to the sender
8
+
9
+ bot = Cinch::Bot.new do
10
+ configure do |c|
11
+ c.server = "irc.libera.chat"
12
+ c.nick = "MrIrCinch"
13
+ c.channels = ["#ircinch-bots"]
14
+ end
15
+
16
+ helpers do
17
+ # This method assumes everything will go ok, it's not the best method
18
+ # of doing this *by far* and is simply a helper method to show how it
19
+ # can be done.. it works!
20
+ def urban_dict(query)
21
+ url = "http://www.urbandictionary.com/define.php?term=#{CGI.escape(query)}"
22
+ CGI.unescape_html Nokogiri::HTML(URI.parse(url)).open.css("div.meaning").first.text.gsub(/\s+/, " ").strip
23
+ rescue
24
+ nil
25
+ end
26
+ end
27
+
28
+ on :message, /^!urban (.+)/ do |m, term|
29
+ m.reply(urban_dict(term) || "No results found", true)
30
+ end
31
+ end
32
+
33
+ bot.start
34
+
35
+ # injekt> !urban cinch
36
+ # MrIrCinch> injekt: describing an action that's extremely easy.
@@ -0,0 +1,36 @@
1
+ require "cgi"
2
+ require "ircinch"
3
+ require "open-uri"
4
+
5
+ # Automatically shorten URL's found in messages
6
+ # Using the tinyURL API
7
+
8
+ bot = Cinch::Bot.new do
9
+ configure do |c|
10
+ c.server = "irc.libera.chat"
11
+ c.channels = ["#ircinch-bots"]
12
+ end
13
+
14
+ helpers do
15
+ def shorten(url)
16
+ url = URI.open("http://tinyurl.com/api-create.php?url=#{CGI.escape(url)}").parse
17
+ (url == "Error") ? nil : url
18
+ rescue OpenURI::HTTPError
19
+ nil
20
+ end
21
+ end
22
+
23
+ on :channel do |m|
24
+ urls = URI.extract(m.message, "http")
25
+
26
+ unless urls.empty?
27
+ short_urls = urls.map { |url| shorten(url) }.compact
28
+
29
+ unless short_urls.empty?
30
+ m.reply short_urls.join(", ")
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ bot.start
@@ -0,0 +1,37 @@
1
+ require "ircinch"
2
+
3
+ # Give this bot ops in a channel and it'll auto voice
4
+ # visitors
5
+ #
6
+ # Enable with !autovoice on
7
+ # Disable with !autovoice off
8
+
9
+ class Autovoice
10
+ include Cinch::Plugin
11
+ listen_to :join
12
+ match(/autovoice (on|off)$/)
13
+
14
+ def listen(m)
15
+ unless m.user.nick == bot.nick
16
+ m.channel.voice(m.user) if @autovoice
17
+ end
18
+ end
19
+
20
+ def execute(m, option)
21
+ @autovoice = option == "on"
22
+
23
+ m.reply "Autovoice is now #{@autovoice ? "enabled" : "disabled"}"
24
+ end
25
+ end
26
+
27
+ bot = Cinch::Bot.new do
28
+ configure do |c|
29
+ c.nick = "ircinch_autovoice"
30
+ c.server = "irc.libera.chat"
31
+ c.channels = ["#ircinch-bots"]
32
+ c.verbose = true
33
+ c.plugins.plugins = [Autovoice]
34
+ end
35
+ end
36
+
37
+ bot.start
@@ -0,0 +1,22 @@
1
+ require "ircinch"
2
+
3
+ class SomeCommand
4
+ include Cinch::Plugin
5
+
6
+ set :prefix, /^~/
7
+ match "somecommand"
8
+
9
+ def execute(m)
10
+ m.reply "Successful"
11
+ end
12
+ end
13
+
14
+ bot = Cinch::Bot.new do
15
+ configure do |c|
16
+ c.server = "irc.libera.chat"
17
+ c.channels = ["#ircinch-bots"]
18
+ c.plugins.plugins = [SomeCommand]
19
+ end
20
+ end
21
+
22
+ bot.start
@@ -0,0 +1,38 @@
1
+ require "ircinch"
2
+
3
+ class DiceRoll
4
+ include Cinch::Plugin
5
+
6
+ # [[<repeats>#]<rolls>]d<sides>[<+/-><offset>]
7
+ match(/roll (?:(?:(\d+)#)?(\d+))?d(\d+)(?:([+-])(\d+))?/)
8
+ def execute(m, repeats, rolls, sides, offset_op, offset)
9
+ repeats = repeats.to_i
10
+ repeats = 1 if repeats < 1
11
+ rolls = rolls.to_i
12
+ rolls = 1 if rolls < 1
13
+
14
+ total = 0
15
+
16
+ repeats.times do
17
+ rolls.times do
18
+ score = rand(sides.to_i) + 1
19
+ if offset_op
20
+ score = score.send(offset_op, offset.to_i)
21
+ end
22
+ total += score
23
+ end
24
+ end
25
+
26
+ m.reply "Your dice roll was: #{total}", true
27
+ end
28
+ end
29
+
30
+ bot = Cinch::Bot.new do
31
+ configure do |c|
32
+ c.server = "irc.libera.chat"
33
+ c.channels = ["#ircinch-bots"]
34
+ c.plugins.plugins = [DiceRoll]
35
+ end
36
+ end
37
+
38
+ bot.start