Add search-printings command
This commit is contained in:
parent
2ef339bbce
commit
0dd67f3bb8
|
@ -1,32 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
STORAGE_DIR="$HOME/.local/share/sevenkeys/scanimages/"
|
||||
mkdir -p "$STORAGE_DIR"
|
||||
|
||||
ADD_CARDS=0
|
||||
echo "scantap: Beginning scan loop"
|
||||
while true; do
|
||||
rng="$(cat /dev/random | tr -cd 'a-f0-9' | head -c 32)"
|
||||
filename="$STORAGE_DIR/$rng.png"
|
||||
|
||||
scanimage --output-file="$filename" --source "ADF Front" --mode Color --page-width 63mm --page-height 88mm 2>/dev/null
|
||||
|
||||
# scanimage exits with code 7 if no documents are available in scanner
|
||||
if test $? -eq 7; then
|
||||
if test $ADD_CARDS -eq 0; then
|
||||
ADD_CARDS=1
|
||||
echo "scantap: No more cards in feeder" >&2
|
||||
fi
|
||||
|
||||
continue
|
||||
fi
|
||||
ADD_CARDS=0
|
||||
|
||||
convert -rotate 180 "$filename" "$filename"
|
||||
|
||||
# TODO: Add "store" command to sevenkeys executable to avoid duplicating insert logic here, then `./sevenkeys --profile=production store --id="0000..0000"`
|
||||
# Return inserted CardLocationId
|
||||
#cardLocationId="1"
|
||||
#mysql --silent --silent --user=root --password="$(pass show sevenkeys/mysql \
|
||||
#-e "USE sevenkeys; INSERT INTO CardScan (CardLocationId, Filename) VALUES ('$cardLocationId', '$filename.png');"
|
||||
done
|
|
@ -1,158 +0,0 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"sevenkeys/database"
|
||||
"sevenkeys/logic"
|
||||
)
|
||||
|
||||
var output string
|
||||
|
||||
func MainCliLoop(db *sql.DB) {
|
||||
var command string
|
||||
|
||||
//var selectedStorageAreaName string
|
||||
var cardLocation database.CardLocation
|
||||
|
||||
var insertSearchCriteria logic.SearchCriteria = logic.SearchCriteria{
|
||||
SetCode: "",
|
||||
Foil: logic.Either,
|
||||
Promo: logic.Either,
|
||||
Language: "en",
|
||||
}
|
||||
//var insertSearchOptions logic.InsertSearchOptions
|
||||
|
||||
// TODO: Add the ability to modify this
|
||||
/*
|
||||
var locateSearchCriteria logic.SearchCriteria = logic.SearchCriteria{
|
||||
SetCode: "",
|
||||
Foil: logic.True,
|
||||
Promo: logic.Either,
|
||||
Language: "en",
|
||||
}
|
||||
*/
|
||||
|
||||
for {
|
||||
ShowSplashScreen()
|
||||
// TODO: Fix this
|
||||
//showStorageInfo(os.Stdout, selectedStorageAreaName)
|
||||
showInsertSearchCriteria(insertSearchCriteria)
|
||||
showSelectedCard()
|
||||
showCopiesInserted()
|
||||
|
||||
command = GetStringResponse("SEVENKEYS $")
|
||||
|
||||
//var err error
|
||||
|
||||
switch command {
|
||||
/*
|
||||
case "q", "quit":
|
||||
return
|
||||
*/
|
||||
/*
|
||||
case "n", "newstorage":
|
||||
var storageArea database.StorageArea
|
||||
storageArea.Name = GetStringResponse("Storage area name:")
|
||||
storageArea.StorageType = GetStringResponse("Storage area type (Binder/Box):")
|
||||
err = logic.CreateStorageArea(db, storageArea)
|
||||
logic.Check(err)
|
||||
break
|
||||
*/
|
||||
/*
|
||||
case "a", "area":
|
||||
options, err := logic.GetStorageAreaSearchOptions(db)
|
||||
logic.Check(err)
|
||||
|
||||
id, _, err := logic.GenericSearch(options)
|
||||
logic.Check(err)
|
||||
|
||||
//selectedStorageAreaName = name
|
||||
// TODO: Make db call to cache StorageArea once we have the ID
|
||||
cardLocation.StorageAreaId = id
|
||||
break
|
||||
case "c", "criteria":
|
||||
insertSearchCriteria = getSearchCriteria()
|
||||
break
|
||||
case "s", "search":
|
||||
if shouldRefreshSearch {
|
||||
insertSearchOptions = getSearchOptions(db, insertSearchCriteria)
|
||||
}
|
||||
|
||||
var previousCardPrintingId = cardLocation.CardPrintingId
|
||||
|
||||
pk, searchLine, err := logic.GenericSearch(insertSearchOptions)
|
||||
cardLocation.CardPrintingId = pk
|
||||
selectedCardPrintingSearchLine = searchLine
|
||||
|
||||
var exitError *exec.ExitError
|
||||
if errors.As(err, &exitError) {
|
||||
break
|
||||
}
|
||||
logic.Check(err)
|
||||
|
||||
output = ""
|
||||
if cardLocation.CardPrintingId != previousCardPrintingId {
|
||||
copiesInserted = 0
|
||||
}
|
||||
break
|
||||
*/
|
||||
case "i", "insert":
|
||||
_, err := logic.StoreCard(db, cardLocation)
|
||||
logic.Check(err)
|
||||
copiesInserted++
|
||||
break
|
||||
/*
|
||||
case "d", "delverlens":
|
||||
filename := GetStringResponse("Filename:")
|
||||
|
||||
cards, err := delverlens.ParseExportFile(filename)
|
||||
logic.Check(err)
|
||||
|
||||
err = logic.ImportDelverLensCards(db, cards, cardLocation.StorageAreaId)
|
||||
logic.Check(err)
|
||||
break
|
||||
*/
|
||||
/*
|
||||
case "l", "locate":
|
||||
filename := GetStringResponse("Filename:")
|
||||
cardNames, err := logic.GetCardNamesFromFile(filename)
|
||||
logic.Check(err)
|
||||
|
||||
locations, err := logic.LocateCards(db, cardNames, locateSearchCriteria)
|
||||
logic.Check(err)
|
||||
|
||||
if len(locations) == 0 {
|
||||
fmt.Println("No results found")
|
||||
fmt.Scanln()
|
||||
break
|
||||
}
|
||||
|
||||
for _, location := range locations {
|
||||
description := logic.GetLocationDescription(location)
|
||||
fmt.Println(description)
|
||||
|
||||
for true {
|
||||
todo := GetStringResponse("TODO:")
|
||||
|
||||
if todo == "r" {
|
||||
logic.RemoveFromStorage(db, location)
|
||||
break
|
||||
} else if todo == "n" {
|
||||
break
|
||||
} else {
|
||||
fmt.Printf("Unrecognized option: %s\n", todo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Though this query has ended, its relics still slumber in New Argive.")
|
||||
fmt.Scanln()
|
||||
break
|
||||
*/
|
||||
default:
|
||||
fmt.Println("Unrecognized command:", command)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"sevenkeys/logic"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetStringResponse(prompt string) string {
|
||||
fmt.Print(prompt + " ")
|
||||
|
||||
var response string
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
scanner.Scan()
|
||||
response = scanner.Text()
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
func GetYesNoResponse(prompt string) bool {
|
||||
response := GetStringResponse(prompt)
|
||||
return strings.ToUpper(response) == "Y"
|
||||
}
|
||||
|
||||
func GetTriadicResponse(prompt string) logic.Triadic {
|
||||
response := GetStringResponse(prompt)
|
||||
|
||||
switch strings.ToUpper(response) {
|
||||
case "Y":
|
||||
return logic.True
|
||||
case "N":
|
||||
return logic.False
|
||||
default:
|
||||
return logic.Either
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"sevenkeys/logic"
|
||||
)
|
||||
|
||||
var shouldRefreshSearch bool = true
|
||||
|
||||
func getSearchCriteria() logic.SearchCriteria {
|
||||
var searchCriteria logic.SearchCriteria
|
||||
|
||||
searchCriteria.SetCode = GetStringResponse("Set code:")
|
||||
searchCriteria.Foil = GetTriadicResponse("Foil (y/n/E):")
|
||||
searchCriteria.Promo = GetTriadicResponse("Promo (y/n/E):")
|
||||
searchCriteria.Language = GetStringResponse("Language:")
|
||||
shouldRefreshSearch = true
|
||||
|
||||
return searchCriteria
|
||||
}
|
||||
|
||||
func getTriadicDisplay(triadic logic.Triadic) string {
|
||||
if triadic == logic.True {
|
||||
return "True"
|
||||
}
|
||||
|
||||
if triadic == logic.False {
|
||||
return "False"
|
||||
}
|
||||
|
||||
return "Either"
|
||||
}
|
||||
|
||||
func showInsertSearchCriteria(insertSearchCriteria logic.SearchCriteria) {
|
||||
fmt.Println("SEARCH CRITERIA")
|
||||
|
||||
setCodeDisplay := getInfoDisplay(insertSearchCriteria.SetCode)
|
||||
foilDisplay := getTriadicDisplay(insertSearchCriteria.Foil)
|
||||
promoDisplay := getTriadicDisplay(insertSearchCriteria.Promo)
|
||||
languageDisplay := getInfoDisplay(insertSearchCriteria.Language)
|
||||
|
||||
fmt.Println("Set code:", setCodeDisplay)
|
||||
fmt.Println("Foil:", foilDisplay)
|
||||
fmt.Println("Promo:", promoDisplay)
|
||||
fmt.Println("Language:", languageDisplay)
|
||||
|
||||
fmt.Print("\n")
|
||||
}
|
||||
|
||||
func showSelectedCard() {
|
||||
selectedCardDisplay := getInfoDisplay(selectedCardPrintingSearchLine)
|
||||
fmt.Println("Selected card:", selectedCardDisplay)
|
||||
}
|
||||
|
||||
func getSearchOptions(db *sql.DB, insertSearchCriteria logic.SearchCriteria) logic.InsertSearchOptions {
|
||||
options, err := logic.GetAllSearchOptions(db, insertSearchCriteria)
|
||||
logic.Check(err)
|
||||
shouldRefreshSearch = false
|
||||
return options
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"sevenkeys/figlet"
|
||||
|
||||
"github.com/inancgumus/screen"
|
||||
)
|
||||
|
||||
func ClearScreen() {
|
||||
screen.Clear()
|
||||
screen.MoveTopLeft()
|
||||
}
|
||||
|
||||
func ShowSplashScreen() {
|
||||
ClearScreen()
|
||||
|
||||
figlet.PrintMsgSlant("SEVENKEYS", "center")
|
||||
figlet.PrintMsgTerm("the ultimate Magic: the Gathering trading card storage system", "center")
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sevenkeys/database"
|
||||
)
|
||||
|
||||
var (
|
||||
selectedCardPrintingSearchLine string
|
||||
|
||||
copiesInserted int
|
||||
)
|
||||
|
||||
func getInfoDisplay(info string) string {
|
||||
if info == "" {
|
||||
return "[EMPTY]"
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
func showStorageInfo(w io.Writer, area database.StorageArea) {
|
||||
fmt.Fprint(w, "Selected Storage Area: ")
|
||||
if area.Name == "" { // TODO: Add a struct method to determine whether it is unset?
|
||||
fmt.Fprint(w, "[None]\n")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s (%s)\n", area.Name, area.StorageType)
|
||||
return
|
||||
}
|
||||
|
||||
func showCopiesInserted() {
|
||||
fmt.Println("Copies inserted:", copiesInserted)
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sevenkeys/database"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_showStorageInfo_DisplaysNone_IfSelectedStorageAreaIsUnset(t *testing.T) {
|
||||
expected := "Selected Storage Area: [None]\n"
|
||||
|
||||
var output bytes.Buffer
|
||||
|
||||
var area database.StorageArea
|
||||
showStorageInfo(&output, area)
|
||||
|
||||
result := output.String()
|
||||
if result != expected {
|
||||
t.Errorf("expected %s, got %s", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_showStorageInfo_DisplaysStorageAreaNameAndType_IfSelectedStorageAreaIsSet(t *testing.T) {
|
||||
expected := "Selected Storage Area: Test A (Box)\n"
|
||||
|
||||
var output bytes.Buffer
|
||||
|
||||
area := database.StorageArea{
|
||||
Id: 1,
|
||||
Name: "Test A",
|
||||
Type: "Box",
|
||||
}
|
||||
showStorageInfo(&output, area)
|
||||
|
||||
result := output.String()
|
||||
if result != expected {
|
||||
t.Errorf("expected %s, got %s", expected, result)
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"sevenkeys/logic"
|
||||
"sevenkeys/logic/scryfall"
|
||||
)
|
||||
|
||||
func RunUpdateCheck(db *sql.DB) {
|
||||
fmt.Println("Checking for updates...")
|
||||
bulkData, err := scryfall.GetBulkDataByType(scryfall.BulkDataTypeAllCards)
|
||||
logic.Check(err)
|
||||
|
||||
needsUpdate, err := logic.CheckForUpdates(db, bulkData)
|
||||
logic.Check(err)
|
||||
|
||||
if !needsUpdate {
|
||||
fmt.Println("No update required.")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Update required.")
|
||||
if GetYesNoResponse("Run update? (y/N)") {
|
||||
fmt.Println("Running update...")
|
||||
|
||||
logic.CreateCacheDirectories()
|
||||
|
||||
err = logic.UpdateSets(db)
|
||||
logic.Check(err)
|
||||
|
||||
err = logic.UpdateCards(db, bulkData)
|
||||
logic.Check(err)
|
||||
|
||||
fmt.Println("Update finished.")
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ INSERT INTO CardPrinting (
|
|||
IsPromo,
|
||||
CollectorNumber,
|
||||
ImageUrl,
|
||||
Language,
|
||||
Language
|
||||
) VALUES (
|
||||
'00000000-0000-0000-0000-0000000000000',
|
||||
'Scanned Card Placeholder',
|
||||
|
@ -43,7 +43,7 @@ INSERT INTO CardPrinting (
|
|||
0,
|
||||
0,
|
||||
'',
|
||||
'en',
|
||||
'en'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS StorageArea (
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
package logic
|
||||
|
||||
import "sevenkeys/database"
|
||||
import (
|
||||
"sevenkeys/database"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func filterPrinting(printing database.CardPrinting, searchCriteria SearchCriteria) bool {
|
||||
if searchCriteria.SetCode != "" && printing.SetCode != searchCriteria.SetCode {
|
||||
if searchCriteria.SetCode != "" && !strings.Contains(printing.SetCode, searchCriteria.SetCode) {
|
||||
return true
|
||||
}
|
||||
|
||||
if searchCriteria.CollectorNumber != "" && !strings.Contains(printing.CollectorNumber, searchCriteria.CollectorNumber) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -400,3 +400,27 @@ func TestFilterPrinting_ReturnsFalse_IfLanguageNotSet(t *testing.T) {
|
|||
t.Errorf("filter was true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterPrinting_ReturnsTrue_IfSetCodeMatchesButCollectorNumberDoesnt(t *testing.T) {
|
||||
printing := database.CardPrinting{
|
||||
SetCode: "rtr",
|
||||
CollectorNumber: "301",
|
||||
IsFoil: false,
|
||||
IsPromo: false,
|
||||
Language: "en",
|
||||
}
|
||||
|
||||
searchCriteria := SearchCriteria{
|
||||
SetCode: "rtr",
|
||||
CollectorNumber: "299",
|
||||
Foil: False,
|
||||
Promo: False,
|
||||
Language: "",
|
||||
}
|
||||
|
||||
filter := filterPrinting(printing, searchCriteria)
|
||||
|
||||
if filter != true {
|
||||
t.Errorf("filter was false")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,17 +20,16 @@ const (
|
|||
|
||||
type SearchCriteria struct {
|
||||
SetCode string
|
||||
CollectorNumber string
|
||||
Foil Triadic
|
||||
Promo Triadic
|
||||
Language string
|
||||
}
|
||||
|
||||
// The InsertSearchOptions type is a map of `string` keys (which can be searched using
|
||||
// fzf) to `string` values (which represent a primary key in the CardPrintings table)
|
||||
type InsertSearchOptions map[string]string
|
||||
type CardPrintingSearchOptions map[string]string
|
||||
|
||||
func GetAllSearchOptions(db *sql.DB, searchCriteria SearchCriteria) (InsertSearchOptions, error) {
|
||||
var searchOptions InsertSearchOptions = make(InsertSearchOptions)
|
||||
func GetAllCardPrintingSearchOptions(db *sql.DB, searchCriteria SearchCriteria) (CardPrintingSearchOptions, error) {
|
||||
var searchOptions CardPrintingSearchOptions = make(CardPrintingSearchOptions)
|
||||
|
||||
cardPrintings, err := database.GetAllCardPrintings(db)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,21 +1,40 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sevenkeys/cli"
|
||||
"sevenkeys/database"
|
||||
"sevenkeys/delverlens"
|
||||
"sevenkeys/logic"
|
||||
"sevenkeys/logic/scryfall"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetStringResponse(prompt string) string {
|
||||
fmt.Print(prompt + " ")
|
||||
|
||||
var response string
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
scanner.Scan()
|
||||
response = scanner.Text()
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
func GetYesNoResponse(prompt string) bool {
|
||||
response := GetStringResponse(prompt)
|
||||
return strings.ToUpper(response) == "Y"
|
||||
}
|
||||
|
||||
const (
|
||||
UpdateSubcommand string = "update"
|
||||
CreateStorageAreaSubcommand string = "createstorage"
|
||||
StoreSubcommand string = "store"
|
||||
ImportSubcommand string = "import"
|
||||
SearchSubcommand string = "search"
|
||||
SearchPrintingsSubcommand string = "search-printings"
|
||||
SearchStorageSubcommand string = "search-storage"
|
||||
DeckSubcommand string = "deck"
|
||||
)
|
||||
|
||||
|
@ -44,7 +63,33 @@ func main() {
|
|||
|
||||
switch flag.Args()[0] {
|
||||
case UpdateSubcommand:
|
||||
cli.RunUpdateCheck(db)
|
||||
fmt.Println("Checking for updates...")
|
||||
bulkData, err := scryfall.GetBulkDataByType(scryfall.BulkDataTypeAllCards)
|
||||
logic.Check(err)
|
||||
|
||||
needsUpdate, err := logic.CheckForUpdates(db, bulkData)
|
||||
logic.Check(err)
|
||||
|
||||
if !needsUpdate {
|
||||
fmt.Println("No update required.")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Update required.")
|
||||
|
||||
if GetYesNoResponse("Run update? (y/N)") {
|
||||
fmt.Println("Running update...")
|
||||
|
||||
logic.CreateCacheDirectories()
|
||||
|
||||
err = logic.UpdateSets(db)
|
||||
logic.Check(err)
|
||||
|
||||
err = logic.UpdateCards(db, bulkData)
|
||||
logic.Check(err)
|
||||
|
||||
fmt.Println("Update finished.")
|
||||
}
|
||||
break
|
||||
case CreateStorageAreaSubcommand:
|
||||
createStorageCmd := flag.NewFlagSet(CreateStorageAreaSubcommand, flag.ExitOnError)
|
||||
|
@ -103,7 +148,37 @@ func main() {
|
|||
err = logic.ImportDelverLensCards(db, delverLensCards, storageAreaId)
|
||||
logic.Check(err)
|
||||
break
|
||||
case SearchSubcommand:
|
||||
case SearchPrintingsSubcommand:
|
||||
searchPrintingsCmd := flag.NewFlagSet(SearchPrintingsSubcommand, flag.ExitOnError)
|
||||
|
||||
setCode := searchPrintingsCmd.String("set-code", "", "The code for the set the card we're searching for belongs to.")
|
||||
collectorNumber := searchPrintingsCmd.String("collector-number", "", "The collector number of the card we're searching for.")
|
||||
foil := searchPrintingsCmd.String("foil", "E", "Whether the card we're searching for is foil.")
|
||||
|
||||
searchPrintingsCmd.Parse(flag.Args()[1:])
|
||||
|
||||
searchCriteria := logic.SearchCriteria{
|
||||
SetCode: *setCode,
|
||||
CollectorNumber: *collectorNumber,
|
||||
Promo: logic.Either,
|
||||
Language: "en",
|
||||
}
|
||||
|
||||
if *foil == "Y" {
|
||||
searchCriteria.Foil = logic.True
|
||||
} else if *foil == "N" {
|
||||
searchCriteria.Foil = logic.False
|
||||
} else {
|
||||
searchCriteria.Foil = logic.Either
|
||||
}
|
||||
|
||||
searchOptions, err := logic.GetAllCardPrintingSearchOptions(db, searchCriteria)
|
||||
logic.Check(err)
|
||||
id, _, err := logic.GenericSearch(searchOptions)
|
||||
logic.Check(err)
|
||||
fmt.Println(id)
|
||||
break
|
||||
case SearchStorageSubcommand:
|
||||
searchOptions, err := logic.GetAllStorageSearchOptions(db)
|
||||
logic.Check(err)
|
||||
id, _, err := logic.GenericSearch(searchOptions)
|
||||
|
|
Loading…
Reference in New Issue