-
-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update #166
- Loading branch information
Showing
8 changed files
with
357 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Examples | ||
|
||
Most examples use environment variable client builders. | ||
You can do it manually, see `bot-auth-manual` for example. | ||
|
||
1. Go to [https://my.telegram.org/apps](https://my.telegram.org/apps) and grab `APP_ID`, `APP_HASH` | ||
2. Set `SESSION_FILE` to something like `~/session.yourbot.json` for persistent auth | ||
3. Run example. | ||
|
||
Please don't share `APP_ID` or `APP_HASH`, it can't be easily rotated. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Binary termAuth implements authentication example for user using terminal. | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"flag" | ||
"fmt" | ||
"os" | ||
"strings" | ||
"syscall" | ||
|
||
"go.uber.org/zap" | ||
"golang.org/x/crypto/ssh/terminal" | ||
"golang.org/x/xerrors" | ||
|
||
"github.com/gotd/td/examples" | ||
"github.com/gotd/td/telegram" | ||
"github.com/gotd/td/telegram/auth" | ||
"github.com/gotd/td/tg" | ||
) | ||
|
||
// noSignUp can be embedded to prevent signing up. | ||
type noSignUp struct{} | ||
|
||
func (c noSignUp) SignUp(ctx context.Context) (auth.UserInfo, error) { | ||
return auth.UserInfo{}, xerrors.New("not implemented") | ||
} | ||
|
||
func (c noSignUp) AcceptTermsOfService(ctx context.Context, tos tg.HelpTermsOfService) error { | ||
return &auth.SignUpRequired{TermsOfService: tos} | ||
} | ||
|
||
// termAuth implements authentication via terminal. | ||
type termAuth struct { | ||
noSignUp | ||
|
||
phone string | ||
} | ||
|
||
func (a termAuth) Phone(_ context.Context) (string, error) { | ||
return a.phone, nil | ||
} | ||
|
||
func (a termAuth) Password(_ context.Context) (string, error) { | ||
fmt.Print("Enter 2FA password: ") | ||
bytePwd, err := terminal.ReadPassword(syscall.Stdin) | ||
if err != nil { | ||
return "", err | ||
} | ||
return strings.TrimSpace(string(bytePwd)), nil | ||
} | ||
|
||
func (a termAuth) Code(_ context.Context, _ *tg.AuthSentCode) (string, error) { | ||
fmt.Print("Enter code: ") | ||
code, err := bufio.NewReader(os.Stdin).ReadString('\n') | ||
if err != nil { | ||
return "", err | ||
} | ||
return strings.TrimSpace(code), nil | ||
} | ||
|
||
func main() { | ||
phone := flag.String("phone", "", "phone number to authenticate") | ||
flag.Parse() | ||
|
||
examples.Run(func(ctx context.Context, log *zap.Logger) error { | ||
// Setting up authentication flow helper based on terminal auth. | ||
flow := auth.NewFlow( | ||
termAuth{phone: *phone}, | ||
auth.SendCodeOptions{}, | ||
) | ||
|
||
client, err := telegram.ClientFromEnvironment(telegram.Options{ | ||
Logger: log, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
return client.Run(ctx, func(ctx context.Context) error { | ||
if err := client.Auth().IfNecessary(ctx, flow); err != nil { | ||
return err | ||
} | ||
|
||
log.Info("Success") | ||
|
||
return nil | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Binary bot-auth-manual implements example of custom session storage and | ||
// manually setting up client options without environment variables. | ||
package main | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"sync" | ||
|
||
"go.uber.org/zap" | ||
|
||
"github.com/gotd/td/examples" | ||
"github.com/gotd/td/session" | ||
"github.com/gotd/td/telegram" | ||
) | ||
|
||
// memorySession implements in-memory session storage. | ||
// Goroutine-safe. | ||
type memorySession struct { | ||
mux sync.RWMutex | ||
data []byte | ||
} | ||
|
||
// LoadSession loads session from memory. | ||
func (s *memorySession) LoadSession(context.Context) ([]byte, error) { | ||
if s == nil { | ||
return nil, session.ErrNotFound | ||
} | ||
|
||
s.mux.RLock() | ||
defer s.mux.RUnlock() | ||
|
||
if len(s.data) == 0 { | ||
return nil, session.ErrNotFound | ||
} | ||
|
||
cpy := append([]byte(nil), s.data...) | ||
|
||
return cpy, nil | ||
} | ||
|
||
// StoreSession stores session to memory. | ||
func (s *memorySession) StoreSession(ctx context.Context, data []byte) error { | ||
s.mux.Lock() | ||
s.data = data | ||
s.mux.Unlock() | ||
return nil | ||
} | ||
|
||
func main() { | ||
// Grab those from https://my.telegram.org/apps. | ||
appID := flag.Int("api-id", 0, "app id") | ||
appHash := flag.String("api-hash", "hash", "app hash") | ||
// Get it from bot father. | ||
token := flag.String("token", "", "bot token") | ||
flag.Parse() | ||
|
||
// Using custom session storage. | ||
// You can save session to database, e.g. Redis, MongoDB or postgres. | ||
// See memorySession for implementation details. | ||
sessionStorage := &memorySession{} | ||
|
||
examples.Run(func(ctx context.Context, log *zap.Logger) error { | ||
client := telegram.NewClient(*appID, *appHash, telegram.Options{ | ||
SessionStorage: sessionStorage, | ||
Logger: log, | ||
}) | ||
|
||
return client.Run(ctx, func(ctx context.Context) error { | ||
// Checking auth status. | ||
status, err := client.Auth().Status(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
// Can be already authenticated if we have valid session in | ||
// session storage. | ||
if !status.Authorized { | ||
// Otherwise, perform bot authentication. | ||
if _, err := client.Auth().Bot(ctx, *token); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// All good, manually authenticated. | ||
log.Info("Done") | ||
|
||
return nil | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Binary bot-echo implements basic example for bot. | ||
package main | ||
|
||
import ( | ||
"context" | ||
|
||
"go.uber.org/zap" | ||
|
||
"github.com/gotd/td/examples" | ||
"github.com/gotd/td/telegram" | ||
"github.com/gotd/td/telegram/message" | ||
"github.com/gotd/td/tg" | ||
) | ||
|
||
func main() { | ||
// Environment variables: | ||
// BOT_TOKEN: token from BotFather | ||
// APP_ID: app_id of Telegram app. | ||
// APP_HASH: app_hash of Telegram app. | ||
// SESSION_FILE: path to session file | ||
// SESSION_DIR: path to session directory, if SESSION_FILE is not set | ||
examples.Run(func(ctx context.Context, log *zap.Logger) error { | ||
// Dispatcher handles incoming updates. | ||
dispatcher := tg.NewUpdateDispatcher() | ||
opts := telegram.Options{ | ||
Logger: log, | ||
UpdateHandler: dispatcher, | ||
} | ||
return telegram.BotFromEnvironment(ctx, opts, func(ctx context.Context, client *telegram.Client) error { | ||
// Raw MTProto API client, allows making raw RPC calls. | ||
api := tg.NewClient(client) | ||
|
||
// Helper for sending messages. | ||
sender := message.NewSender(api) | ||
|
||
// Setting up handler for incoming message. | ||
dispatcher.OnNewMessage(func(ctx context.Context, entities tg.Entities, u *tg.UpdateNewMessage) error { | ||
m, ok := u.Message.(*tg.Message) | ||
if !ok || m.Out { | ||
// Outgoing message, not interesting. | ||
return nil | ||
} | ||
|
||
// Sending reply. | ||
_, err := sender.Reply(entities, u).Text(ctx, m.Message) | ||
return err | ||
}) | ||
return nil | ||
}, telegram.RunUntilCanceled) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Binary bot-upload implements upload example for bot. | ||
package main | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"flag" | ||
"fmt" | ||
|
||
"go.uber.org/zap" | ||
|
||
"github.com/gotd/td/examples" | ||
"github.com/gotd/td/telegram" | ||
"github.com/gotd/td/telegram/message" | ||
"github.com/gotd/td/telegram/message/html" | ||
"github.com/gotd/td/telegram/uploader" | ||
"github.com/gotd/td/tg" | ||
) | ||
|
||
func main() { | ||
// Environment variables: | ||
// BOT_TOKEN: token from BotFather | ||
// APP_ID: app_id of Telegram app. | ||
// APP_HASH: app_hash of Telegram app. | ||
// SESSION_FILE: path to session file | ||
// SESSION_DIR: path to session directory, if SESSION_FILE is not set | ||
filePath := flag.String("file", "", "file to upload") | ||
targetDomain := flag.String("target", "", "target to upload, e.g. channel name") | ||
flag.Parse() | ||
|
||
examples.Run(func(ctx context.Context, log *zap.Logger) error { | ||
if *filePath == "" || *targetDomain == "" { | ||
return errors.New("no --file or --target provided") | ||
} | ||
|
||
// The performUpload will be called after client initialization. | ||
performUpload := func(ctx context.Context, client *telegram.Client) error { | ||
// Raw MTProto API client, allows making raw RPC calls. | ||
api := tg.NewClient(client) | ||
|
||
// Helper for uploading. Automatically uses big file upload when needed. | ||
u := uploader.NewUploader(api) | ||
|
||
// Helper for sending messages. | ||
sender := message.NewSender(api).WithUploader(u) | ||
|
||
// Uploading directly from path. Note that you can do it from | ||
// io.Reader or buffer, see From* methods of uploader. | ||
log.Info("Uploading file") | ||
upload, err := u.FromPath(ctx, *filePath) | ||
if err != nil { | ||
return fmt.Errorf("failed to upload: %w", err) | ||
} | ||
|
||
// Now we have uploaded file handle, sending it as styled message. | ||
// First, preparing message. | ||
document := message.UploadedDocument(upload, | ||
html.String(nil, `Upload: <b>From bot</b>`), | ||
) | ||
|
||
// You can set MIME type, send file as video or audio by using | ||
// document builder: | ||
document. | ||
MIME("audio/mp3"). | ||
Filename("some-audio.mp3"). | ||
Audio() | ||
|
||
// Resolving target. Can be telephone number or @nickname of user, | ||
// group or channel. | ||
target := sender.Resolve(*targetDomain) | ||
|
||
// Sending message with media. | ||
log.Info("Sending file") | ||
if _, err := target.Media(ctx, document); err != nil { | ||
return fmt.Errorf("send: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
return telegram.BotFromEnvironment(ctx, telegram.Options{Logger: log}, nil, performUpload) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// Package examples contains usage examples for gotd features. | ||
package examples | ||
|
||
import ( | ||
_ "github.com/gotd/td" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package examples | ||
|
||
import ( | ||
"context" | ||
|
||
"go.uber.org/zap" | ||
) | ||
|
||
// Run runs f callback with context and logger, panics on error. | ||
func Run(f func(ctx context.Context, log *zap.Logger) error) { | ||
log, err := zap.NewDevelopment() | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer func() { _ = log.Sync() }() | ||
// No graceful shutdown. | ||
ctx := context.Background() | ||
if err := f(ctx, log); err != nil { | ||
log.Fatal("Run failed", zap.Error(err)) | ||
} | ||
// Done. | ||
} |