init
This commit is contained in:
40
src/botutils.go
Normal file
40
src/botutils.go
Normal file
@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-telegram/bot"
|
||||
"github.com/go-telegram/bot/models"
|
||||
)
|
||||
|
||||
func GetChatFullName(chat models.Chat) string {
|
||||
if chat.Title != "" {
|
||||
return chat.Title
|
||||
}
|
||||
if chat.FirstName != "" {
|
||||
if chat.LastName != "" {
|
||||
return fmt.Sprint(chat.FirstName, " ", chat.LastName)
|
||||
}
|
||||
return chat.FirstName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetUserFullName(user models.User) string {
|
||||
if user.FirstName != "" {
|
||||
if user.LastName != "" {
|
||||
return fmt.Sprint(user.FirstName, " ", user.LastName)
|
||||
}
|
||||
return user.FirstName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func FetchMemberFromChat(ctx context.Context, b *bot.Bot, chatID int64, userID int64) (*models.ChatMember, error) {
|
||||
return b.GetChatMember(ctx, &bot.GetChatMemberParams{ChatID: chatID, UserID: userID})
|
||||
}
|
||||
|
||||
func IsAdmin(member models.ChatMember) bool {
|
||||
return member.Administrator != nil || member.Owner != nil
|
||||
}
|
162
src/db.go
Normal file
162
src/db.go
Normal file
@ -0,0 +1,162 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
var schema = `
|
||||
create table if not exists chats
|
||||
(
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT,
|
||||
username TEXT,
|
||||
topic INTEGER,
|
||||
active INTEGER
|
||||
);
|
||||
|
||||
create table if not exists activations
|
||||
(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT
|
||||
);
|
||||
|
||||
create table if not exists messagesToDelete
|
||||
(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
message_id INTEGER,
|
||||
chat_id INTEGER,
|
||||
delete_date INTEGER
|
||||
);
|
||||
|
||||
create table if not exists users
|
||||
(
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT,
|
||||
username TEXT
|
||||
);
|
||||
|
||||
create table if not exists bans
|
||||
(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER,
|
||||
reason TEXT,
|
||||
ban_date INTEGER,
|
||||
unban_date INTEGER,
|
||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
create table if not exists captchas
|
||||
(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER,
|
||||
chat_id INTEGER,
|
||||
message_id INTEGER,
|
||||
correct_answer INTEGER,
|
||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||
)
|
||||
`
|
||||
|
||||
type ChatSchema struct {
|
||||
Id int64 `json:"id" db:"id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Username string `json:"username" db:"username"`
|
||||
Topic int64 `json:"topic" db:"topic"`
|
||||
Active bool `json:"active" db:"active"`
|
||||
}
|
||||
|
||||
type MessageToDelete struct {
|
||||
Id int64 `db:"id"`
|
||||
MessageId int `db:"message_id"`
|
||||
ChatId int64 `db:"chat_id"`
|
||||
DeleteDate int64 `db:"delete_date"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Id int64 `db:"id"`
|
||||
Name string `db:"name"`
|
||||
Username string `db:"username"`
|
||||
}
|
||||
|
||||
var db *sqlx.DB
|
||||
|
||||
func InitDb() error {
|
||||
newdb, err := sqlx.Connect("sqlite", "./bot.db?_time_format=sqlite")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db = newdb
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewChat(chat ChatSchema) error {
|
||||
_, err := db.NamedExec(`insert into chats (id, name, username, topic, active) values (:id, :name, :username, :topic, :active)`, chat)
|
||||
return err
|
||||
}
|
||||
|
||||
func IsChatExists(id int64) bool {
|
||||
var exists bool
|
||||
err := db.Get(&exists, `SELECT exists(SELECT 1 FROM chats WHERE id = $1);`, id)
|
||||
if err != nil {
|
||||
log.Println("Can't check existing of chat", id, err)
|
||||
return false
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func IsChatActive(id int64) bool {
|
||||
var active bool
|
||||
err := db.Get(&active, `SELECT active from chats where id = $1`, id)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return active
|
||||
}
|
||||
|
||||
func GetChatById(id int64) (ChatSchema, error) {
|
||||
c := ChatSchema{}
|
||||
err := db.Get(&c, `select * from chats where id = $1`, id)
|
||||
return c, err
|
||||
}
|
||||
|
||||
func NewActivation(code string) error {
|
||||
_, err := db.Exec(`insert into activations (code) values ($1)`, code)
|
||||
return err
|
||||
}
|
||||
|
||||
func UseActivation(code string) bool {
|
||||
_, err := db.Exec(`delete from activations where code = $1`, code)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func ActivateChat(id int64) error {
|
||||
_, err := db.Exec(`update chats set active = 1 where id = $1`, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func AddMessageToDelete(msg MessageToDelete) error {
|
||||
_, err := db.NamedExec(`insert into messagesToDelete (message_id, chat_id, delete_date) values (:message_id, :chat_id, :delete_date)`, msg)
|
||||
return err
|
||||
}
|
||||
|
||||
func NewUser(user User) error {
|
||||
_, err := db.NamedExec(`insert into users (id, name, username) values (:id, :name, :username)`, user)
|
||||
return err
|
||||
}
|
||||
|
||||
func IsUserExists(id int64) bool {
|
||||
var exists bool
|
||||
err := db.Get(&exists, `SELECT exists(SELECT 1 FROM users WHERE id = $1);`, id)
|
||||
if err != nil {
|
||||
log.Println("Can't check existing of chat", id, err)
|
||||
return false
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func GetUserById(id int64) (User, error) {
|
||||
c := User{}
|
||||
err := db.Get(&c, `select * from users where id = $1`, id)
|
||||
return c, err
|
||||
}
|
64
src/handlers.go
Normal file
64
src/handlers.go
Normal file
@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-telegram/bot"
|
||||
"github.com/go-telegram/bot/models"
|
||||
)
|
||||
|
||||
func defaultHandler(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||||
// b.SendMessage(ctx, &bot.SendMessageParams{
|
||||
// ChatID: update.Message.Chat.ID,
|
||||
// Text: "hello!",
|
||||
// })
|
||||
log.Println(*update)
|
||||
}
|
||||
|
||||
func registerChat(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||||
msg := update.Message
|
||||
log.Println("registering", msg.Chat.ID)
|
||||
m, err := FetchMemberFromChat(ctx, b, msg.Chat.ID, msg.From.ID)
|
||||
if err == nil {
|
||||
if !IsAdmin(*m) {
|
||||
log.Println("register: user is not admin")
|
||||
return
|
||||
}
|
||||
args := strings.Split(msg.Text, " ")
|
||||
if len(args) == 1 {
|
||||
log.Println("register: there's no code")
|
||||
return
|
||||
}
|
||||
if !UseActivation(args[1]) {
|
||||
log.Println("register: wrong code")
|
||||
return
|
||||
}
|
||||
if err := ActivateChat(msg.Chat.ID); err != nil {
|
||||
log.Println("Error activating chat: ", err)
|
||||
return
|
||||
}
|
||||
b.DeleteMessage(ctx, &bot.DeleteMessageParams{ChatID: msg.Chat.ID, MessageID: msg.ID})
|
||||
sent, err := b.SendMessage(ctx, &bot.SendMessageParams{ChatID: msg.Chat.ID, Text: "Чат зарегистрирован", MessageThreadID: msg.MessageThreadID})
|
||||
if err == nil {
|
||||
err := AddMessageToDelete(MessageToDelete{MessageId: sent.ID, ChatId: msg.Chat.ID, DeleteDate: time.Now().Add(1 * time.Minute).Unix()})
|
||||
if err != nil {
|
||||
log.Println("register: failed to add to delete", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Println("register: error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) {
|
||||
for _, user := range u.Message.NewChatMembers {
|
||||
log.Println(user)
|
||||
}
|
||||
}
|
||||
|
||||
func banUser(ctx context.Context, b *bot.Bot, u *models.Update) {
|
||||
|
||||
}
|
40
src/main.go
Normal file
40
src/main.go
Normal file
@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
_ "github.com/glebarez/go-sqlite"
|
||||
"github.com/go-telegram/bot"
|
||||
"github.com/go-telegram/bot/models"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer cancel()
|
||||
|
||||
if err := InitDb(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
db.MustExec(schema)
|
||||
|
||||
opts := []bot.Option{
|
||||
bot.WithMiddlewares(logChats, logUsers, checkRegistered),
|
||||
bot.WithDefaultHandler(defaultHandler),
|
||||
}
|
||||
|
||||
b, err := bot.New(os.Getenv("TG_TOKEN"), opts...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
b.RegisterHandler(bot.HandlerTypeMessageText, "/register", bot.MatchTypePrefix, registerChat)
|
||||
b.RegisterHandler(bot.HandlerTypeMessageText, "/ban", bot.MatchTypePrefix, banUser)
|
||||
b.RegisterHandlerMatchFunc(func(update *models.Update) bool {
|
||||
return update.Message != nil && len(update.Message.NewChatMembers) > 0
|
||||
}, handleNewJoined)
|
||||
b.Start(ctx)
|
||||
}
|
63
src/middleware.go
Normal file
63
src/middleware.go
Normal file
@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/go-telegram/bot"
|
||||
"github.com/go-telegram/bot/models"
|
||||
)
|
||||
|
||||
func checkRegistered(next bot.HandlerFunc) bot.HandlerFunc {
|
||||
return func(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||||
if update.Message == nil {
|
||||
next(ctx, b, update)
|
||||
return
|
||||
}
|
||||
chat := update.Message.Chat
|
||||
if chat.Type == "private" {
|
||||
return
|
||||
}
|
||||
if !IsChatActive(chat.ID) && !strings.HasPrefix(update.Message.Text, "/register") {
|
||||
log.Println("checkRegistered: not registered", chat.ID)
|
||||
return
|
||||
}
|
||||
|
||||
next(ctx, b, update)
|
||||
}
|
||||
}
|
||||
|
||||
func logChats(next bot.HandlerFunc) bot.HandlerFunc {
|
||||
return func(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||||
if update.Message == nil {
|
||||
next(ctx, b, update)
|
||||
return
|
||||
}
|
||||
chat := update.Message.Chat
|
||||
chatName := GetChatFullName(chat)
|
||||
if !IsChatExists(chat.ID) {
|
||||
db.MustExec(`insert into chats (id, username, name, topic, active) values ($1, $2, $3, $4, $5);`, chat.ID, chat.Username, chatName, 0, false)
|
||||
} else {
|
||||
db.MustExec(`update chats set username = $2, name = $3 where id = $1;`, chat.ID, chat.Username, chatName)
|
||||
}
|
||||
next(ctx, b, update)
|
||||
}
|
||||
}
|
||||
|
||||
func logUsers(next bot.HandlerFunc) bot.HandlerFunc {
|
||||
return func(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||||
if update.Message == nil {
|
||||
next(ctx, b, update)
|
||||
return
|
||||
}
|
||||
user := update.Message.From
|
||||
userFullName := GetUserFullName(*user)
|
||||
if !IsUserExists(user.ID) {
|
||||
db.MustExec(`insert into users (id, username, name) values ($1, $2, $3);`, user.ID, user.Username, userFullName, 0, false)
|
||||
} else {
|
||||
db.MustExec(`update users set username = $2, name = $3 where id = $1;`, user.ID, user.Username, userFullName)
|
||||
}
|
||||
next(ctx, b, update)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user