Merge remote-tracking branch 'origin/master'

This commit is contained in:
Him188 2020-02-23 18:14:44 +08:00
commit a8e7fa85a7
12 changed files with 6311 additions and 102 deletions

View File

@ -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.graphical.view.VerificationCodeFragment
import net.mamoe.mirai.console.utils.MiraiConsoleUI import net.mamoe.mirai.console.utils.MiraiConsoleUI
import net.mamoe.mirai.utils.LoginSolver import net.mamoe.mirai.utils.LoginSolver
import tornadofx.Controller import tornadofx.*
import tornadofx.Scope
import tornadofx.find
import tornadofx.observableListOf
class MiraiGraphicalUIController : Controller(), MiraiConsoleUI { class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
@ -28,8 +25,6 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
val botList = observableListOf<BotModel>() val botList = observableListOf<BotModel>()
val pluginList: ObservableList<PluginModel> by lazy(::getPluginsFromConsole) val pluginList: ObservableList<PluginModel> by lazy(::getPluginsFromConsole)
// val consoleConfig : Map<String, Any> by lazy(::getConfigFromConsole)
val consoleInfo = ConsoleInfo() val consoleInfo = ConsoleInfo()
fun login(qq: String, psd: String) { fun login(qq: String, psd: String) {
@ -79,10 +74,9 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
override fun createLoginSolver(): LoginSolver = loginSolver override fun createLoginSolver(): LoginSolver = loginSolver
private fun getPluginsFromConsole(): ObservableList<PluginModel> { private fun getPluginsFromConsole(): ObservableList<PluginModel> =
// TODO MiraiConsole.pluginManager.getAllPluginDescriptions().map(::PluginModel).toObservable()
return observableListOf<PluginModel>()
}
} }
class GraphicalLoginSolver : LoginSolver() { class GraphicalLoginSolver : LoginSolver() {

View File

@ -3,16 +3,17 @@ package net.mamoe.mirai.console.graphical.model
import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject
import javafx.beans.property.SimpleBooleanProperty import javafx.beans.property.SimpleBooleanProperty
import javafx.beans.property.SimpleStringProperty import javafx.beans.property.SimpleStringProperty
import net.mamoe.mirai.console.plugins.PluginDescription
import tornadofx.getValue import tornadofx.getValue
import tornadofx.setValue import tornadofx.setValue
class PluginModel : RecursiveTreeObject<PluginModel>() { class PluginModel(
val name: String,
val nameProperty = SimpleStringProperty(this, "nameProperty") val version: String,
val name by nameProperty val author: String,
val description: String
val descriptionProperty = SimpleStringProperty(this, "descriptionProperty") ) : RecursiveTreeObject<PluginModel>() {
val description by descriptionProperty constructor(plugin: PluginDescription):this(plugin.name, plugin.version, plugin.author, plugin.info)
val enabledProperty = SimpleBooleanProperty(this, "enabledProperty") val enabledProperty = SimpleBooleanProperty(this, "enabledProperty")
var enabled by enabledProperty var enabled by enabledProperty

View File

@ -13,10 +13,21 @@ class PluginsView : View() {
override val root = jfxTreeTableView(plugins) { override val root = jfxTreeTableView(plugins) {
columns.addAll( columns.addAll(
JFXTreeTableColumn<PluginModel, String>("插件名").apply { }, JFXTreeTableColumn<PluginModel, String>("插件名").apply {
JFXTreeTableColumn<PluginModel, String>("版本").apply { }, prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
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.6))
},
JFXTreeTableColumn<PluginModel, String>("操作").apply {
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.08))
}
) )
} }
} }

View File

@ -1,23 +1,36 @@
package net.mamoe.mirai.console.graphical.view package net.mamoe.mirai.console.graphical.view
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController 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 net.mamoe.mirai.console.graphical.util.jfxTextfield
import tornadofx.View import tornadofx.*
import tornadofx.field
import tornadofx.fieldset
import tornadofx.form
class SettingsView : View() { class SettingsView : View() {
private val controller = find<MiraiGraphicalUIController>() private val controller = find<MiraiGraphicalUIController>()
override val root = form { override val root = form {
// controller.consoleConfig.forEach {
// fieldset { fieldset {
// field(it.key) { field {
// jfxTextfield(it.value.toString()) { isEditable = false } jfxButton("撤掉") { }
// } jfxButton("保存") { }
// } }
// } }
fieldset("插件目录") {
field {
jfxTextfield("...") { isEditable = false }
jfxButton("打开目录")
}
}
fieldset("最大日志容量") {
field {
jfxTextfield("...") {
}
}
}
} }
} }

View File

@ -0,0 +1,2 @@
package net.mamoe.mirai.console

View File

@ -131,13 +131,6 @@ object DefaultCommands {
} }
bot.login() bot.login()
bot.subscribeMessages { bot.subscribeMessages {
contains("test") {
if (this is GroupMessage) {
quoteReply("Hello $senderName")
} else {
reply("Hello!")
}
}
this.startsWith("/") { this.startsWith("/") {
if (bot.checkManager(this.sender.id)) { if (bot.checkManager(this.sender.id)) {
val sender = ContactCommandSender(this.subject) val sender = ContactCommandSender(this.subject)
@ -149,7 +142,6 @@ object DefaultCommands {
} }
sendMessage("$qqNumber login successes") sendMessage("$qqNumber login successes")
MiraiConsole.frontEnd.pushBot(bot) MiraiConsole.frontEnd.pushBot(bot)
} catch (e: Exception) { } catch (e: Exception) {
sendMessage("$qqNumber login failed -> " + e.message) sendMessage("$qqNumber login failed -> " + e.message)
} }

View File

@ -48,6 +48,7 @@ interface Config {
fun getFloatList(key: String): List<Float> fun getFloatList(key: String): List<Float>
fun getDoubleList(key: String): List<Double> fun getDoubleList(key: String): List<Double>
fun getLongList(key: String): List<Long> fun getLongList(key: String): List<Long>
fun getConfigSectionList(key: String): List<ConfigSection>
operator fun set(key: String, value: Any) operator fun set(key: String, value: Any)
operator fun get(key: String): Any? operator fun get(key: String): Any?
operator fun contains(key: String): Boolean 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) Float::class -> getFloatList(propertyName)
Double::class -> getDoubleList(propertyName) Double::class -> getDoubleList(propertyName)
Long::class -> getLongList(propertyName) Long::class -> getLongList(propertyName)
//不去支持getConfigSectionList(propertyName)
// LinkedHashMap::class -> getConfigSectionList(propertyName)//faster approach
else -> { else -> {
error("unsupported type") //if(list[0]!! is ConfigSection || list[0]!! is Map<*,*>){
// getConfigSectionList(propertyName)
//}else {
error("unsupported type" + list[0]!!::class)
//}
} }
} }
} as T } 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() } 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 { override fun exist(key: String): Boolean {
return get(key) != null return get(key) != null
} }

View File

@ -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|连接这个图站需要你的网络在外网")
}
}
}

View File

@ -9,15 +9,27 @@
package net.mamoe.mirai.imageplugin package net.mamoe.mirai.imageplugin
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.*
import kotlinx.coroutines.GlobalScope 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.events.BotOnlineEvent
import net.mamoe.mirai.event.subscribeAlways import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.event.subscribeMessages import net.mamoe.mirai.event.subscribeMessages
import net.mamoe.mirai.console.plugins.PluginBase 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 net.mamoe.mirai.utils.MiraiExperimentalAPI
import org.jsoup.Jsoup
import java.io.File
import kotlin.random.Random
class ImageSenderMain : PluginBase() { class ImageSenderMain : PluginBase() {
lateinit var images: Config
lateinit var normal: List<ConfigSection>
lateinit var r18: List<ConfigSection>
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
@MiraiExperimentalAPI @MiraiExperimentalAPI
override fun onEnable() { override fun onEnable() {
@ -25,24 +37,61 @@ class ImageSenderMain : PluginBase() {
GlobalScope.subscribeAlways<BotOnlineEvent> { GlobalScope.subscribeAlways<BotOnlineEvent> {
logger.info("${this.bot.uin} login succeed, it will be controlled by Image Sender Plugin") logger.info("${this.bot.uin} login succeed, it will be controlled by Image Sender Plugin")
this.bot.subscribeMessages { this.bot.subscribeMessages {
(contains("色图")) {
case("at me") { try {
reply(sender.at() + " ? ") 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("")) { (contains("不够色")) {
"图片发送中".reply() try {
ImageProvider().apply { with(r18.random()) {
this.contact = sender getImage(
}.image.await().reply() 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() { 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() { override fun onDisable() {

View File

@ -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)
}
*/
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
name: ImageSender name: ImageSender
main: net.mamoe.mirai.imageplugin.ImageSenderMain main: net.mamoe.mirai.imageplugin.ImageSenderMain
version: 1.0.0 version: 1.0.0
author: mamoe author: 不想写代码
info: a demo plugin of mirai info: a demo[hso] plugin of mirai