тестово events события вместо telegram updates
This commit is contained in:
@@ -302,15 +302,12 @@ func (c *Client) UpdateProjectInviteLinkType(
|
||||
return &project, err
|
||||
}
|
||||
|
||||
func (c *Client) ForwardTelegramUpdate(
|
||||
ctx context.Context,
|
||||
update any,
|
||||
) error {
|
||||
func (c *Client) SendEvent(ctx context.Context, payload any) error {
|
||||
return c.do(
|
||||
ctx,
|
||||
http.MethodPost,
|
||||
"api/v1/internal/telegram/updates",
|
||||
update,
|
||||
"api/v1/internal/events",
|
||||
payload,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package bot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -118,6 +117,204 @@ func (b *Bot) SetState(s State, mode RenderMode) {
|
||||
s.Enter(b, mode)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isChannelChat(chatType string) bool {
|
||||
return chatType == "channel" || chatType == "supergroup"
|
||||
}
|
||||
|
||||
func stringPtr(value string) *string {
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
return &value
|
||||
}
|
||||
|
||||
func (b *Bot) Render(text string, keyboard echotron.InlineKeyboardMarkup, mode RenderMode) {
|
||||
if mode == EditMessage {
|
||||
b.Edit(text, keyboard)
|
||||
@@ -238,21 +435,9 @@ func (b *Bot) Update(u *echotron.Update) {
|
||||
Bool("has_edited_message", u.EditedMessage != nil).
|
||||
Msg("Update received")
|
||||
|
||||
// 1. Системные события (ChatJoinRequest, ChatMember, etc.) -> форвардим асинхронно
|
||||
// 1. Системные события -> отправляем доменные события в backend
|
||||
if u.ChatJoinRequest != nil || u.ChatMember != nil || u.MyChatMember != nil {
|
||||
go func() {
|
||||
ctx := context.Background()
|
||||
raw, err := json.Marshal(u)
|
||||
if err != nil {
|
||||
log.Error().RawJSON("update", raw).Msg("Failed to marshal update")
|
||||
}
|
||||
err = b.Backend.ForwardTelegramUpdate(ctx, u)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to forward system event to backend")
|
||||
return
|
||||
}
|
||||
log.Info().Msg("System event forwarded to backend")
|
||||
}()
|
||||
go b.forwardSystemEvent(u)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user