Compare commits
7 Commits
d76abcf512
...
29ea0c5b84
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29ea0c5b84 | ||
|
|
508218a1c5 | ||
|
|
98774036cd | ||
|
|
e15e1aa4c8 | ||
|
|
1c6c0eaf84 | ||
|
|
02b0708426 | ||
|
|
d433ceb4a9 |
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -5,7 +5,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"command": "npm run build-client-and-server",
|
"command": "npm run debug",
|
||||||
"name": "Debug",
|
"name": "Debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "node-terminal"
|
"type": "node-terminal"
|
||||||
|
|||||||
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"deno.enable": false,
|
|
||||||
"deno.disablePaths": [
|
|
||||||
"./thewhitesilk_data",
|
|
||||||
"./mdui_patched"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -11,10 +11,12 @@ WORKDIR /app
|
|||||||
COPY --exclude=.git --exclude=.gitignore --exclude=Dockerfile --exclude=readme.md --exclude=thewhitesilk_config.json --exclude=thewhitesilk_data . .
|
COPY --exclude=.git --exclude=.gitignore --exclude=Dockerfile --exclude=readme.md --exclude=thewhitesilk_config.json --exclude=thewhitesilk_data . .
|
||||||
|
|
||||||
# 缓存依赖并构建项目
|
# 缓存依赖并构建项目
|
||||||
RUN deno task build
|
RUN npm run install-dependencies
|
||||||
|
|
||||||
|
RUN npm run build-client
|
||||||
|
|
||||||
# 暴露应用端口(根据你的应用调整端口号)
|
# 暴露应用端口(根据你的应用调整端口号)
|
||||||
EXPOSE 3601
|
EXPOSE 3601
|
||||||
|
|
||||||
# 启动服务
|
# 启动服务
|
||||||
CMD ["deno", "task", "build-and-run-server"]
|
CMD ["npm", "run", "server"]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client'
|
|||||||
import crypto from 'node:crypto'
|
import crypto from 'node:crypto'
|
||||||
import { CallMethod, ClientEvent, ClientEventCallback } from './ApiDeclare.ts'
|
import { CallMethod, ClientEvent, ClientEventCallback } from './ApiDeclare.ts'
|
||||||
import ApiCallbackMessage from './ApiCallbackMessage.ts'
|
import ApiCallbackMessage from './ApiCallbackMessage.ts'
|
||||||
import { CallableMethodBeforeAuth } from "lingchair-internal-shared"
|
import { CallableMethodBeforeAuth, randomUUID } from "lingchair-internal-shared"
|
||||||
import CallbackError from "./CallbackError.ts"
|
import CallbackError from "./CallbackError.ts"
|
||||||
|
|
||||||
import Message from "./Message.ts"
|
import Message from "./Message.ts"
|
||||||
@@ -36,7 +36,7 @@ export default class LingChairClient {
|
|||||||
auth: {
|
auth: {
|
||||||
...args.io?.auth,
|
...args.io?.auth,
|
||||||
device_id: this.device_id,
|
device_id: this.device_id,
|
||||||
session_id: crypto.randomUUID(),
|
session_id: randomUUID(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
this.client.on("The_White_Silk", (name: ClientEvent, data: any, _callback: (ret: unknown) => void) => {
|
this.client.on("The_White_Silk", (name: ClientEvent, data: any, _callback: (ret: unknown) => void) => {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lingchair-internal-shared": "*",
|
"lingchair-internal-shared": "*",
|
||||||
"marked": "16.3.0",
|
"marked": "16.3.0",
|
||||||
"socket.io-client": "4.8.1"
|
"socket.io-client": "4.8.1",
|
||||||
|
"crypto-browserify": "3.12.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import process from 'node:process'
|
|
||||||
import child_process from 'node:child_process'
|
|
||||||
import fs from 'node:fs/promises'
|
|
||||||
|
|
||||||
function spawn(exec: string, args: string[]) {
|
|
||||||
child_process.spawnSync(exec, args, {
|
|
||||||
stdio: [process.stdin, process.stdout, process.stderr]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function runBuild() {
|
|
||||||
const args = [
|
|
||||||
"run",
|
|
||||||
"-A",
|
|
||||||
"--node-modules-dir",
|
|
||||||
]
|
|
||||||
let i = 0
|
|
||||||
for (const arg of process.argv) {
|
|
||||||
if (i > 1)
|
|
||||||
args.push(arg)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
spawn('deno', args)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.platform == 'android') {
|
|
||||||
try {
|
|
||||||
await fs.stat('./node_modules/.deno/rollup@4.50.1/node_modules/rollup/')
|
|
||||||
} catch (e) {
|
|
||||||
spawn('deno', ['install', '--node-modules-dir=auto'])
|
|
||||||
}
|
|
||||||
spawn('sh', ["fix-build-on-android.sh"])
|
|
||||||
}
|
|
||||||
|
|
||||||
runBuild()
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
rm -r ./node_modules/.deno/rollup@4.50.1/node_modules/rollup/
|
|
||||||
cp -r ./node_modules/.deno/@rollup+wasm-node@4.48.0/node_modules/@rollup/wasm-node/ node_modules/.deno/rollup@4.50.1/node_modules/rollup/
|
|
||||||
echo Replaced rollup with @rollup/wasm-node successfully
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { LingChairClient } from 'lingchair-client-protocol'
|
import { LingChairClient } from 'lingchair-client-protocol'
|
||||||
import data from "./Data.ts"
|
import data from "./Data.ts"
|
||||||
import { UAParser } from 'ua-parser-js'
|
import { UAParser } from 'ua-parser-js'
|
||||||
import randomUUID from "./utils/randomUUID.ts"
|
import { randomUUID } from 'lingchair-internal-shared'
|
||||||
|
|
||||||
if (!data.device_id) {
|
if (!data.device_id) {
|
||||||
const ua = new UAParser(navigator.userAgent)
|
const ua = new UAParser(navigator.userAgent)
|
||||||
|
|||||||
BIN
client/icon.ico
Normal file
BIN
client/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
@@ -2,6 +2,8 @@ import 'mdui/mdui.css'
|
|||||||
import 'mdui'
|
import 'mdui'
|
||||||
import { breakpoint } from "mdui"
|
import { breakpoint } from "mdui"
|
||||||
|
|
||||||
|
import './mdui.d.ts'
|
||||||
|
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
|
|
||||||
|
|||||||
1
client/mdui.d.ts
vendored
Normal file
1
client/mdui.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="mdui/jsx.zh-cn.d.ts" />
|
||||||
@@ -6,24 +6,26 @@
|
|||||||
"build-watch": "npx vite --watch build"
|
"build-watch": "npx vite --watch build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"crypto-browserify": "3.12.1",
|
||||||
|
"crypto-js": "4.2.0",
|
||||||
|
"dompurify": "3.2.7",
|
||||||
|
"lingchair-internal-shared": "*",
|
||||||
|
"marked": "16.3.0",
|
||||||
|
"mdui": "2.1.4",
|
||||||
|
"pinch-zoom-element": "1.1.1",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"mdui": "2.1.4",
|
|
||||||
"split.js": "1.3.2",
|
|
||||||
"crypto-js": "4.2.0",
|
|
||||||
"socket.io-client": "4.8.1",
|
"socket.io-client": "4.8.1",
|
||||||
"marked": "16.3.0",
|
"split.js": "1.3.2",
|
||||||
"dompurify": "3.2.7",
|
"ua-parser-js": "2.0.6"
|
||||||
"pinch-zoom-element": "1.1.1",
|
|
||||||
"ua-parser-js": "2.0.6",
|
|
||||||
"lingchair-internal-shared": "*"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@rollup/wasm-node": "4.48.0",
|
||||||
"@types/react": "18.3.1",
|
"@types/react": "18.3.1",
|
||||||
"@types/react-dom": "18.3.1",
|
"@types/react-dom": "18.3.1",
|
||||||
"@vitejs/plugin-react": "4.7.0",
|
"@vitejs/plugin-react": "4.7.0",
|
||||||
|
"chalk": "5.4.1",
|
||||||
"vite": "7.0.6",
|
"vite": "7.0.6",
|
||||||
"@rollup/wasm-node": "4.48.0",
|
"vite-plugin-node-polyfills": "^0.24.0"
|
||||||
"chalk": "5.4.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
18
client/tsconfig.json
Normal file
18
client/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"lib": [
|
||||||
|
"ES2022",
|
||||||
|
"DOM",
|
||||||
|
"DOM.Iterable"
|
||||||
|
],
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noEmit": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { UserMySelf } from "lingchair-client-protocol"
|
|||||||
import useAsyncEffect from "../utils/useAsyncEffect.ts"
|
import useAsyncEffect from "../utils/useAsyncEffect.ts"
|
||||||
import Avatar from "./Avatar.tsx"
|
import Avatar from "./Avatar.tsx"
|
||||||
import getClient from "../getClient.ts"
|
import getClient from "../getClient.ts"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
interface Args extends React.HTMLAttributes<HTMLElement> {
|
interface Args extends React.HTMLAttributes<HTMLElement> {
|
||||||
avatarRef?: React.LegacyRef<HTMLElement>
|
avatarRef?: React.LegacyRef<HTMLElement>
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import isMobileUI from "../utils/isMobileUI.ts"
|
import isMobileUI from "../utils/isMobileUI.ts"
|
||||||
import AvatarMySelf from "./AvatarMySelf.tsx"
|
import AvatarMySelf from "./AvatarMySelf.tsx"
|
||||||
import MainSharedContext from './MainSharedContext.ts'
|
import MainSharedContext from './MainSharedContext.ts'
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
export default function Main() {
|
export default function Main() {
|
||||||
const sharedContext = {
|
const sharedContext = {
|
||||||
openChatFragment: React.useRef()
|
openChatFragment: React.useRef()
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<MainSharedContext.Provider value={{}}>
|
<MainSharedContext.Provider value={sharedContext}>
|
||||||
<div style={{
|
<div style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
import config from '../server/config.ts'
|
import config from '../server/config.ts'
|
||||||
|
import { nodePolyfills } from 'vite-plugin-node-polyfills'
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [
|
||||||
|
react(),
|
||||||
|
nodePolyfills({
|
||||||
|
include: ['crypto', 'stream', 'vm'],
|
||||||
|
globals: {
|
||||||
|
Buffer: true,
|
||||||
|
global: true,
|
||||||
|
process: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
],
|
||||||
build: {
|
build: {
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
outDir: "." + config.data_path + '/page_compiled',
|
outDir: "." + config.data_path + '/page_compiled',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
BIN
icon.png
BIN
icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 235 KiB After Width: | Height: | Size: 383 KiB |
@@ -2,3 +2,6 @@ export * from './ApiDeclare.ts'
|
|||||||
|
|
||||||
import ApiCallbackMessage from './ApiCallbackMessage.ts'
|
import ApiCallbackMessage from './ApiCallbackMessage.ts'
|
||||||
export type { ApiCallbackMessage }
|
export type { ApiCallbackMessage }
|
||||||
|
|
||||||
|
import randomUUID from './randomUUID.ts'
|
||||||
|
export { randomUUID }
|
||||||
|
|||||||
34
internal-shared/randomUUID.ts
Normal file
34
internal-shared/randomUUID.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// https://www.xiabingbao.com/post/crypto/js-crypto-randomuuid-qxcuqj.html
|
||||||
|
|
||||||
|
export default function randomUUID() {
|
||||||
|
// crypto - 只支持在安全的上下文使用
|
||||||
|
if (typeof crypto === 'object') {
|
||||||
|
// crypto-browserify 没有这个方法
|
||||||
|
if (typeof crypto.randomUUID === 'function') {
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID
|
||||||
|
return crypto.randomUUID()
|
||||||
|
}
|
||||||
|
if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
|
||||||
|
// https://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid
|
||||||
|
const callback = (c: string) => {
|
||||||
|
const num = Number(c)
|
||||||
|
return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16)
|
||||||
|
};
|
||||||
|
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 随机数
|
||||||
|
let timestamp = new Date().getTime()
|
||||||
|
let perforNow = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||||
|
let random = Math.random() * 16
|
||||||
|
if (timestamp > 0) {
|
||||||
|
random = (timestamp + random) % 16 | 0
|
||||||
|
timestamp = Math.floor(timestamp / 16)
|
||||||
|
} else {
|
||||||
|
random = (perforNow + random) % 16 | 0
|
||||||
|
perforNow = Math.floor(perforNow / 16)
|
||||||
|
}
|
||||||
|
return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
"./client"
|
"./client"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-client-and-server": "npm run build-client && npm run server",
|
"install-dependencies": "npm install -d --workspaces",
|
||||||
|
"debug": "npm run build-client && npx tsx --watch ./server/main.ts",
|
||||||
"server": "npx tsx ./server/main.ts",
|
"server": "npx tsx ./server/main.ts",
|
||||||
"build-client": "cd client && npm run build"
|
"build-client": "cd client && npm run build"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import readline from 'node:readline'
|
|
||||||
import process from "node:process"
|
|
||||||
import chalk from "chalk"
|
import chalk from "chalk"
|
||||||
import child_process from "node:child_process"
|
|
||||||
import createLingChairServer from "./server.ts"
|
import createLingChairServer from "./server.ts"
|
||||||
import config from "./config.ts"
|
import config from "./config.ts"
|
||||||
|
|
||||||
@@ -9,21 +6,3 @@ const { httpServer } = await createLingChairServer()
|
|||||||
|
|
||||||
httpServer.listen(config.server.listen)
|
httpServer.listen(config.server.listen)
|
||||||
console.log(chalk.green(`API & Web 服务已启动, 端口为 ${config.server.listen.port}`))
|
console.log(chalk.green(`API & Web 服务已启动, 端口为 ${config.server.listen.port}`))
|
||||||
function help() {
|
|
||||||
console.log(chalk.yellow("输入 b 或者执行 deno task build 以编译前端"))
|
|
||||||
}
|
|
||||||
help()
|
|
||||||
|
|
||||||
const rl = readline.createInterface({
|
|
||||||
input: process.stdin,
|
|
||||||
output: process.stdout
|
|
||||||
})
|
|
||||||
rl.on('line', (text) => {
|
|
||||||
if (text == 'b') {
|
|
||||||
console.log(chalk.green("重新编译..."))
|
|
||||||
child_process.spawnSync("deno", ["task", "build"], {
|
|
||||||
stdio: [process.stdin, process.stdout, process.stderr]
|
|
||||||
})
|
|
||||||
help()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|||||||
Reference in New Issue
Block a user