|
@@ -1,6 +1,7 @@
|
|
|
-import { TelegramClient } from 'telegram'
|
|
|
|
|
|
|
+import { Api, TelegramClient } from 'telegram'
|
|
|
import { StringSession } from 'telegram/sessions'
|
|
import { StringSession } from 'telegram/sessions'
|
|
|
import { SendMessageResult } from '../dto/tg-msg-send.dto'
|
|
import { SendMessageResult } from '../dto/tg-msg-send.dto'
|
|
|
|
|
+import bigInt from 'big-integer'
|
|
|
|
|
|
|
|
export class TgMsgSendService {
|
|
export class TgMsgSendService {
|
|
|
private app: any
|
|
private app: any
|
|
@@ -22,20 +23,27 @@ export class TgMsgSendService {
|
|
|
try {
|
|
try {
|
|
|
client = await this.createAndConnectClient(sessionString, apiId, apiHash)
|
|
client = await this.createAndConnectClient(sessionString, apiId, apiHash)
|
|
|
|
|
|
|
|
- const parsedTargetId = this.parseTargetId(target)
|
|
|
|
|
- if (!parsedTargetId) {
|
|
|
|
|
|
|
+ const parsedTarget = this.parseTarget(target)
|
|
|
|
|
+ if (!parsedTarget) {
|
|
|
return { success: false, error: 'target 格式错误,请检查是否正确' }
|
|
return { success: false, error: 'target 格式错误,请检查是否正确' }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const targetPeer = await this.getTargetPeer(client, parsedTargetId)
|
|
|
|
|
|
|
+ const targetPeer = await this.getTargetPeer(client, parsedTarget)
|
|
|
if (!targetPeer) {
|
|
if (!targetPeer) {
|
|
|
return { success: false, error: 'target 无效,无法获取目标信息' }
|
|
return { success: false, error: 'target 无效,无法获取目标信息' }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const result = await this.sendMessageToPeer(client, targetPeer, message)
|
|
const result = await this.sendMessageToPeer(client, targetPeer, message)
|
|
|
-
|
|
|
|
|
this.app.log.info('消息发送成功', result.id)
|
|
this.app.log.info('消息发送成功', result.id)
|
|
|
|
|
|
|
|
|
|
+ await this.clearConversation(client, targetPeer)
|
|
|
|
|
+ this.app.log.info('会话清除成功')
|
|
|
|
|
+
|
|
|
|
|
+ if (target.startsWith('+')) {
|
|
|
|
|
+ await this.deleteTempContact(client, targetPeer.id)
|
|
|
|
|
+ this.app.log.info('临时联系人删除成功')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return {
|
|
return {
|
|
|
success: true,
|
|
success: true,
|
|
|
messageId: result.id
|
|
messageId: result.id
|
|
@@ -86,20 +94,35 @@ export class TgMsgSendService {
|
|
|
return client
|
|
return client
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private async getTargetPeer(client: TelegramClient, parsedTargetId: string | number): Promise<any> {
|
|
|
|
|
|
|
+ private async getTargetPeer(client: TelegramClient, parsedTarget: string | number): Promise<any> {
|
|
|
this.app.log.info('正在获取目标实体信息...')
|
|
this.app.log.info('正在获取目标实体信息...')
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
let targetPeer: any
|
|
let targetPeer: any
|
|
|
|
|
|
|
|
- if (typeof parsedTargetId === 'string' && parsedTargetId.startsWith('@')) {
|
|
|
|
|
- // 用户名
|
|
|
|
|
- targetPeer = await client.getEntity(parsedTargetId)
|
|
|
|
|
- } else if (typeof parsedTargetId === 'number') {
|
|
|
|
|
- // 用户 id
|
|
|
|
|
- targetPeer = await client.getEntity(parsedTargetId)
|
|
|
|
|
|
|
+ if (typeof parsedTarget === 'string' && parsedTarget.startsWith('+')) {
|
|
|
|
|
+ this.app.log.info('手机号导入联系人...')
|
|
|
|
|
+ // 手机号
|
|
|
|
|
+ const result = await client.invoke(
|
|
|
|
|
+ new Api.contacts.ImportContacts({
|
|
|
|
|
+ contacts: [
|
|
|
|
|
+ new Api.InputPhoneContact({
|
|
|
|
|
+ clientId: bigInt(0),
|
|
|
|
|
+ phone: parsedTarget,
|
|
|
|
|
+ firstName: 'Temp',
|
|
|
|
|
+ lastName: ''
|
|
|
|
|
+ })
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ const user = result.users?.[0]
|
|
|
|
|
+ if (!user) throw new Error('未找到对应的 Telegram 用户')
|
|
|
|
|
+
|
|
|
|
|
+ targetPeer = user
|
|
|
} else {
|
|
} else {
|
|
|
- targetPeer = await client.getEntity(parsedTargetId)
|
|
|
|
|
|
|
+ // 用户名 用户 id
|
|
|
|
|
+ targetPeer = await client.getEntity(parsedTarget)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (targetPeer) {
|
|
if (targetPeer) {
|
|
@@ -110,11 +133,11 @@ export class TgMsgSendService {
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
const errorMessage = this.extractErrorMessage(error)
|
|
const errorMessage = this.extractErrorMessage(error)
|
|
|
|
|
|
|
|
- if (typeof parsedTargetId === 'number') {
|
|
|
|
|
|
|
+ if (typeof parsedTarget === 'number') {
|
|
|
this.app.log.error({
|
|
this.app.log.error({
|
|
|
msg: '无法获取用户实体',
|
|
msg: '无法获取用户实体',
|
|
|
error: errorMessage,
|
|
error: errorMessage,
|
|
|
- targetId: parsedTargetId.toString()
|
|
|
|
|
|
|
+ targetId: parsedTarget.toString()
|
|
|
})
|
|
})
|
|
|
throw new Error('target 无效,不在用户消息列表中')
|
|
throw new Error('target 无效,不在用户消息列表中')
|
|
|
}
|
|
}
|
|
@@ -122,38 +145,12 @@ export class TgMsgSendService {
|
|
|
this.app.log.error({
|
|
this.app.log.error({
|
|
|
msg: '无法获取目标信息',
|
|
msg: '无法获取目标信息',
|
|
|
error: errorMessage,
|
|
error: errorMessage,
|
|
|
- target: parsedTargetId
|
|
|
|
|
|
|
+ target: parsedTarget
|
|
|
})
|
|
})
|
|
|
throw new Error('target 无效,请检查 target 是否正确')
|
|
throw new Error('target 无效,请检查 target 是否正确')
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private logTargetInfo(targetPeer: any): void {
|
|
|
|
|
- const entityInfo = targetPeer as any
|
|
|
|
|
- const logData: any = {
|
|
|
|
|
- className: entityInfo.className || '未知'
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 记录 ID
|
|
|
|
|
- if (entityInfo.id !== undefined) {
|
|
|
|
|
- logData.id = entityInfo.id.toString()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 记录名称信息
|
|
|
|
|
- if (entityInfo.title) {
|
|
|
|
|
- logData.title = entityInfo.title
|
|
|
|
|
- } else if (entityInfo.firstName) {
|
|
|
|
|
- logData.name = `${entityInfo.firstName} ${entityInfo.lastName || ''}`.trim()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 记录用户名
|
|
|
|
|
- if (entityInfo.username) {
|
|
|
|
|
- logData.username = entityInfo.username
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- this.app.log.info(logData)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private async sendMessageToPeer(client: TelegramClient, targetPeer: any, message: string): Promise<any> {
|
|
private async sendMessageToPeer(client: TelegramClient, targetPeer: any, message: string): Promise<any> {
|
|
|
this.app.log.info('正在发送消息...')
|
|
this.app.log.info('正在发送消息...')
|
|
|
|
|
|
|
@@ -168,6 +165,35 @@ export class TgMsgSendService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private async clearConversation(client: TelegramClient, targetPeer: any): Promise<void> {
|
|
|
|
|
+ this.app.log.info('正在清除会话...')
|
|
|
|
|
+ try {
|
|
|
|
|
+ await client.invoke(
|
|
|
|
|
+ new Api.messages.DeleteHistory({
|
|
|
|
|
+ peer: targetPeer,
|
|
|
|
|
+ revoke: false
|
|
|
|
|
+ })
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const errorMessage = this.extractErrorMessage(error)
|
|
|
|
|
+ throw new Error(`清除会话失败: ${errorMessage}`)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private async deleteTempContact(client: TelegramClient, userId: number) {
|
|
|
|
|
+ this.app.log.info('正在删除临时联系人...')
|
|
|
|
|
+ try {
|
|
|
|
|
+ await client.invoke(
|
|
|
|
|
+ new Api.contacts.DeleteContacts({
|
|
|
|
|
+ id: [userId]
|
|
|
|
|
+ })
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const errorMessage = this.extractErrorMessage(error)
|
|
|
|
|
+ throw new Error(`删除临时联系人失败: ${errorMessage}`)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private async disconnectClient(client: TelegramClient | null): Promise<void> {
|
|
private async disconnectClient(client: TelegramClient | null): Promise<void> {
|
|
|
if (!client) {
|
|
if (!client) {
|
|
|
return
|
|
return
|
|
@@ -201,11 +227,11 @@ export class TgMsgSendService {
|
|
|
return '未知错误'
|
|
return '未知错误'
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private parseTargetId(targetId: string): string | number | null {
|
|
|
|
|
|
|
+ private parseTarget(targetId: string): string | number | null {
|
|
|
const trimmed = targetId.trim()
|
|
const trimmed = targetId.trim()
|
|
|
|
|
|
|
|
- // 用户名
|
|
|
|
|
- if (trimmed.startsWith('@')) {
|
|
|
|
|
|
|
+ // 用户名 手机号
|
|
|
|
|
+ if (trimmed.startsWith('@') || trimmed.startsWith('+')) {
|
|
|
return trimmed
|
|
return trimmed
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -217,4 +243,30 @@ export class TgMsgSendService {
|
|
|
|
|
|
|
|
return null
|
|
return null
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ private logTargetInfo(targetPeer: any): void {
|
|
|
|
|
+ const entityInfo = targetPeer as any
|
|
|
|
|
+ const logData: any = {
|
|
|
|
|
+ className: entityInfo.className || '未知'
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 记录 ID
|
|
|
|
|
+ if (entityInfo.id !== undefined) {
|
|
|
|
|
+ logData.id = entityInfo.id.toString()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 记录名称信息
|
|
|
|
|
+ if (entityInfo.title) {
|
|
|
|
|
+ logData.title = entityInfo.title
|
|
|
|
|
+ } else if (entityInfo.firstName) {
|
|
|
|
|
+ logData.name = `${entityInfo.firstName} ${entityInfo.lastName || ''}`.trim()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 记录用户名
|
|
|
|
|
+ if (entityInfo.username) {
|
|
|
|
|
+ logData.username = entityInfo.username
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.app.log.info(logData)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|