botapi: implement getChat
Adds the getChat method to the HTTP Bot API gateway. Numeric chat_id only (no
@username). Resolution goes through the shared peer resolvers:
- user: ByID; unknown -> CHAT_NOT_FOUND
- channel/supergroup: ResolveChannel, so a public one resolves even when the bot
is not a member (projected as a preview); a private one the bot cannot access
-> CHAT_NOT_FOUND, a banned bot likewise
The Chat projection returns id (bot-api encoded), type ("channel" for a
broadcast, "supergroup" for a megagroup, "private" for a user), title, username,
first/last name, description, is_forum, and the scam/fake/verified flags.
This commit is contained in:
parent
78267ee0d3
commit
d022521d67
5 changed files with 221 additions and 0 deletions
|
|
@ -33,6 +33,78 @@ func (r *Router) BotAPISelf(ctx context.Context, botID int64) (domain.User, erro
|
|||
return u, nil
|
||||
}
|
||||
|
||||
// BotAPIChat resolves a chat for the Bot API getChat method. chat_id is numeric
|
||||
// only (no @username). Public channels/supergroups resolve even when the bot is
|
||||
// not a member; a private chat the bot cannot access is CHAT_NOT_FOUND.
|
||||
func (r *Router) BotAPIChat(ctx context.Context, botID, chatID int64) (domain.BotAPIChat, error) {
|
||||
if r == nil || botID == 0 {
|
||||
return domain.BotAPIChat{}, errors.New("BOT_INVALID")
|
||||
}
|
||||
peer, ok := botAPIPeerFromChatID(chatID)
|
||||
if !ok {
|
||||
return domain.BotAPIChat{}, errors.New("CHAT_ID_INVALID")
|
||||
}
|
||||
switch peer.Type {
|
||||
case domain.PeerTypeUser:
|
||||
if r.deps.Users == nil {
|
||||
return domain.BotAPIChat{}, errors.New("CHAT_NOT_FOUND")
|
||||
}
|
||||
u, found, err := r.deps.Users.ByID(ctx, botID, peer.ID)
|
||||
if err != nil {
|
||||
return domain.BotAPIChat{}, err
|
||||
}
|
||||
if !found {
|
||||
return domain.BotAPIChat{}, errors.New("CHAT_NOT_FOUND")
|
||||
}
|
||||
return domain.BotAPIChat{
|
||||
Peer: peer,
|
||||
Type: "private",
|
||||
FirstName: u.FirstName,
|
||||
LastName: u.LastName,
|
||||
Username: u.Username,
|
||||
Verified: u.Verified,
|
||||
Scam: u.Scam,
|
||||
Fake: u.Fake,
|
||||
}, nil
|
||||
case domain.PeerTypeChannel:
|
||||
if r.deps.Channels == nil {
|
||||
return domain.BotAPIChat{}, errors.New("CHAT_NOT_FOUND")
|
||||
}
|
||||
view, err := r.deps.Channels.ResolveChannel(ctx, botID, peer.ID)
|
||||
if err != nil {
|
||||
return domain.BotAPIChat{}, botAPIChatErr(err)
|
||||
}
|
||||
ch := view.Channel
|
||||
typ := "supergroup"
|
||||
if ch.Broadcast && !ch.Megagroup {
|
||||
typ = "channel"
|
||||
}
|
||||
return domain.BotAPIChat{
|
||||
Peer: peer,
|
||||
Type: typ,
|
||||
Title: ch.Title,
|
||||
Username: ch.Username,
|
||||
Description: ch.About,
|
||||
IsForum: ch.Forum,
|
||||
Verified: ch.Verified,
|
||||
Scam: ch.Scam,
|
||||
Fake: ch.Fake,
|
||||
}, nil
|
||||
}
|
||||
return domain.BotAPIChat{}, errors.New("CHAT_ID_INVALID")
|
||||
}
|
||||
|
||||
func botAPIChatErr(err error) error {
|
||||
switch {
|
||||
case errors.Is(err, domain.ErrChannelInvalid),
|
||||
errors.Is(err, domain.ErrChannelPrivate),
|
||||
errors.Is(err, domain.ErrChannelUserBanned):
|
||||
return errors.New("CHAT_NOT_FOUND")
|
||||
default:
|
||||
return channelInvalidErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
// BotAPIUpdates returns durable update_id based events projected for the HTTP
|
||||
// Bot API. New deployments use the dedicated Bot API queue; the legacy
|
||||
// user_update_events fallback is kept for tests that have not wired the queue.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue