201 lines
6.8 KiB
Go
201 lines
6.8 KiB
Go
package serra
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
)
|
|
|
|
func init() {
|
|
cardCmd.Flags().StringVarP(&artist, "artist", "a", "", "Filter by name of artist")
|
|
cardCmd.Flags().StringVarP(&rarity, "rarity", "r", "", "Filter by rarity of cards (mythic, rare, uncommon, common)")
|
|
cardCmd.Flags().StringVarP(&set, "set", "e", "", "Filter by set code (usg/mmq/vow)")
|
|
cardCmd.Flags().StringVarP(&sortby, "sort", "s", "name", "How to sort cards (value/number/name/added)")
|
|
cardCmd.Flags().StringVarP(&name, "name", "n", "", "Name of the card (regex compatible)")
|
|
cardCmd.Flags().Int64VarP(&cmc, "cmc", "m", -1, "Cumulative mana cost of card")
|
|
cardCmd.Flags().StringVarP(&color, "color", "i", "", "Color identity of card (w,u,b,r,g)")
|
|
cardCmd.Flags().StringVarP(&oracle, "oracle", "o", "", "Contains string in card text")
|
|
cardCmd.Flags().StringVarP(&cardType, "type", "t", "", "Contains string in card type line")
|
|
cardCmd.Flags().Int64VarP(&count, "min-count", "c", 0, "Occource more than X in your collection")
|
|
cardCmd.Flags().BoolVarP(&detail, "detail", "d", false, "Show details for cards (url)")
|
|
cardCmd.Flags().BoolVarP(&reserved, "reserved", "w", false, "If card is on reserved list")
|
|
cardCmd.Flags().BoolVarP(&foil, "foil", "f", false, "If card is foil list")
|
|
rootCmd.AddCommand(cardCmd)
|
|
}
|
|
|
|
var cardCmd = &cobra.Command{
|
|
Aliases: []string{"cards"},
|
|
Use: "card [card]",
|
|
Short: "Search & show cards from your collection",
|
|
Long: `Search and show cards from your collection.
|
|
If you directly put a card as an argument, it will be displayed
|
|
otherwise you'll get a list of cards as a search result.`,
|
|
SilenceErrors: true,
|
|
RunE: func(cmd *cobra.Command, cards []string) error {
|
|
if len(cards) == 0 {
|
|
cardList := Cards(rarity, set, sortby, name, oracle, cardType, reserved, foil, 0, 0)
|
|
showCardList(cardList, detail)
|
|
} else {
|
|
ShowCard(cards)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
func ShowCard(cardids []string) {
|
|
client := storageConnect()
|
|
coll := &Collection{client.Database("serra").Collection("cards")}
|
|
l := Logger()
|
|
defer storageDisconnect(client)
|
|
|
|
for _, v := range cardids {
|
|
if len(strings.Split(v, "/")) < 2 || strings.Split(v, "/")[1] == "" {
|
|
l.Warnf("Invalid card %s", v)
|
|
continue
|
|
}
|
|
|
|
cards, _ := coll.storageFind(bson.D{{"set", strings.Split(v, "/")[0]}, {"collectornumber", strings.Split(v, "/")[1]}}, bson.D{{"name", 1}}, 0, 0)
|
|
|
|
for _, card := range cards {
|
|
showCardDetails(&card)
|
|
}
|
|
}
|
|
}
|
|
|
|
func Cards(rarity, set, sortby, name, oracle, cardType string, reserved, foil bool, skip, limit int64) []Card {
|
|
client := storageConnect()
|
|
coll := &Collection{client.Database("serra").Collection("cards")}
|
|
defer storageDisconnect(client)
|
|
|
|
filter := bson.D{}
|
|
|
|
switch rarity {
|
|
case "uncommon":
|
|
filter = append(filter, bson.E{"rarity", "uncommon"})
|
|
case "common":
|
|
filter = append(filter, bson.E{"rarity", "common"})
|
|
case "rare":
|
|
filter = append(filter, bson.E{"rarity", "rare"})
|
|
case "mythic":
|
|
filter = append(filter, bson.E{"rarity", "mythic"})
|
|
}
|
|
|
|
var sortStage bson.D
|
|
switch sortby {
|
|
case "value":
|
|
if getCurrency() == EUR {
|
|
sortStage = bson.D{{"prices.eur", 1}}
|
|
} else {
|
|
sortStage = bson.D{{"prices.usd", 1}}
|
|
}
|
|
case "number":
|
|
sortStage = bson.D{{"collectornumber", 1}}
|
|
case "name":
|
|
sortStage = bson.D{{"name", 1}}
|
|
case "added":
|
|
sortStage = bson.D{{"serra_created", 1}}
|
|
default:
|
|
sortStage = bson.D{{"name", 1}}
|
|
}
|
|
|
|
if len(set) > 0 {
|
|
filter = append(filter, bson.E{"set", set})
|
|
}
|
|
|
|
if len(name) > 0 {
|
|
filter = append(filter, bson.E{"name", bson.D{{"$regex", ".*" + name + ".*"}, {"$options", "i"}}})
|
|
}
|
|
|
|
if len(artist) > 0 {
|
|
filter = append(filter, bson.E{"artist", bson.D{{"$regex", ".*" + artist + ".*"}, {"$options", "i"}}})
|
|
}
|
|
|
|
if cmc > -1 {
|
|
filter = append(filter, bson.E{"cmc", cmc})
|
|
}
|
|
|
|
if len(oracle) > 0 {
|
|
filter = append(filter, bson.E{"oracletext", bson.D{{"$regex", ".*" + oracle + ".*"}, {"$options", "i"}}})
|
|
}
|
|
|
|
if len(cardType) > 0 {
|
|
filter = append(filter, bson.E{"typeline", bson.D{{"$regex", ".*" + cardType + ".*"}, {"$options", "i"}}})
|
|
}
|
|
|
|
if len(color) > 0 {
|
|
colorArr := strings.Split(strings.ToUpper(color), ",")
|
|
filter = append(filter, bson.E{"coloridentity", colorArr})
|
|
}
|
|
|
|
if reserved {
|
|
filter = append(filter, bson.E{"reserved", true})
|
|
}
|
|
|
|
if foil {
|
|
filter = append(filter, bson.E{"serra_count_foil", bson.D{{"$gt", 0}}})
|
|
}
|
|
|
|
cards, _ := coll.storageFind(filter, sortStage, skip, limit)
|
|
|
|
// This is needed because collectornumbers are strings (ie. "23a") but still we
|
|
// want it to be sorted numerically ... 1,2,3,10,11,100.
|
|
if sortby == "number" {
|
|
sort.Slice(cards, func(i, j int) bool {
|
|
return filterForDigits(cards[i].CollectorNumber) < filterForDigits(cards[j].CollectorNumber)
|
|
})
|
|
}
|
|
|
|
// filter out cards that do not reach the minimum amount (--min-count)
|
|
// this is done after query result because find query constructed does not support
|
|
// aggregating fields (of count and countFoil).
|
|
temp := cards[:0]
|
|
for _, card := range cards {
|
|
if (card.SerraCount + card.SerraCountFoil) >= count {
|
|
temp = append(temp, card)
|
|
}
|
|
}
|
|
cards = temp
|
|
|
|
return cards
|
|
}
|
|
|
|
func showCardList(cards []Card, detail bool) {
|
|
|
|
var total float64
|
|
if detail {
|
|
for _, card := range cards {
|
|
fmt.Printf("* %dx %s%s%s (%s/%s) %s%.2f%s %s %s %s\n", card.SerraCount+card.SerraCountFoil+card.SerraCountEtched, Purple, card.Name, Reset, card.Set, card.CollectorNumber, Yellow, card.getValue(false), getCurrency(), Background, strings.Replace(card.ScryfallURI, "?utm_source=api", "", 1), Reset)
|
|
total = total + card.getValue(false)*float64(card.SerraCount) + card.getValue(true)*float64(card.SerraCountFoil)
|
|
}
|
|
} else {
|
|
for _, card := range cards {
|
|
fmt.Printf("* %dx %s%s%s (%s/%s) %s%.2f%s%s\n", card.SerraCount+card.SerraCountFoil+card.SerraCountEtched, Purple, card.Name, Reset, card.Set, card.CollectorNumber, Yellow, card.getValue(false), getCurrency(), Reset)
|
|
total = total + card.getValue(false)*float64(card.SerraCount) + card.getValue(true)*float64(card.SerraCountFoil)
|
|
}
|
|
}
|
|
|
|
fmt.Printf("\nTotal Value: %s%.2f%s%s\n", Yellow, total, getCurrency(), Reset)
|
|
|
|
}
|
|
|
|
func showCardDetails(card *Card) error {
|
|
fmt.Printf("%s%s%s (%s/%s)\n", Purple, card.Name, Reset, card.Set, card.CollectorNumber)
|
|
fmt.Printf("Added: %s\n", stringToTime(card.SerraCreated))
|
|
fmt.Printf("Rarity: %s\n", card.Rarity)
|
|
fmt.Printf("Scryfall: %s\n", strings.Replace(card.ScryfallURI, "?utm_source=api", "", 1))
|
|
|
|
fmt.Printf("\n%sCurrent Value%s\n", Green, Reset)
|
|
fmt.Printf("* Normal: %dx %s%.2f%s%s\n", card.SerraCount, Yellow, card.getValue(false), getCurrency(), Reset)
|
|
if card.SerraCountFoil > 0 {
|
|
fmt.Printf("* Foil: %dx %s%.2f%s%s\n", card.SerraCountFoil, Yellow, card.getValue(true), getCurrency(), Reset)
|
|
}
|
|
|
|
fmt.Printf("\n%sValue History%s\n", Green, Reset)
|
|
showPriceHistory(card.SerraPrices, "* ", false)
|
|
fmt.Println()
|
|
return nil
|
|
}
|