保存消息
SendMessageEvent
为了有效地存储和处理 Telegram 机器人接收到的消息,首先需要深入分析消息的 SendMessageEvent 数据结构,明确需要存储的关键信息。
关键字段
在示例 SendMessageEvent 数据中,以下字段对于消息处理和存储至关重要:
message.Message.data.Variant2.t1.BaseMessage:
id
: 消息唯一标识符。flags
: 消息标志位,指示消息的各种状态和属性。fromId.PeerUser.userId
: 发送者的用户 ID。peerId.PeerUser.userId
: 接收者的用户 ID。date
: 消息发送的时间戳。message
: 消息内容。entities
: 消息中的实体,如命令、链接等。
chat.PrivateChat.user.User.minData.BaseUser:
id
: 聊天中的另一位用户的 ID。firstName
: 用户的名字。lastName
: 用户的姓氏。username
: 用户的用户名。
chat.PrivateChat.selfUser.User.minData.BaseUser:
id
: 机器人的用户 ID。firstName
: 机器人的名字。username
: 机器人的用户名。
author.User.minData.BaseUser:
id
: 消息的作者 ID(机器人自身)。firstName
: 消息作者的名字。username
: 消息作者的用户名。
数据提取
基于上述分析,可以提取以下关键信息用于存储和后续处理:
- 消息 ID
- 发送者 ID
- 接收者 ID
- 消息内容
- 消息时间
- 消息类型(如命令、文本等)
- 用户信息(发送者和接收者的基本信息)
数据库表设计
为了高效地存储和查询 Telegram 消息数据,设计一个合理的数据库表结构至关重要。以下是一个推荐的数据库表设计方案。
创表语句
drop table if exists telegram_bot_messages;
CREATE TABLE telegram_bot_messages (
id BIGINT PRIMARY KEY,
from_id BIGINT NOT NULL,
to_id BIGINT NOT NULL,
message_text TEXT NOT NULL,
message_date TIMESTAMP NOT NULL,
message_type VARCHAR(50) NOT NULL,
entities JSONB,
from_username VARCHAR(100),
from_first_name VARCHAR(100),
from_last_name VARCHAR(100),
to_username VARCHAR(100),
to_first_name VARCHAR(100),
to_last_name VARCHAR(100),
create_time TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
tenant_id BIGINT NOT NULL DEFAULT 0
);
表结构:telegram_messages
字段名 | 数据类型 | 描述 | 约束 |
---|---|---|---|
id | BIGINT | 消息 id | PRIMARY KEY |
from_id | BIGINT | 发送者的用户 ID | NOT NULL |
to_id | BIGINT | 接收者的用户 ID | NOT NULL |
sequence | BIGINT | 序列 id | NOT NULL |
message_text | TEXT | 消息内容 | NOT NULL |
message_date | TIMESTAMP | 消息发送的时间 | NOT NULL |
message_type | VARCHAR(50) | 消息类型(如文本、命令等) | NOT NULL |
entities | SendMessageEvent | 消息中的实体(如命令、链接等) | NULLABLE |
from_username | VARCHAR(100) | 发送者的用户名 | NULLABLE |
from_first_name | VARCHAR(100) | 发送者的名字 | NULLABLE |
from_last_name | VARCHAR(100) | 发送者的姓氏 | NULLABLE |
to_username | VARCHAR(100) | 接收者的用户名 | NULLABLE |
to_first_name | VARCHAR(100) | 接收者的名字 | NULLABLE |
to_last_name | VARCHAR(100) | 接收者的姓氏 | NULLABLE |
create_time | TIMESTAMP | 记录创建时间 | DEFAULT CURRENT_TIMESTAMP |
字段说明
id
: 消息的唯一标识符,用于唯一标识每条消息。from_id
: 发送者的用户 ID,用于关联用户信息。to_id
: 接收者的用户 ID,可以是另一个用户或机器人自身。sequence
: 消息序列。message_text
: 存储消息的具体内容。message_date
: 消息发送的时间,便于按时间排序和查询。message_type
: 消息的类型,如文本消息、命令、媒体消息等。entities
: 以 SendMessageEvent 格式存储消息中的实体信息,如命令、链接等,便于后续解析和处理。from_username
、from_first_name
、from_last_name
: 发送者的基本信息,便于快速查看和展示。to_username
、to_first_name
、to_last_name
: 接收者的基本信息,便于快速查看和展示。create_time
: 记录数据插入的时间,便于审计和数据管理。
数据存储实现
在完成数据库表设计后,下一步是实现将接收到的 SendMessageEvent 消息数据存储到数据库中。以下是实现步骤和代码示例。
依赖库
确保项目中包含以下依赖库:
- 数据库连接:java-db。
- SendMessageEvent 解析:手动解析。
- 数据库驱动:根据所选数据库,添加相应的驱动依赖。
数据模型
定义一个与数据库表 telegram_messages
对应的实体类。
package com.litongjava.gpt.translator.vo;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TelegramMessage {
private Long id;
private Long fromId;
private Long toId;
private String messageText;
private LocalDateTime messageDate;
private String messageType;
private String entities;
private String fromUsername;
private String fromFirstName;
private String fromLastName;
private String toUsername;
private String toFirstName;
private String toLastName;
private LocalDateTime create_time;
}
数据存储逻辑
在消息处理流程中,将接收到的消息数据转换为 TelegramMessage
实体并保存到数据库。
package com.litongjava.gpt.translator.services;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import com.fasterxml.jackson.databind.SendMessageEventNode;
import com.litongjava.gpt.translator.vo.TelegramMessage;
import telegram4j.core.event.domain.message.SendMessageEvent;
public class SendMessageEventService {
private TelegramMessage extracted(SendMessageEvent event) {
TelegramMessage message = new TelegramMessage();
// 提取消息基本信息
event.getMessage().getId()
message.setId(event.getMessageId().asLong());
message.setFromId(event.getAuthor().get().getId().asLong());
message.setToId(event.getChat().getId().asLong());
message.setMessageText(event.getMessage().getContent());
Instant instant = Instant.ofEpochSecond(event.getMessage().getDate());
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
message.setMessageDate(dateTime);
message.setMessageType(determineMessageType(event));
// 提取实体信息
SendMessageEventNode entitiesNode = objectMapper.valueToTree(event.getMessage().getEntities());
message.setEntities(entitiesNode.toString());
// 提取发送者信息
message.setFromUsername(event.getAuthor().get().getUsername().orElse(null));
message.setFromFirstName(event.getAuthor().get().getFirstName().orElse(null));
message.setFromLastName(event.getAuthor().get().getLastName().orElse(null));
// 提取接收者信息
// 需要根据具体业务逻辑填充接收者信息
// 这里只是一个示例
message.setToUsername(null);
message.setToFirstName(null);
message.setToLastName(null);
return message;
}
private String determineMessageType(SendMessageEvent event) {
// 根据消息内容或其他属性确定消息类型
// 这里只是一个简单的示例
if (event.getMessage().getEntities().stream().anyMatch(entity -> entity instanceof telegram4j.core.object.MessageEntity.BotCommand)) {
return "command";
}
return "text";
}
}
代码说明
- 依赖注入:注入
TelegramMessageRepository
以进行数据库操作。 - SendMessageEvent 解析:使用 Jackson 的
ObjectMapper
将消息中的实体信息转换为 SendMessageEvent 字符串。 - 消息转换:
- 提取消息的基本信息,如 ID、发送者 ID、接收者 ID、消息内容、时间戳等。
- 根据消息内容中的实体信息确定消息类型(如命令、文本等)。
- 提取发送者的用户名、名字和姓氏。
- 根据具体业务逻辑提取接收者的相关信息。
- 数据保存:将转换后的
TelegramMessage
实体保存到数据库中。