rodbot 0.4.2 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/test.yml +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +12 -0
- data/README.md +23 -20
- data/checksums/rodbot-0.4.3.gem.sha512 +1 -0
- data/checksums/rodbot-0.4.4.gem.sha512 +1 -0
- data/lib/rodbot/env.rb +1 -1
- data/lib/rodbot/plugins/word_of_the_day/README.word_of_the_day.md +27 -0
- data/lib/rodbot/plugins/word_of_the_day/lib/adapter.rb +18 -0
- data/lib/rodbot/plugins/word_of_the_day/lib/adapters/base.rb +23 -0
- data/lib/rodbot/plugins/word_of_the_day/lib/adapters/merriam_webster.rb +30 -0
- data/lib/rodbot/plugins/word_of_the_day/lib/adapters/transparent.rb +50 -0
- data/lib/rodbot/plugins/word_of_the_day/schedule.rb +7 -26
- data/lib/rodbot/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +9 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47f769ca6ea9ef12065fddf0efaf8a0269009654aef1a21fe156a92c07199844
|
4
|
+
data.tar.gz: 6c6fec74a830838687e797dabe1076ec800fddd7f1efb1ea8248a455b80a5819
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64dcb382753c7493bad70e24d4fe4e13c12b0388066f16dfc9c491a7d8869254f03d7b2000f910827f477a1a7eaf07e3b1088c46db13db91389bacc11316b25c
|
7
|
+
data.tar.gz: cce4048655798b61cfa1a3724b264ce4d739673771f4f957f5e7878fe469be871de0d28a7b1ab502abf9aefe57f2d8a08e1fcd0d0eb61438b9ca638db8eac3d7
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/workflows/test.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.3
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,18 @@
|
|
2
2
|
|
3
3
|
Nothing so far
|
4
4
|
|
5
|
+
## 0.4.4
|
6
|
+
|
7
|
+
#### Changes
|
8
|
+
* Adhere to plugin file layout suggestions
|
9
|
+
* Support Ruby 3.3
|
10
|
+
* Honor `APP_ENV` as an alternative to `RODBOT_ENV`
|
11
|
+
|
12
|
+
## 0.4.3
|
13
|
+
|
14
|
+
#### Changes
|
15
|
+
* Add more languages to the word of the day demo plugin
|
16
|
+
|
5
17
|
## 0.4.2
|
6
18
|
|
7
19
|
#### Fixes
|
data/README.md
CHANGED
@@ -17,21 +17,21 @@ Minimalistic yet polyglot framework to build chat bots on top of a Roda backend
|
|
17
17
|
|
18
18
|
## Table of Contents
|
19
19
|
|
20
|
-
[Install](#
|
21
|
-
[Anatomy](#
|
22
|
-
   [App Service](#
|
23
|
-
   [Relay Services](#
|
24
|
-
   [Schedule Service](#
|
25
|
-
[CLI](#
|
20
|
+
[Install](#install) <br>
|
21
|
+
[Anatomy](#anatomy) <br>
|
22
|
+
   [App Service](#app-service) <br>
|
23
|
+
   [Relay Services](#relay-services) <br>
|
24
|
+
   [Schedule Service](#schedule-service) <br>
|
25
|
+
[CLI](#CLI) <br>
|
26
26
|
[Request](#request)<br>
|
27
27
|
[Say](#say)<br>
|
28
|
-
[Routes and Commands](#
|
29
|
-
[Database](#
|
28
|
+
[Routes and Commands](#routes-and-commands) <br>
|
29
|
+
[Database](#database) <br>
|
30
30
|
[Environments](#environments) <br>
|
31
31
|
[Credentials](#credentials) <br>
|
32
|
-
[Plugins](#
|
33
|
-
[Environment Variables](#
|
34
|
-
[Development](#
|
32
|
+
[Plugins](#plugins) <br>
|
33
|
+
[Environment Variables](#environment-variables) <br>
|
34
|
+
[Development](#development) <br>
|
35
35
|
|
36
36
|
## Install
|
37
37
|
|
@@ -53,7 +53,7 @@ rodbot new my_bot
|
|
53
53
|
cd my_bot
|
54
54
|
```
|
55
55
|
|
56
|
-
For the bot to be useful at all, you should choose one of the supported [relay service plugins](#
|
56
|
+
For the bot to be useful at all, you should choose one of the supported [relay service plugins](#plugins). Say, you'd like to interact via Matrix:
|
57
57
|
|
58
58
|
```
|
59
59
|
bundle config set --local with matrix
|
@@ -137,7 +137,7 @@ It loads the following Roda plugins:
|
|
137
137
|
* [unescape_path](http://roda.jeremyevans.net/rdoc/classes/Roda/RodaPlugins/UnescapePath.html)
|
138
138
|
* [render](http://roda.jeremyevans.net/rdoc/classes/Roda/RodaPlugins/Render.html)
|
139
139
|
|
140
|
-
It loads the following Roda
|
140
|
+
It also loads the following Roda extension provided by Rodbot:
|
141
141
|
|
142
142
|
* Shortcut `r.arguments` for `r.params['arguments']`
|
143
143
|
|
@@ -159,7 +159,7 @@ port 12345
|
|
159
159
|
|
160
160
|
#### Commands
|
161
161
|
|
162
|
-
All top level GET requests such as `GET /foobar` are commands and therefore
|
162
|
+
All top level GET requests such as `GET /foobar` are commands and therefore accessible by relays, for instance using `!foobar` on Matrix.
|
163
163
|
|
164
164
|
Responses have to be either of the following content types:
|
165
165
|
|
@@ -168,7 +168,7 @@ Responses have to be either of the following content types:
|
|
168
168
|
|
169
169
|
Please note that the Markdown might get stripped on communication networks which feature only limited or no support for Markdown.
|
170
170
|
|
171
|
-
The response may contain special tags which have to be
|
171
|
+
The response may contain special tags which have to be replaced appropriately by the corresponding **relay service**:
|
172
172
|
|
173
173
|
Tag | Replaced with
|
174
174
|
----|--------------
|
@@ -468,6 +468,8 @@ Rodbot.env.production? # => true
|
|
468
468
|
Rodbot.env.development? # => false
|
469
469
|
```
|
470
470
|
|
471
|
+
You can use the more generic alternative `APP_ENV` as well, however, if `RODBOT_ENV` is defined, it takes precedence over `APP_ENV`.
|
472
|
+
|
471
473
|
## Credentials
|
472
474
|
|
473
475
|
In order not to commit secrets to repositories or environment variables, Rodbot bundles the [dry-credentials](https://rubygems.org/gems/dry-credentials) gem and exposes it via the `rodbot credentials` CLI command. The secrets are then available in your code like `Rodbot.credentials.my_secret` and the encrypted files are written to `config/credentials`.
|
@@ -481,11 +483,12 @@ Rodbot aims to keep its core small and add features via plugins, either built-in
|
|
481
483
|
Name | Dependencies | Description
|
482
484
|
-----|--------------|------------
|
483
485
|
[:matrix](https://rubydoc.info/github/svoop/rodbot/file/lib/rodbot/plugins/matrix/README.matrix.md) | yes | relay service for the [Matrix communication network](https://matrix.org)
|
486
|
+
[:slack](https://rubydoc.info/github/svoop/rodbot/file/lib/rodbot/plugins/slack/README.slack.md) | yes | relay service for the [Slack communication network](https://slack.com)
|
484
487
|
[:otp](https://rubydoc.info/github/svoop/rodbot/file/lib/rodbot/plugins/otp/README.otp.md) | yes | guard commands with one-time passwords
|
485
|
-
[:gitlab_webhook](
|
486
|
-
[:github_webhook](
|
488
|
+
[:gitlab_webhook](https://rubydoc.info/github/svoop/rodbot/file/lib/rodbot/plugins/gitlab_webhook/README.gitlab_webhook.md) | no | event announcements from [GitLab](https://gitlab.com)
|
489
|
+
[:github_webhook](https://rubydoc.info/github/svoop/rodbot/file/lib/rodbot/plugins/github_webhook/README.github_webhook.md) | no | event announcements from [GitHub](https://github.com)
|
487
490
|
[:hal](https://rubydoc.info/github/svoop/rodbot/file/lib/rodbot/plugins/hal/README.hal.md) | no | feel like Dave (demo)
|
488
|
-
[:word_of_the_day](
|
491
|
+
[:word_of_the_day](https://rubydoc.info/github/svoop/rodbot/file/lib/rodbot/plugins/word_of_the_day/README.word_of_the_day.md) | no | word of the day announcements (demo)
|
489
492
|
|
490
493
|
You have to install the corresponding Bundler group in case the plugin depends on extra gems. Here's an example for the `:otp` plugin listed above:
|
491
494
|
|
@@ -601,7 +604,7 @@ end
|
|
601
604
|
|
602
605
|
The `loops` method must returns an array of callables (e.g. a Proc or Method) which will be called when this relay service is started. The loops must trap the `INT` signal.
|
603
606
|
|
604
|
-
Proactive
|
607
|
+
Proactive messages require other parts of Rodbot to forward a message directly. To do so, the relay has to implement a TCP socket. This socket must bind to the IP and port you get from the `bind` method which returns an array like `["localhost", 7201]`.
|
605
608
|
|
606
609
|
For an example, take a look at the [:matrix plugin](https://github.com/svoop/rodbot/tree/main/lib/rodbot/plugins/matrix).
|
607
610
|
|
@@ -637,7 +640,7 @@ For an example, take a look at the [:word_of_the_day plugin](https://github.com/
|
|
637
640
|
|
638
641
|
#### Toolbox
|
639
642
|
|
640
|
-
Before you write a plugin,
|
643
|
+
Before you write a plugin, familiarise yourself with the following bundled helpers:
|
641
644
|
|
642
645
|
* [Rodbot::Refinements](https://www.rubydoc.info/gems/rodbot/Rodbot/Refinements.html) – just a few handy extensions to Ruby core classes
|
643
646
|
* [Rodbot::Memoize](https://www.rubydoc.info/gems/rodbot/Rodbot/Memoize.html) – environment-aware memoization for method return values
|
@@ -0,0 +1 @@
|
|
1
|
+
909cbacb1a78772d5da56bfb4f1ed391fd43e5c9d2abfb347332e7d5933b3cf1afc4ee11cb6fdc1cc5cb61e2f187d3e700f7a66648f8c1facd78201c68e553e2
|
@@ -0,0 +1 @@
|
|
1
|
+
263a706d44c8776c413d3800b455249a7c75ed323dc27932ca57d589e13e7da68bc5eb6351beff4efc3cc0dec32d03d7d9c64ee68bfe739426a0f54eccac1229
|
data/lib/rodbot/env.rb
CHANGED
@@ -27,7 +27,7 @@ module Rodbot
|
|
27
27
|
@root = root ? Pathname(root).realpath : Pathname.pwd
|
28
28
|
@tmp = @root.join('tmp')
|
29
29
|
@gem = Pathname(__dir__).join('..', '..').realpath
|
30
|
-
@current = ENV['RODBOT_ENV']
|
30
|
+
@current = ENV['RODBOT_ENV'] || ENV['APP_ENV']
|
31
31
|
@current = 'development' unless ENVS.include? @current
|
32
32
|
end
|
33
33
|
|
@@ -11,3 +11,30 @@ plugin :word_of_the_day do
|
|
11
11
|
time '10:00'
|
12
12
|
end
|
13
13
|
```
|
14
|
+
|
15
|
+
By default, the English word of the day from Merriam-Webster is used, but you can [select another language from Transparent](https://www.transparent.com/word-of-the-day/):
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
plugin :word_of_the_day do
|
19
|
+
time '10:00'
|
20
|
+
languages %w(French)
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
24
|
+
You can also select more than one language:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
plugin :word_of_the_day do
|
28
|
+
time '10:00'
|
29
|
+
languages %w(English French Swedish)
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Given the above, the word of the day for any given day might look something like this:
|
34
|
+
|
35
|
+
```
|
36
|
+
Word of the day: foobar (English) / foobâr (French) / foobår (Swedish)
|
37
|
+
```
|
38
|
+
|
39
|
+
In case the word of the day is not available, the message will contain the missing language struck through.
|
40
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'adapters/base'
|
4
|
+
require_relative 'adapters/merriam_webster'
|
5
|
+
require_relative 'adapters/transparent'
|
6
|
+
|
7
|
+
module WordOfTheDay
|
8
|
+
class Adapter
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def_delegator :@adapter, :message, :message
|
12
|
+
|
13
|
+
def initialize(language)
|
14
|
+
@language = language
|
15
|
+
@adapter = (language == 'English' ? MerriamWebster : Transparent).new(language)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'httpx'
|
4
|
+
|
5
|
+
module WordOfTheDay
|
6
|
+
class Adapter
|
7
|
+
class Base
|
8
|
+
attr_reader :language
|
9
|
+
|
10
|
+
def initialize(language)
|
11
|
+
@language = language.downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
def message
|
15
|
+
if word
|
16
|
+
"[#{word}](#{url}) (#{language.capitalize})"
|
17
|
+
else
|
18
|
+
"~~#{language.capitalize}~~"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WordOfTheDay
|
4
|
+
class Adapter
|
5
|
+
class MerriamWebster < Base
|
6
|
+
private
|
7
|
+
|
8
|
+
def word
|
9
|
+
html.match(/<h2 class="word-header-txt">(.+?)</)&.captures&.first
|
10
|
+
end
|
11
|
+
|
12
|
+
def url
|
13
|
+
"https://www.merriam-webster.com/word-of-the-day/#{today}"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def today
|
19
|
+
Time.now.strftime('%F')
|
20
|
+
end
|
21
|
+
|
22
|
+
def html
|
23
|
+
case (response = HTTPX.get(url))
|
24
|
+
in { status: 200 } then response.body.to_s
|
25
|
+
else ''
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WordOfTheDay
|
4
|
+
class Adapter
|
5
|
+
class Transparent < Base
|
6
|
+
LANGUAGE_CODES = {
|
7
|
+
'arabic' => 'ar',
|
8
|
+
'chinese' => 'zh',
|
9
|
+
'dutch' => 'nl',
|
10
|
+
'esperanto' => 'esp',
|
11
|
+
'french' => 'fr',
|
12
|
+
'german' => 'de',
|
13
|
+
'irish' => 'ga',
|
14
|
+
'italian' => 'it',
|
15
|
+
'japanese' => 'ja',
|
16
|
+
'latin' => 'la',
|
17
|
+
'polish' => 'pl',
|
18
|
+
'portuguese' => 'pt',
|
19
|
+
'russian' => 'ru',
|
20
|
+
'spanish' => 'es'
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
def word
|
24
|
+
xml.match(/<word>(.+?)</)&.captures&.first
|
25
|
+
end
|
26
|
+
|
27
|
+
def url
|
28
|
+
"https://wotd.transparent.com/widget/?lang=#{language}&date=#{today}"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def today
|
34
|
+
Time.now.strftime('%m-%d-%Y')
|
35
|
+
end
|
36
|
+
|
37
|
+
def language_code
|
38
|
+
LANGUAGE_CODES.fetch(language, language)
|
39
|
+
end
|
40
|
+
|
41
|
+
def xml
|
42
|
+
xml_url = "https://wotd.transparent.com/rss/#{today}-#{language_code}-widget.xml"
|
43
|
+
case (response = HTTPX.get(xml_url))
|
44
|
+
in { status: 200 } then response.body.to_s
|
45
|
+
else ''
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
require 'httpx'
|
4
4
|
|
5
|
+
require_relative 'lib/adapter'
|
6
|
+
|
5
7
|
module Rodbot
|
6
8
|
class Plugins
|
7
9
|
class WordOfTheDay
|
8
10
|
class Schedule
|
9
11
|
def initialize
|
10
|
-
Clockwork.every(1.day, -> { Rodbot.say message }, at: time)
|
12
|
+
Clockwork.every(1.day, -> { Rodbot.say "Word of the day: #{message}" }, at: time)
|
11
13
|
end
|
12
14
|
|
13
15
|
private
|
@@ -16,36 +18,15 @@ module Rodbot
|
|
16
18
|
Rodbot.config(:plugin, :word_of_the_day, :time) || '12:00'
|
17
19
|
end
|
18
20
|
|
19
|
-
def
|
20
|
-
Rodbot
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
class Today
|
26
|
-
def initialize
|
27
|
-
@response = HTTPX.with(timeout: { request_timeout: 60 }).get('https://www.merriam-webster.com/word-of-the-day')
|
21
|
+
def languages
|
22
|
+
Rodbot.config(:plugin, :word_of_the_day, :languages) || %w(english)
|
28
23
|
end
|
29
24
|
|
30
25
|
def message
|
31
|
-
|
32
|
-
"Word of the day: [#{word}](#{url})"
|
33
|
-
else
|
34
|
-
"Sorry, there was a problem fetching the word of the day."
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def word
|
41
|
-
@response.body.to_s.match(/<h2 class="word-header-txt">(.+?)</).captures.first
|
42
|
-
end
|
43
|
-
|
44
|
-
def url
|
45
|
-
@response.body.to_s.match(/<meta property="og:url" content="(.+?)"/).captures.first
|
26
|
+
languages.map { ::WordOfTheDay::Adapter.new(_1).message }.compact.join(' / ')
|
46
27
|
end
|
47
28
|
end
|
48
|
-
|
49
29
|
end
|
50
30
|
end
|
51
31
|
end
|
32
|
+
|
data/lib/rodbot/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Schwyn
|
@@ -27,7 +27,7 @@ cert_chain:
|
|
27
27
|
k/QvZU05f6HMYBrPogJgIzHC/C5N/yeE4BVEuBDn+10Zb1iu3aDk8sd0uMgukCY8
|
28
28
|
TUmlP5A6NeGdeDJIoLgromAKs+nvI7TWzhQq9ODs51XhxgUFRCvBqUTpjTQigw==
|
29
29
|
-----END CERTIFICATE-----
|
30
|
-
date:
|
30
|
+
date: 2024-02-12 00:00:00.000000000 Z
|
31
31
|
dependencies:
|
32
32
|
- !ruby/object:Gem::Dependency
|
33
33
|
name: zeitwerk
|
@@ -455,6 +455,8 @@ files:
|
|
455
455
|
- checksums/rodbot-0.4.0.gem.sha512
|
456
456
|
- checksums/rodbot-0.4.1.gem.sha512
|
457
457
|
- checksums/rodbot-0.4.2.gem.sha512
|
458
|
+
- checksums/rodbot-0.4.3.gem.sha512
|
459
|
+
- checksums/rodbot-0.4.4.gem.sha512
|
458
460
|
- doc/rodbot.afphoto
|
459
461
|
- doc/rodbot.avif
|
460
462
|
- exe/rodbot
|
@@ -500,6 +502,10 @@ files:
|
|
500
502
|
- lib/rodbot/plugins/slack/README.slack.md
|
501
503
|
- lib/rodbot/plugins/slack/relay.rb
|
502
504
|
- lib/rodbot/plugins/word_of_the_day/README.word_of_the_day.md
|
505
|
+
- lib/rodbot/plugins/word_of_the_day/lib/adapter.rb
|
506
|
+
- lib/rodbot/plugins/word_of_the_day/lib/adapters/base.rb
|
507
|
+
- lib/rodbot/plugins/word_of_the_day/lib/adapters/merriam_webster.rb
|
508
|
+
- lib/rodbot/plugins/word_of_the_day/lib/adapters/transparent.rb
|
503
509
|
- lib/rodbot/plugins/word_of_the_day/schedule.rb
|
504
510
|
- lib/rodbot/rack.rb
|
505
511
|
- lib/rodbot/refinements.rb
|
@@ -574,7 +580,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
574
580
|
- !ruby/object:Gem::Version
|
575
581
|
version: '0'
|
576
582
|
requirements: []
|
577
|
-
rubygems_version: 3.
|
583
|
+
rubygems_version: 3.5.6
|
578
584
|
signing_key:
|
579
585
|
specification_version: 4
|
580
586
|
summary: Minimalistic framework to build chat bots on top of a Roda backend
|
metadata.gz.sig
CHANGED
Binary file
|