commit e03a70cfc833771d10842d804c41a0fc3692856c Author: Maksim Pischulenok Date: Tue May 18 00:04:51 2021 +0300 Initial commit diff --git a/main.go b/main.go new file mode 100644 index 0000000..c76f0b8 --- /dev/null +++ b/main.go @@ -0,0 +1,133 @@ +package main + +import ( + "fmt" + "gorm.io/driver/sqlite" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "log" + "os" + "strings" + "time" + + tb "gopkg.in/tucnak/telebot.v2" +) + +type ChatUser struct { + ChatID int64 `gorm:"primaryKey"` + UserID int `gorm:"primaryKey"` + Username string +} + +func main() { + db, err := gorm.Open(sqlite.Open("bot_db.db"), &gorm.Config{}) + if err != nil { + panic("failed to connect database") + } + + // Migrate the schema + err = db.AutoMigrate(&ChatUser{}) + if err != nil { + panic("failed to migrate") + } + + b, err := tb.NewBot(tb.Settings{ + Token: os.Getenv("TOKEN"), + Poller: &tb.LongPoller{Timeout: 10 * time.Second}, + }) + + if err != nil { + log.Fatal(err) + return + } + + b.Handle("/start", func(m *tb.Message) { + _, err := b.Send( + m.Sender, "Hey! I can help notify everyone 📢 in the group when someone needs them.\n"+ + "Everyone who wishes to receive mentions needs to /in to opt-in. "+ + "All opted-in users can then be mentioned using /all", + ) + if err != nil { + log.Println(err) + return + } + }) + + b.Handle("/in", func(m *tb.Message) { + user := m.Sender + + username := "anonymous" + if len(user.Username) > 0 { + username = user.Username + } else if len(user.FirstName) > 0 { + username = user.FirstName + } + + db.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "chat_id"}, {Name: "user_id"}}, + DoUpdates: clause.AssignmentColumns([]string{"username"}), + }).Create(&ChatUser{ChatID: m.Chat.ID, UserID: user.ID, Username: username}) + + msg := fmt.Sprintf("Thanks for opting in %s", username) + + _, err := b.Send(m.Chat, msg) + if err != nil { + log.Println("/in", err) + return + } + }) + + b.Handle("/all", func(m *tb.Message) { + var users []ChatUser + db.Find(&users, ChatUser{ChatID: m.Chat.ID}) + + var usersList []string + + for _, chatUser := range users { + usersList = append(usersList, fmt.Sprintf("[yolo](tg://user?id=%v)", chatUser.UserID)) + } + + msg := strings.Join(usersList, " ") + + if len(users) == 0 { + msg = "There are no users\\. To opt in type /in command" + } + + _, err := b.Send(m.Chat, msg, tb.ModeMarkdownV2) + + if err != nil { + log.Println("/all", err) + return + } + }) + + b.Handle("/out", func(m *tb.Message) { + db.Where("chat_id = ? and user_id = ?", m.Chat.ID, m.Sender.ID).Delete(&ChatUser{}) + + msg := fmt.Sprintf("You've been opted out %v", m.Sender.ID) + + _, err := b.Send(m.Chat, msg) + if err != nil { + log.Println("/out", err) + return + } + }) + + b.Handle("/stats", func(m *tb.Message) { + var userCount int64 + var chatCount int64 + + db.Model(&ChatUser{}).Distinct("user_id").Count(&userCount) + db.Model(&ChatUser{}).Distinct("chat_id").Count(&chatCount) + + msg := fmt.Sprintf("Users: %5d\nChats: %5d", userCount, chatCount) + + _, err := b.Send(m.Chat, msg) + if err != nil { + log.Println(err) + return + } + }) + + b.Start() +}