// ==UserScript==
// @name wsmud_api
// @namespace com.wsmud
// @version 0.0.6
// @description 使用于 Tampermonkey 的武神传说脚本的前置 API 库
// @author sq
// @date 2020/08/24
// @modified 2020/08/26
// @match http://*.wsmud.com/*
// @exclude http://*.wsmud.com/news/*
// @exclude http://*.wsmud.com/pay.html
// @homepage https://gf.qytechs.cn/zh-CN/scripts/409901
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js
// @run-at document-start
// @grant unsafeWindow
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict'
if (!WebSocket) return
console.green = function(log) {
console.log(`%c${log}`, 'color:green')
}
console.orange = function(log) {
console.log(`%c${log}`, 'color:orange')
}
console.red = function(log) {
console.log(`%c${log}`, 'color:red')
}
unsafeWindow.console.green = console.green
unsafeWindow.console.orange = console.orange
unsafeWindow.console.red = console.red
unsafeWindow.setValue = function(key, value) {
localStorage.setItem(key, JSON.stringify(value))
}
unsafeWindow.getValue = function(key) {
return JSON.parse(localStorage.getItem(key))
}
unsafeWindow.deleteValue = function(key) {
localStorage.removeItem(key)
}
unsafeWindow.cookie = function() {
const cookies = document.cookie.split(';').reduce((accumulator, currentValue) => {
const i = currentValue.indexOf('=')
const name = currentValue.substr(0, i).trim()
const value = currentValue.substr(i + 1)
accumulator[name] = value
return accumulator
}, {})
const setCookie = (name, value) => document.cookie = name + '=' + value
const deleteCookie = name => document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'
return new Proxy(cookies, {
set: (target, name, value) => {
setCookie(name, value)
return Reflect.set(target, name, value)
},
deleteProperty: (target, name) => {
deleteCookie(name)
return Reflect.deleteProperty(target, name)
},
})
}
unsafeWindow.addStyle = css => GM_addStyle(css)
unsafeWindow.WebSocket = function (uri) {
unsafeWindow._websocket = new WebSocket(uri)
}
unsafeWindow.WebSocket.prototype = {
set onopen(fn) {
unsafeWindow._websocket.onopen = fn
},
set onclose(fn) {
unsafeWindow._websocket.onclose = fn
},
set onerror(fn) {
unsafeWindow._websocket.onerror = fn
},
set onmessage(fn) {
unsafeWindow._onmessage = fn
unsafeWindow._websocket.onmessage = onmessage
},
get readyState() {
return unsafeWindow._websocket.readyState
},
send: function (command) {
onsend(command)
},
}
unsafeWindow.monitors = {}
const monitors = unsafeWindow.monitors
class Api {
constructor() {
this.version = GM_info.script.version
this.roles = getValue('roles')
this.id = String()
this.name = String()
this.state = String()
}
set roles(value) {
if (value instanceof Array) {
value.sort((a, b) => a.sort - b.sort)
value.forEach((item, index) => {
if (item.server) item.sort = index + 1
else item.sort = 9999
})
this._roles = value
} else {
this._roles = []
}
setValue('roles', this._roles)
}
get roles() {
return this._roles
}
ondata(data) {
const type = data.type === 'dialog' ? data.dialog : data.type
if (monitors[type]) {
Object.keys(monitors[type]).forEach(name => {
const callback = monitors[type][name]
callback(data)
})
}
if (data.destroyed) return
const event = data2event(data)
unsafeWindow._onmessage(event)
}
send(command) {
unsafeWindow._websocket.send(command)
}
}
unsafeWindow.api = Vue.observable(new Api())
const api = unsafeWindow.api
unsafeWindow.addMonitor = function(type, name, callback) {
if (!type || !name || typeof callback !== 'function') return
if (!monitors[type]) monitors[type] = {}
monitors[type][name] = callback.bind(api)
console.green(`AddMonitor: type = ${type}; name = ${name};`)
}
unsafeWindow.removeMonitor = function(type, name) {
if (!type || !name) return
delete monitors[type][name]
console.red(`RemoveMonitor: type = ${type}; name = ${name};`)
api.roles = new Object(api.roles)
}
addMonitor('roles', 'RoleList', function(data) {
if (!(data.roles instanceof Array)) return
data.roles.forEach(item => {
const { id, name, title } = item
const index = api.roles.findIndex(role => role.id === id)
if (index === -1) {
api.roles.push({ id, name, title, sort: 9999 })
} else {
api.roles[index].name = name
api.roles[index].title = title
}
})
api.roles = api.roles.slice(0)
})
addMonitor('login', 'Login', function(data) {
const id = data.id
if (api.id || !id) return
api.id = id
const index = api.roles.findIndex(role => role.id === id)
api.name = api.roles[index].name
api.roles[index].u = cookie().u
api.roles[index].p = cookie().p
api.roles[index].s = cookie().s
api.roles[index].server = ['一区', '二区', '三区', '四区', '测试'][cookie().s]
api.roles = api.roles.slice(0)
})
addMonitor('', '', function(data) {})
function onsend(command) {
api.send(command)
}
function onmessage(event) {
const data = event2data(event)
api.ondata(data)
}
function event2data(event) {
const data = event.data
if (typeof data === 'string' && data[0] === '{') {
try {
return new Function('return ' + data)()
} catch (error) {
console.red(error)
console.red(data)
}
}
return { 'type': 'text', 'text': data }
}
function data2event(data) {
if (!data.type) return
if (data.type === 'text') return { data: data.text }
else return { data: JSON.stringify(data) }
}
unsafeWindow.Vue = Vue
document.addEventListener('DOMContentLoaded', function() {
}, false)
// To be continued...
})()