import lodash from 'lodash' import md5 from 'md5' let _connection = {} export class MysSign extends plugin { constructor () { super({ name: 'mysSign', dsc: 'mys签到', route: '/mysSign', rule: [ { method: 'get', path: '/:key', fnc: 'index' }, { method: 'get', path: '/:key/:uid', fnc: 'bbsSign' }, { method: 'post', path: '/:key/:uid', fnc: 'bbsSign' }, { method: 'ws', path: '/', fnc: 'connection' } ] }) } index () { let { key } = this.params let user = this.findUser(key) if (!user) { this.error('UID列表不存在或已失效') return } this.render('mysSign/main', { key, user, copyright: this.cfg.Copyright }) } async bbsSign () { let { connect, id, key, uid, validate } = this.params if (!validate && this.params['validate[geetest_validate]']) { validate = { geetest_challenge: this.params['validate[geetest_challenge]'], geetest_validate: this.params['validate[geetest_validate]'], geetest_seccode: this.params['validate[geetest_seccode]'], } } connect = _connection[connect] let user = connect[key] let uidData = user?.uids.find(v => v.uid == uid) if (!uidData) { this.send({ msg: '签到失败:链接已失效,请重新获取' }) return } let data = uidData.status if (!data) { data = await connect.self.socketSend('doSign', { id, validate, ...uidData }, md5(`${new Date().getTime()}${uid}`)) if (data.retcode == 0) { uidData.status = { ...data, msg: data.msg.replace('签到成功', '今天已签到') } logger.info(`[mysSign] 签到成功, UID: ${uid}`) } } this.send(data) } connection () { if (this.cfg.Key && this.request.query.key !== this.cfg.Key) return this.close() this._wait = this._wait || {} this._key = this.randomKey(10, _connection) this.onClose(() => delete _connection[this._key]) this.onMessage((data) => { try { data = JSON.parse(data) let { id, cmd, payload, key } = data this._wait[id] && this._wait[id](payload) || this[cmd] && this[cmd](payload, id) } catch (err) { logger.error(err) } }) } async createUser (data, id) { let connect = _connection[this._key] if (!connect.self) { connect.self = this } let key = this.hasUser(id) if (!key) { key = this.randomKey(6, connect, { connect: this._key, id, uids: data }) /** uid缓存10分钟 */ setTimeout(() => connect && delete connect[key], 600 * 1000) } let payload = { link: `${this.address}/${key}` } this.socketWrite('createUser', payload, id) } hasUser (id) { let ret = false lodash.forEach(_connection, (connect) => { lodash.forEach(connect, (user, key) => { if (user.id == id) { ret = key return false } }) }) return ret } findUser (key) { let ret = false let connect = this.findConnect(key) if (connect) ret = connect[key] return ret } findConnect (key) { let ret = false if (key) { lodash.forEach(_connection, (connect) => { if (connect[key]) { ret = connect return false } }) } return ret } socketWrite (cmd, payload, id) { if (!id || typeof id == 'number' && String(id).length == 13) id = new Date().getTime() return this.socket.send(JSON.stringify({ id, cmd, payload, key: this._key })) } socketSend (cmd, payload, id) { return new Promise((resolve, reject) => { this.socketWrite(cmd, payload, `${id}`) this._wait[id] = resolve setTimeout(() => resolve(false) && delete this._wait[id], 5 * 1000) }) } get cfg () { return Server.cfg.getConfig('GTest') } get address () { let { Host } = this.cfg let protocol = Server.cfg.http.HTTPS ? 'https' : 'http' let port = Server.cfg.http_listen[0] if (![80, 443,7860].includes(port)) Host += `:${port}` return `${protocol}://${Host}${this.route}` } randomKey (length, checkObj, data) { let letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' let key = lodash.sampleSize(letters, length).join('') while (checkObj[key]) { key = lodash.sampleSize(letters, length).join('') } checkObj[key] = data || {} return key } }