2019-08-20 12:36:26 +00:00
package main
import (
"encoding/json"
"flag"
"fmt"
"os"
"strconv"
"strings"
"unicode"
"git.fromouter.space/hamcha/tg"
)
type config struct {
Token string
Bind string
WebhookURL string
WebhookPath string
MaxRequestsPerMessage int
}
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 cfg config
func main ( ) {
cfgpath := flag . String ( "config" , "mlpcard.conf" , "Path to config file" )
flag . Parse ( )
cfgfile , err := os . Open ( * cfgpath )
checkErr ( err , "Could not open config file" )
err = json . NewDecoder ( cfgfile ) . Decode ( & cfg )
checkErr ( err , "Could not decode JSON from config file contents" )
cfgfile . Close ( )
// Set default maxreq
if cfg . MaxRequestsPerMessage < 1 {
cfg . MaxRequestsPerMessage = 5
}
api = tg . MakeAPIClient ( cfg . Token )
api . SetWebhook ( cfg . WebhookURL )
api . HandleWebhook ( cfg . Bind , cfg . WebhookPath , webhook )
}
type CardFaceFlipPics struct {
Normal string
Flipped string
Ponyhead string
MCM string
}
func webhook ( update tg . APIUpdate ) {
// Handle inline queries (99% of the usage I hope)
2019-08-20 12:57:57 +00:00
if update . Inline != nil && update . Inline . Query != "" {
2019-08-20 12:36:26 +00:00
query := update . Inline . Query
results , err := mlpapiSearch ( query )
if err != nil {
fmt . Println ( err )
// DO SOMETHING
return
}
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 : strconv . FormatInt ( card . GUID , 10 ) ,
PhotoURL : face ,
ThumbURL : face ,
Title : card . FullName ,
Caption : caption ,
Width : 672 ,
Height : 936 ,
ReplyMarkup : & tg . APIInlineKeyboardMarkup {
InlineKeyboard : [ ] [ ] tg . APIInlineKeyboardButton { buttons } ,
} ,
}
}
err = api . AnswerInlineQuery ( tg . InlineQueryResponse {
QueryID : update . Inline . QueryID ,
Results : photos ,
} )
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 ) > cfg . 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 ) , cfg . MaxRequestsPerMessage ) ,
ReplyID : & update . Message . MessageID ,
} )
return
}
cardmedia := [ ] tg . APIInputMediaPhoto { }
errlist := [ ] string { }
for _ , cardname := range requests {
cards , err := mlpapiSearch ( cardname )
if err != nil {
errlist = append ( errlist , cardname )
} else {
for _ , card := range cards . Data {
face , _ , _ := getCardEntry ( card , 0 )
cardmedia = append ( cardmedia , tg . APIInputMediaPhoto {
Type : "photo" ,
Media : face ,
} )
if card . Type == "Mane" {
face , _ , _ := getCardEntry ( card , 1 )
cardmedia = append ( cardmedia , tg . APIInputMediaPhoto {
Type : "photo" ,
Media : face ,
} )
}
}
}
}
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 := mlpapiGetCardByID ( 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 ,
} ,
} )
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 , flipped int ) ( string , string , [ ] tg . APIInlineKeyboardButton ) {
cid := toCardID ( card . AllIDs [ 0 ] )
buttons := [ ] tg . APIInlineKeyboardButton {
{
Text : "Ponyhead" ,
2019-08-20 12:57:57 +00:00
URL : "https://ponyhead.com/cards/" + cid ,
2019-08-20 12:36:26 +00:00
} ,
}
captions := [ ] string { }
suffix := ""
if card . Type == "Mane" {
suffix = "a"
num := 1
if flipped != 0 {
suffix = "b"
num = 0
}
buttons = append ( buttons , tg . APIInlineKeyboardButton {
Text : "🔄" ,
CallbackData : fmt . Sprintf ( "FLIP,%s,%d" , card . GUID , num ) ,
} )
}
face := fmt . Sprintf ( "https://mcg.zyg.ovh/images/cards/%s%s.webp" , cid , suffix )
return face , strings . Join ( captions , " - " ) , buttons
}
func toCardID ( id string ) string {
id = strings . ToLower ( id )
idx := strings . IndexFunc ( id , unicode . IsLetter )
num , set := id [ : idx ] , id [ idx : ]
return set + num
}