Commit d71c92e7 authored by nanahira's avatar nanahira

user system..

parent 842c9c98
Pipeline #3099 passed with stages
in 14 minutes and 29 seconds
......@@ -1327,6 +1327,12 @@
"@types/node": "*"
}
},
"@types/he": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/he/-/he-1.1.1.tgz",
"integrity": "sha512-jpzrsR1ns0n3kyWt92QfOUQhIuJGQ9+QGa7M62rO6toe98woQjnsnzjdMtsQXCdvjjmqjS2ZBCC7xKw0cdzU+Q==",
"dev": true
},
"@types/http-assert": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz",
......@@ -4252,6 +4258,11 @@
}
}
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"highlight.js": {
"version": "10.7.2",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.2.tgz",
......
export const DefaultRollText =
'{{&name}} {{#reason}}因为 {{&reason}} {{/reason}}而投掷了 {{count}} 个 {{size}} 面骰子,投掷出了 {{result}} 点。\n{{&formula}}={{result}}';
'{{&name}} {{#reason}}因为 {{&reason}} 而{{/reason}}投掷了 {{count}} 个 {{size}} 面骰子,投掷出了 {{result}} 点。\n{{&formula}}={{result}}';
export const TooMuchCountText =
'{{&name}} {{#reason}}因为 {{&reason}} {{/reason}}而投掷了 {{count}} 个 {{size}} 面骰子。\n骰子滚落了一地,找不到了。';
'{{&name}} {{#reason}}因为 {{&reason}} 而{{/reason}}投掷了 {{count}} 个 {{size}} 面骰子。\n骰子滚落了一地,找不到了。';
export const TooMuchSizeText =
'{{&name}} {{#reason}}因为 {{&reason}} {{/reason}}而投掷了 {{count}} 个 {{size}} 面骰子。\n丢了个球。丢个球啊!';
'{{&name}} {{#reason}}因为 {{&reason}} 而{{/reason}}投掷了 {{count}} 个 {{size}} 面骰子。\n丢了个球。丢个球啊!';
export const BadUserText = '非法用户。';
export const defaultTemplateMap = new Map<string, string>();
......
......@@ -64,28 +64,48 @@ export class AppService {
return msg;
}
private async renderTemplate(key: string, data: any, groupId?: string) {
let template: TextTemplate;
if (groupId) {
template = await this.db
private async getTemplateForGroup(key: string, groupId: string) {
return await this.db
.getRepository(GroupTemplate)
.createQueryBuilder('template')
.where('template.key = :key', { key })
.andWhere('template.groupId = :groupId', { groupId })
.getOne();
}
private async getTemplate(key: string, groupId: string) {
let template: TextTemplate;
if (groupId) {
template = await this.getTemplateForGroup(key, groupId);
if (template) {
return template.render(data);
return template;
}
}
template = await this.db
.getRepository(DefaultTemplate)
.findOne({ where: { key } });
if (template) {
return template;
}
return null;
}
private async renderTemplate(key: string, data: any, groupId?: string) {
const template = await this.getTemplate(key, groupId);
if (template) {
return template.render(data);
}
return Mustache.render(defaultTemplateMap.get(key), data) || key;
}
async isUserHasPermissions(userId: string, username: string, perm: number) {
const user = await this.botService.findOrCreateUser(userId, username);
if (user.isBanned) {
return false;
}
return user.checkPermissions(perm);
}
private async checkUserAndGroup(
userId: string,
username: string,
......@@ -119,4 +139,59 @@ export class AppService {
AppService.rollProcess(rollResult);
return await this.renderTemplate('roll', rollResult, groupId);
}
async getGroupTemplate(key: string, groupId: string) {
const group = await this.botService.findOrCreateGroup(groupId);
if (group.isBanned) {
return await this.renderTemplate('bad_user', {});
}
const template = await this.getTemplate(key, groupId);
if (template) {
return template.display();
}
return `${key} => ${defaultTemplateMap.get(key) || '没有这个模板'}`;
}
async getAllGroupTemplates(groupId: string) {
const group = await this.botService.findOrCreateGroup(groupId);
if (group.isBanned) {
return await this.renderTemplate('bad_user', {});
}
const notSetTemplateNames = Array.from(defaultTemplateMap.keys()).filter(
(tName) => !group.templates.find((t) => t.key === tName),
);
return `本群设置过的自定义模板有:\n${group.templates
.map((t) => t.display())
.join('\n')}\n\n还没有设置的自定义模板有:\n${notSetTemplateNames.join(
'\n',
)}`;
}
async setGroupTemplate(key: string, groupId: string, content: string) {
const group = await this.botService.findOrCreateGroup(groupId);
if (group.isBanned) {
return await this.renderTemplate('bad_user', {});
}
if (!defaultTemplateMap.has(key)) {
return `模板 ${key} 不存在。`;
}
let template = await this.getTemplateForGroup(key, groupId);
if (!template) {
template = new GroupTemplate();
template.key = key;
template.group = group;
}
template.changeContent(content);
await this.db.getRepository(GroupTemplate).save(template);
return `成功设置自定义模板: ${template.display()}`;
}
async clearGroupTemplate(key: string, groupId: string) {
const group = await this.botService.findOrCreateGroup(groupId);
if (group.isBanned) {
return await this.renderTemplate('bad_user', {});
}
const template = await this.getTemplateForGroup(key, groupId);
if (!template) {
return `自定义模板 ${key} 没有设置过。`;
}
await this.db.getRepository(GroupTemplate).delete(template);
return `成功清除模板 ${key}`;
}
}
import { Controller } from '@nestjs/common';
import { AppService, RollResult } from '../app.service';
import { BotService } from './bot.service';
import { App } from 'koishi';
import { App, Session, segment } from 'koishi';
import * as koishiCommonPlugin from 'koishi-plugin-common';
import * as adapter from 'koishi-adapter-onebot';
import { defaultTemplateMap } from '../DefaultTemplate';
import { UserPermissions } from '../constants';
import { User } from '../entities/User';
const __ = typeof adapter; // just for import
@Controller('_bot')
......@@ -85,5 +88,135 @@ export class BotController {
session.groupId,
);
});
groupCtx
.command('group.template.get [key:string]', '获取本群自定义模板')
.usage(
`只有群管理员才能使用。key 为模板名。目前支持的模板有: ${Array.from(
defaultTemplateMap.keys(),
).join(' ')}`,
)
.example('.group.template.get roll 获取投掷骰子的消息模板。')
.action(async (argv, key) => {
const session = argv.session;
if (
!(await this.checkGroupAdminOrPermission(
session,
UserPermissions.TemplateRead,
))
) {
return `${segment('at', { id: session.userId })} 你没有权限哦。`;
}
let ret;
if (key) {
ret = await this.appService.getGroupTemplate(key, session.groupId);
} else {
ret = await this.appService.getAllGroupTemplates(session.groupId);
}
return `${segment('at', { id: session.userId })} ${ret}`;
});
groupCtx
.command(
'group.template.set <key:string> <content:text>',
'设置本群自定义模板',
)
.usage(
`只有群管理员才能使用。key 为模板名,content为模板内容。目前支持的模板有: ${Array.from(
defaultTemplateMap.keys(),
).join(' ')}`,
)
.example('.group.template.set roll <内容> 设置投掷骰子的消息模板。')
.action(async (argv, key, content) => {
const session = argv.session;
if (
!(await this.checkGroupAdminOrPermission(
session,
UserPermissions.TemplateWrite,
))
) {
return `${segment('at', { id: session.userId })} 你没有权限哦。`;
}
if (!key || !content) {
return `${segment('at', { id: session.userId })} 缺少参数。`;
}
const ret = await this.appService.setGroupTemplate(
key,
session.groupId,
content,
);
return `${segment('at', { id: session.userId })} ${ret}`;
});
groupCtx
.command('group.template.clear <key:string>', '清除本群自定义模板')
.usage(
`只有群管理员才能使用。key 为模板名。目前支持的模板有: ${Array.from(
defaultTemplateMap.keys(),
).join(' ')}`,
)
.example('.group.template.set roll <内容> 设置投掷骰子的消息模板。')
.action(async (argv, key) => {
const session = argv.session;
if (
!(await this.checkGroupAdminOrPermission(
session,
UserPermissions.TemplateWrite,
))
) {
return `${segment('at', { id: session.userId })} 你没有权限哦。`;
}
if (!key) {
return `${segment('at', { id: session.userId })} 缺少参数。`;
}
const ret = await this.appService.clearGroupTemplate(
key,
session.groupId,
);
return `${segment('at', { id: session.userId })} ${ret}`;
});
}
async checkGroupAdminOrPermission(
session: Session<
never,
never,
'onebot',
keyof Session.Events,
| keyof Session.MessageType
| 'role'
| 'ban'
| keyof Session.GroupMemberChangeType
| 'poke'
| 'lucky-king'
| 'honor'
>,
perm: number,
) {
return (
(await this.checkGroupAdmin(session)) ||
(await this.appService.isUserHasPermissions(
session.userId,
session.username,
UserPermissions.TemplateRead,
))
);
}
async checkGroupAdmin(
session: Session<
never,
never,
'onebot',
keyof Session.Events,
| keyof Session.MessageType
| 'role'
| 'ban'
| keyof Session.GroupMemberChangeType
| 'poke'
| 'lucky-king'
| 'honor'
>,
) {
const { role } = await session.bot.$getGroupMemberInfo(
session.groupId,
session.userId,
);
return role === 'owner' || role === 'admin';
}
}
......@@ -39,7 +39,7 @@ export class BotService {
}
async findOrCreateGroup(id: string) {
const repo = this.db.getRepository(Group);
let ent = await repo.findOne({ where: { id } });
let ent = await repo.findOne({ where: { id }, relations: ['templates'] });
if (ent) {
return ent;
}
......
......@@ -9,5 +9,4 @@ export const UserPermissions = {
TemplateWrite: 0x400,
// others
inviteBot: 0x10000,
GroupCheck: 0x20000,
};
......@@ -21,6 +21,6 @@ export class GroupTemplate extends TextTemplate {
@ManyToOne((type) => Group, (group) => group.templates)
group: Group;
/*@RelationId((template: GroupTemplate) => template.group)
groupId: string;*/
@RelationId((template: GroupTemplate) => template.group)
groupId: string;
}
import { TimeBase } from './TimeBase';
import { Column, PrimaryGeneratedColumn } from 'typeorm';
import Mustache from 'mustache';
import { decode } from 'he';
export class TextTemplate extends TimeBase {
key: string; // column differs
......@@ -8,13 +9,18 @@ export class TextTemplate extends TimeBase {
content: string;
changeContent(content: string) {
this.content = Buffer.from(content, 'utf-8').toString('base64');
this.content = Buffer.from(decode(content), 'utf-8').toString('base64');
}
getContent() {
return Buffer.from(this.content, 'base64').toString('utf-8');
}
render(data: any) {
return Mustache.render(
Buffer.from(this.content, 'base64').toString('utf-8'),
data,
);
return Mustache.render(this.getContent(), data);
}
display() {
return `${this.key} => ${this.getContent()}`;
}
}
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