206 lines
6.3 KiB
Go
206 lines
6.3 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"os/signal"
|
||
"strings"
|
||
|
||
_ "github.com/glebarez/go-sqlite"
|
||
"github.com/go-telegram/bot"
|
||
"github.com/go-telegram/bot/models"
|
||
"github.com/jmoiron/sqlx"
|
||
)
|
||
|
||
var BUILD_TIME string
|
||
|
||
var db *sqlx.DB
|
||
|
||
type Godette struct {
|
||
*bot.Bot
|
||
ctx context.Context
|
||
update *models.Update
|
||
}
|
||
|
||
func MakeHandler(handler func(g Godette)) func(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||
return func(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||
if update.Message.Caption != "" && update.Message.Text == "" {
|
||
update.Message.Text = update.Message.Caption
|
||
}
|
||
handler(Godette{b, ctx, update})
|
||
}
|
||
}
|
||
|
||
func (g *Godette) ReplyWithText(text string) (*models.Message, error) {
|
||
return g.Bot.SendMessage(g.ctx, &bot.SendMessageParams{
|
||
Text: text,
|
||
ChatID: g.update.Message.Chat.ID,
|
||
MessageThreadID: g.update.Message.MessageThreadID,
|
||
ReplyParameters: &models.ReplyParameters{
|
||
ChatID: g.update.Message.Chat.ID,
|
||
MessageID: g.update.Message.ID,
|
||
},
|
||
})
|
||
}
|
||
|
||
func (g *Godette) AnswerWithMarkdown(text string) (*models.Message, error) {
|
||
return g.Bot.SendMessage(g.ctx, &bot.SendMessageParams{
|
||
Text: text,
|
||
ChatID: g.update.Message.Chat.ID,
|
||
MessageThreadID: g.update.Message.MessageThreadID,
|
||
ParseMode: models.ParseModeMarkdown,
|
||
})
|
||
}
|
||
|
||
func (g *Godette) ReplyWithMarkdown(text string) (*models.Message, error) {
|
||
return g.Bot.SendMessage(g.ctx, &bot.SendMessageParams{
|
||
Text: text,
|
||
ChatID: g.update.Message.Chat.ID,
|
||
MessageThreadID: g.update.Message.MessageThreadID,
|
||
ParseMode: models.ParseModeMarkdown,
|
||
ReplyParameters: &models.ReplyParameters{
|
||
ChatID: g.update.Message.Chat.ID,
|
||
MessageID: g.update.Message.ID,
|
||
},
|
||
})
|
||
}
|
||
|
||
func main() {
|
||
token := os.Getenv("TOKEN")
|
||
if token == "" {
|
||
panic("No token was provided")
|
||
}
|
||
|
||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||
defer cancel()
|
||
|
||
if err := InitDb(); err != nil {
|
||
log.Fatalln(err)
|
||
}
|
||
|
||
opts := []bot.Option{
|
||
bot.WithDefaultHandler(defHandler),
|
||
bot.WithMiddlewares(writeUsersToDB),
|
||
bot.WithAllowedUpdates(bot.AllowedUpdates{
|
||
"message",
|
||
"callback_query",
|
||
"message_reaction",
|
||
}),
|
||
}
|
||
|
||
b, _ := bot.New(token, opts...)
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "/me ", bot.MatchTypePrefix, HandleMe)
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "/help", bot.MatchTypePrefix, MakeHandler(HandleHelp))
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "/docs ", bot.MatchTypePrefix, MakeHandler(HandleDocRequest))
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "/docs_ru ", bot.MatchTypePrefix, MakeHandler(HandleDocRequestRu))
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "/top", bot.MatchTypePrefix, MakeHandler(HandleUsersTop))
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "/bottom", bot.MatchTypePrefix, MakeHandler(HandleUsersBottom))
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "/stats", bot.MatchTypePrefix, MakeHandler(HandleStats))
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "+", bot.MatchTypePrefix, KarmaGoUp)
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "Спасибо", bot.MatchTypePrefix, KarmaGoUp)
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "спасибо", bot.MatchTypePrefix, KarmaGoUp)
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "СПАСИБО", bot.MatchTypePrefix, KarmaGoUp)
|
||
b.RegisterHandler(bot.HandlerTypeMessageText, "-", bot.MatchTypePrefix, KarmaGoDown)
|
||
b.RegisterHandlerMatchFunc(func(update *models.Update) bool {
|
||
return update.MessageReaction != nil
|
||
}, HandleReactions)
|
||
|
||
b.SetMyCommands(context.Background(), &bot.SetMyCommandsParams{
|
||
Commands: commands,
|
||
Scope: &models.BotCommandScopeDefault{},
|
||
})
|
||
|
||
b.Start(ctx)
|
||
|
||
}
|
||
|
||
func InitDb() error {
|
||
newdb, err := sqlx.Connect("sqlite", "./bot.db?_time_format=sqlite")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
db = newdb
|
||
return nil
|
||
}
|
||
|
||
func defHandler(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||
|
||
}
|
||
func HandleMe(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||
g := Godette{b, ctx, update}
|
||
g.AnswerWithMarkdown(fmt.Sprintf(
|
||
"_*%s* %s_",
|
||
bot.EscapeMarkdown(update.Message.From.FirstName),
|
||
bot.EscapeMarkdown(strings.TrimPrefix(update.Message.Text, "/me ")),
|
||
))
|
||
b.DeleteMessage(ctx, &bot.DeleteMessageParams{
|
||
ChatID: update.Message.Chat.ID,
|
||
MessageID: update.Message.ID,
|
||
})
|
||
}
|
||
|
||
var commands = []models.BotCommand{
|
||
{Command: "/help", Description: "Показать данное сообщение"},
|
||
{Command: "/me", Description: "Написать своё сообщение от третьего лица"},
|
||
{Command: "/top", Description: "Вывод ТОП-10 пользователей"},
|
||
{Command: "/bottom", Description: "Отрицательный ТОП-10"},
|
||
{Command: "/stats", Description: "Информация о пользователе"},
|
||
{Command: "/docs", Description: "Поиск по документации"},
|
||
{Command: "/docs_ru", Description: "Поиск по русскоязычной документации"},
|
||
}
|
||
|
||
func HandleHelp(g Godette) {
|
||
commands_text := ""
|
||
for _, command := range commands {
|
||
commands_text += fmt.Sprintf("`%s` \\- %s\n", bot.EscapeMarkdown(command.Command), bot.EscapeMarkdown(command.Description))
|
||
}
|
||
log.Println(g.ReplyWithMarkdown(fmt.Sprintf(
|
||
`
|
||
Мои команды:
|
||
|
||
%s
|
||
|
||
Дата сборки бота: %s
|
||
`,
|
||
commands_text,
|
||
bot.EscapeMarkdown(BUILD_TIME),
|
||
)))
|
||
}
|
||
|
||
func GetRandomTemplateByTag(tag string) (string, error) {
|
||
var msg string
|
||
err := db.Get(
|
||
&msg,
|
||
`SELECT text FROM message_templates WHERE tag=$1 ORDER BY RANDOM() LIMIT 1;`,
|
||
tag,
|
||
)
|
||
return msg, err
|
||
}
|
||
|
||
func writeUsersToDB(next bot.HandlerFunc) bot.HandlerFunc {
|
||
return func(ctx context.Context, bot *bot.Bot, update *models.Update) {
|
||
if update.Message != nil {
|
||
user := update.Message.From
|
||
chat := update.Message.Chat
|
||
_, err := db.Exec(
|
||
`
|
||
INSERT INTO users(id, name, username) VALUES($1, $2, $3) ON CONFLICT(id) DO UPDATE SET name=$2, username=$3, message_count=message_count+1;
|
||
INSERT INTO chats(id, name, username) VALUES($4, $5, $6) ON CONFLICT(id) DO UPDATE SET name=$5, username=$6;
|
||
`,
|
||
user.ID,
|
||
strings.TrimSpace(fmt.Sprintf("%s %s", user.FirstName, user.LastName)),
|
||
user.Username,
|
||
chat.ID,
|
||
chat.FirstName,
|
||
chat.Username,
|
||
)
|
||
if err != nil {
|
||
log.Println(err)
|
||
}
|
||
}
|
||
next(ctx, bot, update)
|
||
}
|
||
}
|