mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-23 22:30:47 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
a8e7fa85a7
@ -13,10 +13,7 @@ import net.mamoe.mirai.console.graphical.model.VerificationCodeModel
|
||||
import net.mamoe.mirai.console.graphical.view.VerificationCodeFragment
|
||||
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
||||
import net.mamoe.mirai.utils.LoginSolver
|
||||
import tornadofx.Controller
|
||||
import tornadofx.Scope
|
||||
import tornadofx.find
|
||||
import tornadofx.observableListOf
|
||||
import tornadofx.*
|
||||
|
||||
class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
|
||||
|
||||
@ -28,8 +25,6 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
|
||||
val botList = observableListOf<BotModel>()
|
||||
val pluginList: ObservableList<PluginModel> by lazy(::getPluginsFromConsole)
|
||||
|
||||
// val consoleConfig : Map<String, Any> by lazy(::getConfigFromConsole)
|
||||
|
||||
val consoleInfo = ConsoleInfo()
|
||||
|
||||
fun login(qq: String, psd: String) {
|
||||
@ -79,10 +74,9 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
|
||||
|
||||
override fun createLoginSolver(): LoginSolver = loginSolver
|
||||
|
||||
private fun getPluginsFromConsole(): ObservableList<PluginModel> {
|
||||
// TODO
|
||||
return observableListOf<PluginModel>()
|
||||
}
|
||||
private fun getPluginsFromConsole(): ObservableList<PluginModel> =
|
||||
MiraiConsole.pluginManager.getAllPluginDescriptions().map(::PluginModel).toObservable()
|
||||
|
||||
}
|
||||
|
||||
class GraphicalLoginSolver : LoginSolver() {
|
||||
|
@ -3,16 +3,17 @@ package net.mamoe.mirai.console.graphical.model
|
||||
import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject
|
||||
import javafx.beans.property.SimpleBooleanProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import net.mamoe.mirai.console.plugins.PluginDescription
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
class PluginModel : RecursiveTreeObject<PluginModel>() {
|
||||
|
||||
val nameProperty = SimpleStringProperty(this, "nameProperty")
|
||||
val name by nameProperty
|
||||
|
||||
val descriptionProperty = SimpleStringProperty(this, "descriptionProperty")
|
||||
val description by descriptionProperty
|
||||
class PluginModel(
|
||||
val name: String,
|
||||
val version: String,
|
||||
val author: String,
|
||||
val description: String
|
||||
) : RecursiveTreeObject<PluginModel>() {
|
||||
constructor(plugin: PluginDescription):this(plugin.name, plugin.version, plugin.author, plugin.info)
|
||||
|
||||
val enabledProperty = SimpleBooleanProperty(this, "enabledProperty")
|
||||
var enabled by enabledProperty
|
||||
|
@ -13,10 +13,21 @@ class PluginsView : View() {
|
||||
|
||||
override val root = jfxTreeTableView(plugins) {
|
||||
columns.addAll(
|
||||
JFXTreeTableColumn<PluginModel, String>("插件名").apply { },
|
||||
JFXTreeTableColumn<PluginModel, String>("版本").apply { },
|
||||
JFXTreeTableColumn<PluginModel, String>("作者").apply { },
|
||||
JFXTreeTableColumn<PluginModel, String>("介绍").apply { }
|
||||
JFXTreeTableColumn<PluginModel, String>("插件名").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("版本").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("作者").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("介绍").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.6))
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("操作").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.08))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -1,23 +1,36 @@
|
||||
package net.mamoe.mirai.console.graphical.view
|
||||
|
||||
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
|
||||
import net.mamoe.mirai.console.graphical.util.jfxButton
|
||||
import net.mamoe.mirai.console.graphical.util.jfxTextfield
|
||||
import tornadofx.View
|
||||
import tornadofx.field
|
||||
import tornadofx.fieldset
|
||||
import tornadofx.form
|
||||
import tornadofx.*
|
||||
|
||||
class SettingsView : View() {
|
||||
|
||||
private val controller = find<MiraiGraphicalUIController>()
|
||||
|
||||
override val root = form {
|
||||
// controller.consoleConfig.forEach {
|
||||
// fieldset {
|
||||
// field(it.key) {
|
||||
// jfxTextfield(it.value.toString()) { isEditable = false }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fieldset {
|
||||
field {
|
||||
jfxButton("撤掉") { }
|
||||
jfxButton("保存") { }
|
||||
}
|
||||
}
|
||||
|
||||
fieldset("插件目录") {
|
||||
field {
|
||||
jfxTextfield("...") { isEditable = false }
|
||||
jfxButton("打开目录")
|
||||
}
|
||||
}
|
||||
|
||||
fieldset("最大日志容量") {
|
||||
field {
|
||||
jfxTextfield("...") {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
package net.mamoe.mirai.console
|
||||
|
@ -131,13 +131,6 @@ object DefaultCommands {
|
||||
}
|
||||
bot.login()
|
||||
bot.subscribeMessages {
|
||||
contains("test") {
|
||||
if (this is GroupMessage) {
|
||||
quoteReply("Hello $senderName")
|
||||
} else {
|
||||
reply("Hello!")
|
||||
}
|
||||
}
|
||||
this.startsWith("/") {
|
||||
if (bot.checkManager(this.sender.id)) {
|
||||
val sender = ContactCommandSender(this.subject)
|
||||
@ -149,7 +142,6 @@ object DefaultCommands {
|
||||
}
|
||||
sendMessage("$qqNumber login successes")
|
||||
MiraiConsole.frontEnd.pushBot(bot)
|
||||
|
||||
} catch (e: Exception) {
|
||||
sendMessage("$qqNumber login failed -> " + e.message)
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ interface Config {
|
||||
fun getFloatList(key: String): List<Float>
|
||||
fun getDoubleList(key: String): List<Double>
|
||||
fun getLongList(key: String): List<Long>
|
||||
fun getConfigSectionList(key: String): List<ConfigSection>
|
||||
operator fun set(key: String, value: Any)
|
||||
operator fun get(key: String): Any?
|
||||
operator fun contains(key: String): Boolean
|
||||
@ -196,8 +197,14 @@ fun <T : Any> Config._smartCast(propertyName: String, _class: KClass<T>): T {
|
||||
Float::class -> getFloatList(propertyName)
|
||||
Double::class -> getDoubleList(propertyName)
|
||||
Long::class -> getLongList(propertyName)
|
||||
//不去支持getConfigSectionList(propertyName)
|
||||
// LinkedHashMap::class -> getConfigSectionList(propertyName)//faster approach
|
||||
else -> {
|
||||
error("unsupported type")
|
||||
//if(list[0]!! is ConfigSection || list[0]!! is Map<*,*>){
|
||||
// getConfigSectionList(propertyName)
|
||||
//}else {
|
||||
error("unsupported type" + list[0]!!::class)
|
||||
//}
|
||||
}
|
||||
}
|
||||
} as T
|
||||
@ -271,6 +278,20 @@ interface ConfigSection : Config, MutableMap<String, Any> {
|
||||
return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map { it.toString().toLong() }
|
||||
}
|
||||
|
||||
override fun getConfigSectionList(key: String): List<ConfigSection> {
|
||||
return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map {
|
||||
if (it is ConfigSection) {
|
||||
it
|
||||
} else {
|
||||
ConfigSectionDelegation(
|
||||
Collections.synchronizedMap(
|
||||
it as MutableMap<String, Any>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun exist(key: String): Boolean {
|
||||
return get(key) != null
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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.imageplugin
|
||||
|
||||
import com.alibaba.fastjson.JSON
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.uploadAsImage
|
||||
import org.jsoup.Jsoup
|
||||
|
||||
class ImageProvider {
|
||||
lateinit var contact: Contact
|
||||
|
||||
// `Deferred<Image?>` causes a runtime ClassCastException
|
||||
|
||||
val image: Deferred<Image> by lazy {
|
||||
GlobalScope.async {
|
||||
withTimeoutOrNull(5 * 1000) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val result = JSON.parseArray(
|
||||
Jsoup.connect("https://yande.re/post.json?limit=1&page=${(Math.random() * 10000).toInt()}").ignoreContentType(
|
||||
true
|
||||
).timeout(
|
||||
10_0000
|
||||
).get().body().text()
|
||||
)
|
||||
Jsoup.connect(result.getJSONObject(0).getString("jpeg_url"))
|
||||
.userAgent("Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27")
|
||||
.timeout(10_0000)
|
||||
.ignoreContentType(true)
|
||||
.maxBodySize(Int.MAX_VALUE)
|
||||
.execute()
|
||||
.bodyStream()
|
||||
}
|
||||
}?.uploadAsImage(contact) ?: error("Unable to download image|连接这个图站需要你的网络在外网")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,15 +9,27 @@
|
||||
|
||||
package net.mamoe.mirai.imageplugin
|
||||
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.console.plugins.Config
|
||||
import net.mamoe.mirai.console.plugins.ConfigSection
|
||||
import net.mamoe.mirai.event.events.BotOnlineEvent
|
||||
import net.mamoe.mirai.event.subscribeAlways
|
||||
import net.mamoe.mirai.event.subscribeMessages
|
||||
import net.mamoe.mirai.console.plugins.PluginBase
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.uploadAsImage
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import org.jsoup.Jsoup
|
||||
import java.io.File
|
||||
import kotlin.random.Random
|
||||
|
||||
class ImageSenderMain : PluginBase() {
|
||||
|
||||
lateinit var images: Config
|
||||
lateinit var normal: List<ConfigSection>
|
||||
lateinit var r18: List<ConfigSection>
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@MiraiExperimentalAPI
|
||||
override fun onEnable() {
|
||||
@ -25,24 +37,61 @@ class ImageSenderMain : PluginBase() {
|
||||
GlobalScope.subscribeAlways<BotOnlineEvent> {
|
||||
logger.info("${this.bot.uin} login succeed, it will be controlled by Image Sender Plugin")
|
||||
this.bot.subscribeMessages {
|
||||
|
||||
case("at me") {
|
||||
reply(sender.at() + " ? ")
|
||||
(contains("色图")) {
|
||||
try {
|
||||
with(normal.random()) {
|
||||
getImage(
|
||||
subject, this.getString("url"), this.getString("pid")
|
||||
).plus(this.getString("tags")).send()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
reply(e.message ?: "unknown error")
|
||||
}
|
||||
}
|
||||
|
||||
(contains("image") or contains("图")) {
|
||||
"图片发送中".reply()
|
||||
ImageProvider().apply {
|
||||
this.contact = sender
|
||||
}.image.await().reply()
|
||||
(contains("不够色")) {
|
||||
try {
|
||||
with(r18.random()) {
|
||||
getImage(
|
||||
subject, this.getString("url"), this.getString("pid")
|
||||
).plus(this.getString("tags")).send()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
reply(e.message ?: "unknown error")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getImage(contact: Contact, url: String, pid: String): Image {
|
||||
return withTimeoutOrNull(20 * 1000) {
|
||||
withContext(Dispatchers.IO) {
|
||||
Jsoup
|
||||
.connect(url)
|
||||
.followRedirects(true)
|
||||
.timeout(180_000)
|
||||
.ignoreContentType(true)
|
||||
.userAgent("Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27")
|
||||
.referrer("https://www.pixiv.net/member_illust.php?mode=medium&illust_id=$pid")
|
||||
.ignoreHttpErrors(true)
|
||||
.maxBodySize(100000000)
|
||||
.execute().also { check(it.statusCode() == 200) { "Failed to download image" } }
|
||||
}
|
||||
}?.bodyStream()?.uploadAsImage(contact) ?: error("Unable to download image")
|
||||
}
|
||||
|
||||
override fun onLoad() {
|
||||
logger.info("loading...")
|
||||
logger.info("loading local image data")
|
||||
try {
|
||||
images = Config.load(this.javaClass.classLoader.getResource("data.yml")!!.path!!)
|
||||
} catch (e: Exception) {
|
||||
logger.info("无法加载本地图片")
|
||||
}
|
||||
logger.info("本地图片版本" + images.getString("version"))
|
||||
logger.info("Normal * " + images.getList("normal").size)
|
||||
logger.info("R18 * " + images.getList("R18").size)
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
|
@ -0,0 +1,144 @@
|
||||
import com.alibaba.fastjson.JSONObject
|
||||
import com.google.gson.JsonObject
|
||||
import net.mamoe.mirai.console.plugins.*
|
||||
import net.mamoe.mirai.utils.cryptor.contentToString
|
||||
import org.jsoup.Connection
|
||||
import org.jsoup.Jsoup
|
||||
import java.io.File
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
object Data {
|
||||
val section = (File(System.getProperty("user.dir") + "/setu.yml")).loadAsConfig()
|
||||
|
||||
|
||||
val abstract = section.getStringList("abstract").toMutableList()
|
||||
val R18 = section.getConfigSectionList("R18").toMutableList()
|
||||
val normal = section.getConfigSectionList("normal").toMutableList()
|
||||
|
||||
fun init() {
|
||||
section.setIfAbsent("abstract", mutableListOf<String>())
|
||||
section.setIfAbsent("R18", mutableListOf<ConfigSection>())
|
||||
section.setIfAbsent("Normal", mutableListOf<ConfigSection>())
|
||||
}
|
||||
|
||||
fun save() {
|
||||
section["abstract"] = abstract
|
||||
section["R18"] = R18
|
||||
section["normal"] = normal
|
||||
section.save()
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
|
||||
val abstract_file = (File(System.getProperty("user.dir") + "/abstractSetu.yml")).loadAsConfig()
|
||||
|
||||
abstract_file.setIfAbsent("R18", mutableListOf<ConfigSection>())
|
||||
abstract_file.setIfAbsent("normal", mutableListOf<ConfigSection>())
|
||||
|
||||
val r18 = abstract_file.getConfigSectionList("R18").toMutableList()
|
||||
val normal = abstract_file.getConfigSectionList("normal").toMutableList()
|
||||
|
||||
Data.R18.forEach {
|
||||
val forbid = with(it.getString("tags")) {
|
||||
this.contains("初音ミク") || this.contains("VOCALOID") || this.contains("Miku")
|
||||
||
|
||||
this.contains("东方") || this.contains("東方")
|
||||
}
|
||||
if (forbid) {
|
||||
println("过滤掉了一张图")
|
||||
} else {
|
||||
r18.add(
|
||||
ConfigSectionImpl().apply {
|
||||
this["pid"] = it["pid"]!!
|
||||
this["author"] = it["author"]!!
|
||||
this["uid"] = it["uid"]!!
|
||||
this["tags"] = it["tags"]!!
|
||||
this["url"] = it["url"]!!
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Data.normal.forEach {
|
||||
val forbid = with(it.getString("tags")) {
|
||||
this.contains("初音ミク") || this.contains("VOCALOID") || this.contains("Miku")
|
||||
||
|
||||
this.contains("东方") || this.contains("東方")
|
||||
}
|
||||
if (forbid) {
|
||||
println("过滤掉了一张图")
|
||||
} else {
|
||||
normal.add(
|
||||
ConfigSectionImpl().apply {
|
||||
this["pid"] = it["pid"]!!
|
||||
this["author"] = it["author"]!!
|
||||
this["uid"] = it["uid"]!!
|
||||
this["tags"] = it["tags"]!!
|
||||
this["url"] = it["url"]!!
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
abstract_file.set("R18", r18)
|
||||
abstract_file.set("normal", normal)
|
||||
abstract_file.save()
|
||||
|
||||
/**
|
||||
Data.init()
|
||||
Runtime.getRuntime().addShutdownHook(thread(start = false) {
|
||||
Data.save()
|
||||
})
|
||||
|
||||
while (true){
|
||||
try {
|
||||
val val0 = JSONObject.parseObject(Jsoup
|
||||
.connect("https://api.lolicon.app/setu/")
|
||||
.ignoreContentType(true)
|
||||
.method(Connection.Method.GET)
|
||||
.data("r18","1")
|
||||
.data("num","10")
|
||||
.execute().body())
|
||||
|
||||
val val1 = val0.getJSONArray("data")
|
||||
for(index in 0 until val1.size - 1){
|
||||
val content = val1.getJSONObject(index)
|
||||
|
||||
val pid = content.getString("pid")
|
||||
if(Data.abstract.contains(pid)){
|
||||
println("获取到了一张重复图$pid")
|
||||
continue
|
||||
}
|
||||
val configSection = ConfigSectionImpl()
|
||||
val isR18 = content.getBoolean("r18")
|
||||
configSection["author"] = content.getString("author")
|
||||
configSection["pid"] = pid
|
||||
configSection["uid"] = content.getInteger("uid")
|
||||
configSection["width"] = content.getInteger("width")
|
||||
configSection["height"] = content.getInteger("height")
|
||||
configSection["tags"] = content.getJSONArray("tags").map {
|
||||
it.toString()
|
||||
}.joinToString(",")
|
||||
configSection["url"] = content.getString("url")
|
||||
if(isR18){
|
||||
Data.R18.add(configSection)
|
||||
print("获取到了一张R18")
|
||||
}else{
|
||||
Data.normal.add(configSection)
|
||||
print("获取到了一张Normal")
|
||||
}
|
||||
Data.abstract.add(pid)
|
||||
println(configSection.contentToString())
|
||||
}
|
||||
}catch (e:Exception){
|
||||
println(e.message)
|
||||
}
|
||||
Data.save()
|
||||
println("SAVED")
|
||||
Thread.sleep(1000)
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
}
|
6030
mirai-plugins/image-sender/src/main/resources/data.yml
Normal file
6030
mirai-plugins/image-sender/src/main/resources/data.yml
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
name: ImageSender
|
||||
main: net.mamoe.mirai.imageplugin.ImageSenderMain
|
||||
version: 1.0.0
|
||||
author: mamoe
|
||||
info: a demo plugin of mirai
|
||||
author: 不想写代码
|
||||
info: a demo[hso] plugin of mirai
|
||||
|
Loading…
Reference in New Issue
Block a user