fluxerrb 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a1afcd0591253a04f54e8458bcb1a51733f78ecf3afdb7a47a3a22fca8f61949
4
+ data.tar.gz: 34ca494197af5511d3ef6f73c7358f6529a8554d9285701e1272b8bf9b9dce0a
5
+ SHA512:
6
+ metadata.gz: 924dca7689bbd5ccca3b6c917c520597d0f8e9c266becb438232d1572d2a71b1374b345361eac0b26c0904e1d6731ca63356d91a2379518fe4c5b232f6d5f047
7
+ data.tar.gz: b56704e5a38fde8f804a0f652f1495c2b6c4b9739e724ed286abf0e908e93e31d8d99f40b4966be4bb9146438ff8b1ebbcd6d42bc116d7ca26ac59b7c33114ac
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # fluxerrb
2
+
3
+ Fluxerrb is a Ruby package (a.k.a. Gem) that allows you to make Fluxer.app bots and use Fluxer.app webhooks using the Ruby programming language. This package (a.k.a. Gem) is not officially endorsed by fluxer.app and this is not an official fluxer.app product.
4
+
5
+ You need Ruby 3.0 or newer in order to use this package (Ruby 3.2 or newer is recommended)
6
+
7
+ > [!NOTE]
8
+ > This package (a.k.a. Gem) is in an early alpha state so expect things to be buggy and/or broken.
9
+
10
+ ## Setup
11
+
12
+ You can install Fluxerrb through the following methods:
13
+
14
+ #### Method 1: Install from Gemfile
15
+
16
+ Add the following to your Gemfile file and run the "[bundle install](https://rubygems.org/gems/fluxerrb)" command:
17
+
18
+ ```ruby
19
+ gem 'fluxerrb'
20
+ ```
21
+
22
+ or add the following to your Gemfile file to install with Git.
23
+
24
+ ```ruby
25
+ gem 'fluxerrb', git: 'https://codeberg.org/roxannewolf/fluxerrb'
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ You can make a simple bot like this:
31
+
32
+ ```ruby
33
+ require 'fluxerrb'
34
+
35
+ bot = Fluxerrb::Bot.new(token: 'YOUR_BOT_TOKEN_HERE', prefix: '!')
36
+
37
+ bot.on :message do |msg|
38
+ next if msg['author'].nil? || msg['author']['bot'] == true
39
+ puts "New Message: #{msg['content']}"
40
+
41
+ if msg['content'].downcase == 'ping'
42
+ bot.send_message(msg['channel_id'], "Pong!")
43
+ end
44
+ end
45
+
46
+ bot.start
47
+ ```
48
+
49
+ Webhook example:
50
+
51
+ ```ruby
52
+ require 'fluxerrb'
53
+
54
+ webhook = Fluxerrb::Webhook.from_url("<WEBHOOK_URL>")
55
+ webhook.send_message("Hello World! This message was sent through a webhook using fluxerrb.")
56
+ ```
57
+
58
+ You can view the examples directory for more examples on using this Gem
59
+
60
+ ## Support and Help
61
+
62
+ If you need help with this ruby package (a.k.a. Gem), feel free to join the [Roxanne Studios Fluxer Server](https://fluxer.gg/AVbb4B5S) and use the Fluxerrb category to talk about this package.
@@ -0,0 +1,208 @@
1
+ # lib/fluxerrb/client.rb
2
+ require 'net/http'
3
+ require 'json'
4
+ require 'websocket-client-simple'
5
+
6
+ module Fluxerrb
7
+ class Bot
8
+ attr_accessor :base_url, :token, :prefix, :reconnect_attempts
9
+
10
+ def initialize(config = {})
11
+ @base_url = config[:base_url] || 'https://api.fluxer.app/v1'
12
+ @gateway_url = config[:gateway_url] || 'wss://gateway.fluxer.app/?v=1'
13
+ @token = config[:token]
14
+ @prefix = config[:prefix] || '!'
15
+
16
+ @reconnect_attempts = 0
17
+ @max_reconnects = 5
18
+ @event_handlers = { message: [], command: [] }
19
+ @sequence = nil
20
+ end
21
+
22
+ def on(event_type, &block)
23
+ @event_handlers[event_type] << block if @event_handlers.key?(event_type)
24
+ end
25
+
26
+ def start
27
+ raise "[fluxerrb]: Bot token not set" unless @token
28
+ @running = true
29
+ connect_gateway
30
+ while @running
31
+ sleep 1
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def connect_gateway
38
+ puts "[fluxerrb]: Connecting to gateway: #{@gateway_url}..."
39
+ ENV['SSL_CERT_FILE'] = nil
40
+ ENV['OPENSSL_SSL_PROXY_VERIFY'] = 'none'
41
+ OpenSSL::SSL.send(:remove_const, :VERIFY_PEER) if OpenSSL::SSL.const_defined?(:VERIFY_PEER)
42
+ OpenSSL::SSL.const_set(:VERIFY_PEER, OpenSSL::SSL::VERIFY_NONE)
43
+ @ws = WebSocket::Client::Simple.connect(@gateway_url)
44
+ bot_instance = self
45
+ @ws.on :open do
46
+ puts "[fluxerrb]: Connected to Fluxer Gateway!"
47
+ bot_instance.reconnect_attempts = 0
48
+ end
49
+
50
+ @ws.on :message do |msg|
51
+ next if msg.data.nil? || msg.data.empty?
52
+
53
+ begin
54
+ payload = JSON.parse(msg.data)
55
+ bot_instance.send(:handle_gateway_payload, payload)
56
+ rescue JSON::ParserError => e
57
+ puts "JSON Parsing Error: #{e.message} | Raw Data: #{msg.data}"
58
+ end
59
+ end
60
+
61
+ @ws.on :close do |e|
62
+ puts "[fluxerrb]: Connection closed by gateway. Code: #{e}"
63
+ bot_instance.send(:stop_heartbeat)
64
+ bot_instance.send(:handle_reconnect)
65
+ end
66
+
67
+ @ws.on :error do |e|
68
+ puts "[fluxerrb]: WebSocket Error: #{e}"
69
+ end
70
+ end
71
+
72
+ def handle_gateway_payload(payload)
73
+ @sequence = payload['s'] if payload.key?('s')
74
+
75
+ case payload['op'].to_i
76
+ when 10
77
+ interval = payload['d']['heartbeat_interval'].to_f / 1000.0
78
+ puts "Received HELLO. Heartbeat interval set to #{interval}s."
79
+ start_heartbeat(interval)
80
+ send_identify
81
+ when 11
82
+ # Keep silent as the server acknowledges the ping.
83
+ when 0
84
+ handle_gateway_event(payload)
85
+ end
86
+ end
87
+
88
+ def start_heartbeat(interval)
89
+ stop_heartbeat
90
+ @heartbeat_thread = Thread.new do
91
+ loop do
92
+ sleep interval
93
+ puts "[fluxerrb]: Sending heartbeat (Sequence: #{@sequence})..."
94
+ send_payload(1, @sequence)
95
+ end
96
+ end
97
+ end
98
+
99
+ def stop_heartbeat
100
+ @heartbeat_thread&.kill
101
+ @heartbeat_thread = nil
102
+ end
103
+
104
+ def send_identify
105
+ identify_data = {
106
+ token: @token,
107
+ intents: 0,
108
+ properties: {os: RUBY_PLATFORM, browser: "fluxerrb", device: "fluxerrb"}
109
+ }
110
+ send_payload(2, identify_data)
111
+ end
112
+
113
+ def send_payload(op, data)
114
+ return unless @ws && @ws.open?
115
+ @ws.send({ op: op, d: data }.to_json)
116
+ rescue => e
117
+ puts "Failed to transmit payload: #{e.message}"
118
+ end
119
+
120
+ def handle_reconnect
121
+ return unless @running
122
+ if @reconnect_attempts >= @max_reconnects
123
+ puts "[fluxerrb]: Reconnection attempts failed. Exiting"
124
+ @running = false
125
+ return
126
+ end
127
+
128
+ @reconnect_attempts += 1
129
+ wait_time = @reconnect_attempts * 3
130
+ puts "[fluxerrb]: Attempting to reconnect in #{wait_time} seconds..."
131
+
132
+ sleep wait_time
133
+ connect_gateway if @running
134
+ end
135
+
136
+ def handle_gateway_event(payload)
137
+ case payload['t']
138
+ when 'READY'
139
+ puts "Fluxer Bot is ONLINE and READY!"
140
+ when 'MESSAGE_CREATE'
141
+ message_data = payload['d']
142
+ @event_handlers[:message].each { |handler| handler.call(message_data) }
143
+
144
+ if message_data['content']&.start_with?(@prefix)
145
+ raw_content = message_data['content']
146
+ parts = raw_content.slice(@prefix.length..-1).split(' ')
147
+ command_name = parts.first
148
+ args = parts[1..-1] || []
149
+
150
+ ctx = { message: message_data, command: command_name, args: args, content: args.join(' '), channel_id: message_data['channel_id'], client: self }
151
+
152
+ @event_handlers[:command].each { |handler| handler.call(ctx) }
153
+ end
154
+ end
155
+ end
156
+
157
+ public
158
+
159
+ def request(method, path, body = nil)
160
+ uri = URI("#{@base_url}#{path}")
161
+ http = Net::HTTP.new(uri.host, uri.port)
162
+ if uri.scheme == 'https'
163
+ http.use_ssl = true
164
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
165
+ end
166
+
167
+ req_class = Object.const_get("Net::HTTP::#{method.capitalize}")
168
+ req = req_class.new(uri.path, {
169
+ 'Authorization' => "Bot #{@token}",
170
+ 'Content-Type' => 'application/json'
171
+ })
172
+ req.body = body.to_json if body
173
+ response = http.request(req)
174
+
175
+ if response.code.to_i == 429
176
+ puts "[fluxerrb]: AN ERROR HAS OCCURED: 429 Ratelimit."
177
+ @running = false
178
+ exit(1)
179
+ end
180
+
181
+ JSON.parse(response.body) rescue response.body
182
+ end
183
+
184
+ def send_message(channel_id, content = "", embed = nil)
185
+ payload = {}
186
+ payload[:content] = content unless content.empty?
187
+ payload[:embed] = embed if embed
188
+ request('post', "/channels/#{channel_id}/messages", payload)
189
+ end
190
+ def get_channel(channel_id)
191
+ request('get', "/channels/#{channel_id}")
192
+ end
193
+ def get_guild(guild_id)
194
+ request('get', "/guilds/#{guild_id}")
195
+ end
196
+ def nsfw?(channel_or_id)
197
+ channel_data = channel_or_id.is_a?(Hash) ? channel_or_id : get_channel(channel_or_id)
198
+ !!channel_data['nsfw']
199
+ end
200
+ def server_owner?(author_id, guild_or_id)
201
+ guild_data = guild_or_id.is_a?(Hash) ? guild_or_id : get_guild(guild_or_id)
202
+ author_id.to_s == guild_data['owner_id'].to_s
203
+ end
204
+ def user_id?(author_id, target_id)
205
+ author_id.to_s == target_id.to_s
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,3 @@
1
+ module FluxerrbVersion
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,48 @@
1
+ # lib/fluxerrb/webhooks.rb
2
+ require 'net/http'
3
+ require 'json'
4
+
5
+ module Fluxerrb
6
+ class Webhook
7
+ attr_accessor :base_url, :webhook_id, :webhook_token
8
+ def initialize(config = {})
9
+ @base_url = config[:base_url] || 'https://api.fluxer.app/v1'
10
+ @webhook_id = config[:id]
11
+ @webhook_token = config[:token]
12
+ end
13
+
14
+ def self.from_url(url, base_override = nil)
15
+ uri = URI(url)
16
+ parts = uri.path.split('/')
17
+
18
+ token = parts.pop
19
+ id = parts.pop
20
+
21
+ base = base_override || "#{uri.scheme}://#{uri.host}/v1"
22
+ new(base_url: base, id: id, token: token)
23
+ end
24
+
25
+ def send_message(content, extra_params = {})
26
+ raise "[fluxerrb]: Webhook ID/Token not set" unless @webhook_id && @webhook_token
27
+
28
+ path = "/webhooks/#{@webhook_id}/#{@webhook_token}"
29
+ uri = URI("#{@base_url}#{path}")
30
+ payload = { content: content }.merge(extra_params)
31
+ http = Net::HTTP.new(uri.host, uri.port)
32
+ if uri.scheme == 'https'
33
+ http.use_ssl = true
34
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
35
+ end
36
+ req = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/json' })
37
+ req.body = payload.to_json
38
+ response = http.request(req)
39
+
40
+ if response.code.to_i == 429
41
+ puts "[fluxerrb]: AN ERROR HAS OCCURED: 429 Ratelimit."
42
+ return false
43
+ end
44
+
45
+ response.code.to_i == 200 || response.code.to_i == 204
46
+ end
47
+ end
48
+ end
data/lib/fluxerrb.rb ADDED
@@ -0,0 +1,8 @@
1
+ # lib/fluxerrb.rb
2
+ require_relative 'fluxerrb/client'
3
+ require_relative 'fluxerrb/webhooks'
4
+ require_relative 'fluxerrb/version'
5
+
6
+ module Fluxerrb
7
+ # This module can serve as a namespace for the gem's classes. For now, it's a direct require.
8
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluxerrb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Roxanne Studios
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-01 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: json
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 2.13.2
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 2.13.2
26
+ - !ruby/object:Gem::Dependency
27
+ name: net-http
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.6.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
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.3'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.3'
54
+ description: The first Ruby package (a.k.a. gem) to exist for making Fluxer.app bots
55
+ and using Fluxer.app webhooks. This project is not officially endorsed by Fluxer.app
56
+ email:
57
+ - ''
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - README.md
63
+ - lib/fluxerrb.rb
64
+ - lib/fluxerrb/client.rb
65
+ - lib/fluxerrb/version.rb
66
+ - lib/fluxerrb/webhooks.rb
67
+ homepage: https://codeberg.org/roxannewolf/fluxerrb
68
+ licenses:
69
+ - MIT
70
+ metadata:
71
+ changelog_uri: https://codeberg.org/roxannewolf/fluxerrb/src/branch/main/CHANGELOG.md
72
+ documentation_uri: https://codeberg.org/roxannewolf/fluxerrb/src/branch/main/README.md
73
+ source_code_uri: https://codeberg.org/roxannewolf/fluxerrb
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.7.2
89
+ specification_version: 4
90
+ summary: Ruby gem for making Fluxer.app bots
91
+ test_files: []