mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
Nine commands mirroring the names @Stickers uses: /newpack, /mypack, /addsticker, /delsticker, /editsticker, /ordersticker, /setpackicon, /renamepack and /delpack, plus a confirm callback for the destructive one. Sources are replied stickers, photos or image documents; photos are downloaded, resampled to 512px and re-uploaded. One pack per user, keyed by owner id. Creating a pack is the only operation here that makes a durable, publicly linkable object on a user's behalf, so it is built around proving ownership rather than assuming it: - A name is claimed globally and create-only before Telegram is called. A pending record alone proves only that a caller *asked* for a name, which is exactly what someone naming a victim's public slug also does. - Adopting an existing set additionally requires that the claim predates this invocation. The claim lives in our store and the pack lives at Telegram, so a wiped store would otherwise make every pack adoptable. - Names are released only on positive evidence that no pack stands behind them, never on a generic failure, so a transient error cannot hand a live name to the next caller. - Ownership refusals are byte-identical across failure modes, so they cannot be used to probe which sets exist. Error classification is positive-only throughout: "the set is gone" and "nothing was created" are each proven from a specific Telegram response, never inferred from an error. Post-action commits run on a context detached from the request so a shutdown mid-handler cannot lose the record of something Telegram already did. Enabled explicitly via MODULES rather than by default.
57 lines
1.6 KiB
Go
57 lines
1.6 KiB
Go
package sticker
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
|
|
"github.com/go-telegram/bot"
|
|
"github.com/go-telegram/bot/models"
|
|
)
|
|
|
|
// handleSetPackIcon sets the pack thumbnail from a sticker already in the pack.
|
|
//
|
|
// The sticker's own file_id cannot simply be handed to Telegram: a pack
|
|
// thumbnail must be exactly 100x100, which a 512px sticker is not. So the image
|
|
// is fetched, resized, and uploaded as a new file.
|
|
func (s *state) handleSetPackIcon(ctx context.Context, b *bot.Bot, update *models.Update) error {
|
|
ctx, cancel := handlerContext(ctx)
|
|
defer cancel()
|
|
|
|
msg := update.Message
|
|
ownerID, err := senderID(msg)
|
|
if err != nil {
|
|
return reply(ctx, b, msg, senderRefusal)
|
|
}
|
|
|
|
owned, err := s.resolveOwned(ctx, msg, ownerID)
|
|
if err != nil {
|
|
return replyErr(ctx, b, msg, "sticker_setpackicon_resolve", err)
|
|
}
|
|
|
|
// Reserve the reply tail before the slow leg. See mediaContext.
|
|
mediaCtx, cancelMedia := mediaContext(ctx)
|
|
defer cancelMedia()
|
|
|
|
raw, err := downloadFile(mediaCtx, b, owned.fileID)
|
|
if err != nil {
|
|
return replyErr(ctx, b, msg, "sticker_setpackicon_download", err)
|
|
}
|
|
thumb, err := toThumbnailPNG(raw)
|
|
if err != nil {
|
|
return replyErr(ctx, b, msg, "sticker_setpackicon_resize", err)
|
|
}
|
|
|
|
if _, err := b.SetStickerSetThumbnail(ctx, &bot.SetStickerSetThumbnailParams{
|
|
Name: owned.pack.Name,
|
|
UserID: ownerID,
|
|
Thumbnail: &models.InputFileUpload{Filename: "thumb.png", Data: bytes.NewReader(thumb)},
|
|
Format: stickerFormatStatic,
|
|
}); err != nil {
|
|
if isStickerSetMissing(err) {
|
|
s.dropPackRecord(ctx, ownerID)
|
|
}
|
|
return replyAPIError(ctx, b, msg, "sticker_setpackicon", err)
|
|
}
|
|
return reply(ctx, b, msg, "Pack icon updated.")
|
|
}
|