diff --git a/app/dl/iter.go b/app/dl/iter.go index 8bf536159..4fa740378 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" @@ -171,6 +172,31 @@ func (i *iter) process(ctx context.Context) (ret bool, skip bool) { } message, err := tutil.GetSingleMessage(ctx, i.pool.Default(ctx), peer, msg) if err != nil { + // 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++ // increment logical position to skip this message + return false, true + } + // Check if message is deleted + var deletedErr *tutil.DeletedMessageError + if errors.As(err, &deletedErr) { + color.Yellow("Skipping deleted message: %d/%d", + deletedErr.PeerID, deletedErr.MessageID) + logctx.From(ctx).Warn("Skipping deleted message", + zap.Int64("peer_id", deletedErr.PeerID), + zap.Int("message_id", deletedErr.MessageID), + ) + i.logicalPos++ // increment logical position to skip this message + return false, true + } i.err = errors.Wrap(err, "resolve message") return false, false } diff --git a/core/util/tutil/tutil.go b/core/util/tutil/tutil.go index 76f92851a..e6a55fd50 100644 --- a/core/util/tutil/tutil.go +++ b/core/util/tutil/tutil.go @@ -171,6 +171,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). @@ -182,12 +201,21 @@ 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 if m.GetID() != msg { - return nil, errors.Errorf("the message %d/%d may be deleted", GetInputPeerID(peer), msg) + return nil, &DeletedMessageError{ + PeerID: GetInputPeerID(peer), + MessageID: msg, + } } return m, nil