Commit 9524ea1e authored by nanahira's avatar nanahira

group allow

parent 0fbf86e0
Pipeline #3108 passed with stages
in 3 minutes and 49 seconds
...@@ -45,3 +45,15 @@ defaultTemplateMap.set('bad_params', BadParamsText); ...@@ -45,3 +45,15 @@ defaultTemplateMap.set('bad_params', BadParamsText);
export const AdminQuitGroup = `已退出群 {{groupId}}。`; export const AdminQuitGroup = `已退出群 {{groupId}}。`;
defaultTemplateMap.set('admin_quit_group', AdminQuitGroup); defaultTemplateMap.set('admin_quit_group', AdminQuitGroup);
export const WelcomeMessageDemo = `本群的欢迎信息是:\n{{&message}}\n\n示例:\n{{&demo}}`;
defaultTemplateMap.set('welcome_message_demo', WelcomeMessageDemo);
export const WelcomeMessageNotFound = `本群没有设置欢迎信息。\n使用 .group.welcome <信息> 来设置一个。`;
defaultTemplateMap.set('welcome_message_not_found', WelcomeMessageNotFound);
export const WelcomeMessageSet = `已经设置群欢迎信息为 {{&message}}`;
defaultTemplateMap.set('welcome_message_set', WelcomeMessageSet);
export const GroupAllowSet = `已经设置群 {{groupId}} 可加入状态为 {{value}}。`;
defaultTemplateMap.set('group_allow_set', GroupAllowSet);
...@@ -90,16 +90,26 @@ export class AppService { ...@@ -90,16 +90,26 @@ export class AppService {
return profile; return profile;
} }
async checkJoinGroup(userId: string) { async checkJoinGroup(userData: KoishiSessionLike) {
const user = await this.botService.findOrCreateUser(userId); this.log.log(
this.log.log(`Bot being invited by ${user.name} ${userId}`); `Bot being invited to ${userData.groupId} by ${userData.username} ${userData.userId}`,
);
const { user, group, profile, banReason } = await this.getDatabaseUserData(
userData,
);
if (banReason) {
this.log.log(`Bot rejected because of: ${banReason}.`);
return false;
}
if (group && group.allowedToJoin) {
this.log.log(`Bot accepted for being allowed.`);
return true;
}
if (user.checkPermissions(UserPermissions.inviteBot)) { if (user.checkPermissions(UserPermissions.inviteBot)) {
this.log.log(`Bot accepted.`); this.log.log(`Bot accepted for admin.`);
return true; return true;
} else if (user.banReason) {
this.log.log(`Bot rejected because of banned user: ${user.banReason}.`);
return false;
} }
this.log.log(`Bot ignored.`); this.log.log(`Bot ignored.`);
return undefined; return undefined;
} }
...@@ -452,4 +462,63 @@ export class AppService { ...@@ -452,4 +462,63 @@ export class AppService {
) )
).join('\n----------\n'); ).join('\n----------\n');
} }
async getWelcomeMessage(userData: KoishiSessionLike) {
const { user, group, profile, banReason } = await this.getDatabaseUserData(
userData,
);
if (banReason) {
return await this.renderTemplate('bad_user', { reason: banReason });
}
if (group.welcomeMessage) {
return await this.renderTemplate(
'welcome_message_demo',
{ message: group.welcomeMessage, demo: group.welcomeUser(user) },
userData.groupId,
);
} else {
return await this.renderTemplate(
'welcome_message_not_found',
{},
userData.groupId,
);
}
}
async setWelcomeMessage(userData: KoishiSessionLike, message: string) {
const { user, group, profile, banReason } = await this.getDatabaseUserData(
userData,
);
if (banReason) {
return await this.renderTemplate('bad_user', { reason: banReason });
}
group.setWelcomeMessage(message);
await this.db.getRepository(Group).save(group);
return await this.renderTemplate(
'welcome_message_set',
{ message },
userData.groupId,
);
}
async handleWelcome(userData: KoishiSessionLike) {
const { user, group, profile, banReason } = await this.getDatabaseUserData(
userData,
);
if (banReason) {
return null;
}
return group.welcomeUser(user);
}
async setGroupAllow(
userData: KoishiSessionLike,
groupId: string,
value: number,
) {
const { user, banReason } = await this.getDatabaseUserData(userData);
if (banReason) {
return await this.renderTemplate('bad_user', { reason: banReason });
}
const group = await this.botService.findOrCreateGroup(groupId);
group.allowedToJoin = value;
await this.db.getRepository(Group).save(group);
return await this.renderTemplate('group_allow_set', { groupId, value });
}
} }
...@@ -32,8 +32,7 @@ export class BotController { ...@@ -32,8 +32,7 @@ export class BotController {
this.bot.plugin(koishiCommonPlugin, { this.bot.plugin(koishiCommonPlugin, {
onFriendRequest: true, onFriendRequest: true,
onGroupRequest: async (session) => { onGroupRequest: async (session) => {
const userId = session.userId; return await this.appService.checkJoinGroup(session);
return await this.appService.checkJoinGroup(userId);
}, },
}); });
this.loadBotRouters(); this.loadBotRouters();
...@@ -64,6 +63,17 @@ export class BotController { ...@@ -64,6 +63,17 @@ export class BotController {
} }
return next(); return next();
}); });
groupCtx.on('group-member-added', async (session) => {
const messageToSend = await this.appService.handleWelcome(session);
if (messageToSend) {
this.botService.log.log(
`${session.userId} ${session.username} joined group ${session.groupId} => ${messageToSend}`,
);
await session.send(
`${segment('at', { id: session.userId })} ${messageToSend}`,
);
}
});
globalCtx globalCtx
.command('rolldice', '投掷骰子') .command('rolldice', '投掷骰子')
.option('count', '-c <count:posint> 骰子数量', { fallback: 1 }) .option('count', '-c <count:posint> 骰子数量', { fallback: 1 })
...@@ -84,28 +94,52 @@ export class BotController { ...@@ -84,28 +94,52 @@ export class BotController {
return await this.appService.rollDice(rollResult, session); return await this.appService.rollDice(rollResult, session);
}); });
const groupCommand = groupCtx.command('group', '群内指令'); const groupCommand = groupCtx.command('group', '群内指令');
groupCtx
.command('dismiss', '退群,请使用这个命令,而不是踢我出去。')
.usage('只有管理员可以操作。群内数据会保留。')
.action(async (argv) => {
const session = argv.session;
return await this.processDismissCommand(session);
});
groupCommand groupCommand
.subcommand('.dismiss', '退群') .subcommand('.dismiss', '退群')
.usage('群内数据会保留。') .usage('只有管理员可以操作。群内数据会保留。')
.alias('dismiss')
.action(async (argv) => { .action(async (argv) => {
const session = argv.session; const session = argv.session;
return await this.processDismissCommand(session);
});
groupCommand
.subcommand('.welcome [message:text]', '设置群欢迎消息')
.usage(
'只有管理员可以操作。新人加入的时候会自动发送。允许使用模板。设置为 null 则清除。',
)
.alias('welcome')
.action(async (argv, message) => {
const session = argv.session;
if (!message || message === 'get') {
const ret = await this.appService.getWelcomeMessage(session);
return `${segment('at', {
id: session.userId,
})} ${ret}`;
}
if ( if (
!(await this.checkGroupAdminOrPermission( !(await this.checkGroupAdminOrPermission(
session, session,
UserPermissions.GroupDismiss, UserPermissions.GroupTemplateRead,
)) ))
) { ) {
return `${segment('at', { return `${segment('at', {
id: session.userId, id: session.userId,
})} ${await this.appService.renderTemplate( })} ${await this.appService.renderTemplate(
'permission_denied', 'permission_denied',
{ action: '退群' }, { action: '设置群欢迎消息' },
session.groupId, session.groupId,
)}`; )}`;
} }
await this.groupDismiss(session.groupId); const ret = await this.appService.setWelcomeMessage(session, message);
return undefined; return `${segment('at', {
id: session.userId,
})} ${ret}`;
}); });
const groupTemplateCommand = groupCommand const groupTemplateCommand = groupCommand
.subcommand('.template', '获取本群自定义模板') .subcommand('.template', '获取本群自定义模板')
...@@ -216,7 +250,7 @@ export class BotController { ...@@ -216,7 +250,7 @@ export class BotController {
return `${segment('at', { id: session.userId })} ${ret}`; return `${segment('at', { id: session.userId })} ${ret}`;
}); });
const groupUserCommand = groupCommand const groupUserCommand = groupCommand
.subcommand('.user [field:text]', '查看群内用户信息') .subcommand('.user [field:string]', '查看群内用户信息')
.usage('带参数查看其他人的用户信息,但是只有管理员可以用。') .usage('带参数查看其他人的用户信息,但是只有管理员可以用。')
.example( .example(
'.user 查看自己的用户信息。.user Nanahira 查看 Nanahira 的用户信息。', '.user 查看自己的用户信息。.user Nanahira 查看 Nanahira 的用户信息。',
...@@ -255,7 +289,7 @@ export class BotController { ...@@ -255,7 +289,7 @@ export class BotController {
return `${segment('at', { id: session.userId })} ${ret}`; return `${segment('at', { id: session.userId })} ${ret}`;
}); });
const userCommand = globalCtx const userCommand = globalCtx
.command('account [field:text]', '查看用户信息') .command('account [field:string]', '查看用户信息')
.usage('带参数查看其他人的用户信息,但是只有管理员可以用。') .usage('带参数查看其他人的用户信息,但是只有管理员可以用。')
.example( .example(
'.account 查看自己的用户信息。.account Nanahira 查看 Nanahira 的用户信息。', '.account 查看自己的用户信息。.account Nanahira 查看 Nanahira 的用户信息。',
...@@ -325,6 +359,34 @@ export class BotController { ...@@ -325,6 +359,34 @@ export class BotController {
session.groupId, session.groupId,
); );
}); });
adminCommand
.subcommand('.join <groupId:string>', '设置允许加入指定群')
.usage('并不会主动加群,但是允许被邀请的时候加群。')
.option('value', '-v <value:integer>', { fallback: 1 })
.option('value', '--disable', { value: 0 })
.action(async (argv, groupId) => {
const session = argv.session;
const value = argv.options.value;
if (
!(await this.checkUserPermission(session, UserPermissions.inviteBot))
) {
return `${segment('at', {
id: session.userId,
})} ${await this.appService.renderTemplate(
'permission_denied',
{ action: '设置允许加入指定群' },
session.groupId,
)}`;
}
if (!groupId) {
return await this.appService.renderTemplate(
'bad_params',
{},
session.groupId,
);
}
return await this.appService.setGroupAllow(session, groupId, value);
});
const adminTemplateCommand = adminCommand const adminTemplateCommand = adminCommand
.subcommand('.template', '获取默认模板') .subcommand('.template', '获取默认模板')
.usage( .usage(
...@@ -491,6 +553,42 @@ export class BotController { ...@@ -491,6 +553,42 @@ export class BotController {
getBot() { getBot() {
return (this.bot.bots[0] as unknown) as CQBot; return (this.bot.bots[0] as unknown) as CQBot;
} }
async processDismissCommand(
session: Session<
never,
never,
'onebot',
keyof Session.Events,
| keyof Session.MessageType
| 'role'
| 'ban'
| keyof Session.GroupMemberChangeType
| 'poke'
| 'lucky-king'
| 'honor'
>,
) {
if (
!(await this.checkUserPermission(session, UserPermissions.GroupDismiss))
) {
if (
!(await this.checkGroupAdminOrPermission(
session,
UserPermissions.GroupDismiss,
))
) {
return `${segment('at', {
id: session.userId,
})} ${await this.appService.renderTemplate(
'permission_denied',
{ action: '退群' },
session.groupId,
)}`;
}
await this.groupDismiss(session.groupId);
return undefined;
}
}
async groupDismiss(groupId: string) { async groupDismiss(groupId: string) {
try { try {
await this.getBot().$setGroupLeave(groupId, false); await this.getBot().$setGroupLeave(groupId, false);
......
...@@ -9,6 +9,7 @@ export const UserPermissions = { ...@@ -9,6 +9,7 @@ export const UserPermissions = {
GroupUserWrite: 0x200, GroupUserWrite: 0x200,
TemplateWrite: 0x400, TemplateWrite: 0x400,
GroupTemplateWrite: 0x800, GroupTemplateWrite: 0x800,
GroupWelcomeMessage: 0x1000,
// others // others
inviteBot: 0x10000, inviteBot: 0x10000,
GroupDismiss: 0x20000, GroupDismiss: 0x20000,
......
...@@ -2,6 +2,9 @@ import { QQIDBase } from './QQIDBase'; ...@@ -2,6 +2,9 @@ import { QQIDBase } from './QQIDBase';
import { Column, Entity, OneToMany } from 'typeorm'; import { Column, Entity, OneToMany } from 'typeorm';
import { GroupTemplate } from './GroupTemplate'; import { GroupTemplate } from './GroupTemplate';
import { GroupUserProfile } from './GroupUserProfile'; import { GroupUserProfile } from './GroupUserProfile';
import he from 'he';
import { User } from './User';
import Mustache from 'mustache';
@Entity() @Entity()
export class Group extends QQIDBase { export class Group extends QQIDBase {
...@@ -11,6 +14,27 @@ export class Group extends QQIDBase { ...@@ -11,6 +14,27 @@ export class Group extends QQIDBase {
@OneToMany((type) => GroupUserProfile, (profile) => profile.group) @OneToMany((type) => GroupUserProfile, (profile) => profile.group)
userProfiles: GroupUserProfile[]; userProfiles: GroupUserProfile[];
@Column('text', { nullable: true })
welcomeMessage: string;
@Column('tinyint', { default: 0 })
allowedToJoin: number;
setWelcomeMessage(message: string) {
if (!message || message === 'null') {
this.welcomeMessage = null;
} else {
this.welcomeMessage = he.decode(message);
}
}
welcomeUser(user: User) {
if (!this.welcomeMessage) {
return null;
}
return Mustache.render(this.welcomeMessage, user);
}
renderText(key: string, data: any) { renderText(key: string, data: any) {
const template = this.templates.find((t) => key === t.key); const template = this.templates.find((t) => key === t.key);
if (this.templates) { if (this.templates) {
......
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