优化项目结构,优化构建脚本,优化README.MD
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		
							
								
								
									
										16
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								.drone.yml
									
									
									
									
									
								
							@ -7,12 +7,12 @@ kind: pipeline
 | 
			
		||||
name: test
 | 
			
		||||
 | 
			
		||||
steps:
 | 
			
		||||
  - name: installgit p
 | 
			
		||||
  - name: test
 | 
			
		||||
    image: node:16
 | 
			
		||||
    commands:
 | 
			
		||||
      - yarn install
 | 
			
		||||
      - yarn test
 | 
			
		||||
  - name: telgram_notify
 | 
			
		||||
  - name: notify
 | 
			
		||||
    image: appleboy/drone-telegram
 | 
			
		||||
    when:
 | 
			
		||||
      status:
 | 
			
		||||
@ -25,19 +25,19 @@ steps:
 | 
			
		||||
      format: markdown
 | 
			
		||||
      message: >
 | 
			
		||||
        {{#success build.status}}
 | 
			
		||||
        ✅ `{{repo.name}}` #{{build.number}} 号构建测试已通过 .
 | 
			
		||||
        📝 {{commit.author}} 在 `{{commit.branch}}` 的提交:
 | 
			
		||||
        ✅ `{{repo.name}}` #{{build.number}} 号构建测试已通过\n
 | 
			
		||||
        📝 {{commit.author}} 在 `{{commit.branch}}` 的提交:\n
 | 
			
		||||
        ```
 | 
			
		||||
        {{commit.message}}
 | 
			
		||||
        ```
 | 
			
		||||
        🌐 {{ build.link }}
 | 
			
		||||
        \n🌐 {{ build.link }}
 | 
			
		||||
        {{else}}
 | 
			
		||||
        ❌ `{{repo.name}}` #{{build.number}} 号构建测试已失败 .
 | 
			
		||||
        📝 {{commit.author}} 在 `{{commit.branch}}` 的提交:
 | 
			
		||||
        ❌ `{{repo.name}}` #{{build.number}} 号构建测试已失败\n
 | 
			
		||||
        📝 {{commit.author}} 在 `{{commit.branch}}` 的提交:\n
 | 
			
		||||
        ```
 | 
			
		||||
        {{commit.message}}
 | 
			
		||||
        ```
 | 
			
		||||
        🌐 {{ build.link }}
 | 
			
		||||
        \n🌐 {{ build.link }}
 | 
			
		||||
        {{/success}}
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										56
									
								
								README.MD
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								README.MD
									
									
									
									
									
								
							@ -2,26 +2,31 @@
 | 
			
		||||
 | 
			
		||||
老色批世界树 —— 一个高性能麻将、奥苏力不-印寨克托接口的实现。使用fastify来把处理速度加速到老色批的速度(
 | 
			
		||||
 | 
			
		||||
具体有多快呢?登录处理从数据包发出到接收到服务端响应仅需要 __***6ms***__(根据机器不同可能会有浮动,以实际情况为准)! 
 | 
			
		||||
 | 
			
		||||
[](https://996.icu)
 | 
			
		||||
[](https://github.com/996icu/996.ICU/blob/master/LICENSE)
 | 
			
		||||
[](https://ci.186526.xyz/Lama3L9R/lsp-yggdrasil)
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
TODO:
 | 
			
		||||
## 开发计划:
 | 
			
		||||
 | 
			
		||||
- [ ] Basic API
 | 
			
		||||
#### Beta 1.0: 
 | 
			
		||||
- [ ] 基础世界树 API
 | 
			
		||||
  + [x] /authserver
 | 
			
		||||
  + [ ] /sessionserver
 | 
			
		||||
  + [ ] /api
 | 
			
		||||
- [ ] Advanced API
 | 
			
		||||
  - [ ] Skin uploading & security checks for texture
 | 
			
		||||
    + [ ] Texture RSAsigning
 | 
			
		||||
  - [ ] S3 Storage backend
 | 
			
		||||
  - [ ] Server status
 | 
			
		||||
  - [ ] Authlib meta
 | 
			
		||||
- [ ] Telegram Bot
 | 
			
		||||
- [ ] Unit test
 | 
			
		||||
- [ ] 进阶 API
 | 
			
		||||
  - [ ] 皮肤上传和安全检查
 | 
			
		||||
    + [ ] 皮肤数据的RSA签名
 | 
			
		||||
  - [ ] 兼容S3后端
 | 
			
		||||
  - [ ] 服务器状态接口
 | 
			
		||||
  - [ ] authlib-injector 元数据接口
 | 
			
		||||
 | 
			
		||||
#### Release 1.0
 | 
			
		||||
- [ ] TGbot前端
 | 
			
		||||
- [ ] 单元测试
 | 
			
		||||
  + [ ] API
 | 
			
		||||
    - [ ] /authserver
 | 
			
		||||
    - [ ] /sessionserver
 | 
			
		||||
@ -29,16 +34,29 @@ TODO:
 | 
			
		||||
    - [ ] Advanced API
 | 
			
		||||
  + [ ] Utils
 | 
			
		||||
 | 
			
		||||
## WIP
 | 
			
		||||
#### 未来的版本:
 | 
			
		||||
 | 
			
		||||
推荐 Node.js 版本:`16.15.0 LTS (Latest LTS)`
 | 
			
		||||
- [ ] 完整 web 管理
 | 
			
		||||
 | 
			
		||||
*因为魔法,在 Node14 也能跑*
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
构建方法
 | 
			
		||||
```
 | 
			
		||||
$ yarn install && node ./build.js
 | 
			
		||||
```
 | 
			
		||||
## 使用方法
 | 
			
		||||
 | 
			
		||||
**记得手动复制`config.js`!放在和主程序一个目录就行,构建完了看`./production`**
 | 
			
		||||
**因为我设置了项目为`module`,构建出来的是`cjs`因此不能直接在项目目录下跑,扔到别的地方跑**
 | 
			
		||||
1. 安装Node.js、yarn、并下载源代码
 | 
			
		||||
   + 推荐 Node.js 版本:`16.15.0 LTS (Latest LTS)`,最低兼容 `14 LTS`
 | 
			
		||||
   + 使用 `$ npm install -g yarn` 来安装yarn
 | 
			
		||||
   + 使用 `$ git clone https://git.186526.xyz/Lama3L9R/lsp-yggdrasil.git` 下载源代码
 | 
			
		||||
2. 使用 `$ yarn install` 安装依赖库
 | 
			
		||||
3. 配置 `src/config.js`
 | 
			
		||||
4. 使用 `$ node build.js` 创建运行时构建
 | 
			
		||||
5. 使用 `$ node path/to/lsp-yggdrasil.full.cjs` 起飞
 | 
			
		||||
 | 
			
		||||
## 常见问题
 | 
			
		||||
 | 
			
		||||
- Q:支持 `https` 嘛?
 | 
			
		||||
- A:不支持,请使用反代来使用`https`,或者您也可以修改 `index.js` 中初始化代码。
 | 
			
		||||
 | 
			
		||||
## 内置的 yarn 指令
 | 
			
		||||
 | 
			
		||||
+ `dev` —— 启动开发环境服务器
 | 
			
		||||
+ `test` —— 单元测试
 | 
			
		||||
							
								
								
									
										18
									
								
								build.js
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								build.js
									
									
									
									
									
								
							@ -3,9 +3,11 @@ import exec from 'shelljs.exec'
 | 
			
		||||
 | 
			
		||||
const productionVersion = "1.0"
 | 
			
		||||
 | 
			
		||||
const build = exec('git log -n 1 --pretty=format:"%h on %as with key %GK"', { async: false }).stdout
 | 
			
		||||
const build = exec('git log -n 1 --pretty=format:"%h-%GK"', { async: false }).stdout
 | 
			
		||||
const type = exec('git log -n 1 --pretty=format:"%D"', { async: false }).stdout
 | 
			
		||||
const buildDate = new Date().toTimeString()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const banner = `
 | 
			
		||||
 ==========================================================================
 | 
			
		||||
    __   _____ ______  __                __                _ __
 | 
			
		||||
@ -24,18 +26,22 @@ const banner = `
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
console.log(banner)
 | 
			
		||||
console.log("Creating a production build...")
 | 
			
		||||
 | 
			
		||||
if(type.indexOf('stable') === -1) {
 | 
			
		||||
    console.warn("⚠ 警告: 此版本不是正式版,运行可能会存在性能、安全、稳定度等严重风险,请谨慎使用!\n")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
console.log("正在创建运行时文件...")
 | 
			
		||||
 | 
			
		||||
esbuild.build({
 | 
			
		||||
    entryPoints: ['./src/index.js'],
 | 
			
		||||
    outfile: './production/lsp-yggdrasil.full.js',
 | 
			
		||||
    outfile: './production/lsp-yggdrasil.full.cjs',
 | 
			
		||||
    bundle: true,
 | 
			
		||||
    platform: 'node',
 | 
			
		||||
    target: 'es2018',
 | 
			
		||||
    external: ['./config.js'],
 | 
			
		||||
    banner: {
 | 
			
		||||
        js: `/*\n${banner}\n*/`
 | 
			
		||||
        js: `/*\n${banner}\n*/;const PROGRAM_PRODUCTION = true;`
 | 
			
		||||
    },
 | 
			
		||||
}).then(() => {
 | 
			
		||||
    console.log("Done! Enjoy the yggdrasil server as FAST as LSP")
 | 
			
		||||
    console.log("一份运行时文件已保存在 production/lsp-yggdrasil.full.js,您可以尽情的体验和LSP一样快的世界树服务器了!")
 | 
			
		||||
})
 | 
			
		||||
@ -1,23 +1,38 @@
 | 
			
		||||
const defaultPrehandler = async function (req, rep) { }
 | 
			
		||||
 | 
			
		||||
export const config = {
 | 
			
		||||
    database: {
 | 
			
		||||
    database: { // MONGODB IS THE BEST DATABASE
 | 
			
		||||
        url: 'mongodb://localhost:27017/yggdrasil?readPreference=primary&appname=MongoDB%20Compass&directConnection=true&ssl=false',
 | 
			
		||||
    },
 | 
			
		||||
    server: {
 | 
			
		||||
        port: 3000,
 | 
			
		||||
        url: '',
 | 
			
		||||
        port: 3000
 | 
			
		||||
    },
 | 
			
		||||
    signing: {
 | 
			
		||||
    signing: { // 签名材质信息使用
 | 
			
		||||
        public: '/path/to/public.pem',
 | 
			
		||||
        private: '/path/to/private.key'
 | 
			
		||||
    },
 | 
			
		||||
    custom: {
 | 
			
		||||
        overridePrehandler: (url) => {
 | 
			
		||||
            return defaultPrehandler
 | 
			
		||||
        override: {
 | 
			
		||||
            preHandler: {
 | 
			
		||||
                /*
 | 
			
		||||
                "/example/route": async function(req, rep) {}
 | 
			
		||||
                */
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
            handler: {
 | 
			
		||||
                /*
 | 
			
		||||
                "/example/route": async function(req, rep) {}
 | 
			
		||||
                */
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        preHooks: (fastify) => {},
 | 
			
		||||
        preRouting: (fastify) => {},
 | 
			
		||||
        postRouting: (fastify) => {},
 | 
			
		||||
        preHooks: (fastify) => {}, // 在这里添加自定义hook
 | 
			
		||||
        preRouting: (fastify) => {}, // 在这里添加自定义路由
 | 
			
		||||
        postRouting: (fastify) => {}, // IDK what u want to do at here
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getOverrideHandler(route) {
 | 
			
		||||
    return config.custom.override.handler[route]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getOverridePreHandler(route) {
 | 
			
		||||
    return config.custom.override.preHandler[route]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/index.js
									
									
									
									
									
								
							@ -3,6 +3,21 @@ import { mongoose } from 'mongoose'
 | 
			
		||||
import { registerModels } from './models/index.js';
 | 
			
		||||
import * as Hooks from './hooks.js'
 | 
			
		||||
import * as AuthenticateRoutings from './routes/authenticate.js'
 | 
			
		||||
import { config } from './config.js'
 | 
			
		||||
 | 
			
		||||
console.log(`
 | 
			
		||||
 ================================================================
 | 
			
		||||
    __   _____ ______  __                __                _ __
 | 
			
		||||
   / /  / ___// __ \\ \\/ /___ _____ _____/ /________ ______(_) /
 | 
			
		||||
  / /   \\__ \\/ /_/ /\\  / __ \`/ __ \`/ __  / ___/ __ \`/ ___/ / / 
 | 
			
		||||
 / /______/ / ____/ / / /_/ / /_/ / /_/ / /  / /_/ (__  ) / /  
 | 
			
		||||
/_____/____/_/     /_/\\__, /\\__, /\\__,_/_/   \\__,_/____/_/_/   
 | 
			
		||||
                     /____//____/                              
 | 
			
		||||
================================================================\n`)
 | 
			
		||||
 | 
			
		||||
if(typeof PROGRAM_PRODUCTION === 'undefined') {
 | 
			
		||||
    console.warn("⚠ 警告: 您运行的不是正式版本,可能会不稳定,仅限开发环境运行!\n")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const server = fastify({
 | 
			
		||||
    logger: {
 | 
			
		||||
@ -14,10 +29,6 @@ export const server = fastify({
 | 
			
		||||
//export const logger = server.log
 | 
			
		||||
 | 
			
		||||
;(async () => {
 | 
			
		||||
    const { config } = await import('./config.js')
 | 
			
		||||
 | 
			
		||||
    server.decorate('conf', config)
 | 
			
		||||
 | 
			
		||||
    const mongooseClient = await mongoose.connect(config.database.url)
 | 
			
		||||
    const models = registerModels(mongooseClient)
 | 
			
		||||
 | 
			
		||||
@ -28,11 +39,14 @@ export const server = fastify({
 | 
			
		||||
    server.addHook('preHandler', Hooks.headerValidation)
 | 
			
		||||
 | 
			
		||||
    config.custom.preRouting(server)
 | 
			
		||||
    
 | 
			
		||||
    // Authserver routings
 | 
			
		||||
    server.route(AuthenticateRoutings.authenticate)
 | 
			
		||||
    server.route(AuthenticateRoutings.refresh)
 | 
			
		||||
    server.route(AuthenticateRoutings.validate)
 | 
			
		||||
    server.route(AuthenticateRoutings.invalidate)
 | 
			
		||||
    server.route(AuthenticateRoutings.signout)
 | 
			
		||||
 | 
			
		||||
    config.custom.postRouting(server)
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
import * as PlayerModel from '../models/player.js'
 | 
			
		||||
import { createHash } from 'crypto'
 | 
			
		||||
import { generateToken, uuidToNoSymboUUID } from '../generator.js'
 | 
			
		||||
import { getOverrideHandler, getOverridePreHandler } from '../config.js'
 | 
			
		||||
 | 
			
		||||
export const authenticate = {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
@ -46,7 +47,7 @@ export const authenticate = {
 | 
			
		||||
                    },
 | 
			
		||||
                    "availableProfiles": {
 | 
			
		||||
                        "type": "array",
 | 
			
		||||
                        "items": [{...PlayerModel.PlayerSeriliazationSchema}]
 | 
			
		||||
                        "items": [PlayerModel.PlayerSeriliazationSchema]
 | 
			
		||||
                    },
 | 
			
		||||
                    "selectedProfile": PlayerModel.PlayerSeriliazationSchema,
 | 
			
		||||
                    "user": PlayerModel.PlayerAccountSerializationSchema
 | 
			
		||||
@ -54,10 +55,8 @@ export const authenticate = {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    preHandler: async function(req, rep) {
 | 
			
		||||
        this.conf.custom.overridePrehandler('/authserver/authenticate', req, rep)
 | 
			
		||||
    },
 | 
			
		||||
    handler: async function (req, rep) {
 | 
			
		||||
    preHandler: getOverridePreHandler("/authserver/authenticate"),
 | 
			
		||||
    handler: getOverrideHandler("/authserver/authenticate") ?? async function (req, rep) {
 | 
			
		||||
        let { username, password, clientToken, requestUser, agent } = req.body
 | 
			
		||||
 | 
			
		||||
        if(!username || !password || !agent || agent.name.toLowerCase() !== 'minecraft') {
 | 
			
		||||
@ -185,10 +184,8 @@ export const refresh = {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    preHandler: async function(req, rep) {
 | 
			
		||||
        this.conf.custom.overridePrehandler('/authserver/refresh', req, rep)
 | 
			
		||||
    },
 | 
			
		||||
    handler: async function (req, rep) {
 | 
			
		||||
    preHandler: getOverridePreHandler("/authserver/refresh"),
 | 
			
		||||
    handler: getOverrideHandler("/authserver/authenticate") ?? async function (req, rep) {
 | 
			
		||||
        const { accessToken, clientToken, requestUser, selectedProfile } = req.body
 | 
			
		||||
 | 
			
		||||
        const query = { 
 | 
			
		||||
@ -320,10 +317,8 @@ export const validate = {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    preHandler: async function(req, rep) {
 | 
			
		||||
        this.conf.custom.overridePrehandler('/authserver/validate', req, rep)
 | 
			
		||||
    },
 | 
			
		||||
    handler: async function (req, rep) {
 | 
			
		||||
    preHandler: getOverridePreHandler("/authserver/validate"),
 | 
			
		||||
    handler: getOverrideHandler("/authserver/validate") ?? async function (req, rep) {
 | 
			
		||||
        const { accessToken, clientToken } = req.body
 | 
			
		||||
 | 
			
		||||
        const query = { 
 | 
			
		||||
@ -380,10 +375,8 @@ export const invalidate = {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    ,
 | 
			
		||||
    preHandler: async function(req, rep) {
 | 
			
		||||
        this.conf.custom.overridePrehandler('/authserver/invalidate', req, rep)
 | 
			
		||||
    },
 | 
			
		||||
    handler: async function (req, rep) {
 | 
			
		||||
    preHandler: getOverridePreHandler("/authserver/invalidate"),
 | 
			
		||||
    handler: getOverrideHandler("/authserver/authenticate") ?? async function (req, rep) {
 | 
			
		||||
        const { accessToken } = req.body
 | 
			
		||||
 | 
			
		||||
        const { modifiedCount } = await this.models.Token.updateOne({
 | 
			
		||||
@ -428,10 +421,8 @@ export const signout = {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    preHandler: async function(req, rep) {
 | 
			
		||||
        this.conf.custom.overridePrehandler('/authserver/logout', req, rep)
 | 
			
		||||
    },
 | 
			
		||||
    handler: async function (req, rep) {
 | 
			
		||||
    preHandler: getOverridePreHandler("/authserver/signout"),
 | 
			
		||||
    handler: getOverrideHandler("/authserver/signout") ?? async function (req, rep) {
 | 
			
		||||
        const { username, password } = req.body
 | 
			
		||||
 | 
			
		||||
        const player = await this.models.Player.findOne({ email: username, password: createHash('sha256').update(password).digest().toString('hex').toLowerCase() })
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user