mirror of
https://github.com/ctwj/urldb.git
synced 2025-11-25 03:15:04 +08:00
update: 添加tg调试代码
This commit is contained in:
@@ -511,6 +511,27 @@ func (h *TelegramHandler) GetTelegramLogStats(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ManualPushToChannel 手动推送到频道
|
||||||
|
func (h *TelegramHandler) ManualPushToChannel(c *gin.Context) {
|
||||||
|
idStr := c.Param("id")
|
||||||
|
channelID, err := strconv.ParseUint(idStr, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
ErrorResponse(c, "无效的频道ID", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.telegramBotService.ManualPushToChannel(uint(channelID))
|
||||||
|
if err != nil {
|
||||||
|
ErrorResponse(c, "手动推送失败: "+err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
SuccessResponse(c, map[string]interface{}{
|
||||||
|
"success": true,
|
||||||
|
"message": "手动推送请求已提交",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// ClearTelegramLogs 清理旧的Telegram日志
|
// ClearTelegramLogs 清理旧的Telegram日志
|
||||||
func (h *TelegramHandler) ClearTelegramLogs(c *gin.Context) {
|
func (h *TelegramHandler) ClearTelegramLogs(c *gin.Context) {
|
||||||
daysStr := c.DefaultQuery("days", "30")
|
daysStr := c.DefaultQuery("days", "30")
|
||||||
|
|||||||
1
main.go
1
main.go
@@ -435,6 +435,7 @@ func main() {
|
|||||||
api.GET("/telegram/logs/stats", middleware.AuthMiddleware(), middleware.AdminMiddleware(), telegramHandler.GetTelegramLogStats)
|
api.GET("/telegram/logs/stats", middleware.AuthMiddleware(), middleware.AdminMiddleware(), telegramHandler.GetTelegramLogStats)
|
||||||
api.POST("/telegram/logs/clear", middleware.AuthMiddleware(), middleware.AdminMiddleware(), telegramHandler.ClearTelegramLogs)
|
api.POST("/telegram/logs/clear", middleware.AuthMiddleware(), middleware.AdminMiddleware(), telegramHandler.ClearTelegramLogs)
|
||||||
api.POST("/telegram/webhook", telegramHandler.HandleWebhook)
|
api.POST("/telegram/webhook", telegramHandler.HandleWebhook)
|
||||||
|
api.POST("/telegram/manual-push/:id", middleware.AuthMiddleware(), middleware.AdminMiddleware(), telegramHandler.ManualPushToChannel)
|
||||||
|
|
||||||
// 微信公众号相关路由
|
// 微信公众号相关路由
|
||||||
wechatHandler := handlers.NewWechatHandler(
|
wechatHandler := handlers.NewWechatHandler(
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ type TelegramBotService interface {
|
|||||||
IsChannelRegistered(chatID int64) bool
|
IsChannelRegistered(chatID int64) bool
|
||||||
HandleWebhookUpdate(c interface{})
|
HandleWebhookUpdate(c interface{})
|
||||||
CleanupDuplicateChannels() error
|
CleanupDuplicateChannels() error
|
||||||
|
ManualPushToChannel(channelID uint) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type TelegramBotServiceImpl struct {
|
type TelegramBotServiceImpl struct {
|
||||||
@@ -1072,6 +1073,10 @@ func (s *TelegramBotServiceImpl) findResourcesForChannel(channel entity.Telegram
|
|||||||
func (s *TelegramBotServiceImpl) findLatestResources(channel entity.TelegramChannel, excludeResourceIDs []uint) []interface{} {
|
func (s *TelegramBotServiceImpl) findLatestResources(channel entity.TelegramChannel, excludeResourceIDs []uint) []interface{} {
|
||||||
params := s.buildFilterParams(channel)
|
params := s.buildFilterParams(channel)
|
||||||
|
|
||||||
|
// 添加按创建时间倒序的排序参数,确保获取最新资源
|
||||||
|
params["order_by"] = "created_at"
|
||||||
|
params["order_dir"] = "DESC"
|
||||||
|
|
||||||
// 在数据库查询中排除已推送的资源
|
// 在数据库查询中排除已推送的资源
|
||||||
if len(excludeResourceIDs) > 0 {
|
if len(excludeResourceIDs) > 0 {
|
||||||
params["exclude_ids"] = excludeResourceIDs
|
params["exclude_ids"] = excludeResourceIDs
|
||||||
@@ -1330,15 +1335,23 @@ func (s *TelegramBotServiceImpl) SendMessage(chatID int64, text string, img stri
|
|||||||
} else {
|
} else {
|
||||||
// 如果 img 以 http 开头,则为图片URL,否则为文件remote_id
|
// 如果 img 以 http 开头,则为图片URL,否则为文件remote_id
|
||||||
if strings.HasPrefix(img, "http") {
|
if strings.HasPrefix(img, "http") {
|
||||||
// 发送图片URL
|
// 发送图片URL前先验证URL是否可访问并返回有效的图片格式
|
||||||
photoMsg := tgbotapi.NewPhoto(chatID, tgbotapi.FileURL(img))
|
if s.isValidImageURL(img) {
|
||||||
photoMsg.Caption = text
|
photoMsg := tgbotapi.NewPhoto(chatID, tgbotapi.FileURL(img))
|
||||||
photoMsg.ParseMode = "HTML"
|
photoMsg.Caption = text
|
||||||
_, err := s.bot.Send(photoMsg)
|
photoMsg.ParseMode = "HTML"
|
||||||
if err != nil {
|
_, err := s.bot.Send(photoMsg)
|
||||||
utils.Error("[TELEGRAM:MESSAGE:ERROR] 发送图片消息失败: %v", err)
|
if err != nil {
|
||||||
|
utils.Error("[TELEGRAM:MESSAGE:ERROR] 发送图片消息失败: %v", err)
|
||||||
|
// 如果URL方式失败,尝试将URL作为普通文本发送
|
||||||
|
return s.sendTextMessage(chatID, text)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
utils.Warn("[TELEGRAM:MESSAGE:WARNING] 图片URL无效,仅发送文本消息: %s", img)
|
||||||
|
// URL无效时只发送文本消息
|
||||||
|
return s.sendTextMessage(chatID, text)
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
} else {
|
} else {
|
||||||
// imgUrl := s.GetImgUrl(img)
|
// imgUrl := s.GetImgUrl(img)
|
||||||
//todo 判断 imgUrl 是否可用
|
//todo 判断 imgUrl 是否可用
|
||||||
@@ -1349,12 +1362,85 @@ func (s *TelegramBotServiceImpl) SendMessage(chatID int64, text string, img stri
|
|||||||
_, err := s.bot.Send(photoMsg)
|
_, err := s.bot.Send(photoMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Error("[TELEGRAM:MESSAGE:ERROR] 发送图片消息失败: %v", err)
|
utils.Error("[TELEGRAM:MESSAGE:ERROR] 发送图片消息失败: %v", err)
|
||||||
|
// 如果文件ID方式失败,尝试将URL作为普通文本发送
|
||||||
|
return s.sendTextMessage(chatID, text)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isValidImageURL 验证图片URL是否有效
|
||||||
|
func (s *TelegramBotServiceImpl) isValidImageURL(imageURL string) bool {
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果配置了代理,设置代理
|
||||||
|
if s.config.ProxyEnabled && s.config.ProxyHost != "" {
|
||||||
|
var proxyClient *http.Client
|
||||||
|
if s.config.ProxyType == "socks5" {
|
||||||
|
auth := &proxy.Auth{}
|
||||||
|
if s.config.ProxyUsername != "" {
|
||||||
|
auth.User = s.config.ProxyUsername
|
||||||
|
auth.Password = s.config.ProxyPassword
|
||||||
|
}
|
||||||
|
dialer, proxyErr := proxy.SOCKS5("tcp", fmt.Sprintf("%s:%d", s.config.ProxyHost, s.config.ProxyPort), auth, proxy.Direct)
|
||||||
|
if proxyErr != nil {
|
||||||
|
utils.Warn("[TELEGRAM:IMAGE] 代理配置错误: %v", proxyErr)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
proxyClient = &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
Dial: dialer.Dial,
|
||||||
|
},
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proxyURL := &url.URL{
|
||||||
|
Scheme: s.config.ProxyType,
|
||||||
|
Host: fmt.Sprintf("%s:%d", s.config.ProxyHost, s.config.ProxyPort),
|
||||||
|
}
|
||||||
|
if s.config.ProxyUsername != "" {
|
||||||
|
proxyURL.User = url.UserPassword(s.config.ProxyUsername, s.config.ProxyPassword)
|
||||||
|
}
|
||||||
|
proxyClient = &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
Proxy: http.ProxyURL(proxyURL),
|
||||||
|
},
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client = proxyClient
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Head(imageURL)
|
||||||
|
if err != nil {
|
||||||
|
utils.Warn("[TELEGRAM:IMAGE] 检查图片URL失败: %v, URL: %s", err, imageURL)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 检查Content-Type是否为图片格式
|
||||||
|
contentType := resp.Header.Get("Content-Type")
|
||||||
|
isImage := strings.HasPrefix(contentType, "image/")
|
||||||
|
if !isImage {
|
||||||
|
utils.Warn("[TELEGRAM:IMAGE] URL不是图片格式: %s, Content-Type: %s", imageURL, contentType)
|
||||||
|
}
|
||||||
|
return isImage
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendTextMessage 仅发送文本消息的辅助方法
|
||||||
|
func (s *TelegramBotServiceImpl) sendTextMessage(chatID int64, text string) error {
|
||||||
|
msg := tgbotapi.NewMessage(chatID, text)
|
||||||
|
msg.ParseMode = "HTML"
|
||||||
|
_, err := s.bot.Send(msg)
|
||||||
|
if err != nil {
|
||||||
|
utils.Error("[TELEGRAM:MESSAGE:ERROR] 发送文本消息失败: %v", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteMessage 删除消息
|
// DeleteMessage 删除消息
|
||||||
func (s *TelegramBotServiceImpl) DeleteMessage(chatID int64, messageID int) error {
|
func (s *TelegramBotServiceImpl) DeleteMessage(chatID int64, messageID int) error {
|
||||||
if s.bot == nil {
|
if s.bot == nil {
|
||||||
@@ -2017,3 +2103,25 @@ func (s *TelegramBotServiceImpl) isChannelInPushTimeRange(channel entity.Telegra
|
|||||||
return currentTime >= startTime || currentTime <= endTime
|
return currentTime >= startTime || currentTime <= endTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ManualPushToChannel 手动推送内容到指定频道
|
||||||
|
func (s *TelegramBotServiceImpl) ManualPushToChannel(channelID uint) error {
|
||||||
|
// 获取指定频道信息
|
||||||
|
channel, err := s.channelRepo.FindByID(channelID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("找不到指定的频道: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.Info("[TELEGRAM:MANUAL_PUSH] 开始手动推送到频道: %s (ID: %d)", channel.ChatName, channel.ChatID)
|
||||||
|
|
||||||
|
// 检查频道是否启用推送
|
||||||
|
if !channel.PushEnabled {
|
||||||
|
return fmt.Errorf("频道 %s 未启用推送功能", channel.ChatName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 推送内容到频道,使用频道配置的策略
|
||||||
|
s.pushToChannel(*channel)
|
||||||
|
|
||||||
|
utils.Info("[TELEGRAM:MANUAL_PUSH] 手动推送请求已提交: %s (ID: %d)", channel.ChatName, channel.ChatID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -279,6 +279,16 @@
|
|||||||
<n-tag :type="channel.is_active ? 'success' : 'warning'" size="small">
|
<n-tag :type="channel.is_active ? 'success' : 'warning'" size="small">
|
||||||
{{ channel.is_active ? '活跃' : '非活跃' }}
|
{{ channel.is_active ? '活跃' : '非活跃' }}
|
||||||
</n-tag>
|
</n-tag>
|
||||||
|
<n-button
|
||||||
|
v-if="channel.push_enabled"
|
||||||
|
size="small"
|
||||||
|
@click="manualPushToChannel(channel)"
|
||||||
|
:loading="manualPushingChannel === channel.id"
|
||||||
|
title="手动推送">
|
||||||
|
<template #icon>
|
||||||
|
<i class="fas fa-paper-plane"></i>
|
||||||
|
</template>
|
||||||
|
</n-button>
|
||||||
<n-button size="small" @click="editChannel(channel)">
|
<n-button size="small" @click="editChannel(channel)">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
@@ -715,6 +725,8 @@ const loadingLogs = ref(false)
|
|||||||
const logHours = ref(24)
|
const logHours = ref(24)
|
||||||
const editingChannel = ref<any>(null)
|
const editingChannel = ref<any>(null)
|
||||||
const savingChannel = ref(false)
|
const savingChannel = ref(false)
|
||||||
|
const testingPush = ref(false)
|
||||||
|
const manualPushingChannel = ref<number | null>(null)
|
||||||
|
|
||||||
// 机器人状态相关变量
|
// 机器人状态相关变量
|
||||||
const botStatus = ref<any>(null)
|
const botStatus = ref<any>(null)
|
||||||
@@ -1469,6 +1481,55 @@ const refreshBotStatus = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 手动推送内容到频道
|
||||||
|
const manualPushToChannel = async (channel: any) => {
|
||||||
|
if (!channel || !channel.id) {
|
||||||
|
notification.warning({
|
||||||
|
content: '频道信息不完整',
|
||||||
|
duration: 2000
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!telegramBotConfig.value.bot_enabled) {
|
||||||
|
notification.warning({
|
||||||
|
content: '请先启用机器人并配置API Key',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
manualPushingChannel.value = channel.id
|
||||||
|
try {
|
||||||
|
await telegramApi.manualPushToChannel(channel.id)
|
||||||
|
|
||||||
|
notification.success({
|
||||||
|
content: `手动推送请求已提交至频道 "${channel.chat_name}"`,
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
|
||||||
|
// 更新频道推送时间
|
||||||
|
const updatedChannels = telegramChannels.value.map(c => {
|
||||||
|
if (c.id === channel.id) {
|
||||||
|
c.last_push_at = new Date().toISOString()
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
})
|
||||||
|
telegramChannels.value = updatedChannels
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('手动推送失败:', error)
|
||||||
|
notification.error({
|
||||||
|
content: `手动推送失败: ${error?.message || '请稍后重试'}`,
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
// 只有当当前频道ID与推送中的频道ID匹配时才清除状态
|
||||||
|
if (manualPushingChannel.value === channel.id) {
|
||||||
|
manualPushingChannel.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 调试机器人连接
|
// 调试机器人连接
|
||||||
const debugBotConnection = async () => {
|
const debugBotConnection = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ export const useTelegramApi = () => {
|
|||||||
const debugBotConnection = () => useApiFetch('/telegram/debug-connection').then(parseApiResponse)
|
const debugBotConnection = () => useApiFetch('/telegram/debug-connection').then(parseApiResponse)
|
||||||
const reloadBotConfig = () => useApiFetch('/telegram/reload-config', { method: 'POST' }).then(parseApiResponse)
|
const reloadBotConfig = () => useApiFetch('/telegram/reload-config', { method: 'POST' }).then(parseApiResponse)
|
||||||
const testBotMessage = (data: any) => useApiFetch('/telegram/test-message', { method: 'POST', body: data }).then(parseApiResponse)
|
const testBotMessage = (data: any) => useApiFetch('/telegram/test-message', { method: 'POST', body: data }).then(parseApiResponse)
|
||||||
|
const manualPushToChannel = (channelId: number) => useApiFetch(`/telegram/manual-push/${channelId}`, { method: 'POST' }).then(parseApiResponse)
|
||||||
const getChannels = () => useApiFetch('/telegram/channels').then(parseApiResponse)
|
const getChannels = () => useApiFetch('/telegram/channels').then(parseApiResponse)
|
||||||
const createChannel = (data: any) => useApiFetch('/telegram/channels', { method: 'POST', body: data }).then(parseApiResponse)
|
const createChannel = (data: any) => useApiFetch('/telegram/channels', { method: 'POST', body: data }).then(parseApiResponse)
|
||||||
const updateChannel = (id: number, data: any) => useApiFetch(`/telegram/channels/${id}`, { method: 'PUT', body: data }).then(parseApiResponse)
|
const updateChannel = (id: number, data: any) => useApiFetch(`/telegram/channels/${id}`, { method: 'PUT', body: data }).then(parseApiResponse)
|
||||||
@@ -320,6 +321,7 @@ export const useTelegramApi = () => {
|
|||||||
debugBotConnection,
|
debugBotConnection,
|
||||||
reloadBotConfig,
|
reloadBotConfig,
|
||||||
testBotMessage,
|
testBotMessage,
|
||||||
|
manualPushToChannel,
|
||||||
getChannels,
|
getChannels,
|
||||||
createChannel,
|
createChannel,
|
||||||
updateChannel,
|
updateChannel,
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export const useSystemConfigStore = defineStore('systemConfig', {
|
|||||||
this.error = null
|
this.error = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(`[SystemConfig] 开始获取配置 (force: ${force}, useAdminApi: ${useAdminApi})`)
|
// console.log(`[SystemConfig] 开始获取配置 (force: ${force}, useAdminApi: ${useAdminApi})`)
|
||||||
|
|
||||||
// 根据上下文选择API:管理员页面使用管理员API,其他页面使用公开API
|
// 根据上下文选择API:管理员页面使用管理员API,其他页面使用公开API
|
||||||
const apiUrl = useAdminApi ? '/system/config' : '/public/system-config'
|
const apiUrl = useAdminApi ? '/system/config' : '/public/system-config'
|
||||||
@@ -189,14 +189,14 @@ export const useSystemConfigStore = defineStore('systemConfig', {
|
|||||||
// 保存到缓存(仅在客户端)
|
// 保存到缓存(仅在客户端)
|
||||||
this.saveToCache(data)
|
this.saveToCache(data)
|
||||||
|
|
||||||
console.log('[SystemConfig] 配置获取并缓存成功')
|
// console.log('[SystemConfig] 配置获取并缓存成功')
|
||||||
console.log('[SystemConfig] 自动处理状态:', data.auto_process_ready_resources)
|
// console.log('[SystemConfig] 自动处理状态:', data.auto_process_ready_resources)
|
||||||
console.log('[SystemConfig] 自动转存状态:', data.auto_transfer_enabled)
|
// console.log('[SystemConfig] 自动转存状态:', data.auto_transfer_enabled)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
this.error = error instanceof Error ? error.message : '获取配置失败'
|
this.error = error instanceof Error ? error.message : '获取配置失败'
|
||||||
console.error('[SystemConfig] 获取系统配置失败:', error)
|
// console.error('[SystemConfig] 获取系统配置失败:', error)
|
||||||
|
|
||||||
// 如果网络请求失败,尝试使用过期的缓存作为降级方案
|
// 如果网络请求失败,尝试使用过期的缓存作为降级方案
|
||||||
if (!force) {
|
if (!force) {
|
||||||
|
|||||||
Reference in New Issue
Block a user