package bot import ( "context" "fmt" "github.com/NicoNex/echotron/v3" "github.com/rs/zerolog/log" ) func (b *Bot) forwardSystemEvent(u *echotron.Update) { ctx := context.Background() switch { case u.ChatJoinRequest != nil: req := u.ChatJoinRequest if !isChannelChat(req.Chat.Type) { return } inviteLink := "" if req.InviteLink != nil { inviteLink = req.InviteLink.InviteLink } if inviteLink == "" { log.Debug().Msg("No invite link in chat join request") return } userID := req.From.ID username := stringPtr(req.From.Username) firstName := stringPtr(req.From.FirstName) lastName := stringPtr(req.From.LastName) if userID == 0 && req.UserChatID != 0 { userID = req.UserChatID } if userID == 0 { log.Error().Msg("No user id in chat join request") return } payload := map[string]any{ "type": "subscription", "user_telegram_id": userID, "invite_link": inviteLink, "username": username, "first_name": firstName, "last_name": lastName, } if err := b.Backend.SendEvent(ctx, payload); err != nil { log.Error().Err(err).Msg("Failed to send subscription event") } case u.ChatMember != nil: event := u.ChatMember if !isChannelChat(event.Chat.Type) { return } memberUser := event.NewChatMember.User if memberUser == nil { log.Error().Msg("No user in chat member update") return } oldStatus := event.OldChatMember.Status newStatus := event.NewChatMember.Status wasNotMember := oldStatus == "left" || oldStatus == "kicked" isNowMember := newStatus == "member" || newStatus == "administrator" || newStatus == "creator" userJoined := wasNotMember && isNowMember wasMember := oldStatus == "member" || oldStatus == "administrator" || oldStatus == "creator" || oldStatus == "restricted" isNowNotMember := newStatus == "left" || newStatus == "kicked" userLeft := wasMember && isNowNotMember if userJoined { inviteLink := "" if event.InviteLink != nil { inviteLink = event.InviteLink.InviteLink } if inviteLink == "" { log.Debug().Msg("No invite link in chat member update") return } username := stringPtr(memberUser.Username) firstName := stringPtr(memberUser.FirstName) lastName := stringPtr(memberUser.LastName) payload := map[string]any{ "type": "subscription", "user_telegram_id": memberUser.ID, "invite_link": inviteLink, "username": username, "first_name": firstName, "last_name": lastName, } if err := b.Backend.SendEvent(ctx, payload); err != nil { log.Error().Err(err).Msg("Failed to send subscription event") } return } if userLeft { payload := map[string]any{ "type": "unsubscription", "user_telegram_id": memberUser.ID, "channel_telegram_id": event.Chat.ID, } if err := b.Backend.SendEvent(ctx, payload); err != nil { log.Error().Err(err).Msg("Failed to send unsubscription event") } } case u.MyChatMember != nil: event := u.MyChatMember if !isChannelChat(event.Chat.Type) { return } actorID := event.From.ID if actorID == 0 { log.Error().Msg("No user in my chat member update") return } oldStatus := event.OldChatMember.Status newStatus := event.NewChatMember.Status wasMember := oldStatus == "administrator" || oldStatus == "member" isNowNotMember := newStatus == "left" || newStatus == "kicked" botRemoved := wasMember && isNowNotMember permissionsChanged := oldStatus == "administrator" && newStatus == "administrator" if botRemoved { payload := map[string]any{ "type": "bot_removed", "telegram_id": event.Chat.ID, "user_telegram_id": actorID, } if err := b.Backend.SendEvent(ctx, payload); err != nil { log.Error().Err(err).Msg("Failed to send bot removed event") } return } if permissionsChanged { title := event.Chat.Title if title == "" { title = fmt.Sprintf("Channel %d", event.Chat.ID) } payload := map[string]any{ "type": "bot_permissions", "telegram_id": event.Chat.ID, "chat_title": title, "user_telegram_id": actorID, "permissions": map[string]any{ "is_admin": newStatus == "administrator", "can_invite_users": event.NewChatMember.CanInviteUsers, "can_restrict_members": event.NewChatMember.CanRestrictMembers, }, } if err := b.Backend.SendEvent(ctx, payload); err != nil { log.Error().Err(err).Msg("Failed to send bot permissions event") } return } wasNotMember := oldStatus == "left" || oldStatus == "kicked" isNowMember := newStatus == "administrator" || newStatus == "member" botAdded := wasNotMember && isNowMember if botAdded { title := event.Chat.Title if title == "" { title = fmt.Sprintf("Channel %d", event.Chat.ID) } payload := map[string]any{ "type": "bot_added", "telegram_id": event.Chat.ID, "title": title, "username": stringPtr(event.Chat.Username), "user_telegram_id": actorID, "bot_permissions": map[string]any{ "is_admin": newStatus == "administrator", "can_invite_users": event.NewChatMember.CanInviteUsers, "can_restrict_members": event.NewChatMember.CanRestrictMembers, }, } if err := b.Backend.SendEvent(ctx, payload); err != nil { log.Error().Err(err).Msg("Failed to send bot added event") } } } }