move gotd fork into repo. (#111)

- update to latest telegram layer
- remove some references to fields in tg.Entities that don't exist in
the schema
- originally added here:
https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e
  - referenced here
-
https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3
-
https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
This commit is contained in:
Adam Van Ymeren
2025-06-27 20:03:37 -07:00
committed by GitHub
parent 0952df0244
commit 7a04f298d2
19264 changed files with 1539697 additions and 84 deletions
+191
View File
@@ -0,0 +1,191 @@
package tgtest
import (
"context"
"math"
"github.com/go-faster/errors"
"go.mau.fi/mautrix-telegram/pkg/gotd/bin"
"go.mau.fi/mautrix-telegram/pkg/gotd/crypto"
"go.mau.fi/mautrix-telegram/pkg/gotd/mt"
"go.mau.fi/mautrix-telegram/pkg/gotd/proto"
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
"go.mau.fi/mautrix-telegram/pkg/gotd/tgerr"
)
const (
// MessageServerResponse is a message type of RPC calls result.
MessageServerResponse = proto.MessageServerResponse
// MessageFromServer is a message type of server-side updates.
MessageFromServer = proto.MessageFromServer
)
// Send sends given message to user session k.
// Parameter t denotes MTProto message type. It should be MessageServerResponse or MessageFromServer.
func (s *Server) Send(ctx context.Context, k Session, t proto.MessageType, message bin.Encoder) error {
conn, ok := s.users.getConnection(k.ID)
if !ok {
return errors.Errorf("send %T: invalid key: connection %s not found", message, k.AuthKey.String())
}
var b bin.Buffer
if err := message.Encode(&b); err != nil {
return errors.Wrap(err, "encode")
}
data := crypto.EncryptedMessageData{
SessionID: k.ID,
MessageDataLen: int32(b.Len()),
MessageDataWithPadding: b.Copy(),
MessageID: s.msgID.New(t),
}
err := s.cipher.Encrypt(k.AuthKey, data, &b)
if err != nil {
return errors.Wrap(err, "encrypt")
}
ctx, cancel := context.WithTimeout(ctx, s.writeTimeout)
defer cancel()
if err := conn.Send(ctx, &b); err != nil {
return errors.Wrap(err, "send")
}
return nil
}
func (s *Server) sendReq(req *Request, t proto.MessageType, encoder bin.Encoder) error {
return s.Send(req.RequestCtx, req.Session, t, encoder)
}
// SendResult sends RPC answer using msg as result.
func (s *Server) SendResult(req *Request, msg bin.Encoder) error {
var buf bin.Buffer
if err := msg.Encode(&buf); err != nil {
return errors.Wrap(err, "encode result")
}
if err := s.sendReq(req, proto.MessageServerResponse, &proto.Result{
RequestMessageID: req.MsgID,
Result: buf.Raw(),
}); err != nil {
return errors.Wrapf(err, "send result [%T]", msg)
}
return nil
}
// SendGZIP sends RPC answer and packs it into proto.GZIP.
func (s *Server) SendGZIP(req *Request, msg bin.Encoder) error {
var buf bin.Buffer
if err := msg.Encode(&buf); err != nil {
return errors.Wrap(err, "encode gzip data")
}
return s.SendResult(req, proto.GZIP{Data: buf.Buf})
}
// SendErr sends RPC answer using given error as result.
func (s *Server) SendErr(req *Request, e *tgerr.Error) error {
return s.SendResult(req, &mt.RPCError{
ErrorCode: e.Code,
ErrorMessage: e.Message,
})
}
// SendBool sends RPC answer using given bool as result.
// Usually used in methods without explicit response.
func (s *Server) SendBool(req *Request, r bool) error {
var msg tg.BoolClass = &tg.BoolTrue{}
if !r {
msg = &tg.BoolFalse{}
}
return s.SendResult(req, msg)
}
// SendVector sends RPC answer using given vector as result.
func (s *Server) SendVector(req *Request, msgs ...bin.Encoder) error {
return s.SendResult(req, &genericVector{Elems: msgs})
}
// sendSessionCreated sends mt.NewSessionCreated `new_session_created` notification.
func (s *Server) sendSessionCreated(ctx context.Context, k Session, serverSalt int64) error {
if err := s.Send(ctx, k, proto.MessageFromServer, &mt.NewSessionCreated{
FirstMsgID: s.msgID.New(proto.MessageFromClient),
ServerSalt: serverSalt,
}); err != nil {
return errors.Wrap(err, "send sessionCreated")
}
return nil
}
// SendPong sends response for mt.PingRequest request.
func (s *Server) SendPong(req *Request, pingID int64) error {
if err := s.sendReq(req, proto.MessageServerResponse, &mt.Pong{
MsgID: req.MsgID,
PingID: pingID,
}); err != nil {
return errors.Wrap(err, "send pong")
}
return nil
}
// SendEternalSalt sends response for mt.GetFutureSaltsRequest.
// It sends an `eternal` salt, which valid until maximum possible date.
func (s *Server) SendEternalSalt(req *Request) error {
return s.SendFutureSalts(req, mt.FutureSalt{
ValidSince: 1,
ValidUntil: math.MaxInt32,
Salt: 10,
})
}
// SendFutureSalts sends response for mt.GetFutureSaltsRequest.
func (s *Server) SendFutureSalts(req *Request, salts ...mt.FutureSalt) error {
if err := s.Send(req.RequestCtx, req.Session, proto.MessageServerResponse, &mt.FutureSalts{
ReqMsgID: req.MsgID,
Now: int(s.clock.Now().Unix()),
Salts: salts,
}); err != nil {
return errors.Wrap(err, "send future salts")
}
return nil
}
// SendUpdates sends given updates to user session k.
func (s *Server) SendUpdates(ctx context.Context, k Session, updates ...tg.UpdateClass) error {
if len(updates) == 0 {
return nil
}
if err := s.Send(ctx, k, proto.MessageFromServer, &tg.Updates{
Updates: updates,
Date: int(s.clock.Now().Unix()),
}); err != nil {
return errors.Wrap(err, "send updates")
}
return nil
}
// SendAck sends acknowledgment for received message.
func (s *Server) SendAck(ctx context.Context, k Session, ids ...int64) error {
if err := s.Send(ctx, k, proto.MessageFromServer, &mt.MsgsAck{MsgIDs: ids}); err != nil {
return errors.Wrap(err, "send ack")
}
return nil
}
// ForceDisconnect forcibly disconnect user from server.
// It deletes MTProto session (session_id), but not auth key.
func (s *Server) ForceDisconnect(k Session) {
s.users.deleteConnection(k.ID)
}