revoltrb 0.0.2 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a423864396d60b962eebc129b294b03f79e812d9b95eb2511f7c4bb2f07cefc
4
- data.tar.gz: 142aba7edfce9961c36ff0ab2eaa70eced3e1a55ec64e2f2ae32db345fc30347
3
+ metadata.gz: e1833048a57c6bd197930741b0d788bd6b416c8ced680b5874e90d0158e8dfdb
4
+ data.tar.gz: 24a8b1bc143b4e3287c46d066b103abc854905293994ae2f4f35ce1b75ed4f1d
5
5
  SHA512:
6
- metadata.gz: 1c9fb2983e8cba19aa607218619f5b1c7fc8bc712bba8a3030fb6e460060d60ed89a0493c35329668148542156f0591a5d2bbdf6ed0e1d1f5cd799b547293972
7
- data.tar.gz: 8bf120f58d994b0a9617844acbf0b86e0491b85965a228e50e6430ba5402c80ef1c0f22585e9d22558711f4b92255942ca0bca89db9411da924d7523cb4a43f7
6
+ metadata.gz: 0b5d133303eb069a69c0ee5b09bdf0876256650dfe813cfd1590a4e5a031fa6f0f7df7ab51d2857f6557e60c4e84677eceab860dba6f2ccf7f6d540fe91e5778
7
+ data.tar.gz: b2dbd9bd8efd009f64d33471a332841513dcc57d45928e742d335a7ffad4ec669b157e41b5dc0f75d01cc6a1860350836214cd00579ef42a59b6940ce0698dfb
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # revoltrb
2
2
 
3
+ ![revolt-api](https://img.shields.io/npm/v/revolt-api?label=Revolt%20API)
4
+
3
5
  Revoltrb is a Ruby package (a.k.a. Gem) that allows you to make Revolt.chat bots using the Ruby programming language. This package (a.k.a. Gem) is not officially endorsed by Revolt.chat amd this is not an official Revolt.chat product.
4
6
 
5
7
  You need Ruby 3.0 or newer in order to use this package (Ruby 3.2 or newer is recommended)
@@ -11,7 +13,6 @@ You need Ruby 3.0 or newer in order to use this package (Ruby 3.2 or newer is re
11
13
 
12
14
  This list contains a list of things that I know is broken and gotta fix. Contributing will be super helpful.
13
15
 
14
- - Fix obtaining server information
15
16
  - Fix reactions support
16
17
 
17
18
  ## Setup
@@ -20,10 +21,10 @@ You can install Revoltrb through several methods:
20
21
 
21
22
  #### Method 1: Install from rubygems.org (Bundler)
22
23
 
23
- Add the following to your Gemfile file and run the "bundle install" command:
24
+ Add the following to your Gemfile file and run the "[bundle install](https://rubygems.org/gems/revoltrb)" command:
24
25
 
25
26
  ```ruby
26
- gem 'discordrb'
27
+ gem 'revoltrb'
27
28
  ```
28
29
 
29
30
  #### Method 2: Install via Git
@@ -38,6 +39,8 @@ gem 'revoltrb', git: 'https://gitlab.com/roxannewolf/revoltrb'
38
39
 
39
40
  If you encounter the "Exited with code: 16 output:Ignoring debug-1.7.1 because its extensions are not built." error, most likely, there is something wrong with the parser package. This can be fixed by installing parser manually (gem install parser)
40
41
 
42
+ On the v0.0.x releases, you would need to install websocket-client-simple from your Gemfile. Now this is included within the package as of v0.1.0
43
+
41
44
  ## Usage
42
45
 
43
46
  You can make a simple bot like this:
@@ -57,22 +60,7 @@ bot.on_message do |message|
57
60
  end
58
61
  end
59
62
 
60
- begin
61
- unless bot.login
62
- puts "Bot failed to log in. Exiting."
63
- exit(1)
64
- end
65
- puts "Bot is ONLINE and READY! Press Ctrl+C to stop."
66
- bot.instance_variable_get(:@websocket_thread).join
67
- rescue Interrupt
68
- puts "\nCtrl+C detected. Shutting down bot"
69
- rescue => e
70
- puts "An unhandled error occurred in the main script loop: #{e.message}"
71
- puts e.backtrace.join("\n")
72
- ensure
73
- bot.stop
74
- puts "Bot process ended."
75
- end
63
+ bot.run
76
64
  ```
77
65
 
78
66
  or you can make a bot with full prefix commands like this:
@@ -87,22 +75,22 @@ bot.command(:ping) do |message, args|
87
75
  bot.send_message(channel_id, text: "Pong! You sent: #{args.join(' ')}")
88
76
  end
89
77
 
90
- begin
91
- unless bot.login
92
- puts "Bot failed to log in. Exiting."
93
- exit(1)
94
- end
95
- puts "Bot is online and running. Press Ctrl+C to stop."
96
- bot.instance_variable_get(:@websocket_thread).join
97
- rescue Interrupt
98
- puts "\nCtrl+C detected. Shutting down bot gracefully..."
99
- rescue => e
100
- puts "An unhandled error occurred in the main script loop: #{e.message}"
101
- puts e.backtrace.join("\n")
102
- ensure
103
- bot.stop
104
- puts "Bot process ended."
105
- end
78
+ bot.run
79
+ ```
80
+
81
+ Webhook example:
82
+
83
+ ```ruby
84
+ require 'revoltrb'
85
+ # Webhook url should look like this: https://beta.revolt.chat/api/webhooks/<WEBHOOK_ID>/<WEBHOOK_TOKEN>
86
+ # Webhook urls can be obtained and created through beta.revolt.chat
87
+ WEBHOOK_ID = ''
88
+ WEBHOOK_TOKEN = ''
89
+ webhook = RevoltWebhooks::Webhook.new(WEBHOOK_ID, WEBHOOK_TOKEN)
90
+
91
+ webhook.send_message(
92
+ content: "Revoltrb webhook message content",
93
+ )
106
94
  ```
107
95
 
108
96
  ## Support and Help
data/lib/revoltrb/bot.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  # lib/revoltrb/bot.rb
2
-
3
2
  require 'json'
4
3
  require 'net/http'
5
4
  require 'websocket-client-simple' # This is required for WebSocket communication
@@ -7,6 +6,7 @@ require 'thread'
7
6
  require 'time'
8
7
  require_relative 'debuglogger'
9
8
  require_relative 'request_queue'
9
+ require_relative 'webhooks'
10
10
 
11
11
  module Revoltrb
12
12
  class RevoltBot
@@ -25,7 +25,7 @@ module Revoltrb
25
25
  ':-1:' => '👎'
26
26
  }.freeze
27
27
 
28
- attr_reader :token, :user_id, :bot_name, :servers, :prefix, :bot_owner_id, :bot_discriminator, :bot_discoverable, :bot_creation_date
28
+ attr_reader :token, :user_id, :bot_name, :servers, :prefix, :bot_owner_id, :bot_discriminator, :bot_discoverable, :bot_creation_date, :webhooks
29
29
  attr_accessor :websocket_url, :api_url, :cdn_url
30
30
  # Initializes the bot with the provided token, API endpoints, and configuration.
31
31
  def initialize(token, api_url: 'https://api.revolt.chat', websocket_url: 'wss://app.revolt.chat/events', cdn_url: 'https://cdn.revoltusercontent.com', prefix: nil, debuglogs: false, selfbot: false)
@@ -48,6 +48,7 @@ module Revoltrb
48
48
  @ready_event_received = false
49
49
  @logger = Revoltrb::DebugLogger.new(debuglogs)
50
50
  @request_queue = Revoltrb::RequestQueue.new(500)
51
+ @webhooks = Revoltrb::Webhooks.new(api_url, @logger, token, selfbot)
51
52
 
52
53
  @prefix = "!"
53
54
  @prefix = prefix if prefix
@@ -96,18 +97,15 @@ module Revoltrb
96
97
  @bot_analytics = nil
97
98
  @bot_creation_date = Time.at(bot_user_data&.[]('created_at').to_i / 1000) rescue nil
98
99
  if @user_id.nil? || @bot_name.nil?
99
- @logger.debug "Error: Essential properties (_id, username) missing or nil in API response from /users/@me."
100
- @logger.debug "Please inspect the 'Response Body' above for unexpected format."
100
+ @logger.debug "AN ERROR HAS OCCURED: Essential properties (_id, username) missing or nil in API response from /users/@me. Please inspect the 'Response Body' above for unexpected format."
101
101
  return false
102
102
  end
103
103
 
104
104
  @logger.debug "Successfully identified as #{@bot_name} (ID: #{@user_id}) via REST API."
105
- @logger.debug "Bot owner ID after parsing: #{@bot_owner_id}"
106
- @logger.debug "Owner ID: #{@bot_owner_id}, Discoverable: #{@bot_discoverable.inspect}, Created: #{@bot_creation_date}"
105
+ @logger.debug "Bot Owner ID: #{@bot_owner_id}, Owner ID: #{@bot_owner_id}, Discoverable: #{@bot_discoverable.inspect}, Created: #{@bot_creation_date}"
107
106
  else
108
- @logger.debug "Initial REST API call failed: #{res.message} (Code: #{res.code})"
109
- @logger.debug "Response Body: #{res.body}"
110
- @logger.debug "Please check your bot token. Cannot proceed with WebSocket connection."
107
+ @logger.debug "AN ERROR HAS OCCURED: Initial REST API call failed.... #{res.message} (Code: #{res.code})"
108
+ @logger.debug "Please check your bot token. Cannot proceed with WebSocket connection. Response Body: #{res.body}"
111
109
  return false
112
110
  end
113
111
  # Step 2: Connect to the WebSocket
@@ -116,6 +114,60 @@ module Revoltrb
116
114
  @request_queue.start_processing
117
115
  true
118
116
  end
117
+ def run
118
+ begin
119
+ unless login
120
+ puts "Bot failed to log in. Exiting."
121
+ exit(1)
122
+ end
123
+ puts "Bot is online and running. Press Ctrl+C to stop."
124
+ @websocket_thread.join
125
+ rescue Interrupt
126
+ puts "\nCtrl+C detected. Shutting down bot gracefully..."
127
+ rescue => e
128
+ puts "An unhandled error occurred in the main script loop: #{e.message}"
129
+ puts e.backtrace.join("\n")
130
+ ensure
131
+ stop
132
+ puts "Bot process ended."
133
+ end
134
+ end
135
+
136
+ def set_presence(status)
137
+ valid_statuses = ['Online', 'Idle', 'Dnd', 'Focus', 'Invisible']
138
+ unless valid_statuses.include?(status)
139
+ @logger.debug "AN ERROR HAS OCCURED: Invalid status '#{status}'. Must be one of the following choices: #{valid_statuses.join(', ')}."
140
+ return false
141
+ end
142
+
143
+ @logger.debug "Attempting to set bot presence to '#{status}'."
144
+ uri = URI("#{@api_url}/users/@me")
145
+ req = Net::HTTP::Patch.new(uri)
146
+ _add_auth_header(req)
147
+ req['Content-Type'] = 'application/json'
148
+ payload = {
149
+ status: {
150
+ presence: status
151
+ }
152
+ }
153
+ req.body = payload.to_json
154
+ res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
155
+ http.request(req)
156
+ end
157
+
158
+ if res.is_a?(Net::HTTPSuccess)
159
+ @logger.debug "BOT: Presence has been changed to '#{status}'."
160
+ true
161
+ else
162
+ @logger.debug "AN ERROR HAS OCCURED: Failed to update presence. Response: #{res.message} (Code: #{res.code})"
163
+ @logger.debug "Response Body: #{res.body}"
164
+ false
165
+ end
166
+ rescue => e
167
+ @logger.debug "AN ERROR HAS OCCURED: Error setting presence: #{e.message}"
168
+ @logger.debug e.backtrace.join("\n")
169
+ false
170
+ end
119
171
 
120
172
  def connect_websocket
121
173
  if @websocket && @websocket.open? && @running
@@ -126,7 +178,7 @@ module Revoltrb
126
178
  @logger.debug "Connecting to WebSocket: #{@websocket_url}"
127
179
  ws_url_with_token = "#{@websocket_url}?token=#{@token}"
128
180
  bot_instance = self
129
- thread_logger = @logger
181
+ thread_logger = @logger
130
182
 
131
183
  @websocket_thread = Thread.new do
132
184
  begin
@@ -186,7 +238,7 @@ module Revoltrb
186
238
  @last_heartbeat_sent = Time.now.to_i
187
239
  end
188
240
  rescue OpenSSL::SSL::SSLError => e
189
- @logger.debug "AN ERROR HAS OCCURED: Error sending heartbeat (SSL): #{e.message}"
241
+ @logger.debug "AN ERROR HAS OCCURED: Error sending heartbeat (SSL): #{e.message}"
190
242
  @websocket&.close
191
243
  rescue => e
192
244
  @logger.debug "AN ERROR HAS OCCURED: Error sending heartbeat: #{e.message}"
@@ -228,10 +280,10 @@ module Revoltrb
228
280
  # @logger.debug "AN ERROR HAS OCCURED: Unhandled WebSocket event type: #{event_type}"
229
281
  end
230
282
  rescue JSON::ParserError => e
231
- @logger.debug "Failed to parse WebSocket message as JSON: #{e.message}"
283
+ @logger.debug "AN ERROR HAS OCCURED: Failed to parse WebSocket message as JSON: #{e.message}"
232
284
  @logger.debug "Raw message: #{raw_data}"
233
285
  rescue => e
234
- @logger.debug "Error processing WebSocket message: #{e.message}"
286
+ @logger.debug "AN ERROR HAS OCCURED: Error processing WebSocket message: #{e.message}"
235
287
  @logger.debug e.backtrace.join("\n")
236
288
  end
237
289
  end
@@ -246,7 +298,7 @@ module Revoltrb
246
298
  'permissions' => required_permissions,
247
299
  'nsfw_cmd' => nsfw_channel_required
248
300
  }
249
- @logger.debug "Command '#{command_name}' registered with permissions: #{required_permissions.inspect}, NSFW required: #{nsfw_channel_required}."
301
+ @logger.debug "Command '#{command_name}' registered! Permissions: #{required_permissions.inspect}, NSFW required: #{nsfw_channel_required}."
250
302
  end
251
303
 
252
304
  def check_permissions(message, required_permissions, nsfw_channel_required)
@@ -262,12 +314,11 @@ module Revoltrb
262
314
  end
263
315
  user_id = message['author']
264
316
 
265
- @logger.debug "\n--- PERMISSION DEBUG START ---"
266
- @logger.debug "User ID from message (user_id): '#{user_id}' | Bot Owner ID stored (@bot_owner_id): '#{@bot_owner_id}'"
317
+ # --- Permission Check ---
318
+ @logger.debug "PERMISSION DEBUG: User ID from message (user_id): '#{user_id}' | Bot Owner ID stored (@bot_owner_id): '#{@bot_owner_id}'"
267
319
  @logger.debug "Are they equal? (user_id == @bot_owner_id): #{user_id == @bot_owner_id}"
268
320
  # @logger.debug "User ID char codes: #{user_id.each_char.map(&:ord).join(', ')}"
269
321
  # @logger.debug "Bot Owner ID char codes: #{@bot_owner_id.each_char.map(&:ord).join(', ')}"
270
- @logger.debug "--- PERMISSION DEBUG END ---\n"
271
322
  # --- BotOwner Check ---
272
323
  if required_permissions.include?('BotOwner')
273
324
  if user_id == @bot_owner_id
@@ -288,7 +339,7 @@ module Revoltrb
288
339
  else
289
340
  channel_details = get_channel_details(channel_id)
290
341
  if channel_details.nil?
291
- @logger.debug "Permission Check: Command requires NSFW channel but could not retrieve channel details. Denying command to be safe."
342
+ @logger.debug "Permission Check: Command requires NSFW channel but could not retrieve channel details. Denying command."
292
343
  return false
293
344
  end
294
345
  is_channel_nsfw = channel_details['nsfw'] || false
@@ -535,4 +586,4 @@ module Revoltrb
535
586
  end
536
587
  end
537
588
  end
538
- end
589
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Revoltrb
4
4
  # The current version of revoltrb
5
- VERSION = "0.0.2"
5
+ VERSION = "0.1.0"
6
6
  end
@@ -0,0 +1,104 @@
1
+ # lib/revoltrb/webhooks.rb
2
+ require 'json'
3
+ require 'net/http'
4
+ require 'uri'
5
+
6
+ module Revoltrb
7
+ class Webhooks
8
+ attr_reader :api_url, :logger, :token, :selfbot
9
+ def initialize(api_url, logger, token, selfbot)
10
+ @api_url = api_url
11
+ @logger = logger
12
+ @token = token
13
+ @selfbot = selfbot
14
+ end
15
+
16
+ def create_webhook(channel_id, name, avatar_url: nil)
17
+ @logger.debug "Attempting to create a webhook for channel '#{channel_id}' with name '#{name}'."
18
+
19
+ uri = URI("#{@api_url}/channels/#{channel_id}/webhooks")
20
+ req = Net::HTTP::Post.new(uri)
21
+ if @selfbot
22
+ req['Authorization'] = @token
23
+ else
24
+ req['x-bot-token'] = @token
25
+ end
26
+ req['Content-Type'] = 'application/json'
27
+
28
+ payload = {
29
+ name: name
30
+ }
31
+ payload[:avatar] = avatar_url unless avatar_url.nil?
32
+ req.body = payload.to_json
33
+
34
+ res = nil
35
+ begin
36
+ res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https', read_timeout: 10, open_timeout: 10) do |http|
37
+ http.request(req)
38
+ end
39
+ rescue Net::ReadTimeout => e
40
+ @logger.debug "AN ERROR HAS OCCURED: Network request timed out while reading: #{e.message}"
41
+ return nil
42
+ rescue Net::OpenTimeout => e
43
+ @logger.debug "AN ERROR HAS OCCURED: Network request timed out while connecting: #{e.message}"
44
+ return nil
45
+ rescue => e
46
+ @logger.debug "AN ERROR HAS OCCURED: An unexpected error occurred while creating the webhook: #{e.message}"
47
+ return nil
48
+ end
49
+
50
+ if res.is_a?(Net::HTTPSuccess)
51
+ webhook_data = JSON.parse(res.body)
52
+ @logger.debug "Webhook created successfully! Details: #{res.body}"
53
+ @logger.debug "Webhook Name: #{webhook_data['name']} | Webhook ID: #{webhook_data['id']}"
54
+ @logger.debug "Webhook Channel ID: #{webhook_data['channel_id']}"
55
+ return webhook_data
56
+ else
57
+ @logger.debug "AN ERROR HAS OCCURED: Failed to create webhook. (Code: #{res.code}) Response: #{res.message}"
58
+ @logger.debug "Response Body: #{res.body}"
59
+ return nil
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ module RevoltWebhooks
66
+ class Webhook
67
+ DEFAULT_API_URL = 'https://beta.revolt.chat/api'.freeze
68
+ def initialize(webhook_id, webhook_token, api_url: DEFAULT_API_URL)
69
+ @webhook_id = webhook_id
70
+ @webhook_token = webhook_token
71
+ @api_url = api_url
72
+ @uri = URI("#{@api_url}/webhooks/#{@webhook_id}/#{@webhook_token}")
73
+ end
74
+
75
+ def send_message(content:, embeds: nil)
76
+ payload = {
77
+ content: content
78
+ }
79
+
80
+ if embeds
81
+ payload[:embeds] = Array(embeds)
82
+ end
83
+
84
+ http = Net::HTTP.new(@uri.host, @uri.port)
85
+ http.use_ssl = true
86
+ request = Net::HTTP::Post.new(@uri.path, 'Content-Type' => 'application/json')
87
+ request.body = payload.to_json
88
+
89
+ begin
90
+ response = http.request(request)
91
+ if response.code.to_i == 204 || response.code.to_i == 200
92
+ return true
93
+ else
94
+ puts "[Revoltrb Webhooks] AN ERROR HAS OCCURED: Status code: #{response.code}"
95
+ puts "[Revoltrb Webhooks] Response body: #{response.body}"
96
+ return false
97
+ end
98
+ rescue StandardError => e
99
+ puts "[Revoltrb Webhooks] AN ERROR HAS OCCURED: #{e.message}"
100
+ return false
101
+ end
102
+ end
103
+ end
104
+ end
data/lib/revoltrb.rb CHANGED
@@ -1,8 +1,14 @@
1
+ # lib/revoltrb.rb
1
2
  require_relative 'revoltrb/bot'
2
3
  require_relative 'revoltrb/version'
3
4
  require_relative 'revoltrb/debuglogger'
4
5
  require_relative 'revoltrb/request_queue'
6
+ require_relative 'revoltrb/webhooks'
5
7
 
6
8
  module Revoltrb
7
9
  # This module can serve as a namespace for the gem's classes. For now, it's a direct require.
10
+ end
11
+
12
+ module RevoltWebhooks
13
+ # This module can serve as a namespace for the gem's classes. For now, it's a direct require.
8
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: revoltrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roxanne Studios
@@ -37,6 +37,20 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: 0.6.0
40
+ - !ruby/object:Gem::Dependency
41
+ name: websocket-client-simple
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.9.0
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.0
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: thread
42
56
  requirement: !ruby/object:Gem::Requirement
@@ -55,16 +69,16 @@ dependencies:
55
69
  name: parser
56
70
  requirement: !ruby/object:Gem::Requirement
57
71
  requirements:
58
- - - ">="
72
+ - - "~>"
59
73
  - !ruby/object:Gem::Version
60
- version: '0'
74
+ version: 3.3.9.0
61
75
  type: :runtime
62
76
  prerelease: false
63
77
  version_requirements: !ruby/object:Gem::Requirement
64
78
  requirements:
65
- - - ">="
79
+ - - "~>"
66
80
  - !ruby/object:Gem::Version
67
- version: '0'
81
+ version: 3.3.9.0
68
82
  description: The first Ruby package (a.k.a. gem) to exist for making Revolt.chat bots.
69
83
  This project is not officially endorsed by revolt.chat
70
84
  email:
@@ -79,6 +93,7 @@ files:
79
93
  - lib/revoltrb/debuglogger.rb
80
94
  - lib/revoltrb/request_queue.rb
81
95
  - lib/revoltrb/version.rb
96
+ - lib/revoltrb/webhooks.rb
82
97
  homepage: https://gitlab.com/roxannewolf/revoltrb
83
98
  licenses:
84
99
  - MIT