Commit e669c6fd authored by nanahira's avatar nanahira

first

parent 9ae63b73
Pipeline #6297 passed with stages
in 53 seconds
webpack.config.js
dist/*
build/*
\ No newline at end of file
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
/build
/output
/dest
/config.yaml
.idea
stages:
- build
- deploy
variables:
GIT_DEPTH: "1"
build:
stage: build
tags:
- linux
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
upload_to_minio:
stage: deploy
dependencies:
- build
tags:
- linux
script:
- aws s3 --endpoint=https://minio.mycard.moe:9000 sync --delete dist/ s3://nanahira/koishi-plugin/srvpro-roomlist
only:
- master
deploy_npm:
stage: deploy
dependencies:
- build
tags:
- linux
script:
- apt update;apt -y install coreutils
- echo $NPMRC | base64 --decode > ~/.npmrc
- npm publish . || true
only:
- master
/install-npm.sh
.git*
/output
/dest
/config.yaml
.idea
.dockerignore
Dockerfile
/src
.eslintrc.js
.prettierrc
webpack.config.js
tsconfig.json
\ No newline at end of file
{
"singleQuote": true,
"trailingComma": "all"
}
\ No newline at end of file
The MIT License (MIT)
Copyright (c) 2021 Nanahira
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# koishi-plugin-srvpro-roomlist # koishi-plugin-srvpro-roomlist
Koishi 的 [SRVPro](https://github.com/mycard/srvpro) 房间列表插件 Koishi 的 [SRVPro](https://github.com/mycard/srvpro) 房间列表插件
\ No newline at end of file
## 安装
### npm
```bash
npm install koishi-plugin-srvpro-roomlist
```
### 直接安装
在 https://cdn02.moecube.com:444/nanahira/koishi-plugin/srvpro-roomlist/index.js 下载即可。
## 配置
* `listCommandName` 获取服务器列表命令名。默认 `serverlist`
* `roomCommandName` 获取房间列表命令名。默认 `roomlist`
* `servers` 服务器列表。定义如下。
* `name` 必填。服务器名称。
* `endpoint` 必填。服务器后台 URL 。
* `tags` 服务器关键词列表。使用关键词可以搜索服务器。
* `username` `password` 服务器后台登录信息。
* `isDefault` 是否为默认服务器。默认 `false`
* `displayPrivateRooms` 是否显示私密房间。默认 `false`
* `displayPlayerIp` 是否显示玩家 IP 地址。默认 `false`
\ No newline at end of file
#!/bin/bash
npm install --save \
source-map-support
npm install --save-dev \
@types/node \
typescript \
'@typescript-eslint/eslint-plugin@^4.28.2' \
'@typescript-eslint/parser@^4.28.2 '\
'eslint@^7.30.0' \
'eslint-config-prettier@^8.3.0' \
'eslint-plugin-prettier@^3.4.0' \
prettier \
raw-loader \
ts-loader \
webpack \
webpack-cli \
koishi@^4.0.0-alpha.9 \
koishi-utils-schemagen
This diff is collapsed.
{
"name": "koishi-plugin-srvpro-roomlist",
"version": "1.0.0",
"description": "Koishi 的 [SRVPro](https://github.com/mycard/srvpro) 房间列表插件",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"lint": "eslint --fix .",
"build": "webpack"
},
"repository": {
"type": "git",
"url": "https://code.mycard.moe/3rdeye/koishi-plugin-srvpro-roomlist.git"
},
"author": "Nanahira <nanahira@momobako.com>",
"license": "MIT",
"keywords": [
"Koishi.js",
"qqbot",
"cqhttp",
"onebot",
"ygo",
"yugioh",
"ygopro"
],
"bugs": {
"url": "https://code.mycard.moe/3rdeye/koishi-plugin-srvpro-roomlist/issues"
},
"homepage": "https://code.mycard.moe/3rdeye/koishi-plugin-srvpro-roomlist",
"dependencies": {
"source-map-support": "^0.5.20"
},
"peerDependencies": {
"koishi": "^4.0.0-alpha.9"
},
"devDependencies": {
"@types/lodash": "^4.14.175",
"@types/node": "^16.11.1",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"class-transformer": "^0.4.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.1",
"koishi": "^4.0.0-alpha.9",
"koishi-utils-schemagen": "^1.1.2",
"lodash": "^4.17.21",
"prettier": "^2.4.1",
"proxy-agent": "^5.0.0",
"raw-loader": "^4.0.2",
"ts-loader": "^9.2.6",
"typescript": "^4.4.4",
"webpack": "^5.58.2",
"webpack-cli": "^4.9.0"
}
}
import 'source-map-support/register';
import { DefineSchema, SchemaConf } from 'koishi-utils-schemagen';
import { Context } from 'koishi';
import { SRVProRoomInfo } from './def';
import { plainToClass } from 'class-transformer';
export interface ServerLike {
name: string;
tags?: string[];
endpoint: string;
username?: string;
password?: string;
isDefault?: boolean;
displayPrivateRooms?: boolean;
displayPlayerIp?: boolean;
}
@SchemaConf({ desc: 'SRVPro 服务器' })
export class Server implements ServerLike {
@DefineSchema({ desc: '服务器名称', required: true })
name: string;
@DefineSchema({ desc: '服务器搜索词', default: [] })
tags: string[];
@DefineSchema({
desc: '服务器 API 连接后台,不带任何路径和尾随斜杠',
required: true,
})
endpoint: string;
@DefineSchema({ desc: '服务器后台用户名' })
username: string;
@DefineSchema({ desc: '服务器后台密码' })
password: string;
@DefineSchema({ desc: '是否是默认服务器', default: false })
isDefault: boolean;
@DefineSchema({ desc: '是否显示私密房间', default: false })
displayPrivateRooms: boolean;
@DefineSchema({ desc: '是否显示玩家 IP', default: false })
displayPlayerIp: boolean;
async fetchRooms(ctx: Context) {
return ctx.http.get<Partial<SRVProRoomInfo>>(
`${this.endpoint}/api/getrooms`,
{
username: this.username,
pass: this.password,
},
);
}
async getRoomString(ctx: Context) {
const info = await this.fetchRooms(ctx);
if (!info) {
return `获取 ${this.name} 房间列表失败。`;
}
const infoObj = plainToClass(SRVProRoomInfo, info);
return infoObj.stringify(this);
}
}
export interface MyPluginConfigLike {
listCommandName?: string;
roomCommandName?: string;
servers: ServerLike[];
}
@SchemaConf({ required: true })
export class MyPluginConfig implements MyPluginConfigLike {
@DefineSchema({ desc: '服务器列表命令名', default: 'serverlist' })
listCommandName: string;
@DefineSchema({ desc: '房间列表命令名', default: 'roomlist' })
roomCommandName: string;
@DefineSchema({ type: Server, required: true, desc: 'SRVPro 服务器列表' })
servers: Server[];
getServer(value: string) {
return (
this.servers.find((s) => s.name === value) ||
this.servers.find((s) => s.tags.includes(value)) ||
this.servers.find((s) => s.name.includes(value)) ||
this.servers.find((s) => s.endpoint === value) ||
this.servers.find((s) => s.isDefault)
);
}
}
import { Type } from 'class-transformer';
import { Server } from './config';
import _ from 'lodash';
export class Status {
score: number;
lp: number;
cards: number;
stringify(mode: number) {
if (mode === 2) {
return `(LP: ${this.lp})`;
} else if (mode === 0) {
return `(LP: ${this.lp} 卡数: ${this.cards})`;
} else {
return `(比分: ${this.score} LP: ${this.lp} 卡数: ${this.cards})`;
}
}
}
export class User {
id: string;
name: string;
ip?: string;
@Type(() => Status)
status?: Status;
pos: number;
stringify(server: Server, room: Room) {
let ret = this.name;
if (this.ip && server.displayPlayerIp) {
ret += ` (IP: ${this.ip})`;
}
if (this.status) {
ret += ` ${this.status.stringify(room.roommode)}`;
}
return ret;
}
}
export class Room {
roomid: string;
roomname: string;
roommode: number;
needpass: string;
@Type(() => User)
users: User[];
istart: string;
stringify(server: Server) {
const userInPos: Record<number, User> = _.mapValues(
_.groupBy(this.users, (u) => u.pos),
(g) => g[0],
);
let usersString: string;
if (this.roommode === 2) {
usersString = `${userInPos[0]?.stringify(server, this) || '???'} & ${
userInPos[1]?.stringify(server, this) || '???'
} VS ${userInPos[2]?.stringify(server, this) || '???'} & ${
userInPos[3]?.stringify(server, this) || '???'
}`;
} else {
usersString = `${userInPos[0]?.stringify(server, this) || '???'} VS ${
userInPos[1]?.stringify(server, this) || '???'
}`;
}
return `${this.roomname.split('$')[0]}${
this.needpass === 'false' ? '' : ` (LOCK)`
}\t${usersString}\t${this.istart}`;
}
}
export class SRVProRoomInfo {
@Type(() => Room)
rooms: Room[];
stringify(server: Server) {
let rooms = this.rooms;
if (!server.displayPrivateRooms) {
rooms = rooms.filter((r) => r.needpass === 'false');
}
return `${server.name} 的房间列表\n--------------------\n${rooms
.map((r) => r.stringify(server))
.join('\n')}\n--------------------\n共有 ${rooms.length} 个房间`;
}
}
import 'source-map-support/register';
import { Context } from 'koishi';
import { MyPlugin } from './plugin';
import { MyPluginConfig, MyPluginConfigLike } from './config';
export { MyPluginConfig } from './config';
export const name = 'srvpro-roomlist';
const plugin = new MyPlugin();
export const schema = plugin.schema;
export function apply(ctx: Context, config: MyPluginConfigLike) {
ctx.plugin(plugin, config);
}
import 'source-map-support/register';
import { Context, Schema } from 'koishi';
import { MyPluginConfig, MyPluginConfigLike } from './config';
import { schemaFromClass, schemaTransform } from 'koishi-utils-schemagen';
export class MyPlugin {
private config: MyPluginConfig;
private ctx: Context;
name = 'srvpro-roomlist-main';
schema: Schema<MyPluginConfigLike> = schemaFromClass(MyPluginConfig);
apply(ctx: Context, config: MyPluginConfigLike) {
this.ctx = ctx;
this.config = schemaTransform(MyPluginConfig, config);
ctx
.command(`${this.config.listCommandName}`, '获取服务器列表')
.action(
() =>
`可以查询的服务器有:\n${this.config.servers
.map(
(s) => `${s.name}${s.tags.length ? `\t${s.tags.join(',')}` : ''}`,
)
.join('\n')}\n使用服务器名或标签即可查询对应服务器的房间列表。`,
);
ctx
.command(
`${this.config.roomCommandName} [serverName:string]`,
'获取房间列表',
)
.usage(`可以查询的服务器请使用命令 ${this.config.listCommandName} 获取。`)
.action((argv, serverName) => {
const server = this.config.getServer(serverName);
if (!server) {
return `未找到服务器 ${serverName} 。`;
}
return server.getRoomString(ctx);
});
}
}
{
"compilerOptions": {
"outDir": "dist",
"module": "commonjs",
"target": "es2021",
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"declaration": true,
"sourceMap": true
},
"compileOnSave": true,
"allowJs": true,
"include": [
"*.ts",
"src/**/*.ts"
]
}
const path = require("path");
module.exports = {
entry: "./src/index.ts",
mode: "production",
target: "node",
devtool: "source-map",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
{ test: /\.mustache$/, use: "raw-loader" },
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
output: {
filename: "index.js",
library: {
type: "commonjs",
},
path: path.resolve(__dirname, "dist"),
},
externals: {
'koishi': 'koishi',
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment