nmdc-telegramfrontend/NTFServer.go

179 lines
4.3 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"log"
"code.ivysaur.me/libnmdc"
telegram "github.com/go-telegram-bot-api/telegram-bot-api"
)
// NTFServer methods all run on the same thread, so no mutexes are needed for field access
type NTFServer struct {
bot *telegram.BotAPI
upstream chan upstreamMessage
chatName string
inviteLink string
configFile string
config NTFConfig
}
type upstreamMessage struct {
telegramUserId int64
evt libnmdc.HubEvent
}
func NewNTFServer(configFile string) (*NTFServer, error) {
ret := NTFServer{
configFile: configFile,
}
cfg, err := LoadConfig(configFile)
if err != nil {
return nil, err
}
ret.config = cfg
if len(cfg.BotAPIKey) == 0 {
return nil, errors.New("No bot API key supplied (register with BotFather first)")
}
bot, err := telegram.NewBotAPI(cfg.BotAPIKey)
if err != nil {
return nil, fmt.Errorf("Connecting to Telegram: %s", err.Error())
}
ret.bot = bot
bot.Debug = true
log.Printf("Connected to telegram as '%s'", bot.Self.UserName)
if ret.IsSetupMode() {
log.Println("Group chat ID unknown, running in setup mode only - find the groupchat ID then re-run")
} else {
chatInfo, err := bot.GetChat(telegram.ChatConfig{ChatID: ret.config.GroupChatID})
if err != nil {
return nil, fmt.Errorf("Couldn't get supergroup properties: %s", err.Error())
}
inviteLink, err := bot.GetInviteLink(telegram.ChatConfig{ChatID: ret.config.GroupChatID})
if err != nil {
return nil, fmt.Errorf("Couldn't get supergroup invite link: %s", err.Error())
}
log.Printf("Group chat: %s", chatInfo.Title)
log.Printf("Invite link: %s", inviteLink)
ret.chatName = chatInfo.Title
ret.inviteLink = inviteLink
}
// Spawn upstream connections for all known users
ret.upstream = make(chan upstreamMessage, 0)
for k, v := range ret.config.KnownUsers {
ret.LaunchUpstreamWorker(k, v)
}
return &ret, nil
}
func (this *NTFServer) LaunchUpstreamWorker(telegramUserId int64, hubUsername string) {
ctx := context.Background()
// Open NMDC connection
go upstreamWorker()
}
func (this *NTFServer) IsSetupMode() bool {
return this.config.GroupChatID == 0
}
func (this *NTFServer) Run() error {
updateProps := telegram.NewUpdate(0)
updateProps.Timeout = 60 // seconds
updateChan, err := this.bot.GetUpdatesChan(updateProps)
if err != nil {
return err
}
for update := range updateChan {
this.HandleMessage(update)
}
return nil // Update channel was closed
}
func (this *NTFServer) HandleMessage(update telegram.Update) {
if update.Message == nil {
return
}
if this.IsSetupMode() {
log.Printf("Message from '%s': '%s', chat ID '%d'\n", update.Message.From.UserName, update.Message.Text, update.Message.Chat.ID)
} else if update.Message.Chat.ID == this.config.GroupChatID {
err := this.HandleGroupMessage(update)
if err != nil {
log.Printf("Handling group message: %s", err.Error())
}
} else if update.Message.Chat.IsPrivate() {
err := this.HandleDirectMessage(update)
if err != nil {
log.Printf("Handling private message: %s", err.Error())
}
} else {
log.Printf("Message from unknown chat %d (not our supergroup, not a PM, ...)", update.Message.Chat.ID)
}
fmt.Printf("%#v\n", update.Message)
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
}
func (this *NTFServer) HandleGroupMessage(update telegram.Update) error {
// Joins: ????
if update.Message.NewChatMembers != nil && len(*update.Message.NewChatMembers) > 0 {
// Users joining
// Ensure that they have a valid user mapping
// Create upstream NMDC connection for them
}
if update.Message.LeftChatMember != nil {
// User parted
// Close upstream NMDC connection for them
}
// Parts:
/*
&tgbotapi.Message{
MessageID:9, From:(*tgbotapi.User)(0xc420304000), Date:1527989178, Chat:(*tgbotapi.Chat)(0xc4201dc120), [...]
NewChatMembers:(*[]tgbotapi.User)(nil),
LeftChatMember:(*tgbotapi.User)(0xc420304050),
}
*/
return nil
}
func (this *NTFServer) HandleDirectMessage(update telegram.Update) error {
// Registration workflow
// Find out the current status for this chat ID... etc.
msg := telegram.NewMessage(update.Message.Chat.ID, "Hi user, join the group chat at "+this.inviteLink)
msg.ReplyToMessageID = update.Message.MessageID
this.bot.Send(msg)
return nil
}