🔨 Almost completed code refactoring

Rewritten localization strings, remove most linter warnings, move and/or split big code blocks, general formatting
This commit is contained in:
Maxim Lebedev 2017-11-21 19:52:05 +05:00
parent 5009362910
commit 7718553fa4
No known key found for this signature in database
GPG Key ID: F8978F46FF0FFA4F
25 changed files with 636 additions and 295 deletions

69
add.go Normal file
View File

@ -0,0 +1,69 @@
package main
import (
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
"github.com/nicksnyder/go-i18n/i18n" // Internationalization and localization
"github.com/toby3d/go-telegram" // My Telegram bindings
)
func commandAdd(msg *telegram.Message) {
log.Ln("Received a /add command")
log.Ln("Change", msg.From.ID, "state to", stateAdd)
err := dbChangeUserState(msg.From.ID, stateAdd)
errCheck(err)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
reply := telegram.NewMessage(msg.Chat.ID, T("reply_add"))
reply.ParseMode = telegram.ModeMarkdown
log.Ln("Sending add reply...")
_, err = bot.SendMessage(reply)
errCheck(err)
}
func actionAdd(msg *telegram.Message) {
log.Ln("Received a /add action")
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
log.Ln("Change", msg.From.ID, "state to", stateNone)
err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
exists, err := dbAddSticker(msg.From.ID, msg.Sticker.FileID, msg.Sticker.Emoji)
errCheck(err)
markup := telegram.NewInlineKeyboardMarkup(
telegram.NewInlineKeyboardRow(
telegram.NewInlineKeyboardButtonSwitch(
T("button_share"),
msg.Sticker.Emoji,
),
),
)
reply := telegram.NewMessage(msg.Chat.ID, T("success_add"))
reply.ParseMode = telegram.ModeMarkdown
reply.ReplyMarkup = &markup
if exists {
reply.Text = T("error_already_add")
}
_, err = bot.SendMessage(reply)
errCheck(err)
}

42
cancel.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
"github.com/nicksnyder/go-i18n/i18n" // Internationalization and localization
"github.com/toby3d/go-telegram" // My Telegram bindings
)
const keyPhrase = "Yes, I am totally sure."
func commandCancel(msg *telegram.Message) {
log.Ln("Received a /cancel command")
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
state, err := dbGetUserState(msg.From.ID)
errCheck(err)
text := T("cancel_error")
switch state {
case stateAdd:
text = T("cancel_add")
case stateRemove:
text = T("cancel_remove")
case stateReset:
text = T("cancel_reset")
}
err = dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
reply := telegram.NewMessage(msg.Chat.ID, text)
_, err = bot.SendMessage(reply)
errCheck(err)
}

View File

@ -3,90 +3,22 @@ package main
import (
"strings"
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
"github.com/nicksnyder/go-i18n/i18n" // Internationalization and localization
"github.com/toby3d/go-telegram" // My Telegram bindings
"github.com/toby3d/go-telegram" // My Telegram bindings
)
func commands(msg *telegram.Message) {
log.Ln("[commands] Check command message")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
switch strings.ToLower(msg.Command()) {
case "start":
log.Ln("[commands] Received a /start command")
// TODO: Reply by greetings message and add user to DB
_, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
reply := telegram.NewMessage(
msg.Chat.ID, // chat
T("start_message", map[string]interface{}{
"Username": bot.Self.Username,
}), // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
commandStart(msg)
case "help":
log.Ln("[commands] Received a /help command")
_, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
reply := telegram.NewMessage(
msg.Chat.ID, // chat
T("help_message", map[string]interface{}{
"Username": bot.Self.Username,
}), // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
commandHelp(msg)
case "add":
log.Ln("[commands] Received a /add command")
_, err := dbChangeUserState(msg.From.ID, stateAdding)
errCheck(err)
reply := telegram.NewMessage(
msg.Chat.ID, // chat
T("add_reply"), // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
commandAdd(msg)
case "remove":
log.Ln("[commands] Received a /remove command")
_, err := dbChangeUserState(msg.From.ID, stateDeleting)
errCheck(err)
reply := telegram.NewMessage(
msg.Chat.ID, // chat
T("remove_reply"), // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
commandRemove(msg)
case "reset":
commandReset(msg)
case "cancel":
log.Ln("[commands] Received a /cancel command")
prev, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
text := T("error_cancel_nothing")
switch prev {
case stateAdding:
prev = T("add_cancel")
case stateDeleting:
prev = T("remove_cancel")
}
reply := telegram.NewMessage(
msg.Chat.ID, // chat
text, // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
default:
log.Ln("[commands] Received unsupported command")
// Do nothing because unsupported command
commandCancel(msg)
}
}

View File

@ -9,20 +9,15 @@ import (
"github.com/tidwall/buntdb" // Redis-like database
)
const (
stateNone = "none"
stateAdding = "add"
stateDeleting = "remove"
)
var db *buntdb.DB
func dbInit() {
log.Ln("[dbInit] Open database file...")
log.Ln("Open database file...")
var err error
db, err = buntdb.Open("bot.db")
errCheck(err)
log.Ln("Creating user_stickers index...")
err = db.CreateIndex(
"user_stickers", // name
"user:*:sticker:*", // pattern
@ -33,40 +28,40 @@ func dbInit() {
select {}
}
func dbChangeUserState(userID int, state string) (string, error) {
var prevState string
err := db.Update(func(tx *buntdb.Tx) error {
var err error
prevState, _, err = tx.Set(
func dbChangeUserState(userID int, state string) error {
log.Ln("Trying to change", userID, "state to", state)
return db.Update(func(tx *buntdb.Tx) error {
_, _, err := tx.Set(
fmt.Sprint("user:", userID, ":state"), // key
state, // val
nil, // options
)
return err
})
return prevState, err
}
func dbGetUserState(userID int) (string, error) {
log.Ln("Trying to get", userID, "state")
var state string
err := db.View(func(tx *buntdb.Tx) error {
var err error
state, err = tx.Get(
fmt.Sprint("user:", userID, ":state"), // key
)
state, err = tx.Get(fmt.Sprint("user:", userID, ":state"))
return err
})
switch err {
case buntdb.ErrNotFound:
state, err = dbChangeUserState(userID, stateNone)
log.Ln(userID, "not found, create new one")
if err := dbChangeUserState(userID, stateNone); err != nil {
return state, err
}
}
return state, err
}
func dbAddSticker(userID int, fileID, emoji string) (bool, error) {
log.Ln("Trying to add", fileID, "sticker from", userID, "user")
var exists bool
err := db.Update(func(tx *buntdb.Tx) error {
var err error
@ -88,24 +83,55 @@ func dbAddSticker(userID int, fileID, emoji string) (bool, error) {
}
func dbDeleteSticker(userID int, fileID string) (bool, error) {
log.Ln("Trying to remove", fileID, "sticker from", userID, "user")
err := db.Update(func(tx *buntdb.Tx) error {
_, err := tx.Delete(
fmt.Sprint("user:", userID, ":sticker:", fileID), // key
)
_, err := tx.Delete(fmt.Sprint("user:", userID, ":sticker:", fileID))
return err
})
switch err {
case buntdb.ErrNotFound:
log.Ln(userID, "not found, create new one")
return true, nil
}
return false, err
}
func dbResetUserStickers(userID int) error {
log.Ln("Trying reset all stickers of", userID, "user")
return db.Update(func(tx *buntdb.Tx) error {
var keys []string
err := tx.Ascend(
"user_stickers", // index
func(key, val string) bool { // iterator
subKeys := strings.Split(key, ":")
if subKeys[1] == strconv.Itoa(userID) {
keys = append(keys, key)
}
return true
},
)
if err != nil {
return err
}
for i := range keys {
_, err = tx.Delete(keys[i])
if err != nil {
break
}
}
return err
})
}
func dbGetUserStickers(userID, offset int, emoji string) ([]string, error) {
var stickers []string
log.Ln("Trying to get", offset, "page of", userID, "stickers")
count := 0
var stickers []string
err := db.View(func(tx *buntdb.Tx) error {
return tx.Ascend(
"user_stickers", // index
@ -118,22 +144,24 @@ func dbGetUserStickers(userID, offset int, emoji string) ([]string, error) {
count++
if len(stickers) >= 50 {
log.Ln("We get 50 results for", offset, "page, abort")
return false
}
if emoji != "" {
log.Ln("["+emoji+"]", "?=", "["+val+"]")
if val != emoji {
log.Ln("Ignore", subKeys[3], "sticker by emoji")
return true
}
}
if offset >= 1 &&
count <= ((offset-1)*50) {
log.Ln("Ignore sticker from previous", (offset - 1), "page")
return true
}
log.Ln("[", count, "]", key, "=", val)
log.Ln("Added", subKeys[3], "to results")
stickers = append(stickers, subKeys[3])
return true
},
@ -142,6 +170,7 @@ func dbGetUserStickers(userID, offset int, emoji string) ([]string, error) {
switch err {
case buntdb.ErrNotFound:
log.Ln("Not found stickers")
return nil, nil
}

View File

@ -19,14 +19,14 @@ var allowedUpdates = []string{
// getUpdatesChannel return webhook or long polling channel with bot updates
func getUpdatesChannel() (telegram.UpdatesChannel, error) {
log.Ln("[getUpdatesChannel] Preparing channel for updates...")
log.Ln("Preparing channel for updates...")
log.Ln("[getUpdatesChannel] Deleting webhook if exists")
log.Ln("Deleting webhook if exists")
_, err := bot.DeleteWebhook()
errCheck(err)
if !*flagWebhook {
log.Ln("[getUpdatesChannel] Use LongPolling updates")
log.Ln("Use LongPolling updates")
return bot.NewLongPollingChannel(&telegram.GetUpdatesParameters{
Offset: 0,
Limit: 100,
@ -40,18 +40,18 @@ func getUpdatesChannel() (telegram.UpdatesChannel, error) {
tgHookServe := cfg.UString("telegram.webhook.serve")
log.Ln(
"[getUpdatesChannel] Trying set webhook on address:",
"Trying set webhook on address:",
fmt.Sprint(tgHookSet, tgHookListen, bot.AccessToken),
)
log.Ln("[getUpdatesChannel] Creating new webhook...")
log.Ln("Creating new webhook...")
webhook := telegram.NewWebhook(
fmt.Sprint(tgHookSet, tgHookListen, bot.AccessToken),
"cert.pem",
)
webhook.AllowedUpdates = allowedUpdates
log.Ln("[getUpdatesChannel] Setting new webhook...")
log.Ln("Setting new webhook...")
_, err = bot.SetWebhook(webhook)
if err != nil {
return nil, err
@ -59,14 +59,14 @@ func getUpdatesChannel() (telegram.UpdatesChannel, error) {
channel := make(chan telegram.Update, 100)
go func() {
log.Ln("[getUpdatesChannel] Listen and serve TLS...")
log.Ln("Listen and serve TLS...")
err := http.ListenAndServeTLS(
tgHookServe,
"cert.pem",
"cert.key",
func(ctx *http.RequestCtx) {
log.Ln(
"[getUpdatesChannel] Catch request on path:",
"Catch request on path:",
string(ctx.Path()),
)
if strings.HasPrefix(
@ -74,7 +74,7 @@ func getUpdatesChannel() (telegram.UpdatesChannel, error) {
fmt.Sprint(tgHookListen, bot.AccessToken),
) {
log.Ln(
"[getUpdatesChannel] Catch supported request:",
"Catch supported request:",
string(ctx.Request.Body()),
)
@ -82,7 +82,7 @@ func getUpdatesChannel() (telegram.UpdatesChannel, error) {
err := json.Unmarshal(ctx.Request.Body(), &update)
errCheck(err)
log.Ln("[getUpdatesChannel] Unmarshled next:")
log.Ln("Unmarshled next:")
log.D(update)
channel <- update

43
help.go Normal file
View File

@ -0,0 +1,43 @@
package main
import (
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
"github.com/nicksnyder/go-i18n/i18n" // Internationalization and localization
"github.com/toby3d/go-telegram" // My Telegram bindings
)
func commandHelp(msg *telegram.Message) {
log.Ln("Received a /help command")
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
markup := telegram.NewInlineKeyboardMarkup(
telegram.NewInlineKeyboardRow(
telegram.NewInlineKeyboardButtonSwitch(
T("button_share"),
" ",
),
),
)
reply := telegram.NewMessage(
msg.Chat.ID, T("reply_help", map[string]interface{}{
"Username": bot.Self.Username,
}),
)
reply.ParseMode = telegram.ModeMarkdown
reply.ReplyMarkup = &markup
_, err = bot.SendMessage(reply)
errCheck(err)
}

View File

@ -1,10 +0,0 @@
add_cancel:
other: You cancelled the process of adding a new sticker to your pack.
add_error:
other: Error adding a sticker to the pack. Try again later.
add_exists:
other: This sticker is already in your pack.
add_reply:
other: Send an existing sticker from any other pack to add it to yourself.
add_success:
other: The sticker was successfully added to your pack!

View File

@ -1,46 +1,67 @@
add_cancel:
button_inline_add:
other: Add more stickers
button_inline_empty:
other: Your pack is empty
button_inline_nothing:
other: Not found stickers for {{.Query}}, add one?
button_remove:
other: Select sticker for remove
button_share:
other: Use your stickers pack!
cancel_add:
other: You cancelled the process of adding a new sticker to your pack.
add_error:
other: Error adding a sticker to the pack. Try again later.
add_exists:
cancel_error:
other: Nothing to cancel.
cancel_remove:
other: You cancelled the process of removing a sticker from your pack.
cancel_reset:
other: You cancelled the process of reseting your stickers pack.
error_already_add:
other: This sticker is already in your pack.
add_reply:
other: Send an existing sticker from any other pack to add it to yourself.
add_success:
other: The sticker was successfully added to your pack!
cancel_nothing:
other: Nothing to cancel.
error_cancel_nothing:
other: Nothing to cancel.
error_command_first:
error_already_remove:
other: Maybe this sticker is already removed from your pack.
error_already_reset:
other: There is nothing to reset, pack is already empty.
error_empty_remove:
other: There is nothing to remove, pack is empty.
error_reset_phrase:
other: Invalid phrase of resetting. This action has been canceled.
error_unknown:
other: |-
I do not know what to do with this sticker.
Please run /add or /remove command first.
help_message:
meta_reset_1:
other: Wait. Who are you?
meta_reset_2:
other: What are you doing here?
meta_reset_3:
other: What am I doing here?
reply_add:
other: Send an existing sticker from any other pack to add it to yourself.
reply_help:
other: |-
/add - add a sticker to your pack
/remove - remove a sticker from your pack
/reset - remove all stickers from your pack
/cancel - cancel the current operation
To view and send stickers from your pack, just type @{{.Username}} in any chat.
inline_empty:
other: Your pack is empty
inline_nothing:
other: Not found stickers for {{.Query}}
remove_already:
other: I do not know this sticker. Maybe it was already removed from your pack.
remove_cancel:
other: You cancelled the process of removing a sticker from your pack.
remove_error:
other: Error removing a sticker from the pack. Try again later.
remove_exists:
other: I do not know this sticker. Maybe it was already removed from your pack.
remove_reply:
To view and send stickers from your pack, just type `@{{.Username}}` (and space) in any chat.
reply_remove:
other: Send an existing sticker from your pack for removing it.
remove_success:
other: The sticker was successfully removed from your pack!
start_message:
other: |-
reply_reset:
other: |
This operation will remove *all* stickers from your pack and *this can't be undone*.
Send `Yes, I am totally sure.` to confirm what you really want to reset my brain (oh god why).
Or use /cancel for abort current operation.
reply_start:
other: |
Hello, I'm the @{{.Username}}!
I can create your personal pack with stickers from others packs.
Without limits-per-pack. Without installing. In any chat. For free.
Without limits and installing. In any chat. For free.
success_add:
other: The sticker was successfully added to your pack!
success_remove:
other: The sticker was successfully removed from your pack!
success_reset:
other: The contents of your pack are completely reset!..

10
i18n/en-us.buttons.yaml Normal file
View File

@ -0,0 +1,10 @@
button_inline_empty:
other: Your pack is empty
button_inline_nothing:
other: Not found stickers for {{.Query}}, add one?
button_inline_add:
other: Add more stickers
button_remove:
other: Select sticker for remove
button_share:
other: Use your stickers pack!

8
i18n/en-us.cancel.yaml Normal file
View File

@ -0,0 +1,8 @@
cancel_add:
other: You cancelled the process of adding a new sticker to your pack.
cancel_remove:
other: You cancelled the process of removing a sticker from your pack.
cancel_reset:
other: You cancelled the process of reseting your stickers pack.
cancel_error:
other: Nothing to cancel.

View File

@ -1,6 +1,14 @@
error_cancel_nothing:
other: Nothing to cancel.
error_command_first:
error_already_add:
other: This sticker is already in your pack.
error_already_remove:
other: Maybe this sticker is already removed from your pack.
error_already_reset:
other: There is nothing to reset, pack is already empty.
error_reset_phrase:
other: Invalid phrase of resetting. This action has been canceled.
error_empty_remove:
other: There is nothing to remove, pack is empty.
error_unknown:
other: |
I do not know what to do with this sticker.
Please run /add or /remove command first.

View File

@ -1,7 +0,0 @@
help_message:
other: |
/add - add a sticker to your pack
/remove - remove a sticker from your pack
/cancel - cancel the current operation
To view and send stickers from your pack, just type @{{.Username}} in any chat.

View File

@ -1,4 +0,0 @@
inline_empty:
other: Your pack is empty
inline_nothing:
other: Not found stickers for {{.Query}}

6
i18n/en-us.meta.yaml Normal file
View File

@ -0,0 +1,6 @@
meta_reset_1:
other: Wait. Who are you?
meta_reset_2:
other: What are you doing here?
meta_reset_3:
other: What am I doing here?

View File

@ -1,10 +0,0 @@
remove_cancel:
other: You cancelled the process of removing a sticker from your pack.
remove_error:
other: Error removing a sticker from the pack. Try again later.
remove_already:
other: I do not know this sticker. Maybe it was already removed from your pack.
remove_reply:
other: Send an existing sticker from your pack for removing it.
remove_success:
other: The sticker was successfully removed from your pack!

23
i18n/en-us.replies.yaml Normal file
View File

@ -0,0 +1,23 @@
reply_start:
other: |
Hello, I'm the @{{.Username}}!
I can create your personal pack with stickers from others packs.
Without limits and installing. In any chat. For free.
reply_add:
other: Send an existing sticker from any other pack to add it to yourself.
reply_remove:
other: Send an existing sticker from your pack for removing it.
reply_reset:
other: |
This operation will remove *all* stickers from your pack and *this can't be undone*.
Send `Yes, I am totally sure.` to confirm what you really want to reset my brain (oh god why).
Or use /cancel for abort current operation.
reply_help:
other: |
/add - add a sticker to your pack
/remove - remove a sticker from your pack
/reset - remove all stickers from your pack
/cancel - cancel the current operation
To view and send stickers from your pack, just type `@{{.Username}}` (and space) in any chat.

View File

@ -1,5 +0,0 @@
start_message:
other: |
Hello, I'm the @{{.Username}}!
I can create your personal pack with stickers from others packs.
Without limits-per-pack. Without installing. In any chat. For free.

6
i18n/en-us.success.yaml Normal file
View File

@ -0,0 +1,6 @@
success_add:
other: The sticker was successfully added to your pack!
success_remove:
other: The sticker was successfully removed from your pack!
success_reset:
other: The contents of your pack are completely reset!..

27
init.go
View File

@ -8,7 +8,14 @@ import (
"github.com/olebedev/config" // Easy configuration file parsing
)
const langDefault = "en-us"
const (
langDefault = "en-us"
stateNone = "none"
stateAdd = "add"
stateRemove = "remove"
stateReset = "reset"
)
var (
// Variables with types from imports
@ -25,33 +32,33 @@ var (
// init prepare configuration and other things for successful start of main
// function.
func init() {
log.Ln("[init] Initializing...")
log.Ln("[init] Parse flags...")
log.Ln("Initializing...")
log.Ln("Parse flags...")
flag.Parse()
log.Ln("[init] Load english localization...")
log.Ln("Load english localization...")
i18n.MustLoadTranslationFile("./i18n/en-us.all.yaml")
var err error
log.Ln("[init] Loading configuration file...")
log.Ln("Loading configuration file...")
cfg, err = config.ParseYamlFile("config.yaml")
errCheck(err)
log.Ln("[init] Checking bot access token in configuration file...")
log.Ln("Checking bot access token in configuration file...")
_, err = cfg.String("telegram.token")
errCheck(err)
if *flagWebhook {
log.Ln("[init] Enabled webhook mode, check configuration strings...")
log.Ln("[init] Checking webhook set string...")
log.Ln("Enabled webhook mode, check configuration strings...")
log.Ln("Checking webhook set string...")
_, err = cfg.String("telegram.webhook.set")
errCheck(err)
log.Ln("[init] Checking webhook listen string...")
log.Ln("Checking webhook listen string...")
_, err = cfg.String("telegram.webhook.listen")
errCheck(err)
log.Ln("[init] Checking webhook listen string...")
log.Ln("Checking webhook listen string...")
_, err = cfg.String("telegram.webhook.serve")
errCheck(err)
}

View File

@ -1,7 +1,6 @@
package main
import (
"fmt"
"strconv"
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
@ -10,7 +9,7 @@ import (
)
func inlineQuery(inline *telegram.InlineQuery) {
log.Ln("[inlineQuery] Let's preparing answer...")
log.Ln("Let's preparing answer...")
T, err := i18n.Tfunc(inline.From.LanguageCode)
if err != nil {
T, err = i18n.Tfunc(langDefault)
@ -36,17 +35,15 @@ func inlineQuery(inline *telegram.InlineQuery) {
switch {
case offset <= 0 && len(stickers) == 0 && inline.Query == "":
// If query is empty and get 0 stickers
answer.SwitchPrivateMessageText = T("inline_empty")
answer.SwitchPrivateMessageText = T("button_inline_empty")
answer.SwitchPrivateMessageParameter = "add"
case offset <= 0 && len(stickers) == 0 && inline.Query != "":
// If search stickers by emoji return 0 results
answer.SwitchPrivateMessageText = T(
"inline_nothing",
map[string]interface{}{
"Query": inline.Query,
},
"button_inline_nothing",
map[string]interface{}{"Query": inline.Query},
)
answer.SwitchPrivateMessageParameter = "help"
answer.SwitchPrivateMessageParameter = "add"
case offset >= 0 && len(stickers) == 50,
offset >= 0 && len(stickers) < 50:
offset++
@ -55,12 +52,13 @@ func inlineQuery(inline *telegram.InlineQuery) {
var results = make([]interface{}, len(stickers))
for i, sticker := range stickers {
results[i] = telegram.NewInlineQueryResultCachedSticker(
fmt.Sprint("sticker", sticker), // resultID
sticker, // resultID
sticker, // fileID
)
}
answer.SwitchPrivateMessageText = T("button_inline_add")
answer.SwitchPrivateMessageParameter = "add"
answer.Results = results
}

34
main.go
View File

@ -10,42 +10,50 @@ var bot *telegram.Bot
// main function is a general function for work of this bot
func main() {
log.Ln("[main] Let'g Get It Started...")
log.Ln("Let'g Get It Started...")
var err error
go dbInit()
defer db.Close()
log.Ln("[main] Initializing new bot via checking access_token...")
log.Ln("Initializing new bot via checking access_token...")
bot, err = telegram.NewBot(cfg.UString("telegram.token"))
errCheck(err)
log.Ln("[main] Initializing channel for updates...")
log.Ln("Initializing channel for updates...")
updates, err := getUpdatesChannel()
errCheck(err)
log.Ln("[main] Let's check updates channel!")
log.Ln("Let's check updates channel!")
for update := range updates {
switch {
case update.ChosenInlineResult != nil:
log.Ln("[main] Get ChosenInlineResult update")
// TODO: Save info in Yandex.AppMetrika
log.Ln("Get ChosenInlineResult update")
// TODO: Save metrika about chosen results
case update.InlineQuery != nil:
if len(update.InlineQuery.Query) > 255 {
// Just don't check same updates
if len(update.InlineQuery.Query) > 4 {
continue
}
log.Ln("[main] Get InlineQuery update")
inlineQuery(update.InlineQuery)
case update.Message != nil:
log.Ln("[main] Get Message update")
// TODO: Added support of commands, grab and save sticker in DB
if update.Message.From.ID == bot.Self.ID {
log.Ln("Received a message from myself, ignore this update")
return
}
if update.Message.ForwardFrom != nil {
if update.Message.ForwardFrom.ID == bot.Self.ID {
log.Ln("Received a forward from myself, ignore this update")
return
}
}
messages(update.Message)
default:
log.Ln("[main] Get unsupported update")
// Ignore any other updates
log.Ln("Get unsupported update")
}
continue
}
}

View File

@ -9,94 +9,51 @@ import (
// message function check Message update on commands, sended stickers or other
// user stuff
func messages(msg *telegram.Message) {
if msg.From.ID == bot.Self.ID {
log.Ln("[messages] Received a message from myself, ignore this update")
return
}
if msg.ForwardFrom != nil {
if msg.ForwardFrom.ID == bot.Self.ID {
log.Ln("[messages] Received a forward from myself, ignore this update")
return
}
}
if msg.IsCommand() {
log.Ln("[message] Received a command message")
log.Ln("Received a command message")
commands(msg)
return
}
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
state, err := dbGetUserState(msg.From.ID)
errCheck(err)
if msg.Sticker != nil {
state, err := dbGetUserState(msg.From.ID)
errCheck(err)
switch state {
case stateNone:
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
log.D(msg.Sticker)
switch state {
case stateNone:
reply := telegram.NewMessage(
msg.Chat.ID, // chat
T("error_command_first"), // text
)
_, err = bot.SendMessage(reply)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
T, err = i18n.Tfunc(langDefault)
errCheck(err)
case stateAdding:
exists, err := dbAddSticker(msg.From.ID, msg.Sticker.FileID, msg.Sticker.Emoji)
errCheck(err)
if exists {
reply := telegram.NewMessage(
msg.Chat.ID, // chat
T("add_exists"), // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
_, err = dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
return
}
reply := telegram.NewMessage(
msg.Chat.ID, // chat
T("add_success"), // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
_, err = dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
case stateDeleting:
notFound, err := dbDeleteSticker(msg.From.ID, msg.Sticker.FileID)
errCheck(err)
text := T("remove_success")
if notFound {
text = T("remove_already")
}
reply := telegram.NewMessage(
msg.Chat.ID, // chat
text, // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
_, err = dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
default:
_, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
messages(msg)
return
}
reply := telegram.NewMessage(msg.Chat.ID, T("error_unknown"))
reply.ParseMode = telegram.ModeMarkdown
_, err = bot.SendMessage(reply)
errCheck(err)
case stateAdd:
if msg.Sticker != nil {
log.D(msg.Sticker)
log.D(msg.Sticker.Emoji)
actionAdd(msg)
}
case stateRemove:
if msg.Sticker != nil {
log.D(msg.Sticker)
log.D(msg.Sticker.Emoji)
actionRemove(msg)
}
case stateReset:
actionReset(msg)
default:
err = dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
messages(msg)
}
}

77
remove.go Normal file
View File

@ -0,0 +1,77 @@
package main
import (
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
"github.com/nicksnyder/go-i18n/i18n" // Internationalization and localization
"github.com/toby3d/go-telegram" // My Telegram bindings
)
func commandRemove(msg *telegram.Message) {
log.Ln("Received a /remove command")
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
stickers, err := dbGetUserStickers(msg.From.ID, 0, "")
errCheck(err)
if len(stickers) <= 0 {
reply := telegram.NewMessage(msg.Chat.ID, T("error_empty_remove"))
_, err = bot.SendMessage(reply)
errCheck(err)
return
}
err = dbChangeUserState(msg.From.ID, stateRemove)
errCheck(err)
markup := telegram.NewInlineKeyboardMarkup(
telegram.NewInlineKeyboardRow(
telegram.NewInlineKeyboardButtonSwitchSelf(
T("button_remove"),
" ",
),
),
)
reply := telegram.NewMessage(msg.Chat.ID, T("reply_remove"))
reply.ParseMode = telegram.ModeMarkdown
reply.ReplyMarkup = &markup
_, err = bot.SendMessage(reply)
errCheck(err)
}
func actionRemove(msg *telegram.Message) {
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
notExist, err := dbDeleteSticker(msg.From.ID, msg.Sticker.FileID)
errCheck(err)
reply := telegram.NewMessage(msg.Chat.ID, T("success_remove"))
reply.ParseMode = telegram.ModeMarkdown
if notExist {
reply.Text = T("error_already_remove")
}
_, err = bot.SendMessage(reply)
errCheck(err)
}

91
reset.go Normal file
View File

@ -0,0 +1,91 @@
package main
import (
"fmt"
"time"
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
"github.com/nicksnyder/go-i18n/i18n" // Internationalization and localization
"github.com/toby3d/go-telegram" // My Telegram bindings
)
func commandReset(msg *telegram.Message) {
log.Ln("Received a /reset command")
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
stickers, err := dbGetUserStickers(msg.From.ID, 0, "")
errCheck(err)
if len(stickers) <= 0 {
reply := telegram.NewMessage(msg.Chat.ID, T("error_already_reset"))
reply.ParseMode = telegram.ModeMarkdown
_, err = bot.SendMessage(reply)
errCheck(err)
return
}
err = dbChangeUserState(msg.From.ID, stateReset)
errCheck(err)
reply := telegram.NewMessage(msg.Chat.ID, T("reply_reset"))
reply.ParseMode = telegram.ModeMarkdown
_, err = bot.SendMessage(reply)
errCheck(err)
}
func actionReset(msg *telegram.Message) {
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
if msg.Text != keyPhrase {
reply := telegram.NewMessage(msg.Chat.ID, T("error_reset_phrase"))
reply.ParseMode = telegram.ModeMarkdown
_, err = bot.SendMessage(reply)
errCheck(err)
return
}
err = dbResetUserStickers(msg.From.ID)
errCheck(err)
reply := telegram.NewMessage(msg.Chat.ID, T("success_reset"))
reply.ParseMode = telegram.ModeMarkdown
_, err = bot.SendMessage(reply)
errCheck(err)
for i := 1; i <= 3; i++ {
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
text := T(fmt.Sprint("meta_reset_", i))
time.Sleep(time.Minute * time.Duration(len(text)) / 1000)
reply = telegram.NewMessage(msg.Chat.ID, text)
reply.ParseMode = telegram.ModeMarkdown
_, err = bot.SendMessage(reply)
errCheck(err)
}
}

42
start.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
"strings"
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
"github.com/nicksnyder/go-i18n/i18n" // Internationalization and localization
"github.com/toby3d/go-telegram" // My Telegram bindings
)
func commandStart(msg *telegram.Message) {
bot.SendChatAction(msg.Chat.ID, telegram.ActionTyping)
err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
log.Ln("Received a /start command")
if msg.HasArgument() {
if strings.ToLower(msg.CommandArgument()) == "add" {
commandAdd(msg)
return
}
}
log.Ln("Check", msg.From.LanguageCode, "localization")
T, err := i18n.Tfunc(msg.From.LanguageCode)
if err != nil {
log.Ln("Unsupported language, change to 'en-us' by default")
T, err = i18n.Tfunc(langDefault)
errCheck(err)
}
reply := telegram.NewMessage(
msg.Chat.ID, T("reply_start", map[string]interface{}{
"Username": bot.Self.Username,
}),
)
reply.ParseMode = telegram.ModeMarkdown
_, err = bot.SendMessage(reply)
errCheck(err)
}