wip (2)
This commit is contained in:
parent
6a7a7a51f6
commit
9bfdc42187
14
NTFConfig.go
14
NTFConfig.go
@ -10,6 +10,7 @@ import (
|
|||||||
type NTFConfig struct {
|
type NTFConfig struct {
|
||||||
HubAddr string
|
HubAddr string
|
||||||
HubDescription string
|
HubDescription string
|
||||||
|
HubSecNick string // Nickname of Hub-Security to exclude (e.g. "PtokaX")
|
||||||
BotAPIKey string
|
BotAPIKey string
|
||||||
GroupChatID int64
|
GroupChatID int64
|
||||||
|
|
||||||
@ -18,6 +19,9 @@ type NTFConfig struct {
|
|||||||
|
|
||||||
// Map of telegram users known to be in the group chat ==> telegram displayname
|
// Map of telegram users known to be in the group chat ==> telegram displayname
|
||||||
GroupChatMembers map[int64]string
|
GroupChatMembers map[int64]string
|
||||||
|
|
||||||
|
// Map of telegram users to their direct conversation ID with the bot
|
||||||
|
DirectMessageChats map[int64]int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig(configFile string) (NTFConfig, error) {
|
func LoadConfig(configFile string) (NTFConfig, error) {
|
||||||
@ -32,6 +36,16 @@ func LoadConfig(configFile string) (NTFConfig, error) {
|
|||||||
return NTFConfig{}, err
|
return NTFConfig{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ret.KnownUsers == nil {
|
||||||
|
ret.KnownUsers = make(map[int64]string)
|
||||||
|
}
|
||||||
|
if ret.GroupChatMembers == nil {
|
||||||
|
ret.GroupChatMembers = make(map[int64]string)
|
||||||
|
}
|
||||||
|
if ret.DirectMessageChats == nil {
|
||||||
|
ret.DirectMessageChats = make(map[int64]int64)
|
||||||
|
}
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
230
NTFServer.go
230
NTFServer.go
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -32,6 +33,7 @@ func NewNTFServer(configFile string) (*NTFServer, error) {
|
|||||||
ret := NTFServer{
|
ret := NTFServer{
|
||||||
configFile: configFile,
|
configFile: configFile,
|
||||||
hubMessages: make(chan upstreamMessage, 0),
|
hubMessages: make(chan upstreamMessage, 0),
|
||||||
|
conns: make(map[string]*libnmdc.HubConnection),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
@ -105,6 +107,10 @@ func NewNTFServer(configFile string) (*NTFServer, error) {
|
|||||||
// An actual NMDC connection will occur once the user joins for the first time.
|
// An actual NMDC connection will occur once the user joins for the first time.
|
||||||
func (this *NTFServer) registerUser(telegramUserId int64, hubUsername string) error {
|
func (this *NTFServer) registerUser(telegramUserId int64, hubUsername string) error {
|
||||||
if existingHubNick, ok := this.config.KnownUsers[telegramUserId]; ok {
|
if existingHubNick, ok := this.config.KnownUsers[telegramUserId]; ok {
|
||||||
|
if existingHubNick == hubUsername {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Telegram account is already registered with hub nick '%s'", existingHubNick)
|
return fmt.Errorf("Telegram account is already registered with hub nick '%s'", existingHubNick)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +146,8 @@ func (this *NTFServer) LaunchUpstreamWorker(telegramUserId int64, hubUsername st
|
|||||||
return fmt.Errorf("Duplicate hub connection for user '%s', abandoning", hubUsername)
|
return fmt.Errorf("Duplicate hub connection for user '%s', abandoning", hubUsername)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("Connecting to hub '%s' as user '%s'...", this.config.HubAddr, hubUsername)
|
||||||
|
|
||||||
// We want to use the async NMDC connection, but at the same time, provide
|
// We want to use the async NMDC connection, but at the same time, provide
|
||||||
// extra information in the channel. Wrap the upstream NMDC channel with one
|
// extra information in the channel. Wrap the upstream NMDC channel with one
|
||||||
// of our own
|
// of our own
|
||||||
@ -154,14 +162,14 @@ func (this *NTFServer) LaunchUpstreamWorker(telegramUserId int64, hubUsername st
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
hubUser := libnmdc.NewUserInfo(hubUsername)
|
||||||
|
hubUser.ClientTag = AppName
|
||||||
|
hubUser.ClientVersion = AppVersion
|
||||||
|
|
||||||
conn := libnmdc.ConnectAsync(
|
conn := libnmdc.ConnectAsync(
|
||||||
&libnmdc.HubConnectionOptions{
|
&libnmdc.HubConnectionOptions{
|
||||||
Address: libnmdc.HubAddress(this.config.HubAddr),
|
Address: libnmdc.HubAddress(this.config.HubAddr),
|
||||||
Self: &libnmdc.UserInfo{
|
Self: hubUser,
|
||||||
Nick: hubUsername,
|
|
||||||
ClientTag: AppName,
|
|
||||||
ClientVersion: AppVersion,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
upstreamChan,
|
upstreamChan,
|
||||||
)
|
)
|
||||||
@ -205,6 +213,36 @@ func (this *NTFServer) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *NTFServer) HandleHubMessage(msg upstreamMessage) {
|
func (this *NTFServer) HandleHubMessage(msg upstreamMessage) {
|
||||||
|
switch msg.evt.EventType {
|
||||||
|
|
||||||
|
case libnmdc.EVENT_SYSTEM_MESSAGE_FROM_CONN, libnmdc.EVENT_CONNECTION_STATE_CHANGED:
|
||||||
|
log.Printf("Hub(%s): * %s", msg.hubNick, msg.evt.Message)
|
||||||
|
|
||||||
|
case libnmdc.EVENT_PRIVATE:
|
||||||
|
err := this.DirectMessageTelegramUser(msg.telegramUserId, fmt.Sprintf("PM from user '%s': %s", msg.evt.Nick, msg.evt.Message))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Delivering PM to telegram user: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
case libnmdc.EVENT_PUBLIC:
|
||||||
|
if msg.evt.Nick == this.config.HubSecNick {
|
||||||
|
return // ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME coalesce from multiple connections
|
||||||
|
htmlMsg := "<b><" + html.EscapeString(msg.evt.Nick) + "></b> " + html.EscapeString(msg.evt.Message)
|
||||||
|
err := this.GroupChatSayHTML(htmlMsg)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Delivering public message to group chat: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
case libnmdc.EVENT_USER_JOINED, libnmdc.EVENT_USER_PART, libnmdc.EVENT_USER_UPDATED_INFO, libnmdc.EVENT_USERCOMMAND, libnmdc.EVENT_DEBUG_MESSAGE, libnmdc.EVENT_HUBNAME_CHANGED:
|
||||||
|
// ignore
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.Printf("Hub(%s): Unhandled(%d): %s", msg.hubNick, msg.evt.EventType, msg.evt.Message)
|
||||||
|
|
||||||
|
}
|
||||||
log.Printf("Hub: %#v", msg)
|
log.Printf("Hub: %#v", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,27 +275,60 @@ func (this *NTFServer) HandleMessage(update telegram.Update) {
|
|||||||
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
|
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *NTFServer) HandleTelegramUserParted(telegramUserId int64, update telegram.Update) error {
|
// kickAndDrop deregisters an account and kicks them from the group chat
|
||||||
delete(this.config.GroupChatMembers, telegramUserId)
|
func (this *NTFServer) kickAndDrop(telegramUserId int64) {
|
||||||
return this.config.Save(this.configFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *NTFServer) HandleTelegramUserJoined(telegramUserId int64, update telegram.Update) error {
|
// Hubnick
|
||||||
// If known, spawn the upstream connection; if unknown, kick them
|
if hubNick, ok := this.config.KnownUsers[telegramUserId]; ok {
|
||||||
hubNick, ok := this.config.KnownUsers[telegramUserId]
|
|
||||||
if !ok {
|
// Close upstream connection (if any)
|
||||||
|
if conn, ok := this.conns[hubNick]; ok {
|
||||||
|
delete(this.conns, hubNick)
|
||||||
|
|
||||||
|
log.Printf("Disconnecting '%s' from hub", hubNick)
|
||||||
|
conn.Disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deregister from known users
|
||||||
|
delete(this.config.KnownUsers, telegramUserId)
|
||||||
|
err := this.config.Save(this.configFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't save changes when deregistering user: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kick from telegram groupchat (if logged in)
|
||||||
_, err := this.bot.KickChatMember(telegram.KickChatMemberConfig{
|
_, err := this.bot.KickChatMember(telegram.KickChatMemberConfig{
|
||||||
ChatMemberConfig: telegram.ChatMemberConfig{
|
ChatMemberConfig: telegram.ChatMemberConfig{
|
||||||
ChatID: update.Message.Chat.ID,
|
ChatID: this.config.GroupChatID,
|
||||||
UserID: int(telegramUserId),
|
UserID: int(telegramUserId),
|
||||||
},
|
},
|
||||||
UntilDate: time.Now().Add(24 * time.Hour).Unix(),
|
UntilDate: time.Now().Add(24 * time.Hour).Unix(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Couldn't kick unexpected chat member from group: %s", err.Error())
|
log.Printf("Couldn't kick user from telegram group: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleTelegramUserParted processes a user leaving the groupchat, without deregistering their account
|
||||||
|
func (this *NTFServer) HandleTelegramUserParted(telegramUserId int64, update telegram.Update) error {
|
||||||
|
delete(this.config.GroupChatMembers, telegramUserId)
|
||||||
|
return this.config.Save(this.configFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *NTFServer) HandleTelegramUserJoined(telegramUserId int64, telegramDisplayName string, update telegram.Update) error {
|
||||||
|
// If known, spawn the upstream connection; if unknown, kick them
|
||||||
|
hubNick, ok := this.config.KnownUsers[telegramUserId]
|
||||||
|
if !ok {
|
||||||
|
log.Printf("Unexpected user '%s' (%d) joined the group chat, kicking...", telegramDisplayName, telegramUserId)
|
||||||
|
this.kickAndDrop(telegramUserId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
// Remember which users are currently joined
|
||||||
|
this.config.GroupChatMembers[telegramUserId] = telegramDisplayName
|
||||||
|
err := this.config.Save(this.configFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn the upstream connection for this user
|
// Spawn the upstream connection for this user
|
||||||
@ -272,7 +343,7 @@ func (this *NTFServer) HandleGroupMessage(update telegram.Update) error {
|
|||||||
// Ensure that they have a valid user mapping
|
// Ensure that they have a valid user mapping
|
||||||
// Create upstream NMDC connection for them
|
// Create upstream NMDC connection for them
|
||||||
for _, joinedUser := range *update.Message.NewChatMembers {
|
for _, joinedUser := range *update.Message.NewChatMembers {
|
||||||
err := this.HandleTelegramUserJoined(int64(joinedUser.ID), update)
|
err := this.HandleTelegramUserJoined(int64(joinedUser.ID), joinedUser.String(), update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Handling user join: %s", err.Error())
|
log.Printf("Handling user join: %s", err.Error())
|
||||||
}
|
}
|
||||||
@ -283,77 +354,154 @@ func (this *NTFServer) HandleGroupMessage(update telegram.Update) error {
|
|||||||
if update.Message.LeftChatMember != nil {
|
if update.Message.LeftChatMember != nil {
|
||||||
// User parted
|
// User parted
|
||||||
// Close upstream NMDC connection for them
|
// Close upstream NMDC connection for them
|
||||||
|
log.Printf("Telegram user '%s' (%d) leaving group chat", update.Message.LeftChatMember.String(), update.Message.LeftChatMember.ID)
|
||||||
return this.HandleTelegramUserParted(int64(update.Message.LeftChatMember.ID), update)
|
return this.HandleTelegramUserParted(int64(update.Message.LeftChatMember.ID), update)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(update.Message.Text) > 0 {
|
||||||
// Actual chat message
|
// Actual chat message
|
||||||
// Find the responsible user and send it to the upstream hub using their account
|
// Find the responsible user and send it to the upstream hub, using their account
|
||||||
// TODO
|
// FIXME also add it to the coalesce buffer so that we don't replay it from someone else's NMDC connection
|
||||||
|
|
||||||
|
userID := int64(update.Message.From.ID)
|
||||||
|
hubNick, ok := this.config.KnownUsers[userID]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Couldn't send public message for user '%d' unexpectedly missing hub nick!", userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, ok := this.conns[hubNick]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Couldn't send public message for user '%d' (%s) unexpectedly missing upstream connection!", userID, hubNick)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.SayPublic(update.Message.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO probably a file/image upload???
|
||||||
|
// TODO support "editing messages" by re-sending them with a ** suffix
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *NTFServer) ReplyTelegramUser(userID int64, str string, replyToMessageID int) error {
|
||||||
|
chatId, ok := this.config.DirectMessageChats[userID]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Can't send telegram message to user '%s': no DM chat known", userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := telegram.NewMessage(chatId, str)
|
||||||
|
if replyToMessageID != 0 {
|
||||||
|
msg.ReplyToMessageID = replyToMessageID
|
||||||
|
}
|
||||||
|
_, err := this.bot.Send(msg)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *NTFServer) DirectMessageTelegramUser(userID int64, str string) error {
|
||||||
|
return this.ReplyTelegramUser(userID, str, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *NTFServer) GroupChatSayHTML(str string) error {
|
||||||
|
msg := telegram.NewMessage(this.config.GroupChatID, str)
|
||||||
|
msg.ParseMode = telegram.ModeHTML
|
||||||
|
_, err := this.bot.Send(msg)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (this *NTFServer) HandleDirectMessage(update telegram.Update) error {
|
func (this *NTFServer) HandleDirectMessage(update telegram.Update) error {
|
||||||
|
|
||||||
// Registration workflow
|
// Registration workflow
|
||||||
|
|
||||||
// Find out the current status for this chat ID
|
|
||||||
userID := int64(update.Message.From.ID)
|
userID := int64(update.Message.From.ID)
|
||||||
hubNick, isKnown := this.config.KnownUsers[userID]
|
|
||||||
|
// Stash the telegram user ID against this direct-message chat ID so that
|
||||||
|
// we can always reply later on
|
||||||
|
chatID := update.Message.Chat.ID
|
||||||
|
if oldChatID, ok := this.config.DirectMessageChats[userID]; !ok || oldChatID != chatID {
|
||||||
|
this.config.DirectMessageChats[userID] = chatID
|
||||||
|
err := this.config.Save(this.configFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't save chat ID %d for user %d", chatID, userID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
respond := func(str string) error {
|
respond := func(str string) error {
|
||||||
msg := telegram.NewMessage(update.Message.Chat.ID, str)
|
return this.ReplyTelegramUser(userID, str, update.Message.MessageID)
|
||||||
msg.ReplyToMessageID = update.Message.MessageID
|
|
||||||
_, err := this.bot.Send(msg)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find out the current status for this chat ID
|
||||||
|
hubNick, isKnown := this.config.KnownUsers[userID]
|
||||||
|
_, isInGroupChat := this.config.GroupChatMembers[userID]
|
||||||
|
|
||||||
// Handle the incoming request
|
// Handle the incoming request
|
||||||
|
|
||||||
msg := update.Message.Text
|
msg := update.Message.Text
|
||||||
if strings.HasPrefix(msg, "/pm ") {
|
if strings.HasPrefix(msg, "/pm ") {
|
||||||
if !isKnown {
|
if !(isKnown && isInGroupChat) {
|
||||||
return respond("Can't send a native PM until you've joined.")
|
return respond("Can't send a native PM until you've joined.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
conn, ok := this.conns[hubNick]
|
||||||
return respond("Not yet implemented.")
|
if !ok {
|
||||||
|
return respond("Can't send a native PM (No upstream hub connection)")
|
||||||
} else if strings.HasPrefix(msg, "/join ") {
|
|
||||||
if isKnown {
|
|
||||||
return respond("You've already joined as '" + hubNick + "'.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parts := strings.SplitN(msg, " ", 3)
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return respond("Expected format /pm [recipient] [message] - try again...")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !conn.UserExists(parts[1]) {
|
||||||
|
return respond(fmt.Sprintf("Can't PM offline user '%s'", parts[1]))
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.SayPrivate(parts[1], parts[2])
|
||||||
|
|
||||||
|
} else if strings.HasPrefix(msg, "/join ") {
|
||||||
requestedHubNick := msg[6:]
|
requestedHubNick := msg[6:]
|
||||||
err := this.registerUser(userID, requestedHubNick)
|
err := this.registerUser(userID, requestedHubNick)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to join user: %s", err.Error())
|
log.Printf("Failed to register user: %s", err.Error())
|
||||||
return respond(fmt.Sprintf("Couldn't allow join because: %s", err.Error()))
|
return respond(fmt.Sprintf("Couldn't allow registration because: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return respond(fmt.Sprintf("Hi '%s'! You can join %s at %s", requestedHubNick, this.config.HubDescription, this.inviteLink))
|
return respond(fmt.Sprintf("Hi '%s'! You are now registered, and can join %s at %s", requestedHubNick, this.config.HubDescription, this.inviteLink))
|
||||||
|
|
||||||
|
} else if strings.HasPrefix(msg, "/rejoin") {
|
||||||
|
if isKnown && !isInGroupChat {
|
||||||
|
return respond(fmt.Sprintf("Welcome back '%s'! You can join %s at %s", hubNick, this.config.HubDescription, this.inviteLink))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return respond("You are either already joined (try /quit first), or not yet registered (try /join first).")
|
||||||
|
}
|
||||||
|
|
||||||
} else if strings.HasPrefix(msg, "/quit") {
|
} else if strings.HasPrefix(msg, "/quit") {
|
||||||
|
|
||||||
// TODO
|
this.kickAndDrop(userID)
|
||||||
return respond("Not yet implemented.")
|
return respond("Disconnected. You can register again by typing /help .")
|
||||||
|
|
||||||
} else { // e.g. /setup or /help
|
} else { // e.g. /start or /help
|
||||||
// Help
|
// Help
|
||||||
helpMsg := `I am a bot that connects Telegram with ` + this.config.HubDescription + ".\n"
|
helpMsg := `I am a bot that connects Telegram with ` + this.config.HubDescription + ".\n"
|
||||||
if isKnown {
|
if isKnown {
|
||||||
helpMsg += "You are currently connected as: '" + hubNick + "'\n"
|
helpMsg += "You are currently registered as: '" + hubNick + "'\n"
|
||||||
} else {
|
} else {
|
||||||
helpMsg += "You aren't connected yet.\n"
|
helpMsg += "You aren't connected yet.\n"
|
||||||
}
|
}
|
||||||
|
if isInGroupChat {
|
||||||
|
helpMsg += "You are currently in the groupchat.\n"
|
||||||
|
} else {
|
||||||
|
helpMsg += "You haven't joined the groupchat.\n"
|
||||||
|
}
|
||||||
|
|
||||||
helpMsg += `
|
helpMsg += `
|
||||||
|
|
||||||
Available commands:
|
Available commands:
|
||||||
/setup - Welcome message
|
/setup - Welcome message
|
||||||
/join [hubnick] - Join ` + this.config.HubDescription + ` as user 'hubnick'
|
/join [hubnick] - Register as 'hubnick' and join ` + this.config.HubDescription + `
|
||||||
|
/rejoin - Re-invite if you are already registered
|
||||||
/pm [recipient] [message] - Send a native PM (if connected)
|
/pm [recipient] [message] - Send a native PM (if connected)
|
||||||
/quit - Leave the group chat
|
/quit - Unregister your nick and leave the group chat
|
||||||
`
|
`
|
||||||
|
|
||||||
return respond(helpMsg)
|
return respond(helpMsg)
|
||||||
|
29
README.txt
29
README.txt
@ -1,20 +1,35 @@
|
|||||||
A bot to synchronise an NMDC hub with a Telegram supergroup.
|
A bot to synchronise chat between an NMDC/ADC hub and a Telegram supergroup.
|
||||||
|
|
||||||
## USAGE
|
Tags: NMDC
|
||||||
|
Written in Go
|
||||||
|
|
||||||
Create a new bot
|
## FEATURES
|
||||||
|
|
||||||
|
- NMDC/ADC support
|
||||||
|
- Exclude messages from hub-security nicks
|
||||||
|
- Standalone binary
|
||||||
|
|
||||||
|
## SETUP
|
||||||
|
|
||||||
|
Create a new telegram bot
|
||||||
- Use BotFather to create a new bot
|
- Use BotFather to create a new bot
|
||||||
- Use BotFather to change its privacy mode for group chats
|
- Use BotFather to disable its privacy mode for group chats
|
||||||
|
|
||||||
Create a group
|
Create a telegram group
|
||||||
- Manually create a group chat and add the bot to it
|
- Manually create a group chat and add the bot to it
|
||||||
- Convert group chat to supergroup
|
- Convert group chat to supergroup
|
||||||
- Grant bot to be an administrator (including ability to add more administrators)
|
- Grant bot to be an administrator (including ability to add more administrators)
|
||||||
- Settings > "Who can add members" > Only administrators
|
- Settings > "Who can add members" > Only administrators
|
||||||
- Create an invite link
|
- Create an invite link
|
||||||
|
|
||||||
Start nmdc-telegramfrontend
|
Handover to nmdc-telegramfrontend
|
||||||
- Run this bot with no -GroupChatID, to learn the groupchat ID
|
- Run this bot with no -GroupChatID, to learn the groupchat ID
|
||||||
- Post a test message in the group chat, to discover the groupchat ID
|
- Post a test message in the group chat, to discover the groupchat ID
|
||||||
- Leave the group chat
|
- Leave the group chat (long press on mobile, can't do it on desktop)
|
||||||
- Run this bot with -GroupChatID for normal operation
|
- Run this bot with -GroupChatID for normal operation
|
||||||
|
|
||||||
|
## USAGE
|
||||||
|
|
||||||
|
Chat with the bot to enter/leave the synchronised channel.
|
||||||
|
|
||||||
|
Sometimes the telegram invite links can take a few minutes to activate, especially if there has been unusual activity (e.g. frequent join/parts)
|
||||||
|
20
TODO.txt
20
TODO.txt
@ -1,19 +1,26 @@
|
|||||||
|
|
||||||
[X] Menu for direct messages
|
[X] Menu for direct messages
|
||||||
[X] Commands for new user registration
|
[X] Commands for new user registration
|
||||||
[ ] If registered/online -- responding to PMs (always require prefix)
|
[X] If registered/online -- responding to PMs (always require prefix)
|
||||||
|
|
||||||
[X] Open upstream connections
|
[X] Open upstream connections
|
||||||
[X] when registered users join the groupchat
|
[X] when registered users join the groupchat
|
||||||
[X] open existing connections at app startup
|
[X] open existing connections at app startup
|
||||||
|
|
||||||
[ ] Handle upstream messages
|
[ ] Handle upstream messages
|
||||||
[ ] Coalesce matches from multiple upstream connections?
|
[X] System messages
|
||||||
[ ] When recieving a PM - send directly to telegram user account
|
[X] Public messages
|
||||||
|
[ ] Coalesce matches from multiple upstream connections (timer?)
|
||||||
|
[X] Exclude messages from hub-security (custom nick)
|
||||||
|
[ ] Allow sending public messages to DC from inside the group chat
|
||||||
|
[ ] Nick translation
|
||||||
|
[X] Private messages
|
||||||
|
[X] Send directly to telegram user account (even if they're telegramuser-on-dc - telegramuser-on-dc PMs i guess)
|
||||||
|
[X] Allow replying to PMs with /pm [recipient] message
|
||||||
|
|
||||||
[ ] Graceful termination
|
[X] Graceful termination
|
||||||
[ ] Ability to close nmdc connections
|
[X] Ability to close nmdc connections
|
||||||
[ ] Close nmdc connection && deregister user (with bot message) when user leaves groupchat
|
[X] Close nmdc connection && deregister user (with bot message) when user leaves groupchat
|
||||||
|
|
||||||
[X] Block unknown users from entering telegram channel
|
[X] Block unknown users from entering telegram channel
|
||||||
|
|
||||||
@ -21,5 +28,6 @@
|
|||||||
[ ] Convert telegram files/images/videos to raw URLs for NMDC
|
[ ] Convert telegram files/images/videos to raw URLs for NMDC
|
||||||
[ ] Bot API does allow downloading - but (?authenticated)? need to re-host (either internally or upload to contented server)
|
[ ] Bot API does allow downloading - but (?authenticated)? need to re-host (either internally or upload to contented server)
|
||||||
[ ] Contented support - convert known URLs with image mime type to telegram images
|
[ ] Contented support - convert known URLs with image mime type to telegram images
|
||||||
|
[ ] Including private messages??? is that possible?
|
||||||
|
|
||||||
[ ] Publish
|
[ ] Publish
|
||||||
|
Loading…
Reference in New Issue
Block a user