feat: 增加机器人接受到新的收件箱信息时调用回调

pull/70/head
moonrailgun 2 years ago
parent 3382189dee
commit 7fb9ddc4b5

@ -834,6 +834,7 @@ importers:
ts-jest: 27.1.4 ts-jest: 27.1.4
ts-node: ^10.0.0 ts-node: ^10.0.0
typescript: ^4.3.3 typescript: ^4.3.3
url-regex: ^5.0.0
vinyl-fs: ^3.0.3 vinyl-fs: ^3.0.3
dependencies: dependencies:
'@socket.io/admin-ui': 0.5.1_socket.io@4.5.1 '@socket.io/admin-ui': 0.5.1_socket.io@4.5.1
@ -874,6 +875,7 @@ importers:
tailchat-server-sdk: link:packages/sdk tailchat-server-sdk: link:packages/sdk
ts-node: 10.9.1_t4lrjbt3sxauai4t5o275zsepa ts-node: 10.9.1_t4lrjbt3sxauai4t5o275zsepa
typescript: 4.7.4 typescript: 4.7.4
url-regex: 5.0.0
devDependencies: devDependencies:
'@babel/helper-compilation-targets': 7.18.9 '@babel/helper-compilation-targets': 7.18.9
'@types/accepts': 1.3.5 '@types/accepts': 1.3.5
@ -24433,7 +24435,7 @@ packages:
pretty-format: 27.5.1 pretty-format: 27.5.1
slash: 3.0.0 slash: 3.0.0
strip-json-comments: 3.1.1 strip-json-comments: 3.1.1
ts-node: 10.9.1_k2dsl7zculo2nmh5s33pladmoa ts-node: 10.9.1_t4lrjbt3sxauai4t5o275zsepa
transitivePeerDependencies: transitivePeerDependencies:
- bufferutil - bufferutil
- canvas - canvas
@ -37236,7 +37238,6 @@ packages:
typescript: 4.7.4 typescript: 4.7.4
v8-compile-cache-lib: 3.0.1 v8-compile-cache-lib: 3.0.1
yn: 3.1.1 yn: 3.1.1
dev: false
/ts-node/10.9.1_typescript@4.7.4: /ts-node/10.9.1_typescript@4.7.4:
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}

@ -1,5 +1,6 @@
import randomString from 'crypto-random-string'; import randomString from 'crypto-random-string';
import _ from 'lodash'; import _ from 'lodash';
import urlRegex from 'url-regex';
/** /**
* *
@ -33,6 +34,13 @@ export function isValidStr(str: unknown): str is string {
return typeof str == 'string' && str !== ''; return typeof str == 'string' && str !== '';
} }
/**
* url
*/
export function isValidUrl(str: unknown): str is string {
return typeof str == 'string' && urlRegex({ exact: true }).test(str);
}
/** /**
* *
*/ */

@ -12,28 +12,22 @@ import type { Types } from 'mongoose';
import { User } from '../user/user'; import { User } from '../user/user';
import { Message } from './message'; import { Message } from './message';
class InboxMessage { interface InboxMessage {
/** /**
* Id * Id
*/ */
@prop()
groupId?: string; groupId?: string;
/** /**
* Id * Id
*/ */
@prop()
converseId: string; converseId: string;
@prop({ messageId: string;
ref: () => Message,
})
messageId: Ref<Message>;
/** /**
* / * /
*/ */
@prop()
messageSnippet: string; messageSnippet: string;
} }
@ -60,11 +54,9 @@ export class Inbox extends TimeStamps implements Base {
@prop({ @prop({
type: () => String, type: () => String,
}) })
type: 'message'; type: string;
@prop({ @prop()
type: () => InboxMessage,
})
message?: InboxMessage; message?: InboxMessage;
/** /**

@ -8,12 +8,10 @@ import {
} from '@typegoose/typegoose'; } from '@typegoose/typegoose';
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'; import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';
import type { Types } from 'mongoose'; import type { Types } from 'mongoose';
import { UserType, userType } from 'tailchat-server-sdk';
type BaseUserInfo = Pick<User, 'nickname' | 'discriminator' | 'avatar'>; type BaseUserInfo = Pick<User, 'nickname' | 'discriminator' | 'avatar'>;
const userType = ['normalUser', 'pluginBot', 'openapiBot'];
type UserType = typeof userType[number];
/** /**
* *
*/ */

@ -74,7 +74,8 @@
"socket.io-msgpack-parser": "^3.0.2", "socket.io-msgpack-parser": "^3.0.2",
"tailchat-server-sdk": "workspace:*", "tailchat-server-sdk": "workspace:*",
"ts-node": "^10.0.0", "ts-node": "^10.0.0",
"typescript": "^4.3.3" "typescript": "^4.3.3",
"url-regex": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/helper-compilation-targets": "^7.18.2", "@babel/helper-compilation-targets": "^7.18.2",

@ -30,6 +30,7 @@ export type {
MessageStruct, MessageStruct,
MessageReactionStruct, MessageReactionStruct,
MessageMetaStruct, MessageMetaStruct,
InboxStruct,
} from './structs/chat'; } from './structs/chat';
export type { BuiltinEventMap } from './structs/events'; export type { BuiltinEventMap } from './structs/events';
export type { export type {
@ -38,7 +39,8 @@ export type {
GroupPanelStruct, GroupPanelStruct,
} from './structs/group'; } from './structs/group';
export { GroupPanelType } from './structs/group'; export { GroupPanelType } from './structs/group';
export type { UserStruct } from './structs/user'; export { userType } from './structs/user';
export type { UserStruct, UserType } from './structs/user';
// db // db
export * as db from './db'; export * as db from './db';

@ -2,11 +2,11 @@ import {
GroupStruct, GroupStruct,
UserStruct, UserStruct,
SYSTEM_USERID, SYSTEM_USERID,
TcContext,
PERMISSION, PERMISSION,
TcPureContext,
} from '../../index'; } from '../../index';
export function call(ctx: TcContext) { export function call(ctx: TcPureContext) {
return { return {
/** /**
* socketio * socketio

@ -21,3 +21,42 @@ export interface MessageMetaStruct {
content: string; content: string;
}; };
} }
interface InboxMessageStruct {
/**
* Id
*/
groupId?: string;
/**
* Id
*/
converseId: string;
/**
* ID
*/
messageId: string;
/**
* /
*/
messageSnippet: string;
}
export interface InboxStruct {
_id: string;
userId: string;
type: string;
message?: InboxMessageStruct;
/**
*
*/
payload?: object;
/**
*
*/
readed: boolean;
}

@ -1,4 +1,4 @@
import type { MessageMetaStruct } from './chat'; import type { InboxStruct, MessageMetaStruct } from './chat';
/** /**
* *
@ -22,4 +22,5 @@ export interface BuiltinEventMap {
meta: MessageMetaStruct; meta: MessageMetaStruct;
}; };
'config.updated': { config: Record<string, any> }; 'config.updated': { config: Record<string, any> };
'chat.inbox.append': InboxStruct;
} }

@ -1,5 +1,5 @@
const userType = ['normalUser', 'pluginBot', 'openapiBot']; export const userType = ['normalUser', 'pluginBot', 'openapiBot'] as const;
type UserType = typeof userType[number]; export type UserType = typeof userType[number];
export interface UserStruct { export interface UserStruct {
/** /**
@ -39,7 +39,7 @@ export interface UserStruct {
*/ */
avatar?: string; avatar?: string;
type: UserType[]; type: UserType;
emailVerified: boolean; emailVerified: boolean;
} }

@ -4,6 +4,7 @@ import {
TcContext, TcContext,
TcDbService, TcDbService,
TcPureContext, TcPureContext,
InboxStruct,
} from 'tailchat-server-sdk'; } from 'tailchat-server-sdk';
/** /**
@ -114,6 +115,7 @@ class InboxService extends TcService {
const inboxItem = await this.transformDocuments(ctx, {}, doc); const inboxItem = await this.transformDocuments(ctx, {}, doc);
await this.notifyUsersInboxAppend(ctx, [userId], inboxItem); await this.notifyUsersInboxAppend(ctx, [userId], inboxItem);
await this.emitInboxAppendEvent(ctx, inboxItem);
return true; return true;
} }
@ -152,6 +154,7 @@ class InboxService extends TcService {
const inboxItem = await this.transformDocuments(ctx, {}, doc); const inboxItem = await this.transformDocuments(ctx, {}, doc);
await this.notifyUsersInboxAppend(ctx, [userId], inboxItem); await this.notifyUsersInboxAppend(ctx, [userId], inboxItem);
await this.emitInboxAppendEvent(ctx, inboxItem);
return true; return true;
} }
@ -237,9 +240,7 @@ class InboxService extends TcService {
} }
/** /**
* *
*
*
*/ */
private async notifyUsersInboxAppend( private async notifyUsersInboxAppend(
ctx: TcPureContext, ctx: TcPureContext,
@ -250,9 +251,7 @@ class InboxService extends TcService {
} }
/** /**
* *
*
*
*/ */
private async notifyUsersInboxUpdate( private async notifyUsersInboxUpdate(
ctx: TcPureContext, ctx: TcPureContext,
@ -260,6 +259,16 @@ class InboxService extends TcService {
): Promise<void> { ): Promise<void> {
await this.listcastNotify(ctx, userIds, 'updated', {}); await this.listcastNotify(ctx, userIds, 'updated', {});
} }
/**
*
*/
private async emitInboxAppendEvent(
ctx: TcPureContext,
inboxItem: InboxStruct
) {
await ctx.emit('chat.inbox.append', inboxItem);
}
} }
export default InboxService; export default InboxService;

@ -197,6 +197,11 @@ class UserService extends TcService {
avatar: { type: 'string', optional: true }, avatar: { type: 'string', optional: true },
}, },
}); });
this.registerAction('findOpenapiBotId', this.findOpenapiBotId, {
params: {
email: 'string',
},
});
this.registerAction('ensureOpenapiBot', this.ensureOpenapiBot, { this.registerAction('ensureOpenapiBot', this.ensureOpenapiBot, {
params: { params: {
/** /**
@ -912,6 +917,13 @@ class UserService extends TcService {
}; };
} }
/**
* id
*/
findOpenapiBotId(ctx: TcContext<{ email: string }>): string {
return this.parseOpenapiBotEmail(ctx.params.email);
}
async generateUserToken( async generateUserToken(
ctx: TcContext<{ ctx: TcContext<{
userId: string; userId: string;
@ -1056,6 +1068,14 @@ class UserService extends TcService {
return `${botId}@tailchat-openapi.com`; return `${botId}@tailchat-openapi.com`;
} }
private parseOpenapiBotEmail(email: string): string | null {
if (email.endsWith('@tailchat-openapi.com')) {
return email.replace('@tailchat-openapi.com', '');
}
return null;
}
/** /**
* key * key
*/ */

@ -1,5 +1,8 @@
import { TcService, config, TcContext } from 'tailchat-server-sdk'; import { TcService, config, TcContext, call } from 'tailchat-server-sdk';
import { isValidStr, isValidUrl } from '../../lib/utils';
import type { OpenApp } from '../../models/openapi/app'; import type { OpenApp } from '../../models/openapi/app';
import got from 'got';
import _ from 'lodash';
class OpenBotService extends TcService { class OpenBotService extends TcService {
get serviceName(): string { get serviceName(): string {
@ -11,6 +14,45 @@ class OpenBotService extends TcService {
return; return;
} }
this.registerEventListener('chat.inbox.append', async (payload, ctx) => {
const userInfo = await call(ctx).getUserInfo(payload._id);
if (userInfo.type !== 'openapiBot') {
return;
}
// 开放平台机器人
const botId: string | null = await ctx.call('user.findOpenapiBotId', {
email: userInfo.email,
});
if (!(isValidStr(botId) && botId.startsWith('open_'))) {
return;
}
// 是合法的机器人id
const appId = botId.replace('open_', '');
const appInfo: OpenApp | null = await ctx.call('openapi.app.get', {
appId,
});
const callbackUrl = _.get(appInfo, 'bot.callbackUrl');
if (!isValidUrl(callbackUrl)) {
this.logger.info('机器人回调地址不是一个可用的url, skip.');
return;
}
got
.post(callbackUrl)
.then((res) => {
this.logger.info('调用机器人通知接口回调成功', res);
})
.catch((err) => {
this.logger.error('调用机器人通知接口回调失败:', err);
});
});
this.registerAction('login', this.login, { this.registerAction('login', this.login, {
params: { params: {
appId: 'string', appId: 'string',
@ -94,7 +136,7 @@ class OpenBotService extends TcService {
avatar, avatar,
}); });
this.logger.info('Simple Notify Bot Id:', botUserId); this.logger.info('[getOrCreateBotAccount] Bot Id:', botUserId);
return { return {
userId: String(botUserId), userId: String(botUserId),

Loading…
Cancel
Save