510 行
16 KiB
PHP
510 行
16 KiB
PHP
<?php
|
|
// 引入数据库模块和用户模块
|
|
require_once __DIR__ . '/../db.php';
|
|
require_once __DIR__ . '/user.php';
|
|
|
|
// 格式化时间
|
|
function formatTime($timestamp) {
|
|
return date('H:i', $timestamp);
|
|
}
|
|
|
|
// 发送消息
|
|
function sendMessage($senderId, $receiverId, $content, $isImage = false, $quote = null, $isGroup = false) {
|
|
$db = Database::getInstance();
|
|
|
|
// 创建新消息
|
|
$newMessage = [
|
|
'id' => generateId(),
|
|
'sender_id' => $senderId,
|
|
'receiver_id' => $receiverId,
|
|
'content' => $content,
|
|
'is_image' => $isImage ? 1 : 0,
|
|
'is_group' => $isGroup ? 1 : 0,
|
|
'timestamp' => getCurrentTimestamp(),
|
|
'read' => 0,
|
|
'delivered' => 0,
|
|
'recalled' => 0
|
|
];
|
|
|
|
// 插入新消息
|
|
$sql = "INSERT INTO messages (id, sender_id, receiver_id, content, timestamp, read, delivered, is_image, is_group, recalled)
|
|
VALUES (:id, :sender_id, :receiver_id, :content, :timestamp, :read, :delivered, :is_image, :is_group, :recalled)";
|
|
|
|
$db->execute($sql, $newMessage);
|
|
|
|
// 添加引用消息信息
|
|
if ($quote) {
|
|
$db->execute("INSERT INTO message_quotes (message_id, sender, content, quoted_message_id)
|
|
VALUES (:message_id, :sender, :content, :quoted_message_id)", [
|
|
'message_id' => $newMessage['id'],
|
|
'sender' => $quote['sender'],
|
|
'content' => $quote['content'],
|
|
'quoted_message_id' => isset($quote['message_id']) ? $quote['message_id'] : null
|
|
]);
|
|
}
|
|
|
|
// 检查是否是向Parlz官方发送消息
|
|
$systemUserId = 100000;
|
|
if ($receiverId == $systemUserId && !$isImage) {
|
|
// 立即发送一条"正在处理..."的消息给用户
|
|
$db = Database::getInstance();
|
|
|
|
$processingMessage = [
|
|
'id' => generateId(),
|
|
'sender_id' => $systemUserId,
|
|
'receiver_id' => $senderId,
|
|
'content' => '正在处理您的消息,请稍候...',
|
|
'is_image' => 0,
|
|
'is_group' => 0,
|
|
'timestamp' => getCurrentTimestamp(),
|
|
'read' => 0,
|
|
'delivered' => 0,
|
|
'recalled' => 0
|
|
];
|
|
|
|
// 插入正在处理的消息
|
|
$sql = "INSERT INTO messages (id, sender_id, receiver_id, content, timestamp, read, delivered, is_image, is_group, recalled)
|
|
VALUES (:id, :sender_id, :receiver_id, :content, :timestamp, :read, :delivered, :is_image, :is_group, :recalled)";
|
|
|
|
$db->execute($sql, $processingMessage);
|
|
|
|
// 同步处理系统消息回复,便于调试
|
|
// 记录开始处理消息
|
|
file_put_contents(__DIR__ . '/../logs/ai_error.log', date('Y-m-d H:i:s') . ' - 开始处理消息: ' . addslashes($content) . '\n', FILE_APPEND);
|
|
|
|
// 处理消息
|
|
$result = handleSystemMessageReply($senderId, $content);
|
|
|
|
// 记录处理结果
|
|
file_put_contents(__DIR__ . '/../logs/ai_error.log', date('Y-m-d H:i:s') . ' - 处理结果: ' . ($result ? '成功' : '失败') . '\n', FILE_APPEND);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// 获取聊天历史(支持私聊和群聊)
|
|
function getChatHistory($userId, $targetId, $page = 1, $limit = 20, $olderThan = null, $isGroup = false) {
|
|
$db = Database::getInstance();
|
|
|
|
// 计算偏移量
|
|
$offset = ($page - 1) * $limit;
|
|
|
|
// 构建查询
|
|
if ($isGroup) {
|
|
// 群组聊天:获取所有发送到该群组的消息
|
|
$sql = "SELECT * FROM messages WHERE receiver_id = :targetId AND is_group = 1 ORDER BY timestamp DESC LIMIT :limit OFFSET :offset";
|
|
$params = [
|
|
'targetId' => $targetId,
|
|
'limit' => $limit,
|
|
'offset' => $offset
|
|
];
|
|
|
|
// 获取总数
|
|
$totalResult = $db->query("SELECT COUNT(*) as total FROM messages WHERE receiver_id = :targetId AND is_group = 1", ['targetId' => $targetId]);
|
|
} else {
|
|
// 私聊:获取两个用户之间的消息
|
|
$sql = "SELECT * FROM messages WHERE (sender_id = :userId AND receiver_id = :targetId) OR
|
|
(sender_id = :targetId AND receiver_id = :userId) ORDER BY timestamp DESC LIMIT :limit OFFSET :offset";
|
|
$params = [
|
|
'userId' => $userId,
|
|
'targetId' => $targetId,
|
|
'limit' => $limit,
|
|
'offset' => $offset
|
|
];
|
|
|
|
// 获取总数
|
|
$totalResult = $db->query("SELECT COUNT(*) as total FROM messages WHERE (sender_id = :userId AND receiver_id = :targetId) OR
|
|
(sender_id = :targetId AND receiver_id = :userId)", [
|
|
'userId' => $userId,
|
|
'targetId' => $targetId
|
|
]);
|
|
}
|
|
|
|
// 执行查询
|
|
$pagedMessages = $db->query($sql, $params);
|
|
$total = !empty($totalResult) ? $totalResult[0]['total'] : 0;
|
|
|
|
if (empty($pagedMessages)) {
|
|
return [
|
|
'messages' => [],
|
|
'total' => $total,
|
|
'page' => $page,
|
|
'limit' => $limit,
|
|
'hasMore' => $offset + $limit < $total
|
|
];
|
|
}
|
|
|
|
// 收集需要的用户ID和消息ID
|
|
$userIds = [];
|
|
$messageIds = [];
|
|
foreach ($pagedMessages as $message) {
|
|
$messageIds[] = $message['id'];
|
|
if ($isGroup && $message['sender_id'] !== $userId) {
|
|
$userIds[] = $message['sender_id'];
|
|
}
|
|
}
|
|
|
|
// 批量获取用户信息
|
|
$usersMap = [];
|
|
if (!empty($userIds)) {
|
|
$userIds = array_unique($userIds);
|
|
$placeholders = [];
|
|
$userParams = [];
|
|
foreach ($userIds as $index => $id) {
|
|
$key = 'id' . $index;
|
|
$placeholders[] = ':' . $key;
|
|
$userParams[$key] = $id;
|
|
}
|
|
|
|
$userSql = "SELECT * FROM users WHERE id IN (" . implode(',', $placeholders) . ")";
|
|
$users = $db->query($userSql, $userParams);
|
|
foreach ($users as $user) {
|
|
$usersMap[$user['id']] = $user;
|
|
}
|
|
}
|
|
|
|
// 批量获取引用信息
|
|
$quotesMap = [];
|
|
if (!empty($messageIds)) {
|
|
$placeholders = [];
|
|
$quoteParams = [];
|
|
foreach ($messageIds as $index => $id) {
|
|
$key = 'id' . $index;
|
|
$placeholders[] = ':' . $key;
|
|
$quoteParams[$key] = $id;
|
|
}
|
|
|
|
$quoteSql = "SELECT * FROM message_quotes WHERE message_id IN (" . implode(',', $placeholders) . ")";
|
|
$quotes = $db->query($quoteSql, $quoteParams);
|
|
foreach ($quotes as $quote) {
|
|
$quotesMap[$quote['message_id']] = $quote;
|
|
}
|
|
}
|
|
|
|
// 按时间正序排序(显示时按时间顺序)
|
|
usort($pagedMessages, function($a, $b) {
|
|
return $a['timestamp'] - $b['timestamp'];
|
|
});
|
|
|
|
// 格式化消息
|
|
$formattedMessages = [];
|
|
foreach ($pagedMessages as $message) {
|
|
$formattedMessage = [
|
|
'id' => $message['id'],
|
|
'sender_id' => $message['sender_id'],
|
|
'sender' => $message['sender_id'] === $userId ? 'me' : 'other',
|
|
'content' => $message['content'],
|
|
'is_image' => $message['is_image'] === 1,
|
|
'is_group' => $message['is_group'] === 1,
|
|
'recalled' => $message['recalled'] === 1,
|
|
'read' => $message['read'] === 1,
|
|
'delivered' => $message['delivered'] === 1,
|
|
'time' => formatTime($message['timestamp']),
|
|
'timestamp' => $message['timestamp']
|
|
];
|
|
|
|
// 在群组消息中添加发送者名称和头像
|
|
if ($isGroup && $message['sender_id'] !== $userId && isset($usersMap[$message['sender_id']])) {
|
|
$senderUser = $usersMap[$message['sender_id']];
|
|
$formattedMessage['sender_name'] = $senderUser['username'];
|
|
$formattedMessage['sender_avatar'] = isset($senderUser['avatar']) ? $senderUser['avatar'] : '';
|
|
}
|
|
|
|
// 添加引用消息信息
|
|
if (isset($quotesMap[$message['id']])) {
|
|
$quote = $quotesMap[$message['id']];
|
|
$formattedMessage['quote'] = [
|
|
'sender' => $quote['sender'],
|
|
'content' => $quote['content'],
|
|
'message_id' => $quote['quoted_message_id']
|
|
];
|
|
}
|
|
|
|
$formattedMessages[] = $formattedMessage;
|
|
}
|
|
|
|
return [
|
|
'messages' => $formattedMessages,
|
|
'total' => $total,
|
|
'page' => $page,
|
|
'limit' => $limit,
|
|
'hasMore' => $offset + $limit < $total
|
|
];
|
|
}
|
|
|
|
// 获取用户的所有未读消息
|
|
function getUnreadMessages($userId) {
|
|
$db = Database::getInstance();
|
|
|
|
$result = $db->query("SELECT * FROM messages WHERE receiver_id = :userId AND read = 0", ['userId' => $userId]);
|
|
|
|
return $result;
|
|
}
|
|
|
|
// 标记消息为已读
|
|
function markMessagesAsRead($userId, $senderId) {
|
|
$db = Database::getInstance();
|
|
|
|
$sql = "UPDATE messages SET read = 1 WHERE receiver_id = :userId AND sender_id = :senderId AND read = 0";
|
|
|
|
return $db->execute($sql, [
|
|
'userId' => $userId,
|
|
'senderId' => $senderId
|
|
]);
|
|
}
|
|
|
|
// 标记消息为已送达
|
|
function markMessagesAsDelivered($userId, $senderId) {
|
|
$db = Database::getInstance();
|
|
|
|
$sql = "UPDATE messages SET delivered = 1 WHERE receiver_id = :userId AND sender_id = :senderId AND delivered = 0";
|
|
|
|
return $db->execute($sql, [
|
|
'userId' => $userId,
|
|
'senderId' => $senderId
|
|
]);
|
|
}
|
|
|
|
// 获取用户的最新消息
|
|
function getLatestMessages($userId, $limit = 10) {
|
|
$db = Database::getInstance();
|
|
|
|
$result = $db->query("SELECT * FROM messages WHERE sender_id = :userId OR receiver_id = :userId ORDER BY timestamp DESC LIMIT :limit", [
|
|
'userId' => $userId,
|
|
'limit' => $limit
|
|
]);
|
|
|
|
return $result;
|
|
}
|
|
|
|
// 删除消息
|
|
function deleteMessage($messageId) {
|
|
$db = Database::getInstance();
|
|
|
|
// 删除消息引用
|
|
$db->execute("DELETE FROM message_quotes WHERE message_id = :message_id", ['message_id' => $messageId]);
|
|
|
|
// 删除消息
|
|
return $db->execute("DELETE FROM messages WHERE id = :message_id", ['message_id' => $messageId]);
|
|
}
|
|
|
|
// 撤回消息
|
|
function recallMessage($senderId, $receiverId, $content, $isGroup = false, $messageId = '') {
|
|
$db = Database::getInstance();
|
|
$updated = false;
|
|
|
|
// 如果提供了消息ID,使用消息ID匹配
|
|
if ($messageId) {
|
|
$result = $db->execute("UPDATE messages SET recalled = 1 WHERE id = :messageId AND sender_id = :senderId", [
|
|
'messageId' => $messageId,
|
|
'senderId' => $senderId
|
|
]);
|
|
$updated = $result;
|
|
} else {
|
|
// 否则使用内容匹配
|
|
$result = $db->execute("UPDATE messages SET recalled = 1 WHERE sender_id = :senderId AND receiver_id = :receiverId AND content = :content AND is_group = :isGroup", [
|
|
'senderId' => $senderId,
|
|
'receiverId' => $receiverId,
|
|
'content' => $content,
|
|
'isGroup' => $isGroup ? 1 : 0
|
|
]);
|
|
$updated = $result;
|
|
}
|
|
|
|
return $updated;
|
|
}
|
|
|
|
// 举报消息
|
|
function reportMessage($messageId, $reporterId, $reason = '') {
|
|
$db = Database::getInstance();
|
|
|
|
// 检查消息是否存在
|
|
$message = $db->query("SELECT * FROM messages WHERE id = :message_id", ['message_id' => $messageId]);
|
|
if (empty($message)) {
|
|
return false;
|
|
}
|
|
|
|
// 检查是否已经举报过
|
|
$existingReport = $db->query("SELECT * FROM reports WHERE message_id = :message_id AND reporter_id = :reporter_id", [
|
|
'message_id' => $messageId,
|
|
'reporter_id' => $reporterId
|
|
]);
|
|
if (!empty($existingReport)) {
|
|
return false;
|
|
}
|
|
|
|
// 创建新举报
|
|
$newReport = [
|
|
'id' => generateId(),
|
|
'message_id' => $messageId,
|
|
'reporter_id' => $reporterId,
|
|
'reason' => $reason,
|
|
'status' => 'pending',
|
|
'created_at' => getCurrentTimestamp()
|
|
];
|
|
|
|
// 插入新举报
|
|
$sql = "INSERT INTO reports (id, message_id, reporter_id, reason, status, created_at)
|
|
VALUES (:id, :message_id, :reporter_id, :reason, :status, :created_at)";
|
|
|
|
return $db->execute($sql, $newReport);
|
|
}
|
|
|
|
// 获取所有举报
|
|
function getReports($status = null) {
|
|
$db = Database::getInstance();
|
|
|
|
if ($status) {
|
|
$result = $db->query("SELECT * FROM reports WHERE status = :status ORDER BY created_at DESC", ['status' => $status]);
|
|
} else {
|
|
$result = $db->query("SELECT * FROM reports ORDER BY created_at DESC");
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
// 获取举报详情
|
|
function getReportById($reportId) {
|
|
$db = Database::getInstance();
|
|
|
|
$result = $db->query("SELECT * FROM reports WHERE id = :id", ['id' => $reportId]);
|
|
|
|
return !empty($result) ? $result[0] : null;
|
|
}
|
|
|
|
// 处理举报
|
|
function processReport($reportId, $adminId, $action, $reason = '') {
|
|
$db = Database::getInstance();
|
|
|
|
// 更新举报状态
|
|
$sql = "UPDATE reports SET status = :status, processed_by = :processed_by, processed_at = :processed_at WHERE id = :id";
|
|
|
|
$result = $db->execute($sql, [
|
|
'status' => $action,
|
|
'processed_by' => $adminId,
|
|
'processed_at' => getCurrentTimestamp(),
|
|
'id' => $reportId
|
|
]);
|
|
|
|
// 如果是删除消息
|
|
if ($action === 'deleted') {
|
|
$report = $db->query("SELECT message_id FROM reports WHERE id = :id", ['id' => $reportId]);
|
|
if (!empty($report)) {
|
|
deleteMessage($report[0]['message_id']);
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
// 获取举报的消息详情
|
|
function getReportedMessage($messageId) {
|
|
$db = Database::getInstance();
|
|
|
|
$result = $db->query("SELECT * FROM messages WHERE id = :id", ['id' => $messageId]);
|
|
|
|
if (empty($result)) {
|
|
return null;
|
|
}
|
|
|
|
$message = $result[0];
|
|
|
|
// 获取发送者信息
|
|
$sender = $db->query("SELECT * FROM users WHERE id = :id", ['id' => $message['sender_id']]);
|
|
if (!empty($sender)) {
|
|
$message['sender_info'] = $sender[0];
|
|
}
|
|
|
|
return $message;
|
|
}
|
|
|
|
// 发布系统公告
|
|
function publishSystemAnnouncement($title, $content) {
|
|
$db = Database::getInstance();
|
|
|
|
// 虚拟系统账户信息
|
|
$systemUserId = 100000;
|
|
$systemUsername = 'Parlz官方';
|
|
|
|
// 构建公告内容
|
|
$announcementContent = "【系统公告】$title\n\n$content";
|
|
|
|
// 获取所有用户
|
|
$users = $db->query("SELECT id FROM users");
|
|
|
|
// 向每个用户发送私信
|
|
foreach ($users as $user) {
|
|
$userId = $user['id'];
|
|
|
|
// 创建新消息
|
|
$newMessage = [
|
|
'id' => generateId(),
|
|
'sender_id' => $systemUserId,
|
|
'receiver_id' => $userId,
|
|
'content' => $announcementContent,
|
|
'is_image' => 0,
|
|
'is_group' => 0,
|
|
'timestamp' => getCurrentTimestamp(),
|
|
'read' => 0,
|
|
'delivered' => 0,
|
|
'recalled' => 0
|
|
];
|
|
|
|
// 插入新消息
|
|
$sql = "INSERT INTO messages (id, sender_id, receiver_id, content, timestamp, read, delivered, is_image, is_group, recalled)
|
|
VALUES (:id, :sender_id, :receiver_id, :content, :timestamp, :read, :delivered, :is_image, :is_group, :recalled)";
|
|
|
|
$db->execute($sql, $newMessage);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// 获取系统用户信息(虚拟账户)
|
|
function getSystemUser() {
|
|
return [
|
|
'id' => 100000,
|
|
'username' => 'Parlz官方',
|
|
'avatar' => '',
|
|
'is_admin' => true,
|
|
'is_banned' => false
|
|
];
|
|
}
|
|
|
|
// 处理用户向Parlz官方发送消息的自动回复
|
|
function handleSystemMessageReply($senderId, $content) {
|
|
$systemUserId = 100000;
|
|
$systemUsername = 'Parlz官方';
|
|
|
|
// 加载本地AI模型
|
|
require_once __DIR__ . '/local_ai.php';
|
|
$localAI = new LocalAI();
|
|
|
|
// 使用本地AI模型生成回复
|
|
$replyContent = $localAI->generateReply($content);
|
|
|
|
// 发送回复消息
|
|
$db = Database::getInstance();
|
|
|
|
$newMessage = [
|
|
'id' => generateId(),
|
|
'sender_id' => $systemUserId,
|
|
'receiver_id' => $senderId,
|
|
'content' => $replyContent,
|
|
'is_image' => 0,
|
|
'is_group' => 0,
|
|
'timestamp' => getCurrentTimestamp(),
|
|
'read' => 0,
|
|
'delivered' => 0,
|
|
'recalled' => 0
|
|
];
|
|
|
|
// 插入新消息
|
|
$sql = "INSERT INTO messages (id, sender_id, receiver_id, content, timestamp, read, delivered, is_image, is_group, recalled)
|
|
VALUES (:id, :sender_id, :receiver_id, :content, :timestamp, :read, :delivered, :is_image, :is_group, :recalled)";
|
|
|
|
$db->execute($sql, $newMessage);
|
|
|
|
return true;
|
|
}
|
|
?>
|