Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
Mirai
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
Mirai
Commits
12ad7542
Commit
12ad7542
authored
Feb 27, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Separate `mirai-demos` series from main repository
parent
c6ae8e32
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
2 additions
and
1886 deletions
+2
-1886
mirai-demos/build.gradle
mirai-demos/build.gradle
+0
-0
mirai-demos/mirai-demo-1/build.gradle
mirai-demos/mirai-demo-1/build.gradle
+0
-12
mirai-demos/mirai-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
...i-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
+0
-272
mirai-demos/mirai-demo-android/build.gradle
mirai-demos/mirai-demo-android/build.gradle
+0
-65
mirai-demos/mirai-demo-android/proguard-rules.pro
mirai-demos/mirai-demo-android/proguard-rules.pro
+0
-22
mirai-demos/mirai-demo-android/src/main/AndroidManifest.xml
mirai-demos/mirai-demo-android/src/main/AndroidManifest.xml
+0
-25
mirai-demos/mirai-demo-android/src/main/kotlin/net/mamoe/mirai/demo/LoginCallback.kt
...oid/src/main/kotlin/net/mamoe/mirai/demo/LoginCallback.kt
+0
-20
mirai-demos/mirai-demo-android/src/main/kotlin/net/mamoe/mirai/demo/MainActivity.kt
...roid/src/main/kotlin/net/mamoe/mirai/demo/MainActivity.kt
+0
-123
mirai-demos/mirai-demo-android/src/main/kotlin/net/mamoe/mirai/demo/MiraiService.kt
...roid/src/main/kotlin/net/mamoe/mirai/demo/MiraiService.kt
+0
-118
mirai-demos/mirai-demo-android/src/main/res/layout/activity_main.xml
.../mirai-demo-android/src/main/res/layout/activity_main.xml
+0
-62
mirai-demos/mirai-demo-android/src/main/res/values/colors.xml
...i-demos/mirai-demo-android/src/main/res/values/colors.xml
+0
-6
mirai-demos/mirai-demo-android/src/main/res/values/strings.xml
...-demos/mirai-demo-android/src/main/res/values/strings.xml
+0
-4
mirai-demos/mirai-demo-android/src/main/res/values/styles.xml
...i-demos/mirai-demo-android/src/main/res/values/styles.xml
+0
-11
mirai-demos/mirai-demo-gentleman/build.gradle
mirai-demos/mirai-demo-gentleman/build.gradle
+0
-31
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Gentleman.kt
...emo-gentleman/src/main/kotlin/demo/gentleman/Gentleman.kt
+0
-48
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt
...rai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt
+0
-183
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/UserAgent.kt
...emo-gentleman/src/main/kotlin/demo/gentleman/UserAgent.kt
+0
-206
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/a.html
...irai-demo-gentleman/src/main/kotlin/demo/gentleman/a.html
+0
-17
mirai-demos/mirai-demo-gentleman/src/main/resources/tag.ini
mirai-demos/mirai-demo-gentleman/src/main/resources/tag.ini
+0
-569
mirai-demos/mirai-demo-java/build.gradle
mirai-demos/mirai-demo-java/build.gradle
+0
-18
mirai-demos/mirai-demo-java/src/main/java/demo/BlockingTest.java
...emos/mirai-demo-java/src/main/java/demo/BlockingTest.java
+0
-52
settings.gradle
settings.gradle
+2
-22
No files found.
mirai-demos/build.gradle
deleted
100644 → 0
View file @
c6ae8e32
mirai-demos/mirai-demo-1/build.gradle
deleted
100644 → 0
View file @
c6ae8e32
apply
plugin:
"kotlin"
apply
plugin:
"java"
dependencies
{
runtimeOnly
files
(
"../../mirai-core/build/classes/kotlin/jvm/main"
)
// IDE bug
runtimeOnly
files
(
"../../mirai-core-qqandroid/build/classes/kotlin/jvm/main"
)
// IDE bug
implementation
project
(
":mirai-core-qqandroid"
)
api
group:
'org.jetbrains.kotlin'
,
name:
'kotlin-stdlib-jdk8'
,
version:
kotlinVersion
api
group:
'org.jetbrains.kotlinx'
,
name:
'kotlinx-coroutines-core'
,
version:
coroutinesVersion
}
mirai-demos/mirai-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
deleted
100644 → 0
View file @
c6ae8e32
/*
* Copyright 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
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
demo.subscribe
import
kotlinx.coroutines.CompletableJob
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.BotAccount
import
net.mamoe.mirai.alsoLogin
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.contact.isOperator
import
net.mamoe.mirai.contact.sendMessage
import
net.mamoe.mirai.event.*
import
net.mamoe.mirai.message.FriendMessage
import
net.mamoe.mirai.message.GroupMessage
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.message.nextMessage
import
net.mamoe.mirai.message.sendAsImageTo
import
net.mamoe.mirai.utils.FileBasedDeviceInfo
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
java.io.File
@MiraiInternalAPI
private
fun
readTestAccount
():
BotAccount
?
{
val
file
=
File
(
"testAccount.txt"
)
if
(!
file
.
exists
()
||
!
file
.
canRead
())
{
return
null
}
println
(
"Reading account from testAccount.text"
)
val
lines
=
file
.
readLines
()
return
try
{
BotAccount
(
lines
[
0
].
toLong
(),
lines
[
1
])
}
catch
(
e
:
IndexOutOfBoundsException
)
{
null
}
}
@Suppress
(
"UNUSED_VARIABLE"
)
suspend
fun
main
()
{
val
bot
=
Bot
(
// JVM 下也可以不写 `QQAndroid.` 引用顶层函数
123456789
,
"123456"
)
{
// 覆盖默认的配置
+
FileBasedDeviceInfo
// 使用 "device.json" 保存设备信息
// networkLoggerSupplier = { SilentLogger } // 禁用网络层输出
}.
alsoLogin
()
bot
.
messageDSL
()
directlySubscribe
(
bot
)
bot
.
join
()
//等到直到断开连接
}
/**
* 使用 dsl 监听消息事件
*
* @see subscribeFriendMessages
* @see subscribeMessages
* @see subscribeGroupMessages
*
* @see MessageSubscribersBuilder
*/
fun
Bot
.
messageDSL
()
{
// 监听这个 bot 的来自所有群和好友的消息
this
.
subscribeMessages
{
// 当接收到消息 == "你好" 时就回复 "你好!"
"你好"
reply
"你好!"
// 当消息 == "查看 subject" 时, 执行 lambda
case
(
"查看 subject"
)
{
if
(
subject
is
QQ
)
{
reply
(
"消息主体为 QQ, 你在发私聊消息"
)
}
else
{
reply
(
"消息主体为 Group, 你在群里发消息"
)
}
// 在回复的时候, 一般使用 subject 来作为回复对象.
// 因为当群消息时, subject 为这个群.
// 当好友消息时, subject 为这个好友.
// 所有在 MessagePacket(也就是此时的 this 指代的对象) 中实现的扩展方法, 如刚刚的 "reply", 都是以 subject 作为目标
}
// 当消息里面包含这个类型的消息时
has
<
Image
>
{
// this: MessagePacket
// message: MessageChain
// sender: QQ
// it: String (MessageChain.toString)
// message[Image].download() // 还未支持 download
if
(
this
is
GroupMessage
)
{
//如果是群消息
// group: Group
this
.
group
.
sendMessage
(
"你在一个群里"
)
// 等同于 reply("你在一个群里")
}
reply
(
"图片, ID= ${message[Image]}"
)
//获取第一个 Image 类型的消息
reply
(
message
)
}
"hello.*world"
.
toRegex
()
matchingReply
{
"Hello!"
}
"123"
containsReply
"你的消息里面包含 123"
// 当收到 "我的qq" 就执行 lambda 并回复 lambda 的返回值 String
"我的qq"
reply
{
sender
.
id
}
"at all"
reply
AtAll
// at 全体成员
// 如果是这个 QQ 号发送的消息(可以是好友消息也可以是群消息)
sentBy
(
123456789
)
{
}
// 当消息前缀为 "我是" 时
startsWith
(
"我是"
,
removePrefix
=
true
)
{
// it: 删除了消息前缀 "我是" 后的消息
// 如一条消息为 "我是张三", 则此时的 it 为 "张三".
reply
(
"你是$it"
)
}
// listener 管理
var
repeaterListener
:
CompletableJob
?
=
null
contains
(
"开启复读"
)
{
repeaterListener
?.
complete
()
bot
.
subscribeGroupMessages
{
repeaterListener
=
contains
(
"复读"
)
{
reply
(
message
)
}
}
}
contains
(
"关闭复读"
)
{
if
(
repeaterListener
?.
complete
()
==
null
)
{
reply
(
"没有开启复读"
)
}
else
{
reply
(
"成功关闭复读"
)
}
}
// 自定义的 filter, filter 中 it 为转为 String 的消息.
// 也可以用任何能在处理时使用的变量, 如 subject, sender, message
content
({
it
.
length
==
3
})
{
reply
(
"你发送了长度为 3 的消息"
)
}
case
(
"上传好友图片"
)
{
val
filename
=
it
.
substringAfter
(
"上传好友图片"
)
File
(
"C:\\Users\\Him18\\Desktop\\$filename"
).
sendAsImageTo
(
subject
)
}
case
(
"上传群图片"
)
{
val
filename
=
it
.
substringAfter
(
"上传好友图片"
)
File
(
"C:\\Users\\Him18\\Desktop\\$filename"
).
sendAsImageTo
(
subject
)
}
}
subscribeMessages
{
case
(
"你好"
)
{
// this: MessagePacket
// message: MessageChain
// sender: QQ
// it: String (来自 MessageChain.toString)
// group: Group (如果是群消息)
reply
(
"你好"
)
}
}
subscribeFriendMessages
{
contains
(
"A"
)
{
// this: FriendMessage
// message: MessageChain
// sender: QQ
// it: String (来自 MessageChain.toString)
reply
(
"B"
)
}
}
subscribeGroupMessages
{
// this: FriendMessage
// message: MessageChain
// sender: QQ
// it: String (来自 MessageChain.toString)
// group: Group
case
(
"recall"
)
{
reply
(
"😎"
).
recallIn
(
3000
)
// 3 秒后自动撤回这条消息
}
case
(
"禁言"
)
{
// 挂起当前协程, 等待下一条满足条件的消息.
// 发送 "禁言" 后需要再发送一条消息 at 一个人.
val
value
:
At
=
nextMessage
{
message
.
any
(
At
)
}[
At
]
value
.
member
().
mute
(
10
)
}
startsWith
(
"群名="
)
{
if
(!
sender
.
isOperator
())
{
sender
.
mute
(
5
)
return
@
startsWith
}
group
.
name
=
it
}
}
}
/**
* 监听单个事件
*/
@Suppress
(
"UNUSED_VARIABLE"
)
suspend
fun
directlySubscribe
(
bot
:
Bot
)
{
// 在当前协程作用域 (CoroutineScope) 下创建一个子 Job, 监听一个事件.
//
// 手动处理消息
//
// subscribeAlways 函数返回 Listener, Listener 是一个 CompletableJob.
//
// 例如:
// ```kotlin
// runBlocking {// this: CoroutineScope
// subscribeAlways<FriendMessage> {
// }
// }
// ```
// 则这个 `runBlocking` 永远不会结束, 因为 `subscribeAlways` 在 `runBlocking` 的 `CoroutineScope` 下创建了一个 Job.
// 正确的用法为:
// 在 Bot 的 CoroutineScope 下创建一个监听事件的 Job, 则这个子 Job 会在 Bot 离线后自动完成 (complete).
bot
.
subscribeAlways
<
FriendMessage
>
{
// this: FriendMessageEvent
// event: FriendMessageEvent
// 获取第一个纯文本消息, 获取不到会抛出 NoSuchElementException
// val firstText = message.first<PlainText>()
val
firstText
=
message
.
firstOrNull
<
PlainText
>()
// 获取第一个图片
val
firstImage
=
message
.
firstOrNull
<
Image
>()
when
{
message
eq
"你好"
->
reply
(
"你好!"
)
"复读"
in
message
->
sender
.
sendMessage
(
message
)
"发群消息"
in
message
->
{
bot
.
getGroup
(
580266363
).
sendMessage
(
message
.
toString
().
substringAfter
(
"发群消息"
))
}
}
}
}
\ No newline at end of file
mirai-demos/mirai-demo-android/build.gradle
deleted
100644 → 0
View file @
c6ae8e32
plugins
{
id
'com.android.application'
id
'org.jetbrains.kotlin.multiplatform'
id
'kotlin-android-extensions'
}
android
{
compileSdkVersion
29
defaultConfig
{
applicationId
"net.mamoe.mirai.demo"
minSdkVersion
21
targetSdkVersion
29
versionCode
1
versionName
"1.0"
}
buildTypes
{
release
{
minifyEnabled
true
proguardFiles
getDefaultProguardFile
(
'proguard-android.txt'
),
'proguard-rules.pro'
}
}
packagingOptions
{
exclude
'META-INF/main.kotlin_module'
exclude
'META-INF/ktor-http.kotlin_module'
exclude
'META-INF/kotlinx-io.kotlin_module'
exclude
'META-INF/atomicfu.kotlin_module'
exclude
'META-INF/ktor-utils.kotlin_module'
exclude
'META-INF/kotlinx-coroutines-io.kotlin_module'
exclude
'META-INF/kotlinx-coroutines-core.kotlin_module'
exclude
'META-INF/ktor-http-cio.kotlin_module'
exclude
'META-INF/ktor-http-cio.kotlin_module'
exclude
'META-INF/ktor-client-core.kotlin_module'
exclude
"META-INF/kotlinx-serialization-runtime.kotlin_module"
exclude
'META-INF/ktor-io.kotlin_module'
}
}
kotlin
{
targets
.
fromPreset
(
presets
.
android
,
'android'
)
}
dependencies
{
implementation
"org.jetbrains.kotlin:kotlin-stdlib"
implementation
project
(
':mirai-core-qqandroid'
)
implementation
group:
'org.jetbrains.kotlin'
,
name:
'kotlin-stdlib-jdk8'
,
version:
kotlinVersion
implementation
group:
'org.jetbrains.kotlinx'
,
name:
'kotlinx-coroutines-core'
,
version:
coroutinesVersion
implementation
group:
'org.jetbrains.kotlinx'
,
name:
'kotlinx-coroutines-android'
,
version:
"1.3.2"
//implementation 'com.android.support:appcompat-v7:29.1.1'// https://mvnrepository.com/artifact/androidx.appcompat/appcompat
implementation
group:
'androidx.appcompat'
,
name:
'appcompat'
,
version:
'1.1.0'
testImplementation
"org.jetbrains.kotlin:kotlin-test"
testImplementation
'junit:junit:4.12'
androidTestImplementation
'junit:junit:4.12'
def
anko_version
=
"0.10.8"
implementation
"org.jetbrains.anko:anko-commons:$anko_version"
implementation
group:
'io.ktor'
,
name:
'ktor-client-android'
,
version:
'1.2.5'
implementation
(
"io.ktor:ktor-client-android:1.2.5"
)
}
\ No newline at end of file
mirai-demos/mirai-demo-android/proguard-rules.pro
deleted
100644 → 0
View file @
c6ae8e32
# Add project specific ProGuard rules here.
#
You
can
control
the
set
of
applied
configuration
files
using
the
#
proguardFiles
setting
in
build
.
gradle
.
#
#
For
more
details
,
see
#
http
://
developer
.
android
.
com
/
guide
/
developing
/
tools
/
proguard
.
html
#
If
your
project
uses
WebView
with
JS
,
uncomment
the
following
#
and
specify
the
fully
qualified
class
name
to
the
JavaScript
interface
#
class
:
#-
keepclassmembers
class
fqcn
.
of
.
javascript
.
interface
.
for
.
webview
{
#
public
*
;
#
}
#
Uncomment
this
to
preserve
the
line
number
information
for
#
debugging
stack
traces
.
#-
keepattributes
SourceFile
,
LineNumberTable
#
If
you
keep
the
line
number
information
,
uncomment
this
to
#
hide
the
original
source
file
name
.
#-
renamesourcefileattribute
SourceFile
mirai-demos/mirai-demo-android/src/main/AndroidManifest.xml
deleted
100644 → 0
View file @
c6ae8e32
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"net.mamoe.mirai.demo"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<application
android:label=
"@string/app_name"
android:allowBackup=
"true"
android:supportsRtl=
"true"
android:theme=
"@style/AppTheme"
>
<activity
android:name=
"net.mamoe.mirai.demo.MainActivity"
android:theme=
"@style/AppTheme"
>
<intent-filter>
<action
android:name=
"android.intent.action.MAIN"
/>
<category
android:name=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
<service
android:name=
".MiraiService"
/>
</application>
</manifest>
mirai-demos/mirai-demo-android/src/main/kotlin/net/mamoe/mirai/demo/LoginCallback.kt
deleted
100644 → 0
View file @
c6ae8e32
/*
* Copyright 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
*/
package
net.mamoe.mirai.demo
import
android.graphics.Bitmap
interface
LoginCallback
{
suspend
fun
onCaptcha
(
bitmap
:
Bitmap
)
suspend
fun
onSuccess
()
suspend
fun
onFailed
()
suspend
fun
onMessage
(
message
:
String
)
}
\ No newline at end of file
mirai-demos/mirai-demo-android/src/main/kotlin/net/mamoe/mirai/demo/MainActivity.kt
deleted
100644 → 0
View file @
c6ae8e32
/*
* Copyright 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
:
Suppress
(
"DEPRECATION"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.demo
import
android.annotation.SuppressLint
import
android.app.ProgressDialog
import
android.app.Service
import
android.content.ComponentName
import
android.content.Intent
import
android.content.ServiceConnection
import
android.graphics.Bitmap
import
android.os.Bundle
import
android.os.IBinder
import
android.view.View
import
android.widget.Toast
import
androidx.appcompat.app.AppCompatActivity
import
kotlinx.android.synthetic.main.activity_main.*
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
class
MainActivity
:
AppCompatActivity
(),
LoginCallback
{
private
lateinit
var
progressDialog
:
ProgressDialog
override
suspend
fun
onCaptcha
(
bitmap
:
Bitmap
)
{
withContext
(
Dispatchers
.
Main
){
ll_captcha
.
visibility
=
View
.
VISIBLE
iv_captcha
.
setImageBitmap
(
bitmap
)
needCaptcha
=
true
if
(
progressDialog
.
isShowing
){
progressDialog
.
dismiss
()
}
}
}
@SuppressLint
(
"SetTextI18n"
)
override
suspend
fun
onMessage
(
message
:
String
)
{
withContext
(
Dispatchers
.
Main
){
msg
.
text
=
"${msg.text}\n$message"
}
}
override
suspend
fun
onSuccess
()
{
withContext
(
Dispatchers
.
Main
){
Toast
.
makeText
(
this
@MainActivity
,
"登录成功"
,
Toast
.
LENGTH_SHORT
).
show
()
if
(
progressDialog
.
isShowing
){
progressDialog
.
dismiss
()
}
ll_captcha
.
visibility
=
View
.
GONE
et_pwd
.
visibility
=
View
.
GONE
et_qq
.
visibility
=
View
.
GONE
bt_login
.
visibility
=
View
.
GONE
}
}
override
suspend
fun
onFailed
()
{
withContext
(
Dispatchers
.
Main
){
Toast
.
makeText
(
this
@MainActivity
,
"登录失败"
,
Toast
.
LENGTH_SHORT
).
show
()
if
(
progressDialog
.
isShowing
){
progressDialog
.
dismiss
()
}
}
}
var
binder
:
MiraiService
.
MiraiBinder
?
=
null
private
var
needCaptcha
=
false
private
val
conn
=
object
:
ServiceConnection
{
override
fun
onServiceConnected
(
name
:
ComponentName
?,
service
:
IBinder
?)
{
binder
=
service
as
MiraiService
.
MiraiBinder
?
}
override
fun
onServiceDisconnected
(
name
:
ComponentName
?)
{
binder
=
null
}
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setContentView
(
R
.
layout
.
activity_main
)
val
intent
=
Intent
(
this
,
MiraiService
::
class
.
java
)
startService
(
intent
)
bindService
(
intent
,
conn
,
Service
.
BIND_AUTO_CREATE
)
progressDialog
=
ProgressDialog
(
this
)
bt_login
.
setOnClickListener
{
if
(!
progressDialog
.
isShowing
){
progressDialog
.
show
()
}
binder
?.
setCallback
(
this
)
if
(!
needCaptcha
){
val
qq
=
et_qq
.
text
.
toString
().
toLong
()
val
pwd
=
et_pwd
.
text
.
toString
()
binder
?.
startLogin
(
qq
,
pwd
)
}
else
{
val
captcha
=
et_captcha
.
text
.
toString
()
binder
?.
setCaptcha
(
captcha
)
}
}
}
override
fun
onDestroy
()
{
super
.
onDestroy
()
unbindService
(
conn
)
}
}
\ No newline at end of file
mirai-demos/mirai-demo-android/src/main/kotlin/net/mamoe/mirai/demo/MiraiService.kt
deleted
100644 → 0
View file @
c6ae8e32
/*
* Copyright 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
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.demo
import
android.app.Service
import
android.content.Context
import
android.content.Intent
import
android.graphics.BitmapFactory
import
android.os.Binder
import
android.os.IBinder
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.subscribeMessages
import
net.mamoe.mirai.qqandroid.QQAndroid
import
net.mamoe.mirai.utils.LoginSolver
import
java.lang.ref.WeakReference
class
MiraiService
:
Service
()
{
private
lateinit
var
mCaptchaDeferred
:
CompletableDeferred
<
String
>
private
lateinit
var
mBot
:
Bot
private
var
mCaptcha
=
""
set
(
value
)
{
field
=
value
mCaptchaDeferred
.
complete
(
value
)
}
private
var
mBinder
:
MiraiBinder
?
=
null
private
var
mCallback
:
WeakReference
<
LoginCallback
>?
=
null
override
fun
onCreate
()
{
super
.
onCreate
()
mBinder
=
MiraiBinder
()
}
private
fun
login
(
context
:
Context
,
qq
:
Long
,
pwd
:
String
)
{
GlobalScope
.
launch
{
mBot
=
QQAndroid
.
Bot
(
context
,
qq
,
pwd
)
{
loginSolver
=
object
:
LoginSolver
()
{
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
val
bytes
=
data
.
readBytes
()
val
bitmap
=
BitmapFactory
.
decodeByteArray
(
bytes
,
0
,
bytes
.
size
)
mCaptchaDeferred
=
CompletableDeferred
()
mCallback
?.
get
()
?.
onCaptcha
(
bitmap
)
return
mCaptchaDeferred
.
await
()
}
override
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
url
:
String
):
String
?
{
TODO
(
"not implemented"
)
}
override
suspend
fun
onSolveUnsafeDeviceLoginVerify
(
bot
:
Bot
,
url
:
String
):
String
?
{
TODO
(
"not implemented"
)
}
}
}.
apply
{
try
{
login
()
mCallback
?.
get
()
?.
onSuccess
()
}
catch
(
e
:
Exception
)
{
mCallback
?.
get
()
?.
onFailed
()
}
}
mBot
.
subscribeMessages
{
always
{
mCallback
?.
get
()
?.
onMessage
(
"收到来自${sender.id}的消息"
)
}
// 当接收到消息 == "你好" 时就回复 "你好!"
"你好"
reply
"你好!"
}
}
}
override
fun
onBind
(
intent
:
Intent
?):
IBinder
?
{
return
mBinder
}
inner
class
MiraiBinder
:
Binder
()
{
fun
startLogin
(
qq
:
Long
,
pwd
:
String
)
{
login
(
applicationContext
,
qq
,
pwd
)
}
fun
setCaptcha
(
captcha
:
String
)
{
mCaptcha
=
captcha
}
fun
setCallback
(
callback
:
LoginCallback
)
{
mCallback
=
WeakReference
(
callback
)
}
}
}
\ No newline at end of file
mirai-demos/mirai-demo-android/src/main/res/layout/activity_main.xml
deleted
100644 → 0
View file @
c6ae8e32
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:scrollbars=
"vertical"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<EditText
android:layout_width=
"match_parent"
android:layout_height=
"46dp"
android:inputType=
"number"
android:layout_marginTop=
"10dp"
android:ems=
"15"
android:hint=
"请输入QQ号"
android:id=
"@+id/et_qq"
/>
<EditText
android:layout_width=
"match_parent"
android:layout_height=
"46dp"
android:inputType=
"textPassword"
android:hint=
"请输入密码"
android:layout_marginTop=
"10dp"
android:id=
"@+id/et_pwd"
/>
<LinearLayout
android:id=
"@+id/ll_captcha"
android:layout_marginTop=
"5dp"
android:visibility=
"gone"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
<EditText
android:id=
"@+id/et_captcha"
android:layout_weight=
"1"
android:layout_width=
"0dp"
android:layout_height=
"46dp"
android:hint=
"输入验证码"
/>
<ImageView
android:id=
"@+id/iv_captcha"
android:layout_weight=
"1"
android:layout_width=
"0dp"
android:layout_height=
"match_parent"
android:layout_marginLeft=
"5dp"
android:scaleType=
"fitXY"
/>
</LinearLayout>
<Button
android:text=
"登录"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"5dp"
android:id=
"@+id/bt_login"
android:background=
"#3F51B5"
android:textColor=
"#FFFFFF"
/>
<TextView
android:id=
"@+id/msg"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
</LinearLayout>
\ No newline at end of file
mirai-demos/mirai-demo-android/src/main/res/values/colors.xml
deleted
100644 → 0
View file @
c6ae8e32
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color
name=
"colorPrimary"
>
#3F51B5
</color>
<color
name=
"colorPrimaryDark"
>
#303F9F
</color>
<color
name=
"colorAccent"
>
#FF4081
</color>
</resources>
mirai-demos/mirai-demo-android/src/main/res/values/strings.xml
deleted
100644 → 0
View file @
c6ae8e32
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string
name=
"app_name"
>
Mirai
</string>
</resources>
\ No newline at end of file
mirai-demos/mirai-demo-android/src/main/res/values/styles.xml
deleted
100644 → 0
View file @
c6ae8e32
<resources>
<!-- Base application theme. -->
<style
name=
"AppTheme"
parent=
"Theme.AppCompat.Light.DarkActionBar"
>
<!-- Customize your theme here. -->
<item
name=
"colorPrimary"
>
@color/colorPrimary
</item>
<item
name=
"colorPrimaryDark"
>
@color/colorPrimaryDark
</item>
<item
name=
"colorAccent"
>
@color/colorAccent
</item>
</style>
</resources>
mirai-demos/mirai-demo-gentleman/build.gradle
deleted
100644 → 0
View file @
c6ae8e32
apply
plugin:
"kotlin"
apply
plugin:
"java"
apply
plugin:
"application"
apply
plugin:
"kotlinx-serialization"
dependencies
{
runtimeOnly
files
(
"../../mirai-core/build/classes/kotlin/jvm/main"
)
// IDE bug
runtimeOnly
files
(
"../../mirai-core-qqandroid/build/classes/kotlin/jvm/main"
)
// IDE bug
api
project
(
":mirai-core"
)
api
project
(
":mirai-core-qqandroid"
)
api
(
"org.jetbrains.kotlinx:atomicfu:$atomicFuVersion"
)
implementation
group:
'org.jetbrains.kotlin'
,
name:
'kotlin-stdlib-jdk8'
,
version:
kotlinVersion
implementation
group:
'org.jetbrains.kotlinx'
,
name:
'kotlinx-coroutines-core'
,
version:
coroutinesVersion
implementation
(
"org.jetbrains.kotlinx:kotlinx-io:$kotlinXIoVersion"
)
implementation
(
"org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion"
)
implementation
(
"org.jetbrains.kotlinx:kotlinx-coroutines-io:$coroutinesIoVersion"
)
implementation
group:
'com.alibaba'
,
name:
'fastjson'
,
version:
'1.2.62'
api
'org.jsoup:jsoup:1.12.1'
}
run
{
standardInput
=
System
.
in
mainClassName
=
"demo.gentleman.MainKt"
}
compileKotlin
{
kotlinOptions
{
freeCompilerArgs
=
[
"-XXLanguage:+InlineClasses"
]
}
}
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Gentleman.kt
deleted
100644 → 0
View file @
c6ae8e32
/*
* Copyright 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
*/
package
demo.gentleman
import
kotlinx.coroutines.ExperimentalCoroutinesApi
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.channels.Channel
import
kotlinx.coroutines.launch
import
net.mamoe.mirai.contact.Contact
/**
* 最少缓存的图片数量
*/
private
const
val
IMAGE_BUFFER_CAPACITY
:
Int
=
5
/**
* 为不同的联系人提供图片
*/
@ExperimentalUnsignedTypes
@ExperimentalCoroutinesApi
object
Gentlemen
:
MutableMap
<
Long
,
Gentleman
>
by
mutableMapOf
()
{
fun
provide
(
key
:
Contact
,
keyword
:
String
=
""
):
Gentleman
=
this
.
getOrPut
(
key
.
id
)
{
Gentleman
(
key
,
keyword
)
}
}
/**
* 工作是缓存图片
*/
@ExperimentalCoroutinesApi
class
Gentleman
(
private
val
contact
:
Contact
,
private
val
keyword
:
String
)
:
Channel
<
GentleImage
>
by
Channel
(
IMAGE_BUFFER_CAPACITY
)
{
init
{
GlobalScope
.
launch
{
while
(!
isClosedForSend
)
{
send
(
GentleImage
(
contact
,
keyword
).
apply
{
seImage
// start downloading
})
}
}
}
}
\ No newline at end of file
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt
deleted
100644 → 0
View file @
c6ae8e32
/*
* Copyright 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
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
demo.gentleman
import
kotlinx.coroutines.Dispatchers.IO
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.alsoLogin
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.contact.MemberPermission
import
net.mamoe.mirai.event.Event
import
net.mamoe.mirai.event.events.BotEvent
import
net.mamoe.mirai.event.subscribeAlways
import
net.mamoe.mirai.event.subscribeGroupMessages
import
net.mamoe.mirai.event.subscribeMessages
import
net.mamoe.mirai.message.FriendMessage
import
net.mamoe.mirai.message.GroupMessage
import
net.mamoe.mirai.message.data.At
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.buildXMLMessage
import
net.mamoe.mirai.message.data.getValue
import
net.mamoe.mirai.message.sendAsImageTo
import
net.mamoe.mirai.utils.ContextImpl
import
java.io.File
import
java.util.*
import
javax.swing.filechooser.FileSystemView
import
kotlin.random.Random
@Suppress
(
"UNUSED_VARIABLE"
)
suspend
fun
main
()
{
val
bot
=
Bot
(
ContextImpl
(),
913366033
,
"a18260132383"
)
{
// override config here.
}.
alsoLogin
()
// 任何可以监听的对象都继承 Event, 因此这个订阅会订阅全部的事件.
GlobalScope
.
subscribeAlways
<
Event
>
{
//bot.logger.verbose("收到了一个事件: $this")
}
// 全局范围订阅事件, 不受 bot 实例影响
GlobalScope
.
subscribeAlways
<
BotEvent
>
{
}
// 订阅来自这个 bot 的群消息事件
bot
.
subscribeGroupMessages
{
startsWith
(
"mute"
)
{
val
at
:
At
by
message
at
.
member
().
mute
(
30
)
}
startsWith
(
"unmute"
)
{
val
at
:
At
by
message
at
.
member
().
unmute
()
}
}
// 订阅来自这个 bot 的消息事件, 可以是群消息也可以是好友消息
bot
.
subscribeMessages
{
always
{
}
case
(
"at me"
)
{
At
(
sender
as
Member
).
reply
()
}
// 等同于 "at me" reply { At(sender) }
"你好"
reply
"你好!"
"grouplist"
reply
{
//"https://ssl.ptlogin2.qq.com/jump?pt_clientver=5509&pt_src=1&keyindex=9&clientuin=" + bot.qqAccount + "&clientkey=" + com.tick_tock.pctim.utils.Util.byte2HexString(
// user.txprotocol.serviceTicketHttp
//).replace(" ", "").toString() + "&u1=http%3A%2F%2Fqun.qq.com%2Fmember.html%23gid%3D168209441"
}
"xml"
reply
{
val
template
=
"""
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<msg templateID='1' serviceID='1' action='plugin' actionData='ACTION_LINK' brief='BRIEF' flag='3' url=''>
<item bg='0' layout='4'>
<picture cover='TITLE_PICTURE_LINK'/>
<title size='30' color='#fc7299'>TITLE</title>
</item>
<item>
<summary color='#fc7299'>CONTENT</summary>
<picture cover='CONTENT_PICTURE_LINK'/>
</item>
<source name='ExHentai' icon='ExHentai'/>
</msg>
"""
.
trimIndent
()
buildXMLMessage
{
item
{
picture
(
"http://img.mamoe.net/2019/12/03/be35ccb489ecb.jpg"
)
title
(
"This is title"
)
}
item
{
summary
(
"This is a summary colored #66CCFF"
,
color
=
"#66CCFF"
)
picture
(
"http://img.mamoe.net/2019/12/03/74c8614c4a161.jpg"
)
}
source
(
"Mirai"
,
"http://img.mamoe.net/2019/12/03/02eea0f6e826a.png"
)
}.
reply
()
}
(
contains
(
"1"
)
and
has
<
Image
>()){
reply
(
"Your message has a string \"1\" and an image contained"
)
}
has
<
Image
>
{
if
(
this
is
FriendMessage
||
(
this
is
GroupMessage
&&
this
.
permission
==
MemberPermission
.
ADMINISTRATOR
))
withContext
(
IO
)
{
val
image
:
Image
by
message
// 等同于 val image = message[Image]
try
{
image
.
downloadTo
(
newTestTempFile
(
suffix
=
".png"
).
also
{
reply
(
"Temp file: ${it.absolutePath}"
)
})
reply
(
image
.
imageId
+
" downloaded"
)
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
()
reply
(
e
.
message
?:
e
::
class
.
java
.
simpleName
)
}
}
}
startsWith
(
"上传图片"
,
removePrefix
=
true
)
handler
@
{
val
file
=
File
(
FileSystemView
.
getFileSystemView
().
homeDirectory
,
it
)
if
(!
file
.
exists
())
{
reply
(
"图片不存在"
)
return
@
handler
}
reply
(
"sent"
)
file
.
sendAsImageTo
(
subject
)
}
startsWith
(
"色图"
,
removePrefix
=
true
)
{
repeat
(
it
.
toIntOrNull
()
?:
1
)
{
GlobalScope
.
launch
{
delay
(
Random
.
Default
.
nextLong
(
100
,
1000
))
Gentlemen
.
provide
(
subject
).
receive
().
image
.
await
().
send
()
}
}
}
startsWith
(
"不够色"
,
removePrefix
=
true
)
{
repeat
(
it
.
toIntOrNull
()
?:
1
)
{
GlobalScope
.
launch
{
delay
(
Random
.
Default
.
nextLong
(
100
,
1000
))
Gentlemen
.
provide
(
subject
).
receive
().
seImage
.
await
().
send
()
}
}
}
startsWith
(
"添加好友"
,
removePrefix
=
true
)
{
reply
(
bot
.
addFriend
(
it
.
toLong
()).
toString
())
}
}
bot
.
join
()
//等到直到断开连接
}
private
fun
newTestTempFile
(
filename
:
String
=
"${UUID.randomUUID()}"
,
suffix
:
String
=
".tmp"
):
File
=
File
(
System
.
getProperty
(
"user.dir"
),
filename
+
suffix
).
also
{
it
.
createNewFile
();
it
.
deleteOnExit
()
}
\ No newline at end of file
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/UserAgent.kt
deleted
100644 → 0
View file @
c6ae8e32
This diff is collapsed.
Click to expand it.
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/a.html
deleted
100644 → 0
View file @
c6ae8e32
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"UTF-8"
>
<title></title>
</head>
<body>
<p><a
href=
"http://www.kyotoanimation.co.jp/"
>
京都动画
</a>
作品
<a
href=
"https://www.bilibili.com/bangumi/media/md3365/?from=search&seid=14448313700764690387"
>
《境界的彼方》
</a>
的
<a
href=
"https://zh.moegirl.org/zh-hans/%E6%A0%97%E5%B1%B1%E6%9C%AA%E6%9D%A5"
>
栗山未来(Kuriyama
<b>
Mirai
</b>
)
</a></p>
<p><a
href=
"https://www.crypton.co.jp/miku_eng"
>
初音未来
</a>
的线下创作文化活动
<a
href=
"https://magicalmirai.com/2019/index_en.html"
>
(Magical
<b>
Mirai
</b>
)
</a></p>
</body>
</html>
\ No newline at end of file
mirai-demos/mirai-demo-gentleman/src/main/resources/tag.ini
deleted
100644 → 0
View file @
c6ae8e32
This diff is collapsed.
Click to expand it.
mirai-demos/mirai-demo-java/build.gradle
deleted
100644 → 0
View file @
c6ae8e32
apply
plugin:
"java"
apply
plugin:
"kotlin"
dependencies
{
runtimeOnly
files
(
"../../mirai-core/build/classes/kotlin/jvm/main"
)
// IDE bug
runtimeOnly
files
(
"../../mirai-core-qqandroid/build/classes/kotlin/jvm/main"
)
// IDE bug
implementation
project
(
":mirai-core-qqandroid"
)
implementation
project
(
":mirai-japt"
)
}
tasks
.
withType
(
JavaCompile
)
{
options
.
encoding
=
"UTF-8"
}
compileJava
.
options
.
encoding
=
'UTF-8'
compileTestJava
.
options
.
encoding
=
'UTF-8'
\ No newline at end of file
mirai-demos/mirai-demo-java/src/main/java/demo/BlockingTest.java
deleted
100644 → 0
View file @
c6ae8e32
package
demo
;
import
net.mamoe.mirai.japt.BlockingBot
;
import
net.mamoe.mirai.japt.BlockingContacts
;
import
net.mamoe.mirai.japt.BlockingQQ
;
import
net.mamoe.mirai.japt.Events
;
import
net.mamoe.mirai.message.GroupMessage
;
import
net.mamoe.mirai.message.data.At
;
import
net.mamoe.mirai.message.data.Image
;
import
net.mamoe.mirai.message.data.MessageUtils
;
import
net.mamoe.mirai.utils.BotConfiguration
;
import
net.mamoe.mirai.utils.SystemDeviceInfoKt
;
import
java.io.File
;
class
BlockingTest
{
public
static
void
main
(
String
[]
args
)
throws
InterruptedException
{
// 使用自定义的配置
BlockingBot
bot
=
BlockingBot
.
newInstance
(
123456
,
""
,
new
BotConfiguration
()
{
{
setDeviceInfo
(
context
->
SystemDeviceInfoKt
.
loadAsDeviceInfo
(
new
File
(
"deviceInfo.json"
),
context
)
);
setHeartbeatPeriodMillis
(
50
*
1000
);
}
});
// 使用默认的配置
// BlockingBot bot = BlockingBot.newInstance(123456, "");
bot
.
login
();
bot
.
getFriendList
().
forEach
(
friend
->
{
System
.
out
.
println
(
friend
.
getNick
());
});
Events
.
subscribeAlways
(
GroupMessage
.
class
,
(
GroupMessage
message
)
->
{
final
BlockingQQ
sender
=
BlockingContacts
.
createBlocking
(
message
.
getSender
());
sender
.
sendMessage
(
"Hello World!"
);
System
.
out
.
println
(
"发送完了"
);
sender
.
sendMessage
(
MessageUtils
.
newChain
()
.
plus
(
new
At
(
message
.
getSender
()))
.
plus
(
Image
.
fromId
(
"{xxxx}.jpg"
))
.
plus
(
"123465"
)
);
});
Thread
.
sleep
(
999999999
);
}
}
settings.gradle
View file @
12ad7542
...
...
@@ -21,34 +21,14 @@ pluginManagement {
rootProject
.
name
=
'mirai'
include
(
':mirai-demos'
)
try
{
def
keyProps
=
new
Properties
()
def
keyFile
=
file
(
"local.properties"
)
if
(
keyFile
.
exists
())
keyFile
.
withInputStream
{
keyProps
.
load
(
it
)
}
if
(!
keyProps
.
getProperty
(
"sdk.dir"
,
""
).
isEmpty
())
{
include
(
':mirai-demos:mirai-demo-android'
)
project
(
':mirai-demos:mirai-demo-android'
).
projectDir
=
file
(
'mirai-demos/mirai-demo-android'
)
}
else
{
println
(
"Android SDK 可能未安装. \n将不会加载模块 `mirai-demo-android`, 但这并不影响其他 demo 的加载 "
)
println
(
"Android SDK might not be installed. \nModule `mirai-demo-android` will not be included, but other demos will not be influenced"
)
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
()
}
include
(
':mirai-core'
)
//include(':mirai-core-timpc')
include
(
':mirai-core-qqandroid'
)
//include(':mirai-api')
include
(
':mirai-api-http'
)
include
(
':mirai-demos:mirai-demo-1'
)
include
(
':mirai-demos:mirai-demo-gentleman'
)
include
(
':mirai-demos:mirai-demo-java'
)
include
(
':mirai-plugins'
)
include
(
':mirai-plugins:image-sender'
)
//include(':mirai-plugins')
//include(':mirai-plugins:image-sender')
try
{
def
javaVersion
=
System
.
getProperty
(
"java.version"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment