rubirai 0.0.2

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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/CI.yml +64 -0
  4. data/.github/workflows/docs.yml +32 -0
  5. data/.github/workflows/pull_request.yml +34 -0
  6. data/.gitignore +145 -0
  7. data/.rubocop.yml +41 -0
  8. data/.yardopts +7 -0
  9. data/Gemfile +19 -0
  10. data/LICENSE +661 -0
  11. data/README.md +24 -0
  12. data/Rakefile +16 -0
  13. data/examples/helper.rb +3 -0
  14. data/examples/listener_example.rb +25 -0
  15. data/examples/simple_example.rb +24 -0
  16. data/lib/rubirai.rb +66 -0
  17. data/lib/rubirai/auth.rb +73 -0
  18. data/lib/rubirai/errors.rb +26 -0
  19. data/lib/rubirai/event_recv.rb +83 -0
  20. data/lib/rubirai/event_resp.rb +129 -0
  21. data/lib/rubirai/events/bot_events.rb +53 -0
  22. data/lib/rubirai/events/event.rb +115 -0
  23. data/lib/rubirai/events/message_events.rb +77 -0
  24. data/lib/rubirai/events/request_events.rb +35 -0
  25. data/lib/rubirai/events/rubirai_events.rb +17 -0
  26. data/lib/rubirai/listener.rb +44 -0
  27. data/lib/rubirai/listing.rb +37 -0
  28. data/lib/rubirai/management.rb +200 -0
  29. data/lib/rubirai/message.rb +84 -0
  30. data/lib/rubirai/messages/message.rb +306 -0
  31. data/lib/rubirai/messages/message_chain.rb +119 -0
  32. data/lib/rubirai/multipart.rb +44 -0
  33. data/lib/rubirai/objects/group.rb +23 -0
  34. data/lib/rubirai/objects/info.rb +71 -0
  35. data/lib/rubirai/objects/user.rb +30 -0
  36. data/lib/rubirai/plugin_info.rb +19 -0
  37. data/lib/rubirai/retcode.rb +18 -0
  38. data/lib/rubirai/session.rb +26 -0
  39. data/lib/rubirai/utils.rb +62 -0
  40. data/lib/rubirai/version.rb +9 -0
  41. data/misc/common.css +11 -0
  42. data/rubirai.gemspec +24 -0
  43. data/spec/auth_spec.rb +118 -0
  44. data/spec/error_spec.rb +30 -0
  45. data/spec/events/event_spec.rb +78 -0
  46. data/spec/message_spec.rb +12 -0
  47. data/spec/messages/message_chain_spec.rb +32 -0
  48. data/spec/messages/message_spec.rb +171 -0
  49. data/spec/plugin_info_spec.rb +28 -0
  50. data/spec/rubirai_bot_spec.rb +45 -0
  51. data/spec/spec_helper.rb +31 -0
  52. data/spec/utils_spec.rb +70 -0
  53. metadata +121 -0
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubirai/events/event'
4
+
5
+ module Rubirai
6
+ class BotEvent < Event
7
+ set_event nil, :qq
8
+ end
9
+
10
+ class BotOnlineEvent < BotEvent
11
+ set_event :BotOnlineEvent
12
+ end
13
+
14
+ class BotActiveOfflineEvent < BotEvent
15
+ set_event :BotOfflineEventActive
16
+ end
17
+
18
+ class BotForcedOfflineEvent < BotEvent
19
+ set_event :BotOfflineEventForce
20
+ end
21
+
22
+ class BotDroppedEvent < BotEvent
23
+ set_event :BotOfflineEventDropped
24
+ end
25
+
26
+ class BotReloginEvent < BotEvent
27
+ set_event :BotReloginEvent
28
+ end
29
+
30
+ class BotGroupPermissionChangedEvent < BotEvent
31
+ set_event :BotGroupPermissionChangeEvent, :origin, :new, :current, :group
32
+ end
33
+
34
+ class BotMutedEvent < BotEvent
35
+ set_event :BotMuteEvent, :duration_seconds, :operator
36
+ end
37
+
38
+ class BotUnmutedEvent < BotEvent
39
+ set_event :BotUnmuteEvent, :operator
40
+ end
41
+
42
+ class BotJoinGroupEvent < BotEvent
43
+ set_event :BotJoinGroupEvent, :group
44
+ end
45
+
46
+ class BotActiveLeaveEvent < BotEvent
47
+ set_event :BotLeaveEventActive, :group
48
+ end
49
+
50
+ class BotKickedEvent < BotEvent
51
+ set_event :BotLeaveEventKick, :group
52
+ end
53
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubirai/objects/group'
4
+ require 'rubirai/utils'
5
+
6
+ module Rubirai
7
+ # @abstract
8
+ class Event
9
+ # @private
10
+ def self.gen_descendants
11
+ descs = ObjectSpace.each_object(Class).select do |klass|
12
+ klass < self
13
+ end
14
+
15
+ metaclass.instance_eval do
16
+ define_method(:descendants) do
17
+ descs
18
+ end
19
+ leaf_descs = descs.filter { |d| d.respond_to? :type }
20
+ all_types = leaf_descs.map(&:type)
21
+ define_method(:all_types) do
22
+ all_types
23
+ end
24
+ type_map = leaf_descs.to_h { |d| [d.type, d] }
25
+ define_method(:type_map) do
26
+ type_map
27
+ end
28
+ end
29
+
30
+ private_class_method :descendants
31
+ end
32
+
33
+ def self.type_to_klass(type)
34
+ # noinspection RubyResolve
35
+ type_map[type.to_sym]
36
+ end
37
+
38
+ def self.valid_type?(type)
39
+ # noinspection RubyResolve
40
+ all_types.include? type
41
+ end
42
+
43
+ def self.set_event(type, *attr_keys)
44
+ attr_reader(*attr_keys)
45
+
46
+ metaclass.instance_eval do
47
+ break if type.nil?
48
+ define_method(:type) do
49
+ type
50
+ end
51
+ end
52
+
53
+ class_eval do
54
+ define_method(:initialize) do |hash, bot = nil|
55
+ # noinspection RubySuperCallWithoutSuperclassInspection
56
+ super hash, bot
57
+ hash = hash.stringify_keys
58
+ attr_keys.each do |k|
59
+ k2 = k.to_s.snake_to_camel(lower: true)
60
+ val = hash[k2]
61
+ val = case k2
62
+ when 'group'
63
+ Group.new val, bot
64
+ when 'operator', 'member'
65
+ GroupUser.new val, bot
66
+ when 'sender'
67
+ if val.key? 'group'
68
+ GroupUser.new val, bot
69
+ else
70
+ User.new val, bot
71
+ end
72
+ when 'messageChain'
73
+ MessageChain.new bot, val
74
+ else
75
+ val
76
+ end
77
+ instance_variable_set("@#{k}", val)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def self.metaclass
84
+ class << self
85
+ self
86
+ end
87
+ end
88
+
89
+ private_class_method :metaclass
90
+
91
+ # @param hash [Hash]
92
+ # @param bot [Rubirai::Bot, nil]
93
+ def self.parse(hash, bot = nil)
94
+ hash = hash.stringify_keys
95
+ type_to_klass(hash['type']).new hash, bot
96
+ end
97
+
98
+ # @!attribute [r] bot
99
+ # @return [Bot]
100
+ # @!attribute [r] raw
101
+ # The raw hash representation of the event
102
+ # @return [Hash]
103
+ attr_reader :bot, :raw
104
+
105
+ def initialize(hash, bot = nil)
106
+ @raw = hash
107
+ @bot = bot
108
+ end
109
+ end
110
+ end
111
+
112
+ require_relative 'bot_events'
113
+ require_relative 'message_events'
114
+
115
+ Rubirai::Event.gen_descendants
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubirai/events/event'
4
+
5
+ module Rubirai
6
+ # The base class for message events
7
+ # @abstract
8
+ class MessageEvent < Event
9
+ # @!attribute [r] message_chain
10
+ # @return [MessageChain] the message chain
11
+ set_event nil, :message_chain, :sender
12
+ end
13
+
14
+ # Friend message event
15
+ class FriendMessageEvent < MessageEvent
16
+ # @!method initialize(hash, bot = nil)
17
+ # @param hash [Hash]
18
+ # @param bot [Rubirai::Bot]
19
+ # @!attribute [r] sender
20
+ # @return [User] the sender
21
+ set_event :FriendMessage
22
+ end
23
+
24
+ # Group message event
25
+ class GroupMessageEvent < MessageEvent
26
+ # @!method initialize(hash, bot = nil)
27
+ # @param hash [Hash]
28
+ # @param bot [Rubirai::Bot]
29
+ # @!attribute [r] sender
30
+ # @return [GroupUser] the sender
31
+ set_event :GroupMessage
32
+ end
33
+
34
+ # Temp message event
35
+ class TempMessageEvent < MessageEvent
36
+ # @!method initialize(hash, bot = nil)
37
+ # @param hash [Hash]
38
+ # @param bot [Rubirai::Bot]
39
+ # @!attribute [r] sender
40
+ # @return [GroupUser] the sender
41
+ set_event :TempMessage
42
+ end
43
+
44
+ # The base class for recall events
45
+ # @abstract
46
+ class RecallEvent < Event
47
+ # @!attribute [r] author_id
48
+ # @return [Integer] the author's id
49
+ # @!attribute [r] message_id
50
+ # @return [Integer] the message id
51
+ # @!attribute [r] time
52
+ # @return [Integer] the time the message is sent
53
+ set_event nil, :author_id, :message_id, :time
54
+ end
55
+
56
+ # Group recall event
57
+ class GroupRecallEvent < RecallEvent
58
+ # @!method initialize(hash, bot = nil)
59
+ # @param hash [Hash]
60
+ # @param bot [Rubirai::Bot]
61
+ # @!attribute [r] group
62
+ # @return [Group] the group
63
+ # @!attribute [r] operator
64
+ # @return [GroupUser] the operator
65
+ set_event :GroupRecallEvent, :group, :operator
66
+ end
67
+
68
+ # Friend recall event
69
+ class FriendRecallEvent < RecallEvent
70
+ # @!method initialize(hash, bot = nil)
71
+ # @param hash [Hash]
72
+ # @param bot [Rubirai::Bot]
73
+ # @!attribute [r] operator
74
+ # @return [Integer] the operator id
75
+ set_event :FriendRecallEvent, :operator
76
+ end
77
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubirai/events/event'
4
+
5
+ module Rubirai
6
+ class RequestEvent < Event
7
+ # @!attribute [r] event_id
8
+ # @return [Integer] the event id
9
+ # @!attribute [r] from_id
10
+ # @return [Integer] the id of the sender of the request
11
+ # @!attribute [r] group_id
12
+ # @return [Integer] the group where the request is from. 0 if not from group
13
+ # @!attribute [r] nick
14
+ # @return [String] the nickname of the sender of the request
15
+ # @!attribute [r] message
16
+ # @return [String] the message from the sender
17
+ set_event nil, :event_id, :from_id, :group_id, :nick, :message
18
+ end
19
+
20
+ class NewFriendRequestEvent < RequestEvent
21
+ set_event :NewFriendRequestEvent
22
+ end
23
+
24
+ class JoinGroupRequestEvent < RequestEvent
25
+ # @!attribute [r] group_name
26
+ # @return [String] the group name
27
+ set_event :MemberJoinRequestEvent, :group_name
28
+ end
29
+
30
+ class BotInvitedToGroupEvent < RequestEvent
31
+ # @!attribute [r] group_name
32
+ # @return [String] the group name
33
+ set_event :BotInvitedJoinGroupRequestEvent, :group_name
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubirai/events/event'
4
+
5
+ module Rubirai
6
+ class RubiraiErrorEvent < Event
7
+ attr_reader :err
8
+
9
+ # An error event just for internal use
10
+ #
11
+ # @param err [RuntimeError] the error object
12
+ def initialize(err, bot = nil)
13
+ super nil, bot
14
+ @err = err
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'concurrent'
4
+ require 'rubirai/events/rubirai_events'
5
+
6
+ module Rubirai
7
+ class Bot
8
+ def start_listen(interval, is_blocking: false, ignore_error: false)
9
+ raise RubiraiError, 'listener is already running' if @listener&.running?
10
+ @listener_stop_event = Concurrent::Event.new if is_blocking
11
+ bot = self
12
+ @listener = Concurrent::TimerTask.new(execution_interval: interval) do
13
+ loop do
14
+ events = fetch_message
15
+ events.each do |e|
16
+ @listener_funcs.each { |f| f.call e }
17
+ rescue RuntimeError => e
18
+ @listener_funcs.each { |f| f.call RubiraiErrorEvent.new(e, bot) unless ignore_error }
19
+ end
20
+ break if events.length < 10
21
+ rescue RuntimeError => e
22
+ @listener_funcs.each { |f| f.call RubiraiErrorEvent.new(e, bot) unless ignore_error }
23
+ break
24
+ end
25
+ end
26
+ @listener.execute
27
+ @listener_stop_event.wait if is_blocking
28
+ end
29
+
30
+ def add_listener(&listener_block)
31
+ @listener_funcs << listener_block
32
+ end
33
+
34
+ def clear_listener
35
+ @listener_funcs.clear
36
+ end
37
+
38
+ def stop_listen
39
+ @listener.shutdown
40
+ @listener_stop_event&.set
41
+ @listener_stop_event = nil
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubirai/objects/user'
4
+ require 'rubirai/objects/group'
5
+
6
+ module Rubirai
7
+ class Bot
8
+ # Get friend list of the bot
9
+ # @return [Array<User>] list of friends
10
+ def friend_list
11
+ resp = call :get, '/friendList', params: {
12
+ sessionKey: @session
13
+ }
14
+ resp.map { |friend| User.new(friend, self) }
15
+ end
16
+
17
+ # Get group list of the bot
18
+ # @return [Array<Group>] list of groups
19
+ def group_list
20
+ resp = call :get, '/groupList', params: {
21
+ sessionKey: @session
22
+ }
23
+ resp.map { |group| Group.new(group, self) }
24
+ end
25
+
26
+ # Get member list of a group
27
+ # @param group_id [Integer, String] group id
28
+ # @return [Array<GroupUser>] list of members
29
+ def member_list(group_id)
30
+ resp = call :get, '/memberList', params: {
31
+ sessionKey: @session,
32
+ target: group_id
33
+ }
34
+ resp.map { |member| GroupUser.new(member, self) }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubirai/objects/info'
4
+
5
+ module Rubirai
6
+ class Bot
7
+ # Mute a group member
8
+ #
9
+ # @param group_id [Integer] group id
10
+ # @param member_id [Integer] member id
11
+ # @param time [Integer] the mute time
12
+ def mute(group_id, member_id, time = 0)
13
+ call :post, '/mute', json: {
14
+ sessionKey: @session,
15
+ target: group_id,
16
+ memberId: member_id,
17
+ time: time
18
+ }
19
+ nil
20
+ end
21
+
22
+ # Unmute a group member
23
+ #
24
+ # @param group_id [Integer] group id
25
+ # @param member_id [Integer] member id
26
+ # @return [void]
27
+ def unmute(group_id, member_id)
28
+ call :post, '/unmute', json: {
29
+ sessionKey: @session,
30
+ target: group_id,
31
+ memberId: member_id
32
+ }
33
+ nil
34
+ end
35
+
36
+ # Kick a member from a group
37
+ #
38
+ # @param group_id [Integer] group id
39
+ # @param member_id [Integer] member id
40
+ # @param msg [String, nil] the message for the kicked
41
+ # @return [void]
42
+ def kick(group_id, member_id, msg = nil)
43
+ json = {
44
+ sessionKey: @session,
45
+ target: group_id,
46
+ memberId: member_id
47
+ }
48
+ json[:msg] = msg if msg
49
+ call :post, '/kick', json: json
50
+ nil
51
+ end
52
+
53
+ # Quit a group
54
+ #
55
+ # @param group_id [Integer] group id
56
+ # @return [void]
57
+ def quit(group_id)
58
+ call :post, '/quit', json: {
59
+ sessionKey: @session,
60
+ target: group_id
61
+ }
62
+ nil
63
+ end
64
+
65
+ # Mute all group
66
+ #
67
+ # @param group_id [Integer] group id
68
+ # @return [void]
69
+ def mute_all(group_id)
70
+ call :post, '/muteAll', json: {
71
+ sessionKey: @session,
72
+ target: group_id
73
+ }
74
+ nil
75
+ end
76
+
77
+ def unmute_all(group_id)
78
+ call :post, '/unmuteAll', json: {
79
+ sessionKey: @session,
80
+ target: group_id
81
+ }
82
+ nil
83
+ end
84
+
85
+ def get_group_config(group_id)
86
+ resp = call :get, '/groupConfig', params: {
87
+ sessionKey: @session,
88
+ target: group_id
89
+ }
90
+ GroupConfig.new resp, self
91
+ end
92
+
93
+ # Set group config
94
+ #
95
+ # @param group_id [Integer] group id
96
+ # @param config [GroupConfig, Hash{String => Object}] the configuration
97
+ # @return [void]
98
+ def set_group_config(group_id, config)
99
+ config.must_be! [GroupConfig, Hash], RubiraiError, 'must be GroupConfig or Hash'
100
+ config.stringify_keys! if config.is_a? Hash
101
+ config = config.to_h if config.is_a? GroupConfig
102
+ call :post, '/groupConfig', json: {
103
+ sessionKey: @session,
104
+ target: group_id,
105
+ config: config
106
+ }
107
+ nil
108
+ end
109
+
110
+ def get_member_info(group_id, member_id)
111
+ resp = call :get, '/memberInfo', params: {
112
+ sessionKey: @session,
113
+ target: group_id,
114
+ memberId: member_id
115
+ }
116
+ MemberInfo.new resp, self
117
+ end
118
+
119
+ def set_member_info(group_id, member_id, info)
120
+ info.must_be! [MemberInfo, Hash], RubiraiError, 'must be MemberInfo or Hash'
121
+ info.stringify_keys! if info.is_a? Hash
122
+ info = info.to_h if info.is_a? MemberInfo
123
+ call :post, '/memberInfo', json: {
124
+ sessionKey: @session,
125
+ target: group_id,
126
+ memberId: member_id,
127
+ info: info
128
+ }
129
+ nil
130
+ end
131
+
132
+ def get_group_file_list(group_id, dir = nil)
133
+ resp = call :get, '/groupFileList', params: {
134
+ sessionKey: @session,
135
+ target: group_id,
136
+ dir: dir
137
+ }.compact
138
+ resp.must_be! Array # assert resp is Array
139
+ resp.map { |f| GroupFileSimple.new(f, self) }
140
+ end
141
+
142
+ # Get the info about a group file
143
+ # @param group_id [Integer] the group id
144
+ # @param file_id [String] the file id, e.g. `/xxx-xxx-xxx-xxx`
145
+ def get_group_file_info(group_id, file_id)
146
+ resp = call :get, '/groupFileInfo', params: {
147
+ sessionKey: @session,
148
+ target: group_id,
149
+ id: file_id
150
+ }
151
+ GroupFile.new resp, self
152
+ end
153
+
154
+ def rename_group_file(group_id, file_id, new_name)
155
+ call :post, '/groupFileRename', json: {
156
+ sessionKey: @session,
157
+ target: group_id,
158
+ id: file_id,
159
+ rename: new_name
160
+ }
161
+ nil
162
+ end
163
+
164
+ def group_mkdir(group_id, dir)
165
+ call :post, '/groupMkdir', json: {
166
+ sessionKey: @session,
167
+ group: group_id,
168
+ dir: dir
169
+ }
170
+ nil
171
+ end
172
+
173
+ def group_file_mv(group_id, file_id, path)
174
+ call :post, '/groupFileMove', json: {
175
+ sessionKey: @session,
176
+ target: group_id,
177
+ id: file_id,
178
+ movePath: path
179
+ }
180
+ nil
181
+ end
182
+
183
+ def group_file_delete(group_id, file_id)
184
+ call :post, '/groupFileDelete', json: {
185
+ sessionKey: @session,
186
+ target: group_id,
187
+ id: file_id
188
+ }
189
+ nil
190
+ end
191
+
192
+ def group_set_essence(msg_id)
193
+ call :post, '/setEssence', json: {
194
+ sessionKey: @session,
195
+ target: msg_id
196
+ }
197
+ nil
198
+ end
199
+ end
200
+ end