Skip to content

Commit afaa31c

Browse files
committed
feat: better artwork previe
1 parent 6ed8592 commit afaa31c

19 files changed

+350
-67
lines changed

bot/bot.go

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ func RunPolling() {
5656
baseGroup.HandleMessageCtx(postArtworkCmd, telegohandler.CommandEqual("post"))
5757
baseGroup.HandleMessageCtx(batchPostArtwork, telegohandler.CommandEqual("batch_post"))
5858
baseGroup.HandleCallbackQueryCtx(postArtworkCb, telegohandler.CallbackDataContains("post_artwork"))
59+
baseGroup.HandleCallbackQueryCtx(artworkPreview, telegohandler.CallbackDataContains("artwork_preview"))
5960
baseGroup.HandleMessageCtx(getArtworkInfo, sourceUrlMatches)
6061
baseGroup.HandleInlineQueryCtx(inlineQuery)
6162

bot/handlers_admin.go

+65-16
Original file line numberDiff line numberDiff line change
@@ -253,29 +253,24 @@ func postArtworkCb(ctx context.Context, bot *telego.Bot, query telego.CallbackQu
253253
})
254254
return
255255
}
256-
if err := service.UpdateCachedArtworkByURL(ctx, sourceURL, types.ArtworkStatusPosting); err != nil {
256+
if err := service.UpdateCachedArtworkStatusByURL(ctx, sourceURL, types.ArtworkStatusPosting); err != nil {
257257
Logger.Errorf("更新缓存作品状态失败: %s", err)
258258
}
259259
artwork = cachedArtwork.Artwork
260-
defer func() {
261-
if err := service.UpdateCachedArtworkByURL(ctx, sourceURL, types.ArtworkStatusCached); err != nil {
262-
Logger.Errorf("更新缓存作品状态失败: %s", err)
263-
}
264-
}()
265260
}
266-
go bot.EditMessageText(&telego.EditMessageTextParams{
261+
go bot.EditMessageCaption(&telego.EditMessageCaptionParams{
267262
ChatID: telegoutil.ID(query.Message.GetChat().ID),
268263
MessageID: query.Message.GetMessageID(),
269-
Text: fmt.Sprintf("正在发布: %s", artwork.SourceURL),
264+
Caption: fmt.Sprintf("正在发布: %s", artwork.SourceURL),
270265
ReplyMarkup: nil,
271266
})
272267
if service.CheckDeletedByURL(ctx, sourceURL) {
273268
if err := service.DeleteDeletedByURL(ctx, sourceURL); err != nil {
274269
Logger.Errorf("取消删除记录失败: %s", err)
275-
bot.EditMessageText(&telego.EditMessageTextParams{
270+
bot.EditMessageCaption(&telego.EditMessageCaptionParams{
276271
ChatID: telegoutil.ID(query.Message.GetChat().ID),
277272
MessageID: query.Message.GetMessageID(),
278-
Text: "取消删除记录失败: " + err.Error(),
273+
Caption: "取消删除记录失败: " + err.Error(),
279274
})
280275
return
281276
}
@@ -285,28 +280,31 @@ func postArtworkCb(ctx context.Context, bot *telego.Bot, query telego.CallbackQu
285280
}
286281
if err := fetcher.PostAndCreateArtwork(ctx, artwork, bot, query.Message.GetChat().ID, query.Message.GetMessageID()); err != nil {
287282
Logger.Errorf("发布失败: %s", err)
288-
bot.EditMessageText(&telego.EditMessageTextParams{
283+
bot.EditMessageCaption(&telego.EditMessageCaptionParams{
289284
ChatID: telegoutil.ID(query.Message.GetChat().ID),
290285
MessageID: query.Message.GetMessageID(),
291-
Text: "发布失败: " + err.Error() + "\n\n" + time.Now().Format("2006-01-02 15:04:05"),
286+
Caption: "发布失败: " + err.Error() + "\n" + time.Now().Format("2006-01-02 15:04:05"),
292287
})
293288
return
294289
}
295290
artwork, err = service.GetArtworkByURL(ctx, sourceURL)
296291
if err != nil {
297292
Logger.Errorf("获取发布后的作品信息失败: %s", err)
298-
bot.EditMessageText(&telego.EditMessageTextParams{
293+
bot.EditMessageCaption(&telego.EditMessageCaptionParams{
299294
ChatID: telegoutil.ID(query.Message.GetChat().ID),
300295
MessageID: query.Message.GetMessageID(),
301-
Text: "发布成功, 但获取作品信息失败: " + err.Error(),
296+
Caption: "发布成功, 但获取作品信息失败: " + err.Error(),
302297
ReplyMarkup: nil,
303298
})
304299
return
305300
}
306-
bot.EditMessageText(&telego.EditMessageTextParams{
301+
if err := service.UpdateCachedArtworkStatusByURL(ctx, sourceURL, types.ArtworkStatusPosted); err != nil {
302+
Logger.Errorf("更新缓存作品状态失败: %s", err)
303+
}
304+
bot.EditMessageCaption(&telego.EditMessageCaptionParams{
307305
ChatID: telegoutil.ID(query.Message.GetChat().ID),
308306
MessageID: query.Message.GetMessageID(),
309-
Text: "发布成功: " + artwork.Title + "\n\n发布时间: " + artwork.CreatedAt.Format("2006-01-02 15:04:05"),
307+
Caption: "发布成功: " + artwork.Title + "\n发布时间: " + artwork.CreatedAt.Format("2006-01-02 15:04:05"),
310308
ReplyMarkup: telegoutil.InlineKeyboard(
311309
[]telego.InlineKeyboardButton{
312310
telegoutil.InlineKeyboardButton("查看").WithURL(telegram.GetArtworkPostMessageURL(artwork.Pictures[0].TelegramInfo.MessageID)),
@@ -381,6 +379,57 @@ func postArtworkCmd(ctx context.Context, bot *telego.Bot, message telego.Message
381379
).WithReplyMarkup(telegram.GetPostedPictureReplyMarkup(artwork.Pictures[0])))
382380
}
383381

382+
func artworkPreview(ctx context.Context, bot *telego.Bot, query telego.CallbackQuery) {
383+
// if !service.CheckAdminPermission(ctx, query.From.ID, types.PermissionPostArtwork) &&
384+
// !service.CheckAdminPermission(ctx, query.Message.GetChat().ID, types.PermissionPostArtwork) {
385+
// bot.AnswerCallbackQuery(&telego.AnswerCallbackQueryParams{
386+
// CallbackQueryID: query.ID,
387+
// Text: "你没有发布作品的权限",
388+
// ShowAlert: true,
389+
// CacheTime: 60,
390+
// })
391+
// return
392+
// }
393+
// queryDataSlice := strings.Split(query.Data, " ")
394+
// dataID := queryDataSlice[1]
395+
// sourceURL, err := service.GetCallbackDataByID(ctx, dataID)
396+
// if err != nil {
397+
// bot.AnswerCallbackQuery(&telego.AnswerCallbackQueryParams{
398+
// CallbackQueryID: query.ID,
399+
// Text: "获取回调数据失败 " + err.Error(),
400+
// ShowAlert: true,
401+
// CacheTime: 60,
402+
// })
403+
// return
404+
// }
405+
406+
// cachedArtwork, err := service.GetCachedArtworkByURL(ctx, sourceURL)
407+
// if err != nil {
408+
// bot.AnswerCallbackQuery(&telego.AnswerCallbackQueryParams{
409+
// CallbackQueryID: query.ID,
410+
// Text: "获取缓存作品失败 " + err.Error(),
411+
// ShowAlert: true,
412+
// CacheTime: 60,
413+
// })
414+
// return
415+
// }
416+
417+
// Logger.Infof("previewing artwork: %s", sourceURL)
418+
419+
// pictureIndexStr := queryDataSlice[2]
420+
// if pictureIndexStr == "delete" {
421+
422+
// }
423+
424+
bot.AnswerCallbackQuery(&telego.AnswerCallbackQueryParams{
425+
CallbackQueryID: query.ID,
426+
Text: "Work in progress...",
427+
ShowAlert: true,
428+
CacheTime: 60,
429+
})
430+
431+
}
432+
384433
func processPictures(ctx context.Context, bot *telego.Bot, message telego.Message) {
385434
userAdmin, err := service.GetAdminByUserID(ctx, message.From.ID)
386435
if err != nil {

bot/handlers_common.go

+66-18
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/google/uuid"
2323
"github.com/mymmrac/telego"
2424
"github.com/mymmrac/telego/telegoutil"
25+
"go.mongodb.org/mongo-driver/bson/primitive"
2526
"go.mongodb.org/mongo-driver/mongo"
2627
)
2728

@@ -93,7 +94,7 @@ func getPictureFile(ctx context.Context, bot *telego.Bot, message telego.Message
9394
telegram.ReplyMessage(bot, message, "请回复一条频道的图片消息")
9495
return
9596
}
96-
hash, err := common.GetPhash(fileBytes)
97+
hash, err := common.GetImagePhash(fileBytes)
9798
if err != nil {
9899
telegram.ReplyMessage(bot, message, "请回复一条频道的图片消息")
99100
return
@@ -301,10 +302,10 @@ func getArtworkInfo(ctx context.Context, bot *telego.Bot, message telego.Message
301302
}
302303
}
303304

304-
text := telegram.GetArtworkHTMLCaption(artwork) + fmt.Sprintf("\n该作品共有%d张图片", len(artwork.Pictures))
305+
text := telegram.GetArtworkHTMLCaption(artwork) + fmt.Sprintf("\n<i>该作品共有%d张图片</i>", len(artwork.Pictures))
305306
deleteModel, _ := service.GetDeletedByURL(ctx, sourceURL)
306307
if deleteModel != nil && hasPermission {
307-
text += fmt.Sprintf("\n\n这是一个在 %s 删除的作品\n如果发布则会取消删除", deleteModel.DeletedAt.Time().Format("2006-01-02 15:04:05"))
308+
text += fmt.Sprintf("\n<i>这是一个在 %s 删除的作品\n如果发布则会取消删除</i>", common.EscapeHTML(deleteModel.DeletedAt.Time().Format("2006-01-02 15:04:05")))
308309
}
309310
var replyMarkup telego.ReplyMarkup
310311
if isAlreadyPosted {
@@ -320,21 +321,68 @@ func getArtworkInfo(ctx context.Context, bot *telego.Bot, message telego.Message
320321
telegoutil.InlineKeyboardButton("发布").WithCallbackData("post_artwork " + cbId),
321322
telegoutil.InlineKeyboardButton("设为R18并发布").WithCallbackData("post_artwork_r18 " + cbId),
322323
},
324+
[]telego.InlineKeyboardButton{
325+
telegoutil.InlineKeyboardButton("删除这张").WithCallbackData("artwork_preview " + cbId + " delete"),
326+
telegoutil.InlineKeyboardButton("下一张").WithCallbackData("artwork_preview " + cbId + " 1"),
327+
},
323328
)
324329
}
325-
_, err = bot.SendMessage(telegoutil.Message(message.Chat.ChatID(), text).
326-
WithReplyMarkup(replyMarkup).
330+
331+
var inputFile telego.InputFile
332+
needUpdatePreview := false
333+
if artwork.Pictures[0].TelegramInfo != nil && artwork.Pictures[0].TelegramInfo.PhotoFileID != "" {
334+
inputFile = telegoutil.FileFromID(artwork.Pictures[0].TelegramInfo.PhotoFileID)
335+
} else {
336+
if fileBytes := common.GetReqCachedFile(artwork.Pictures[0].Original); fileBytes != nil {
337+
fileBytes, err = common.CompressImageWithCache(fileBytes, 10, 2560, artwork.Pictures[0].Original)
338+
if err != nil {
339+
telegram.ReplyMessage(bot, message, "压缩图片失败: "+err.Error())
340+
return
341+
}
342+
inputFile = telegoutil.File(telegoutil.NameReader(bytes.NewReader(fileBytes), artwork.Title))
343+
} else {
344+
needUpdatePreview = true
345+
if botPhotoFileId := service.GetEtcData(ctx, "bot_photo_file_id"); botPhotoFileId != nil {
346+
inputFile = telegoutil.FileFromID(botPhotoFileId.(string))
347+
} else if botPhotoFileBytes := service.GetEtcData(ctx, "bot_photo_bytes"); botPhotoFileBytes != nil {
348+
if data, ok := botPhotoFileBytes.(primitive.Binary); ok {
349+
inputFile = telegoutil.File(telegoutil.NameReader(bytes.NewReader(data.Data), artwork.Title))
350+
} else {
351+
inputFile = telegoutil.FileFromURL(artwork.Pictures[0].Thumbnail)
352+
}
353+
} else {
354+
inputFile = telegoutil.FileFromURL(artwork.Pictures[0].Thumbnail)
355+
}
356+
}
357+
}
358+
359+
photo := telegoutil.Photo(message.Chat.ChatID(), inputFile).
327360
WithReplyParameters(&telego.ReplyParameters{MessageID: message.MessageID}).
328-
WithParseMode(telego.ModeHTML).
329-
WithLinkPreviewOptions(
330-
&telego.LinkPreviewOptions{
331-
URL: artwork.Pictures[0].Original,
332-
ShowAboveText: true,
333-
},
334-
))
361+
WithCaption(text).
362+
WithReplyMarkup(replyMarkup).
363+
WithParseMode(telego.ModeHTML)
364+
365+
if artwork.R18 && !needUpdatePreview {
366+
photo.WithHasSpoiler()
367+
}
368+
msg, err := bot.SendPhoto(photo)
335369
if err != nil {
336-
Logger.Errorf("发送消息失败: %s", err)
370+
telegram.ReplyMessage(bot, message, "发送图片失败: "+err.Error())
371+
return
337372
}
373+
if needUpdatePreview {
374+
if err := UpdateLinkPreview(ctx, msg, artwork, bot, 0, photo); err != nil {
375+
Logger.Errorf("更新预览失败: %s", err)
376+
bot.EditMessageCaption(&telego.EditMessageCaptionParams{
377+
ChatID: message.Chat.ChatID(),
378+
MessageID: msg.MessageID,
379+
Caption: text + "\n<i>更新预览失败</i>",
380+
ParseMode: telego.ModeHTML,
381+
ReplyMarkup: msg.ReplyMarkup,
382+
})
383+
}
384+
}
385+
338386
}
339387

340388
func searchPicture(ctx context.Context, bot *telego.Bot, message telego.Message) {
@@ -350,7 +398,7 @@ func searchPicture(ctx context.Context, bot *telego.Bot, message telego.Message)
350398
telegram.ReplyMessage(bot, message, "获取图片文件失败: "+err.Error())
351399
return
352400
}
353-
hash, err := common.GetPhash(fileBytes)
401+
hash, err := common.GetImagePhash(fileBytes)
354402
if err != nil {
355403
telegram.ReplyMessage(bot, message, "获取图片哈希失败: "+err.Error())
356404
return
@@ -428,12 +476,12 @@ func calculatePicture(ctx context.Context, bot *telego.Bot, message telego.Messa
428476
telegram.ReplyMessage(bot, message, "获取图片文件失败: "+err.Error())
429477
return
430478
}
431-
hash, err := common.GetPhash(fileBytes)
479+
hash, err := common.GetImagePhash(fileBytes)
432480
if err != nil {
433481
telegram.ReplyMessage(bot, message, "计算图片信息失败: "+err.Error())
434482
return
435483
}
436-
blurScore, err := common.GetBlurScore(fileBytes)
484+
blurScore, err := common.GetImageBlurScore(fileBytes)
437485
if err != nil {
438486
telegram.ReplyMessage(bot, message, "计算图片信息失败: "+err.Error())
439487
return
@@ -451,10 +499,10 @@ func calculatePicture(ctx context.Context, bot *telego.Bot, message telego.Messa
451499
telegram.ReplyMessageWithHTML(bot, message, text)
452500
return
453501
}
454-
bot.EditMessageText(&telego.EditMessageTextParams{
502+
bot.EditMessageCaption(&telego.EditMessageCaptionParams{
455503
ChatID: message.Chat.ChatID(),
456504
MessageID: waitMessageID,
457-
Text: text,
505+
Caption: text,
458506
ParseMode: telego.ModeHTML,
459507
})
460508

bot/utils.go

+44
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package bot
22

33
import (
4+
"ManyACG/common"
5+
"ManyACG/errors"
46
"ManyACG/service"
57
"ManyACG/sources"
8+
"ManyACG/telegram"
69
"ManyACG/types"
10+
"bytes"
711
"context"
812

913
"github.com/mymmrac/telego"
14+
"github.com/mymmrac/telego/telegoutil"
1015
)
1116

1217
func CheckPermissionInGroup(ctx context.Context, message telego.Message, permissions ...types.Permission) bool {
@@ -38,3 +43,42 @@ func FindSourceURLForMessage(message *telego.Message) string {
3843
}
3944
return sources.FindSourceURL(text)
4045
}
46+
47+
func UpdateLinkPreview(ctx context.Context, targetMessage *telego.Message, artwork *types.Artwork, bot *telego.Bot, pictureIndex uint, photoParams *telego.SendPhotoParams) error {
48+
if pictureIndex >= uint(len(artwork.Pictures)) {
49+
return errors.ErrIndexOOB
50+
}
51+
var inputFile telego.InputFile
52+
fileBytes, err := common.DownloadWithCache(artwork.Pictures[pictureIndex].Original, nil)
53+
if err != nil {
54+
return err
55+
}
56+
fileBytes, err = common.CompressImageWithCache(fileBytes, 10, 2560, artwork.Pictures[pictureIndex].Original)
57+
if err != nil {
58+
return err
59+
}
60+
inputFile = telegoutil.File(telegoutil.NameReader(bytes.NewReader(fileBytes), artwork.Title))
61+
mediaPhoto := telegoutil.MediaPhoto(inputFile)
62+
mediaPhoto.WithCaption(photoParams.Caption).WithParseMode(photoParams.ParseMode)
63+
64+
var replyMarkup *telego.InlineKeyboardMarkup
65+
cachedArtwork, err := service.GetCachedArtworkByURL(ctx, artwork.SourceURL)
66+
if err != nil {
67+
return err
68+
}
69+
if cachedArtwork.Status == types.ArtworkStatusPosted {
70+
replyMarkup = telegram.GetPostedPictureReplyMarkup(artwork.Pictures[pictureIndex])
71+
} else if cachedArtwork.Status == types.ArtworkStatusCached {
72+
replyMarkup = targetMessage.ReplyMarkup
73+
} else {
74+
mediaPhoto.WithCaption(photoParams.Caption + "\n<i>正在发布...</i>").WithParseMode(telego.ModeHTML)
75+
}
76+
_, err = bot.EditMessageMedia(&telego.EditMessageMediaParams{
77+
ChatID: targetMessage.Chat.ChatID(),
78+
MessageID: targetMessage.MessageID,
79+
Media: mediaPhoto,
80+
ReplyMarkup: replyMarkup,
81+
})
82+
fileBytes = nil
83+
return err
84+
}

cmd/version.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
)
88

99
const (
10-
Version string = "0.10.12"
10+
Version string = "0.11.0"
1111
)
1212

1313
var VersionCmd = &cobra.Command{

common/client.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func DownloadWithCache(url string, client *req.Client) ([]byte, error) {
2323
if client == nil {
2424
client = Client
2525
}
26-
cachePath := config.Cfg.Storage.CacheDir + "/" + ReplaceFileNameInvalidChar(url)
26+
cachePath := config.Cfg.Storage.CacheDir + "/req/" + ReplaceFileNameInvalidChar(url)
2727
data, err := os.ReadFile(cachePath)
2828
if err == nil {
2929
Logger.Debugf("cache hit: %s", cachePath)
@@ -41,3 +41,12 @@ func DownloadWithCache(url string, client *req.Client) ([]byte, error) {
4141
}
4242
return data, nil
4343
}
44+
45+
func GetReqCachedFile(path string) []byte {
46+
cachePath := config.Cfg.Storage.CacheDir + "/req/" + ReplaceFileNameInvalidChar(path)
47+
data, err := os.ReadFile(cachePath)
48+
if err != nil {
49+
return nil
50+
}
51+
return data
52+
}

0 commit comments

Comments
 (0)