disrb 0.1.4 → 0.1.4.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 +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +2 -2
- data/lib/disrb/message.rb +8 -3
- data/lib/disrb.rb +83 -94
- data/lib/version.rb +2 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 27b3ea7d837fad369bc6abba57e0567143ce819dd3a13ca2516e32d49bc22991
|
|
4
|
+
data.tar.gz: c024c1d8817e3dfff8684cf3dfa2a5023361f25ef0941cd8e2bded03062ab0c2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d8dba8108d27f12906108120d0acbb8009f3023a336ddcc24bae46f35ee2badbb026314ef1428e1916c6d5ceda2221595a318e19d2c9ff606ca4b91db90a3158
|
|
7
|
+
data.tar.gz: 278ab5b9ca773e2dbfed4280204cace3b5b26f577647cfd4317c86b976372298bb9760dffddc9162169b0065a4e6be864568e32709409f030b412e2f89f225e7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# v0.1.4.1 (2026-04-14)
|
|
2
|
+
|
|
3
|
+
- File uploading was just not implemented in `edit_message`
|
|
4
|
+
- Fix file uploading function being used incorrectly in `create_message`
|
|
5
|
+
- Add new testing function in `test.rb`
|
|
6
|
+
- Fix HTTP handlers getting called incorrectly sometimes
|
|
7
|
+
- Add file uploading support to `respond_interaction` (you will need to specify `attachments` in the response yourself for now)
|
|
8
|
+
- Add uploading files to Discord also via PATCH requests
|
|
9
|
+
- Fix Faraday request types being set incorrectly
|
|
10
|
+
- Fix payload_json being added to multipart form data incorrectly
|
|
11
|
+
- Add info on how to create a new release in `CONTRIBUTING.md`
|
|
12
|
+
- Fix some typos and minor mistakes
|
|
13
|
+
- Add `Gemfile.lock` and remove it from `.gitignore`
|
|
14
|
+
|
|
1
15
|
# v0.1.4 (2026-04-05)
|
|
2
16
|
|
|
3
17
|
- Add support for file uploading
|
data/README.md
CHANGED
|
@@ -19,7 +19,7 @@ If you wanted to use this project, but found that something is missing, doesn't
|
|
|
19
19
|
|
|
20
20
|
## Demonstration
|
|
21
21
|
|
|
22
|
-
The test.rb file creates
|
|
22
|
+
The test.rb file creates three commands "test", "test2" and "file", that return "Hi", "Hello World!" and then "Hello World!" plus a file called "file.txt" with content "Hello World in a file!" respectively, sets the bot's current activity to 'Watching if i work', and sets the presence to online since the program was started. If the bot itself has been mentioned, it replies to that message with 'pong'.
|
|
23
23
|
|
|
24
24
|
> [!NOTE]
|
|
25
25
|
> You will need to fill out the required data in `env.rb.template` and rename it to `env.rb` before running `test.rb`.
|
|
@@ -47,7 +47,7 @@ If you want to get the contents of the response, use the `body` instance method
|
|
|
47
47
|
- [ ] Alpha release (v0.2.0)
|
|
48
48
|
- [ ] Add support for all Discord API endpoints (v0.2.0)
|
|
49
49
|
- [ ] Add support for all Discord Gateway events and properly handle the connection (v0.1.5)
|
|
50
|
-
- [
|
|
50
|
+
- [x] Add support for uploading files (v0.1.4)
|
|
51
51
|
- [x] Documentation (v0.1.3)
|
|
52
52
|
- [x] Full message resource support (v0.1.2)
|
|
53
53
|
- [x] Transition to Faraday for HTTP requests (v0.1.1)
|
data/lib/disrb/message.rb
CHANGED
|
@@ -115,7 +115,7 @@ class DiscordApi
|
|
|
115
115
|
data = JSON.generate(output)
|
|
116
116
|
headers = { 'Authorization': @authorization_header }
|
|
117
117
|
if files
|
|
118
|
-
response = file_upload(url, files, data, headers)
|
|
118
|
+
response = file_upload(url, files, payload_json: data, headers: headers)
|
|
119
119
|
else
|
|
120
120
|
headers['Content-Type'] = 'application/json'
|
|
121
121
|
response = post(url, data, headers)
|
|
@@ -272,7 +272,7 @@ class DiscordApi
|
|
|
272
272
|
components: nil, files: nil, attachments: nil)
|
|
273
273
|
if args[2..].all?(&:nil?)
|
|
274
274
|
@logger.warn("No modifications provided for message with ID #{message_id} in channel with ID #{channel_id}. " \
|
|
275
|
-
'
|
|
275
|
+
'Skipping function.')
|
|
276
276
|
return
|
|
277
277
|
end
|
|
278
278
|
output = {}
|
|
@@ -289,7 +289,12 @@ class DiscordApi
|
|
|
289
289
|
url = "#{@base_url}/channels/#{channel_id}/messages/#{message_id}"
|
|
290
290
|
data = JSON.generate(output)
|
|
291
291
|
headers = { 'Authorization': @authorization_header, 'Content-Type': 'application/json' }
|
|
292
|
-
|
|
292
|
+
if files
|
|
293
|
+
response = file_upload(url, files, headers: headers, payload_json: data, request_type: :patch)
|
|
294
|
+
else
|
|
295
|
+
headers['Content-Type'] = 'application/json'
|
|
296
|
+
response = patch(url, data, headers)
|
|
297
|
+
end
|
|
293
298
|
return response if response.is_a?(Faraday::Response) && response.status == 200
|
|
294
299
|
|
|
295
300
|
@logger.error("Failed to edit message with ID #{message_id} in channel with ID #{channel_id}. " \
|
data/lib/disrb.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
|
+
require 'uri'
|
|
4
5
|
require 'async'
|
|
5
6
|
require 'async/http/endpoint'
|
|
6
7
|
require 'async/websocket/client'
|
|
@@ -50,7 +51,6 @@ class Snowflake
|
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
# Class that contains functions that allow interacting with the Discord API.
|
|
53
|
-
# @version 0.1.4
|
|
54
54
|
class DiscordApi
|
|
55
55
|
# @!attribute [r] base_url
|
|
56
56
|
# @return [String] the base URL that is used to access the Discord API. ex: "https://discord.com/api/v10"
|
|
@@ -126,7 +126,7 @@ class DiscordApi
|
|
|
126
126
|
end
|
|
127
127
|
url = "#{@base_url}/applications/@me"
|
|
128
128
|
headers = { 'Authorization': @authorization_header }
|
|
129
|
-
response =
|
|
129
|
+
response = get(url, headers)
|
|
130
130
|
if response.is_a?(Faraday::Response) && response.status == 200
|
|
131
131
|
@application_id = JSON.parse(response.body)['id']
|
|
132
132
|
else
|
|
@@ -253,7 +253,7 @@ class DiscordApi
|
|
|
253
253
|
loop do
|
|
254
254
|
recieved_ready = false
|
|
255
255
|
url = if rescue_connection.nil?
|
|
256
|
-
response =
|
|
256
|
+
response = get("#{@base_url}/gateway")
|
|
257
257
|
if response.is_a?(Faraday::Response) && response.status == 200
|
|
258
258
|
"#{JSON.parse(response.body)['url']}/?v=#{@api_version}&encoding=json"
|
|
259
259
|
else
|
|
@@ -369,15 +369,21 @@ class DiscordApi
|
|
|
369
369
|
# @param interaction [Hash] The interaction payload received from the Gateway.
|
|
370
370
|
# @param response [Hash] The interaction response payload.
|
|
371
371
|
# @param with_response [TrueClass, FalseClass] Whether to request the created message in the response.
|
|
372
|
+
# @param files [Array] An array of arrays, each inner-array first has its filename (index 0),
|
|
373
|
+
# raw file data as a string (index 1), and then the MIME type of the file (index 2).
|
|
372
374
|
# @return [Faraday::Response] The response from the Discord API.
|
|
373
|
-
def respond_interaction(interaction, response, with_response: false)
|
|
375
|
+
def respond_interaction(interaction, response, with_response: false, files: nil)
|
|
374
376
|
query_string_hash = {}
|
|
375
377
|
query_string_hash[:with_response] = with_response
|
|
376
378
|
query_string = DiscordApi.handle_query_strings(query_string_hash)
|
|
377
379
|
url = "#{@base_url}/interactions/#{interaction[:d][:id]}/#{interaction[:d][:token]}/callback#{query_string}"
|
|
378
380
|
data = JSON.generate(response)
|
|
379
|
-
|
|
380
|
-
|
|
381
|
+
if files
|
|
382
|
+
response = file_upload(url, files, payload_json: data)
|
|
383
|
+
else
|
|
384
|
+
headers = { 'Content-Type' => 'application/json' }
|
|
385
|
+
response = post(url, data, headers)
|
|
386
|
+
end
|
|
381
387
|
return response if response.is_a?(Faraday::Response) &&
|
|
382
388
|
((response.status == 204 && !with_response) || (response.status == 200 && with_response))
|
|
383
389
|
|
|
@@ -508,18 +514,37 @@ class DiscordApi
|
|
|
508
514
|
'Empty'
|
|
509
515
|
end
|
|
510
516
|
|
|
517
|
+
# Parses a full URL and returns connection host and request path.
|
|
518
|
+
# @param url [String] Full URL.
|
|
519
|
+
# @param method_name [String] HTTP method name used for logging context.
|
|
520
|
+
# @return [Hash, nil] { host:, path: } or nil if URL is invalid.
|
|
521
|
+
def parse_request_url(url, method_name)
|
|
522
|
+
begin
|
|
523
|
+
uri = URI.parse(url.to_s)
|
|
524
|
+
rescue URI::InvalidURIError
|
|
525
|
+
@logger.error("Empty/invalid URL provided: #{url}. Cannot perform #{method_name} request.")
|
|
526
|
+
return nil
|
|
527
|
+
end
|
|
528
|
+
if uri.scheme.nil? || uri.host.nil?
|
|
529
|
+
@logger.error("Empty/invalid URL provided: #{url}. Cannot perform #{method_name} request.")
|
|
530
|
+
return nil
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
host = "#{uri.scheme}://#{uri.host}"
|
|
534
|
+
host = "#{host}:#{uri.port}" if uri.port && uri.port != uri.default_port
|
|
535
|
+
{ host: host, path: uri.request_uri }
|
|
536
|
+
end
|
|
537
|
+
|
|
511
538
|
# Performs an HTTP GET request using Faraday.
|
|
512
539
|
# @param url [String] Full URL including scheme and host; path may be included.
|
|
513
540
|
# @param headers [Hash, nil] Optional request headers.
|
|
514
541
|
# @return [Faraday::Response, nil] The Faraday response object, or nil if an error was encountered.
|
|
515
542
|
def get(url, headers = nil)
|
|
516
|
-
|
|
517
|
-
if
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
host = split_url[0]
|
|
522
|
-
path = split_url[1] if split_url[1]
|
|
543
|
+
parsed_url = parse_request_url(url, 'GET')
|
|
544
|
+
return if parsed_url.nil?
|
|
545
|
+
|
|
546
|
+
host = parsed_url[:host]
|
|
547
|
+
path = parsed_url[:path]
|
|
523
548
|
if headers.is_a?(Hash)
|
|
524
549
|
headers['User-Agent'] = @user_agent
|
|
525
550
|
elsif headers.nil?
|
|
@@ -529,11 +554,7 @@ class DiscordApi
|
|
|
529
554
|
headers = { 'User-Agent' => @user_agent }
|
|
530
555
|
end
|
|
531
556
|
conn = Faraday.new(url: host, headers: headers)
|
|
532
|
-
|
|
533
|
-
conn.get(path)
|
|
534
|
-
else
|
|
535
|
-
conn.get
|
|
536
|
-
end
|
|
557
|
+
conn.get(path)
|
|
537
558
|
end
|
|
538
559
|
|
|
539
560
|
# Performs an HTTP DELETE request using Faraday.
|
|
@@ -541,13 +562,11 @@ class DiscordApi
|
|
|
541
562
|
# @param headers [Hash, nil] Optional request headers.
|
|
542
563
|
# @return [Faraday::Response, nil] The Faraday response object, or nil if an error was encountered.
|
|
543
564
|
def delete(url, headers = nil)
|
|
544
|
-
|
|
545
|
-
if
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
host = split_url[0]
|
|
550
|
-
path = split_url[1] if split_url[1]
|
|
565
|
+
parsed_url = parse_request_url(url, 'DELETE')
|
|
566
|
+
return if parsed_url.nil?
|
|
567
|
+
|
|
568
|
+
host = parsed_url[:host]
|
|
569
|
+
path = parsed_url[:path]
|
|
551
570
|
if headers.is_a?(Hash)
|
|
552
571
|
headers['User-Agent'] = @user_agent
|
|
553
572
|
elsif headers.nil?
|
|
@@ -557,11 +576,7 @@ class DiscordApi
|
|
|
557
576
|
headers = { 'User-Agent' => @user_agent }
|
|
558
577
|
end
|
|
559
578
|
conn = Faraday.new(url: host, headers: headers)
|
|
560
|
-
|
|
561
|
-
conn.delete(path)
|
|
562
|
-
else
|
|
563
|
-
conn.delete
|
|
564
|
-
end
|
|
579
|
+
conn.delete(path)
|
|
565
580
|
end
|
|
566
581
|
|
|
567
582
|
# Performs an HTTP POST request using Faraday.
|
|
@@ -570,13 +585,11 @@ class DiscordApi
|
|
|
570
585
|
# @param headers [Hash, nil] Optional request headers.
|
|
571
586
|
# @return [Faraday::Response, nil] The Faraday response object, or nil if an error was encountered.
|
|
572
587
|
def post(url, data, headers = nil)
|
|
573
|
-
|
|
574
|
-
if
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
host = split_url[0]
|
|
579
|
-
path = split_url[1] if split_url[1]
|
|
588
|
+
parsed_url = parse_request_url(url, 'POST')
|
|
589
|
+
return if parsed_url.nil?
|
|
590
|
+
|
|
591
|
+
host = parsed_url[:host]
|
|
592
|
+
path = parsed_url[:path]
|
|
580
593
|
if headers.is_a?(Hash)
|
|
581
594
|
headers['User-Agent'] = @user_agent
|
|
582
595
|
elsif headers.nil?
|
|
@@ -586,11 +599,7 @@ class DiscordApi
|
|
|
586
599
|
headers = { 'User-Agent' => @user_agent }
|
|
587
600
|
end
|
|
588
601
|
conn = Faraday.new(url: host, headers: headers)
|
|
589
|
-
|
|
590
|
-
conn.post(path, data)
|
|
591
|
-
else
|
|
592
|
-
conn.post('', data)
|
|
593
|
-
end
|
|
602
|
+
conn.post(path, data)
|
|
594
603
|
end
|
|
595
604
|
|
|
596
605
|
# Performs an HTTP PATCH request using Faraday.
|
|
@@ -599,13 +608,11 @@ class DiscordApi
|
|
|
599
608
|
# @param headers [Hash, nil] Optional request headers.
|
|
600
609
|
# @return [Faraday::Response, nil] The Faraday response object, or nil if an error was encountered.
|
|
601
610
|
def patch(url, data, headers = nil)
|
|
602
|
-
|
|
603
|
-
if
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
host = split_url[0]
|
|
608
|
-
path = split_url[1] if split_url[1]
|
|
611
|
+
parsed_url = parse_request_url(url, 'PATCH')
|
|
612
|
+
return if parsed_url.nil?
|
|
613
|
+
|
|
614
|
+
host = parsed_url[:host]
|
|
615
|
+
path = parsed_url[:path]
|
|
609
616
|
if headers.is_a?(Hash)
|
|
610
617
|
headers['User-Agent'] = @user_agent
|
|
611
618
|
elsif headers.nil?
|
|
@@ -615,11 +622,7 @@ class DiscordApi
|
|
|
615
622
|
headers = { 'User-Agent' => @user_agent }
|
|
616
623
|
end
|
|
617
624
|
conn = Faraday.new(url: host, headers: headers)
|
|
618
|
-
|
|
619
|
-
conn.patch(path, data)
|
|
620
|
-
else
|
|
621
|
-
conn.patch('', data)
|
|
622
|
-
end
|
|
625
|
+
conn.patch(path, data)
|
|
623
626
|
end
|
|
624
627
|
|
|
625
628
|
# Performs an HTTP PUT request using Faraday.
|
|
@@ -628,13 +631,11 @@ class DiscordApi
|
|
|
628
631
|
# @param headers [Hash, nil] Optional request headers.
|
|
629
632
|
# @return [Faraday::Response, nil] The Faraday response object, or nil if an error was encountered.
|
|
630
633
|
def put(url, data, headers = nil)
|
|
631
|
-
|
|
632
|
-
if
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
host = split_url[0]
|
|
637
|
-
path = split_url[1] if split_url[1]
|
|
634
|
+
parsed_url = parse_request_url(url, 'PUT')
|
|
635
|
+
return if parsed_url.nil?
|
|
636
|
+
|
|
637
|
+
host = parsed_url[:host]
|
|
638
|
+
path = parsed_url[:path]
|
|
638
639
|
if headers.is_a?(Hash)
|
|
639
640
|
headers['User-Agent'] = @user_agent
|
|
640
641
|
elsif headers.nil?
|
|
@@ -644,14 +645,10 @@ class DiscordApi
|
|
|
644
645
|
headers = { 'User-Agent' => @user_agent }
|
|
645
646
|
end
|
|
646
647
|
conn = Faraday.new(url: host, headers: headers)
|
|
647
|
-
|
|
648
|
-
conn.put(path, data)
|
|
649
|
-
else
|
|
650
|
-
conn.put('', data)
|
|
651
|
-
end
|
|
648
|
+
conn.put(path, data)
|
|
652
649
|
end
|
|
653
650
|
|
|
654
|
-
# Sends a HTTP POST request to the specified URL, containing multipart/form-data data structured
|
|
651
|
+
# Sends a HTTP POST/PATCH request to the specified URL, containing multipart/form-data data structured
|
|
655
652
|
# according to Discord documentation.
|
|
656
653
|
# See https://docs.discord.com/developers/reference#uploading-files
|
|
657
654
|
# @param url [String] Full URL including scheme and host; path may be included.
|
|
@@ -660,15 +657,14 @@ class DiscordApi
|
|
|
660
657
|
# @param files [Array] An array of arrays, each inner-array first has its filename (index 0),
|
|
661
658
|
# raw file data as a string (index 1), and then the MIME type of the file (index 2).
|
|
662
659
|
# @param headers [Hash, nil] Optional request headers.
|
|
660
|
+
# @param request_type [Symbol, nil] Specify whether to make a POST (:post) or PATCH (:patch) request. POST by default.
|
|
663
661
|
# @return [Faraday::Response, nil] The Faraday response object, or nil if an error was encountered.
|
|
664
|
-
def file_upload(url, files, payload_json: nil, headers: nil)
|
|
665
|
-
|
|
666
|
-
if
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
host = split_url[0]
|
|
671
|
-
path = split_url[1] if split_url[1]
|
|
662
|
+
def file_upload(url, files, payload_json: nil, headers: nil, request_type: :post)
|
|
663
|
+
parsed_url = parse_request_url(url, 'multipart/form-data')
|
|
664
|
+
return if parsed_url.nil?
|
|
665
|
+
|
|
666
|
+
host = parsed_url[:host]
|
|
667
|
+
path = parsed_url[:path]
|
|
672
668
|
if headers.is_a?(Hash)
|
|
673
669
|
headers['User-Agent'] = @user_agent
|
|
674
670
|
elsif headers.nil?
|
|
@@ -677,35 +673,28 @@ class DiscordApi
|
|
|
677
673
|
@logger.warn('Invalid headers parameter. It will be discarded.')
|
|
678
674
|
headers = { 'User-Agent' => @user_agent }
|
|
679
675
|
end
|
|
680
|
-
conn = Faraday.new(url: host, headers: headers
|
|
681
|
-
|
|
682
|
-
# FilePart expects File/IO objects as the first argument.
|
|
683
|
-
# However, since the function is being given raw data instead of File/IO objects, we should be using ParamPart
|
|
684
|
-
# But, ParamPart doesn't let us use a customized Content-Disposition, which is what we need
|
|
685
|
-
# So we will just have to wrap the raw data in an IO class with StringIO
|
|
686
|
-
if payload_json
|
|
687
|
-
payload[:payload_json] = Faraday::Multipart::FilePart.new(
|
|
688
|
-
StringIO.new(payload_json),
|
|
689
|
-
'application/json',
|
|
690
|
-
nil,
|
|
691
|
-
'Content-Disposition' => 'form-data; name="payload_json"'
|
|
692
|
-
)
|
|
676
|
+
conn = Faraday.new(url: host, headers: headers) do |faraday|
|
|
677
|
+
faraday.request :multipart
|
|
693
678
|
end
|
|
679
|
+
payload = {}
|
|
680
|
+
payload['payload_json'] = Faraday::Multipart::ParamPart.new(payload_json, 'application/json') if payload_json
|
|
694
681
|
files.each_with_index do |(filename, raw_bytes, mime_type), i|
|
|
695
|
-
payload[
|
|
682
|
+
payload["files[#{i}]"] = Faraday::Multipart::FilePart.new(
|
|
696
683
|
StringIO.new(raw_bytes),
|
|
697
684
|
mime_type,
|
|
698
|
-
filename
|
|
699
|
-
'Content-Disposition' => "form-data; name=\"files[#{i}]\"; filename=\"#{filename}\""
|
|
685
|
+
filename
|
|
700
686
|
)
|
|
701
687
|
end
|
|
702
688
|
if payload.empty?
|
|
703
689
|
@logger.warn("Payload empty, not sending Discord multipart/form-data POST request to #{url}.")
|
|
704
690
|
nil
|
|
705
|
-
elsif path
|
|
706
|
-
conn.post(path, payload)
|
|
707
691
|
else
|
|
708
|
-
|
|
692
|
+
case request_type
|
|
693
|
+
when :post
|
|
694
|
+
conn.post(path, payload)
|
|
695
|
+
when :patch
|
|
696
|
+
conn.patch(path, payload)
|
|
697
|
+
end
|
|
709
698
|
end
|
|
710
699
|
end
|
|
711
700
|
|
data/lib/version.rb
CHANGED