|
|
@@ -4,6 +4,7 @@ import { Task } from '../entities/task.entity'
|
|
|
import { TaskItem, TaskItemStatus } from '../entities/task-item.entity'
|
|
|
import { PaginationResponse } from '../dto/common.dto'
|
|
|
import { Sender } from '../entities/sender.entity'
|
|
|
+import { ChatGroupService } from './chat-group.service'
|
|
|
import { TgClientService } from './tgClient.service'
|
|
|
import { SenderService } from './sender.service'
|
|
|
import { buildStringSession, buildStringSessionByDcIdAndAuthKey } from '../utils/tg.util'
|
|
|
@@ -15,6 +16,7 @@ export class TaskService {
|
|
|
private senderRepository: Repository<Sender>
|
|
|
private senderService: SenderService
|
|
|
private tgClientService: TgClientService
|
|
|
+ private chatGroupService: ChatGroupService
|
|
|
private app: FastifyInstance
|
|
|
|
|
|
constructor(app: FastifyInstance) {
|
|
|
@@ -24,6 +26,7 @@ export class TaskService {
|
|
|
this.senderRepository = app.dataSource.getRepository(Sender)
|
|
|
this.senderService = new SenderService(app)
|
|
|
this.tgClientService = TgClientService.getInstance()
|
|
|
+ this.chatGroupService = new ChatGroupService(app)
|
|
|
}
|
|
|
|
|
|
async create(data: { name: string; message: string; userId: number; buffer: Buffer }): Promise<Task> {
|
|
|
@@ -487,7 +490,8 @@ export class TaskService {
|
|
|
groupType: string,
|
|
|
session?: string,
|
|
|
dcId?: number,
|
|
|
- authKey?: string
|
|
|
+ authKey?: string,
|
|
|
+ initMsg?: string
|
|
|
): Promise<any> {
|
|
|
let client: TelegramClient | null = null
|
|
|
|
|
|
@@ -549,18 +553,24 @@ export class TaskService {
|
|
|
accessHash: accessHash
|
|
|
})
|
|
|
|
|
|
- // ⭐ 必须发送一条消息,让群出现在会话列表中
|
|
|
- try {
|
|
|
- await client.sendMessage(inputChannel, {
|
|
|
- message: groupDescription || `Welcome to ${groupName}!`
|
|
|
- })
|
|
|
- this.app.log.info('已向群组发送欢迎消息')
|
|
|
- } catch (e) {
|
|
|
- this.app.log.warn('发送欢迎消息失败: ' + (e instanceof Error ? e.message : '未知错误'))
|
|
|
+ const shouldSendInit = typeof initMsg === 'string' && initMsg.trim().length > 0
|
|
|
+ if (shouldSendInit) {
|
|
|
+ // ⭐ 发送自定义初始化消息,让群出现在会话列表中
|
|
|
+ try {
|
|
|
+ await client.sendMessage(inputChannel, {
|
|
|
+ message: initMsg.trim()
|
|
|
+ })
|
|
|
+ this.app.log.info('已向群组发送自定义欢迎消息')
|
|
|
+ } catch (e) {
|
|
|
+ this.app.log.warn('发送欢迎消息失败: ' + (e instanceof Error ? e.message : '未知错误'))
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.app.log.info('未提供 initMsg,跳过欢迎消息发送')
|
|
|
}
|
|
|
|
|
|
- // 获取链接
|
|
|
- let groupLink: string | null = null
|
|
|
+ // 获取公开链接 + 永久邀请链接;若无用户名则为群配置一个
|
|
|
+ let publicLink: string | null = null
|
|
|
+ let inviteLinkPermanent: string | null = null
|
|
|
try {
|
|
|
const fullChannel = await client.invoke(
|
|
|
new Api.channels.GetFullChannel({
|
|
|
@@ -569,35 +579,75 @@ export class TaskService {
|
|
|
)
|
|
|
|
|
|
const channel = fullChannel.chats?.[0] as any
|
|
|
+ let channelUsername: string | undefined = channel?.username
|
|
|
|
|
|
- // 若存在 username(公开群)
|
|
|
- if (channel?.username) {
|
|
|
- groupLink = `https://t.me/${channel.username}`
|
|
|
- this.app.log.info(`群组公开链接(永久): ${groupLink}`)
|
|
|
- } else {
|
|
|
- // 创建私有邀请链接(有效期 1 天)
|
|
|
- const expireDate = Math.floor(Date.now() / 1000) + 24 * 60 * 60
|
|
|
+ // 若无用户名,固定用 “group_时间戳”(长度限制 5-32)
|
|
|
+ if (!channelUsername) {
|
|
|
+ const candidate = `group_${Date.now()}`
|
|
|
+ let desiredHandle = candidate.toLowerCase()
|
|
|
+ if (desiredHandle.length > 32) desiredHandle = desiredHandle.slice(0, 32)
|
|
|
+ if (desiredHandle.length < 5) desiredHandle = desiredHandle.padEnd(5, '0')
|
|
|
+
|
|
|
+ try {
|
|
|
+ await client.invoke(
|
|
|
+ new Api.channels.UpdateUsername({
|
|
|
+ channel: inputChannel,
|
|
|
+ username: desiredHandle
|
|
|
+ })
|
|
|
+ )
|
|
|
+ channelUsername = desiredHandle
|
|
|
+ this.app.log.info(`已为群设置用户名: ${channelUsername}`)
|
|
|
+ } catch (setError) {
|
|
|
+ const msg = setError instanceof Error ? setError.message : '未知错误'
|
|
|
+ this.app.log.warn(`为群设置用户名失败: ${msg}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ if (channelUsername) {
|
|
|
+ publicLink = `https://t.me/${channelUsername}`
|
|
|
+ this.app.log.info(`群组公开链接(永久): ${publicLink}`)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 永久邀请链接(不设置 expireDate)
|
|
|
+ try {
|
|
|
const inviteLink = await client.invoke(
|
|
|
new Api.messages.ExportChatInvite({
|
|
|
- peer: inputChannel,
|
|
|
- expireDate: expireDate
|
|
|
+ peer: inputChannel
|
|
|
})
|
|
|
)
|
|
|
|
|
|
const invite = inviteLink as any
|
|
|
if (invite?.link) {
|
|
|
- groupLink = invite.link
|
|
|
- this.app.log.info(`群组邀请链接(1 天有效): ${groupLink}`)
|
|
|
+ inviteLinkPermanent = invite.link
|
|
|
+ this.app.log.info(`群组邀请链接(永久): ${inviteLinkPermanent}`)
|
|
|
} else {
|
|
|
this.app.log.warn('未能获取群组邀请链接')
|
|
|
}
|
|
|
+ } catch (inviteError) {
|
|
|
+ const msg = inviteError instanceof Error ? inviteError.message : '未知错误'
|
|
|
+ this.app.log.warn(`获取群组邀请链接失败: ${msg}`)
|
|
|
}
|
|
|
} catch (error) {
|
|
|
const errorMessage = error instanceof Error ? error.message : '未知错误'
|
|
|
this.app.log.warn(`获取群组链接失败: ${errorMessage}`)
|
|
|
}
|
|
|
|
|
|
+ try {
|
|
|
+ await this.chatGroupService.upsertGroup({
|
|
|
+ chatId: chatId.toString(),
|
|
|
+ accessHash: accessHash?.toString() || '',
|
|
|
+ name: createdChat.title || groupName,
|
|
|
+ groupType,
|
|
|
+ publicLink: publicLink || undefined,
|
|
|
+ inviteLink: inviteLinkPermanent || undefined,
|
|
|
+ senderId
|
|
|
+ })
|
|
|
+ this.app.log.info('群组信息已保存到数据库')
|
|
|
+ } catch (saveError) {
|
|
|
+ const msg = saveError instanceof Error ? saveError.message : '未知错误'
|
|
|
+ this.app.log.warn(`保存群组信息失败: ${msg}`)
|
|
|
+ }
|
|
|
+
|
|
|
return {
|
|
|
success: true,
|
|
|
message: '群组创建成功',
|
|
|
@@ -605,7 +655,8 @@ export class TaskService {
|
|
|
chatId: chatId.toString(),
|
|
|
chatTitle: groupName,
|
|
|
chatType: groupType,
|
|
|
- groupLink: groupLink || null
|
|
|
+ groupLinkPublic: publicLink || null,
|
|
|
+ groupInviteLink: inviteLinkPermanent || null
|
|
|
}
|
|
|
}
|
|
|
} catch (error) {
|