diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 32218673..e85a38d9 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -26,13 +26,16 @@ "@javatypes/spring-data-redis": "^0.0.3", "@javatypes/spring-web": "^0.0.3", "@javatypes/tomcat": "^0.0.3", + "@types/crypto-js": "^4.0.1", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "typescript": "^4.0.5" }, "dependencies": { + "@babel/standalone": "^7.12.9", "@ccms/api": "^0.12.0", "@ccms/container": "^0.12.0", - "@ccms/plugin": "^0.12.0" + "@ccms/plugin": "^0.12.0", + "crypto-js": "^4.0.0" } } diff --git a/packages/plugins/src/HelloWorld.ts b/packages/plugins/src/HelloWorld.ts index 6cc8e6d5..1e0dbfdf 100644 --- a/packages/plugins/src/HelloWorld.ts +++ b/packages/plugins/src/HelloWorld.ts @@ -1,24 +1,24 @@ /// -/// +/// /// -import { server } from '@ccms/api'; -import { inject } from '@ccms/container'; -import { plugin, interfaces, cmd, listener, tab } from '@ccms/plugin' +import { server } from '@ccms/api' +import { Autowired } from '@ccms/container' +import { Cmd, JSPlugin, Listener, Tab, interfaces } from '@ccms/plugin' -@plugin({ name: 'HelloWorld', version: '1.0.0', author: 'MiaoWoo', source: __filename }) +@JSPlugin({ name: 'HelloWorld', version: '1.0.0', author: 'MiaoWoo', source: __filename }) export class HelloWorld extends interfaces.Plugin { - @inject(server.Server) + @Autowired(server.Server) private Server: server.Server load() { - this.logger.log('Plugin load from MiaoScript Plugin System...'); + this.logger.log('Plugin load from MiaoScript Plugin System...') } enable() { - this.logger.log('Plugin enable from MiaoScript Plugin System...'); + this.logger.log('Plugin enable from MiaoScript Plugin System...') } disable() { - this.logger.log('Plugin disable from MiaoScript Plugin System...'); + this.logger.log('Plugin disable from MiaoScript Plugin System...') } bukkitload() { @@ -61,28 +61,29 @@ export class HelloWorld extends interfaces.Plugin { this.logger.log('Plugin Disable When ServerType is Nukkit!') } - @cmd() + @Cmd() hello(sender: any, command: string, args: string[]) { - this.logger.log(sender, command, args); + this.logger.log(sender, command, args) sender.sendMessage(JSON.stringify({ command, ...args })) } - @tab() + @Tab() tabhello(_sender: any, _command: string, _args: string[]) { return ['world'] } - @listener({ servers: ['bukkit', 'nukkit'] }) + @Listener({ servers: ['bukkit', 'nukkit'] }) PlayerJoin(event: org.bukkit.event.player.PlayerJoinEvent) { - let plyaer = event.getPlayer(); + let plyaer = event.getPlayer() this.logger.console(`§cBukkit §aPlayerJoinEvent: §b${plyaer.getName()}`) - setTimeout(() => this.sendWelcome(plyaer), 10); + setTimeout(() => this.sendWelcome(plyaer), 500) } - @listener({ servers: ['sponge'] }) + @Listener({ servers: ['sponge'] }) ClientConnectionEvent$Join(event: org.spongepowered.api.event.network.ClientConnectionEvent.Join) { + event.getTargetEntity().getLocation() this.logger.console(`§cSponge §aClientConnectionEvent.Join: §b${event.getTargetEntity().getName()}`) - setTimeout(() => this.sendWelcome(event.getTargetEntity()), 10); + setTimeout(() => this.sendWelcome(event.getTargetEntity()), 500) } private sendWelcome(player: any) { @@ -90,10 +91,9 @@ export class HelloWorld extends interfaces.Plugin { this.logger.sender(player, `§6当前版本: §c${this.Server.getVersion()}`) } - @listener({ servers: ['bungee'] }) - ServerConnected(e: any) { - let event = e as net.md_5.bungee.api.event.ServerConnectedEvent + @Listener({ servers: ['bungee'] }) + ServerConnected(event: net.md_5.bungee.api.event.ServerConnectedEvent) { this.logger.console(`§cBungeeCord §aServerConnectedEvent: §b${event.getPlayer().getDisplayName()}`) - setTimeout(() => this.logger.sender(event.getPlayer(), `§a欢迎来到 §bMiaoScript §a的世界 §6来自 §cBungeeCord §6的问候!`), 10); + setTimeout(() => this.logger.sender(event.getPlayer(), `§a欢迎来到 §bMiaoScript §a的世界 §6来自 §cBungeeCord §6的问候!`), 500) } } diff --git a/packages/plugins/src/MiaoAuth.ts b/packages/plugins/src/MiaoAuth.ts new file mode 100644 index 00000000..69fdc1e4 --- /dev/null +++ b/packages/plugins/src/MiaoAuth.ts @@ -0,0 +1,48 @@ +/// +/// +/// + +import { plugin, server } from '@ccms/api' +import { Autowired } from '@ccms/container' +import { Cmd, interfaces, JSPlugin, Tab } from '@ccms/plugin' + +import type { MiaoReward } from './MiaoReward' +import * as fs from '@ccms/common/dist/fs' + +@JSPlugin({ version: '1.0.0', author: 'MiaoWoo', source: __filename, depends: ['MiaoReward'] }) +export class MiaoAuth extends interfaces.Plugin { + @Autowired() + private Server: server.Server + @Autowired() + private pluginManager: plugin.PluginManager + + private MiaoReward: MiaoReward + + load() { + } + + enable() { + this.MiaoReward = this.pluginManager.getPlugin('MiaoReward') as MiaoReward + if (!this.MiaoReward) { return this.logger.error('当前脚本插件需要 MiaoReward 作为前置插件!') } + + } + + disable() { + } + + @Cmd({ autoMain: true }) + msma() { } + + cmdbind(sender: org.bukkit.entity.Player) { + if (!sender.getItemInHand) { return this.logger.sender(sender, '§4控制台无法执行此命令!') } + if (!this.MiaoReward.serverInfo) { return this.logger.sender(sender, '§4当前服务器尚未配置 请联系管理员配置MiaoReward!') } + this.MiaoReward.scanAuth(sender, 'bind', { title: '账号绑定', content: '是否绑定' }, (token, user) => { + + }, () => { + + }) + } + + @Tab() + tabmsma() { } +} diff --git a/packages/plugins/src/MiaoChat.ts b/packages/plugins/src/MiaoChat.ts index 7c98d99e..244ed113 100644 --- a/packages/plugins/src/MiaoChat.ts +++ b/packages/plugins/src/MiaoChat.ts @@ -50,7 +50,7 @@ class MiaoMessage { } } -@plugin({ name: 'MiaoChat', version: '1.0.0', author: 'MiaoWoo', source: __filename }) +@plugin({ version: '1.0.1', author: 'MiaoWoo', source: __filename }) export class MiaoChat extends interfaces.Plugin { @Autowired() private Server: server.Server diff --git a/packages/plugins/src/MiaoConsole.ts b/packages/plugins/src/MiaoConsole.ts index eb1a6199..98dea07b 100644 --- a/packages/plugins/src/MiaoConsole.ts +++ b/packages/plugins/src/MiaoConsole.ts @@ -19,7 +19,7 @@ let help = [ '§6/mconsole §areload §6- §3重载插件', ] -@plugin({ prefix: 'Console', version: '1.0.0', author: 'MiaoWoo', servers: ['!nukkit'], source: __filename }) +@plugin({ prefix: 'Console', version: '1.1.0', author: 'MiaoWoo', servers: ['!nukkit'], source: __filename }) export class MiaoConsole extends interfaces.Plugin { @Autowired(ContainerInstance) private container: Container @@ -42,6 +42,7 @@ export class MiaoConsole extends interfaces.Plugin { private rootLogger: any private appender: any private handler: any + private babel: any private logCache: string[] = [] @@ -62,6 +63,15 @@ export class MiaoConsole extends interfaces.Plugin { this.logCache = this.logCache.slice(this.logCache.length - 30, this.logCache.length) } }) + this.task.create(() => { + if (!this.babel) { + this.logger.console('§3脚本 Babel 引擎初始化中 请稍候...') + let startTime = Date.now() + this.babel = require('@babel/standalone') + this.compileCode(`() => console.log("Babel ready!")`) + this.logger.console(`§3脚本 Babel 引擎初始化完毕 耗时 §a${Date.now() - startTime}ms...`) + } + }).async().submit() } @cmd() @@ -81,8 +91,6 @@ export class MiaoConsole extends interfaces.Plugin { } cmdreload(sender: any) { - // @ts-ignore - require.clear('websocket') this.pluginManager.reload(this) return } @@ -223,7 +231,7 @@ export class MiaoConsole extends interfaces.Plugin { startSocketIOServer() { let namespace = this.socketIOServer.of('/MiaoConsole') process.on('message', (msg) => namespace.emit('log', msg)) - namespace.on('connect', (client: SocketIOSocket) => { + namespace.on('connection', (client: SocketIOSocket) => { if (!this.token) { this.logger.console(`§6客户端 §b${client.id} §a请求连接 §4服务器尚未设置 Token 无法连接!`) client.emit('unauthorized', () => client.disconnect(true)) @@ -247,14 +255,23 @@ export class MiaoConsole extends interfaces.Plugin { client.emit('log', `Currect Server Version is ${this.server.getVersion()}`) }) client.on('command', (cmd) => { - setTimeout(() => this.server.dispatchConsoleCommand(cmd), 0) + this.task.callSyncMethod(() => this.server.dispatchConsoleCommand(cmd)) client.emit('log', `§6命令: §b${cmd} §a执行成功!`) }) client.on('tabComplate', (input, index, callback) => { - callback?.(this.command.tabComplete(this.server.getConsoleSender(), input, index) || []) + try { + callback?.(this.command.tabComplete(this.server.getConsoleSender(), input, index) || []) + } catch (error) { + callback?.([]) + client.emit('log', `§4命令补全发生异常: ${error}!`) + console.ex(error) + } }) client.on('exec', (code) => { try { + if (!this.babel) { + return client.emit('log', '§cBabel 引擎初始化中 请稍候再试!') + } client.emit('log', this.runCode(code, client.nsp, client)) } catch (ex) { client.emit('log', `§4代码执行异常 错误: ${ex}\n${console.stack(ex).join('\n')}`) @@ -307,15 +324,30 @@ export class MiaoConsole extends interfaces.Plugin { this.container, this.pluginManager ] - let tfunc = new Function( - ...paramNames, - `var api = require('@ccms/api'); + client.emit('log', '§3代码编译中 请稍候...') + let startTime = Date.now() + let tfunc = new Function(...paramNames, this.compileCode(code)) + client.emit('log', `§3代码编译完成 耗时 §e${Date.now() - startTime}ms §b开始执行 请稍候...`) + return tfunc.apply(this, params) + '' + } + + private compileCode(code: string) { + return `var api = require('@ccms/api'); if (this.serverType == "spring") { var dbm = container.get(api.database.DataBaseManager) var db = dbm.getMainDatabase() var bf = base.getInstance().getAutowireCapableBeanFactory() } -return '§a返回结果: §r'+ eval(${JSON.stringify(code)});`) - return this.task.callSyncMethod(() => tfunc.apply(this, params)) + '' +var startTime = Date.now() +var result = eval(${JSON.stringify(this.babel.transform(code, { + filename: 'miaoconsole-temp.ts', + presets: ['typescript', 'es2015'], + plugins: [ + ['proposal-decorators', { legacy: true }], + 'transform-runtime' + ], + sourceMaps: "inline" + }).code)}); +return '§3代码执行完成 耗时 §e' + (Date.now() - startTime) + 'ms §a返回结果: §r'+ result` } } diff --git a/packages/plugins/src/MiaoExplorer.ts b/packages/plugins/src/MiaoExplorer.ts index cad09116..77d1ab4b 100644 --- a/packages/plugins/src/MiaoExplorer.ts +++ b/packages/plugins/src/MiaoExplorer.ts @@ -46,7 +46,7 @@ export class MiaoExplorer extends interfaces.Plugin { let consolePlugin: any = this.pluginManager.getPlugin('MiaoConsole') this.token = consolePlugin.token this.namespace = server.of('/MiaoExplorer') - this.namespace.on('connect', (client: SocketIOSocket) => { + this.namespace.on('connection', (client: SocketIOSocket) => { if (!this.token) { this.logger.console(`§6客户端 §b${client.id} §a请求连接 §4服务器尚未设置 Token 无法连接!`) client.emit('unauthorized', () => client.disconnect(true)) diff --git a/packages/plugins/src/MiaoParticle.ts b/packages/plugins/src/MiaoParticle.ts new file mode 100644 index 00000000..938372b2 --- /dev/null +++ b/packages/plugins/src/MiaoParticle.ts @@ -0,0 +1,36 @@ +/// +/// +/// + +import { particle } from '@ccms/api' +import { Autowired } from '@ccms/container' +import { Cmd, JSPlugin, Tab, interfaces } from '@ccms/plugin' + +@JSPlugin({ version: '1.0.0', author: 'MiaoWoo', source: __filename }) +export class MiaoParticle extends interfaces.Plugin { + @Autowired() + private particleManager: particle.ParticleManager + + private particleTask: particle.ParticleTask + + enable() { + // let boot = new Bootstrap() + this.particleTask = this.particleManager.create(new particle.Circle(2, 20).setParticle(org.bukkit.Particle.BLOCK_DUST), this) + } + + diable() { + this.particleTask.cancel() + } + + @Cmd({ autoMain: true }) + mpt() { } + + cmdtest(sender: org.bukkit.entity.Player) { + this.particleTask.follow(sender).async(true).timer(5).submit() + } + + @Tab() + tabmpt(_sender: any, _command: string, _args: string[]) { + return [] + } +} diff --git a/packages/plugins/src/MiaoPay.ts b/packages/plugins/src/MiaoPay.ts new file mode 100644 index 00000000..055a0792 --- /dev/null +++ b/packages/plugins/src/MiaoPay.ts @@ -0,0 +1,295 @@ +/// +/// +/// + +import { plugin, server, task } from '@ccms/api' +import { Autowired, JSClass } from '@ccms/container' +import { Cmd, Config, interfaces, JSPlugin, PluginConfig, Tab } from '@ccms/plugin' + +import type { MiaoReward } from './MiaoReward' +import http from '@ccms/common/dist/http' +import * as CryptoJS from "crypto-js" + +interface PlayerPointsAPI { + look(name: string) + give(name: string, amount: number) + take(name: string, amount: number) +} + +interface Order { + order_id: string + amount: string + url: string +} +interface Sync { + scaned: boolean + start?: number + left?: number + cancelled?: boolean +} + +interface PlaceholderAPI { + registerPlaceholderHook: (key: string, onPlaceholderRequest: (player, s) => string) => void + unregisterPlaceholderHook: (key: string) => void + setPlaceholders: (player: any, str: string) => string +} + +const defaultConfig = { + prefix: '§6[§b喵式支付§6]', + id: '', + secret: '', + command: 'p give %player_name% %amount%', + check: '%playerpoints_points%', + ratio: 100, + coinName: '点券' +} + +@JSPlugin({ version: '1.2.0', author: 'MiaoWoo', source: __filename, depends: ['MiaoReward'], nativeDepends: ['PlaceholderAPI'] }) +export class MiaoPay extends interfaces.Plugin { + @Autowired() + private server: server.Server + @Autowired() + private taskManager: task.TaskManager + @Autowired() + private pluginManager: plugin.PluginManager + + @JSClass('me.clip.placeholderapi.PlaceholderAPI') + private PlaceholderAPI: PlaceholderAPI + + private MiaoReward: MiaoReward + + private cacheMap = new Map(); + private cacheSyncMap = new Map(); + + @Config() + private config: PluginConfig & typeof defaultConfig = defaultConfig + + load() { + let needSave = false + for (const key of Object.keys(defaultConfig)) { + if (!this.config[key]) { + this.config[key] = defaultConfig[key] + needSave = true + } + } + needSave && this.config.save() + } + + cmdtest(sender: org.bukkit.entity.Player) { + try { + this.logger.sender(sender, this.getPlayerAmount(sender)) + } catch (error) { + return this.logger.sender(sender, error.message) + } + } + + enable() { + this.MiaoReward = this.pluginManager.getPlugin('MiaoReward') as MiaoReward + if (!this.MiaoReward) { return this.logger.error('当前脚本插件需要 MiaoReward 作为前置脚本插件!') } + if (!this.config.id || !this.config.secret) { return this.logger.console('§4尚未配置商户信息 将无法正常收款!') } + } + + disable() { + this.cacheMap.forEach((v, k) => { + this.MiaoReward.cancelTask(this.server.getPlayer(k)) + }) + this.cacheMap.clear() + } + + @Cmd({ autoMain: true }) + mpay() { } + + cmdpay(sender: org.bukkit.entity.Player, amount: number) { + if (!sender.getItemInHand) { return this.logger.sender(sender, '§4控制台无法执行此命令!') } + if (!this.MiaoReward.serverInfo) { return this.logger.sender(sender, '§4当前服务器尚未配置 请联系管理员先配置MiaoReward!') } + if (!this.config.id || !this.config.secret) { return this.logger.sender(sender, '§c当前服务器尚未配置 请联系管理员配置支付密钥!') } + if (this.cacheMap.has(sender.getName())) { + this.logger.sender(sender, '§c您有一笔订单尚未完成 请完成支付或等待订单超时!') + let sync = this.cacheSyncMap.get(sender.getName()) + if (!sync.cancelled) { return } + sync.left = 55 - (Math.round(Date.now() / 1000) - sync.start) + let order = this.cacheMap.get(sender.getName()) + this.MiaoReward.setItemAndTp(sender, order.url, sync, `充值 ${order.amount} ${this.config.coinName}`, `支付宝/微信/QQ 扫码支付`) + return + } + if (amount < 1) { return this.logger.sender(sender, `§c充值异常 §4充值金额不得小于 1 ${this.config.coinName}!`) } + try { + this.getPlayerAmount(sender) + } catch (error) { + return this.logger.sender(sender, error.message) + } + this.MiaoReward.sendTitle(sender, `§6充值 §a${amount} §6${this.config.coinName}`, '§c正在请求充值二维码 请稍候...') + let sync = { scaned: false, start: Math.round(Date.now() / 1000) } + let order = this.createOrder(sender, amount) + this.cacheMap.set(sender.getName(), order) + this.cacheSyncMap.set(sender.getName(), sync) + let order_id = order.order_id + this.MiaoReward.setItemAndTp(sender, order.url, sync, `充值 ${amount} ${this.config.coinName}`, `支付宝/微信/QQ 扫码支付`) + this.taskManager.create(() => { + try { + let status = this.queryStatus(order_id, 0, 55) + if (status.code != 200) { throw new Error('§c扫码超时 请重新充值!') } + this.MiaoReward.sendTitle(sender, '§a已扫码', `§3订单已创建 请及时支付!`) + this.MiaoReward.sendActionBar(sender, '§6订单号: §3' + order_id) + sync.scaned = true + status = this.queryStatus(order_id, 1, 120) + if (status.code != 200) { throw new Error('§c支付超时 请重新充值!') } + if (status.data == 2) { + this.MiaoReward.sendTitle(sender, '§a已支付', `§3订单已支付 请等待充值到账...`) + this.MiaoReward.sendActionBar(sender, '§6订单号: §3' + order_id) + this.logger.sender(sender, `§6订单号: §3${order_id} §a支付成功!`) + this.recharge(sender, order_id, order.amount) + } else { + this.logger.sender(sender, `§c充值系统异常 §4订单状态异常${status.data} §c点券可能未到账 请联系管理员!`) + } + } catch (error) { + let cacheOrder = this.cacheMap.get(sender.getName()) + if (cacheOrder && cacheOrder.order_id == order_id) { + this.MiaoReward.sendTitle(sender, '§4充值失败', error.message) + } + } finally { + sync.scaned = true + this.cacheMap.delete(sender.getName()) + this.cacheSyncMap.delete(sender.getName()) + } + }).async().submit() + this.MiaoReward.clearTitle(sender) + } + + cmdquery(sender: org.bukkit.entity.Player, id: string) { + if (!id) { return this.logger.sender(sender, '§c请输入订单号!') } + this.taskManager.create(() => { + let result = this.queryOrder(id, sender.getName(), sender.getUniqueId().toString()) + if (result.code != 200) { return this.logger.sender(sender, `§c查询异常! §4ERROR: ${result.msg}`) } + let order = result.data + this.logger.sender(sender, [ + `§6商户名称: §3${order.appname}`, + `§6订单号: §3${id}`, + `§6商品: §b${order.subject}`, + `§6金额: §e${order.amount}`, + `§6玩家: §a${order.username}`, + `§6状态: §c${order.status}`, + ]) + if (order.status > 1 && order.status < 4) { + this.logger.sender(sender, `§3当前订单已支付 尚未完成充值 开始补单操作...`) + this.recharge(sender, id, order.amount) + } + }).async().submit() + } + + /** + * @param amount 订单金额(非点券金额) + */ + recharge(sender: org.bukkit.entity.Player, order_id: string, amount: number) { + let point = amount * this.config.ratio + this.taskManager.create(() => { + let finish = this.preFinishOrder(order_id) + if (finish.code != 200) { + return this.logger.console(`§c充值系统异常 订单 §3${order_id} 预标记异常! §4${this.config.coinName}已停止充值 §c请手动补单!`) + } + this.taskManager.callSyncMethod(() => { + let prePoint = this.getPlayerAmount(sender) + let command = this.config.command.replace('%player_name%', sender.getName()).replace('%amount%', `${point}`).replace('%remark%', `${order_id}`) + if (!this.server.dispatchConsoleCommand(command)) { + return this.sendError(sender, order_id, amount, '§4充值命令执行异常!') + } + let nowPoint = this.getPlayerAmount(sender) + if (nowPoint != prePoint + point) { + return this.sendError(sender, order_id, amount, '§4充值结果检测异常!') + } else { + this.taskManager.create(() => { + this.logger.sender(sender, [ + `§6充值 §a${point} §6${this.config.coinName} §a成功 §6当前账户余额: §3${nowPoint} §6${this.config.coinName}`, + `§c如出现未到账的情况 请联系管理员!` + ]) + let finish = this.finishOrder(order_id) + if (finish.code != 200) { + return this.logger.console(`§c充值系统异常 订单 §3${order_id} 完成标记异常! §4${this.config.coinName}可能重复到账!`) + } + }).async().submit() + } + }) + }).async().submit() + } + + sendError(sender: org.bukkit.entity.Player, order_id: string, amount: number, error: string) { + return this.logger.sender(sender, [ + `§c========== ${this.config.prefix}§4充值异常 §c==========`, + `§6异常订单: §3${order_id}`, + `§6订单金额: §3${amount}`, + `§6异常原因: §4${error}`, + `§6异常账号: §b${sender.getName()}`, + `§6异常时间: §a${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`, + `§c如果已付款但${this.config.coinName}未到账 请截图发往QQ群!`, + `§c========== ${this.config.prefix}§4充值异常 §c==========`, + ]) + } + + @Tab() + tabmpay() { } + + private getPlayerAmount(sender: any): number { + let result = this.PlaceholderAPI.setPlaceholders(sender, this.config.check) + let amount = parseFloat(result) + if (isNaN(amount)) { + throw new Error(`§c读取玩家 §3${this.config.coinName} §c异常 §6请检查 §3check §6配置是否正确!\n§6数据解析链路: §3${this.config.check} §6=> §3${result} §6=> §3${amount}`) + } + return amount + } + + private queryStatus(id: string, wait: number, time = 60) { + return this.httpPost('/status', { id, wait, time }) + } + + private preFinishOrder(id: string) { + return this.httpPost('/preFinish', { id }) + } + + private finishOrder(id: string) { + return this.httpPost('/finish', { id }) + } + + private createOrder(sender: org.bukkit.entity.Player, amount: number) { + let result = this.httpPost('/create', { + subject: `${this.MiaoReward.serverInfo.name} 充值 ${amount} ${this.config.coinName}`, + totalAmount: amount / this.config.ratio, + username: sender.getName(), + union_id: sender.getUniqueId().toString() + }) + if (result.code != 200) { + throw new Error(`订单创建失败: ${result.msg}`) + } + return result.data + } + + private queryOrder(id: string, username: string, uuid: string) { + return this.httpPost('/query', { id, username, uuid }) + } + + private httpPost(method: string, data: any) { + let startTime = Date.now() + data.appid = this.config.id + data.timestamp = Math.round(Date.now() / 1000) + data.sign = this.sign(data) + let url = `https://pay.yumc.pw/api${method}` + let result = http.post(url, data) + console.debug(` +====== HTTP POST ====== +REQUEST URL : ${url} +REQUEST DATA: ${JSON.stringify(data)} +RESPONSE : ${JSON.stringify(result)} +CAST TIME : ${Date.now() - startTime}`) + return result + } + + private http_build_query(params: any) { + return Object.keys(params).filter(key => key !== 'sign' && params[key] != undefined && params[key] != null) + .sort().map(key => key + '=' + params[key]).join('&') + } + + private sign(params) { + // 排序后转换为字符串 + let signStr = `${this.http_build_query(params)}&key=${this.config.secret}` + return CryptoJS.MD5(signStr).toString().toUpperCase() + } +} diff --git a/packages/plugins/src/MiaoReward.ts b/packages/plugins/src/MiaoReward.ts index 8076cec2..32746a56 100644 --- a/packages/plugins/src/MiaoReward.ts +++ b/packages/plugins/src/MiaoReward.ts @@ -21,6 +21,26 @@ interface UserInfo { sign: string video: string box: string + block: string +} + +interface ServerInfo { + // 16, + id: number + // "圈云大陆", + name: string + // 1, + owner: number + // 48200, + score: number + // 1, + ratio: number + // 1, + audit: number + // 2, + status: number + // 0 + today: number } let createPacketAdapterFunction = eval(` @@ -30,9 +50,18 @@ function(cls, plugin, type, onPacketSending){ } }`) -@JSPlugin({ prefix: 'MRD', version: '1.4.2', author: 'MiaoWoo', servers: [constants.ServerType.Bukkit], source: __filename }) +const defaultConfig = { + prefix: '§6[§b广告系统§6]§r', + serverId: '', + serverToken: '', + drawCommand: 'p give %player_name% %amount%', + coinName: '点券', + joinTip: true +} + +@JSPlugin({ prefix: 'MRD', version: '1.5.1', author: 'MiaoWoo', servers: [constants.ServerType.Bukkit], nativeDepends: ['ProtocolLib', 'PlaceholderAPI'], source: __filename }) export class MiaoReward extends interfaces.Plugin { - private serverInfo: any + public serverInfo: ServerInfo private cacheBindUuid = '' private zeroMapView = undefined private playerImageCache = new Map() @@ -53,19 +82,7 @@ export class MiaoReward extends interfaces.Plugin { private bungee: proxy.BungeeCord @Config() - private config: PluginConfig & { - prefix: string - serverId: string - serverToken: string - drawCommand: string - coinName: string - } = { - prefix: '§6[§b广告系统§6]§r', - serverId: '', - serverToken: '', - drawCommand: 'p give %player_name% %amount%', - coinName: '点券' - } + private config: PluginConfig & typeof defaultConfig = defaultConfig @JSClass('org.bukkit.Bukkit') private Bukkit: any @@ -95,6 +112,10 @@ export class MiaoReward extends interfaces.Plugin { this.config.coinName = '点券' this.config.save() } + if (!this.config.joinTip) { + this.config.joinTip = true + this.config.save() + } //@ts-ignore this.logger.prefix = this.config.prefix this.downgrade = this.Bukkit.server.class.name.split('.')[3] == "v1_7_R4" @@ -172,13 +193,15 @@ export class MiaoReward extends interfaces.Plugin { } else { this.PlaceholderAPI.registerPlaceholderHook("mrd", new this.PlaceholderHook({ onPlaceholderRequest: (player: any, s: string) => { - if (!this.playerInfoCache.has(player.getName())) { return '用户未绑定' } + if (!this.playerInfoCache.has(player.getName())) { return '数据加载中' } let data = this.playerInfoCache.get(player.getName()) + if (!data) { return '用户未绑定' } switch (s.toLowerCase()) { case "balance": return data.balance case "sign": return data.sign case "video": return data.video case "box": return data.box + case "block": return data.block default: return "未知的参数: " + s } } @@ -197,11 +220,14 @@ export class MiaoReward extends interfaces.Plugin { this.initPacketAdapter() } - createPacketAdapter(onPacketSending: (event) => void) { + private createPacketAdapter(onPacketSending: (event) => void) { return createPacketAdapterFunction(this.PacketAdapter, base.getInstance(), [this.PacketType.Play.Server.MAP], onPacketSending) } - initPacketAdapter() { + private initPacketAdapter() { + if (!this.ProtocolLibrary) { + return this.logger.console(`§4服务器未安装 ProtocolLib 无法扫码功能 请安装后重试!`) + } this.adapter = this.createPacketAdapter((event) => { let integers = event.getPacket().getIntegers().getValues() let mapId = integers.get(0) @@ -247,6 +273,7 @@ export class MiaoReward extends interfaces.Plugin { } disable() { + if (!this.ProtocolLibrary) return this.PlaceholderAPI?.unregisterPlaceholderHook("mrd") this.adapter && this.ProtocolLibrary.getProtocolManager().removePacketListener(this.adapter) Java.from(this.server.getOnlinePlayers()).forEach(p => this.checkAndClear(p)) @@ -254,7 +281,7 @@ export class MiaoReward extends interfaces.Plugin { } @Cmd() - mrd(sender: any, command: string, args: string[]) { + private mrd(sender: any, command: string, args: string[]) { let cmd = args[0] || 'help' let cmdKey = 'cmd' + cmd if (!this[cmdKey]) { @@ -266,7 +293,7 @@ export class MiaoReward extends interfaces.Plugin { this.taskManager.create(() => this[cmdKey](sender, ...args)).async().submit() } - private scanAuth(sender: org.bukkit.entity.Player, scanType: string, scanObj: { title: string, content: string }, success: (token: string, user: any) => void, cancel?: () => void) { + public scanAuth(sender: org.bukkit.entity.Player, scanType: string, scanObj: { title: string, content: string }, success: (token: string, user: any) => void, cancel?: () => void) { this.logger.sender(sender, '§a正在获取授权二维码...') let scan = this.httpPost('https://reward.yumc.pw/auth/scan', { ...scanObj, type: scanType }) if (scan.code == 200) { @@ -313,6 +340,9 @@ export class MiaoReward extends interfaces.Plugin { } private bindCheck(sender: org.bukkit.entity.Player) { + if (!this.ProtocolLibrary) { + return this.logger.sender(sender, `§4服务器未安装 ProtocolLib 无法扫码功能 请安装后重试!`) + } let scanning = this.playerTaskCache.has(sender.getName()) if (scanning) { this.logger.sender(sender, "§4当前正在进行扫码 请稍候重试!") @@ -320,7 +350,7 @@ export class MiaoReward extends interfaces.Plugin { return scanning } - cmdopen(sender: org.bukkit.entity.Player) { + private cmdopen(sender: org.bukkit.entity.Player) { if (this.bindCheck(sender)) return this.logger.sender(sender, '§a正在获取小程序二维码...') let sync = { scaned: false } @@ -328,7 +358,7 @@ export class MiaoReward extends interfaces.Plugin { this.taskManager.create(() => sync.scaned = true).later(20 * 50).submit() } - cmdbind(sender: org.bukkit.entity.Player, server: boolean) { + private cmdbind(sender: org.bukkit.entity.Player, server: boolean) { if (!sender.getItemInHand) { return this.logger.sender(sender, '§c手持物品检测异常 请检查是否在客户端执行命令!') } if (this.bindCheck(sender)) return if (server) { @@ -338,9 +368,9 @@ export class MiaoReward extends interfaces.Plugin { } } - cmddraw(sender: org.bukkit.entity.Player, amount: number) { + private cmddraw(sender: org.bukkit.entity.Player, amount: number) { if (!sender.getItemInHand) { return this.logger.sender(sender, '§c手持物品检测异常 请检查是否在客户端执行命令!') } - if (!this.playerInfoCache.has(sender.getName())) { return this.logger.sender(sender, '§c当前用户尚未绑定服务器玩家账号 请先执行 /mrd bind 绑定账号!') } + if (!this.playerInfoCache.get(sender.getName())) { return this.logger.sender(sender, '§c当前用户尚未绑定服务器玩家账号 请先执行 /mrd bind 绑定账号!') } amount = Number(amount) if (!Number.isInteger(amount)) { return this.logger.sender(sender, '§4金额必须是数字!') @@ -356,7 +386,7 @@ export class MiaoReward extends interfaces.Plugin { "是否授权 " + this.serverInfo.name + " 兑换喵币", "兑换玩家: " + sender.getName(), "兑换数量: " + amount, - "兑换比例: " + parseFloat(this.serverInfo.ratio), + "兑换比例: " + this.serverInfo.ratio, "预计到帐: " + (amount * this.serverInfo.ratio).toFixed(0), "注意: 数据可能更新不及时 请以实际到账金额为准!" ].join('\n') @@ -404,7 +434,7 @@ export class MiaoReward extends interfaces.Plugin { ]) } - cmdrank(sender: any, boardcast: boolean) { + private cmdrank(sender: any, boardcast: boolean) { if (!sender.isOp()) { return this.logger.sender(sender, '§4你没有此命令的权限!') } let result = this.httpPost(`https://reward.yumc.pw/server/rank`, { id: this.config.serverId, @@ -425,7 +455,7 @@ export class MiaoReward extends interfaces.Plugin { } } - cmdserver(sender: any) { + private cmdserver(sender: any) { if (!sender.isOp()) { return this.logger.sender(sender, '§4你没有此命令的权限!') } let result = this.httpPost(`https://reward.yumc.pw/server/server`, { id: this.config.serverId, @@ -445,7 +475,7 @@ export class MiaoReward extends interfaces.Plugin { ]) } - cmdratio(sender: any, ratioStr: string, confirm: string) { + private cmdratio(sender: any, ratioStr: string, confirm: string) { if (!sender.isOp()) { return this.logger.sender(sender, '§4你没有此命令的权限!') } if (!sender.getItemInHand) { return this.logger.sender(sender, '§c手持物品检测异常 请检查是否在客户端执行命令!') } let [ratio, mbr, msg] = this.ratio2string(ratioStr) @@ -484,7 +514,7 @@ export class MiaoReward extends interfaces.Plugin { }) } - cmdreload() { + private cmdreload() { this.config.reload() } @@ -556,35 +586,41 @@ export class MiaoReward extends interfaces.Plugin { this.setItemAndTp(sender, bindUrl, sync) } - private sendActionBar(sender, message) { + public sendActionBar(sender, message) { if (!this.downgrade) { this.chat.sendActionBar(sender, message) } } - private sendTitle(sender, title, subtitle?) { + public sendTitle(sender: any, title: string, subtitle: string = '', fadeIn: number = 20, time: number = 100, fadeOut: number = 20) { if (!title) return if (this.downgrade) { this.logger.sender(sender, `${title}${subtitle ? ` ${subtitle}` : ''}`) } else { - this.chat.sendTitle(sender, title, subtitle) + this.chat.sendTitle(sender, title, subtitle, fadeIn, time, fadeOut) } } - private setItemAndTp(sender: org.bukkit.entity.Player, content: string, sync: { scaned: boolean }) { + public clearTitle(sender) { + this.chat.clearTitle(sender) + } + + public setItemAndTp(sender: org.bukkit.entity.Player, content: string, sync: { scaned: boolean, left?: number, cancelled?: boolean }, name: string = '手机QQ扫描二维码', tip: string = '手机QQ扫描二维码') { this.taskManager.create(() => { - let bindingLeftTime = 55 + if (!sync.left) { sync.left = 55 } + sync.cancelled = false let task = this.taskManager.create(() => { try { - if (sync.scaned || !sender.isOnline() || !this.isHoldQrCodeItem(sender) || --bindingLeftTime < 0) { - if (bindingLeftTime < 0) { + if (sync.scaned || !sender.isOnline() || !this.isHoldQrCodeItem(sender) || --sync.left < 0) { + if (sync.left < 0) { this.logger.sender(sender, '§c二维码已过期 请重新获取 如已扫码请忽略!') task.cancel() } this.cancelTask(sender) + sync.cancelled = true return } - this.sendActionBar(sender, `§c§l手机QQ扫描二维码 剩余 ${bindingLeftTime} 秒...`) + this.sendActionBar(sender, `§c§l${tip} 剩余 ${sync.left} 秒...`) } catch (error) { console.ex(error) } @@ -610,7 +646,7 @@ export class MiaoReward extends interfaces.Plugin { temp.setPitch(90) sender.teleport(temp) } - this.sendWindowItems(sender, this.createQrCodeMapItem()) + this.sendWindowItems(sender, this.createQrCodeMapItem(name)) sender.sendMap(this.zeroMapView) }).submit() } @@ -624,13 +660,11 @@ export class MiaoReward extends interfaces.Plugin { username: sender.getName(), sync }) - if (result?.code == 200) { - this.playerInfoCache.set(sender.getName(), result.data) - } + this.playerInfoCache.set(sender.getName(), result?.code == 200 ? result.data : null) return result } - cmdquery(sender: org.bukkit.entity.Player) { + private cmdquery(sender: org.bukkit.entity.Player) { let info = this.queryUser(sender) if (info.code !== 200) { return this.logger.sender(sender, '§4查询异常! §cError: ' + info.msg) @@ -648,11 +682,12 @@ export class MiaoReward extends interfaces.Plugin { `§6签 到: §b${data.sign}`, `§6视频广告: §b${data.video}`, `§6盒子广告: §b${data.box}`, + `§6积木广告: §b${data.block}`, '§6===========================' ]) } - private httpPost(url, data) { + public httpPost(url, data) { let startTime = Date.now() let result = http.post(url, data) console.debug(` @@ -664,7 +699,7 @@ CAST TIME : ${Date.now() - startTime}`) return result } - private createQrCodeMapItem() { + private createQrCodeMapItem(name: string = '手机QQ扫描二维码') { let item: org.bukkit.inventory.ItemStack item = new org.bukkit.inventory.ItemStack(org.bukkit.Material.FILLED_MAP || org.bukkit.Material.MAP) let meta = item.getItemMeta() @@ -675,7 +710,7 @@ CAST TIME : ${Date.now() - startTime}`) } else { item.setDurability(this.zeroMapView.getId()) } - meta.setDisplayName('§c请使用手机QQ扫描二维码!') + meta.setDisplayName(`§c${name}`) meta.setLore(["QRCODE"]) item.setItemMeta(meta) return item @@ -714,31 +749,33 @@ CAST TIME : ${Date.now() - startTime}`) } @Listener() - PlayerJoinEvent(event: org.bukkit.event.player.PlayerJoinEvent) { + private PlayerJoinEvent(event: org.bukkit.event.player.PlayerJoinEvent) { const player = event.getPlayer() this.bungeeCordDetect(player) this.updatePlayerInfo(player) - this.taskManager.create(() => this.logger.sender(player, `§a本服已使用喵式奖励 §3可以看广告赚${this.config.coinName} §c/mrd help §b查看帮助!`)).later(50).submit() + if (this.config.joinTip) { + this.taskManager.create(() => this.logger.sender(player, `§a本服已使用喵式奖励 §3可以看广告赚${this.config.coinName} §c/mrd help §b查看帮助!`)).later(50).submit() + } } @Listener() - PlayerDropItemEvent(event: org.bukkit.event.player.PlayerDropItemEvent) { + private PlayerDropItemEvent(event: org.bukkit.event.player.PlayerDropItemEvent) { if (this.checkAndClear(event.getPlayer())) { event.setCancelled(true) } } @Listener() - PlayerItemHeldEvent(event: org.bukkit.event.player.PlayerItemHeldEvent) { + private PlayerItemHeldEvent(event: org.bukkit.event.player.PlayerItemHeldEvent) { this.checkAndClear(event.getPlayer()) } @Listener() - PlayerQuitEvent(event: org.bukkit.event.player.PlayerQuitEvent) { + private PlayerQuitEvent(event: org.bukkit.event.player.PlayerQuitEvent) { this.checkAndClear(event.getPlayer()) } - private cancelTask(player) { + public cancelTask(player) { if (!this.playerTaskCache.has(player.getName())) { return } this.checkAndClear(player) this.sendActionBar(player, "") @@ -760,7 +797,7 @@ CAST TIME : ${Date.now() - startTime}`) return false } - cmdhelp(sender: any) { + private cmdhelp(sender: any) { let help = [ `§6====== ${this.config.prefix} §a帮助菜单 §6======`, `§6/mrd bind §a绑定圈云盒子`, @@ -785,7 +822,7 @@ CAST TIME : ${Date.now() - startTime}`) } @Tab() - tabmrd(sender: any, _command: any, args: string | any[]) { + private tabmrd(sender: any, _command: any, args: string | any[]) { if (args.length === 1) return ['help', 'bind', 'show', 'statistic', 'query', 'draw', 'ratio', 'rank', 'server'] if (args.length === 2 && args[0] === "bind" && sender.isOp()) return ['server'] } diff --git a/packages/plugins/src/MiaoRobot.ts b/packages/plugins/src/MiaoRobot.ts new file mode 100644 index 00000000..3c4bd5ca --- /dev/null +++ b/packages/plugins/src/MiaoRobot.ts @@ -0,0 +1,102 @@ +/// +/// +/// +/// +// @ts-ignore +require.clear('websocket/client') +import { server } from '@ccms/api' +import { Autowired, Container, ContainerInstance } from '@ccms/container' +import { Cmd, JSPlugin, Tab, interfaces, PluginConfig, Config } from '@ccms/plugin' +import { WebSocket } from '@ccms/websocket' + +const defaultConfig = { + address: '', + token: '' +} +//https://github3.mk-proxy.ml/-----https://github.com/Mrs4s/go-cqhttp/releases/download/v0.9.34/go-cqhttp-v0.9.34-linux-amd64 +@JSPlugin({ version: '1.0.0', author: 'MiaoWoo', source: __filename }) +export class MiaoRobot extends interfaces.Plugin { + @Autowired() + private server: server.Server + + private client: WebSocket + + @Config() + private config: PluginConfig & typeof defaultConfig = defaultConfig + + load() { + } + + private downloadRobot() { + //https://api.github.com/repos/Mrs4s/go-cqhttp/releases?per_page=1&page=1 + } + + enable() { + if (!this.config.address || !this.config.token) { + return this.logger + } + this.cmdconnect(this.server.getConsoleSender(), this.config.address, this.config.token) + } + + disable() { + this.cmdclose(this.server.getConsoleSender()) + } + + @Cmd({ autoMain: true }) + mbot() { } + + cmdconnect(sender: org.bukkit.entity.Player, address: string = this.config.address, token: string = this.config.token) { + if (this.client && this.client.readyState == WebSocket.OPEN) { + this.client.close() + this.client = undefined + } + if (!address || !token) { + return this.logger.sender(sender, '§4错误 请配置服务器地址和Token!') + } + try { + this.client = new WebSocket(address, '', { Authorization: `Bearer ${token}` }) + this.initRobot(this.client) + } catch (error) { + console.ex(error) + } + } + + private initRobot(client: WebSocket) { + client.onopen = () => { + this.logger.console(`§3连接到 §b${client.url} §a成功!`) + } + client.onmessage = (event) => { + let messageEvent = JSON.parse(event.data) + switch (messageEvent.post_type) { + case "message": + this.logger.console(`§6接收到 §3群 §b${messageEvent.group_id} §2成员 §a${messageEvent.sender.nickname} §6的消息: §r${messageEvent.message}`) + break + } + } + client.onclose = (event) => { + this.logger.console(`§4连接已断开 §6Code: §3${event.code} §6原因: §c${event.reason}!`) + } + client.onerror = (event) => { + this.logger.console(`§4发生错误: §r${event.error}`) + console.ex(event.error) + } + } + + cmdclose(sender: org.bukkit.entity.Player) { + if (this.client) { + this.client.close(0, 'plugin close socket') + } + } + + cmdsend(sender: org.bukkit.entity.Player, text: string) { + if (this.client) { + this.client.send(text) + this.logger.sender(sender, '§a发送成功!') + } + } + + @Tab() + tabmbot(_sender: any, _command: string, _args: string[]) { + return [] + } +} diff --git a/packages/plugins/src/MiaoScriptPackageManager.ts b/packages/plugins/src/MiaoScriptPackageManager.ts index 2005734f..fe542c07 100644 --- a/packages/plugins/src/MiaoScriptPackageManager.ts +++ b/packages/plugins/src/MiaoScriptPackageManager.ts @@ -15,8 +15,9 @@ let help = [ '§6/mspm §areload §e<插件名称> §6- §3重载已安装插件(无名称则重载自身)', '§6/mspm §alist [i] §6- §3列出仓库插件[已安装的插件]', '§6/mspm §aupdate §e[插件名称] §6- §3更新插件(无名称则更新源)', - '§6/mspm §aupgrade §e[插件名称] §6- §3升级插件/框架(§4无名称则升级框架§3)', - '§6/mspm §arun §e §6- §3运行JS代码', + '§6/mspm §aupgrade §e[插件名称|system] §6- §3升级插件/§4框架(§csystem§3)', + '§6/mspm §arun §e[插件名称] §3 §6- §3运行JS代码', + '§6/mspm §aprun §e §6- §3运行JS代码', '§6/mspm §adeploy §e<插件名称> §6- §3发布插件', '§6/mspm §crestart §6- §4重启MiaoScript脚本引擎' ] @@ -132,6 +133,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { public serverName: string private translate: Translate private channelOff: { off: () => void } + private subCommandCache = [] load() { this.translate = new Translate({ @@ -139,6 +141,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { fallbackMap }) this.updateRepo(this.server.getConsoleSender()) + this.subCommandCache = Object.keys(this).filter(c => c.startsWith('cmd') && typeof this[c] == "function") } @enable({ servers: [constants.ServerType.Bukkit, constants.ServerType.Sponge] }) @@ -383,7 +386,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { } cmdrestart(sender: any) { - setTimeout(() => { + this.taskManager.callSyncMethod(() => { if (this.serverType === "sponge") { this.server.dispatchConsoleCommand('sponge plugins reload') return @@ -398,7 +401,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { this.logger.sender(sender, "§3MiaoScript Engine §6Reload §cError! ERR: " + ex) this.logger.sender(sender, this.logger.stack(ex)) } - }, 0) + }) } cmdrun(sender: any, ...args: any[]) { @@ -477,7 +480,7 @@ return eval(${JSON.stringify(code)});`) @Tab({ alias: ['gmspm', 'bungeemspm'] }) tabmspm(_sender: any, _command: any, args: string | any[]) { - if (args.length === 1) { return ['list', 'install', 'update', 'upgrade', 'reload', 'restart', 'run', 'prun', 'sudo', 'help', 'create', 'deploy'] } + if (args.length === 1) { return ['list', 'install', 'update', 'load', 'unload', 'upgrade', 'reload', 'restart', 'run', 'prun', 'sudo', 'help', 'create', 'deploy'] } if (args.length > 1) { switch (args[0]) { case "list":