From f23f489b221a898a73889d67656ba5f876213bff Mon Sep 17 00:00:00 2001 From: Artem Tsyrulnikov Date: Wed, 28 Jan 2026 18:29:56 +0300 Subject: [PATCH] =?UTF-8?q?fix=20=D0=BF=D0=B0=D1=80=D1=81=D0=B5=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/adapter/database/get_channels.go | 37 +++++++++-------- .../adapter/database/update_channel.go | 40 +++++++++++-------- .../adapter/telegram/get_channel_diff.go | 15 +++---- .../internal/adapter/telegram/resolve.go | 13 +++--- .../adapter/telegram/resolve_invite.go | 15 +++---- tg_parser/internal/domain/channel.go | 15 +++---- tg_parser/internal/usecase/fetch_channels.go | 13 +++++- 7 files changed, 87 insertions(+), 61 deletions(-) diff --git a/tg_parser/internal/adapter/database/get_channels.go b/tg_parser/internal/adapter/database/get_channels.go index 9d43207..9d9004a 100644 --- a/tg_parser/internal/adapter/database/get_channels.go +++ b/tg_parser/internal/adapter/database/get_channels.go @@ -18,9 +18,11 @@ func (d *Database) GetChannels(ctx context.Context) []domain.Channel { title, access_hash, pts, - invite_link + invite_link, + is_accessible FROM channel -WHERE deleted_at IS NULL;` +WHERE deleted_at IS NULL + AND is_accessible = true;` txOrPool := transaction.TryExtractTX(ctx) @@ -49,13 +51,14 @@ WHERE deleted_at IS NULL;` } type getChannelsDTO struct { - ID pgtype.UUID - TelegramID pgtype.Int8 - Username pgtype.Text - Title pgtype.Text - AccessHash pgtype.Int8 - Pts pgtype.Int4 - InviteLink pgtype.Text + ID pgtype.UUID + TelegramID pgtype.Int8 + Username pgtype.Text + Title pgtype.Text + AccessHash pgtype.Int8 + Pts pgtype.Int4 + InviteLink pgtype.Text + IsAccessible pgtype.Bool } func (dto *getChannelsDTO) destination() []any { @@ -67,17 +70,19 @@ func (dto *getChannelsDTO) destination() []any { &dto.AccessHash, &dto.Pts, &dto.InviteLink, + &dto.IsAccessible, } } func (dto *getChannelsDTO) toDomain() domain.Channel { return domain.Channel{ - ID: dto.ID.Bytes, - TelegramID: domain.NormalizeChatID(dto.TelegramID.Int64), - Username: dto.Username.String, - Title: dto.Title.String, - AccessHash: dto.AccessHash.Int64, - Pts: int(dto.Pts.Int32), - InviteLink: dto.InviteLink.String, + ID: dto.ID.Bytes, + TelegramID: domain.NormalizeChatID(dto.TelegramID.Int64), + Username: dto.Username.String, + Title: dto.Title.String, + AccessHash: dto.AccessHash.Int64, + Pts: int(dto.Pts.Int32), + InviteLink: dto.InviteLink.String, + IsAccessible: dto.IsAccessible.Bool, } } diff --git a/tg_parser/internal/adapter/database/update_channel.go b/tg_parser/internal/adapter/database/update_channel.go index fc25b69..08d2387 100644 --- a/tg_parser/internal/adapter/database/update_channel.go +++ b/tg_parser/internal/adapter/database/update_channel.go @@ -18,24 +18,31 @@ SET telegram_id = $2, title = $4, access_hash = $5, pts = $6, + is_accessible = $7, updated_at = CURRENT_TIMESTAMP WHERE id = $1;` txOrPool := transaction.TryExtractTX(ctx) username := strings.TrimSpace(channel.Username) - usernameValid := username != "" - - dto := updateChannelDTO{ - ID: pgtype.UUID{Bytes: channel.ID, Valid: true}, - TelegramID: pgtype.Int8{Int64: channel.TelegramID, Valid: true}, - Username: pgtype.Text{String: username, Valid: usernameValid}, - Title: pgtype.Text{String: channel.Title, Valid: true}, - AccessHash: pgtype.Int8{Int64: channel.AccessHash, Valid: true}, - Pts: pgtype.Int4{Int32: int32(channel.Pts), Valid: true}, + var usernameDTO pgtype.Text + if username != "" { + usernameDTO = pgtype.Text{String: username, Valid: true} + } else { + usernameDTO = pgtype.Text{Valid: false} } - _, err := txOrPool.Exec(ctx, query, dto.ID, dto.TelegramID, dto.Username, dto.Title, dto.AccessHash, dto.Pts) + dto := updateChannelDTO{ + ID: pgtype.UUID{Bytes: channel.ID, Valid: true}, + TelegramID: pgtype.Int8{Int64: channel.TelegramID, Valid: true}, + Username: usernameDTO, + Title: pgtype.Text{String: channel.Title, Valid: true}, + AccessHash: pgtype.Int8{Int64: channel.AccessHash, Valid: true}, + Pts: pgtype.Int4{Int32: int32(channel.Pts), Valid: true}, + IsAccessible: pgtype.Bool{Bool: channel.IsAccessible, Valid: true}, + } + + _, err := txOrPool.Exec(ctx, query, dto.ID, dto.TelegramID, dto.Username, dto.Title, dto.AccessHash, dto.Pts, dto.IsAccessible) if err != nil { return fmt.Errorf("txOrPool.Exec: %w", err) } @@ -44,10 +51,11 @@ WHERE id = $1;` } type updateChannelDTO struct { - ID pgtype.UUID - TelegramID pgtype.Int8 - Username pgtype.Text - Title pgtype.Text - AccessHash pgtype.Int8 - Pts pgtype.Int4 + ID pgtype.UUID + TelegramID pgtype.Int8 + Username pgtype.Text + Title pgtype.Text + AccessHash pgtype.Int8 + Pts pgtype.Int4 + IsAccessible pgtype.Bool } diff --git a/tg_parser/internal/adapter/telegram/get_channel_diff.go b/tg_parser/internal/adapter/telegram/get_channel_diff.go index fd62da4..9fcb405 100644 --- a/tg_parser/internal/adapter/telegram/get_channel_diff.go +++ b/tg_parser/internal/adapter/telegram/get_channel_diff.go @@ -96,7 +96,7 @@ func extractChannelMeta(currentChannel domain.Channel, chats []tg.ChatClass) *do } username := "" - if usernameVal, ok := ch.GetUsername(); ok { + if usernameVal, ok := ch.GetUsername(); ok && usernameVal != "" { username = usernameVal } @@ -107,12 +107,13 @@ func extractChannelMeta(currentChannel domain.Channel, chats []tg.ChatClass) *do } updated := domain.Channel{ - ID: currentChannel.ID, - TelegramID: domain.ChatIDFromChannelID(ch.ID), - Username: username, - Title: ch.Title, - AccessHash: accessHash, - Pts: currentChannel.Pts, + ID: currentChannel.ID, + TelegramID: domain.ChatIDFromChannelID(ch.ID), + Username: username, + Title: ch.Title, + AccessHash: accessHash, + Pts: currentChannel.Pts, + IsAccessible: currentChannel.IsAccessible, } return &updated diff --git a/tg_parser/internal/adapter/telegram/resolve.go b/tg_parser/internal/adapter/telegram/resolve.go index 29b0afe..e09a33a 100644 --- a/tg_parser/internal/adapter/telegram/resolve.go +++ b/tg_parser/internal/adapter/telegram/resolve.go @@ -49,11 +49,12 @@ func (t *Telegram) ParseChannelMeta(ctx context.Context, username string) (domai } return domain.Channel{ - ID: uuid.New(), - TelegramID: domain.ChatIDFromChannelID(ch.ID), - Username: username, - Title: ch.Title, - AccessHash: ch.AccessHash, - Pts: pts, + ID: uuid.New(), + TelegramID: domain.ChatIDFromChannelID(ch.ID), + Username: username, + Title: ch.Title, + AccessHash: ch.AccessHash, + Pts: pts, + IsAccessible: true, }, nil } diff --git a/tg_parser/internal/adapter/telegram/resolve_invite.go b/tg_parser/internal/adapter/telegram/resolve_invite.go index c81e376..31a9e93 100644 --- a/tg_parser/internal/adapter/telegram/resolve_invite.go +++ b/tg_parser/internal/adapter/telegram/resolve_invite.go @@ -56,17 +56,18 @@ func (t *Telegram) ParseChannelMetaByInvite(ctx context.Context, inviteLink stri } username := "" - if usernameVal, ok := channel.GetUsername(); ok { + if usernameVal, ok := channel.GetUsername(); ok && usernameVal != "" { username = usernameVal } return domain.Channel{ - ID: uuid.New(), - TelegramID: domain.ChatIDFromChannelID(channel.ID), - Username: username, - Title: channel.Title, - AccessHash: channel.AccessHash, - Pts: pts, + ID: uuid.New(), + TelegramID: domain.ChatIDFromChannelID(channel.ID), + Username: username, + Title: channel.Title, + AccessHash: channel.AccessHash, + Pts: pts, + IsAccessible: true, }, nil } diff --git a/tg_parser/internal/domain/channel.go b/tg_parser/internal/domain/channel.go index 6dc22d8..bc092ec 100644 --- a/tg_parser/internal/domain/channel.go +++ b/tg_parser/internal/domain/channel.go @@ -7,13 +7,14 @@ import ( ) type Channel struct { - ID uuid.UUID - TelegramID int64 - Username string - Title string - AccessHash int64 - Pts int - InviteLink string + ID uuid.UUID + TelegramID int64 + Username string + Title string + AccessHash int64 + Pts int + InviteLink string + IsAccessible bool } const channelIDOffset int64 = 1000000000000 diff --git a/tg_parser/internal/usecase/fetch_channels.go b/tg_parser/internal/usecase/fetch_channels.go index fc3d341..a2fdb2b 100644 --- a/tg_parser/internal/usecase/fetch_channels.go +++ b/tg_parser/internal/usecase/fetch_channels.go @@ -44,16 +44,25 @@ func (uc *UseCase) processChannel(ctx context.Context, channel domain.Channel) e if isPrivateChannelError(err) { log.Warn().Err(err).Int64("telegram_id", channel.TelegramID).Msg("Private channel, attempting rejoin") if channel.InviteLink == "" { - log.Warn().Int64("telegram_id", channel.TelegramID).Msg("No invite link stored, skipping channel") + log.Warn().Int64("telegram_id", channel.TelegramID).Msg("No invite link stored, marking inaccessible") + channel.IsAccessible = false + if err := uc.database.UpdateChannel(ctx, channel); err != nil { + return fmt.Errorf("database.UpdateChannel (mark inaccessible): %w", err) + } return nil } updatedChannel, joinErr := uc.telegram.ParseChannelMetaByInvite(ctx, channel.InviteLink) if joinErr != nil { - log.Warn().Err(joinErr).Int64("telegram_id", channel.TelegramID).Msg("Invite rejoin failed") + log.Warn().Err(joinErr).Int64("telegram_id", channel.TelegramID).Msg("Invite rejoin failed, marking inaccessible") + channel.IsAccessible = false + if err := uc.database.UpdateChannel(ctx, channel); err != nil { + return fmt.Errorf("database.UpdateChannel (mark inaccessible): %w", err) + } return nil } updatedChannel.ID = channel.ID updatedChannel.InviteLink = channel.InviteLink + updatedChannel.IsAccessible = true updatedChannel.Pts = 0 if err := uc.database.UpdateChannel(ctx, updatedChannel); err != nil { return fmt.Errorf("database.UpdateChannel: %w", err)