godette/main.go

206 lines
6.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
}