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
35f06b3b
Commit
35f06b3b
authored
Feb 12, 2020
by
Him188
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
fec3702b
240183d5
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
301 additions
and
90 deletions
+301
-90
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
...ain/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
+4
-0
mirai-console/build.gradle.kts
mirai-console/build.gradle.kts
+1
-0
mirai-console/src/main/kotlin/Command.kt
mirai-console/src/main/kotlin/Command.kt
+11
-3
mirai-console/src/main/kotlin/MiraiConsole.kt
mirai-console/src/main/kotlin/MiraiConsole.kt
+112
-51
mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/ConfigSection.kt
...e/src/main/kotlin/net/mamoe/mirai/plugin/ConfigSection.kt
+164
-14
mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
...sole/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
+9
-22
No files found.
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
View file @
35f06b3b
...
...
@@ -24,6 +24,10 @@ object MiraiHttpAPIServer {
SessionManager
.
authKey
=
generateSessionKey
()
//用于验证的key, 使用和SessionKey相同的方法生成, 但意义不同
}
fun
setAuthKey
(
key
:
String
)
{
SessionManager
.
authKey
=
key
}
@UseExperimental
(
KtorExperimentalAPI
::
class
)
fun
start
(
port
:
Int
=
8080
,
...
...
mirai-console/build.gradle.kts
View file @
35f06b3b
...
...
@@ -25,6 +25,7 @@ fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
dependencies
{
api
(
project
(
":mirai-core"
))
api
(
project
(
":mirai-core-qqandroid"
))
api
(
project
(
":mirai-api-http"
))
runtimeOnly
(
files
(
"../mirai-core-qqandroid/build/classes/kotlin/jvm/main"
))
runtimeOnly
(
files
(
"../mirai-core/build/classes/kotlin/jvm/main"
))
api
(
kotlin
(
"serialization"
))
...
...
mirai-console/src/main/kotlin/
net/mamoe/mirai/plugin/
Command.kt
→
mirai-console/src/main/kotlin/Command.kt
View file @
35f06b3b
...
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.plugin
import
net.mamoe.mirai.plugin.PluginManager
object
CommandManager
{
private
val
registeredCommand
:
MutableMap
<
String
,
Command
>
=
mutableMapOf
()
...
...
@@ -25,6 +25,13 @@ object CommandManager {
}
}
fun
unregister
(
command
:
Command
)
{
val
allNames
=
mutableListOf
<
String
>(
command
.
name
).
also
{
it
.
addAll
(
command
.
alias
)
}
allNames
.
forEach
{
registeredCommand
.
remove
(
it
)
}
}
fun
runCommand
(
fullCommand
:
String
):
Boolean
{
val
blocks
=
fullCommand
.
split
(
" "
)
val
commandHead
=
blocks
[
0
].
replace
(
"/"
,
""
)
...
...
@@ -43,12 +50,12 @@ object CommandManager {
return
true
}
}
abstract
class
Command
(
val
name
:
String
,
val
alias
:
List
<
String
>
=
listOf
()
val
alias
:
List
<
String
>
=
listOf
(),
val
description
:
String
=
""
)
{
/**
* 最高优先级监听器
...
...
@@ -58,3 +65,4 @@ abstract class Command(
return
true
}
}
mirai-console/src/main/kotlin/MiraiConsole.kt
View file @
35f06b3b
...
...
@@ -9,73 +9,134 @@
import
kotlinx.coroutines.runBlocking
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.plugin.Command
import
net.mamoe.mirai.plugin.CommandManager
import
net.mamoe.mirai.alsoLogin
import
net.mamoe.mirai.api.http.generateSessionKey
import
net.mamoe.mirai.plugin.JsonConfig
import
net.mamoe.mirai.plugin.PluginBase
import
net.mamoe.mirai.plugin.PluginManager
import
java.io.File
import
kotlin.concurrent.thread
val
bots
=
mutableMapOf
<
Long
,
Bot
>()
object
MiraiConsole
{
val
bots
get
()
=
Bot
.
instances
fun
main
()
{
println
(
"loading Mirai in console environments"
)
println
(
"正在控制台环境中启动Mirai "
)
println
()
println
(
"Mirai-console is still in testing stage, some feature is not available"
)
println
(
"Mirai-console 还处于测试阶段, 部分功能不可用"
)
println
()
println
(
"Mirai-console now running on "
+
System
.
getProperty
(
"user.dir"
))
println
(
"Mirai-console 正在 "
+
System
.
getProperty
(
"user.dir"
)
+
" 运行"
)
println
()
println
(
"\"/login qqnumber qqpassword \" to login a bot"
)
println
(
"\"/login qq号 qq密码 \" 来登陆一个BOT"
)
thread
{
processNextCommandLine
()
}
PluginManager
.
loadPlugins
()
defaultCommands
()
val
pluginManager
:
PluginManager
get
()
=
PluginManager
Runtime
.
getRuntime
().
addShutdownHook
(
thread
(
start
=
false
)
{
PluginManager
.
disableAllPlugins
()
})
}
var
logger
:
MiraiConsoleLogger
=
DefaultLogger
var
path
:
String
=
System
.
getProperty
(
"user.dir"
)
fun
defaultCommands
()
{
class
LoginCommand
:
Command
(
"login"
)
{
override
fun
onCommand
(
args
:
List
<
String
>):
Boolean
{
if
(
args
.
size
<
2
)
{
println
(
"\"/login qqnumber qqpassword \" to login a bot"
)
println
(
"\"/login qq号 qq密码 \" 来登录一个BOT"
)
return
false
}
val
qqNumber
=
args
[
0
].
toLong
()
val
qqPassword
=
args
[
1
]
println
(
"login..."
)
runBlocking
{
val
version
=
" 0.13"
val
build
=
"Beta"
fun
start
()
{
logger
(
"Mirai-console v${version} $build is still in testing stage, majority feature is available"
)
logger
(
"Mirai-console v${version} $build 还处于测试阶段, 大部分功能可用"
)
logger
()
logger
(
"Mirai-console now running under "
+
System
.
getProperty
(
"user.dir"
))
logger
(
"Mirai-console 正在 "
+
System
.
getProperty
(
"user.dir"
)
+
"下运行"
)
logger
()
logger
(
"Get news in github: https://github.com/mamoe/mirai"
)
logger
(
"在Github中获取项目最新进展: https://github.com/mamoe/mirai"
)
logger
(
"Mirai为开源项目,请自觉遵守开源项目协议"
)
logger
(
"Powered by Mamoe Technology"
)
logger
()
logger
(
"\"/login qqnumber qqpassword \" to login a bot"
)
logger
(
"\"/login qq号 qq密码 \" 来登陆一个BOT"
)
CommandManager
.
register
(
DefaultCommands
.
DefaultLoginCommand
())
pluginManager
.
loadPlugins
()
CommandListener
.
start
()
}
fun
stop
()
{
PluginManager
.
disableAllPlugins
()
}
/**
* Defaults Commands are recommend to be replaced by plugin provided commands
*/
object
DefaultCommands
{
class
DefaultLoginCommand
:
Command
(
"login"
)
{
override
fun
onCommand
(
args
:
List
<
String
>):
Boolean
{
if
(
args
.
size
<
2
)
{
println
(
"\"/login qqnumber qqpassword \" to login a bot"
)
println
(
"\"/login qq号 qq密码 \" 来登录一个BOT"
)
return
false
}
val
qqNumber
=
args
[
0
].
toLong
()
val
qqPassword
=
args
[
1
]
println
(
"login..."
)
try
{
Bot
(
qqNumber
,
qqPassword
).
also
{
it
.
login
()
bots
[
qqNumber
]
=
it
runBlocking
{
Bot
(
qqNumber
,
qqPassword
).
alsoLogin
()
}
}
catch
(
e
:
Exception
)
{
println
(
"$qqNumber login failed"
)
}
return
true
}
return
true
}
}
CommandManager
.
register
(
LoginCommand
())
}
tailrec
fun
processNextCommandLine
()
{
val
fullCommand
=
readLine
()
if
(
fullCommand
!=
null
&&
fullCommand
.
startsWith
(
"/"
))
{
if
(!
CommandManager
.
runCommand
(
fullCommand
))
{
println
(
"unknown command $fullCommand"
)
println
(
"未知指令 $fullCommand"
)
object
CommandListener
{
fun
start
()
{
thread
{
processNextCommandLine
()
}
}
tailrec
fun
processNextCommandLine
()
{
val
fullCommand
=
readLine
()
if
(
fullCommand
!=
null
&&
fullCommand
.
startsWith
(
"/"
))
{
if
(!
CommandManager
.
runCommand
(
fullCommand
))
{
logger
(
"unknown command $fullCommand"
)
logger
(
"未知指令 $fullCommand"
)
}
}
processNextCommandLine
();
}
}
interface
MiraiConsoleLogger
{
operator
fun
invoke
(
any
:
Any
?
=
null
)
}
object
DefaultLogger
:
MiraiConsoleLogger
{
override
fun
invoke
(
any
:
Any
?)
{
println
(
"[Mirai${version} $build]: "
+
any
?.
toString
())
}
}
object
MiraiProperties
{
var
HTTP_API_ENABLE
:
Boolean
=
true
var
HTTP_API_PORT
:
Short
=
8080
var
HTTP_API_AUTH_KEY
:
String
=
""
private
val
file
=
File
(
path
+
"/mirai.json"
.
replace
(
"//"
,
"/"
))
private
lateinit
var
config
:
JsonConfig
fun
load
()
{
if
(!
file
.
exists
())
{
HTTP_API_AUTH_KEY
=
"INITKEY"
+
generateSessionKey
()
save
()
return
}
config
=
PluginBase
}
fun
save
()
{
}
}
processNextCommandLine
();
}
fun
main
()
{
MiraiConsole
.
start
()
Runtime
.
getRuntime
().
addShutdownHook
(
thread
(
start
=
false
)
{
MiraiConsole
.
stop
()
})
}
mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/ConfigSection.kt
View file @
35f06b3b
...
...
@@ -9,55 +9,205 @@
package
net.mamoe.mirai.plugin
import
kotlinx.serialization.KSerializer
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
kotlinx.serialization.UnstableDefault
import
kotlinx.serialization.json.Json
import
java.io.File
import
java.util.concurrent.ConcurrentHashMap
import
kotlin.properties.Delegates
import
kotlin.properties.ReadWriteProperty
import
kotlin.reflect.KProperty
import
kotlin.reflect.full.isSubclassOf
@Serializable
class
ConfigSection
()
:
ConcurrentHashMap
<
String
,
Any
>()
{
/**
* TODO: support all config types
*/
interface
Config
{
fun
getConfigSection
(
key
:
String
):
ConfigSection
fun
getString
(
key
:
String
):
String
fun
getInt
(
key
:
String
):
Int
fun
getFloat
(
key
:
String
):
Float
fun
getDouble
(
key
:
String
):
Double
fun
getLong
(
key
:
String
):
Long
fun
getList
(
key
:
String
):
List
<
*
>
fun
getStringList
(
key
:
String
):
List
<
String
>
fun
getIntList
(
key
:
String
):
List
<
Int
>
fun
getFloatList
(
key
:
String
):
List
<
Float
>
fun
getDoubleList
(
key
:
String
):
List
<
Double
>
fun
getLongList
(
key
:
String
):
List
<
Long
>
operator
fun
set
(
key
:
String
,
value
:
Any
)
operator
fun
get
(
key
:
String
):
Any
?
fun
exist
(
key
:
String
):
Boolean
fun
asMap
():
Map
<
String
,
Any
>
}
inline
fun
<
reified
T
:
Any
>
Config
.
withDefault
(
crossinline
defaultValue
:
()
->
T
):
ReadWriteProperty
<
Any
,
T
>
{
return
object
:
ReadWriteProperty
<
Any
,
T
>
{
override
fun
getValue
(
thisRef
:
Any
,
property
:
KProperty
<
*
>):
T
{
if
(!
this
@
withDefault
.
exist
(
property
.
name
))
{
return
defaultValue
.
invoke
()
}
return
getValue
(
thisRef
,
property
)
}
override
fun
setValue
(
thisRef
:
Any
,
property
:
KProperty
<
*
>,
value
:
T
)
{
this
@
withDefault
[
property
.
name
]
=
value
}
}
}
@Suppress
(
"IMPLICIT_CAST_TO_ANY"
)
inline
operator
fun
<
reified
T
>
ConfigSection
.
getValue
(
thisRef
:
Any
?,
property
:
KProperty
<
*
>):
T
{
return
when
(
T
::
class
)
{
String
::
class
-> this.get
String
(
property
.
name
)
Int
::
class
-> this.get
Int
(
property
.
name
)
Float
::
class
-> this.get
Float
(
property
.
name
)
Double
::
class
-> this.get
Double
(
property
.
name
)
Long
::
class
-> this.get
Long
(
property
.
name
)
else
->
when
{
T
::
class
.
isSubclassOf
(
ConfigSection
::
class
)
->
this
.
getConfigSection
(
property
.
name
)
T
::
class
==
List
::
class
||
T
::
class
==
MutableList
::
class
-> {
val list = this.get
List
(
property
.
name
)
return
if
(
list
.
isEmpty
())
{
list
}
else
{
when
(
list
[
0
]
!!::
class
)
{
String
::
class
-> get
StringList
(
property
.
name
)
Int
::
class
-> get
IntList
(
property
.
name
)
Float
::
class
-> get
FloatList
(
property
.
name
)
Double
::
class
-> get
DoubleList
(
property
.
name
)
Long
::
class
-> get
LongList
(
property
.
name
)
else
->
{
error
(
"unsupported type"
)
}
}
}
as
T
}
else
->
{
error
(
"unsupported type"
)
}
}
}
as
T
}
inline
operator
fun
<
reified
T
>
ConfigSection
.
setValue
(
thisRef
:
Any
?,
property
:
KProperty
<
*
>,
value
:
T
)
{
this
[
property
.
name
]
=
value
!!
}
interface
ConfigSection
:
Config
{
override
fun
getConfigSection
(
key
:
String
):
ConfigSection
{
return
(
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
))
as
ConfigSection
}
fun
getString
(
key
:
String
):
String
{
override
fun
getString
(
key
:
String
):
String
{
return
(
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
)).
toString
()
}
fun
getInt
(
key
:
String
):
Int
{
override
fun
getInt
(
key
:
String
):
Int
{
return
(
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
)).
toString
().
toInt
()
}
fun
getFloat
(
key
:
String
):
Float
{
override
fun
getFloat
(
key
:
String
):
Float
{
return
(
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
)).
toString
().
toFloat
()
}
fun
getDouble
(
key
:
String
):
Double
{
override
fun
getDouble
(
key
:
String
):
Double
{
return
(
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
)).
toString
().
toDouble
()
}
fun
getLong
(
key
:
String
):
Long
{
override
fun
getLong
(
key
:
String
):
Long
{
return
(
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
)).
toString
().
toLong
()
}
fun
getConfigSection
(
key
:
String
):
ConfigSection
{
return
(
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
))
as
ConfigSection
override
fun
getList
(
key
:
String
):
List
<
*
>
{
return
(
(
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
))
as
List
<
*
>)
}
fun
getStringList
(
key
:
String
):
List
<
String
>
{
override
fun
getStringList
(
key
:
String
):
List
<
String
>
{
return
((
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
))
as
List
<
*
>).
map
{
it
.
toString
()
}
}
fun
getIntList
(
key
:
String
):
List
<
Int
>
{
override
fun
getIntList
(
key
:
String
):
List
<
Int
>
{
return
((
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
))
as
List
<
*
>).
map
{
it
.
toString
().
toInt
()
}
}
fun
getFloatList
(
key
:
String
):
List
<
Float
>
{
override
fun
getFloatList
(
key
:
String
):
List
<
Float
>
{
return
((
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
))
as
List
<
*
>).
map
{
it
.
toString
().
toFloat
()
}
}
fun
getDoubleList
(
key
:
String
):
List
<
Double
>
{
override
fun
getDoubleList
(
key
:
String
):
List
<
Double
>
{
return
((
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
))
as
List
<
*
>).
map
{
it
.
toString
().
toDouble
()
}
}
fun
getLongList
(
key
:
String
):
List
<
Long
>
{
override
fun
getLongList
(
key
:
String
):
List
<
Long
>
{
return
((
get
(
key
)
?:
error
(
"ConfigSection does not contain $key "
))
as
List
<
*
>).
map
{
it
.
toString
().
toLong
()
}
}
override
operator
fun
set
(
key
:
String
,
value
:
Any
)
{
this
[
key
]
=
value
}
}
@Serializable
open
class
ConfigSectionImpl
()
:
ConcurrentHashMap
<
String
,
Any
>(),
ConfigSection
{
override
operator
fun
get
(
key
:
String
):
Any
?
{
return
super
.
get
(
key
)
}
override
fun
exist
(
key
:
String
):
Boolean
{
return
containsKey
(
key
)
}
override
fun
asMap
():
Map
<
String
,
Any
>
{
return
this
}
}
interface
FileConfig
{
}
@Serializable
abstract
class
FileConfigImpl
internal
constructor
()
:
ConfigSectionImpl
(),
FileConfig
{
}
@Serializable
class
JsonConfig
internal
constructor
()
:
FileConfigImpl
()
{
companion
object
{
@UnstableDefault
fun
load
(
file
:
File
):
Config
{
require
(
file
.
extension
.
toLowerCase
()
==
"json"
)
val
content
=
file
.
apply
{
if
(!
this
.
exists
())
this
.
createNewFile
()
}.
readText
()
if
(
content
.
isEmpty
()
||
content
.
isBlank
())
{
return
JsonConfig
()
}
return
Json
.
parse
(
JsonConfig
.
serializer
(),
content
)
}
@UnstableDefault
fun
save
(
file
:
File
,
config
:
JsonConfig
)
{
require
(
file
.
extension
.
toLowerCase
()
==
"json"
)
val
content
=
Json
.
stringify
(
JsonConfig
.
serializer
(),
config
)
file
.
apply
{
if
(!
this
.
exists
())
this
.
createNewFile
()
}.
writeText
(
content
)
}
}
}
\ No newline at end of file
mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
View file @
35f06b3b
...
...
@@ -9,6 +9,7 @@
package
net.mamoe.mirai.plugin
import
Command
import
kotlinx.coroutines.*
import
kotlinx.serialization.UnstableDefault
import
kotlinx.serialization.json.Json
...
...
@@ -66,32 +67,18 @@ abstract class PluginBase(coroutineContext: CoroutineContext) : CoroutineScope {
this
.
onEnable
()
}
/**
* TODO: support all config types
*/
@UnstableDefault
fun
loadConfig
(
fileName
:
String
=
"config.json"
):
ConfigSection
{
var
content
=
File
(
dataFolder
.
name
+
"/"
+
fileName
)
.
also
{
if
(!
it
.
exists
())
it
.
createNewFile
()
}.
readText
()
if
(
content
==
""
)
{
content
=
"{}"
}
return
Json
.
parse
(
ConfigSection
.
serializer
(),
content
)
fun
loadConfig
(
fileName
:
String
):
Config
{
return
JsonConfig
.
load
(
File
(
fileName
))
}
@UnstableDefault
fun
saveConfig
(
config
:
ConfigSection
,
fileName
:
String
=
"config.json"
)
{
val
content
=
Json
.
stringify
(
ConfigSection
.
serializer
(),
config
)
File
(
dataFolder
.
name
+
"/"
+
fileName
)
.
also
{
if
(!
it
.
exists
())
it
.
createNewFile
()
}.
writeText
(
content
)
fun
saveConfig
(
config
:
Config
,
fileName
:
String
=
"config.json"
)
{
JsonConfig
.
save
(
file
=
File
(
fileName
),
config
=
config
as
JsonConfig
)
}
...
...
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