@stappabot telegram bot
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

234 lines
5.9 KiB

package main
import (
"fmt"
"os"
"strconv"
"strings"
"git.fromouter.space/hamcha/tg"
)
func checkErr(err error, msg string, args ...interface{}) {
if err != nil {
fmt.Printf("FATAL ERROR\n"+msg+":\n ", args...)
fmt.Println(err.Error())
os.Exit(1)
}
}
var api *tg.Telegram
var MaxRequestsPerMessage int
func main() {
MaxRequestsPerMessage, _ = strconv.Atoi(os.Getenv("STAPPA_MAXREQ"))
bind := os.Getenv("STAPPA_BIND")
if bind == "" {
bind = ":8080"
}
// Set default maxreq
if MaxRequestsPerMessage < 1 {
MaxRequestsPerMessage = 5
}
api = tg.MakeAPIClient(os.Getenv("STAPPA_TOKEN"))
api.SetWebhook(os.Getenv("STAPPA_WEBHOOK"))
api.HandleWebhook(bind, os.Getenv("STAPPA_PATH"), webhook)
}
type CardFaceFlipPics struct {
Normal string
Flipped string
Scryfall string
Edhrec string
MCM string
}
func webhook(update tg.APIUpdate) {
// Handle inline queries (99% of the usage I hope)
if update.Inline != nil {
query := update.Inline.Query
offset, _ := strconv.Atoi(update.Inline.Offset)
results, err := scryfallSearch(query, offset)
if err != nil {
fmt.Println(err)
// DO SOMETHING
return
}
nextcard := ""
if results.HasMore {
nextcard = strconv.Itoa(offset + len(results.Data))
}
photos := make([]tg.APIInlineQueryResultPhoto, len(results.Data))
for i, card := range results.Data {
face, caption, buttons := getCardEntry(card, 0)
photos[i] = tg.APIInlineQueryResultPhoto{
Type: "photo",
ResultID: card.ID,
PhotoURL: face.Large,
ThumbURL: face.Normal,
Title: card.Name,
Caption: caption,
Width: 672,
Height: 936,
ReplyMarkup: &tg.APIInlineKeyboardMarkup{
InlineKeyboard: [][]tg.APIInlineKeyboardButton{buttons},
},
}
}
err = api.AnswerInlineQuery(tg.InlineQueryResponse{
QueryID: update.Inline.QueryID,
Results: photos,
NextOffset: nextcard,
})
if err != nil {
fmt.Println(err)
// DO SOMETHING
return
}
}
// Check for card requests
if update.Message != nil && update.Message.Text != nil {
requests := getCardRequests(*update.Message.Text)
if len(requests) > MaxRequestsPerMessage {
api.SendTextMessage(tg.ClientTextMessageData{
ChatID: update.Message.Chat.ChatID,
Text: fmt.Sprintf("You asked for way too many cards (%d!), please only ask me for at most %d cards in a single message.", len(requests), MaxRequestsPerMessage),
ReplyID: &update.Message.MessageID,
})
return
}
cardmedia := []tg.APIInputMediaPhoto{}
errlist := []string{}
for _, cardname := range requests {
card, err := scryfallGetCardByName(cardname)
if err != nil {
errlist = append(errlist, cardname)
} else {
if card.ImageUris.Large == "" && card.CardFaces != nil {
for _, cardface := range card.CardFaces {
cardmedia = append(cardmedia, tg.APIInputMediaPhoto{
Type: "photo",
Media: cardface.ImageUris.Large,
})
}
} else {
cardmedia = append(cardmedia, tg.APIInputMediaPhoto{
Type: "photo",
Media: card.ImageUris.Large,
})
}
}
}
if len(cardmedia) > 0 {
api.SendAlbum(tg.ClientAlbumData{
ChatID: update.Message.Chat.ChatID,
Media: cardmedia,
Silent: true,
ReplyID: &update.Message.MessageID,
})
}
if len(errlist) > 0 {
api.SendTextMessage(tg.ClientTextMessageData{
ChatID: update.Message.Chat.ChatID,
Text: "I couldn't find these cards you mentioned: " + strings.Join(errlist, ", "),
ReplyID: &update.Message.MessageID,
})
}
}
// Handle inline callback requests (flipped cards)
if update.Callback != nil {
if update.Callback.Data != nil && strings.HasPrefix(*update.Callback.Data, "FLIP") {
parts := strings.SplitN(*update.Callback.Data, ",", 3)
card, err := scryfallGetCardByID(parts[1])
facenum, _ := strconv.Atoi(parts[2])
if err == nil {
face, caption, buttons := getCardEntry(card, facenum)
api.EditMedia(tg.ClientEditMediaData{
InlineID: *update.Callback.InlineID,
Media: tg.APIInputMediaPhoto{
Type: "photo",
Media: face.Large,
},
})
api.EditCaption(tg.ClientEditCaptionData{
InlineID: *update.Callback.InlineID,
Caption: caption,
ReplyMarkup: &tg.APIInlineKeyboardMarkup{
InlineKeyboard: [][]tg.APIInlineKeyboardButton{buttons},
},
})
}
} else {
fmt.Println("Unknown callback: ", *update.Callback.Data)
}
api.AnswerCallback(tg.ClientCallbackQueryData{
QueryID: update.Callback.ID,
})
}
}
func getCardRequests(str string) (out []string) {
remaining := str
for len(remaining) > 1 {
nextToken := strings.Index(remaining, "[[")
if nextToken < 0 {
break
}
endToken := strings.Index(remaining[nextToken:], "]]")
if endToken < 0 {
break
}
out = append(out, remaining[nextToken+2:nextToken+endToken])
remaining = remaining[nextToken+2+endToken:]
}
return
}
func getCardEntry(card CardData, facenum int) (CardImage, string, []tg.APIInlineKeyboardButton) {
buttons := []tg.APIInlineKeyboardButton{
{
Text: "Scryfall",
URL: card.ScryfallURI,
},
}
if card.RelatedUris.Edhrec != "" {
buttons = append(buttons, tg.APIInlineKeyboardButton{
Text: "EDHREC",
URL: card.RelatedUris.Edhrec,
})
}
if card.PurchaseUris.Cardmarket != "" {
buttons = append(buttons, tg.APIInlineKeyboardButton{
Text: "MCM",
URL: card.PurchaseUris.Cardmarket,
})
}
captions := []string{}
if card.EdhrecRank != nil {
captions = append(captions, fmt.Sprintf("EDHREC rank: #%d", *card.EdhrecRank))
}
if card.Eur != "" {
captions = append(captions, fmt.Sprintf("cardmarket: € %s", card.Eur))
}
face := card.ImageUris
if card.ImageUris.Large == "" && card.CardFaces != nil {
face = card.CardFaces[facenum].ImageUris
num := 1
if facenum != 0 {
num = 0
}
buttons = append(buttons, tg.APIInlineKeyboardButton{
Text: "🔄",
CallbackData: fmt.Sprintf("FLIP,%s,%d", card.ID, num),
})
}
return face, strings.Join(captions, " - "), buttons
}