forked from mamoe/mirai
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsubscribeMessages.kt
163 lines (148 loc) · 6.38 KB
/
subscribeMessages.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
* Copyright 2019-2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("SubscribeMessagesKt")
@file:Suppress("EXPERIMENTAL_API_USAGE", "MemberVisibilityCanBePrivate", "unused")
package net.mamoe.mirai.event
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ReceiveChannel
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.Listener.ConcurrencyKind.CONCURRENT
import net.mamoe.mirai.event.events.FriendMessageEvent
import net.mamoe.mirai.event.events.GroupMessageEvent
import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.event.events.TempMessageEvent
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
public typealias MessagePacketSubscribersBuilder = MessageSubscribersBuilder<MessageEvent, Listener<MessageEvent>, Unit, Unit>
/**
* 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话.
*
* @see subscribe 事件监听基础
* @see EventChannel 事件通道
*/
public fun <R> EventChannel<*>.subscribeMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
listeners: MessagePacketSubscribersBuilder.() -> R
): R {
// contract 可帮助 IDE 进行类型推断. 无实际代码作用.
contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
}
return MessageSubscribersBuilder(Unit)
{ filter, messageListener: MessageListener<MessageEvent, Unit> ->
// subscribeAlways 即注册一个监听器. 这个监听器收到消息后就传递给 [messageListener]
// messageListener 即为 DSL 里 `contains(...) { }`, `startsWith(...) { }` 的代码块.
subscribeAlways<MessageEvent>(coroutineContext, concurrencyKind, priority) {
// this.message.contentToString() 即为 messageListener 中 it 接收到的值
val toString = this.message.contentToString()
if (filter.invoke(this, toString))
messageListener.invoke(this, toString)
}
}.run(listeners)
}
public typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder<GroupMessageEvent, Listener<GroupMessageEvent>, Unit, Unit>
/**
* 订阅来自所有 [Bot] 的所有群消息事件
*
* @see subscribe 事件监听基础
* @see EventChannel 事件通道
*/
public fun <R> EventChannel<*>.subscribeGroupMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
listeners: GroupMessageSubscribersBuilder.() -> R
): R {
contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
}
return GroupMessageSubscribersBuilder(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.contentToString()
if (filter(this, toString))
listener(this, toString)
}
}.run(listeners)
}
public typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder<FriendMessageEvent, Listener<FriendMessageEvent>, Unit, Unit>
/**
* 订阅来自所有 [Bot] 的所有好友消息事件
*
* @see subscribe 事件监听基础
* @see EventChannel 事件通道
*/
public fun <R> EventChannel<*>.subscribeFriendMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
listeners: FriendMessageSubscribersBuilder.() -> R
): R {
contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
}
return FriendMessageSubscribersBuilder(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.contentToString()
if (filter(this, toString))
listener(this, toString)
}
}.run(listeners)
}
public typealias TempMessageSubscribersBuilder = MessageSubscribersBuilder<TempMessageEvent, Listener<TempMessageEvent>, Unit, Unit>
/**
* 订阅来自所有 [Bot] 的所有临时会话消息事件
*
* @see subscribe 事件监听基础
* @see EventChannel 事件通道
*/
public fun <R> EventChannel<*>.subscribeTempMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
listeners: TempMessageSubscribersBuilder.() -> R
): R {
contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
}
return TempMessageSubscribersBuilder(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.contentToString()
if (filter(this, toString))
listener(this, toString)
}
}.run(listeners)
}
/**
* 打开一个指定事件的接收通道
*
* @param capacity 同 [Channel] 的参数, 参见 [Channel.Factory] 中的常量.
*
* @see capacity 默认无限大小. 详见 [Channel.Factory] 中的常量 [Channel.UNLIMITED], [Channel.CONFLATED], [Channel.RENDEZVOUS].
* 请谨慎使用 [Channel.RENDEZVOUS]: 在 [Channel] 未被 [接收][Channel.receive] 时他将会阻塞事件处理
*
* @see subscribe 事件监听基础
*
* @see subscribeFriendMessages
* @see subscribeMessages
* @see subscribeGroupMessages
*/
@Deprecated("Use asChannel", ReplaceWith("asChannel(capacity, coroutineContext, concurrencyKind, priority)"))
public fun <E : Event> EventChannel<E>.incoming(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
capacity: Int = Channel.UNLIMITED
): ReceiveChannel<E> {
return asChannel(capacity, coroutineContext, concurrencyKind, priority)
}