discorb 0.6.1 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d2ef47227e1e5895bdcaf6a67641d22319909c0f6a461d72ab35be1e0c9a42b
4
- data.tar.gz: 688a952b571421e8c43ca53b10f9404f6ba2abf8b9071222c35d3a10e34c5b7e
3
+ metadata.gz: c4197e97af48fc47c1062d0327ccc048cb8317701be673a2bce035b108f7cade
4
+ data.tar.gz: 7c48b69868636ca4722e3ec2aee50bb6148174c1cfdcf0b31a2d227110aefa76
5
5
  SHA512:
6
- metadata.gz: 9fd5eb78a1acda90e3c673a8745a2a9954ff8b8817c38210c5c609e6a85b16e4074b59bf8ae7bcc7725f7f45f22dfd785fb5edd321e9f61994bb071e4aa25a43
7
- data.tar.gz: 4bee75498af33d4716e033f51103382d8931c079495d27234cf07cf5e5b288891b40fb7e00902d3c1d7150249d0c820701d9962130890005bea5378e46af5ac8
6
+ metadata.gz: 7215a8dc3b0c3502f1948838aac8c08cc0ae0ac4c7c874dcc695c48fc5ead628f36718f08e7e2854aa46f191e9f0c851ff23a6f96aa82edaa3c7d7c912ff490b
7
+ data.tar.gz: 7ade9dcd2e56efb2513928a021d0f557d827a230b02f2c23ee6691cc9decc919f2e51b19e9e95fab13f535e8cc112cc8f3a29ac36e3a2144651a625e60ea0e25
data/.gitignore CHANGED
@@ -45,9 +45,9 @@ build-iPhoneSimulator/
45
45
 
46
46
  # for a library or gem, you might want to ignore these files since the code is
47
47
  # intended to run in multiple environments; otherwise, check them in:
48
- # Gemfile.lock
49
- # .ruby-version
50
- # .ruby-gemset
48
+ Gemfile.lock
49
+ .ruby-version
50
+ .ruby-gemset
51
51
 
52
52
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
53
  .rvmrc
data/.yardopts CHANGED
@@ -4,6 +4,7 @@
4
4
  --tag flags:"Flags"
5
5
  --verbose
6
6
  --asset docs/assets:assets
7
+ --asset assets:assets
7
8
  -
8
9
  docs/**/*.md
9
10
  Changelog.md
data/Changelog.md CHANGED
@@ -150,3 +150,44 @@
150
150
 
151
151
  - Change: Rename `Event#discriminator` to `Event#metadata`
152
152
  - Add: Add `:override` to `Client#on`
153
+
154
+ ## 0.7.0
155
+
156
+ - Add: Add `error` event
157
+ - Fix: Fix some issues with client without guild intent
158
+ - Add: Add alias for `#fired_by`
159
+ - Change!: Change block usage of `ApplicationCommand::Handler#group`
160
+
161
+ ```ruby
162
+ # before
163
+ client.slash_group do
164
+ slash "help", "Help" do |interaction|
165
+ # ...
166
+ end
167
+ end
168
+
169
+ # after
170
+ client.slash_group do |group|
171
+ group.slash "help", "Help" do |interaction|
172
+ # ...
173
+ end
174
+ end
175
+
176
+ ```
177
+
178
+ ## 0.7.1
179
+
180
+ - Fix: Fix error of responding to interaction
181
+
182
+ ## 0.7.2
183
+
184
+ - Add: Add `Member#owner?`
185
+ - Fix: Fix `Member#permissions`
186
+ - Add: Add `Member#guild_permissions` as alias of `Member#permissions`
187
+ - Add: Add default role to `Member#roles`
188
+ - Fix: Fix error in `Integration#_set_data`
189
+ - Change: Reverse `Member#roles`
190
+
191
+ ## 0.7.3
192
+
193
+ - Add: Improve `discorb init`
data/README.md CHANGED
@@ -1,9 +1,12 @@
1
- # discorb
2
- [![Document](https://img.shields.io/badge/Document-discord--lib.github.io-blue.svg)](https://discorb-lib.github.io/)
3
- [![Gem](https://img.shields.io/gem/dt/discorb?logo=rubygems&logoColor=fff)](https://rubygems.org/gems/discorb)
4
- [![Gem](https://img.shields.io/gem/v/discorb?logo=rubygems&logoColor=fff)](https://rubygems.org/gems/discorb)
5
- [![Discord](https://img.shields.io/discord/863581274916913193?logo=discord&logoColor=fff&color=5865f2&label=Discord)](https://discord.gg/hCP6zq8Vpj)
6
- [![GitHub](https://img.shields.io/github/stars/discorb-lib/discorb?color=24292e&label=Stars&logo=GitHub&logoColor=fff)](https://github.com/discorb-lib/discorb)
1
+ ![discorb](./assets/banner.svg)
2
+
3
+ <div align="center"><a href="https://discorb-lib.github.io/"><img src="https://img.shields.io/badge/Document-discorb--lib.github.io-blue.svg" alt="Document"></a>
4
+ <a href="https://rubygems.org/gems/discorb"><img src="https://img.shields.io/gem/dt/discorb?logo=rubygems&logoColor=fff" alt="Gem"></a>
5
+ <a href="https://rubygems.org/gems/discorb"><img src="https://img.shields.io/gem/v/discorb?logo=rubygems&logoColor=fff" alt="Gem"></a>
6
+ <a href="https://discord.gg/hCP6zq8Vpj"><img src="https://img.shields.io/discord/863581274916913193?logo=discord&logoColor=fff&color=5865f2&label=Discord" alt="Discord"></a>
7
+ <a href="https://github.com/discorb-lib/discorb"><img src="https://img.shields.io/github/stars/discorb-lib/discorb?color=24292e&label=Stars&logo=GitHub&logoColor=fff" alt="GitHub"></a></div>
8
+
9
+ ----
7
10
 
8
11
  discorb is a Discord API wrapper for Ruby.
9
12
 
data/assets/banner.svg ADDED
@@ -0,0 +1,125 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
5
+ y="0px" width="1080px" height="150px" viewBox="0 0 1080 150" enable-background="new 0 0 1080 150" xml:space="preserve">
6
+ <g>
7
+ <defs>
8
+ <rect id="SVGID_1_" x="283.667" y="-12.667" width="343.333" height="201.333"/>
9
+ </defs>
10
+ <clipPath id="SVGID_2_">
11
+ <use xlink:href="#SVGID_1_" overflow="visible"/>
12
+ </clipPath>
13
+ <g clip-path="url(#SVGID_2_)">
14
+ <g>
15
+ <g>
16
+ <path fill="#2E3338" d="M370.533,119.061c-13.503,0-21.565-10.312-21.565-27.582c0-18.543,9.872-30.525,25.149-30.525
17
+ c5.186,0,10.446,0.915,14.432,2.509l3.429,1.372V31.79l6.393-1.006v86.997h-4.456l-1.936-12.146l-3.522,4.208
18
+ C383.265,116.045,377.402,119.061,370.533,119.061z M374.501,65.554c-9.191,0-19.013,6.676-19.013,25.413
19
+ c0,13.96,6.559,22.98,16.708,22.98c7.18,0,13.308-3.736,19.286-11.758l0.495-0.665V69.983l-1.358-0.697
20
+ C385.253,66.53,381.035,65.554,374.501,65.554z"/>
21
+ </g>
22
+ <g>
23
+ <path fill="#2E3338" d="M419.624,117.78V61.721h6.393v56.059H419.624z M422.884,44.433c-2.645,0-4.796-2.094-4.796-4.668
24
+ c0-2.6,2.196-4.796,4.796-4.796c2.574,0,4.668,2.152,4.668,4.796C427.552,42.338,425.458,44.433,422.884,44.433z"/>
25
+ </g>
26
+ <g>
27
+ <path fill="#2E3338" d="M463.332,119.061c-7.015,0-14.662-2.282-19.529-4.647l0.809-5.23c4.905,2.794,11.627,5.405,19.616,5.405
28
+ c9.34,0,14.917-3.949,14.917-10.564c0-8.187-6.482-10.382-16.372-12.797c-13.937-3.485-18.19-7.314-18.19-16.388
29
+ c0-8.611,7.638-14.397,19.005-14.397c6.173,0,11.985,1.055,17.305,3.139l-0.902,5.412c-5.417-2.532-11.33-3.95-16.659-3.95
30
+ c-12.06,0-12.997,7.302-12.997,9.54c0,6.302,5.57,8.979,14.559,11.256c15.329,3.897,20.003,7.967,20.003,17.418
31
+ C484.897,113.3,477.037,119.061,463.332,119.061z"/>
32
+ </g>
33
+ <g>
34
+ <path fill="#2E3338" d="M523.746,119.061c-15.986,0-25.917-11.206-25.917-29.246c0-17.843,10.273-29.373,26.173-29.373
35
+ c6.897,0,12.696,1.453,17.263,4.322l-0.821,5.493c-5.086-3.282-10.441-4.83-16.57-4.83c-12.043,0-19.525,9.296-19.525,24.262
36
+ c0,15.271,7.777,24.389,20.805,24.389c6.137,0,11.114-1.451,15.996-4.757l0.746,4.59
37
+ C536.669,117.509,531.15,119.061,523.746,119.061z"/>
38
+ </g>
39
+ <g>
40
+ <path fill="#2E3338" d="M580.834,119.061c-15.511,0-25.533-11.479-25.533-29.246c0-17.843,10.022-29.373,25.533-29.373
41
+ c15.744,0,25.917,11.53,25.917,29.373C606.751,107.581,596.578,119.061,580.834,119.061z M580.834,65.042
42
+ c-11.729,0-19.014,9.492-19.014,24.772c0,15.049,7.463,24.773,19.014,24.773c11.964,0,19.396-9.492,19.396-24.773
43
+ C600.23,74.766,592.617,65.042,580.834,65.042z"/>
44
+ </g>
45
+ <g>
46
+ <path d="M623.652,117.78V61.721h4.444l2.615,16.91l3.563-5.661c3.16-5.019,8.634-11.016,17.176-12.309l0.981,5.953
47
+ c-9.186,1.447-17.664,7.67-22.117,16.437l-0.271,0.533v34.196H623.652z"/>
48
+ </g>
49
+ <g>
50
+ <path d="M688.224,118.549c-8.27,0-14.267-1.167-21.31-3.208V31.79l6.393-1.006V72.56l4.295-4.43
51
+ c5.017-5.173,10.417-7.688,16.51-7.688c13.302,0,21.565,10.569,21.565,27.582C715.677,107.423,705.671,118.549,688.224,118.549z
52
+ M692.447,65.554c-6.539,0-12.794,3.675-18.593,10.923l-0.548,0.685v33.856l1.64,0.601c3.981,1.461,7.108,2.202,13.148,2.202
53
+ c9.608,0,21.062-4.387,21.062-25.285C709.156,74.575,702.598,65.554,692.447,65.554z"/>
54
+ </g>
55
+ </g>
56
+ </g>
57
+ </g>
58
+ <g>
59
+ <defs>
60
+ <rect id="SVGID_3_" x="610.334" y="8" width="268" height="246"/>
61
+ </defs>
62
+ <clipPath id="SVGID_4_">
63
+ <use xlink:href="#SVGID_3_" overflow="visible"/>
64
+ </clipPath>
65
+ <g clip-path="url(#SVGID_4_)">
66
+ <g>
67
+ <path fill="#2E3338" d="M391.782,120.28l-1.408-8.833c-4.608,5.505-10.88,10.113-19.841,10.113
68
+ c-13.185,0-24.065-9.601-24.065-30.082c0-22.272,12.8-33.025,27.649-33.025c6.017,0,11.521,1.152,15.361,2.688v-31.49
69
+ l11.393-1.792v92.42H391.782z M389.478,71.51c-4.736-2.432-8.448-3.456-14.977-3.456c-9.601,0-16.513,7.809-16.513,22.913
70
+ c0,13.441,6.016,20.48,14.208,20.48c7.041,0,12.417-4.224,17.281-10.752V71.51z"/>
71
+ <path fill="#2E3338" d="M422.884,46.933c-3.968,0-7.296-3.2-7.296-7.168s3.328-7.296,7.296-7.296s7.168,3.328,7.168,7.296
72
+ S426.852,46.933,422.884,46.933z M417.124,120.28V59.221h11.393v61.059H417.124z"/>
73
+ <path fill="#2E3338" d="M463.332,121.561c-8.064,0-17.025-2.816-22.273-5.76l1.664-10.754c5.76,3.969,13.185,7.041,21.505,7.041
74
+ c7.808,0,12.417-2.944,12.417-8.064c0-5.633-3.456-7.68-14.465-10.368c-14.336-3.585-20.097-7.937-20.097-18.817
75
+ c0-9.729,8.192-16.897,21.505-16.897c7.552,0,14.336,1.536,20.097,4.096l-1.792,10.752c-5.376-3.072-12.161-5.248-18.561-5.248
76
+ c-6.913,0-10.497,2.688-10.497,7.04c0,4.096,3.072,6.4,12.672,8.832c15.105,3.841,21.889,8.193,21.889,19.842
77
+ C487.397,114.393,479.077,121.561,463.332,121.561z"/>
78
+ <path fill="#2E3338" d="M523.746,121.561c-16.385,0-28.417-11.393-28.417-31.746c0-20.865,12.8-31.873,28.673-31.873
79
+ c8.96,0,15.36,2.304,19.968,5.632l-1.664,11.136c-5.632-4.608-11.392-6.784-18.432-6.784c-9.985,0-17.025,7.552-17.025,21.762
80
+ c0,14.848,7.552,21.889,18.305,21.889c6.145,0,11.521-1.408,17.793-6.785l1.664,10.241
81
+ C538.339,119.768,531.938,121.561,523.746,121.561z"/>
82
+ <path fill="#2E3338" d="M580.834,121.561c-16.258,0-28.033-11.648-28.033-31.746c0-20.097,11.775-31.873,28.033-31.873
83
+ c16.385,0,28.417,11.776,28.417,31.873C609.251,109.912,597.219,121.561,580.834,121.561z M580.834,67.542
84
+ c-11.009,0-16.514,9.472-16.514,22.272c0,12.545,5.761,22.273,16.514,22.273c11.264,0,16.896-9.473,16.896-22.273
85
+ C597.73,77.271,591.842,67.542,580.834,67.542z"/>
86
+ <path fill="#CC342D" d="M632.545,84.183v36.098h-11.393V59.221h9.088l1.92,12.417c4.353-6.913,11.393-13.185,21.377-13.697
87
+ l1.793,10.88C645.217,69.334,636.641,76.118,632.545,84.183z"/>
88
+ <path fill="#CC342D" d="M688.224,121.049c-9.217,0-15.745-1.408-23.81-3.841V29.652l11.393-1.792v38.53
89
+ c4.096-4.224,9.984-8.448,18.305-8.448c13.185,0,24.065,9.729,24.065,30.082C718.177,110.296,705.888,121.049,688.224,121.049z
90
+ M692.447,68.054c-6.4,0-12.032,4.224-16.641,9.984v31.233c3.84,1.408,6.656,2.049,12.288,2.049
91
+ c11.905,0,18.562-7.041,18.562-22.785C706.656,75.222,700.64,68.054,692.447,68.054z"/>
92
+ </g>
93
+ </g>
94
+ </g>
95
+ <g>
96
+ </g>
97
+ <g>
98
+ </g>
99
+ <g>
100
+ </g>
101
+ <g>
102
+ </g>
103
+ <g>
104
+ </g>
105
+ <g>
106
+ </g>
107
+ <g>
108
+ </g>
109
+ <g>
110
+ </g>
111
+ <g>
112
+ </g>
113
+ <g>
114
+ </g>
115
+ <g>
116
+ </g>
117
+ <g>
118
+ </g>
119
+ <g>
120
+ </g>
121
+ <g>
122
+ </g>
123
+ <g>
124
+ </g>
125
+ </svg>
@@ -136,8 +136,8 @@ Since v0.5.1, You can use block for register commands.
136
136
 
137
137
  ```ruby
138
138
 
139
- client.slash_group("settings", "Set settings of bot.") do
140
- slash("message_expand", "Whether bot should expand message.", {
139
+ client.slash_group("settings", "Set settings of bot.") do |group|
140
+ group.slash("message_expand", "Whether bot should expand message.", {
141
141
  "enabled" => {
142
142
  type: :boolean,
143
143
  description: "Whether bot should expand message."
@@ -145,7 +145,7 @@ client.slash_group("settings", "Set settings of bot.") do
145
145
  }) do |interaction|
146
146
  # ...
147
147
  end
148
- slash("bump_alert", "Whether bot should notify DISBOARD bump.", {
148
+ group.slash("bump_alert", "Whether bot should notify DISBOARD bump.", {
149
149
  "enabled" => {
150
150
  type: :boolean,
151
151
  description: "Whether bot should notify DISBOARD bump."
@@ -164,14 +164,14 @@ group = client.slash_group("permission", "Set/Get command permissions.")
164
164
  group_user = group.group("user", "Set/Get user's command permissions.")
165
165
 
166
166
  group_user.slash("set", "Set user's command permissions.", {
167
- "user_id" => {
168
- type: :user,
169
- description: "The user."
170
- },
171
- "value" => {
172
- type: :boolean,
173
- description: "Whether the user can use the command."
174
- }
167
+ "user_id" => {
168
+ type: :user,
169
+ description: "The user."
170
+ },
171
+ "value" => {
172
+ type: :boolean,
173
+ description: "Whether the user can use the command."
174
+ }
175
175
  }) do |interaction, user|
176
176
  # ...
177
177
  end
data/docs/cli/init.md CHANGED
@@ -32,6 +32,18 @@ If true, the command will initialize git and commit the initial files with commi
32
32
  Use `git commit --amend -m "..."` to change the commit message.
33
33
  Default to false.
34
34
 
35
+ ### `--[no-]desc`
36
+
37
+ Whether to create a description file.
38
+ If true, the command will create a `.env.sample` and `README.md` file.
39
+ Default to false.
40
+
41
+ ### `-n` `--name`
42
+
43
+ The name of the project.
44
+ It will be used in the `README.md` file.
45
+ Default to the directory name.
46
+
35
47
  ### `-t`, `--token`
36
48
 
37
49
  The name of token environment variable.
@@ -49,7 +61,9 @@ The following files will be created:
49
61
  | File | Description |
50
62
  | ---- | ----------- |
51
63
  | `.env` | Environment variables. |
64
+ | `main.rb` | Main script. |
52
65
  | `.gitignore` | Git ignore file. Won't be created if `--git` is false. |
53
66
  | `Gemfile` | Gemfile. Won't be created if `--bundle` is false. |
54
67
  | `Gemfile.lock` | Gemfile lock file. Won't be created if `--bundle` is false. |
55
- | `main.rb` | Main script. |
68
+ | `README.md` | Readme file. Won't be created if `--desc` is false. |
69
+ | `.env.sample` | Sample environment variables. Won't be created if `--desc` is false. |
data/docs/events.md CHANGED
@@ -79,6 +79,11 @@ Fires when the client is ready.
79
79
 
80
80
  Fires when the client is resumed connection.
81
81
 
82
+ #### `error(event_name, args, error)`
83
+
84
+ Fires when an error occurs during an event.
85
+ Defaults to printing the error to stderr, override to handle it yourself.
86
+
82
87
  ### Guild events
83
88
 
84
89
  #### `guild_join(guild)`
data/docs/extension.md CHANGED
@@ -46,13 +46,13 @@ module MyExtension
46
46
  # ...
47
47
  end
48
48
 
49
- slash_group("group", "Group") do
50
- slash("subcommand", "Subcommand") do |interaction|
49
+ slash_group("group", "Group") do |group|
50
+ group.slash("subcommand", "Subcommand") do |interaction|
51
51
  # ...
52
52
  end
53
53
 
54
- group("subgroup", "Subcommand group") do
55
- slash("group_subcommand", "Command in Subcommand group") do |interaction|
54
+ group.group("subgroup", "Subcommand group") do |group|
55
+ group.slash("group_subcommand", "Command in Subcommand group") do |interaction|
56
56
  # ...
57
57
  end
58
58
  end
@@ -86,7 +86,7 @@ module MyExtension
86
86
  extend Discorb::Extension
87
87
 
88
88
  event :ready do |message|
89
- puts "Logged in as #{client.user}"
89
+ puts "Logged in as #{@client.user}"
90
90
  end
91
91
  end
92
92
  ```
@@ -46,8 +46,8 @@ module Discorb
46
46
  # @param [String] description Command description.
47
47
  # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
48
48
  #
49
- # @yield Block to execute as the command. It can be used to define sub-commands.
50
- # @yieldself [Discorb::ApplicationCommand::Command::GroupCommand] Group command.
49
+ # @yield Block to yield with the command.
50
+ # @yieldparam [Discorb::ApplicationCommand::Command::GroupCommand] group Group command.
51
51
  #
52
52
  # @return [Discorb::ApplicationCommand::Command::GroupCommand] Command object.
53
53
  #
@@ -56,7 +56,7 @@ module Discorb
56
56
  #
57
57
  def slash_group(command_name, description, guild_ids: nil, &block)
58
58
  command = Discorb::ApplicationCommand::Command::GroupCommand.new(command_name, description, guild_ids, nil, self)
59
- command.instance_eval(&block) if block_given?
59
+ command.yield_self(&block) if block_given?
60
60
  @commands << command
61
61
  command
62
62
  end
@@ -284,8 +284,8 @@ module Discorb
284
284
  # @param [String] command_name Group name.
285
285
  # @param [String] description Group description.
286
286
  #
287
- # @yield Block to execute as the command. It can be used to define sub-commands.
288
- # @yieldself [Discorb::ApplicationCommand::Command::SubcommandGroup] Group command.
287
+ # @yield Block to yield with the command.
288
+ # @yieldparam [Discorb::ApplicationCommand::Command::SubcommandGroup] group Group command.
289
289
  #
290
290
  # @return [Discorb::ApplicationCommand::Command::SubcommandGroup] Command object.
291
291
  #
@@ -293,7 +293,7 @@ module Discorb
293
293
  #
294
294
  def group(command_name, description, &block)
295
295
  command = Discorb::ApplicationCommand::Command::SubcommandGroup.new(command_name, description, @name, @client)
296
- command.instance_eval(&block) if block_given?
296
+ command.yield_self(&block) if block_given?
297
297
  @commands << command
298
298
  command
299
299
  end
@@ -91,6 +91,7 @@ module Discorb
91
91
  @commands = []
92
92
  @bottom_commands = []
93
93
  @status = :initialized
94
+ set_default_events
94
95
  end
95
96
 
96
97
  #
@@ -172,23 +173,17 @@ module Discorb
172
173
  end
173
174
  @log.debug "Dispatching event #{event_name}"
174
175
  events.each do |block|
175
- lambda { |event_args|
176
+ Async do
176
177
  Async(annotation: "Discorb event: #{event_name}") do |task|
177
178
  if block.is_a?(Discorb::Event)
178
179
  @events[event_name].delete(block) if block.metadata[:once]
179
180
  end
180
- block.call(*event_args)
181
+ block.call(*args)
181
182
  @log.debug "Dispatched proc with ID #{block.id.inspect}"
182
183
  rescue StandardError, ScriptError => e
183
- message = "An error occurred while dispatching proc with ID #{block.id.inspect}\n#{e.full_message}"
184
- dispatch(:error, event_name, event_args, e)
185
- if @log.out
186
- @log.error message
187
- else
188
- warn message
189
- end
184
+ dispatch(:error, event_name, args, e)
190
185
  end
191
- }.call(args)
186
+ end
192
187
  end
193
188
  end
194
189
  end
@@ -482,5 +477,12 @@ module Discorb
482
477
  @main_task.stop
483
478
  end
484
479
  end
480
+
481
+ def set_default_events
482
+ on :error, override: true do |event_name, _args, e|
483
+ message = "An error occurred while dispatching #{event_name}:\n#{e.full_message}"
484
+ @log.error message, fallback: $stderr
485
+ end
486
+ end
485
487
  end
486
488
  end
@@ -4,7 +4,7 @@ module Discorb
4
4
  # @return [String] The API base URL.
5
5
  API_BASE_URL = "https://discord.com/api/v9"
6
6
  # @return [String] The version of discorb.
7
- VERSION = "0.6.1"
7
+ VERSION = "0.7.3"
8
8
  # @return [String] The user agent for the bot.
9
9
  USER_AGENT = "DiscordBot (https://github.com/discorb-lib/discorb #{VERSION}) Ruby/#{RUBY_VERSION}"
10
10
 
data/lib/discorb/embed.rb CHANGED
@@ -93,18 +93,18 @@ module Discorb
93
93
  # @return [Hash] Converted embed.
94
94
  #
95
95
  def to_hash
96
- {
97
- title: @title,
98
- description: @description,
99
- url: @url,
100
- timestamp: @timestamp&.iso8601,
101
- color: @color&.to_i,
102
- footer: @footer&.to_hash,
103
- image: @image&.to_hash,
104
- thumbnail: @thumbnail&.to_hash,
105
- author: @author&.to_hash,
106
- fields: @fields&.map { |f| f.to_hash },
107
- }
96
+ ret = { type: "rich" }
97
+ ret[:title] = @title if @title
98
+ ret[:description] = @description if @description
99
+ ret[:url] = @url if @url
100
+ ret[:timestamp] = @timestamp&.iso8601 if @timestamp
101
+ ret[:color] = @color&.to_i if @color
102
+ ret[:footer] = @footer&.to_hash if @footer
103
+ ret[:image] = @image&.to_hash if @image
104
+ ret[:thumbnail] = @thumbnail&.to_hash if @thumbnail
105
+ ret[:author] = @author&.to_hash if @author
106
+ ret[:fields] = @fields&.map { |f| f.to_hash } if @fields.any?
107
+ ret
108
108
  end
109
109
 
110
110
  #
@@ -96,11 +96,46 @@ FILES = {
96
96
  gem "discorb", "~> #{Discorb::VERSION}"
97
97
  gem "dotenv", "~> 2.7"
98
98
  RUBY
99
+ ".env.sample" => <<~BASH,
100
+ %<token>s=
101
+ BASH
102
+ "README.md" => <<~MARKDOWN,
103
+ # %<name>s
104
+
105
+ Welcome to your bot: %<name>s!
106
+
107
+ TODO: Write your bot's description here.
108
+
109
+ ## Usage
110
+
111
+ TODO: Write your bot's usage here.
112
+
113
+ ## Features
114
+
115
+ TODO: Write your bot's features here.
116
+
117
+ ## How to host
118
+
119
+ 1. Clone the repository.
120
+ 2. Run `bundle install`.
121
+ 3. Get your bot's token from the Discord developer portal.
122
+ 4. Copy `.env.sample` to `.env` and fill in the token.
123
+ 5. Run `bundle exec discorb run`.
124
+
125
+ TODO: Write your own customizations here.
126
+
127
+ ## License
128
+
129
+ TODO: Write your bot's license here.
130
+ See https://choosealicense.com/ for more information.
131
+ https://rubygems.org/gems/license-cli may be useful.
132
+
133
+ MARKDOWN
99
134
  }
100
135
 
101
136
  # @!visibility private
102
137
  def create_file(name)
103
- File.write($path + "/#{name}", format(FILES[name], token: $values[:token]), mode: "wb")
138
+ File.write($path + "/#{name}", format(FILES[name], token: $values[:token], name: $values[:name]), mode: "wb")
104
139
  end
105
140
 
106
141
  # @!visibility private
@@ -132,6 +167,14 @@ def git_init
132
167
  " to change commit message of initial commit.\n"
133
168
  end
134
169
 
170
+ # @!visibility private
171
+ def make_descs
172
+ iputs "Making descriptions..."
173
+ create_file(".env.sample")
174
+ create_file("README.md")
175
+ sputs "Made descriptions.\n"
176
+ end
177
+
135
178
  opt = OptionParser.new <<~BANNER
136
179
  A tool to make a new project.
137
180
 
@@ -145,6 +188,8 @@ $values = {
145
188
  git: false,
146
189
  force: false,
147
190
  token: "TOKEN",
191
+ descs: false,
192
+ name: nil,
148
193
  }
149
194
 
150
195
  opt.on("--[no-]bundle", "Whether to use bundle. Default to true.") do |v|
@@ -155,10 +200,18 @@ opt.on("--[no-]git", "Whether to initialize git. Default to false.") do |v|
155
200
  $values[:git] = v
156
201
  end
157
202
 
203
+ opt.on("--[no-]descs", "Whether to put some file for description. Default to false.") do |v|
204
+ $values[:descs] = v
205
+ end
206
+
158
207
  opt.on("-t NAME", "--token NAME", "The name of token environment variable. Default to TOKEN.") do |v|
159
208
  $values[:token] = v
160
209
  end
161
210
 
211
+ opt.on("-n NAME", "--name NAME", "The name of your project. Default to the directory name.") do |v|
212
+ $values[:name] = v
213
+ end
214
+
162
215
  opt.on("-f", "--force", "Whether to force use directory. Default to false.") do |v|
163
216
  $values[:force] = v
164
217
  end
@@ -187,10 +240,14 @@ if (dir = ARGV[0])
187
240
  Dir.chdir($path)
188
241
  end
189
242
 
243
+ $values[:name] ||= Dir.pwd.split("/").last
244
+
190
245
  bundle_init if $values[:bundle]
191
246
 
192
247
  make_files
193
248
 
194
249
  git_init if $values[:git]
195
250
 
251
+ make_descs if $values[:descs]
252
+
196
253
  sputs "\nSuccessfully made a new project at \e[32m#{$path}\e[92m."
@@ -53,6 +53,12 @@ module Discorb
53
53
  attr_reader :member
54
54
  # @return [Discorb::UnicodeEmoji, Discorb::PartialEmoji] The emoji that was reacted with.
55
55
  attr_reader :emoji
56
+ # @macro client_cache
57
+ # @return [Discorb::Member, Discorb::User] The user or member who reacted.
58
+ attr_reader :fired_by
59
+
60
+ alias reactor fired_by
61
+ alias from fired_by
56
62
 
57
63
  # @!visibility private
58
64
  def initialize(client, data)
@@ -79,6 +85,8 @@ module Discorb
79
85
  end
80
86
  end
81
87
 
88
+ @fired_by = @member || @user || @client.users[data[:user_id]]
89
+
82
90
  @message = client.messages[data[:message_id]]
83
91
  @emoji = data[:emoji][:id].nil? ? UnicodeEmoji.new(data[:emoji][:name]) : PartialEmoji.new(data[:emoji])
84
92
  end
@@ -355,6 +363,9 @@ module Discorb
355
363
  class TypingStartEvent < GatewayEvent
356
364
  # @return [Discorb::Snowflake] The ID of the channel the user is typing in.
357
365
  attr_reader :user_id
366
+ # @macro client_cache
367
+ # @return [Discorb::Member] The member that is typing.
368
+ attr_reader :member
358
369
 
359
370
  # @!attribute [r] channel
360
371
  # @macro client_cache
@@ -365,6 +376,9 @@ module Discorb
365
376
  # @!attribute [r] user
366
377
  # @macro client_cache
367
378
  # @return [Discorb::User] The user that is typing.
379
+ # @!attribute [r] fired_by
380
+ # @macro client_cache
381
+ # @return [Discorb::Member, Discorb::User] The member or user that started typing.
368
382
 
369
383
  # @!visibility private
370
384
  def initialize(client, data)
@@ -388,6 +402,12 @@ module Discorb
388
402
  def guild
389
403
  @client.guilds[@guild_id]
390
404
  end
405
+
406
+ def fired_by
407
+ @member || user
408
+ end
409
+
410
+ alias from fired_by
391
411
  end
392
412
 
393
413
  #
@@ -584,10 +604,10 @@ module Discorb
584
604
  @session_id = data[:session_id]
585
605
  @user = ClientUser.new(self, data[:user])
586
606
  @uncached_guilds = data[:guilds].map { |g| g[:id] }
587
- if @uncached_guilds == []
607
+ if @uncached_guilds == [] or !@intents.guilds
588
608
  @ready = true
589
609
  dispatch(:ready)
590
- @log.info("Guilds were cached")
610
+ @log.info("Successfully connected to Discord.")
591
611
  end
592
612
  @tasks << handle_heartbeat(@heartbeat_interval)
593
613
  when "GUILD_CREATE"
@@ -597,7 +617,7 @@ module Discorb
597
617
  if @uncached_guilds == []
598
618
  @ready = true
599
619
  dispatch(:ready)
600
- @log.info("Guilds were cached")
620
+ @log.info("Successfully connected to Discord, and cached all guilds.")
601
621
  end
602
622
  elsif @guilds.has?(data[:id])
603
623
  @guilds[data[:id]].send(:_set_data, data)
@@ -80,7 +80,7 @@ module Discorb
80
80
  @enable_emoticons = data[:enable_emoticons]
81
81
  @expire_behavior = self.class.expire_behavior[data[:expire_behavior]]
82
82
  @expire_grace_period = data[:expire_grace_period]
83
- @user = client.users[data[:user].to_i]
83
+ @user = @client.users[data[:user].to_i]
84
84
  @account = Account.new(data[:account])
85
85
  @subscriber_count = data[:subscriber_count]
86
86
  @revoked = data[:revoked]
@@ -64,6 +64,7 @@ module Discorb
64
64
  end
65
65
 
66
66
  alias fired_by target
67
+ alias from target
67
68
 
68
69
  def inspect
69
70
  "#<#{self.class} id=#{@id}>"
@@ -99,6 +100,9 @@ module Discorb
99
100
  #
100
101
  # Response with `DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE`(`5`).
101
102
  #
103
+ # @macro async
104
+ # @macro http
105
+ #
102
106
  # @param [Boolean] ephemeral Whether to make the response ephemeral.
103
107
  #
104
108
  def defer_source(ephemeral: false)
@@ -116,6 +120,9 @@ module Discorb
116
120
  #
117
121
  # Response with `CHANNEL_MESSAGE_WITH_SOURCE`(`4`).
118
122
  #
123
+ # @macro async
124
+ # @macro http
125
+ #
119
126
  # @param [String] content The content of the response.
120
127
  # @param [Boolean] tts Whether to send the message as text-to-speech.
121
128
  # @param [Discorb::Embed] embed The embed to send.
@@ -125,45 +132,48 @@ module Discorb
125
132
  # @param [Boolean] ephemeral Whether to make the response ephemeral.
126
133
  #
127
134
  def post(content = nil, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
128
- payload = {}
129
- payload[:content] = content if content
130
- payload[:tts] = tts
131
- tmp_embed = if embed
132
- [embed]
133
- elsif embeds
134
- embeds
135
- end
136
- payload[:embeds] = tmp_embed.map(&:to_hash) if tmp_embed
137
- payload[:allowed_mentions] = allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
138
- if components
139
- tmp_components = []
140
- tmp_row = []
141
- components.each do |c|
142
- case c
143
- when Array
144
- tmp_components << tmp_row
145
- tmp_row = []
146
- tmp_components << c
147
- when SelectMenu
148
- tmp_components << tmp_row
149
- tmp_row = []
150
- tmp_components << [c]
151
- else
152
- tmp_row << c
135
+ Async do
136
+ payload = {}
137
+ payload[:content] = content if content
138
+ payload[:tts] = tts
139
+ tmp_embed = if embed
140
+ [embed]
141
+ elsif embeds
142
+ embeds
143
+ end
144
+ payload[:embeds] = tmp_embed.map(&:to_hash) if tmp_embed
145
+ payload[:allowed_mentions] = allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
146
+ if components
147
+ tmp_components = []
148
+ tmp_row = []
149
+ components.each do |c|
150
+ case c
151
+ when Array
152
+ tmp_components << tmp_row
153
+ tmp_row = []
154
+ tmp_components << c
155
+ when SelectMenu
156
+ tmp_components << tmp_row
157
+ tmp_row = []
158
+ tmp_components << [c]
159
+ else
160
+ tmp_row << c
161
+ end
153
162
  end
163
+ tmp_components << tmp_row
164
+ payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
154
165
  end
155
- tmp_components << tmp_row
156
- payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
157
- end
158
- payload[:flags] = (ephemeral ? 1 << 6 : 0)
159
- if @responded
160
- @client.http.post("/webhooks/#{@id}/#{@token}", { type: 4, data: payload }).wait
161
- elsif @defered
162
- @client.http.post("/interactions/#{@id}/#{@token}/@original/edit", { type: 4, data: payload }).wait
163
- else
164
- @client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 4, data: payload }).wait
166
+ payload[:flags] = (ephemeral ? 1 << 6 : 0)
167
+
168
+ if @responded
169
+ @client.http.post("/webhooks/#{@application_id}/#{@token}", payload).wait
170
+ elsif @defered
171
+ @client.http.patch("/webhooks/#{@application_id}/#{@token}/messages/@original", payload).wait
172
+ else
173
+ @client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 4, data: payload }).wait
174
+ end
175
+ @responded = true
165
176
  end
166
- @responded = true
167
177
  end
168
178
  end
169
179
 
@@ -190,6 +200,9 @@ module Discorb
190
200
  #
191
201
  # Response with `UPDATE_MESSAGE`(`7`).
192
202
  #
203
+ # @macro async
204
+ # @macro http
205
+ #
193
206
  # @param [String] content The content of the response.
194
207
  # @param [Boolean] tts Whether to send the message as text-to-speech.
195
208
  # @param [Discorb::Embed] embed The embed to send.
@@ -199,38 +212,40 @@ module Discorb
199
212
  # @param [Boolean] ephemeral Whether to make the response ephemeral.
200
213
  #
201
214
  def edit(content, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
202
- payload = {}
203
- payload[:content] = content if content
204
- payload[:tts] = tts
205
- tmp_embed = if embed
206
- [embed]
207
- elsif embeds
208
- embeds
209
- end
210
- payload[:embeds] = tmp_embed.map(&:to_hash) if tmp_embed
211
- payload[:allowed_mentions] = allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
212
- if components
213
- tmp_components = []
214
- tmp_row = []
215
- components.each do |c|
216
- case c
217
- when Array
218
- tmp_components << tmp_row
219
- tmp_row = []
220
- tmp_components << c
221
- when SelectMenu
222
- tmp_components << tmp_row
223
- tmp_row = []
224
- tmp_components << [c]
225
- else
226
- tmp_row << c
215
+ Async do
216
+ payload = {}
217
+ payload[:content] = content if content
218
+ payload[:tts] = tts
219
+ tmp_embed = if embed
220
+ [embed]
221
+ elsif embeds
222
+ embeds
223
+ end
224
+ payload[:embeds] = tmp_embed.map(&:to_hash) if tmp_embed
225
+ payload[:allowed_mentions] = allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
226
+ if components
227
+ tmp_components = []
228
+ tmp_row = []
229
+ components.each do |c|
230
+ case c
231
+ when Array
232
+ tmp_components << tmp_row
233
+ tmp_row = []
234
+ tmp_components << c
235
+ when SelectMenu
236
+ tmp_components << tmp_row
237
+ tmp_row = []
238
+ tmp_components << [c]
239
+ else
240
+ tmp_row << c
241
+ end
227
242
  end
243
+ tmp_components << tmp_row
244
+ payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
228
245
  end
229
- tmp_components << tmp_row
230
- payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
246
+ payload[:flags] = (ephemeral ? 1 << 6 : 0)
247
+ @client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 6, data: payload }).wait
231
248
  end
232
- payload[:flags] = (ephemeral ? 1 << 6 : 0)
233
- @client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 6, data: payload }).wait
234
249
  end
235
250
  end
236
251
 
data/lib/discorb/log.rb CHANGED
@@ -22,34 +22,34 @@ module Discorb
22
22
  raise ArgumentError, "Invalid log level: #{level}" unless @level
23
23
  end
24
24
 
25
- def debug(message)
25
+ def debug(message, fallback: nil)
26
26
  return unless @level <= 0
27
27
 
28
- write_output("DEBUG", "\e[90m", message)
28
+ write_output("DEBUG", "\e[90m", message, fallback)
29
29
  end
30
30
 
31
- def info(message)
31
+ def info(message, fallback: nil)
32
32
  return unless @level <= 1
33
33
 
34
- write_output("INFO", "\e[94m", message)
34
+ write_output("INFO", "\e[94m", message, fallback)
35
35
  end
36
36
 
37
- def warn(message)
37
+ def warn(message, fallback: nil)
38
38
  return unless @level <= 2
39
39
 
40
- write_output("WARN", "\e[93m", message)
40
+ write_output("WARN", "\e[93m", message, fallback)
41
41
  end
42
42
 
43
- def error(message)
43
+ def error(message, fallback: nil)
44
44
  return unless @level <= 3
45
45
 
46
- write_output("ERROR", "\e[31m", message)
46
+ write_output("ERROR", "\e[31m", message, fallback)
47
47
  end
48
48
 
49
- def fatal(message)
49
+ def fatal(message, fallback: nil)
50
50
  return unless @level <= 4
51
51
 
52
- write_output("FATAL", "\e[91m", message)
52
+ write_output("FATAL", "\e[91m", message, fallback)
53
53
  end
54
54
 
55
55
  class << self
@@ -58,8 +58,12 @@ module Discorb
58
58
 
59
59
  private
60
60
 
61
- def write_output(name, color, message)
62
- return unless @out
61
+ def write_output(name, color, message, fallback)
62
+ unless @out
63
+ fallback.puts(message) if fallback
64
+
65
+ return
66
+ end
63
67
 
64
68
  if @colorize_log
65
69
  @out.puts("\e[2;90m[#{Time.now.iso8601}] #{color}#{name}\e[m -- #{message}")
@@ -59,6 +59,8 @@ module Discorb
59
59
  # @!attribute [r] status
60
60
  # @macro client_cache
61
61
  # @return [Symbol] The status of the member. It's from the {#presence}.
62
+ # @!attribute [r] owner?
63
+ # @return [Boolean] Whether the member is the owner of the guild.
62
64
 
63
65
  # @!visibility private
64
66
  def initialize(client, guild_id, user_data, member_data)
@@ -99,18 +101,27 @@ module Discorb
99
101
  guild.voice_states[@id]
100
102
  end
101
103
 
104
+ def owner?
105
+ guild.owner_id == @id
106
+ end
107
+
102
108
  def guild
103
109
  @client.guilds[@guild_id]
104
110
  end
105
111
 
106
112
  def roles
107
- @role_ids.map { |r| guild.roles[r] }
113
+ @role_ids.map { |r| guild.roles[r] }.sort_by(&:position).reverse + [guild.roles[guild.id]]
108
114
  end
109
115
 
110
116
  def permissions
117
+ if owner?
118
+ return Permission.new((1 << 38) - 1)
119
+ end
111
120
  roles.map(&:permissions).sum(Permission.new(0))
112
121
  end
113
122
 
123
+ alias guild_permissions permissions
124
+
114
125
  def hoisted_role
115
126
  @hoisted_role_id && guild.roles[@hoisted_role_id]
116
127
  end
@@ -234,7 +245,7 @@ module Discorb
234
245
  @custom_avatar = member_data[:avatar] && Asset.new(member_data[:avatar])
235
246
  super(user_data)
236
247
  @display_avatar = @avatar || @custom_avatar
237
- @client.guilds[@guild_id].members[@id] = self unless @guild_id.nil?
248
+ @client.guilds[@guild_id].members[@id] = self unless @guild_id.nil? || @client.guilds[@guild_id].nil?
238
249
  @_member_data.update(member_data)
239
250
  end
240
251
  end
@@ -522,11 +522,11 @@ module Discorb
522
522
  if data[:member].nil? && data[:webhook_id]
523
523
  @webhook_id = Snowflake.new(data[:webhook_id])
524
524
  @author = Webhook::Message::Author.new(data[:author])
525
- elsif data[:guild_id].nil? || data[:guild_id].empty?
525
+ elsif data[:guild_id].nil? || data[:guild_id].empty? || data[:member].nil?
526
526
  @author = @client.users[data[:author][:id]] || User.new(@client, data[:author])
527
527
  else
528
- @author = guild.members[data[:author][:id]] || Member.new(@client,
529
- @guild_id, data[:author], data[:member])
528
+ @author = guild&.members&.get(data[:author][:id]) || Member.new(@client,
529
+ @guild_id, data[:author], data[:member])
530
530
  end
531
531
  @content = data[:content]
532
532
  @created_at = Time.iso8601(data[:timestamp])
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: discorb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - sevenc-nanashi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-17 00:00:00.000000000 Z
11
+ date: 2021-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -82,10 +82,10 @@ files:
82
82
  - ".yardopts"
83
83
  - Changelog.md
84
84
  - Gemfile
85
- - Gemfile.lock
86
85
  - LICENSE.txt
87
86
  - README.md
88
87
  - Rakefile
88
+ - assets/banner.svg
89
89
  - bin/console
90
90
  - bin/setup
91
91
  - crowdin.yml
data/Gemfile.lock DELETED
@@ -1,67 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- discorb (0.6.1)
5
- async (~> 1.30.1)
6
- async-http (~> 0.56.5)
7
- async-websocket (~> 0.19.0)
8
- mime-types (~> 3.3)
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- async (1.30.1)
14
- console (~> 1.10)
15
- nio4r (~> 2.3)
16
- timers (~> 4.1)
17
- async-http (0.56.5)
18
- async (>= 1.25)
19
- async-io (>= 1.28)
20
- async-pool (>= 0.2)
21
- protocol-http (~> 0.22.0)
22
- protocol-http1 (~> 0.14.0)
23
- protocol-http2 (~> 0.14.0)
24
- async-io (1.32.2)
25
- async
26
- async-pool (0.3.8)
27
- async (>= 1.25)
28
- async-websocket (0.19.0)
29
- async-http (~> 0.54)
30
- async-io (~> 1.23)
31
- protocol-websocket (~> 0.7.0)
32
- console (1.13.1)
33
- fiber-local
34
- fiber-local (1.0.0)
35
- mime-types (3.3.1)
36
- mime-types-data (~> 3.2015)
37
- mime-types-data (3.2021.0901)
38
- nio4r (2.5.8)
39
- protocol-hpack (1.4.2)
40
- protocol-http (0.22.5)
41
- protocol-http1 (0.14.2)
42
- protocol-http (~> 0.22)
43
- protocol-http2 (0.14.2)
44
- protocol-hpack (~> 1.4)
45
- protocol-http (~> 0.18)
46
- protocol-websocket (0.7.5)
47
- protocol-http (~> 0.2)
48
- protocol-http1 (~> 0.2)
49
- rake (13.0.6)
50
- redcarpet (3.5.1)
51
- rufo (0.13.0)
52
- timers (4.3.3)
53
- yard (0.9.26)
54
-
55
- PLATFORMS
56
- x86-mingw32
57
- x86_64-linux
58
-
59
- DEPENDENCIES
60
- discorb!
61
- rake (~> 13.0)
62
- redcarpet
63
- rufo (~> 0.13.0)
64
- yard (~> 0.9.26)
65
-
66
- BUNDLED WITH
67
- 2.2.22