Allowing resending captcha
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -2,3 +2,4 @@
 | 
				
			|||||||
bot.db
 | 
					bot.db
 | 
				
			||||||
.env
 | 
					.env
 | 
				
			||||||
.vscode
 | 
					.vscode
 | 
				
			||||||
 | 
					kickbot
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@ -13,6 +13,7 @@ require (
 | 
				
			|||||||
	github.com/google/uuid v1.5.0 // indirect
 | 
						github.com/google/uuid v1.5.0 // indirect
 | 
				
			||||||
	github.com/inconshreveable/mousetrap v1.0.0 // indirect
 | 
						github.com/inconshreveable/mousetrap v1.0.0 // indirect
 | 
				
			||||||
	github.com/jmoiron/sqlx v1.4.0 // indirect
 | 
						github.com/jmoiron/sqlx v1.4.0 // indirect
 | 
				
			||||||
 | 
						github.com/joho/godotenv v1.5.1 // indirect
 | 
				
			||||||
	github.com/mattn/go-isatty v0.0.20 // indirect
 | 
						github.com/mattn/go-isatty v0.0.20 // indirect
 | 
				
			||||||
	github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
 | 
						github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
 | 
				
			||||||
	github.com/spf13/cobra v0.0.5 // indirect
 | 
						github.com/spf13/cobra v0.0.5 // indirect
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@ -27,6 +27,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
 | 
				
			|||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 | 
					github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 | 
				
			||||||
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
 | 
					github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
 | 
				
			||||||
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
 | 
					github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
 | 
				
			||||||
 | 
					github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
 | 
				
			||||||
 | 
					github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
 | 
				
			||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
					github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
				
			||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
					github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
				
			||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 | 
					github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 | 
				
			||||||
 | 
				
			|||||||
@ -68,7 +68,7 @@ func InitResources() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GenCaptcha() ([]byte, string) {
 | 
					func GenCaptcha(answer string) ([]byte, string) {
 | 
				
			||||||
	width, height := 500.0, 500.0
 | 
						width, height := 500.0, 500.0
 | 
				
			||||||
	ctx := gg.NewContext(int(width), int(height))
 | 
						ctx := gg.NewContext(int(width), int(height))
 | 
				
			||||||
	// Make gradient
 | 
						// Make gradient
 | 
				
			||||||
@ -91,9 +91,15 @@ func GenCaptcha() ([]byte, string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	items := []Item{}
 | 
						items := []Item{}
 | 
				
			||||||
	for i, image := range Images {
 | 
						for i, image := range Images {
 | 
				
			||||||
 | 
							var code string
 | 
				
			||||||
 | 
							if i == CorrectImage {
 | 
				
			||||||
 | 
								code = answer
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								code = generateRandomDigits(4)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		items = append(items, Item{
 | 
							items = append(items, Item{
 | 
				
			||||||
			img:     image,
 | 
								img:     image,
 | 
				
			||||||
			code:    generateRandomDigits(4),
 | 
								code:    code,
 | 
				
			||||||
			correct: i == CorrectImage,
 | 
								correct: i == CorrectImage,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,8 @@ id INTEGER PRIMARY KEY,
 | 
				
			|||||||
name TEXT NOT NULL,
 | 
					name TEXT NOT NULL,
 | 
				
			||||||
username TEXT DEFAULT '',
 | 
					username TEXT DEFAULT '',
 | 
				
			||||||
topic INTEGER DEFAULT 0,
 | 
					topic INTEGER DEFAULT 0,
 | 
				
			||||||
active INTEGER DEFAULT 0
 | 
					active INTEGER DEFAULT 0,
 | 
				
			||||||
 | 
					rules_msg TEXT DEFAULT ''
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
create table if not exists activations
 | 
					create table if not exists activations
 | 
				
			||||||
@ -79,6 +80,7 @@ type Chat struct {
 | 
				
			|||||||
	Username string `json:"username" db:"username"`
 | 
						Username string `json:"username" db:"username"`
 | 
				
			||||||
	Topic    int    `json:"topic" db:"topic"`
 | 
						Topic    int    `json:"topic" db:"topic"`
 | 
				
			||||||
	Active   bool   `json:"active" db:"active"`
 | 
						Active   bool   `json:"active" db:"active"`
 | 
				
			||||||
 | 
						RulesMsg string `json:"rules_msg" db:"rules_msg"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MessageToDelete struct {
 | 
					type MessageToDelete struct {
 | 
				
			||||||
 | 
				
			|||||||
@ -106,6 +106,10 @@ var NewUserTemplate = `
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
					func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
				
			||||||
	var chat Chat
 | 
						var chat Chat
 | 
				
			||||||
 | 
						b.DeleteMessage(ctx, &bot.DeleteMessageParams{
 | 
				
			||||||
 | 
							ChatID:    u.Message.Chat.ID,
 | 
				
			||||||
 | 
							MessageID: u.Message.ID,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	err := db.Get(&chat, "select * from chats where id = $1 and active = 1", u.Message.Chat.ID)
 | 
						err := db.Get(&chat, "select * from chats where id = $1 and active = 1", u.Message.Chat.ID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Println("can't get chat for new joined: ", err)
 | 
							log.Println("can't get chat for new joined: ", err)
 | 
				
			||||||
@ -120,7 +124,7 @@ func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
				
			|||||||
			ReplyMarkup: models.InlineKeyboardMarkup{
 | 
								ReplyMarkup: models.InlineKeyboardMarkup{
 | 
				
			||||||
				InlineKeyboard: [][]models.InlineKeyboardButton{
 | 
									InlineKeyboard: [][]models.InlineKeyboardButton{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						{URL: fmt.Sprintf("https://t.me/nefrace_php_test_bot?start=cap_%d", u.Message.Chat.ID), Text: "Check"},
 | 
											{URL: fmt.Sprintf("https://t.me/%s?start=cap_%d", BOT_NAME, u.Message.Chat.ID), Text: "Check"},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@ -255,6 +259,7 @@ var NewCaptchaTemplate = `
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func handlePrivateStartCaptcha(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
					func handlePrivateStartCaptcha(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
				
			||||||
	args := strings.Split(u.Message.Text, " ")
 | 
						args := strings.Split(u.Message.Text, " ")
 | 
				
			||||||
 | 
						log.Println(u.Message.From.FirstName, u.Message.Text)
 | 
				
			||||||
	userID := u.Message.From.ID
 | 
						userID := u.Message.From.ID
 | 
				
			||||||
	chatID := 0
 | 
						chatID := 0
 | 
				
			||||||
	if len(args) > 1 {
 | 
						if len(args) > 1 {
 | 
				
			||||||
@ -307,10 +312,10 @@ WHERE captchas.id = $1`, captcha.Id)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if captcha.CorrectAnswer == "" {
 | 
						if captcha.CorrectAnswer == "" {
 | 
				
			||||||
		img, answer := GenCaptcha()
 | 
							img, answer := GenCaptcha(generateRandomDigits(4))
 | 
				
			||||||
		captcha.CorrectAnswer = answer
 | 
							captcha.CorrectAnswer = answer
 | 
				
			||||||
		if _, err := b.SendPhoto(ctx, &bot.SendPhotoParams{
 | 
							if _, err := b.SendPhoto(ctx, &bot.SendPhotoParams{
 | 
				
			||||||
			Caption:   fmt.Sprintf(NewCaptchaTemplate, userchat.UserName, userchat.ChatName),
 | 
								Caption:   fmt.Sprintf(NewCaptchaTemplate, bot.EscapeMarkdown(userchat.UserName), bot.EscapeMarkdown(userchat.ChatName)),
 | 
				
			||||||
			Photo:     &models.InputFileUpload{Filename: "captcha.png", Data: bytes.NewReader(img)},
 | 
								Photo:     &models.InputFileUpload{Filename: "captcha.png", Data: bytes.NewReader(img)},
 | 
				
			||||||
			ChatID:    u.Message.Chat.ID,
 | 
								ChatID:    u.Message.Chat.ID,
 | 
				
			||||||
			ParseMode: models.ParseModeMarkdown,
 | 
								ParseMode: models.ParseModeMarkdown,
 | 
				
			||||||
@ -322,10 +327,15 @@ WHERE captchas.id = $1`, captcha.Id)
 | 
				
			|||||||
			log.Println("Can't update captcha:", err)
 | 
								log.Println("Can't update captcha:", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		b.SendMessage(ctx, &bot.SendMessageParams{
 | 
							img, _ := GenCaptcha(captcha.CorrectAnswer)
 | 
				
			||||||
			Text:   fmt.Sprintf("Я тебе уже выдавал капчу для %d", captcha.ChatID),
 | 
							if _, err := b.SendPhoto(ctx, &bot.SendPhotoParams{
 | 
				
			||||||
 | 
								Caption:   fmt.Sprintf(NewCaptchaTemplate, bot.EscapeMarkdown(userchat.UserName), bot.EscapeMarkdown(userchat.ChatName)),
 | 
				
			||||||
 | 
								Photo:     &models.InputFileUpload{Filename: "captcha.png", Data: bytes.NewReader(img)},
 | 
				
			||||||
			ChatID:    u.Message.Chat.ID,
 | 
								ChatID:    u.Message.Chat.ID,
 | 
				
			||||||
		})
 | 
								ParseMode: models.ParseModeMarkdown,
 | 
				
			||||||
 | 
							}); err != nil {
 | 
				
			||||||
 | 
								log.Println("can't send private captcha: ", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -388,8 +398,28 @@ func handlePrivateCaptcha(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
				
			|||||||
	log.Println("Deleting message:", result, err)
 | 
						log.Println("Deleting message:", result, err)
 | 
				
			||||||
	db.Exec("delete from captchas where id = $1", captcha.Id)
 | 
						db.Exec("delete from captchas where id = $1", captcha.Id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b.SendMessage(ctx, &bot.SendMessageParams{
 | 
						congrats := `
 | 
				
			||||||
		Text:   "Капча решена! Поздравляю! Теперь можешь вернуться в чат, я вернул тебе возможность отправлять там сообщения.\n\nСоветую ознакомиться с местными правилами, прежде чем что-либо писать!",
 | 
					Капча решена, поздравляю\!
 | 
				
			||||||
 | 
					Теперь можешь вернуться в чат, я вернул тебе возможность отправлять там сообщения\.
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
						rulesText := `Советую ознакомиться с местными [правилами](%s), прежде чем что\-либо писать\!`
 | 
				
			||||||
 | 
						fullCongrats := congrats
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var chat Chat
 | 
				
			||||||
 | 
						err = db.Get(&chat, "select * from chats where id = $1", captcha.ChatID)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							if chat.RulesMsg != "" {
 | 
				
			||||||
 | 
								rules := fmt.Sprintf(rulesText, chat.RulesMsg)
 | 
				
			||||||
 | 
								fullCongrats = fmt.Sprintf("%s\n\n%s", congrats, rules)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = b.SendMessage(ctx, &bot.SendMessageParams{
 | 
				
			||||||
 | 
							Text:      fullCongrats,
 | 
				
			||||||
 | 
							ParseMode: models.ParseModeMarkdown,
 | 
				
			||||||
		ChatID:    msg.From.ID,
 | 
							ChatID:    msg.From.ID,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println("Can't send congrats: ", err, "\n===\n", fullCongrats)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								src/main.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/main.go
									
									
									
									
									
								
							@ -11,11 +11,19 @@ import (
 | 
				
			|||||||
	_ "github.com/glebarez/go-sqlite"
 | 
						_ "github.com/glebarez/go-sqlite"
 | 
				
			||||||
	"github.com/go-telegram/bot"
 | 
						"github.com/go-telegram/bot"
 | 
				
			||||||
	"github.com/go-telegram/bot/models"
 | 
						"github.com/go-telegram/bot/models"
 | 
				
			||||||
 | 
						"github.com/joho/godotenv"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var BOT_NAME string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	log.SetFlags(log.Lshortfile + log.Ltime + log.Ldate)
 | 
						log.SetFlags(log.Lshortfile + log.Ltime + log.Ldate)
 | 
				
			||||||
	InitResources()
 | 
						InitResources()
 | 
				
			||||||
 | 
						err := godotenv.Load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println("No .env loaded. Relying on existing variables")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
 | 
						ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
 | 
				
			||||||
	defer cancel()
 | 
						defer cancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -35,6 +43,12 @@ func main() {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						me, err := b.GetMe(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Can't get me: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						BOT_NAME = me.Username
 | 
				
			||||||
 | 
						log.Println("Using name", BOT_NAME)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b.RegisterHandler(bot.HandlerTypeMessageText, "/register", bot.MatchTypePrefix, registerChat)
 | 
						b.RegisterHandler(bot.HandlerTypeMessageText, "/register", bot.MatchTypePrefix, registerChat)
 | 
				
			||||||
	b.RegisterHandler(bot.HandlerTypeMessageText, "/unregister", bot.MatchTypePrefix, unregisterChat)
 | 
						b.RegisterHandler(bot.HandlerTypeMessageText, "/unregister", bot.MatchTypePrefix, unregisterChat)
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user