用Golang和Mongodb的电报机器人
#go #mongodb #telegrambot #bot

所以在周末,我正在研究一个电报机器人,该机器人是管理一个特定的电报组。想知道机器人有什么?

  1. 该机器人欢迎新添加的用户到Telegram Group
  2. 删除用户发送给组的链接,除了管理员
  3. 删除新用户发送给该组的每个消息,直到他们向组添加了一定数量的用户,并且可以将消息发送给组

在本文中,我将向您展示如何使用Golang和MongoDB创建电报机器人。首先在电报上搜索“ botfather”并创建一个newbot。为您的机器人设置名称和用户名之后,将发送给您的令牌。这个令牌将用于验证您的bot。

这是.env配置:

TOKEN=<generated token from botfather in telegram>

USER_NAME=<the group admin username>

MONGO_URI=mongodb://localhost:27017<for local host mongodb>
DATABASE_NAME=<database name>

这是机器人的代码:

package tele

import (
    "encoding/json"
    "fmt"
    "log"
    "os"
    "strings"

    tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
    "github.com/hisyntax/telebot/database"
    "go.mongodb.org/mongo-driver/bson"
)

func urlChecker(character string) bool {
    var val bool
    //check if the string contains a .
    if strings.Contains(character, ".") {
        for i, value := range character {
            //get the index of .
            if string(value) == "." {
                fmt.Printf("%d - %v\n", i, string(value))
                prev := i - 1
                next := i + 1
                for e, v := range character {
                    //check the previous character if its an "" string
                    if e == prev {
                        if string(v) != " " && string(v) != "." {
                            //check the next character if its an "" string
                            for ee, vv := range character {
                                if ee == next {
                                    if string(vv) != " " && string(vv) != "." {
                                        val = true
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return val
}

func Bot() {
    token := os.Getenv("TOKEN")
    bot, err := tgbotapi.NewBotAPI(token)
    if err != nil {
        log.Panic(err)
    }

    bot.Debug = true

    log.Printf("Authorized on account %s", bot.Self.UserName)

    u := tgbotapi.NewUpdate(0)
    u.Timeout = 60

    updates := bot.GetUpdatesChan(u)

    for update := range updates {
        if update.Message != nil {
            log.Printf("[%s] %s\n", update.Message.From.UserName, update.Message.Text)


            // THESE APPLIES TO EVERYONE IN THE GROUP EXCEPT THE ADMIN OF THE GROUP
            foundUser := update.Message.From.UserName
            if foundUser != os.Getenv("USER_NAME") {

                //welcome new users
                wc := update.Message.NewChatMembers
                if wc != nil {
                    var byt []map[string]string

                    jsonM, _ := json.Marshal(wc)

                    json.Unmarshal(jsonM, &byt)
                    for val := range byt {
                        if byt[val]["first_name"] != "" {
                            firstname := byt[val]["first_name"]

                            sendMsg := fmt.Sprintf("your message")
                            msg := tgbotapi.NewMessage(update.Message.Chat.ID, sendMsg)

                            bot.Send(msg)
                        }
                    }
                }

                if update.Message.NewChatMembers != nil {

                    up := update.Message
                    var addedUsers database.AddedUsers
                    jsonr, _ := json.Marshal(up)

                    json.Unmarshal(jsonr, &addedUsers)
                    insertID, _ := database.CreateMongoDoc(database.UserCollection, addedUsers)
                    fmt.Printf("Mongodb data created with ID: %v\n", insertID)

                }

                usersFirstname := update.Message.From.FirstName
                //delete messages that contains link sent by other users aside from the admin
                domain := urlChecker(update.Message.Text)
                if domain {

                    deleteMsg := tgbotapi.NewDeleteMessage(update.Message.Chat.ID, update.Message.MessageID)
                    bot.Send(deleteMsg)

                    //notify they user that links can't be sent to the group
                    sendMsg := fmt.Sprintf("%s The message you sent contains a link or you failed to add a space after the full stop(.). Links cannot be sent to this group", usersFirstname)
                    msg := tgbotapi.NewMessage(update.Message.Chat.ID, sendMsg)

                    bot.Send(msg)
                } else { //if the messages sent to the group is not a link

                    //check if the text message sent is not empty
                    if update.Message.Text != "" {
                        //check if the user have already added _ number of users to the group
                        countFilter := bson.M{"from.firstname": update.Message.From.FirstName}
                        addedUserCount := database.CountCollection(database.UserCollection, countFilter)
                        fmt.Printf("This is the number of users you have added to the group %v\n....", addedUserCount)
                        userNum := 5
                        if addedUserCount < userNum {
                            // delete the messages sent to the group by the user who have not added the set numbers of users
                            deleteMsg := tgbotapi.NewDeleteMessage(update.Message.Chat.ID, update.Message.MessageID)
                            bot.Send(deleteMsg)

                            fmt.Println(deleteMsg)
                            // and if not delete their message and notify them to first add _ numbers of users before they can send in messages
                            usersToAdd := userNum - addedUserCount
                            sendMsg := fmt.Sprintf("%s you have only added %v user(s). You need to add %v more user(s) to be able to send messages to this group. If you can't follow the process send a DM to @EXODUSTV to pay #500 and get verified to the VCF file", usersFirstname, addedUserCount, usersToAdd)
                            msg := tgbotapi.NewMessage(update.Message.Chat.ID, sendMsg)
                            // msg.ReplyToMessageID = update.Message.MessageID
                            bot.Send(msg)
                        }
                    }
                }

            }

        }
    }
}

这是mongodb代码:

package database

import (
    "context"
    "fmt"
    "log"
    "os"
    "time"

    "github.com/joho/godotenv"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)


var (
    UserCollection  *mongo.Collection = OpenCollection(Client, "users")
)

type AddedUsers struct {
    From           From             `json:"from"`
    NewChatMembers []NewChatMembers `json:"new_chat_members"`
}

type From struct {
    ID        int64  `json:"id"`
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
    Username  string `json:"username"`
}

type NewChatMembers struct {
    ID        int64  `json:"id"`
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
    Username  string `json:"username"`
}


func DbInstance() *mongo.Client {
    if err := godotenv.Load(); err != nil {
        log.Println("no env gotten")
    }
    MongoDb := os.Getenv("MONGO_URI")
    client, err := mongo.NewClient(options.Client().ApplyURI(MongoDb))
    if err != nil {
        log.Fatal(err)
    }

    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    err = client.Connect(ctx)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("successfully connected to mongodb")
    return client
}

var Client *mongo.Client = DbInstance()

func OpenCollection(client *mongo.Client, collectionName string) *mongo.Collection {
    if err := godotenv.Load(); err != nil {
        log.Println("no env gotten")
    }
    databaseName := os.Getenv("DATABASE_NAME")
    var collection *mongo.Collection = client.Database(databaseName).Collection(collectionName)
    return collection
}

func GetMongoDoc(colName *mongo.Collection, filter interface{}) (*AddedUsers, error) {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    var data AddedUsers

    if err := colName.FindOne(ctx, filter).Decode(&data); err != nil {
        return nil, err
    }

    return &data, nil
}

func GetMongoDocs(colName *mongo.Collection, filter interface{}, opts ...*options.FindOptions) (*[]AddedUsers, error) {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    var data []AddedUsers

    filterCusor, err := colName.Find(ctx, filter, opts...)
    if err != nil {
        return nil, err
    }

    if err := filterCusor.All(ctx, &data); err != nil {
        return nil, err
    }

    return &data, nil
}

func CreateMongoDoc(colName *mongo.Collection, data interface{}) (*mongo.InsertOneResult, error) {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    insertNum, insertErr := colName.InsertOne(ctx, data)
    if insertErr != nil {
        return nil, insertErr
    }

    return insertNum, nil
}

func CountCollection(colName *mongo.Collection, filter interface{}) int {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    count, err := colName.CountDocuments(ctx, filter)

    if err != nil {
        return 0
    }
    return int(count)
}

这是我的main.go文件中的代码:

package main

import (
    "log"

    "github.com/hisyntax/telebot/tele"
    "github.com/joho/godotenv"
)

func main() {
    if err := godotenv.Load(); err != nil {
        log.Println(".env not found")
    }

    tele.Bot()
}

之后,您已经完成了机器人,您需要将其部署到服务器。 Heroku与之合作不佳,因此我强烈建议您在https://railway.app上部署机器人。成功部署到服务器的机器人后,将您的机器人添加到您希望为您管理的组中,然后将机器人作为管理员在组中。您的机器人现在设置为:)

我希望这可以帮助您构建自己的电报机器人。您可以查看此GitHub存储库github.com/hisyntax/telebot的完整代码。