From 548abe95834c26ee93d4f81e0f7cdb2d12e6cfe1 Mon Sep 17 00:00:00 2001 From: EzekialSA Date: Tue, 9 Dec 2025 21:12:22 -0600 Subject: [PATCH 1/2] fix: handle service messages and unsupported message types - Add UnsupportedMessageTypeError to handle MessageService, MessageEmpty, etc. - Update GetSingleMessage to return specific error instead of generic 'invalid message' - Add error handling in download iterator to skip system messages gracefully - System messages include 'user joined', 'message pinned', etc. which aren't downloadable --- app/dl/iter.go | 17 ++++++++++++++--- core/util/tutil/tutil.go | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/app/dl/iter.go b/app/dl/iter.go index 44503e248a..2d9f7cb38b 100644 --- a/app/dl/iter.go +++ b/app/dl/iter.go @@ -181,9 +181,20 @@ func (i *iter) process(ctx context.Context) (ret bool, skip bool) { 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) { + 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..64a526bcf9 100644 --- a/core/util/tutil/tutil.go +++ b/core/util/tutil/tutil.go @@ -174,6 +174,16 @@ func FileExists(msg tg.MessageClass) bool { } } +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 +195,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 From 3910b93b77954537b3119bc442bd4e69841aeb9b Mon Sep 17 00:00:00 2001 From: EzekialSA Date: Tue, 9 Dec 2025 21:29:13 -0600 Subject: [PATCH 2/2] feat: add console output for skipped messages - Add DeletedMessageError type for better error handling - Show yellow warning in console when skipping system/deleted messages - Both log to file and display to user during download --- app/dl/iter.go | 4 ++++ core/util/tutil/tutil.go | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/app/dl/iter.go b/app/dl/iter.go index 2d9f7cb38b..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,6 +178,7 @@ 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), @@ -189,6 +191,8 @@ func (i *iter) process(ctx context.Context) (ret bool, skip bool) { // 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), diff --git a/core/util/tutil/tutil.go b/core/util/tutil/tutil.go index 64a526bcf9..c7e4029e96 100644 --- a/core/util/tutil/tutil.go +++ b/core/util/tutil/tutil.go @@ -174,6 +174,15 @@ 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