Compare commits
4 Commits
7e30956c31
...
d2007fbdcc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2007fbdcc | ||
|
|
7bf5921298 | ||
|
|
f79fe55fe5 | ||
|
|
91bfbcb3b3 |
11
readme.md
Normal file
11
readme.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
## TheWhiteSilk
|
||||||
|
|
||||||
|
Under developing...
|
||||||
|
|
||||||
|
### TODO
|
||||||
|
|
||||||
|
* [x] 接口完備
|
||||||
|
* [ ] 對外接口
|
||||||
|
* [ ] 單元測試
|
||||||
|
* [ ] 基本可用
|
||||||
|
* [ ] 負載均衡
|
||||||
@@ -2,6 +2,7 @@ import BaseApi from './BaseApi.ts'
|
|||||||
import HttpServerLike from '../types/HttpServerLike.ts'
|
import HttpServerLike from '../types/HttpServerLike.ts'
|
||||||
import UserApi from "./UserApi.ts"
|
import UserApi from "./UserApi.ts"
|
||||||
import SocketIo from "socket.io"
|
import SocketIo from "socket.io"
|
||||||
|
import UnknownFunction from "../types/UnknownFunction.ts";
|
||||||
|
|
||||||
export default class ApiManager {
|
export default class ApiManager {
|
||||||
static httpServer: HttpServerLike
|
static httpServer: HttpServerLike
|
||||||
@@ -14,9 +15,22 @@ export default class ApiManager {
|
|||||||
static getHttpServer() {
|
static getHttpServer() {
|
||||||
return this.httpServer
|
return this.httpServer
|
||||||
}
|
}
|
||||||
|
static getSocketIoServer() {
|
||||||
|
return this.socketIoServer
|
||||||
|
}
|
||||||
static initAllApis() {
|
static initAllApis() {
|
||||||
this.apis_instance = {
|
this.apis_instance = {
|
||||||
user: new UserApi()
|
user: new UserApi()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static initEvents() {
|
||||||
|
const io = this.socketIoServer
|
||||||
|
io.on('connection', (socket) => {
|
||||||
|
socket.on("The_White_Silk", (name: string, args: {}, callback: UnknownFunction) => {
|
||||||
|
if (name == null || args == null) return callback({
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import UnknownFunction from '../types/UnknownFunction.ts'
|
import UnknownFunction from '../types/UnknownFunction.ts'
|
||||||
|
import ApiManager from "./ApiManager.ts";
|
||||||
|
|
||||||
export default abstract class BaseApi {
|
export default abstract class BaseApi {
|
||||||
abstract getName(): string
|
abstract getName(): string
|
||||||
@@ -7,6 +8,7 @@ export default abstract class BaseApi {
|
|||||||
}
|
}
|
||||||
abstract onInit(): void
|
abstract onInit(): void
|
||||||
registerEvent(name: string, func: UnknownFunction) {
|
registerEvent(name: string, func: UnknownFunction) {
|
||||||
|
const io = ApiManager.getSocketIoServer()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,39 @@
|
|||||||
import { DatabaseSync } from "node:sqlite"
|
import { DatabaseSync, SQLInputValue } from "node:sqlite"
|
||||||
import { Buffer } from "node:buffer"
|
import { Buffer } from "node:buffer"
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import crypto from 'node:crypto'
|
import crypto from 'node:crypto'
|
||||||
import fs_sync from 'node:fs'
|
import fs_sync from 'node:fs'
|
||||||
|
import chalk from "chalk"
|
||||||
import { fileTypeFromBuffer } from 'file-type'
|
import { fileTypeFromBuffer } from 'file-type'
|
||||||
|
|
||||||
export default class FileManager {
|
import config from "../config.ts"
|
||||||
static FileBean = class {
|
|
||||||
|
class FileBean {
|
||||||
declare count: number
|
declare count: number
|
||||||
declare name: string
|
declare name: string
|
||||||
declare hash: string
|
declare hash: string
|
||||||
declare mime: string
|
declare mime: string
|
||||||
declare chatid: string | null
|
declare chatid?: string
|
||||||
declare upload_time: number
|
declare upload_time: number
|
||||||
declare last_used_time: number
|
declare last_used_time: number
|
||||||
}
|
}
|
||||||
|
|
||||||
static File = class {
|
class File {
|
||||||
declare bean: FileManager.FileBean
|
declare bean: FileBean
|
||||||
constructor(bean: FileManager.FileBean) {
|
constructor(bean: FileBean) {
|
||||||
this.bean = bean
|
this.bean = bean
|
||||||
}
|
}
|
||||||
private setAttr(key: string, value: unknown): void {
|
private setAttr(key: string, value: SQLInputValue) {
|
||||||
FileManager.database.prepare(`UPDATE ${FileManager.table_name} SET ${key} = ? WHERE count = ?`).run(value, this.bean.count)
|
FileManager.database.prepare(`UPDATE ${FileManager.table_name} SET ${key} = ? WHERE count = ?`).run(value, this.bean.count)
|
||||||
this.bean[key] = value
|
this.bean[key] = value
|
||||||
}
|
}
|
||||||
getMime(): string {
|
getMime() {
|
||||||
return this.bean.mime
|
return this.bean.mime
|
||||||
}
|
}
|
||||||
getName(): string {
|
getName() {
|
||||||
return this.bean.name
|
return this.bean.name
|
||||||
}
|
}
|
||||||
getFilePath(): string {
|
getFilePath() {
|
||||||
const hash = this.bean.hash
|
const hash = this.bean.hash
|
||||||
return path.join(
|
return path.join(
|
||||||
config.data_path,
|
config.data_path,
|
||||||
@@ -43,23 +44,27 @@ export default class FileManager {
|
|||||||
this.bean.hash
|
this.bean.hash
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
getChatId(): string | null {
|
getChatId() {
|
||||||
return this.bean.chatid
|
return this.bean.chatid
|
||||||
}
|
}
|
||||||
getUploadTime(): number {
|
getUploadTime() {
|
||||||
return this.bean.upload_time
|
return this.bean.upload_time
|
||||||
}
|
}
|
||||||
getLastUsedTime(): number {
|
getLastUsedTime() {
|
||||||
return this.bean.last_used_time
|
return this.bean.last_used_time
|
||||||
}
|
}
|
||||||
readSync(): Buffer {
|
readSync() {
|
||||||
this.setAttr("last_used_time", Date.now())
|
this.setAttr("last_used_time", Date.now())
|
||||||
return fs_sync.readFileSync(this.getFilePath())
|
return fs_sync.readFileSync(this.getFilePath())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default class FileManager {
|
||||||
|
static FileBean = FileBean
|
||||||
|
static File = File
|
||||||
|
|
||||||
static table_name: string = "FileReferences"
|
static table_name: string = "FileReferences"
|
||||||
private static database: DatabaseSync = FileManager.init()
|
static database: DatabaseSync = FileManager.init()
|
||||||
private static init(): DatabaseSync {
|
private static init(): DatabaseSync {
|
||||||
const db: DatabaseSync = new DatabaseSync(path.join(config.data_path, FileManager.table_name + '.db'))
|
const db: DatabaseSync = new DatabaseSync(path.join(config.data_path, FileManager.table_name + '.db'))
|
||||||
db.exec(`
|
db.exec(`
|
||||||
@@ -76,7 +81,7 @@ export default class FileManager {
|
|||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
static uploadFile(fileName: string, data: Buffer, chatId: string | null) {
|
static async uploadFile(fileName: string, data: Buffer, chatId?: string) {
|
||||||
const hash = crypto.createHash('sha256').update(data).digest('hex')
|
const hash = crypto.createHash('sha256').update(data).digest('hex')
|
||||||
try {
|
try {
|
||||||
return FileManager.findByHash(hash)
|
return FileManager.findByHash(hash)
|
||||||
@@ -84,7 +89,7 @@ export default class FileManager {
|
|||||||
// Do nothing...
|
// Do nothing...
|
||||||
}
|
}
|
||||||
|
|
||||||
const mime = fileTypeFromBuffer(data)
|
const mime = (await fileTypeFromBuffer(data))?.mime || 'application/octet-stream'
|
||||||
fs_sync.writeFileSync(
|
fs_sync.writeFileSync(
|
||||||
path.join(
|
path.join(
|
||||||
config.data_path,
|
config.data_path,
|
||||||
@@ -110,7 +115,7 @@ export default class FileManager {
|
|||||||
fileName,
|
fileName,
|
||||||
hash,
|
hash,
|
||||||
mime,
|
mime,
|
||||||
chatId,
|
chatId || null,
|
||||||
Date.now(),
|
Date.now(),
|
||||||
-1
|
-1
|
||||||
).lastInsertRowid
|
).lastInsertRowid
|
||||||
@@ -118,15 +123,15 @@ export default class FileManager {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static findAllBeansByCondition(condition: string, ...args: unknown[]): FileManager.FileBean[] {
|
private static findAllBeansByCondition(condition: string, ...args: SQLInputValue[]): FileBean[] {
|
||||||
return FileManager.database.prepare(`SELECT * FROM ${FileManager.table_name} WHERE ${condition};`).all(...args)
|
return FileManager.database.prepare(`SELECT * FROM ${FileManager.table_name} WHERE ${condition};`).all(...args) as unknown as FileBean[]
|
||||||
}
|
}
|
||||||
static findByHash(hash: string): FileManager.File {
|
static findByHash(hash: string): File {
|
||||||
const beans = FileManager.findAllBeansByCondition('hash = ?', hash)
|
const beans = FileManager.findAllBeansByCondition('hash = ?', hash)
|
||||||
if (beans.length == 0)
|
if (beans.length == 0)
|
||||||
throw new Error(`找不到 hash 为 ${hash} 的文件`)
|
throw new Error(`找不到 hash 为 ${hash} 的文件`)
|
||||||
else if (beans.length > 1)
|
else if (beans.length > 1)
|
||||||
console.error(chalk.red(`警告: 查询 hash = ${id} 时, 查询到多个相同 Hash 的文件`))
|
console.error(chalk.red(`警告: 查询 hash = ${hash} 时, 查询到多个相同 Hash 的文件`))
|
||||||
return new FileManager.File(beans[0])
|
return new FileManager.File(beans[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
src/types/ApiCallbackMessage.ts
Normal file
4
src/types/ApiCallbackMessage.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
type ApiCallbackMessage = {
|
||||||
|
msg: string,
|
||||||
|
code: 200 | 400 | 401 | 403 | 404 | 500 | 501
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user