Files
mautrix-telegram/main.go
T
Sumner Evans 0d502a8c55 Basic message converter and login
Signed-off-by: Sumner Evans <sumner.evans@automattic.com>
2024-05-14 10:17:19 -06:00

170 lines
4.5 KiB
Go

package main
import (
"bufio"
"context"
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"github.com/gotd/td/session"
"github.com/gotd/td/telegram"
"github.com/gotd/td/telegram/auth"
"github.com/gotd/td/telegram/updates"
updhook "github.com/gotd/td/telegram/updates/hook"
"github.com/gotd/td/tg"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"go.mau.fi/zerozap"
"go.uber.org/zap"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
"go.mau.fi/mautrix-telegram/msgconv"
)
type FileSession struct{}
func (s *FileSession) LoadSession(context.Context) ([]byte, error) {
if data, err := os.ReadFile("session"); err != nil {
return nil, session.ErrNotFound
} else {
return data, nil
}
}
func (s *FileSession) StoreSession(ctx context.Context, data []byte) error {
return os.WriteFile("session", data, 0600)
}
type Authenticator struct{}
func (a *Authenticator) Phone(ctx context.Context) (string, error) {
reader := bufio.NewReader(os.Stdin)
fmt.Printf("Phone (include country code with +): ")
raw, err := reader.ReadString('\n')
return strings.TrimSpace(raw), err
}
func (a *Authenticator) Password(ctx context.Context) (string, error) {
reader := bufio.NewReader(os.Stdin)
fmt.Printf("Password: ")
raw, err := reader.ReadString('\n')
return strings.TrimSpace(raw), err
}
func (a *Authenticator) AcceptTermsOfService(ctx context.Context, tos tg.HelpTermsOfService) error {
return nil
}
func (a *Authenticator) SignUp(ctx context.Context) (auth.UserInfo, error) {
panic("not supported")
}
func (a *Authenticator) Code(ctx context.Context, sentCode *tg.AuthSentCode) (string, error) {
reader := bufio.NewReader(os.Stdin)
fmt.Printf("Code: ")
return reader.ReadString('\n')
}
type FakePortal struct {
}
func (*FakePortal) DownloadMedia(ctx context.Context, uri id.ContentURIString, file *event.EncryptedFileInfo) ([]byte, error) {
return nil, nil
}
func (*FakePortal) UploadMedia(ctx context.Context, roomID id.RoomID, data []byte, fileName, mimeType string) (url id.ContentURIString, file *event.EncryptedFileInfo, err error) {
return id.ContentURIString("mxc://test"), nil, nil
}
func main() {
apiID, err := strconv.ParseInt(os.Args[1], 10, 32)
if err != nil {
panic(err)
}
apiHash := os.Args[2]
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
zaplog := zap.New(zerozap.New(log.Logger))
var authenticator Authenticator
var sessionStorage FileSession
d := tg.NewUpdateDispatcher()
gaps := updates.New(updates.Config{
Handler: d,
Logger: zaplog.Named("gaps"),
})
// https://core.telegram.org/api/obtaining_api_id
client := telegram.NewClient(int(apiID), apiHash, telegram.Options{
SessionStorage: &sessionStorage,
Logger: zaplog,
UpdateHandler: gaps,
Middlewares: []telegram.Middleware{
updhook.UpdateHook(gaps.Handle),
},
})
portal := &FakePortal{}
mc := msgconv.MessageConverter{
PortalMethods: portal,
Client: client,
}
// Setup message update handlers.
d.OnNewChannelMessage(func(ctx context.Context, e tg.Entities, update *tg.UpdateNewChannelMessage) error {
log.Info().Any("update", update.Message).Msg("Channel message")
converted := mc.ToMatrix(ctx, update.Message)
fmt.Printf("CONVERTED\n")
fmt.Printf("CONVERTED\n")
for _, part := range converted.Parts {
wrapped := &event.Content{Parsed: part.Content, Raw: part.Extra}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.Encode(wrapped)
}
fmt.Printf("CONVERTED\n")
fmt.Printf("CONVERTED\n")
return nil
})
d.OnNewMessage(func(ctx context.Context, e tg.Entities, update *tg.UpdateNewMessage) error {
log.Info().Any("update", update.Message).Msg("Message")
return nil
})
d.OnEditChannelMessage(func(ctx context.Context, e tg.Entities, update *tg.UpdateEditChannelMessage) error {
fmt.Printf("on edit channel message %v\n", update)
return nil
})
d.OnEditMessage(func(ctx context.Context, e tg.Entities, update *tg.UpdateEditMessage) error {
fmt.Printf("on edit message %v\n", update)
return nil
})
if err := client.Run(context.Background(), func(ctx context.Context) error {
authFlow := auth.NewFlow(&authenticator, auth.SendCodeOptions{})
err := client.Auth().IfNecessary(ctx, authFlow)
if err != nil {
return err
}
user, err := client.Self(ctx)
if err != nil {
return fmt.Errorf("error getting self: %w", err)
}
return gaps.Run(ctx, client.API(), user.ID, updates.AuthOptions{
OnStart: func(ctx context.Context) {
log.Info().Msg("gaps started")
},
})
}); err != nil {
panic(err)
}
// Client is closed.
}