From 94643557aeddbc37f0b84d8da62db5eb5a9f06cb Mon Sep 17 00:00:00 2001 From: AzatF Date: Sat, 9 Jul 2022 00:48:15 +0700 Subject: [PATCH 1/7] first version --- README.md | 12 ++ cmd/main.go | 89 ++++++++++ conf.yml | 23 +++ go.mod | 18 ++ go.sum | 26 +++ internal/callbackmsg/callbackmsg.go | 83 +++++++++ internal/chatmembers/chatmembers.go | 63 +++++++ internal/comandmsg/comandmsg.go | 94 ++++++++++ internal/config/config.go | 55 ++++++ internal/config/constants.go | 15 ++ internal/data/data.go | 28 +++ internal/functions/functions.go | 263 ++++++++++++++++++++++++++++ internal/menu/menu.go | 21 +++ internal/socialmsg/socialmsg.go | 27 +++ internal/textmsg/textmsg.go | 227 ++++++++++++++++++++++++ pkg/client/telegram/client.go | 31 ++++ pkg/logging/logging.go | 47 +++++ 17 files changed, 1122 insertions(+) create mode 100644 cmd/main.go create mode 100755 conf.yml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/callbackmsg/callbackmsg.go create mode 100644 internal/chatmembers/chatmembers.go create mode 100644 internal/comandmsg/comandmsg.go create mode 100755 internal/config/config.go create mode 100755 internal/config/constants.go create mode 100755 internal/data/data.go create mode 100755 internal/functions/functions.go create mode 100755 internal/menu/menu.go create mode 100644 internal/socialmsg/socialmsg.go create mode 100644 internal/textmsg/textmsg.go create mode 100755 pkg/client/telegram/client.go create mode 100755 pkg/logging/logging.go diff --git a/README.md b/README.md index 1164b0e..c4c7f5f 100644 --- a/README.md +++ b/README.md @@ -1 +1,13 @@ # tg-bot-users 🤖 + +# Список команд: + +1. /menu (Список команд) +2. /jubileelist (выводин список юбилейных пользователей) +3. /addmoderatorgroup номер (добавление группы модераторов) +4. Меню. (список команд) +5. Привет, Здравствуйте и т.п. приветствия. +6. Доброе утро. +7. Спокойной ночи. +8. Комплимент. (А так же, Мужской и Женский) +9. Мат слово (Слово будет добавлено в базу нецензурных слов) \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..1d9280b --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,89 @@ +package main + +import ( + "flag" + "log" + "skbot/internal/callbackmsg" + "skbot/internal/chatmembers" + "skbot/internal/comandmsg" + "skbot/internal/config" + "skbot/internal/functions" + "skbot/internal/socialmsg" + "skbot/internal/textmsg" + "skbot/pkg/client/telegram" + "skbot/pkg/logging" +) + +var cfgPath string + +func init() { + flag.StringVar(&cfgPath, "config", "tg-bot-users/conf.yml", "config file path") +} + +func main() { + + log.Print("config initializing") + cfg := config.GetConfig(cfgPath) + + log.Print("logger initializing") + logger := logging.GetLogger(cfg.AppConfig.LogLevel) + + modGroupId := cfg.ModersGroupID.ModeratorsGroup + _, _, err := functions.AddModeratorsGroup(cfg.ModersGroupID.ModeratorsGroup) + _, _, err = functions.AddModeratorsGroup(cfg.ModersGroupID.ModeratorsGroupGolang) + _, _, err = functions.AddModeratorsGroup(cfg.ModersGroupID.ModeratorsGroupJava) + _, _, err = functions.AddModeratorsGroup(cfg.ModersGroupID.ModeratorsGroupPython) + _, _, err = functions.AddModeratorsGroup(cfg.ModersGroupID.ModeratorsGroup1S) + _, _, err = functions.AddModeratorsGroup(cfg.ModersGroupID.ModeratorsGroupCSharp) + if err != nil { + logger.Info(err) + } + + updChan, bot, err := telegram.StartBotByChan(cfg, logger) + if err != nil { + logger.Fatal(err) + } + defer bot.StopReceivingUpdates() + + for { + + update := <-updChan + + // make slice from text message + //if update.Message != nil { + // command := strings.Split(update.Message.Text, " ") + //} else { + // continue + //} + if update.Message != nil { + + // text messages operations + textmsg.WithTextQueryDo(update, bot, logger, modGroupId) + + // social messages from bot in chat + socialmsg.WithSocialTextQueryDo(update, bot, logger) + } else if update.CallbackQuery != nil { + + callbackmsg.WithCallBackDo(update, bot, logger, modGroupId) + + } else if update.Message.Command() != "" { + + //com menu (only moderator's chats) + comandmsg.CommandQueryDo(update, bot, logger) + } else if update.Message.NewChatMembers != nil { + + chatmembers.WithChatMembersDo(update, bot, logger) + } + + // TODO inline help + if update.InlineQuery != nil { + log.Println("response from Inline query") + query := update.InlineQuery.Query + + log.Println(query) + + } + + } + +} diff --git a/conf.yml b/conf.yml new file mode 100755 index 0000000..d4091d4 --- /dev/null +++ b/conf.yml @@ -0,0 +1,23 @@ +--- + + +telegram: + tg_token: + tg_sert: + + + +app: + log_level: trace + +chat_count_config: + test_chat_id_count: + chat_id_count: + +moderators: + moderators_group: + moderators_group_golang: + moderators_group_java: + moderators_group_python: + moderators_group_1s: + moderators_group_csharp: diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7d922e3 --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module skbot + +go 1.18 + +require ( + github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 + github.com/ilyakaznacheev/cleanenv v1.3.0 + github.com/mattn/go-sqlite3 v1.14.14 + github.com/sirupsen/logrus v1.8.1 +) + +require ( + github.com/BurntSushi/toml v1.1.0 // indirect + github.com/joho/godotenv v1.4.0 // indirect + golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..220a7ff --- /dev/null +++ b/go.sum @@ -0,0 +1,26 @@ +github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc= +github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8= +github.com/ilyakaznacheev/cleanenv v1.3.0 h1:RapuLclPPUbmdd5Bi5UXScwMEZA6+ZNLU5OW9itPjj0= +github.com/ilyakaznacheev/cleanenv v1.3.0/go.mod h1:i0owW+HDxeGKE0/JPREJOdSCPIyOnmh6C0xhWAkF/xA= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ= +olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw= diff --git a/internal/callbackmsg/callbackmsg.go b/internal/callbackmsg/callbackmsg.go new file mode 100644 index 0000000..cc172b6 --- /dev/null +++ b/internal/callbackmsg/callbackmsg.go @@ -0,0 +1,83 @@ +package callbackmsg + +import ( + "fmt" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" + "skbot/internal/config" + "skbot/internal/functions" + "skbot/internal/menu" + "skbot/pkg/logging" + "time" +) + +func WithCallBackDo(update tgbotapi.Update, bot *tgbotapi.BotAPI, logger *logging.Logger, modGroupId int64) { + + data := update.CallbackQuery.Data + + switch data { + + case "com_list": + + msg := tgbotapi.NewMessage(update.CallbackQuery.Message.Chat.ID, menu.ComMenu) + msg.ParseMode = "markdown" + delMsg, _ := bot.Send(msg) + + callback := tgbotapi.NewCallback(update.CallbackQuery.ID, "✅") + if _, err := bot.Request(callback); err != nil { + logger.Error(err) + } + + go func() { + time.Sleep(30 * time.Second) + _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.CallbackQuery.Message.Chat.ID, delMsg.MessageID)) + }() + + case "jubilee_list": + + var list string + var count = 1 + users, err := functions.GetJubileeUsers() + chatId := update.CallbackQuery.Message.Chat.ID + if err != nil { + logger.Info(err) + } + + moderGroupList, err := functions.GetModeratorsGroup() + if err != nil { + logger.Error(err) + } + + for _, group := range moderGroupList { + + if group.GroupID == chatId { + + for _, user := range users { + // TODO take id from base to number users in list + text := fmt.Sprintf("*№%d* \nГруппа: *%s*\nИмя: *%s* Ник: *@%s*\nНомер: *%d* "+ + "Время: *%s* ", count, user.GroupName, user.UserName, user.UserNick, + user.Serial, user.Time.Format(config.StructDateTimeFormat)) + + list = list + text + "\n\n" + count++ + + } + } + } + msg := tgbotapi.NewMessage(update.CallbackQuery.Message.Chat.ID, "Список юбилейный:\n"+list) + msg.ParseMode = "markdown" + _, _ = bot.Send(msg) + + callback := tgbotapi.NewCallback(update.CallbackQuery.ID, "✅") + if _, err := bot.Request(callback); err != nil { + logger.Error(err) + } + + case "add_mod": + + callback := tgbotapi.NewCallback(update.CallbackQuery.ID, "✅") + if _, err := bot.Request(callback); err != nil { + logger.Error(err) + } + + } +} diff --git a/internal/chatmembers/chatmembers.go b/internal/chatmembers/chatmembers.go new file mode 100644 index 0000000..74a86d9 --- /dev/null +++ b/internal/chatmembers/chatmembers.go @@ -0,0 +1,63 @@ +package chatmembers + +import ( + "fmt" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" + "skbot/internal/config" + "skbot/internal/functions" + "skbot/pkg/logging" + "time" +) + +func WithChatMembersDo(update tgbotapi.Update, bot *tgbotapi.BotAPI, logger *logging.Logger) { + + newUser := update.Message.NewChatMembers[0] + chatId := update.Message.Chat.ID + groupName := update.Message.Chat.Title + + if !newUser.IsBot { + count, err := bot.GetChatMembersCount(tgbotapi.ChatMemberCountConfig{ + ChatConfig: tgbotapi.ChatConfig{ + ChatID: chatId, + SuperGroupUsername: groupName, + }, + }) + + if count%500 == 0 || count%500 == 1 || count%500 == 2 || count == 4 { + + err = functions.AddNewJubileeUser(&newUser, count, groupName) + if err != nil { + logger.Error(err) + } + + moderGroupList, err := functions.GetModeratorsGroup() + if err != nil { + logger.Error(err) + } + + for _, group := range moderGroupList { + + text := fmt.Sprintf("🎉 В группу: %s вступил юбилейный пользователь\n%s "+ + "(@%s), %d. \nВремя вступления %s", + groupName, newUser.FirstName, newUser.UserName, count, + time.Now().Format(config.StructDateTimeFormat)) + + _, _ = bot.Send(tgbotapi.NewMessage(group.GroupID, text)) + } + + } + + msg := tgbotapi.NewMessage(chatId, fmt.Sprintf("_Рады вас приветствовать_ "+ + "*%s*, _расскажите нам о себе пожалуйста._", newUser.FirstName)) + + msg.ParseMode = "markdown" + ans, _ := bot.Send(msg) + + go func() { + + time.Sleep(20 * time.Second) + _, _ = bot.Send(tgbotapi.NewDeleteMessage(chatId, ans.MessageID)) + }() + } + +} diff --git a/internal/comandmsg/comandmsg.go b/internal/comandmsg/comandmsg.go new file mode 100644 index 0000000..f309aca --- /dev/null +++ b/internal/comandmsg/comandmsg.go @@ -0,0 +1,94 @@ +package comandmsg + +import ( + "fmt" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" + "skbot/internal/config" + "skbot/internal/functions" + "skbot/internal/menu" + "skbot/pkg/logging" + "time" +) + +func CommandQueryDo(update tgbotapi.Update, bot *tgbotapi.BotAPI, logger *logging.Logger) { + + // com menu (only moderator's chats) ---------------------------- + if update.Message.Command() == "menu" { + + moderGroupList, err := functions.GetModeratorsGroup() + if err != nil { + logger.Error(err) + } + + for _, group := range moderGroupList { + + if group.GroupID == update.Message.Chat.ID { + + msg := tgbotapi.NewMessage(update.Message.Chat.ID, menu.ComMenu) + + del, _ := bot.Send(msg) + + go func() { + time.Sleep(60 * time.Second) + msDel := tgbotapi.NewDeleteMessage(update.Message.Chat.ID, del.MessageID) + _, _ = bot.Send(msDel) + msg.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true) + + }() + + } + } + + } + + // LIST of all jubilee users -------------------------------------- + if update.Message.Command() == "jubileelist" { + + users, err := functions.GetJubileeUsers() + chatId := update.Message.Chat.ID + if err != nil { + logger.Info(err) + } + + moderGroupList, err := functions.GetModeratorsGroup() + if err != nil { + logger.Error(err) + } + for _, group := range moderGroupList { + + if group.GroupID == chatId { + + for _, user := range users { + + text := fmt.Sprintf("*Группа:* _%s_\n*Имя:* %s\n*Ник:* @%s\n*Номер вступления:* %d\n"+ + "*Время вступления:* %s ", user.GroupName, user.UserName, user.UserNick, + user.Serial, user.Time.Format(config.StructDateTimeFormat)) + + msg := tgbotapi.NewMessage(chatId, text) + msg.ParseMode = "markdown" + _, _ = bot.Send(msg) + + } + } + } + + } + + //if update.Message.Command() == "12" { + // + // msg := tgbotapi.NewMessage(update.Message.Chat.ID, "keyboard") + // + // msg.ReplyMarkup = menu.NumericKeyboard + // + // _, err := bot.Send(msg) + // if err != nil { + // logger.Error(err) + // } + // + // go func() { + // time.Sleep(30 * time.Second) + // msg.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true) + // }() + //} + +} diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100755 index 0000000..76e0788 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,55 @@ +package config + +import ( + "github.com/ilyakaznacheev/cleanenv" + "log" + "sync" +) + +type Config struct { + Telegram struct { + Token string `yaml:"tg_token" env:"TG-BOT-TOKEN" env-required:"true"` + Sert string `yaml:"tg_sert"` + } + YouTube struct { + APIURL string `yaml:"api_url"` + AccessToken string `yaml:"access_token"` + } + AppConfig AppConfig `yaml:"app"` + ChatCountConfig ChatCountConfig `yaml:"chat_count_config"` + ModersGroupID ModersGroupID `yaml:"moderators"` +} + +type AppConfig struct { + LogLevel string `yaml:"log_level" env:"TG-BOT-LogLevel" env-default:"error" env-required:"true"` +} + +type ChatCountConfig struct { + TestChatIdCount int64 `yaml:"test_chat_id_count"` + ChatIdCount int64 `yaml:"chat_id_count"` +} + +type ModersGroupID struct { + ModeratorsGroup int64 `yaml:"moderators_group" env:"moderators_group" env-required:"true"` + ModeratorsGroupGolang int64 `yaml:"moderators_group_golang" env:"moderators_group_golang"` + ModeratorsGroupJava int64 `yaml:"moderators_group_java" env:"moderators_group_java"` + ModeratorsGroupPython int64 `yaml:"moderators_group_python" env:"moderators_group_python"` + ModeratorsGroup1S int64 `yaml:"moderators_group_1s" env:"moderators_group_1s"` + ModeratorsGroupCSharp int64 `yaml:"moderators_group_csharp" env:"moderators_group_csharp"` +} + +var instance *Config +var once sync.Once + +func GetConfig(path string) *Config { + once.Do(func() { + log.Printf("read application config from path %s", path) + + instance = &Config{} + + if err := cleanenv.ReadConfig(path, instance); err != nil { + log.Fatal(err) + } + }) + return instance +} diff --git a/internal/config/constants.go b/internal/config/constants.go new file mode 100755 index 0000000..083af3f --- /dev/null +++ b/internal/config/constants.go @@ -0,0 +1,15 @@ +package config + +const StructDateTimeFormat = "2006-01-02 15:04" +const StructDateFormat = "2006-01-02" +const StructTimeFormat = "15:04" +const ( + Jubileelist = "jubileelist" +) + +var SocialMessage bool + +//var SocialChoice = SocialDown +//var SocialUP = "Включено" +//var SocialDown = "Выключено" +//var SocText = fmt.Sprintf("Социальные сообщения: %s", SocialChoice) diff --git a/internal/data/data.go b/internal/data/data.go new file mode 100755 index 0000000..33c793b --- /dev/null +++ b/internal/data/data.go @@ -0,0 +1,28 @@ +package data + +import "time" + +type User struct { + ID int + Name string + Sex string +} + +type BadWords struct { + ID int + Word string +} +type ModeratorsGroup struct { + ID int + GroupID int64 +} + +type JubileeUser struct { + ID int + Serial int + UserID int + UserName string + UserNick string + Time time.Time + GroupName string +} diff --git a/internal/functions/functions.go b/internal/functions/functions.go new file mode 100755 index 0000000..a797d1b --- /dev/null +++ b/internal/functions/functions.go @@ -0,0 +1,263 @@ +package functions + +import ( + "database/sql" + "errors" + "fmt" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" + _ "github.com/mattn/go-sqlite3" + "log" + "skbot/internal/data" + "strings" +) + +var ( + qb = "CREATE TABLE IF NOT EXISTS badwords (id INTEGER PRIMARY KEY, word VARCHAR (30) NOT NULL)" + + qbu = "SELECT * FROM badwords" + + mod = "CREATE TABLE IF NOT EXISTS moderators (id INTEGER PRIMARY KEY, groupid INTEGER NOT NULL)" + + modSel = "SELECT * FROM moderators" + + addNewUsersDB = "CREATE TABLE IF NOT EXISTS newJubileeUsers (id INTEGER PRIMARY KEY, serial INTEGER NOT NULL, " + + "user_id INTEGER NOT NULL, user_name VARCHAR (30) NOT NULL, user_nick VARCHAR (50) DEFAULT ('нет ника'), " + + "time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, group_name VARCHAR (50) NOT NULL)" +) + +func TrimSymbolsFromSlice(s []string) (words []string, err error) { + + var messageUpd []string + + for _, k := range s { + + k = strings.Trim(k, "([]{}*).,!") + messageUpd = append(messageUpd, k) + } + + words = messageUpd + + return words, nil +} + +func CheckBadWords(badList []string) (clearList []string, haveBadWords bool, err error) { + + var badWords []data.BadWords + var badWord data.BadWords + haveBadWords = false + + db, err := sql.Open("sqlite3", "./tg-bot-users/internal/sqlitedb/badwords.db") + if err != nil { + return + } + + rows, err := db.Query(qbu) + if err != nil { + return nil, false, err + } + + defer db.Close() + + for rows.Next() { + err = rows.Scan(&badWord.ID, &badWord.Word) + badWords = append(badWords, badWord) + } + + for _, word := range badList { + + for _, bad := range badWords { + + if word == bad.Word { + + log.Println("найдено совпадение матерного слова в базе", word) + haveBadWords = true + } + + } + + } + + return clearList, haveBadWords, err + +} + +func AddBadWord(word string) (bool, error) { + + var badWord data.BadWords + var haveWord = false + + db, err := sql.Open("sqlite3", "./tg-bot-users/internal/sqlitedb/badwords.db") + if err != nil { + return false, err + } + + stat, err := db.Prepare(qb) + if err != nil { + return false, err + } + + _, _ = stat.Exec() + + rows, err := db.Query(qbu) + if err != nil { + } + + defer db.Close() + + for rows.Next() { + err = rows.Scan(&badWord.ID, &badWord.Word) + if badWord.Word == word { + haveWord = true + return true, nil + } + } + + if !haveWord { + + stat, err = db.Prepare(fmt.Sprintf("INSERT INTO badwords (word) VALUES ('%s')", word)) + stat.Exec() + if err != nil { + return false, errors.New("ошибка добавления матерного слова в базу") + + } else { + return true, errors.New("новое матерное слово занесено в базу") + } + } + + return true, errors.New("added") + +} + +func AddModeratorsGroup(group int64) (haveGroup bool, modGroups []data.ModeratorsGroup, err error) { + + var modGroup data.ModeratorsGroup + haveGroup = false + + db, err := sql.Open("sqlite3", "./tg-bot-users/internal/sqlitedb/moderators.db") + if err != nil { + return haveGroup, nil, err + } + + defer db.Close() + + stat, err := db.Prepare(mod) + if err != nil { + log.Println(err) + } + + _, err = stat.Exec() + if err != nil { + return haveGroup, nil, err + } + + rows, err := db.Query(modSel) + if err != nil { + log.Println(err) + } + + for rows.Next() { + err = rows.Scan(&modGroup.ID, &modGroup.GroupID) + modGroups = append(modGroups, modGroup) + } + + for _, grp := range modGroups { + if grp.GroupID == group { + haveGroup = true + return haveGroup, modGroups, errors.New("have group") + } + } + + if !haveGroup && group != 0 { + stat, err = db.Prepare(fmt.Sprintf("INSERT INTO moderators (groupid) VALUES ('%d')", group)) + if err != nil { + log.Println(err) + } + _, _ = stat.Exec() + haveGroup = true + } + return haveGroup, modGroups, nil +} + +func GetModeratorsGroup() (groups []data.ModeratorsGroup, err error) { + + var group data.ModeratorsGroup + + db, err := sql.Open("sqlite3", "./tg-bot-users/internal/sqlitedb/moderators.db") + if err != nil { + return nil, err + } + + defer db.Close() + + rows, err := db.Query(modSel) + if err != nil { + log.Println(err) + } + + for rows.Next() { + err = rows.Scan(&group.ID, &group.GroupID) + groups = append(groups, group) + } + + return + +} + +func AddNewJubileeUser(newUser *tgbotapi.User, serial int, groupName string) error { + + db, err := sql.Open("sqlite3", "./tg-bot-users/internal/sqlitedb/newJubileeUsers.db") + if err != nil { + return err + } + defer db.Close() + + log.Println("создание таблицы") + stat, err := db.Prepare(addNewUsersDB) + if err != nil { + return err + } + _, _ = stat.Exec() + + stat, err = db.Prepare(fmt.Sprintf("INSERT INTO newJubileeUsers (serial, user_id, user_name, user_nick, "+ + "group_name) VALUES ('%d', '%d', '%s', '%s', '%s')", serial, newUser.ID, newUser.FirstName, newUser.UserName, groupName)) + if err != nil { + log.Println(err) + } + _, err = stat.Exec() + if err != nil { + log.Println(err) + } + + return nil +} + +func GetJubileeUsers() (jubUsers []data.JubileeUser, err error) { + + var user data.JubileeUser + var users []data.JubileeUser + + db, err := sql.Open("sqlite3", "./tg-bot-users/internal/sqlitedb/newJubileeUsers.db") + if err != nil { + return nil, err + } + defer db.Close() + + rows, err := db.Query("SELECT * FROM newJubileeUsers") + if err != nil { + return nil, err + } + + for rows.Next() { + err = rows.Scan(&user.ID, &user.Serial, &user.UserID, &user.UserName, &user.UserNick, &user.Time, &user.GroupName) + users = append(users, user) + } + + for _, v := range users { + if v.Serial%500 == 0 || v.Serial%500 == 1 || v.Serial%500 == 2 || v.Serial%4 == 0 { + jubUsers = append(jubUsers, v) + } + } + + return jubUsers, nil + +} diff --git a/internal/menu/menu.go b/internal/menu/menu.go new file mode 100755 index 0000000..d817fda --- /dev/null +++ b/internal/menu/menu.go @@ -0,0 +1,21 @@ +package menu + +import ( + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" +) + +const ComMenu = " Список доступных вам команд: 🛠 \n \n" + + "✅ `addmoderatorgroup` + номер _(добавление группы модераторов)._\n" + + "✅ `chatinfo` _(информация о имени и ID группы будет отправлено в админку," + + " сообщение будет удалено из группы пользователей, если бот админ. )_\n" + + "✅ *Мат + слово* _(Слово будет добавлено в базу)._\n" + +var NumericKeyboard = tgbotapi.NewInlineKeyboardMarkup( + tgbotapi.NewInlineKeyboardRow(button1), + tgbotapi.NewInlineKeyboardRow(button2), + tgbotapi.NewInlineKeyboardRow(button3), +) + +var button1 = tgbotapi.NewInlineKeyboardButtonData("Список команд", "com_list") +var button2 = tgbotapi.NewInlineKeyboardButtonData("Список юбилейный", "jubilee_list") +var button3 = tgbotapi.NewInlineKeyboardButtonData("Добавить группу администраторов", "add_mod") diff --git a/internal/socialmsg/socialmsg.go b/internal/socialmsg/socialmsg.go new file mode 100644 index 0000000..5d1999a --- /dev/null +++ b/internal/socialmsg/socialmsg.go @@ -0,0 +1,27 @@ +package socialmsg + +import ( + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" + "skbot/internal/functions" + "skbot/pkg/logging" + "strings" +) + +func WithSocialTextQueryDo(update tgbotapi.Update, bot *tgbotapi.BotAPI, logger *logging.Logger) { + + // trim symbols and make slice from text message + if len(update.Message.Text) > 0 { + + command, err := functions.TrimSymbolsFromSlice(strings.Split(update.Message.Text, " ")) + if err != nil { + logger.Info("error trim symbols from message") + } + + switch strings.ToLower(command[0]) { + case "": + + default: + + } + } +} diff --git a/internal/textmsg/textmsg.go b/internal/textmsg/textmsg.go new file mode 100644 index 0000000..8e50268 --- /dev/null +++ b/internal/textmsg/textmsg.go @@ -0,0 +1,227 @@ +package textmsg + +import ( + "fmt" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" + "log" + "skbot/internal/config" + "skbot/internal/functions" + "skbot/internal/menu" + "skbot/pkg/logging" + "strconv" + "strings" + "time" +) + +func WithTextQueryDo(update tgbotapi.Update, bot *tgbotapi.BotAPI, logger *logging.Logger, modGroupId int64) { + + // trim symbols + if len(update.Message.Text) > 0 { + + command, err := functions.TrimSymbolsFromSlice(strings.Split(update.Message.Text, " ")) + if err != nil { + logger.Info("error trim symbols from message") + } + + // menu + //if strings.Contains(strings.ToLower(command[0]), "меню") { + // + // chatMsgDel := update.Message.MessageID + // + // moderGroupList, err := functions.GetModeratorsGroup() + // if err != nil { + // logger.Error(err) + // } + // + // for _, group := range moderGroupList { + // + // if group.GroupID == update.Message.Chat.ID { + // + // del, _ := bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, menu.ComMenu)) + // + // go func() { + // time.Sleep(20 * time.Second) + // _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, del.MessageID)) + // _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, chatMsgDel)) + // }() + // } + // } + //} + + // check jubilee users ! + if strings.Contains(strings.ToLower(command[0]), "списокюбилейный") { + + users, err := functions.GetJubileeUsers() + chatId := update.Message.Chat.ID + if err != nil { + logger.Info(err) + } + + moderGroupList, err := functions.GetModeratorsGroup() + if err != nil { + logger.Error(err) + } + + for _, group := range moderGroupList { + + if group.GroupID == chatId { + + for _, user := range users { + + text := fmt.Sprintf("Группа: %s\nИмя: %s\nНик: @%s\nНомер вступления: %d\n"+ + "Время вступления: %s ", user.GroupName, user.UserName, user.UserNick, + user.Serial, user.Time.Format(config.StructDateTimeFormat)) + + _, _ = bot.Send(tgbotapi.NewMessage(chatId, text)) + + } + } + } + } + + // add moderator group + if strings.Contains(strings.ToLower(command[0]), "addmoderatorgroup") { + + if update.Message.Chat.ID == modGroupId { + + newModGroup, err := strconv.ParseInt(command[1], 10, 64) + if err != nil { + logger.Error(err) + } + + b, _, err := functions.AddModeratorsGroup(newModGroup) + if err != nil { + logger.Error(err) + } + + if b && err != nil { + + _, _ = bot.Send(tgbotapi.NewMessage(modGroupId, fmt.Sprintf("Такая группа уже есть: %d", newModGroup))) + } + + if b && err == nil { + + _, _ = bot.Send(tgbotapi.NewMessage(modGroupId, fmt.Sprintf("Успешно добавлена: %d", newModGroup))) + + } + } + } + + // new users count + if strings.Contains(strings.ToLower(command[0]), "chatinfo") { + delMes := update.Message.MessageID + chatId := update.Message.Chat.ID + groupName := update.Message.Chat.Title + + go func() { + _, _ = bot.Send(tgbotapi.NewDeleteMessage(chatId, delMes)) + }() + + _, err = bot.Send(tgbotapi.NewMessage(modGroupId, fmt.Sprintf( + "ID группы: %d\nИмя группы: %s", chatId, groupName))) + if err != nil { + logger.Error(err) + } + } + + // add bad words to the base + if strings.Contains(strings.ToLower(command[0]), "мат") { + + if len(command) > 1 { + + go func() { + time.Sleep(5 * time.Second) + _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, update.Message.MessageID)) + + }() + + b, err := functions.AddBadWord(command[1]) + if err != nil { + log.Println(err) + } + + if b == true && err == nil { + + del, _ := bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Уже есть.")) + + go func() { + + time.Sleep(5 * time.Second) + _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, del.MessageID)) + + }() + + } else if b == true && err != nil { + + del, _ := bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Добавлено.")) + + go func() { + + time.Sleep(5 * time.Second) + _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, del.MessageID)) + }() + + } + } + } + + // check bad words in chat messages + _, b, err := functions.CheckBadWords(command) + if err != nil { + logger.Error("bad words error", err) + } + + // message to chat where found bad word, copy to moderator + if b && strings.ToLower(command[0]) != "мат" { + + msgID := update.Message.MessageID + badText := update.Message.Text + + go func() { + _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, msgID)) + }() + + badGuyName := update.Message.From.FirstName + badGuyNick := update.Message.From.UserName + badGuyID := update.Message.From.ID + groupName := update.Message.Chat.Title + + modMess := tgbotapi.NewMessage(modGroupId, fmt.Sprintf( + "Замечены нецензурные выражения:\nГруппа: %s\nИмя пользователя: %s\nНик пользователя: "+ + "@%s\nID пользователя: %d\nТекст сообщения: %s\nОригинал сообщения удален из чата.", + groupName, badGuyName, badGuyNick, badGuyID, badText)) + _, _ = bot.Send(modMess) + + cleanAnswer := tgbotapi.NewMessage(update.Message.Chat.ID, fmt.Sprintf( + "Уважаемые коллеги, просим вас воздержаться от нецензурных выражений в %s. "+ + "Сообщение удалено, надеемся на ваше понимание.", groupName)) + del, _ := bot.Send(cleanAnswer) + + go func() { + time.Sleep(30 * time.Second) + _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, del.MessageID)) + }() + } + + if strings.Contains(strings.ToLower(command[0]), "меню") { + + _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, update.Message.MessageID)) + + msg := tgbotapi.NewMessage(update.Message.Chat.ID, "30 seconds") + + msg.ReplyMarkup = menu.NumericKeyboard + + delMes, err := bot.Send(msg) + if err != nil { + logger.Error(err) + } + + go func() { + time.Sleep(30 * time.Second) + _, _ = bot.Send(tgbotapi.NewDeleteMessage(update.Message.Chat.ID, delMes.MessageID)) + }() + } + + } + +} diff --git a/pkg/client/telegram/client.go b/pkg/client/telegram/client.go new file mode 100755 index 0000000..14f6e08 --- /dev/null +++ b/pkg/client/telegram/client.go @@ -0,0 +1,31 @@ +package telegram + +import ( + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" + "log" + "skbot/internal/config" + "skbot/pkg/logging" + "time" +) + +func StartBotByChan(cfg *config.Config, logger *logging.Logger) (tgbotapi.UpdatesChannel, *tgbotapi.BotAPI, error) { + + bot, err := tgbotapi.NewBotAPI(cfg.Telegram.Token) + if err != nil { + log.Fatal(err) + } + + bot.Debug = false + + logger.Infof("Bot %s started at: %v", bot.Self.UserName, time.Now().Format("2 January 2006 15:04")) + + u := tgbotapi.NewUpdate(0) + u.Timeout = 60 + u.Limit = 0 + u.Offset = 0 + + updates := bot.GetUpdatesChan(u) + + return updates, bot, nil + +} diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go new file mode 100755 index 0000000..c1a5057 --- /dev/null +++ b/pkg/logging/logging.go @@ -0,0 +1,47 @@ +package logging + +import ( + "fmt" + "github.com/sirupsen/logrus" + "log" + "os" + "path" + "runtime" +) + +type Logger struct { + *logrus.Entry +} + +func (s *Logger) ExtraFields(fields map[string]interface{}) *Logger { + return &Logger{s.WithFields(fields)} +} + +var instance Logger + +func GetLogger(level string) *Logger { + + logrusLevel, err := logrus.ParseLevel(level) + if err != nil { + log.Fatal(err) + } + + l := logrus.New() + l.SetReportCaller(true) + l.Formatter = &logrus.TextFormatter{ + CallerPrettyfier: func(f *runtime.Frame) (string, string) { + filename := path.Base(f.File) + return fmt.Sprintf("%s:%d", filename, f.Line), fmt.Sprintf("%s()", f.Function) + }, + DisableColors: false, + FullTimestamp: true, + } + + l.SetOutput(os.Stdout) + l.SetLevel(logrusLevel) + + instance = Logger{logrus.NewEntry(l)} + + return &instance + +} From 3db1733641c4074c3ea09dfed247e551f52aced6 Mon Sep 17 00:00:00 2001 From: AzatF Date: Sat, 9 Jul 2022 00:51:15 +0700 Subject: [PATCH 2/7] clean readme --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index c4c7f5f..5b1e80b 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,3 @@ # Список команд: -1. /menu (Список команд) -2. /jubileelist (выводин список юбилейных пользователей) -3. /addmoderatorgroup номер (добавление группы модераторов) -4. Меню. (список команд) -5. Привет, Здравствуйте и т.п. приветствия. -6. Доброе утро. -7. Спокойной ночи. -8. Комплимент. (А так же, Мужской и Женский) -9. Мат слово (Слово будет добавлено в базу нецензурных слов) \ No newline at end of file From 419a2c2aca1182579c62232972f9aa0fe303f8ed Mon Sep 17 00:00:00 2001 From: AzatF Date: Sat, 9 Jul 2022 01:01:44 +0700 Subject: [PATCH 3/7] db add --- internal/sqlitedb/badwords.db | Bin 0 -> 8192 bytes internal/sqlitedb/newJubileeUsers.db | Bin 0 -> 8192 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100755 internal/sqlitedb/badwords.db create mode 100644 internal/sqlitedb/newJubileeUsers.db diff --git a/internal/sqlitedb/badwords.db b/internal/sqlitedb/badwords.db new file mode 100755 index 0000000000000000000000000000000000000000..67af31940cc394ac5810f144df5744e0bd8b98be GIT binary patch literal 8192 zcmeH~K~ED=5XawkQLM0USWzoN!{cB=jT#f=;LR0RB-Vm!H9=2piiSkeSexj91GQ0N ztTa7&@e_ElAjHz9)eqodUOam9=+&ba=hbe6lXo*OyV*ChGynO&-=6l?&E#@%N!`yE zRx(93C5D7$iAzceA;#&B&>b#|Hhp10PZR%Zjf->lrX8xX;EkY*7ZYFtOn?b60Vco% zm;e)C0!)AjFaaj;m%sz7KNgQ$rHNuD`*10n$vw#za*xAjWG3*vw6D_M<)p8|teRZT zskv0zpY;Q^5X{~1f<<-RUp%8sv%2F2GuOO8O-`LpsMLH~rEVva3G;70CNBv13E$x> ze1`Y%7GA?DJc2CD!xcCUqc8{;N;J+o{#%+XN5OaRF5lryH*qOL7Qx^t`1 zLE2u;KV2x~-2r2=WDcvJ(I66Y4pScmTco?DE72$wcTZP^L&iYQ5ANs}PJcLp9An)* zXb2h*WB?obCD!2pwdfL^cHPKPP2awn?m*k9^xAXQtr zyaGbvDYzgZB<^rP3NOG@@N;Ed$)WfVK#1FnY^_K0&5ZWDdG~?sM*IkOxFj&;jskSapKe*&$J!|pH+ zJG|Al_#SMty%NYtzT2PGI`Pl6H?m)mpi#P9D915mhgf!qE9RCEW z64+w5t*-4rVQu_GX=Q*u5+jXq=&Wvq#IcFWGH>;Gu3r6FU z-mm-P@yY&T{BNGkJtx|G?S!?pjz&Xa=!UVO*Ee(nj7p=j*{E)Ez53{>QLfjn{7qlQ zO!{fM@i@b>lE^Vrq4Z~>YdeTwOTy!kSj&B)>#=JL=Ux@kTWyybC ka0AahJvcj>!(Ue}=EwXOB@~CJp|)zcUG0r=;|ssI20 literal 0 HcmV?d00001 From 8c1ec77bb3c45cceb6462e8aa84dc15abf89ca9b Mon Sep 17 00:00:00 2001 From: lebedevs Date: Fri, 8 Jul 2022 22:45:49 +0300 Subject: [PATCH 4/7] Makefile and Dockerfile added First basic versions --- Dockerfile | 22 ++++++++++++++++++++++ Makefile | 12 ++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 Dockerfile create mode 100644 Makefile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9587230 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM golang:1.18.3 as builder + +#RUN apk --no-cache --no-progress add tzdata make sqlite && rm -rf /var/cache/apk/* + +WORKDIR /src + +COPY go.mod . +COPY go.sum . +RUN go mod download + +COPY . . + +RUN make build + +FROM scratch + +#COPY --from=builder /usr/share/zoneinfo /use/share/zoneinfo +COPY --from=builder /app /app +#ADD config /config + +ENTRYPOINT [ "/app" ] +#EXPOSE 80 \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6b0fb1c --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: default build image run + +default: build + +build: + CGO_ENABLED=1 GOOS=linux go build -o /app -a -ldflags '-linkmode external -extldflags "-static"' cmd/main.go + +image: + docker build -t skillbot:latest . + +run: + go run cmd/main.go \ No newline at end of file From 9ad3edada188965c4a99bc5fe5b2ac414ad6ff5e Mon Sep 17 00:00:00 2001 From: lebedevs Date: Fri, 8 Jul 2022 22:47:23 +0300 Subject: [PATCH 5/7] Dockerfile cleanup --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9587230..7478e47 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,5 @@ FROM golang:1.18.3 as builder -#RUN apk --no-cache --no-progress add tzdata make sqlite && rm -rf /var/cache/apk/* - WORKDIR /src COPY go.mod . @@ -14,9 +12,7 @@ RUN make build FROM scratch -#COPY --from=builder /usr/share/zoneinfo /use/share/zoneinfo COPY --from=builder /app /app -#ADD config /config ENTRYPOINT [ "/app" ] #EXPOSE 80 \ No newline at end of file From c251cb6231a0e54d7d9323c6b0c4ed7c67fbc11e Mon Sep 17 00:00:00 2001 From: lebedevs Date: Fri, 15 Jul 2022 21:02:43 +0300 Subject: [PATCH 6/7] Updated build tools --- Dockerfile | 8 ++++---- Makefile | 1 + folders.tar.gz | Bin 0 -> 175 bytes 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 folders.tar.gz diff --git a/Dockerfile b/Dockerfile index 7478e47..2c39b99 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM golang:1.18.3 as builder - +LABEL stage=tgbotbuilder WORKDIR /src COPY go.mod . @@ -9,10 +9,10 @@ RUN go mod download COPY . . RUN make build +RUN mkdir -p /etc/tgbot && mkdir /data FROM scratch - COPY --from=builder /app /app +ADD folders.tar.gz / -ENTRYPOINT [ "/app" ] -#EXPOSE 80 \ No newline at end of file +ENTRYPOINT [ "/app" ] \ No newline at end of file diff --git a/Makefile b/Makefile index 6b0fb1c..b7fafa6 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ build: image: docker build -t skillbot:latest . + docker image prune --filter label=stage=tgbotbuilder run: go run cmd/main.go \ No newline at end of file diff --git a/folders.tar.gz b/folders.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..1bf6740e5ee37beea0ca531adac9a3c8efcecd49 GIT binary patch literal 175 zcmb2|=3oE==C@ZIxegf!I9#;!^1q-qbBU$@6{V(#jK_bsZf%m@7`sH_&-Rl_kt}sa zrOHQVE|)m8<(9;m=fBjh?Y_49vtMY>*0|n~g@3NPyi4|T4n6tQ?AvvdlKbcW-ufS0 zTI^*xwU(v$zr^(~*Db!6OX>Xm9$+48CpM39_OIUtU(2^G{Vx~y_w&yS&y&_C9R3sk YYqi#Yd5EjPWWrSTqKUd~3>pj!0EgRBjsO4v literal 0 HcmV?d00001 From 6892ab44ffc8687f6584e609a9c204bd14b6fa4e Mon Sep 17 00:00:00 2001 From: lebedevs Date: Fri, 15 Jul 2022 21:03:32 +0300 Subject: [PATCH 7/7] prune force flag added --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b7fafa6..a589b8e 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ build: image: docker build -t skillbot:latest . - docker image prune --filter label=stage=tgbotbuilder + docker image prune -f --filter label=stage=tgbotbuilder run: go run cmd/main.go \ No newline at end of file