refactor: 重構後端代碼, 換用 Deno
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
export class TheWhiteSilkParams {
|
||||
/**
|
||||
* @type { String }
|
||||
*/
|
||||
method
|
||||
/**
|
||||
* @type { Object }
|
||||
*/
|
||||
args
|
||||
}
|
||||
|
||||
export class CallbackMessage {
|
||||
static Code = class {
|
||||
/**
|
||||
* 无权限
|
||||
*/
|
||||
static PERMISSION_DENIED = 401
|
||||
/**
|
||||
* 不存在
|
||||
*/
|
||||
static NOT_FOUND = 404
|
||||
/**
|
||||
* 服务端错误
|
||||
*/
|
||||
static SERVER_ERROR = 500
|
||||
/**
|
||||
* 请求成功
|
||||
*/
|
||||
static OK = 200
|
||||
}
|
||||
/**
|
||||
* @type { String }
|
||||
*/
|
||||
msg
|
||||
/**
|
||||
* @type { Number }
|
||||
*/
|
||||
code
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import io from '../lib/io.js';
|
||||
import { sha256 } from '../lib/crypto.js'
|
||||
|
||||
const baseDir = 'whitesilk_data/chat'
|
||||
io.mkdirs(baseDir)
|
||||
|
||||
export class ChatManager {
|
||||
/**
|
||||
* 获取私聊实例 (双方可对调)
|
||||
* @param { String } a 用户A 的 ID
|
||||
* @param { String } b 用户B 的 ID
|
||||
* @returns { Chat }
|
||||
*/
|
||||
static getPrivateChat(a, b) {
|
||||
let id = sha256([
|
||||
a,
|
||||
b,
|
||||
].sort().join())
|
||||
io.mkdirs(`${baseDir}/${id}`)
|
||||
let chat = new Chat(id)
|
||||
chat.id = id
|
||||
chat.updateInfo()
|
||||
return chat
|
||||
}
|
||||
}
|
||||
|
||||
export class Chat {
|
||||
constructor(id) {
|
||||
if (!io.exists(`${baseDir}/${id}`)) throw new Error(`聊天 [id=${id}]不存在!`)
|
||||
|
||||
// 尽管所有的键都是 undefined 但是仍然是键哦
|
||||
for (let k of Object.keys(this)) {
|
||||
this[k] = io.open(`${baseDir}/${id}/${k}`, 'rw').checkExistsOrWrite('').readAllAndClose().toString()
|
||||
}
|
||||
}
|
||||
updateInfo() {
|
||||
// 尽管所有的键都是 undefined 但是仍然是键哦
|
||||
for (let k of Object.keys(this)) {
|
||||
io.open(`${baseDir}/${this.id}/${k}`, 'w').writeAll((this[k] || '') + '').close()
|
||||
}
|
||||
// 防止服务端错误修改此值 主要是都是属性了再搞特殊对待很麻烦的
|
||||
io.open(`${baseDir}/${this.id}/id`, 'w').writeAll(this.id + '').close()
|
||||
}
|
||||
/**
|
||||
* 聊天 ID
|
||||
* @type { String }
|
||||
*/
|
||||
id
|
||||
}
|
||||
|
||||
export class ChatApi {
|
||||
static createUser() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
import io from '../lib/io.js';
|
||||
import { sha256 } from '../lib/crypto.js'
|
||||
import { CallbackMessage } from '../Types.js';
|
||||
|
||||
const baseDir = 'whitesilk_data/user'
|
||||
io.mkdirs(baseDir)
|
||||
|
||||
export class UserManager {
|
||||
static getUserProfileDir(id) {
|
||||
return `${baseDir}/${id}`
|
||||
}
|
||||
static getUserById(id) {
|
||||
return new User(id)
|
||||
}
|
||||
static getUserByName(name) {
|
||||
let list = io.listFolders(baseDir, {
|
||||
fullPath: false,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新用户
|
||||
* @param { Object } arg
|
||||
* @param { String } [arg.name] 用户名
|
||||
* @returns { User }
|
||||
*/
|
||||
static createUser({ name } = {}) {
|
||||
let idCountFile = io.open(`${baseDir}/idcount`, 'rw').checkExistsOrWrite('10000')
|
||||
let idCount = parseInt(idCountFile.readAll())
|
||||
|
||||
io.mkdirs(`${baseDir}/${idCount}`)
|
||||
|
||||
idCount++
|
||||
idCountFile.writeAll(idCount + '').close()
|
||||
idCount--
|
||||
|
||||
let user = new User(idCount)
|
||||
user.id = idCount
|
||||
user.name = name
|
||||
user.updateProfile()
|
||||
return user
|
||||
}
|
||||
}
|
||||
|
||||
export class User {
|
||||
constructor(id) {
|
||||
if (!io.exists(`${baseDir}/${id}`)) throw new Error(`用户 [id=${id}]不存在!`)
|
||||
|
||||
// 尽管所有的键都是 undefined 但是仍然是键哦
|
||||
for (let k of Object.keys(this)) {
|
||||
this[k] = io.open(`${baseDir}/${id}/${k}`, 'rw').checkExistsOrWrite('').readAllAndClose().toString()
|
||||
}
|
||||
}
|
||||
updateProfile() {
|
||||
// 尽管所有的键都是 undefined 但是仍然是键哦
|
||||
for (let k of Object.keys(this)) {
|
||||
io.open(`${baseDir}/${this.id}/${k}`, 'w').writeAll((this[k] || '') + '').close()
|
||||
}
|
||||
// 防止服务端错误修改此值 主要是都是属性了再搞特殊对待很麻烦的
|
||||
io.open(`${baseDir}/${this.id}/id`, 'w').writeAll(this.id + '').close()
|
||||
}
|
||||
/**
|
||||
* 设置头像
|
||||
* @param { Buffer } data 头像数据
|
||||
*/
|
||||
setAvatar(data) {
|
||||
io.open(`${baseDir}/${this.id}/avatar`, 'w').writeAll(data).close()
|
||||
}
|
||||
/**获取头像
|
||||
* @returns { Buffer } data 头像数据
|
||||
*/
|
||||
getAvatar() {
|
||||
return io.open(`${baseDir}/${this.id}/avatar`, 'r').readAllAndClose()
|
||||
}
|
||||
/**
|
||||
* 用户 ID
|
||||
* @type { String }
|
||||
*/
|
||||
id
|
||||
/**
|
||||
* 用户名
|
||||
* @type { String }
|
||||
*/
|
||||
name
|
||||
/**
|
||||
* 用户昵称
|
||||
* @type { String }
|
||||
*/
|
||||
nick
|
||||
/**
|
||||
* 用户简介
|
||||
* @type { String }
|
||||
*/
|
||||
description
|
||||
/**
|
||||
* 密码(经过加盐哈希处理后的 哈希后的密码)
|
||||
* @type { String }
|
||||
*/
|
||||
passwordHashed
|
||||
}
|
||||
|
||||
export const UserApi = {
|
||||
API_NAME: 'UserApi',
|
||||
/**
|
||||
* 注册用户
|
||||
* @param { Object } args
|
||||
* @param { String } args.name 用户名(必须, 注册后可以删除)
|
||||
* @param { String } args.password 密码(哈希后)
|
||||
* @returns { CallbackMessage }
|
||||
*/
|
||||
["createUser"]: (args) => {
|
||||
// TODO: 想办法解决账号注册的问题
|
||||
// 思路之一: 扫名称 重复则不允许
|
||||
// 思路之二: 邮箱制 但是无法多账号 以及其他遗留问题
|
||||
// 长远思考
|
||||
|
||||
// 2025.6.2 決定
|
||||
// 使用郵箱驗證, 以賬號ID為基準, 用戶名可改但不可重複制度
|
||||
// 關聯性字符串數據庫
|
||||
|
||||
// 具體方案: 先使用郵箱驗證
|
||||
// 再注冊賬號
|
||||
// 賬號支持修改不重複的用戶名
|
||||
// 可以一個郵箱多個賬號
|
||||
// 修改郵箱 = 修改文件名
|
||||
// 多賬號管理 = 郵箱 (文件夾) + 多賬戶ID
|
||||
// 忘記賬號 = 郵箱驗證 + 給出所有賬號
|
||||
let user = UserManager.createUser({
|
||||
name: args.name,
|
||||
})
|
||||
user.passwordHashed = sha256('我是盐 这个后面会给成配置文件来配置的喵~' + args.password)
|
||||
user.updateProfile()
|
||||
return {
|
||||
msg: '🥰🥰🥰🥰🥰',
|
||||
code: CallbackMessage.Code.OK,
|
||||
data: args,
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
// @ts-types="npm:@types/babel__core"
|
||||
import babel from '@babel/core'
|
||||
import io from './lib/io.js'
|
||||
|
||||
function compileJs(path) {
|
||||
function compileJs(path: string) {
|
||||
babel.transformFileAsync(path, {
|
||||
presets: [
|
||||
[
|
||||
@@ -22,13 +23,14 @@ function compileJs(path) {
|
||||
},
|
||||
sourceMaps: true,
|
||||
}).then(function (result) {
|
||||
if (result == null) throw new Error('result == null')
|
||||
io.open(path, 'w').writeAll(result.code + '\n' + `//@ sourceMappingURL=${io.getName(path)}.map`).close()
|
||||
io.open(path + '.map', 'w').writeAll(JSON.stringify(result.map)).close()
|
||||
console.log(`Compile js: ${path}`)
|
||||
})
|
||||
}
|
||||
|
||||
export default function (path) {
|
||||
export default function (path: string) {
|
||||
io.listFiles(path, {
|
||||
recursive: true,
|
||||
fullPath: true,
|
||||
13
server/config.ts
Normal file
13
server/config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import io from './lib/io.js'
|
||||
|
||||
export default class Config {
|
||||
static ensureAllDirsAreCreated() {
|
||||
for (const key of Object.keys(Config.dirs)) {
|
||||
io.mkdirs(Config.dirs[key])
|
||||
}
|
||||
}
|
||||
static BASE_DIR = 'whitesilk'
|
||||
static dirs : { [key: string]: string } = {
|
||||
WEB_PAGE_DIR: this.BASE_DIR + '/_webpage'
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import http from 'node:http'
|
||||
// import https from 'node:https' // 暂时
|
||||
import express from 'express'
|
||||
import { Server as SocketIoServer } from 'socket.io'
|
||||
|
||||
// 类型提示
|
||||
import { TheWhiteSilkParams, CallbackMessage } from './Types.js'
|
||||
|
||||
const app = express()
|
||||
const httpApp = http.createServer(app)
|
||||
const sio = new SocketIoServer(httpApp, {})
|
||||
|
||||
// 编译前端代码
|
||||
import io from './lib/io.js'
|
||||
io.copyDir('./client/', './whitesilk_data/page_builded/')
|
||||
await import('./build.js').then(a => a.default('whitesilk_data/page_builded/'))
|
||||
app.use('/', express.static('whitesilk_data/page_builded/'))
|
||||
|
||||
const events = {}
|
||||
import { UserApi } from './api/User.js'
|
||||
|
||||
for (let i of [
|
||||
UserApi,
|
||||
]) {
|
||||
for (let i2 of Object.keys(i)) {
|
||||
if (i2 == 'API_NAME') continue
|
||||
events[i.API_NAME + '.' + [i2]] = i[i2]
|
||||
}
|
||||
}
|
||||
|
||||
sio.on("connection", (socket) => {
|
||||
socket.on('the_white_silk',
|
||||
/**
|
||||
* @param { TheWhiteSilkParams } params
|
||||
* @param { Function } callback
|
||||
*/
|
||||
(params, callback) => {
|
||||
if ((params || callback) == null || typeof callback != 'function') return;
|
||||
|
||||
/** @type { CallbackMessage } */
|
||||
let data = events[params.method] ? events[params.method](params.args) : {
|
||||
msg: '找不到此方法',
|
||||
code: CallbackMessage.Code.NOT_FOUND,
|
||||
}
|
||||
callback(data)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
httpApp.listen(80)
|
||||
Reference in New Issue
Block a user