Skip to content

Commit

Permalink
feat(telegram): implement bot login
Browse files Browse the repository at this point in the history
  • Loading branch information
ernado committed Nov 28, 2020
1 parent 78ddb42 commit 72a78eb
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 2 deletions.
52 changes: 52 additions & 0 deletions telegram/bot_login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package telegram

import (
"context"

"golang.org/x/xerrors"

"github.com/ernado/td/bin"
"github.com/ernado/td/internal/tg"
)

// BotLogin wraps credentials that are required to login as bot.
type BotLogin struct {
// ID is api_id.
ID int
// Hash is api_hash.
Hash string
// Token is bot auth token.
Token string
}

type authBox struct {
Auth tg.AuthAuthorizationClass
}

func (a *authBox) Decode(b *bin.Buffer) error {
v, err := tg.DecodeAuthAuthorization(b)
if err != nil {
return err
}
a.Auth = v
return nil
}

// BotLogin performs bot authorization request.
func (c *Client) BotLogin(ctx context.Context, login BotLogin) error {
var res authBox
if err := c.do(ctx, &tg.AuthImportBotAuthorizationRequest{
APIID: login.ID,
APIHash: login.Hash,
BotAuthToken: login.Token,
}, &res); err != nil {
return xerrors.Errorf("failed to do request: %w", err)
}
switch res.Auth.(type) {
case *tg.AuthAuthorization:
// Ok.
return nil
default:
return xerrors.Errorf("got unexpected response %T", res.Auth)
}
}
17 changes: 16 additions & 1 deletion telegram/cmd/gotdcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ func run(ctx context.Context) error {
return xerrors.Errorf("APP_ID not set or invalid: %w", err)
}

appHash := os.Getenv("APP_HASH")
if appHash == "" {
return xerrors.New("no APP_HASH provided")
}

// Creating connection.
client, err := telegram.Dial(ctx, telegram.Options{
Addr: "149.154.167.40:443",
Addr: "149.154.167.50:443",
Logger: logger,
})
if err != nil {
Expand All @@ -44,6 +49,16 @@ func run(ctx context.Context) error {
}); err != nil {
return xerrors.Errorf("failed to init connection: %w", err)
}

// Trying to log in as bot.
if err := client.BotLogin(ctx, telegram.BotLogin{
ID: appID,
Hash: appHash,
Token: os.Getenv("BOT_TOKEN"),
}); err != nil {
return xerrors.Errorf("failed to perform bot login: %w", err)
}

return nil
}

Expand Down
18 changes: 18 additions & 0 deletions telegram/handle_ack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package telegram

import (
"go.uber.org/zap"
"golang.org/x/xerrors"

"github.com/ernado/td/bin"
"github.com/ernado/td/internal/mt"
)

func (c *Client) handleAck(b *bin.Buffer) error {
var ack mt.MsgsAck
if err := ack.Decode(b); err != nil {
return xerrors.Errorf("failed to decode: %x", err)
}
c.log.With(zap.Int64s("messages", ack.MsgIds)).Debug("Ack")
return nil
}
34 changes: 34 additions & 0 deletions telegram/handle_result.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
package telegram

import (
"fmt"

"go.uber.org/zap"
"golang.org/x/xerrors"

"github.com/ernado/td/bin"
"github.com/ernado/td/internal/mt"
"github.com/ernado/td/internal/proto"
)

// Error represents RPC error returned to request.
type Error struct {
Code int
Message string
}

func (e Error) Error() string {
return fmt.Sprintf("rpc error code %d: %s", e.Code, e.Message)
}

func (c *Client) handleResult(b *bin.Buffer) error {
// Response to an RPC query.
var res proto.Result
Expand All @@ -30,6 +43,27 @@ func (c *Client) handleResult(b *bin.Buffer) error {
}
// Replacing buffer so callback will deal with uncompressed data.
b = &bin.Buffer{Buf: content.Data}

// Replacing id with inner id if error is compressed for any reason.
if id, err = b.PeekID(); err != nil {
return xerrors.Errorf("failed to peek id: %w", err)
}
}

if id == mt.RPCErrorTypeID {
var rpcErr mt.RPCError
if err := rpcErr.Decode(b); err != nil {
return xerrors.Errorf("failed to decode: %w", err)
}

c.rpcMux.Lock()
f, ok := c.rpc[res.RequestMessageID]
c.rpcMux.Unlock()
if ok {
f(nil, &Error{Code: rpcErr.ErrorCode, Message: rpcErr.ErrorMessage})
}

return nil
}

c.rpcMux.Lock()
Expand Down
1 change: 0 additions & 1 deletion telegram/new_encrypted_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@ func (c *Client) newEncryptedMessage(id crypto.MessageID, payload bin.Encoder, b

c.log.With(zap.Int64("request_id", int64(d.MessageID))).Debug("Request")

c.seq++
return nil
}
3 changes: 3 additions & 0 deletions telegram/ping.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ func (c *Client) Ping(ctx context.Context) error {
return xerrors.Errorf("failed to write: %w", err)
}

// Ack is not required.
c.seq++

// Waiting for result.
select {
case <-result:
Expand Down
2 changes: 2 additions & 0 deletions telegram/read_loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ func (c *Client) handleMessage(b *bin.Buffer) error {
return c.handleResult(b)
case mt.PongTypeID:
return c.handlePong(b)
case mt.MsgsAckTypeID:
return c.handleAck(b)
default:
return c.handleUnknown(b)
}
Expand Down
3 changes: 3 additions & 0 deletions telegram/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ func (c *Client) do(ctx context.Context, req bin.Encoder, res bin.Decoder) error
return xerrors.Errorf("failed to write: %w", err)
}

// Ack is required.
c.seq += 2

select {
case <-ctx.Done():
return ctx.Err()
Expand Down

0 comments on commit 72a78eb

Please sign in to comment.