khl 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/README.md +53 -0
- data/lib/khl/http/asset.rb +19 -0
- data/lib/khl/http/badge.rb +20 -0
- data/lib/khl/http/base.rb +101 -0
- data/lib/khl/http/blacklist.rb +41 -0
- data/lib/khl/http/channel.rb +58 -0
- data/lib/khl/http/channel_role.rb +50 -0
- data/lib/khl/http/channel_user.rb +22 -0
- data/lib/khl/http/client.rb +78 -0
- data/lib/khl/http/direct_message.rb +85 -0
- data/lib/khl/http/game.rb +59 -0
- data/lib/khl/http/gateway.rb +19 -0
- data/lib/khl/http/guild.rb +70 -0
- data/lib/khl/http/guild_emoji.rb +46 -0
- data/lib/khl/http/guild_mute.rb +38 -0
- data/lib/khl/http/guild_role.rb +70 -0
- data/lib/khl/http/intimacy.rb +29 -0
- data/lib/khl/http/invite.rb +43 -0
- data/lib/khl/http/message.rb +92 -0
- data/lib/khl/http/response.rb +69 -0
- data/lib/khl/http/user.rb +32 -0
- data/lib/khl/http/user_chat.rb +42 -0
- data/lib/khl/version.rb +5 -0
- data/lib/khl/web_socket/client.rb +151 -0
- data/lib/khl/web_socket/message.rb +54 -0
- data/lib/khl.rb +6 -0
- metadata +108 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 服务器相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/guild
|
9
|
+
class Guild < Base
|
10
|
+
# 获取当前用户加入的服务器列表
|
11
|
+
# @param [Hash] options 可选参数
|
12
|
+
# @option options [Integer] :page 页数
|
13
|
+
# @option options [Integer] :page_size 每页数据数量
|
14
|
+
# @option options [String] :sort 代表排序的字段,比如 -id 代表 id 按 DESC 排序,id 代表 id 按 ASC 排序
|
15
|
+
# @return [KHL::HTTP::Response]
|
16
|
+
def list(options = {})
|
17
|
+
get(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# 获取服务器详情
|
21
|
+
# @param [String] guild_id 服务器 ID
|
22
|
+
# @return [KHL::HTTP::Response]
|
23
|
+
def view(guild_id)
|
24
|
+
get(guild_id: guild_id)
|
25
|
+
end
|
26
|
+
|
27
|
+
# 获取服务器中的用户列表
|
28
|
+
# @param [String] guild_id 服务器 ID
|
29
|
+
# @param [Hash] options 可选参数
|
30
|
+
# @option options [String] :channel_id 频道 ID
|
31
|
+
# @option options [String] :search 搜索关键字,在用户名或昵称中搜索
|
32
|
+
# @option options [Integer] :role_id 角色 ID,获取特定角色的用户列表
|
33
|
+
# @option options [Integer] :mobile_verified 只能为 0 或 1,0 是未认证,1 是已认证
|
34
|
+
# @option options [Integer] :active_time 根据活跃时间排序,0 是顺序排列,1 是倒序排列
|
35
|
+
# @option options [Integer] :joined_at 根据加入时间排序,0 是顺序排列,1 是倒序排列
|
36
|
+
# @option options [Integer] :page 页数
|
37
|
+
# @option options [Integer] :page_size 每页数据数量
|
38
|
+
# @option options [String] :filter_user_id 获取指定 ID 所属用户的信息
|
39
|
+
# @return [KHL::HTTP::Response]
|
40
|
+
def user_list(guild_id, options = {})
|
41
|
+
get(options.merge(guild_id: guild_id))
|
42
|
+
end
|
43
|
+
|
44
|
+
# 修改服务器中用户的昵称
|
45
|
+
# @param [String] guild_id 服务器 ID
|
46
|
+
# @param [Hash] options 可选参数
|
47
|
+
# @option options [String] :nickname 昵称,2-64 长度,不传则清空昵称
|
48
|
+
# @option options [String] :user_id 用户 ID,不传则修改当前登陆用户的昵称
|
49
|
+
# @return [KHL::HTTP::Response]
|
50
|
+
def nickname(guild_id, options = {})
|
51
|
+
post(options.merge(guild_id: guild_id))
|
52
|
+
end
|
53
|
+
|
54
|
+
# 离开服务器
|
55
|
+
# @param [String] guild_id 服务器 ID
|
56
|
+
# @return [KHL::HTTP::Response]
|
57
|
+
def leave(guild_id)
|
58
|
+
post(guild_id: guild_id)
|
59
|
+
end
|
60
|
+
|
61
|
+
# 踢出服务器
|
62
|
+
# @param [String] guild_id 服务器 ID
|
63
|
+
# @param [String] target_id 用户 ID
|
64
|
+
# @return [KHL::HTTP::Response]
|
65
|
+
def kickout(guild_id, target_id)
|
66
|
+
post(guild_id: guild_id, target_id: target_id)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 服务器表情相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/guild-emoji
|
9
|
+
class GuildEmoji < Base
|
10
|
+
# 获取服务器表情列表
|
11
|
+
# @param [String] guild_id 服务器 ID
|
12
|
+
# @param [Hash] options 可选参数
|
13
|
+
# @option options [Integer] :page 页数
|
14
|
+
# @option options [Integer] :page_size 每页数据数量
|
15
|
+
# @return [KHL::HTTP::Response]
|
16
|
+
def list(guild_id, options = {})
|
17
|
+
get(options.merge(guild_id: guild_id))
|
18
|
+
end
|
19
|
+
|
20
|
+
# 创建服务器表情
|
21
|
+
# @param [String] guild_id 服务器 ID
|
22
|
+
# @param [IO] emoji 表情文件。必须为 PNG 类型,大小不能超过 256 KB
|
23
|
+
# @param [Hash] options 可选参数
|
24
|
+
# @option options [String] :name 表情名。长度限制 2-32 字符,如果不写,则为随机字符串
|
25
|
+
# @return [KHL::HTTP::Response]
|
26
|
+
def create(guild_id, emoji, options = {})
|
27
|
+
post_file(options.merge(content_type: "multipart/form-data", guild_id: guild_id, emoji: emoji))
|
28
|
+
end
|
29
|
+
|
30
|
+
# 更新服务器表情
|
31
|
+
# @param [String] name 表情名。长度限制 2-32 字符,如果不写,则为随机字符串
|
32
|
+
# @param [String] id 表情 ID
|
33
|
+
# @return [KHL::HTTP::Response]
|
34
|
+
def update(name, id)
|
35
|
+
post(name: name, id: id)
|
36
|
+
end
|
37
|
+
|
38
|
+
# 删除服务器表情
|
39
|
+
# @param [String] id 表情 ID
|
40
|
+
# @return [KHL::HTTP::Response]
|
41
|
+
def delete(id)
|
42
|
+
post(id: id)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 服务器静音闭麦相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/guild
|
9
|
+
class GuildMute < Base
|
10
|
+
# 服务器静音闭麦列表
|
11
|
+
# @param [String] guild_id 服务器 ID
|
12
|
+
# @param [Hash] options 可选参数
|
13
|
+
# @option options [String] :return_type 返回格式,建议为 "detail", 其他情况仅作为兼容
|
14
|
+
# @return [KHL::HTTP::Response]
|
15
|
+
def list(guild_id, options = {})
|
16
|
+
get(options.merge(guild_id: guild_id))
|
17
|
+
end
|
18
|
+
|
19
|
+
# 添加服务器静音或闭麦
|
20
|
+
# @param [String] guild_id 服务器 ID
|
21
|
+
# @param [String] user_id 用户 ID
|
22
|
+
# @param [Integer] type 静音类型,1 代表麦克风闭麦,2 代表耳机静音
|
23
|
+
# @return [KHL::HTTP::Response]
|
24
|
+
def create(guild_id, user_id, type)
|
25
|
+
post(guild_id: guild_id, user_id: user_id, type: type)
|
26
|
+
end
|
27
|
+
|
28
|
+
# 删除服务器静音或闭麦
|
29
|
+
# @param [String] guild_id 服务器 ID
|
30
|
+
# @param [String] user_id 用户 ID
|
31
|
+
# @param [Integer] type 静音类型,1 代表麦克风闭麦,2 代表耳机静音
|
32
|
+
# @return [KHL::HTTP::Response]
|
33
|
+
def delete(guild_id, user_id, type)
|
34
|
+
post(guild_id: guild_id, user_id: user_id, type: type)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 服务器角色权限相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/guild-role
|
9
|
+
class GuildRole < Base
|
10
|
+
# 获取服务器角色列表
|
11
|
+
# @param [String] guild_id 服务器 ID
|
12
|
+
# @param [Hash] options 可选参数
|
13
|
+
# @option options [Integer] :page 页数
|
14
|
+
# @option options [Integer] :page_size 每页数据数量
|
15
|
+
# @return [KHL::HTTP::Response]
|
16
|
+
def list(guild_id, options = {})
|
17
|
+
get(options.merge(guild_id: guild_id))
|
18
|
+
end
|
19
|
+
|
20
|
+
# 创建服务器角色
|
21
|
+
# @param [String] guild_id 服务器 ID
|
22
|
+
# @param [Hash] options 可选参数
|
23
|
+
# @option options [String] :name 角色名称,如果不写,则为 "新角色"
|
24
|
+
# @return [KHL::HTTP::Response]
|
25
|
+
def create(guild_id, options = {})
|
26
|
+
post(options.merge(guild_id: guild_id))
|
27
|
+
end
|
28
|
+
|
29
|
+
# 更新服务器角色
|
30
|
+
# @param [String] guild_id 服务器 ID
|
31
|
+
# @param [Integer] role_id 角色 ID
|
32
|
+
# @param [Hash] options 可选参数
|
33
|
+
# @option options [String] :name 角色名称
|
34
|
+
# @option options [Integer] :color 颜色
|
35
|
+
# @option options [Integer] :hoist 只能为 0 或者 1,是否把该角色的用户在用户列表排到前面
|
36
|
+
# @option options [Integer] :mentionable 只能为 0 或者 1,该角色是否可以被提及
|
37
|
+
# @option options [Integer] :permissions 权限
|
38
|
+
# @return [KHL::HTTP::Response]
|
39
|
+
def update(guild_id, role_id, options = {})
|
40
|
+
post(options.merge(guild_id: guild_id, role_id: role_id))
|
41
|
+
end
|
42
|
+
|
43
|
+
# 删除服务器角色
|
44
|
+
# @param [String] guild_id 服务器 ID
|
45
|
+
# @param [Integer] role_id 角色 ID
|
46
|
+
# @return [KHL::HTTP::Response]
|
47
|
+
def delete(guild_id, role_id)
|
48
|
+
post(guild_id: guild_id, role_id: role_id)
|
49
|
+
end
|
50
|
+
|
51
|
+
# 赋予用户角色
|
52
|
+
# @param [String] guild_id 服务器 ID
|
53
|
+
# @param [String] user_id 用户 ID
|
54
|
+
# @param [Integer] role_id 角色 ID
|
55
|
+
# @return [KHL::HTTP::Response]
|
56
|
+
def grant(guild_id, user_id, role_id)
|
57
|
+
post(guild_id: guild_id, user_id: user_id, role_id: role_id)
|
58
|
+
end
|
59
|
+
|
60
|
+
# 删除用户角色
|
61
|
+
# @param [String] guild_id 服务器 ID
|
62
|
+
# @param [String] user_id 用户 ID
|
63
|
+
# @param [Integer] role_id 角色 ID
|
64
|
+
# @return [KHL::HTTP::Response]
|
65
|
+
def revoke(guild_id, user_id, role_id)
|
66
|
+
post(guild_id: guild_id, user_id: user_id, role_id: role_id)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 亲密度相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/intimacy
|
9
|
+
class Intimacy < Base
|
10
|
+
# 获取用户亲密度
|
11
|
+
# @param [String] user_id 用户 ID
|
12
|
+
# @return [KHL::HTTP::Response]
|
13
|
+
def index(user_id)
|
14
|
+
get(user_id: user_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
# 更新用户亲密度
|
18
|
+
# @param [String] user_id 用户 ID
|
19
|
+
# @param [Hash] options 可选参数
|
20
|
+
# @option options [Integer] :score 亲密度,0-2200
|
21
|
+
# @option options [String] :social_info 机器人与用户的社交信息,500 字以内
|
22
|
+
# @option options [String] :img_id 表情 ID
|
23
|
+
# @return [KHL::HTTP::Response]
|
24
|
+
def update(user_id, options = {})
|
25
|
+
post(options.merge(user_id: user_id))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 邀请相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/invite
|
9
|
+
class Invite < Base
|
10
|
+
# 获取邀请列表
|
11
|
+
# @param [Hash] options 可选参数
|
12
|
+
# @option options [String] :guild_id 服务器 ID
|
13
|
+
# @option options [String] :channel_id 频道 ID
|
14
|
+
# @option options [Integer] :page 页数
|
15
|
+
# @option options [Integer] :page_size 每页数据数量
|
16
|
+
# @return [KHL::HTTP::Response]
|
17
|
+
def list(options = {})
|
18
|
+
get(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
# 创建邀请链接
|
22
|
+
# @option options [String] :guild_id 服务器 ID
|
23
|
+
# @option options [String] :channel_id 频道 ID
|
24
|
+
# @option options [Integer] :duration 邀请链接有效时长(秒),默认 7 天。
|
25
|
+
# 可选值: 0(永不)、1800(0.5 小时)、3600(1 小时)、21600(6 小时)、43200(12小时)、86400(1 天)、604800(7 天)
|
26
|
+
# @option options [Integer] :setting_times 设置的次数,默认-1。可选值:-1(无限制)、1、5、10、25、50、100
|
27
|
+
# @return [KHL::HTTP::Response]
|
28
|
+
def create(options = {})
|
29
|
+
post(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
# 删除邀请链接
|
33
|
+
# @param [String] url_code 邀请码
|
34
|
+
# @param [Hash] options 可选参数
|
35
|
+
# @option options [String] :guild_id 服务器 ID
|
36
|
+
# @option options [String] :channel_id 频道 ID
|
37
|
+
# @return [KHL::HTTP::Response]
|
38
|
+
def delete(url_code, options = {})
|
39
|
+
post(options.merge(url_code: url_code))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 频道消息相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/message
|
9
|
+
class Message < Base
|
10
|
+
# 获取频道聊天消息列表
|
11
|
+
# @note 此接口非标准分页,需要根据参考消息来查询相邻分页的消息
|
12
|
+
# @param [String] target_id 频道 ID
|
13
|
+
# @param [Hash] options 可选参数
|
14
|
+
# @option options [String] :msg_id 参考消息 ID,不传则查询最新消息
|
15
|
+
# @option options [Integer] :pin 只能为 0 或者 1,是否查询置顶消息。置顶消息只支持查询最新的消息
|
16
|
+
# @option options [String] :flag 查询模式,有三种模式可以选择 before、around、after。不传则默认查询最新的消息
|
17
|
+
# @option options [Integer] :page_size 当前分页消息数量,默认 50
|
18
|
+
# @return [KHL::HTTP::Response]
|
19
|
+
def list(target_id, options = {})
|
20
|
+
get(options.merge(target_id: target_id))
|
21
|
+
end
|
22
|
+
|
23
|
+
# 获取频道聊天消息详情
|
24
|
+
# @param [String] msg_id 消息 ID
|
25
|
+
# @return [KHL::HTTP::Response]
|
26
|
+
def view(msg_id)
|
27
|
+
get(msg_id: msg_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
# 发送频道聊天消息
|
31
|
+
# @note 此接口与频道相关接口下的 "发送频道聊天消息" 功能相同
|
32
|
+
# @warning 强列建议过滤掉机器人发送的消息,再进行回应。否则会很容易形成两个机器人循环自言自语导致发送量过大,进而导致机器人被封禁。如果确实需要机器人联动的情况,慎重进行处理,防止形成循环
|
33
|
+
# @param [String] target_id 频道 ID
|
34
|
+
# @param [String] content 消息内容
|
35
|
+
# @param [Hash] options 可选参数
|
36
|
+
# @option options [Integer] :type 消息类型,不传默认为 1,代表文本类型。9 代表 kmarkdown 消息,10 代表卡片消息
|
37
|
+
# @option options [String] :quote 回复某条消息的 msg_id
|
38
|
+
# @option options [String] :nonce 随机字符串,服务端不做处理,原样返回
|
39
|
+
# @option options [String] :temp_target_id 用户 ID,如果传了,代表该消息是临时消息,该消息不会存数据库,但是会在频道内只给该用户推送临时消息。用于在频道内针对用户的操作进行单独的回应通知等
|
40
|
+
# @return [KHL::HTTP::Response]
|
41
|
+
def create(target_id, content, options = {})
|
42
|
+
post(options.merge(target_id: target_id, content: content))
|
43
|
+
end
|
44
|
+
|
45
|
+
# 更新频道聊天消息
|
46
|
+
# @note 目前支持消息 type 为 9、10 的修改,即 KMarkdown 和 CardMessage
|
47
|
+
# @param [String] msg_id 消息 ID
|
48
|
+
# @param [String] content 消息内容
|
49
|
+
# @param [Hash] options 可选参数
|
50
|
+
# @option options [String] :quote 回复某条消息的 msg_id。如果为空,则代表删除回复,不传则无影响
|
51
|
+
# @option options [String] :temp_target_id 用户 ID,针对特定用户临时更新消息,必须是正常消息才能更新。与发送临时消息概念不同,但同样不保存数据库
|
52
|
+
# @return [KHL::HTTP::Response]
|
53
|
+
def update(msg_id, content, options = {})
|
54
|
+
post(options.merge(msg_id: msg_id, content: content))
|
55
|
+
end
|
56
|
+
|
57
|
+
# 删除频道聊天消息
|
58
|
+
# @note 普通用户只能删除自己的消息,有权限的用户可以删除权限范围内他人的消息
|
59
|
+
# @param [String] msg_id 消息 ID
|
60
|
+
# @return [KHL::HTTP::Response]
|
61
|
+
def delete(msg_id)
|
62
|
+
post(msg_id: msg_id)
|
63
|
+
end
|
64
|
+
|
65
|
+
# 获取频道消息某回应的用户列表
|
66
|
+
# @param [String] msg_id 频道消息 ID
|
67
|
+
# @param [String] emoji Emoji ID,可以为 GuilEmoji 或者 Emoji,注意:在 GET 中,应该进行 urlencode
|
68
|
+
# @return [KHL::HTTP::Response]
|
69
|
+
def reaction_list(msg_id, emoji)
|
70
|
+
get(msg_id: msg_id, emoji: emoji)
|
71
|
+
end
|
72
|
+
|
73
|
+
# 给某个消息添加回应
|
74
|
+
# @param [String] msg_id 频道消息 ID
|
75
|
+
# @param [String] emoji Emoji ID,可以为 GuilEmoji 或者 Emoji,注意:在 GET 中,应该进行 urlencode
|
76
|
+
# @return [KHL::HTTP::Response]
|
77
|
+
def add_reaction(msg_id, emoji)
|
78
|
+
post(msg_id: msg_id, emoji: emoji)
|
79
|
+
end
|
80
|
+
|
81
|
+
# 删除消息的某个回应
|
82
|
+
# @param [String] msg_id 频道消息 ID
|
83
|
+
# @param [String] emoji Emoji ID,可以为 GuilEmoji 或者 Emoji,注意:在 GET 中,应该进行 urlencode
|
84
|
+
# @param [Hash] options 可选参数
|
85
|
+
# @option options [String] :user_id 用户 ID, 如果不填则为自己的 ID。删除别人的回应需要有管理频道消息的权限
|
86
|
+
# @return [KHL::HTTP::Response]
|
87
|
+
def delete_reaction(msg_id, emoji, options = {})
|
88
|
+
post(options.merge(msg_id: msg_id, emoji: emoji))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KHL
|
4
|
+
module HTTP
|
5
|
+
class Response
|
6
|
+
attr_reader :http_code, :body
|
7
|
+
|
8
|
+
# @param [Net::HTTPResponse] raw_response The raw HTTP response
|
9
|
+
def initialize(raw_response)
|
10
|
+
@raw_response = raw_response
|
11
|
+
@http_code = raw_response.code.to_i
|
12
|
+
@body = JSON.parse(@raw_response.body)
|
13
|
+
end
|
14
|
+
|
15
|
+
def data
|
16
|
+
@body["data"]
|
17
|
+
end
|
18
|
+
|
19
|
+
# The code in the response body
|
20
|
+
def code
|
21
|
+
@body["code"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def max_request_limit
|
25
|
+
@raw_response["X-Rate-Limit-Limit"].to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def remain_request_limit
|
29
|
+
@raw_response["X-Rate-Limit-Remaining"].to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
def reset_limit_time
|
33
|
+
@raw_response["X-Rate-Limit-Reset"].to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
def limit_bucket
|
37
|
+
@raw_response["X-Rate-Limit-Bucket"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def limit?
|
41
|
+
@http_code == 429 || !@raw_response["X-Rate-Limit-Global"].nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def success?
|
45
|
+
http_code == 200 && code.zero?
|
46
|
+
end
|
47
|
+
|
48
|
+
def error?
|
49
|
+
!success?
|
50
|
+
end
|
51
|
+
|
52
|
+
def message
|
53
|
+
@body["message"]
|
54
|
+
end
|
55
|
+
|
56
|
+
def page
|
57
|
+
data.dig("meta", "page") || 0
|
58
|
+
end
|
59
|
+
|
60
|
+
def page_size
|
61
|
+
data.dig("meta", "page_size") || 0
|
62
|
+
end
|
63
|
+
|
64
|
+
def page_total
|
65
|
+
data.dig("meta", "total") || 0
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 用户相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/user
|
9
|
+
class User < Base
|
10
|
+
# 获取当前用户信息
|
11
|
+
# @return [KHL::HTTP::Response]
|
12
|
+
def me
|
13
|
+
get
|
14
|
+
end
|
15
|
+
|
16
|
+
# 获取目标用户信息
|
17
|
+
# @param [String] user_id 用户 ID
|
18
|
+
# @param [Hash] options 可选参数
|
19
|
+
# @option options [String] :guild_id 服务器 ID
|
20
|
+
# @return [KHL::HTTP::Response]
|
21
|
+
def view(user_id, options = {})
|
22
|
+
get(options.merge(user_id: user_id))
|
23
|
+
end
|
24
|
+
|
25
|
+
# 下线机器人
|
26
|
+
# @return [KHL::HTTP::Response]
|
27
|
+
def offline
|
28
|
+
post
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module KHL
|
6
|
+
module HTTP
|
7
|
+
# 私信聊天会话相关接口
|
8
|
+
# https://developer.kaiheila.cn/doc/http/user-chat
|
9
|
+
class UserChat < Base
|
10
|
+
# 获取私信聊天会话列表
|
11
|
+
# @param [Hash] options 可选参数
|
12
|
+
# @option options [Integer] :page 页数
|
13
|
+
# @option options [Integer] :page_size 每页数据数量
|
14
|
+
# @return [KHL::HTTP::Response]
|
15
|
+
def list(options = {})
|
16
|
+
get(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# 获取私信聊天会话详情
|
20
|
+
# @param [String] chat_code 私聊会话 Code
|
21
|
+
# @return [KHL::HTTP::Response]
|
22
|
+
def view(chat_code)
|
23
|
+
get(chat_code: chat_code)
|
24
|
+
end
|
25
|
+
|
26
|
+
# 创建私信聊天会话
|
27
|
+
# @param [String] target_id 用户 ID
|
28
|
+
# @return [KHL::HTTP::Response]
|
29
|
+
def create(target_id)
|
30
|
+
post(target_id: target_id)
|
31
|
+
end
|
32
|
+
|
33
|
+
# 删除私信聊天会话
|
34
|
+
# @note 只能删除自己的消息
|
35
|
+
# @param [String] target_id 用户 ID
|
36
|
+
# @return [KHL::HTTP::Response]
|
37
|
+
def delete(target_id)
|
38
|
+
post(target_id: target_id)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/khl/version.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cgi"
|
4
|
+
require "eventmachine"
|
5
|
+
require "faye/websocket"
|
6
|
+
require "json"
|
7
|
+
require "uri"
|
8
|
+
require "zlib"
|
9
|
+
|
10
|
+
require_relative "message"
|
11
|
+
|
12
|
+
module KHL
|
13
|
+
module WebSocket
|
14
|
+
# Client for the KHL WebSocket API
|
15
|
+
# @example
|
16
|
+
# client = KHL::WebSocket.new(token: "bot_token")
|
17
|
+
# Thread.new { client.run }
|
18
|
+
# client.message.pop # Get message from queue
|
19
|
+
class Client
|
20
|
+
attr_reader :config, :url, :messages, :state
|
21
|
+
|
22
|
+
# @param config [String] :token Bot token
|
23
|
+
# @option config [String] :token_type Token type
|
24
|
+
# @option config [String] :language Language
|
25
|
+
# @option config [Boolean] :compress Compress
|
26
|
+
def initialize(config)
|
27
|
+
config[:compress] ||= false
|
28
|
+
|
29
|
+
@config = config
|
30
|
+
@http_gateway = HTTP::Gateway.new(config)
|
31
|
+
@url = gateway_url
|
32
|
+
@messages = Queue.new
|
33
|
+
@sn = 0
|
34
|
+
@state = :disconnected
|
35
|
+
@ping_signal = false
|
36
|
+
@resume_signal = false
|
37
|
+
@ws = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Only receive messages from the server
|
41
|
+
def run
|
42
|
+
EM.run {
|
43
|
+
Signal.trap("INT") { EventMachine.stop }
|
44
|
+
Signal.trap("TERM") { EventMachine.stop }
|
45
|
+
|
46
|
+
@ws = Faye::WebSocket::Client.new(gateway_url)
|
47
|
+
@state = :connecting
|
48
|
+
|
49
|
+
EventMachine.add_periodic_timer(30) do
|
50
|
+
EventMachine.add_timer(6) do
|
51
|
+
if @ping_signal
|
52
|
+
@state = :timeout
|
53
|
+
|
54
|
+
unless reconnect
|
55
|
+
unless resume
|
56
|
+
@state = :disconnected
|
57
|
+
EventMachine.stop
|
58
|
+
rerun
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Send ping message
|
65
|
+
@ws.send({s: 2, sn: @sn}.to_json)
|
66
|
+
@ping_signal = true
|
67
|
+
end
|
68
|
+
|
69
|
+
@ws.on :message do |event|
|
70
|
+
raw = config[:compress] ? Zlib::Inflate.inflate(event.data.pack("C*")) : event.data
|
71
|
+
msg = Message.parse(raw)
|
72
|
+
|
73
|
+
if msg.hello?
|
74
|
+
@state = :connected
|
75
|
+
elsif msg.pong?
|
76
|
+
@ping_signal = false
|
77
|
+
elsif msg.resume_ack?
|
78
|
+
@resume_signal = false
|
79
|
+
elsif msg.reconnect?
|
80
|
+
@state = :reconnecting
|
81
|
+
rerun
|
82
|
+
elsif msg.event?
|
83
|
+
messages << msg
|
84
|
+
@sn = msg.sn
|
85
|
+
end
|
86
|
+
end
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def gateway_url
|
93
|
+
response = @http_gateway.index
|
94
|
+
return nil unless response.success?
|
95
|
+
|
96
|
+
uri = URI(response.data["url"])
|
97
|
+
query = CGI.parse(uri.query)
|
98
|
+
query["compress"] = config[:compress] ? 1 : 0
|
99
|
+
uri.query = URI.encode_www_form(query)
|
100
|
+
uri.to_s
|
101
|
+
end
|
102
|
+
|
103
|
+
def reconnect
|
104
|
+
@state = :reconnecting
|
105
|
+
@ping_signal = false
|
106
|
+
|
107
|
+
@ws.send({s: 2, sn: @sn}.to_json)
|
108
|
+
@ping_signal = true
|
109
|
+
sleep(2)
|
110
|
+
return true unless @ping_signal
|
111
|
+
|
112
|
+
@ws.send({s: 2, sn: @sn}.to_json)
|
113
|
+
@ping_signal = true
|
114
|
+
sleep(4)
|
115
|
+
return true unless @ping_signal
|
116
|
+
|
117
|
+
false
|
118
|
+
end
|
119
|
+
|
120
|
+
def resume
|
121
|
+
@state = :resuming
|
122
|
+
@resume_signal = false
|
123
|
+
|
124
|
+
@ws.send({s: 4, sn: @sn}.to_json)
|
125
|
+
@resume_signal = true
|
126
|
+
sleep(8)
|
127
|
+
return true unless @resume_signal
|
128
|
+
|
129
|
+
@ws.send({s: 4, sn: @sn}.to_json)
|
130
|
+
@resume_signal = true
|
131
|
+
sleep(16)
|
132
|
+
return true unless @resume_signal
|
133
|
+
|
134
|
+
false
|
135
|
+
end
|
136
|
+
|
137
|
+
def rerun
|
138
|
+
@url = gateway_url
|
139
|
+
@messages.clear
|
140
|
+
@sn = 0
|
141
|
+
@state = :disconnected
|
142
|
+
@ping_signal = false
|
143
|
+
@resume_signal = false
|
144
|
+
@ws = nil
|
145
|
+
|
146
|
+
EventMachine.stop
|
147
|
+
run
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|