onyxcord 1.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 +7 -0
- data/.devcontainer/Dockerfile +13 -0
- data/.devcontainer/devcontainer.json +29 -0
- data/.devcontainer/postcreate.sh +4 -0
- data/.github/CONTRIBUTING.md +13 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- data/.github/pull_request_template.md +37 -0
- data/.github/workflows/ci.yml +78 -0
- data/.github/workflows/codeql.yml +65 -0
- data/.github/workflows/deploy.yml +54 -0
- data/.github/workflows/release.yml +51 -0
- data/.gitignore +16 -0
- data/.markdownlint.json +4 -0
- data/.overcommit.yml +7 -0
- data/.rspec +2 -0
- data/.rubocop.yml +129 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +305 -0
- data/Rakefile +17 -0
- data/bin/console +15 -0
- data/bin/setup +7 -0
- data/lib/onyxcord/allowed_mentions.rb +43 -0
- data/lib/onyxcord/api/application.rb +316 -0
- data/lib/onyxcord/api/channel.rb +700 -0
- data/lib/onyxcord/api/interaction.rb +67 -0
- data/lib/onyxcord/api/invite.rb +44 -0
- data/lib/onyxcord/api/server.rb +775 -0
- data/lib/onyxcord/api/user.rb +158 -0
- data/lib/onyxcord/api/webhook.rb +163 -0
- data/lib/onyxcord/api.rb +335 -0
- data/lib/onyxcord/await.rb +51 -0
- data/lib/onyxcord/bot.rb +1971 -0
- data/lib/onyxcord/cache.rb +326 -0
- data/lib/onyxcord/colour_rgb.rb +43 -0
- data/lib/onyxcord/commands/command_bot.rb +511 -0
- data/lib/onyxcord/commands/container.rb +112 -0
- data/lib/onyxcord/commands/events.rb +11 -0
- data/lib/onyxcord/commands/parser.rb +327 -0
- data/lib/onyxcord/commands/rate_limiter.rb +144 -0
- data/lib/onyxcord/configuration.rb +125 -0
- data/lib/onyxcord/container.rb +988 -0
- data/lib/onyxcord/data/activity.rb +271 -0
- data/lib/onyxcord/data/application.rb +341 -0
- data/lib/onyxcord/data/attachment.rb +91 -0
- data/lib/onyxcord/data/audit_logs.rb +438 -0
- data/lib/onyxcord/data/avatar_decoration.rb +26 -0
- data/lib/onyxcord/data/call.rb +22 -0
- data/lib/onyxcord/data/channel.rb +1355 -0
- data/lib/onyxcord/data/channel_tag.rb +69 -0
- data/lib/onyxcord/data/collectibles.rb +47 -0
- data/lib/onyxcord/data/component.rb +583 -0
- data/lib/onyxcord/data/embed.rb +258 -0
- data/lib/onyxcord/data/emoji.rb +123 -0
- data/lib/onyxcord/data/install_params.rb +24 -0
- data/lib/onyxcord/data/integration.rb +144 -0
- data/lib/onyxcord/data/interaction.rb +1141 -0
- data/lib/onyxcord/data/invite.rb +137 -0
- data/lib/onyxcord/data/member.rb +528 -0
- data/lib/onyxcord/data/message.rb +612 -0
- data/lib/onyxcord/data/message_activity.rb +41 -0
- data/lib/onyxcord/data/overwrite.rb +109 -0
- data/lib/onyxcord/data/poll.rb +365 -0
- data/lib/onyxcord/data/primary_server.rb +60 -0
- data/lib/onyxcord/data/profile.rb +79 -0
- data/lib/onyxcord/data/reaction.rb +64 -0
- data/lib/onyxcord/data/recipient.rb +34 -0
- data/lib/onyxcord/data/role.rb +449 -0
- data/lib/onyxcord/data/role_connection_data.rb +69 -0
- data/lib/onyxcord/data/role_subscription.rb +41 -0
- data/lib/onyxcord/data/scheduled_event.rb +513 -0
- data/lib/onyxcord/data/server.rb +1614 -0
- data/lib/onyxcord/data/server_preview.rb +68 -0
- data/lib/onyxcord/data/snapshot.rb +112 -0
- data/lib/onyxcord/data/team.rb +98 -0
- data/lib/onyxcord/data/timestamp.rb +69 -0
- data/lib/onyxcord/data/user.rb +324 -0
- data/lib/onyxcord/data/voice_region.rb +46 -0
- data/lib/onyxcord/data/voice_state.rb +41 -0
- data/lib/onyxcord/data/webhook.rb +238 -0
- data/lib/onyxcord/data.rb +57 -0
- data/lib/onyxcord/errors.rb +246 -0
- data/lib/onyxcord/event_executor.rb +80 -0
- data/lib/onyxcord/events/await.rb +48 -0
- data/lib/onyxcord/events/bans.rb +60 -0
- data/lib/onyxcord/events/channels.rb +225 -0
- data/lib/onyxcord/events/generic.rb +129 -0
- data/lib/onyxcord/events/guilds.rb +269 -0
- data/lib/onyxcord/events/integrations.rb +100 -0
- data/lib/onyxcord/events/interactions.rb +624 -0
- data/lib/onyxcord/events/invites.rb +127 -0
- data/lib/onyxcord/events/lifetime.rb +31 -0
- data/lib/onyxcord/events/members.rb +110 -0
- data/lib/onyxcord/events/message.rb +399 -0
- data/lib/onyxcord/events/polls.rb +118 -0
- data/lib/onyxcord/events/presence.rb +131 -0
- data/lib/onyxcord/events/raw.rb +74 -0
- data/lib/onyxcord/events/reactions.rb +218 -0
- data/lib/onyxcord/events/roles.rb +87 -0
- data/lib/onyxcord/events/scheduled_events.rb +171 -0
- data/lib/onyxcord/events/threads.rb +100 -0
- data/lib/onyxcord/events/typing.rb +73 -0
- data/lib/onyxcord/events/voice_server_update.rb +48 -0
- data/lib/onyxcord/events/voice_state_update.rb +106 -0
- data/lib/onyxcord/events/webhooks.rb +65 -0
- data/lib/onyxcord/gateway.rb +890 -0
- data/lib/onyxcord/id_object.rb +39 -0
- data/lib/onyxcord/light/data.rb +62 -0
- data/lib/onyxcord/light/integrations.rb +73 -0
- data/lib/onyxcord/light/light_bot.rb +58 -0
- data/lib/onyxcord/light.rb +8 -0
- data/lib/onyxcord/logger.rb +120 -0
- data/lib/onyxcord/message_components.rb +70 -0
- data/lib/onyxcord/paginator.rb +60 -0
- data/lib/onyxcord/permissions.rb +255 -0
- data/lib/onyxcord/rate_limiter/gateway.rb +42 -0
- data/lib/onyxcord/rate_limiter/rest.rb +89 -0
- data/lib/onyxcord/version.rb +7 -0
- data/lib/onyxcord/voice/encoder.rb +115 -0
- data/lib/onyxcord/voice/network.rb +380 -0
- data/lib/onyxcord/voice/opcodes.rb +29 -0
- data/lib/onyxcord/voice/sodium.rb +157 -0
- data/lib/onyxcord/voice/timer.rb +19 -0
- data/lib/onyxcord/voice/voice_bot.rb +386 -0
- data/lib/onyxcord/webhooks.rb +14 -0
- data/lib/onyxcord/websocket.rb +62 -0
- data/lib/onyxcord.rb +180 -0
- data/onyxcord-webhooks.gemspec +30 -0
- data/onyxcord.gemspec +50 -0
- metadata +421 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
# Event execution strategies used by bot dispatch.
|
|
5
|
+
module EventExecutor
|
|
6
|
+
STOP = Object.new.freeze
|
|
7
|
+
|
|
8
|
+
# Deterministic executor useful for tests, benchmarks, and tiny bots.
|
|
9
|
+
class Inline
|
|
10
|
+
def post
|
|
11
|
+
yield
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def shutdown; end
|
|
15
|
+
|
|
16
|
+
def threads
|
|
17
|
+
[]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Fixed-size worker pool for event handlers.
|
|
22
|
+
class Pool
|
|
23
|
+
attr_reader :threads
|
|
24
|
+
|
|
25
|
+
def initialize(size:)
|
|
26
|
+
raise ArgumentError, 'Pool size must be greater than zero' unless size.positive?
|
|
27
|
+
|
|
28
|
+
@queue = Queue.new
|
|
29
|
+
@closed = false
|
|
30
|
+
@threads = Array.new(size) do |index|
|
|
31
|
+
Thread.new do
|
|
32
|
+
Thread.current[:onyxcord_name] = "event-worker-#{index + 1}"
|
|
33
|
+
worker_loop
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def post(&block)
|
|
39
|
+
raise ArgumentError, 'EventExecutor::Pool#post requires a block' unless block
|
|
40
|
+
raise 'Event executor has been shut down' if @closed
|
|
41
|
+
|
|
42
|
+
@queue << block
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def shutdown
|
|
46
|
+
return if @closed
|
|
47
|
+
|
|
48
|
+
@closed = true
|
|
49
|
+
@threads.length.times { @queue << STOP }
|
|
50
|
+
@threads.each { |thread| thread.join unless thread == Thread.current }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def worker_loop
|
|
56
|
+
loop do
|
|
57
|
+
job = @queue.pop
|
|
58
|
+
break if job.equal?(STOP)
|
|
59
|
+
|
|
60
|
+
job.call
|
|
61
|
+
rescue StandardError => e
|
|
62
|
+
OnyxCord::LOGGER.log_exception(e) if defined?(OnyxCord::LOGGER)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
module_function
|
|
68
|
+
|
|
69
|
+
def build(type, workers:)
|
|
70
|
+
case type
|
|
71
|
+
when :inline
|
|
72
|
+
Inline.new
|
|
73
|
+
when :pool
|
|
74
|
+
Pool.new(size: workers)
|
|
75
|
+
else
|
|
76
|
+
raise ArgumentError, "Unknown event executor: #{type.inspect}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'onyxcord/events/generic'
|
|
4
|
+
require 'onyxcord/await'
|
|
5
|
+
|
|
6
|
+
module OnyxCord::Events
|
|
7
|
+
# @see Bot#await
|
|
8
|
+
class AwaitEvent < Event
|
|
9
|
+
# The await that was triggered.
|
|
10
|
+
# @return [Await] The await
|
|
11
|
+
attr_reader :await
|
|
12
|
+
|
|
13
|
+
# The event that triggered the await.
|
|
14
|
+
# @return [Event] The event
|
|
15
|
+
attr_reader :event
|
|
16
|
+
|
|
17
|
+
# @!attribute [r] key
|
|
18
|
+
# @return [Symbol] the await's key.
|
|
19
|
+
# @see Await#key
|
|
20
|
+
# @!attribute [r] type
|
|
21
|
+
# @return [Class] the await's event class.
|
|
22
|
+
# @see Await#type
|
|
23
|
+
# @!attribute [r] attributes
|
|
24
|
+
# @return [Hash] a hash of attributes defined on the await.
|
|
25
|
+
# @see Await#attributes
|
|
26
|
+
delegate :key, :type, :attributes, to: :await
|
|
27
|
+
|
|
28
|
+
# @!visibility private
|
|
29
|
+
def initialize(await, event, bot)
|
|
30
|
+
@await = await
|
|
31
|
+
@event = event
|
|
32
|
+
@bot = bot
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Event handler for {AwaitEvent}
|
|
37
|
+
class AwaitEventHandler < EventHandler
|
|
38
|
+
def matches?(event)
|
|
39
|
+
# Check for the proper event type
|
|
40
|
+
return false unless event.is_a? AwaitEvent
|
|
41
|
+
|
|
42
|
+
[
|
|
43
|
+
matches_all(@attributes[:key], event.key) { |a, e| a == e },
|
|
44
|
+
matches_all(@attributes[:type], event.type) { |a, e| a == e }
|
|
45
|
+
].reduce(true, &:&)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'onyxcord/events/generic'
|
|
4
|
+
|
|
5
|
+
module OnyxCord::Events
|
|
6
|
+
# Raised when a user is banned
|
|
7
|
+
class UserBanEvent < Event
|
|
8
|
+
# @return [User] the user that was banned
|
|
9
|
+
attr_reader :user
|
|
10
|
+
|
|
11
|
+
# @return [Server] the server from which the user was banned
|
|
12
|
+
attr_reader :server
|
|
13
|
+
|
|
14
|
+
# @!visibility private
|
|
15
|
+
def initialize(data, bot)
|
|
16
|
+
@user = bot.user(data['user']['id'].to_i)
|
|
17
|
+
@server = bot.server(data['guild_id'].to_i)
|
|
18
|
+
@bot = bot
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Event handler for {UserBanEvent}
|
|
23
|
+
class UserBanEventHandler < EventHandler
|
|
24
|
+
def matches?(event)
|
|
25
|
+
# Check for the proper event type
|
|
26
|
+
return false unless event.is_a? UserBanEvent
|
|
27
|
+
|
|
28
|
+
[
|
|
29
|
+
matches_all(@attributes[:user], event.user) do |a, e|
|
|
30
|
+
case a
|
|
31
|
+
when String
|
|
32
|
+
a == e.name
|
|
33
|
+
when Integer
|
|
34
|
+
a == e.id
|
|
35
|
+
when :bot
|
|
36
|
+
e.current_bot?
|
|
37
|
+
else
|
|
38
|
+
a == e
|
|
39
|
+
end
|
|
40
|
+
end,
|
|
41
|
+
matches_all(@attributes[:server], event.server) do |a, e|
|
|
42
|
+
a == case a
|
|
43
|
+
when String
|
|
44
|
+
e.name
|
|
45
|
+
when Integer
|
|
46
|
+
e.id
|
|
47
|
+
else
|
|
48
|
+
e
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
].reduce(true, &:&)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Raised when a user is unbanned from a server
|
|
56
|
+
class UserUnbanEvent < UserBanEvent; end
|
|
57
|
+
|
|
58
|
+
# Event handler for {UserUnbanEvent}
|
|
59
|
+
class UserUnbanEventHandler < UserBanEventHandler; end
|
|
60
|
+
end
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'onyxcord/events/generic'
|
|
4
|
+
require 'onyxcord/data'
|
|
5
|
+
|
|
6
|
+
module OnyxCord::Events
|
|
7
|
+
# Raised when a channel is created
|
|
8
|
+
class ChannelCreateEvent < Event
|
|
9
|
+
# @return [Channel] the channel in question.
|
|
10
|
+
attr_reader :channel
|
|
11
|
+
|
|
12
|
+
# @!attribute [r] type
|
|
13
|
+
# @return [Integer] the channel's type (0: text, 1: private, 2: voice, 3: group).
|
|
14
|
+
# @see Channel#type
|
|
15
|
+
# @!attribute [r] topic
|
|
16
|
+
# @return [String] the channel's topic.
|
|
17
|
+
# @see Channel#topic
|
|
18
|
+
# @!attribute [r] position
|
|
19
|
+
# @return [Integer] the position of the channel in the channels list.
|
|
20
|
+
# @see Channel#position
|
|
21
|
+
# @!attribute [r] name
|
|
22
|
+
# @return [String] the channel's name
|
|
23
|
+
# @see Channel#name
|
|
24
|
+
# @!attribute [r] id
|
|
25
|
+
# @return [Integer] the channel's unique ID.
|
|
26
|
+
# @see Channel#id
|
|
27
|
+
# @!attribute [r] server
|
|
28
|
+
# @return [Server] the server the channel belongs to.
|
|
29
|
+
# @see Channel#server
|
|
30
|
+
delegate :name, :server, :type, :owner_id, :recipients, :topic, :user_limit, :position, :permission_overwrites, to: :channel
|
|
31
|
+
|
|
32
|
+
# @!visibility private
|
|
33
|
+
def initialize(data, bot)
|
|
34
|
+
@bot = bot
|
|
35
|
+
@channel = data.is_a?(OnyxCord::Channel) ? data : bot.channel(data['id'].to_i)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Event handler for ChannelCreateEvent
|
|
40
|
+
class ChannelCreateEventHandler < EventHandler
|
|
41
|
+
def matches?(event)
|
|
42
|
+
# Check for the proper event type
|
|
43
|
+
return false unless event.is_a? ChannelCreateEvent
|
|
44
|
+
|
|
45
|
+
[
|
|
46
|
+
matches_all(@attributes[:type], event.type) do |a, e|
|
|
47
|
+
a == if a.is_a? String
|
|
48
|
+
e.name
|
|
49
|
+
else
|
|
50
|
+
e
|
|
51
|
+
end
|
|
52
|
+
end,
|
|
53
|
+
matches_all(@attributes[:name], event.name) do |a, e|
|
|
54
|
+
a == if a.is_a? String
|
|
55
|
+
e.to_s
|
|
56
|
+
else
|
|
57
|
+
e
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
].reduce(true, &:&)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Raised when a channel is deleted
|
|
65
|
+
class ChannelDeleteEvent < Event
|
|
66
|
+
# @return [Integer] the channel's type (0: text, 1: private, 2: voice, 3: group).
|
|
67
|
+
attr_reader :type
|
|
68
|
+
|
|
69
|
+
# @return [String] the channel's topic
|
|
70
|
+
attr_reader :topic
|
|
71
|
+
|
|
72
|
+
# @return [Integer] the position of the channel on the list
|
|
73
|
+
attr_reader :position
|
|
74
|
+
|
|
75
|
+
# @return [String] the channel's name
|
|
76
|
+
attr_reader :name
|
|
77
|
+
|
|
78
|
+
# @return [Integer] the channel's ID
|
|
79
|
+
attr_reader :id
|
|
80
|
+
|
|
81
|
+
# @return [Server] the channel's server
|
|
82
|
+
attr_reader :server
|
|
83
|
+
|
|
84
|
+
# @return [Integer, nil] the channel's owner ID if this is a group channel
|
|
85
|
+
attr_reader :owner_id
|
|
86
|
+
|
|
87
|
+
# @!visibility private
|
|
88
|
+
def initialize(data, bot)
|
|
89
|
+
@bot = bot
|
|
90
|
+
|
|
91
|
+
@type = data['type']
|
|
92
|
+
@topic = data['topic']
|
|
93
|
+
@position = data['position']
|
|
94
|
+
@name = data['name']
|
|
95
|
+
@is_private = data['is_private']
|
|
96
|
+
@id = data['id'].to_i
|
|
97
|
+
@server = bot.server(data['guild_id'].to_i) if data['guild_id']
|
|
98
|
+
@owner_id = bot.user(data['owner_id']) if @type == 3
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Event handler for ChannelDeleteEvent
|
|
103
|
+
class ChannelDeleteEventHandler < EventHandler
|
|
104
|
+
def matches?(event)
|
|
105
|
+
# Check for the proper event type
|
|
106
|
+
return false unless event.is_a? ChannelDeleteEvent
|
|
107
|
+
|
|
108
|
+
[
|
|
109
|
+
matches_all(@attributes[:type], event.type) do |a, e|
|
|
110
|
+
a == if a.is_a? String
|
|
111
|
+
e.name
|
|
112
|
+
else
|
|
113
|
+
e
|
|
114
|
+
end
|
|
115
|
+
end,
|
|
116
|
+
matches_all(@attributes[:name], event.name) do |a, e|
|
|
117
|
+
a == if a.is_a? String
|
|
118
|
+
e.to_s
|
|
119
|
+
else
|
|
120
|
+
e
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
].reduce(true, &:&)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Generic subclass for recipient events (add/remove)
|
|
128
|
+
class ChannelRecipientEvent < Event
|
|
129
|
+
# @return [Channel] the channel in question.
|
|
130
|
+
attr_reader :channel
|
|
131
|
+
|
|
132
|
+
delegate :name, :server, :type, :owner_id, :recipients, :topic, :user_limit, :position, :permission_overwrites, to: :channel
|
|
133
|
+
|
|
134
|
+
# @return [Recipient] the recipient that was added/removed from the group
|
|
135
|
+
attr_reader :recipient
|
|
136
|
+
|
|
137
|
+
delegate :id, to: :recipient
|
|
138
|
+
|
|
139
|
+
# @!visibility private
|
|
140
|
+
def initialize(data, bot)
|
|
141
|
+
@bot = bot
|
|
142
|
+
|
|
143
|
+
@channel = bot.channel(data['channel_id'].to_i)
|
|
144
|
+
recipient = data['user']
|
|
145
|
+
recipient_user = bot.ensure_user(recipient)
|
|
146
|
+
@recipient = OnyxCord::Recipient.new(recipient_user, @channel, bot)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Generic event handler for channel recipient events
|
|
151
|
+
class ChannelRecipientEventHandler < EventHandler
|
|
152
|
+
def matches?(event)
|
|
153
|
+
# Check for the proper event type
|
|
154
|
+
return false unless event.is_a? ChannelRecipientEvent
|
|
155
|
+
|
|
156
|
+
[
|
|
157
|
+
matches_all(@attributes[:owner_id], event.owner_id) do |a, e|
|
|
158
|
+
a.resolve_id == e.resolve_id
|
|
159
|
+
end,
|
|
160
|
+
matches_all(@attributes[:id], event.id) do |a, e|
|
|
161
|
+
a.resolve_id == e.resolve_id
|
|
162
|
+
end,
|
|
163
|
+
matches_all(@attributes[:name], event.name) do |a, e|
|
|
164
|
+
a == if a.is_a? String
|
|
165
|
+
e.to_s
|
|
166
|
+
else
|
|
167
|
+
e
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
]
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Raised when a message is pinned or unpinned.
|
|
175
|
+
class ChannelPinsUpdateEvent < Event
|
|
176
|
+
# @return [Time, nil] Time at which the most recent pinned message was pinned.
|
|
177
|
+
attr_reader :last_pin_timestamp
|
|
178
|
+
|
|
179
|
+
# @return [Channel] The channel this event originates from.
|
|
180
|
+
attr_reader :channel
|
|
181
|
+
|
|
182
|
+
# @return [Server, nil] The server this event originates from.
|
|
183
|
+
attr_reader :server
|
|
184
|
+
|
|
185
|
+
# @!visibility private
|
|
186
|
+
def initialize(data, bot)
|
|
187
|
+
@bot = bot
|
|
188
|
+
|
|
189
|
+
@server = bot.server(data['guild_id']) if data['guild_id']
|
|
190
|
+
@channel = bot.channel(data['channel_id'])
|
|
191
|
+
@last_pin_timestamp = Time.iso8601(data['last_pin_timestamp']) if data['last_pin_timestamp']
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Event handler for ChannelPinsUpdateEvent.
|
|
196
|
+
class ChannelPinsUpdateEventHandler < EventHandler
|
|
197
|
+
def matches?(event)
|
|
198
|
+
# Check for the proper event type.
|
|
199
|
+
return false unless event.is_a? ChannelPinsUpdateEvent
|
|
200
|
+
|
|
201
|
+
[
|
|
202
|
+
matches_all(@attributes[:server], event.server) { |a, e| a.resolve_id == e&.id },
|
|
203
|
+
matches_all(@attributes[:channel], event.channel) { |a, e| a.resolve_id == e.id }
|
|
204
|
+
].reduce(true, &:&)
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Raised when a user is added to a private channel
|
|
209
|
+
class ChannelRecipientAddEvent < ChannelRecipientEvent; end
|
|
210
|
+
|
|
211
|
+
# Event handler for ChannelRecipientAddEvent
|
|
212
|
+
class ChannelRecipientAddEventHandler < ChannelRecipientEventHandler; end
|
|
213
|
+
|
|
214
|
+
# Raised when a recipient that isn't the bot leaves or is kicked from a group channel
|
|
215
|
+
class ChannelRecipientRemoveEvent < ChannelRecipientEvent; end
|
|
216
|
+
|
|
217
|
+
# Event handler for ChannelRecipientRemoveEvent
|
|
218
|
+
class ChannelRecipientRemoveEventHandler < ChannelRecipientEventHandler; end
|
|
219
|
+
|
|
220
|
+
# Raised when a channel is updated (e.g. topic changes)
|
|
221
|
+
class ChannelUpdateEvent < ChannelCreateEvent; end
|
|
222
|
+
|
|
223
|
+
# Event handler for ChannelUpdateEvent
|
|
224
|
+
class ChannelUpdateEventHandler < ChannelCreateEventHandler; end
|
|
225
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Events used by onyxcord
|
|
4
|
+
module OnyxCord::Events
|
|
5
|
+
# A negated object, used to not match something in event parameters.
|
|
6
|
+
# @see OnyxCord::Events.matches_all
|
|
7
|
+
class Negated
|
|
8
|
+
attr_reader :object
|
|
9
|
+
|
|
10
|
+
# @!visibility private
|
|
11
|
+
def initialize(object)
|
|
12
|
+
@object = object
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Attempts to match possible formats of event attributes to a set comparison value, using a comparison block.
|
|
17
|
+
# It allows five kinds of attribute formats:
|
|
18
|
+
# 0. nil -> always returns true
|
|
19
|
+
# 1. A single attribute, not negated
|
|
20
|
+
# 2. A single attribute, negated
|
|
21
|
+
# 3. An array of attributes, not negated
|
|
22
|
+
# 4. An array of attributes, not negated
|
|
23
|
+
# Note that it doesn't allow an array of negated attributes. For info on negation stuff, see {::#not!}
|
|
24
|
+
# @param attributes [Object, Array<Object>, Negated<Object>, Negated<Array<Object>>, nil] One or more attributes to
|
|
25
|
+
# compare to the to_check value.
|
|
26
|
+
# @param to_check [Object] What to compare the attributes to.
|
|
27
|
+
# @yield [a, e] The block will be called when a comparison happens.
|
|
28
|
+
# @yieldparam [Object] a The attribute to compare to the value to check. Will always be a single not-negated object,
|
|
29
|
+
# all the negation and array handling is done by the method
|
|
30
|
+
# @yieldparam [Object] e The value to compare the attribute to. Will always be the value passed to the function as
|
|
31
|
+
# to_check.
|
|
32
|
+
# @yieldreturn [true, false] Whether or not the attribute a matches the given comparison value e.
|
|
33
|
+
# @return [true, false] whether the attributes match the comparison value in at least one way.
|
|
34
|
+
def self.matches_all(attributes, to_check, &block)
|
|
35
|
+
# "Zeroth" case: attributes is nil
|
|
36
|
+
return true if attributes.nil?
|
|
37
|
+
|
|
38
|
+
# First case: there's a single negated attribute
|
|
39
|
+
if attributes.is_a? Negated
|
|
40
|
+
# The contained object might also be an array, so recursively call matches_all (and negate the result)
|
|
41
|
+
return !matches_all(attributes.object, to_check, &block)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Second case: there's a single, not-negated attribute
|
|
45
|
+
return yield(attributes, to_check) unless attributes.is_a? Array
|
|
46
|
+
|
|
47
|
+
# Third case: it's an array of attributes
|
|
48
|
+
attributes.reduce(false) do |result, element|
|
|
49
|
+
result || yield(element, to_check)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Generic event class that can be extended
|
|
54
|
+
class Event
|
|
55
|
+
# @return [Bot] the bot used to initialize this event.
|
|
56
|
+
attr_reader :bot
|
|
57
|
+
|
|
58
|
+
class << self
|
|
59
|
+
protected
|
|
60
|
+
|
|
61
|
+
# Delegates a list of methods to a particular object. This is essentially a reimplementation of ActiveSupport's
|
|
62
|
+
# `#delegate`, but without the overhead provided by the rest. Used in subclasses of `Event` to delegate properties
|
|
63
|
+
# on events to properties on data objects.
|
|
64
|
+
# @param methods [Array<Symbol>] The methods to delegate.
|
|
65
|
+
# @param hash [Hash<Symbol => Symbol>] A hash with one `:to` key and the value the method to be delegated to.
|
|
66
|
+
def delegate(*methods, hash)
|
|
67
|
+
methods.each do |e|
|
|
68
|
+
define_method(e) do
|
|
69
|
+
object = __send__(hash[:to])
|
|
70
|
+
object.__send__(e)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Generic event handler that can be extended
|
|
78
|
+
class EventHandler
|
|
79
|
+
# @!visibility private
|
|
80
|
+
def initialize(attributes, block)
|
|
81
|
+
@attributes = attributes
|
|
82
|
+
@block = block
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Whether or not this event handler matches the given event with its attributes.
|
|
86
|
+
# @raise [RuntimeError] if this method is called - overwrite it in your event handler!
|
|
87
|
+
def matches?(_)
|
|
88
|
+
raise 'Attempted to call matches?() from a generic EventHandler'
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Checks whether this handler matches the given event, and then calls it.
|
|
92
|
+
# @param event [Object] The event object to match and call the handler with
|
|
93
|
+
def match(event)
|
|
94
|
+
call(event) if matches? event
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Calls this handler
|
|
98
|
+
# @param event [Object] The event object to call this handler with
|
|
99
|
+
def call(event)
|
|
100
|
+
@block.call(event)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# to be overwritten by extending event handlers
|
|
104
|
+
def after_call(event); end
|
|
105
|
+
|
|
106
|
+
# @see OnyxCord::Events::matches_all
|
|
107
|
+
def matches_all(attributes, to_check, &block)
|
|
108
|
+
OnyxCord::Events.matches_all(attributes, to_check, &block)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Event handler that matches all events. Only useful for making an event that has no attributes, such as {ReadyEvent}.
|
|
113
|
+
class TrueEventHandler < EventHandler
|
|
114
|
+
# Always returns true.
|
|
115
|
+
# @return [true]
|
|
116
|
+
def matches?(_)
|
|
117
|
+
true
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Utility function that creates a negated object for {OnyxCord::Events.matches_all}
|
|
123
|
+
# @param [Object] object The object to negate
|
|
124
|
+
# @see OnyxCord::Events::Negated
|
|
125
|
+
# @see OnyxCord::Events.matches_all
|
|
126
|
+
# @return [Negated<Object>] the object, negated, as an attribute to pass to matches_all
|
|
127
|
+
def not!(object)
|
|
128
|
+
OnyxCord::Events::Negated.new(object)
|
|
129
|
+
end
|