owpengram-server/internal/rpc/messages_translation.go

156 lines
4.4 KiB
Go

package rpc
import (
"context"
"errors"
"github.com/iamxvbaba/td/tg"
"telesrv/internal/domain"
)
func (r *Router) onMessagesTranslateText(ctx context.Context, req *tg.MessagesTranslateTextRequest) (*tg.MessagesTranslateResult, error) {
if req == nil {
return nil, inputTextEmptyErr()
}
userID, _, err := r.currentUserID(ctx)
if err != nil {
return nil, internalErr()
}
if r.deps.Translation == nil {
return nil, translationsDisabledErr()
}
if err := r.requireTranslationUser(ctx, userID); err != nil {
return nil, err
}
peerInput, idMode := req.GetPeer()
ids, idsSet := req.GetID()
texts, textMode := req.GetText()
if idMode != idsSet || idMode == textMode {
return nil, inputTextEmptyErr()
}
request := domain.TranslationRequest{
UserID: userID,
ToLang: req.ToLang,
Tone: req.Tone,
}
if idMode {
peer, err := r.checkedTranslationPeer(ctx, userID, peerInput)
if err != nil {
return nil, peerIDInvalidErr()
}
request.Peer = peer
request.IDs = append([]int(nil), ids...)
} else {
request.Texts = make([]domain.TranslationText, 0, len(texts))
for _, text := range texts {
request.Texts = append(request.Texts, domain.TranslationText{
Text: text.Text,
Entities: domainMessageEntitiesForViewer(userID, text.Entities),
})
}
}
result, err := r.deps.Translation.Translate(ctx, request)
if err != nil {
return nil, translationRPCErr(err)
}
out := &tg.MessagesTranslateResult{Result: make([]tg.TextWithEntities, 0, len(result.Texts))}
for _, text := range result.Texts {
out.Result = append(out.Result, tg.TextWithEntities{
Text: text.Text,
Entities: tgMessageEntities(text.Entities),
})
}
return out, nil
}
func (r *Router) onMessagesTogglePeerTranslations(ctx context.Context, req *tg.MessagesTogglePeerTranslationsRequest) (bool, error) {
if req == nil || req.Peer == nil {
return false, peerIDInvalidErr()
}
userID, _, err := r.currentUserID(ctx)
if err != nil {
return false, internalErr()
}
if r.deps.Translation == nil {
return false, translationsDisabledErr()
}
if err := r.requireTranslationUser(ctx, userID); err != nil {
return false, err
}
peer, err := r.checkedTranslationPeer(ctx, userID, req.Peer)
if err != nil {
return false, peerIDInvalidErr()
}
if _, err := r.deps.Translation.SetPeerDisabled(ctx, userID, peer, req.Disabled); err != nil {
return false, translationRPCErr(err)
}
return true, nil
}
func (r *Router) requireTranslationUser(ctx context.Context, userID int64) error {
if r.deps.Users == nil {
return nil
}
self, err := r.deps.Users.Self(ctx, userID)
if err != nil {
return internalErr()
}
if self.Bot {
return botMethodInvalidErr()
}
return nil
}
func (r *Router) checkedTranslationPeer(ctx context.Context, userID int64, input tg.InputPeerClass) (domain.Peer, error) {
peer, err := r.checkedDomainPeerFromInputPeer(ctx, userID, input)
if err != nil {
return domain.Peer{}, err
}
if peer.Type != domain.PeerTypeUser || r.deps.Users == nil {
return peer, nil
}
var userInput tg.InputUserClass
switch value := input.(type) {
case *tg.InputPeerSelf:
userInput = &tg.InputUserSelf{}
case *tg.InputPeerUser:
userInput = &tg.InputUser{UserID: value.UserID, AccessHash: value.AccessHash}
default:
return domain.Peer{}, peerIDInvalidErr()
}
_, found, err := r.userFromInput(ctx, userID, userInput)
if err != nil {
return domain.Peer{}, internalErr()
}
if !found {
return domain.Peer{}, peerIDInvalidErr()
}
return peer, nil
}
func translationRPCErr(err error) error {
switch {
case errors.Is(err, domain.ErrTranslationInputEmpty):
return inputTextEmptyErr()
case errors.Is(err, domain.ErrTranslationInputTooLong):
return inputTextTooLongErr()
case errors.Is(err, domain.ErrTranslationLanguageInvalid):
return toLangInvalidErr()
case errors.Is(err, domain.ErrTranslationMessageInvalid), errors.Is(err, domain.ErrMessageIDInvalid):
return msgIDInvalidErr()
case errors.Is(err, domain.ErrTranslationPeerInvalid), errors.Is(err, domain.ErrChannelInvalid), errors.Is(err, domain.ErrChannelPrivate):
return peerIDInvalidErr()
case errors.Is(err, domain.ErrTranslationRateLimited):
return translateReqQuotaExceededErr()
case errors.Is(err, domain.ErrTranslationDisabled):
return translationsDisabledErr()
case errors.Is(err, domain.ErrTranslationTimeout):
return translationTimeoutErr()
case errors.Is(err, domain.ErrTranslationProviderUnavailable):
return translateReqFailedErr()
default:
return internalErr()
}
}