rodbot 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f32541e2113ba1425a81da6374fc3353d578ba5fd0b9b1905f5eeae95fab0180
4
- data.tar.gz: ad474b634ffa0fb96fe23cb7602b9de81df2367636cb0327cce578901237615d
3
+ metadata.gz: 0bf9f1ee8fd09d93797a5ba276aa6fec09be9620e540f118240525c73a6fda6b
4
+ data.tar.gz: b36fdd850e38596aaf7da805107d0cbbbcb46de823e76cad151676fbcc14dd9c
5
5
  SHA512:
6
- metadata.gz: 45fc1790e2d559610ebca8ce834bcaf245f6fb922e18edd56d55f2ee307fbf2daffe2db10b507efc1944d27e4c562577108013c48186e6a743bf2e5cd1dfe67b
7
- data.tar.gz: 9787f11da1619228e571644be1643e66d3b4b65f46ed14d2782b9b20a73b35f98f33bce02bd26c5dd7677e377e09874945412155cca9e55e220363cd41776e4a
6
+ metadata.gz: 37a9346640167dc0543d9361b1d53789e363d27e6c57129fde777897f7e8ec3fff51e735129accdfaf8caee943a29fa19daae2ea5acdab6023d11d7dbf4ebaaa
7
+ data.tar.gz: 6fec833877807a7b6dc85e19682c5bf88172ad2ff32ce0d0c5e83565cecbf60e54517f1aaeda451e17ee610f5338969bd05ffe5a8c002b649c28c3e35f25949b
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  Nothing so far
4
4
 
5
+ ## 0.3.2
6
+
7
+ #### Additions
8
+ * Simple /healthz route e.g. for deployments on render.com
9
+ * Deploy templates for render.com
10
+
11
+ #### Changes
12
+ * Switch from httparty to httpx
13
+
5
14
  ## 0.3.1
6
15
 
7
16
  #### Fixes
data/README.md CHANGED
@@ -302,13 +302,13 @@ overmind start
302
302
 
303
303
  ## Request
304
304
 
305
- To query the **app service**, you can either use the bundled [HTTParty](https://rubygems.org/gems/httparty) gem or the following convenience wrapper:
305
+ To query the **app service**, you can either use the bundled [HTTPX](https://rubygems.org/gems/httpx) gem or the following convenience wrapper:
306
306
 
307
307
  ```ruby
308
- response = Rodbot.request('/time', query: { zone: 'UTC' })
308
+ response = Rodbot.request('/time', params: { zone: 'UTC' })
309
309
  ```
310
310
 
311
- This uses the default `method: :get` and the default `timeout: 10` seconds, it returns an instance of [HTTParty::Response](https://www.rubydoc.info/gems/httparty/HTTParty/Response):
311
+ This uses the default `method: :get` and the default `timeout: 10` seconds, it returns an instance of [HTTPX::Response](https://www.rubydoc.info/gems/httpx/HTTPX/Response):
312
312
 
313
313
  ```ruby
314
314
  response.code # => 200
@@ -0,0 +1 @@
1
+ 3704bffdb0e27a9544bbdc7538051a9253eeefe81bbbfeea14e1f486e36c701ae200a1b6da151306a96d8e8ccb154236cf18ce4cb27821cd42cbc165a6bc79e6
@@ -22,7 +22,7 @@ module Rodbot
22
22
  class Generator
23
23
 
24
24
  # Glob to filter relevant template files
25
- GLOB = "**/{*,.ruby-version,.gitignore,.keep}"
25
+ GLOB = "**/{*,.ruby-version*,.gitignore,.keep}"
26
26
 
27
27
  # Colors used by +info+ to color part of the output
28
28
  TAG_COLORS = {
@@ -38,8 +38,9 @@ module Rodbot
38
38
 
39
39
  # Print the interpolated template to STDOUT
40
40
  def display
41
+ puts
41
42
  each_template_path do |template_path, target_path, content|
42
- puts "# #{target_path}", (content || template_path.read)
43
+ puts "### #{target_path} ###", (content || template_path.read), nil
43
44
  end
44
45
  end
45
46
 
@@ -71,9 +71,7 @@ module Rodbot
71
71
 
72
72
  def on_message(message)
73
73
  if message.content[:msgtype] == 'm.text' && message.content[:body].start_with?('!')
74
- html = 'pong' if message.content[:body] == '!ping'
75
- html ||= reply_to(message)
76
- room.send_html(html)
74
+ room.send_html(reply_to(message))
77
75
  end
78
76
  end
79
77
 
@@ -42,7 +42,11 @@ module Rodbot
42
42
  body = remote.gets("\x04")
43
43
  remote.close
44
44
  body.force_encoding('UTF-8')
45
- client.web_client.chat_postMessage(channel: channel_id, text: body, as_user: true)
45
+ client.web_client.chat_postMessage(
46
+ channel: channel_id,
47
+ text: md_to_slack_text(body),
48
+ as_user: true
49
+ )
46
50
  end
47
51
  end
48
52
  end
@@ -56,23 +60,34 @@ module Rodbot
56
60
 
57
61
  def on_message(message)
58
62
  if message.text.start_with?('!')
59
- md = 'pong' if message.text == '!ping'
60
- md ||= reply_to(message)
61
- client.web_client.chat_postMessage(channel: message.channel, text: md, as_user: true)
63
+ client.web_client.chat_postMessage(
64
+ channel: message.channel,
65
+ text: reply_to(message),
66
+ as_user: true
67
+ )
62
68
  end
63
69
  end
64
70
 
65
71
  def reply_to(message)
66
72
  command(*message.text[1..].split(/\s+/, 2)).
67
- psub(placeholders(message.user))
73
+ psub(placeholders(message.user)).
74
+ then { md_to_slack_text(_1) }
68
75
  end
69
76
 
77
+ # @see https://api.slack.com/reference/surfaces/formatting
70
78
  def placeholders(sender)
71
79
  {
72
80
  sender: "<@#{sender}>"
73
81
  }
74
82
  end
75
83
 
84
+ # @see https://api.slack.com/reference/surfaces/formatting
85
+ def md_to_slack_text(md)
86
+ md.
87
+ gsub(/\[(.+?)\]\((.+?)\)/, '<\2|\1>'). # convert links
88
+ gsub(/^\s*[*-]\s+/, '• ') # convert bullet lists
89
+ end
90
+
76
91
  end
77
92
  end
78
93
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'httparty'
3
+ require 'httpx'
4
4
 
5
5
  module Rodbot
6
6
  class Plugins
@@ -24,11 +24,11 @@ module Rodbot
24
24
 
25
25
  class Today
26
26
  def initialize
27
- @response = HTTParty.get('https://www.merriam-webster.com/word-of-the-day')
27
+ @response = HTTPX.with(timeout: { request_timeout: 60 }).get('https://www.merriam-webster.com/word-of-the-day')
28
28
  end
29
29
 
30
30
  def message
31
- if @response.success?
31
+ if @response.status == 200
32
32
  "Word of the day: [#{word}](#{url})"
33
33
  else
34
34
  "Sorry, there was a problem fetching the word of the day."
@@ -38,11 +38,11 @@ module Rodbot
38
38
  private
39
39
 
40
40
  def word
41
- @response.body.match(/<h2 class="word-header-txt">(.+?)</).captures.first
41
+ @response.body.to_s.match(/<h2 class="word-header-txt">(.+?)</).captures.first
42
42
  end
43
43
 
44
44
  def url
45
- @response.body.match(/<meta property="og:url" content="(.+?)"/).captures.first
45
+ @response.body.to_s.match(/<meta property="og:url" content="(.+?)"/).captures.first
46
46
  end
47
47
  end
48
48
 
data/lib/rodbot/rack.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- require 'httparty'
3
+ require 'httpx'
4
4
 
5
5
  using Rodbot::Refinements
6
6
 
@@ -36,12 +36,11 @@ module Rodbot
36
36
  # Send request to the app service
37
37
  #
38
38
  # @param path [String] path e.g. +/help+
39
- # @param query [Hash] query hash e.g. +{ search: 'foobar' }+
40
- # @param method [Symbol, String] HTTP method
39
+ # @param params [Hash] params hash e.g. +{ search: 'foobar' }+
41
40
  # @param timeout [Integer] max seconds to wait for response
42
- # @return [HTTParty::Response]
43
- def request(path, query: {}, method: :get, timeout: 10)
44
- HTTParty.send(method, Rodbot::Services::App.url.uri_concat(path), query: query, timeout: timeout)
41
+ # @return [HTTPX::Response]
42
+ def request(path, params: {}, timeout: 10)
43
+ HTTPX.with(timeout: { request_timeout: timeout }).get(Rodbot::Services::App.url.uri_concat(path), params: params)
45
44
  end
46
45
 
47
46
  end
data/lib/rodbot/relay.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'digest'
4
4
  require 'socket'
5
- require 'httparty'
5
+ require 'httpx'
6
6
 
7
7
  module Rodbot
8
8
 
@@ -84,15 +84,28 @@ module Rodbot
84
84
  ]
85
85
  end
86
86
 
87
- # Perform the command on the app using a GET request
87
+ # Perform the built-in command or fall back to the app using +request+
88
88
  #
89
89
  # @param command [String] command to perform
90
90
  # @param argument [String, nil] optional arguments
91
91
  # @return [String] response as Markdown
92
92
  def command(command, argument=nil)
93
- response = Rodbot.request(command, query: { argument: argument })
94
- case response.code
95
- when 200 then response.body
93
+ case command
94
+ when 'ping' then 'pong'
95
+ when 'version' then "rodbot-#{Rodbot::VERSION}"
96
+ else request(command, argument)
97
+ end
98
+ end
99
+
100
+ # Perform the command on the app using a GET request
101
+ #
102
+ # @param command [String] command to perform
103
+ # @param argument [String, nil] optional arguments
104
+ # @return [String] response as Markdown
105
+ def request(command, argument=nil)
106
+ response = Rodbot.request(command, params: { argument: argument })
107
+ case response.status
108
+ when 200 then response.body.to_s
96
109
  when 404 then "[[SENDER]] I don't know what do do with `!#{command}`. 🤔"
97
110
  else fail
98
111
  end
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  require 'readline'
4
- require 'httparty'
4
+ require 'httpx'
5
5
  require 'pastel'
6
6
  require 'tty-markdown'
7
7
 
@@ -16,6 +16,7 @@ module Rodbot
16
16
  # @param raw [Boolean] whether to display raw Markdown
17
17
  def initialize(sender, raw: false)
18
18
  @sender, @raw = sender, raw
19
+ @relay = Rodbot::Relay.new
19
20
  @pastel = Pastel.new
20
21
  end
21
22
 
@@ -33,17 +34,7 @@ module Rodbot
33
34
  def reply_to(message)
34
35
  return "(no command given)" unless message.match?(/^!/)
35
36
  command, argument = message[1..].split(/\s+/, 2)
36
- body = begin
37
- response = Rodbot.request(command, query: { argument: argument })
38
- case response.code
39
- when 200 then response.body
40
- when 404 then "[[SENDER]] I've never heard of `!#{command}`, try `!help` instead. 🤔"
41
- else fail
42
- end
43
- rescue
44
- "[[SENDER]] I'm having trouble talking to the app. 💣"
45
- end
46
- text_for body.psub(placeholders)
37
+ text_for @relay.send(:command, command, argument).psub(placeholders)
47
38
  end
48
39
 
49
40
  def placeholders
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rodbot
4
- VERSION = "0.3.1"
4
+ VERSION = "0.3.2"
5
5
  end
@@ -4,7 +4,7 @@ x-defaults: &defaults
4
4
  build:
5
5
  context: .
6
6
  dockerfile_inline: |
7
- FROM ruby:3.2-alpine
7
+ FROM ruby:[%= RUBY_VERSION.sub(/\.\d+$/, '') %]-alpine
8
8
  RUN apk update && apk --no-cache add build-base
9
9
  ENV RODBOT_ENV="production"
10
10
  ENV RACK_ENV="production"
@@ -4,7 +4,7 @@ x-defaults: &defaults
4
4
  build:
5
5
  context: .
6
6
  dockerfile_inline: |
7
- FROM ruby:3.2-alpine
7
+ FROM ruby:[%= RUBY_VERSION.sub(/\.\d+$/, '') %]-alpine
8
8
  RUN apk update && apk --no-cache add build-base
9
9
  ENV RODBOT_ENV="production"
10
10
  ENV RACK_ENV="production"
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ echo "--> Checking environment"
5
+ echo "RODBOT_ENV: $RODBOT_ENV"
6
+ echo "RODBOT_PLUGINS: $RODBOT_PLUGINS"
7
+
8
+ echo "--> Installing bundle"
9
+ bundle config set with $RODBOT_PLUGINS
10
+ bundle install
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+
3
+ export RODBOT_APP_HOST=0.0.0.0
4
+ bundle exec rodbot start
5
+ sleep infinity
@@ -0,0 +1,19 @@
1
+ services:
2
+ - type: web
3
+ name: bot
4
+ domains:
5
+ - bot.example.com # TODO: use a domain name of your own
6
+ runtime: ruby
7
+ buildCommand: render-build.sh
8
+ startCommand: render-start.sh
9
+ healthCheckPath: /healthz
10
+ autoDeploy: true
11
+ envVars:
12
+ - key: PORT
13
+ value: 7200
14
+ - key: PRODUCTION_CREDENTIALS_KEY
15
+ value:
16
+ - key: RODBOT_ENV
17
+ value: production
18
+ - key: RODBOT_PLUGINS
19
+ value: matrix # TODO: update space separated list of plugins
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ echo "--> Checking environment"
5
+ echo "RODBOT_ENV: $RODBOT_ENV"
6
+ echo "RODBOT_PLUGINS: $RODBOT_PLUGINS"
7
+
8
+ echo "--> Installing bundle"
9
+ bundle config set with $RODBOT_PLUGINS
10
+ bundle install
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bash
2
+
3
+ case 1 in
4
+ "app")
5
+ export RODBOT_APP_HOST=0.0.0.0
6
+ bundle exec rodbot start app
7
+ ;;
8
+ "relay")
9
+ bundle exec rodbot start relay
10
+ ;;
11
+ "schedule")
12
+ bundle exec rodbot start schedule
13
+ ;;
14
+ *)
15
+ echo "Invalid argument"
16
+ exit 1
17
+ ;;
18
+ esac
@@ -0,0 +1,42 @@
1
+ services:
2
+ - type: web
3
+ name: bot-app
4
+ domains:
5
+ - bot.example.com # TODO: use a domain name of your own
6
+ runtime: ruby
7
+ buildCommand: render-build.sh
8
+ startCommand: render-start.sh app
9
+ healthCheckPath: /healthz
10
+ autoDeploy: true
11
+ envVars:
12
+ - fromGroup: bot
13
+ - key: PORT
14
+ value: 7200
15
+ - type: worker
16
+ name: bot-relay
17
+ runtime: ruby
18
+ buildCommand: render-build.sh
19
+ startCommand: render-start.sh relay
20
+ autoDeploy: true
21
+ envVars:
22
+ - fromGroup: bot
23
+ - type: worker
24
+ name: bot-schedule
25
+ runtime: ruby
26
+ buildCommand: render-build.sh
27
+ startCommand: render-start.sh schedule
28
+ autoDeploy: true
29
+ envVars:
30
+ - fromGroup: bot
31
+
32
+ envVarGroups:
33
+ - name: bot
34
+ envVars:
35
+ - key: PRODUCTION_CREDENTIALS_KEY
36
+ value:
37
+ - key: RODBOT_ENV
38
+ value: production
39
+ - key: RODBOT_PLUGINS
40
+ value: "matrix" # TODO: update space separated list of plugins
41
+ - key: RODBOT_APP_URL
42
+ value: https://bot.example.com # TODO: use the above service domain name
@@ -0,0 +1 @@
1
+ [%= RUBY_VERSION.sub(/\.\d+$/, '') %]
@@ -7,5 +7,6 @@ class App < Roda
7
7
  r.root { view :root }
8
8
  end
9
9
 
10
+ run :healthz, Routes::Healthz
10
11
  run :help, Routes::Help
11
12
  end
@@ -0,0 +1,15 @@
1
+ module Routes
2
+ class Healthz < App
3
+
4
+ route do |r|
5
+
6
+ # GET /healthz
7
+ r.root do
8
+ response['Content-Type'] = 'text/plain; charset=utf-8'
9
+ 'alive and kicking'
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
data/rodbot.gemspec CHANGED
@@ -46,7 +46,7 @@ Gem::Specification.new do |spec|
46
46
  spec.add_runtime_dependency 'dry-credentials', '~> 0'
47
47
  spec.add_runtime_dependency 'tty-markdown', '~> 0'
48
48
  spec.add_runtime_dependency 'pastel', '~> 0'
49
- spec.add_runtime_dependency 'httparty', '~> 0'
49
+ spec.add_runtime_dependency 'httpx', '~> 1'
50
50
  spec.add_runtime_dependency 'puma', '~> 6', '>= 6.2'
51
51
  spec.add_runtime_dependency 'roda', '~> 3'
52
52
  spec.add_runtime_dependency 'tilt', '~> 2'
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.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Schwyn
@@ -29,7 +29,7 @@ cert_chain:
29
29
  kAyiRqgxF4dJviwtqI7mZIomWL63+kXLgjOjMe1SHxfIPo/0ji6+r1p4KYa7o41v
30
30
  fwIwU1MKlFBdsjkd
31
31
  -----END CERTIFICATE-----
32
- date: 2023-10-11 00:00:00.000000000 Z
32
+ date: 2023-10-18 00:00:00.000000000 Z
33
33
  dependencies:
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: zeitwerk
@@ -102,19 +102,19 @@ dependencies:
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  - !ruby/object:Gem::Dependency
105
- name: httparty
105
+ name: httpx
106
106
  requirement: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '1'
111
111
  type: :runtime
112
112
  prerelease: false
113
113
  version_requirements: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '1'
118
118
  - !ruby/object:Gem::Dependency
119
119
  name: puma
120
120
  requirement: !ruby/object:Gem::Requirement
@@ -451,6 +451,7 @@ files:
451
451
  - checksums/rodbot-0.2.0.gem.sha512
452
452
  - checksums/rodbot-0.3.0.gem.sha512
453
453
  - checksums/rodbot-0.3.1.gem.sha512
454
+ - checksums/rodbot-0.3.2.gem.sha512
454
455
  - doc/rodbot.afphoto
455
456
  - doc/rodbot.avif
456
457
  - exe/rodbot
@@ -509,12 +510,17 @@ files:
509
510
  - lib/templates/deploy/docker/compose.yaml.gerb
510
511
  - lib/templates/deploy/procfile-split/Procfile.gerb
511
512
  - lib/templates/deploy/procfile/Procfile.gerb
513
+ - lib/templates/deploy/render-split/render-build.sh
514
+ - lib/templates/deploy/render-split/render-start.sh
512
515
  - lib/templates/deploy/render-split/render.yaml.gerb
516
+ - lib/templates/deploy/render/render-build.sh
517
+ - lib/templates/deploy/render/render-start.sh
513
518
  - lib/templates/deploy/render/render.yaml.gerb
514
519
  - lib/templates/new/.gitignore
515
- - lib/templates/new/.ruby-version
520
+ - lib/templates/new/.ruby-version.gerb
516
521
  - lib/templates/new/README.md
517
522
  - lib/templates/new/app/app.rb
523
+ - lib/templates/new/app/routes/healthz.rb
518
524
  - lib/templates/new/app/routes/help.rb
519
525
  - lib/templates/new/app/views/layout.erb
520
526
  - lib/templates/new/app/views/root.erb
@@ -563,7 +569,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
563
569
  - !ruby/object:Gem::Version
564
570
  version: '0'
565
571
  requirements: []
566
- rubygems_version: 3.4.20
572
+ rubygems_version: 3.4.21
567
573
  signing_key:
568
574
  specification_version: 4
569
575
  summary: Minimalistic framework to build chat bots on top of a Roda backend
metadata.gz.sig CHANGED
Binary file
@@ -1 +0,0 @@
1
- 3.2