File: client.rb

package info (click to toggle)
ruby-discordrb-webhooks 3.5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 92 kB
  • sloc: ruby: 408; makefile: 3
file content (134 lines) | stat: -rw-r--r-- 5,545 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# frozen_string_literal: true

require 'rest-client'
require 'json'

require 'discordrb/webhooks/builder'

module Discordrb::Webhooks
  # A client for a particular webhook added to a Discord channel.
  class Client
    # Create a new webhook
    # @param url [String] The URL to post messages to.
    # @param id [Integer] The webhook's ID. Will only be used if `url` is not
    #   set.
    # @param token [String] The webhook's authorisation token. Will only be used
    #   if `url` is not set.
    def initialize(url: nil, id: nil, token: nil)
      @url = url || generate_url(id, token)
    end

    # Executes the webhook this client points to with the given data.
    # @param builder [Builder, nil] The builder to start out with, or nil if one should be created anew.
    # @param wait [true, false] Whether Discord should wait for the message to be successfully received by clients, or
    #   whether it should return immediately after sending the message.
    # @yield [builder] Gives the builder to the block to add additional steps, or to do the entire building process.
    # @yieldparam builder [Builder] The builder given as a parameter which is used as the initial step to start from.
    # @example Execute the webhook with an already existing builder
    #   builder = Discordrb::Webhooks::Builder.new # ...
    #   client.execute(builder)
    # @example Execute the webhook by building a new message
    #   client.execute do |builder|
    #     builder.content = 'Testing'
    #     builder.username = 'discordrb'
    #     builder.add_embed do |embed|
    #       embed.timestamp = Time.now
    #       embed.title = 'Testing'
    #       embed.image = Discordrb::Webhooks::EmbedImage.new(url: 'https://i.imgur.com/PcMltU7.jpg')
    #     end
    #   end
    # @return [RestClient::Response] the response returned by Discord.
    def execute(builder = nil, wait = false, components = nil)
      raise TypeError, 'builder needs to be nil or like a Discordrb::Webhooks::Builder!' unless
        (builder.respond_to?(:file) && builder.respond_to?(:to_multipart_hash)) || builder.respond_to?(:to_json_hash) || builder.nil?

      builder ||= Builder.new
      view = View.new

      yield(builder, view) if block_given?

      components ||= view

      if builder.file
        post_multipart(builder, components, wait)
      else
        post_json(builder, components, wait)
      end
    end

    # Modify this webhook's properties.
    # @param name [String, nil] The default name.
    # @param avatar [String, #read, nil] The new avatar, in base64-encoded JPG format.
    # @param channel_id [String, Integer, nil] The channel to move the webhook to.
    # @return [RestClient::Response] the response returned by Discord.
    def modify(name: nil, avatar: nil, channel_id: nil)
      RestClient.patch(@url, { name: name, avatar: avatarise(avatar), channel_id: channel_id }.compact.to_json, content_type: :json)
    end

    # Delete this webhook.
    # @param reason [String, nil] The reason this webhook was deleted.
    # @return [RestClient::Response] the response returned by Discord.
    # @note This is permanent and cannot be undone.
    def delete(reason: nil)
      RestClient.delete(@url, 'X-Audit-Log-Reason': reason)
    end

    # Edit a message from this webhook.
    # @param message_id [String, Integer] The ID of the message to edit.
    # @param builder [Builder, nil] The builder to start out with, or nil if one should be created anew.
    # @param content [String] The message content.
    # @param embeds [Array<Embed, Hash>]
    # @param allowed_mentions [Hash]
    # @return [RestClient::Response] the response returned by Discord.
    # @example Edit message content
    #   client.edit_message(message_id, content: 'goodbye world!')
    # @example Edit a message via builder
    #   client.edit_message(message_id) do |builder|
    #     builder.add_embed do |e|
    #       e.description = 'Hello World!'
    #     end
    #   end
    # @note Not all builder options are available when editing.
    def edit_message(message_id, builder: nil, content: nil, embeds: nil, allowed_mentions: nil)
      builder ||= Builder.new

      yield builder if block_given?

      data = builder.to_json_hash.merge({ content: content, embeds: embeds, allowed_mentions: allowed_mentions }.compact)
      RestClient.patch("#{@url}/messages/#{message_id}", data.compact.to_json, content_type: :json)
    end

    # Delete a message created by this webhook.
    # @param message_id [String, Integer] The ID of the message to delete.
    # @return [RestClient::Response] the response returned by Discord.
    def delete_message(message_id)
      RestClient.delete("#{@url}/messages/#{message_id}")
    end

    private

    # Convert an avatar to API ready data.
    # @param avatar [String, #read] Avatar data.
    def avatarise(avatar)
      if avatar.respond_to? :read
        "data:image/jpg;base64,#{Base64.strict_encode64(avatar.read)}"
      else
        avatar
      end
    end

    def post_json(builder, components, wait)
      data = builder.to_json_hash.merge({ components: components.to_a })
      RestClient.post(@url + (wait ? '?wait=true' : ''), data.to_json, content_type: :json)
    end

    def post_multipart(builder, components, wait)
      data = builder.to_multipart_hash.merge({ components: components.to_a })
      RestClient.post(@url + (wait ? '?wait=true' : ''), data)
    end

    def generate_url(id, token)
      "https://discord.com/api/v8/webhooks/#{id}/#{token}"
    end
  end
end