Feat(Initial): Initial Go codebase
All checks were successful
Webhook-Everything/Webhook-Everything/pipeline/head This commit looks good

This commit is contained in:
2022-05-29 00:06:52 +08:00
parent f31bc0cd52
commit 53829a2788
27 changed files with 1489 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
package telegrampackage
import (
"fmt"
"math/rand"
"strings"
"time"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"gorm.io/gorm"
)
type TelegramHandlerFunction func(shortCode string, text string) (handled bool, responseText *string)
type Env struct {
DB *gorm.DB
TelegramAPIKey string
HandlerFunctions []TelegramHandlerFunction
}
func NewEnv(db *gorm.DB, telegramAPIKey string, handlerFunctions []TelegramHandlerFunction) *Env {
var env Env
env.DB = db
env.TelegramAPIKey = telegramAPIKey
env.HandlerFunctions = handlerFunctions
// Example handler function
_ = env.telegramHandlerExample
// Seed random
rand.Seed(time.Now().UnixNano())
// Start listening job
go env.TelegramListenAndGen()
return &env
}
func (env *Env) AddTelegramHandlerFunc(handlerFunction TelegramHandlerFunction) {
env.HandlerFunctions = append(env.HandlerFunctions, handlerFunction)
}
// Not used normally. Shown here as example only
func (env *Env) telegramHandlerExample(shortCode string, text string) (bool, *string) {
commandSplitted := ParseTelegramBotCommand(text)
if len(commandSplitted) > 0 && commandSplitted[0] == "/command" {
responseText := fmt.Sprintf("Your short code is %s.\n\nYour message is %s", shortCode, text)
responseText = responseText + fmt.Sprintf("\n\nYour parameters are: %s", strings.Join(commandSplitted[1:], "\n - "))
responseText = "<code>" + tgbotapi.EscapeText("HTML", responseText) + "</code>"
return true, &responseText
}
return false, nil
}

View File

@@ -0,0 +1,35 @@
package telegrampackage
import "strings"
func ParseTelegramBotCommand(fullCmd string) []string {
var results []string
currentInsideQuote := false
splitted := strings.Split(fullCmd, " ")
for _, currSplit := range splitted {
if !currentInsideQuote {
if strings.HasPrefix(currSplit, "\"") {
if len(currSplit) >= 2 && !strings.HasSuffix(currSplit, "\\\"") && strings.HasSuffix(currSplit, "\"") {
currSplit = strings.ReplaceAll(currSplit, "\\\"", "\"")
results = append(results, currSplit[1:len(currSplit)-1])
} else {
currentInsideQuote = true
currSplit = strings.ReplaceAll(currSplit, "\\\"", "\"")
results = append(results, currSplit[1:])
}
} else {
results = append(results, currSplit)
}
} else {
if !strings.HasSuffix(currSplit, "\\\"") && strings.HasSuffix(currSplit, "\"") {
currentInsideQuote = false
currSplit = strings.ReplaceAll(currSplit, "\\\"", "\"")
results[len(results)-1] = results[len(results)-1] + " " + currSplit[:len(currSplit)-1]
} else {
currSplit = strings.ReplaceAll(currSplit, "\\\"", "\"")
results[len(results)-1] = results[len(results)-1] + " " + currSplit
}
}
}
return results
}

View File

@@ -0,0 +1,173 @@
package telegrampackage
import (
"errors"
"fmt"
"log"
"math/rand"
"strings"
"time"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/google/uuid"
"gorm.io/gorm"
)
type ChatIDMap struct {
ID uuid.UUID `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
ChatID int64
ChatIDShort string
}
func (env *Env) TelegramSend(chatIDShort string, msg string) error {
if chatIDShort == "" {
return errors.New("no chat ID provided")
}
bot, err := tgbotapi.NewBotAPI(env.TelegramAPIKey)
if err != nil {
log.Println(err)
return err
}
var chatIDMap ChatIDMap
err = env.DB.Where(&ChatIDMap{ChatIDShort: chatIDShort}).Last(&chatIDMap).Error
if err != nil {
log.Println(err)
log.Println("No such telegram chat ID")
return err
}
chatMsg := tgbotapi.NewMessage(chatIDMap.ChatID, msg)
_, err = bot.Send(chatMsg)
if err != nil {
log.Println(err)
}
return nil
}
func (env *Env) TelegramListenAndGen() error {
for {
bot, err := tgbotapi.NewBotAPI(env.TelegramAPIKey)
if err != nil {
log.Println(err)
log.Println("Error occured on Telegram listen. Waiting 1 minute")
time.Sleep(60 * time.Second)
}
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates := bot.GetUpdatesChan(u)
for update := range updates {
if update.Message == nil { // ignore any non-Message Updates
continue
}
log.Printf("New message: [%s] %s", update.Message.From.UserName, update.Message.Text)
// check if contains registration
if strings.Compare(update.Message.Text, "/register") == 0 {
var chatIDMap ChatIDMap
err := env.DB.Where(&ChatIDMap{ChatID: update.Message.Chat.ID}).Last(&chatIDMap).Error
// chatID already exists
if err == nil {
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "You already have a chat ID")
_, err := bot.Send(msg)
if err != nil {
log.Println(err)
}
msg = tgbotapi.NewMessage(update.Message.Chat.ID, fmt.Sprintf("Your chat ID is: %s", chatIDMap.ChatIDShort))
_, err = bot.Send(msg)
if err != nil {
log.Println(err)
}
} else {
currChatCode := genShortCode(5)
chatIDMap.ChatIDShort = currChatCode
chatIDMap.ChatID = update.Message.Chat.ID
err := env.DB.Create(&chatIDMap).Error
if err != nil {
fmt.Println(err)
}
msg := tgbotapi.NewMessage(update.Message.Chat.ID, fmt.Sprintf("Your chat ID is: %s", chatIDMap.ChatIDShort))
_, err = bot.Send(msg)
if err != nil {
log.Println(err)
}
}
} else {
// Get his current chat ID
var chatIDMap ChatIDMap
err := env.DB.Where(&ChatIDMap{ChatID: update.Message.Chat.ID}).Last(&chatIDMap).Error
if err != nil {
fmt.Println(err)
}
var handled = false
for _, currFunc := range env.HandlerFunctions {
currHandled, responseText := currFunc(chatIDMap.ChatIDShort, update.Message.Text)
handled = handled || currHandled
if responseText != nil {
splitSendMessage(bot, update.Message.Chat.ID, *responseText)
}
}
if !handled {
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "Please send /register to register for a chat ID")
_, err := bot.Send(msg)
if err != nil {
log.Println(err)
}
}
}
}
}
}
func genShortCode(n int) string {
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
runeCode := make([]rune, n)
for i := range runeCode {
runeCode[i] = letters[rand.Intn(len(letters))]
}
return string(runeCode)
}
func splitSendMessage(bot *tgbotapi.BotAPI, chatID int64, message string) {
MAXMESSAGELENGTH := 2000
leftoverMessage := []rune(tgbotapi.EscapeText("HTML", message))
if len(leftoverMessage) > MAXMESSAGELENGTH {
for len(leftoverMessage) > 0 {
var currMessage []rune
if len(leftoverMessage) <= MAXMESSAGELENGTH {
currMessage = leftoverMessage[:]
leftoverMessage = []rune("")
} else {
currMessage = leftoverMessage[:MAXMESSAGELENGTH]
leftoverMessage = leftoverMessage[MAXMESSAGELENGTH:]
}
msg := tgbotapi.NewMessage(chatID, string(currMessage))
msg.ParseMode = "HTML"
msg.DisableWebPagePreview = true
_, err := bot.Send(msg)
if err != nil {
msg := tgbotapi.NewMessage(chatID, err.Error())
bot.Send(msg)
log.Println(err)
}
}
} else {
msg := tgbotapi.NewMessage(chatID, string(message))
msg.ParseMode = "HTML"
msg.DisableWebPagePreview = true
_, err := bot.Send(msg)
if err != nil {
msg := tgbotapi.NewMessage(chatID, err.Error())
bot.Send(msg)
log.Println(err)
}
}
}