diff --git a/app/dl/iter.go b/app/dl/iter.go index 44503e248a..263adb6ade 100644 --- a/app/dl/iter.go +++ b/app/dl/iter.go @@ -13,6 +13,7 @@ import ( "text/template" "time" + "github.com/fatih/color" "github.com/go-faster/errors" "github.com/gotd/td/telegram/peers" "github.com/gotd/td/tg" @@ -177,13 +178,27 @@ func (i *iter) process(ctx context.Context) (ret bool, skip bool) { if err != nil { // Check if the error is due to a deleted message if errors.Is(err, tutil.ErrMessageDeleted) { + color.Yellow("Skipping deleted message: %d/%d", tutil.GetInputPeerID(peer), msg) logctx.From(ctx).Info("Message may be deleted, skipping", zap.Int64("dialog_id", tutil.GetInputPeerID(peer)), zap.Int("message_id", msg), ) - i.skippedDeleted.Inc() // increment skipped deleted counter - i.deletedIDs = append(i.deletedIDs, fmt.Sprintf("%d/%d", tutil.GetInputPeerID(peer), msg)) // track deleted message ID - i.logicalPos++ // increment logical position for skipped message + i.skippedDeleted.Inc() + i.deletedIDs = append(i.deletedIDs, fmt.Sprintf("%d/%d", tutil.GetInputPeerID(peer), msg)) + i.logicalPos++ + return false, true + } + // Check if message is an unsupported type (MessageService, MessageEmpty, etc.) + var unsupportedErr *tutil.UnsupportedMessageTypeError + if errors.As(err, &unsupportedErr) { + color.Yellow("Skipping system message: %d/%d (%s)", + unsupportedErr.PeerID, unsupportedErr.MessageID, unsupportedErr.MessageType) + logctx.From(ctx).Warn("Skipping system message", + zap.Int64("peer_id", unsupportedErr.PeerID), + zap.Int("message_id", unsupportedErr.MessageID), + zap.String("message_type", unsupportedErr.MessageType), + ) + i.logicalPos++ return false, true } i.err = errors.Wrap(err, "resolve message") diff --git a/core/util/tutil/tutil.go b/core/util/tutil/tutil.go index 4ffe4f1af8..c7e4029e96 100644 --- a/core/util/tutil/tutil.go +++ b/core/util/tutil/tutil.go @@ -174,6 +174,25 @@ func FileExists(msg tg.MessageClass) bool { } } +type DeletedMessageError struct { + PeerID int64 + MessageID int +} + +func (e *DeletedMessageError) Error() string { + return fmt.Sprintf("message %d/%d may be deleted", e.PeerID, e.MessageID) +} + +type UnsupportedMessageTypeError struct { + PeerID int64 + MessageID int + MessageType string +} + +func (e *UnsupportedMessageTypeError) Error() string { + return fmt.Sprintf("message %d/%d has unsupported type: %s (system message, not downloadable)", e.PeerID, e.MessageID, e.MessageType) +} + func GetSingleMessage(ctx context.Context, c *tg.Client, peer tg.InputPeerClass, msg int) (*tg.Message, error) { it := query.Messages(c). GetHistory(peer).OffsetID(msg + 1). @@ -185,7 +204,13 @@ func GetSingleMessage(ctx context.Context, c *tg.Client, peer tg.InputPeerClass, m, ok := it.Value().Msg.(*tg.Message) if !ok { - return nil, errors.Errorf("invalid message %d", msg) + // Message exists but is not a regular message (likely MessageService, MessageEmpty, etc.) + // These are system messages like "user joined", "message pinned", etc. and should be skipped + return nil, &UnsupportedMessageTypeError{ + PeerID: GetInputPeerID(peer), + MessageID: msg, + MessageType: fmt.Sprintf("%T", it.Value().Msg), + } } // check if message is deleted