File size: 4,179 Bytes
1b5ed97 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
import express from 'express'
import template from 'express-art-template'
import http from 'http'
import lodash from 'lodash'
import fs from 'node:fs'
import { resolve } from 'node:path'
import YAML from 'yaml'
class example {
constructor () {
this.cfg = YAML.parse(fs.readFileSync('./config.yaml', 'utf8'))
this.tmp = {}
this.isRegister = {}
this.result = {}
this.load(express())
console.log(`Successfully started, port: \x1b[32m${this.cfg.Port}\x1b[0m`)
console.log('\x1b[32m%s\x1b[0m', `[POST] ${this.address}/register${this.cfg.Key && `?key=${this.cfg.Key}`}`)//`
}
load(app) {
// 使用服务器自带的 HTTP 配置
http.createServer(app).listen(this.cfg.Port);
this.route(app);
}
route (app) {
app.use(express.static(resolve('public')))
app.use(express.urlencoded({ extended: false }))
app.use(express.json())
app.engine('html', template)
app.set('views', resolve('public'))
app.set('view engine', 'html')
app.get('/GTest/:key', this.self('index'))
app.post('/GTest/register', this.self('register'))
app.get('/GTest/register/:key', this.self('get_register'))
app.post('/GTest/validate/:key', this.self('validate'))
app.get('/GTest/validate/:key', this.self('get_validate'))
app.use(this.invalid)
app.use(this.error)
}
/** 模板引擎为常用的art-template */
index (req, res, next) {
let { key } = req.params
if (!key || !this.isRegister[key]) return next('验证信息不存在或已失效。')
res.render('GTest/main', { key, copyright: this.cfg.Copyright })
}
/** 验证信息, post传mys接口res.data */
register (req, res, next) {
let { key } = req.query, { gt, challenge } = req.body || {}
if (!gt || !challenge) return next('error')
if (this.cfg.Key && key !== this.cfg.Key) return next('please enter the correct key')
for (let i = 0; i < 99; i++) {
key = lodash.sampleSize('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 6).join('')
if (this.isRegister[key] || this.result[key]) continue
break
}
this.tmp[key] = req.body
this.isRegister[key] = 1
/** 未点击2分钟后删除 */
setTimeout(() => delete this.tmp[key] && delete this.isRegister[key], 120000)
this.send(res, {
link: `${this.address}/${key}`,
result: `${this.address}/validate/${key}`
})
}
/** 浏览器获取gt参数 */
get_register (req, res, next) {
let { key } = req.params
if (!key || !this.tmp[key]) return next('该验证信息已被使用,若非本人操作请重新获取')
res.send(this.tmp[key] || {})
delete this.tmp[key]
}
/** 浏览器返回validate */
validate (req, res, next) {
let { key } = req.params
if (!key || !req.body) return next('error')
this.result[key] = req.body
setTimeout(() => delete this.result[key], 30000)
this.send(res, {})
delete this.isRegister[key]
console.log('[GeeTest] 验证成功, key:', key)
}
/** 获取验证结果validate,改为挂起 */
async get_validate (req, res, next) {
let { key } = req.params, data = null
if (!key) return next('error')
if (this.isRegister[key] || this.result[key]) {
for (let i = 0; i < 120; i++) {
if (this.result[key]) {
data = this.result[key]
break
}
await new Promise((resolve) => setTimeout(resolve, 1000))
}
if (!data) data = {}
}
this.send(res, data)
}
invalid (req, res) {
if (!res.finished) res.status(404).end()
}
error (err, req, res, next) {
let message = err?.message || (err !== 'error' && `${err}`) || 'Invalid request'
if (!res.finished) res.send({ status: 1, message })
}
send (res, data, message = 'OK') {
res.send({
status: Number(!data),
message,
data
})
}
get address () {
let { Host, Port, Https, Key } = this.cfg
if (![80, 443,7860].includes(Port)) Host += `:${Port}`
return `https://${Host}/GTest`
}
self (fn) {
return (...args) => this[fn].call(this, ...args)
}
}
process.on('unhandledRejection', (error, promise) => console.log(error))
new example() |