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日志
|
||||
func (h *TelegramHandler) ClearTelegramLogs(c *gin.Context) {
|
||||
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.POST("/telegram/logs/clear", middleware.AuthMiddleware(), middleware.AdminMiddleware(), telegramHandler.ClearTelegramLogs)
|
||||
api.POST("/telegram/webhook", telegramHandler.HandleWebhook)
|
||||
api.POST("/telegram/manual-push/:id", middleware.AuthMiddleware(), middleware.AdminMiddleware(), telegramHandler.ManualPushToChannel)
|
||||
|
||||
// 微信公众号相关路由
|
||||
wechatHandler := handlers.NewWechatHandler(
|
||||
|
||||
@@ -39,6 +39,7 @@ type TelegramBotService interface {
|
||||
IsChannelRegistered(chatID int64) bool
|
||||
HandleWebhookUpdate(c interface{})
|
||||
CleanupDuplicateChannels() error
|
||||
ManualPushToChannel(channelID uint) error
|
||||
}
|
||||
|
||||
type TelegramBotServiceImpl struct {
|
||||
@@ -1072,6 +1073,10 @@ func (s *TelegramBotServiceImpl) findResourcesForChannel(channel entity.Telegram
|
||||
func (s *TelegramBotServiceImpl) findLatestResources(channel entity.TelegramChannel, excludeResourceIDs []uint) []interface{} {
|
||||
params := s.buildFilterParams(channel)
|
||||
|
||||
// 添加按创建时间倒序的排序参数,确保获取最新资源
|
||||
params["order_by"] = "created_at"
|
||||
params["order_dir"] = "DESC"
|
||||
|
||||
// 在数据库查询中排除已推送的资源
|
||||
if len(excludeResourceIDs) > 0 {
|
||||
params["exclude_ids"] = excludeResourceIDs
|
||||
@@ -1330,15 +1335,23 @@ func (s *TelegramBotServiceImpl) SendMessage(chatID int64, text string, img stri
|
||||
} else {
|
||||
// 如果 img 以 http 开头,则为图片URL,否则为文件remote_id
|
||||
if strings.HasPrefix(img, "http") {
|
||||
// 发送图片URL
|
||||
// 发送图片URL前先验证URL是否可访问并返回有效的图片格式
|
||||
if s.isValidImageURL(img) {
|
||||
photoMsg := tgbotapi.NewPhoto(chatID, tgbotapi.FileURL(img))
|
||||
photoMsg.Caption = text
|
||||
photoMsg.ParseMode = "HTML"
|
||||
_, err := s.bot.Send(photoMsg)
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
// imgUrl := s.GetImgUrl(img)
|
||||
//todo 判断 imgUrl 是否可用
|
||||
@@ -1349,12 +1362,85 @@ func (s *TelegramBotServiceImpl) SendMessage(chatID int64, text string, img stri
|
||||
_, err := s.bot.Send(photoMsg)
|
||||
if err != nil {
|
||||
utils.Error("[TELEGRAM:MESSAGE:ERROR] 发送图片消息失败: %v", err)
|
||||
// 如果文件ID方式失败,尝试将URL作为普通文本发送
|
||||
return s.sendTextMessage(chatID, text)
|
||||
}
|
||||
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 删除消息
|
||||
func (s *TelegramBotServiceImpl) DeleteMessage(chatID int64, messageID int) error {
|
||||
if s.bot == nil {
|
||||
@@ -2017,3 +2103,25 @@ func (s *TelegramBotServiceImpl) isChannelInPushTimeRange(channel entity.Telegra
|
||||
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">
|
||||
{{ channel.is_active ? '活跃' : '非活跃' }}
|
||||
</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)">
|
||||
<template #icon>
|
||||
<i class="fas fa-edit"></i>
|
||||
@@ -715,6 +725,8 @@ const loadingLogs = ref(false)
|
||||
const logHours = ref(24)
|
||||
const editingChannel = ref<any>(null)
|
||||
const savingChannel = ref(false)
|
||||
const testingPush = ref(false)
|
||||
const manualPushingChannel = ref<number | null>(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 () => {
|
||||
try {
|
||||
|
||||
@@ -305,6 +305,7 @@ export const useTelegramApi = () => {
|
||||
const debugBotConnection = () => useApiFetch('/telegram/debug-connection').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 manualPushToChannel = (channelId: number) => useApiFetch(`/telegram/manual-push/${channelId}`, { method: 'POST' }).then(parseApiResponse)
|
||||
const getChannels = () => useApiFetch('/telegram/channels').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)
|
||||
@@ -320,6 +321,7 @@ export const useTelegramApi = () => {
|
||||
debugBotConnection,
|
||||
reloadBotConfig,
|
||||
testBotMessage,
|
||||
manualPushToChannel,
|
||||
getChannels,
|
||||
createChannel,
|
||||
updateChannel,
|
||||
|
||||
@@ -172,7 +172,7 @@ export const useSystemConfigStore = defineStore('systemConfig', {
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
console.log(`[SystemConfig] 开始获取配置 (force: ${force}, useAdminApi: ${useAdminApi})`)
|
||||
// console.log(`[SystemConfig] 开始获取配置 (force: ${force}, useAdminApi: ${useAdminApi})`)
|
||||
|
||||
// 根据上下文选择API:管理员页面使用管理员API,其他页面使用公开API
|
||||
const apiUrl = useAdminApi ? '/system/config' : '/public/system-config'
|
||||
@@ -189,14 +189,14 @@ export const useSystemConfigStore = defineStore('systemConfig', {
|
||||
// 保存到缓存(仅在客户端)
|
||||
this.saveToCache(data)
|
||||
|
||||
console.log('[SystemConfig] 配置获取并缓存成功')
|
||||
console.log('[SystemConfig] 自动处理状态:', data.auto_process_ready_resources)
|
||||
console.log('[SystemConfig] 自动转存状态:', data.auto_transfer_enabled)
|
||||
// console.log('[SystemConfig] 配置获取并缓存成功')
|
||||
// console.log('[SystemConfig] 自动处理状态:', data.auto_process_ready_resources)
|
||||
// console.log('[SystemConfig] 自动转存状态:', data.auto_transfer_enabled)
|
||||
|
||||
} catch (error) {
|
||||
this.isLoading = false
|
||||
this.error = error instanceof Error ? error.message : '获取配置失败'
|
||||
console.error('[SystemConfig] 获取系统配置失败:', error)
|
||||
// console.error('[SystemConfig] 获取系统配置失败:', error)
|
||||
|
||||
// 如果网络请求失败,尝试使用过期的缓存作为降级方案
|
||||
if (!force) {
|
||||
|
||||
Reference in New Issue
Block a user