Added dict with additional cards
This commit is contained in:
parent
181f3bc0aa
commit
88ea431a27
26 changed files with 232 additions and 35 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
vendor
|
vendor
|
||||||
go-mtg-vk
|
|
||||||
*.swp
|
*.swp
|
||||||
hosts
|
hosts
|
||||||
.idea
|
.idea
|
||||||
|
.venv
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
FROM golang:1.15.4-alpine3.12
|
FROM golang:1.15.4-alpine3.12
|
||||||
|
|
||||||
COPY . /go/src/go-mtg-vk
|
COPY . /go/src/go-mtg-vk
|
||||||
WORKDIR /go/src/go-mtg-vk
|
WORKDIR /go/src/go-mtg-vk/cmd/go-mtg-vk
|
||||||
RUN go install
|
RUN go install
|
||||||
WORKDIR /go/bin
|
WORKDIR /go/bin
|
||||||
RUN mkdir logs
|
RUN mkdir logs
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitlab.com/flygrounder/go-mtg-vk/vk"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"gitlab.com/flygrounder/go-mtg-vk/internal/vk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -17,5 +17,5 @@ func main() {
|
||||||
log.SetOutput(logFile)
|
log.SetOutput(logFile)
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.POST("callback/message", vk.HandleMessage)
|
r.POST("callback/message", vk.HandleMessage)
|
||||||
_ = r.Run(":80")
|
_ = r.Run(":8000")
|
||||||
}
|
}
|
||||||
16
docker-compose-dev.yaml
Normal file
16
docker-compose-dev.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
version: "3.3"
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
environment:
|
||||||
|
- VK_TOKEN
|
||||||
|
- VK_SECRET_KEY
|
||||||
|
- VK_GROUP_ID
|
||||||
|
- VK_CONFIRMATION_STRING
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8888:8000"
|
||||||
|
restart: "always"
|
||||||
|
redis:
|
||||||
|
image: "redis:6.0.9"
|
||||||
|
restart: "always"
|
||||||
|
|
@ -9,7 +9,7 @@ services:
|
||||||
- VK_CONFIRMATION_STRING
|
- VK_CONFIRMATION_STRING
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8888:80"
|
- "127.0.0.1:8888:8000"
|
||||||
restart: "always"
|
restart: "always"
|
||||||
redis:
|
redis:
|
||||||
image: "redis:6.0.9"
|
image: "redis:6.0.9"
|
||||||
|
|
|
||||||
1
go.mod
1
go.mod
|
|
@ -14,6 +14,7 @@ require (
|
||||||
github.com/onsi/gomega v1.7.1 // indirect
|
github.com/onsi/gomega v1.7.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
|
github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c
|
||||||
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da // indirect
|
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da // indirect
|
||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
|
||||||
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c // indirect
|
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c // indirect
|
||||||
|
|
|
||||||
3
go.sum
3
go.sum
|
|
@ -52,6 +52,9 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U=
|
||||||
|
github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c h1:HelZ2kAFadG0La9d+4htN4HzQ68Bm2iM9qKMSMES6xg=
|
||||||
|
github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c/go.mod h1:JlzghshsemAMDGZLytTFY8C1JQxQPhnatWqNwUXjggo=
|
||||||
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
|
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ func getTestClient() (*CacheClient, *miniredis.Miniredis) {
|
||||||
Addr: s.Addr(),
|
Addr: s.Addr(),
|
||||||
})
|
})
|
||||||
return &CacheClient{
|
return &CacheClient{
|
||||||
Storage: c,
|
Storage: c,
|
||||||
Expiration: 0,
|
Expiration: 0,
|
||||||
}, s
|
}, s
|
||||||
}
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ func FormatCardPrices(name string, prices []CardPrice) string {
|
||||||
message := fmt.Sprintf("Оригинальное название: %v\n", name)
|
message := fmt.Sprintf("Оригинальное название: %v\n", name)
|
||||||
message += fmt.Sprintf("Результатов: %v\n", len(prices))
|
message += fmt.Sprintf("Результатов: %v\n", len(prices))
|
||||||
for i, v := range prices {
|
for i, v := range prices {
|
||||||
message += fmt.Sprintf("%v. %v", i + 1, v.Format())
|
message += fmt.Sprintf("%v. %v", i+1, v.Format())
|
||||||
}
|
}
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,8 @@ package cardsinfo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"gitlab.com/flygrounder/go-mtg-vk/internal/dicttranslate"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
@ -18,9 +20,13 @@ func GetNameByCardId(set string, number string) string {
|
||||||
return GetCardByUrl(path)
|
return GetCardByUrl(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetOriginalName(name string) string {
|
func GetOriginalName(name string, dict io.Reader) string {
|
||||||
path := ScryfallUrl + "/cards/named?fuzzy=" + ApplyFilters(name)
|
path := ScryfallUrl + "/cards/named?fuzzy=" + ApplyFilters(name)
|
||||||
return GetCardByUrl(path)
|
result := GetCardByUrl(path)
|
||||||
|
if result == "" && dict != nil {
|
||||||
|
result, _ = dicttranslate.FindFromReader(name, dict, 5)
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyFilters(name string) string {
|
func ApplyFilters(name string) string {
|
||||||
|
|
@ -2,36 +2,37 @@ package cardsinfo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetCardByStringFull(t *testing.T) {
|
func TestGetCardByStringFull(t *testing.T) {
|
||||||
name := GetOriginalName("Шок")
|
name := GetOriginalName("Шок", nil)
|
||||||
assert.Equal(t, "Shock", name)
|
assert.Equal(t, "Shock", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCardByStringSplit(t *testing.T) {
|
func TestGetCardByStringSplit(t *testing.T) {
|
||||||
name := GetOriginalName("commit")
|
name := GetOriginalName("commit", nil)
|
||||||
assert.Equal(t, "Commit // Memory", name)
|
assert.Equal(t, "Commit // Memory", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCardByStringDouble(t *testing.T) {
|
func TestGetCardByStringDouble(t *testing.T) {
|
||||||
name := GetOriginalName("Legion's landing")
|
name := GetOriginalName("Legion's landing", nil)
|
||||||
assert.Equal(t, "Legion's Landing | Adanto, the First Fort", name)
|
assert.Equal(t, "Legion's Landing | Adanto, the First Fort", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCardByStringPrefix(t *testing.T) {
|
func TestGetCardByStringPrefix(t *testing.T) {
|
||||||
name := GetOriginalName("Тефери, герой")
|
name := GetOriginalName("Тефери, герой", nil)
|
||||||
assert.Equal(t, "Teferi, Hero of Dominaria", name)
|
assert.Equal(t, "Teferi, Hero of Dominaria", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCardByStringEnglish(t *testing.T) {
|
func TestGetCardByStringEnglish(t *testing.T) {
|
||||||
name := GetOriginalName("Teferi, Hero of Dominaria")
|
name := GetOriginalName("Teferi, Hero of Dominaria", nil)
|
||||||
assert.Equal(t, "Teferi, Hero of Dominaria", name)
|
assert.Equal(t, "Teferi, Hero of Dominaria", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCardByStringWrong(t *testing.T) {
|
func TestGetCardByStringWrong(t *testing.T) {
|
||||||
name := GetOriginalName("fwijefiwjfew")
|
name := GetOriginalName("fwijefiwjfew", nil)
|
||||||
assert.Equal(t, "", name)
|
assert.Equal(t, "", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,3 +45,9 @@ func TestGetCardBySetIdWrong(t *testing.T) {
|
||||||
name := GetNameByCardId("DOM", "1207")
|
name := GetNameByCardId("DOM", "1207")
|
||||||
assert.Equal(t, "", name)
|
assert.Equal(t, "", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetCardByStringDict(t *testing.T) {
|
||||||
|
dictContent := "{\"n0suchc8rdc8n3x1s1\":\"Success\"}"
|
||||||
|
name := GetOriginalName("n0suchc8rdc8n3x1s1", strings.NewReader(dictContent))
|
||||||
|
assert.Equal(t, "Success", name)
|
||||||
|
}
|
||||||
|
|
@ -8,10 +8,10 @@ import (
|
||||||
func TestFormat(t *testing.T) {
|
func TestFormat(t *testing.T) {
|
||||||
data := []CardPrice{
|
data := []CardPrice{
|
||||||
&TcgCardPrice{
|
&TcgCardPrice{
|
||||||
Name: "Green lotus",
|
Name: "Green lotus",
|
||||||
PriceFoil: "22.8",
|
PriceFoil: "22.8",
|
||||||
Link: "scg.com/1",
|
Link: "scg.com/1",
|
||||||
Edition: "alpha",
|
Edition: "alpha",
|
||||||
},
|
},
|
||||||
&TcgCardPrice{
|
&TcgCardPrice{
|
||||||
Name: "White lotus",
|
Name: "White lotus",
|
||||||
|
|
@ -71,12 +71,12 @@ func GetPricesTcg(name string) ([]CardPrice, error) {
|
||||||
if card.Prices.USD == "" && card.Prices.USDFoil == "" {
|
if card.Prices.USD == "" && card.Prices.USDFoil == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cardPrice := &TcgCardPrice {
|
cardPrice := &TcgCardPrice{
|
||||||
Edition: edition,
|
Edition: edition,
|
||||||
Price: card.Prices.USD,
|
Price: card.Prices.USD,
|
||||||
PriceFoil: card.Prices.USDFoil,
|
PriceFoil: card.Prices.USDFoil,
|
||||||
Name: card.Name,
|
Name: card.Name,
|
||||||
Link: card.PurchaseURIs.TCGPlayer,
|
Link: card.PurchaseURIs.TCGPlayer,
|
||||||
}
|
}
|
||||||
prices = append(prices, cardPrice)
|
prices = append(prices, cardPrice)
|
||||||
}
|
}
|
||||||
|
|
@ -10,12 +10,12 @@ type CardPrice interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TcgCardPrice struct {
|
type TcgCardPrice struct {
|
||||||
FullArt bool
|
FullArt bool
|
||||||
Name string
|
Name string
|
||||||
Price string
|
Price string
|
||||||
PriceFoil string
|
PriceFoil string
|
||||||
Link string
|
Link string
|
||||||
Edition string
|
Edition string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TcgCardPrice) Format() string {
|
func (t *TcgCardPrice) Format() string {
|
||||||
|
|
@ -30,9 +30,9 @@ func formatTcgPrice(price string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ScgCardPrice struct {
|
type ScgCardPrice struct {
|
||||||
Price string
|
Price string
|
||||||
Edition string
|
Edition string
|
||||||
Link string
|
Link string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ScgCardPrice) Format() string {
|
func (s *ScgCardPrice) Format() string {
|
||||||
23
internal/dicttranslate/find.go
Normal file
23
internal/dicttranslate/find.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package dicttranslate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func find(query string, dict map[string]string, maxDist int) (string, bool) {
|
||||||
|
var keys []string
|
||||||
|
for i := range dict {
|
||||||
|
keys = append(keys, i)
|
||||||
|
}
|
||||||
|
key, f := match(query, keys, maxDist)
|
||||||
|
return dict[key], f
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindFromReader(query string, reader io.Reader, maxDist int) (string, bool) {
|
||||||
|
content, _ := ioutil.ReadAll(reader)
|
||||||
|
dict := map[string]string{}
|
||||||
|
_ = json.Unmarshal(content, &dict)
|
||||||
|
return find(query, dict, maxDist)
|
||||||
|
}
|
||||||
33
internal/dicttranslate/find_test.go
Normal file
33
internal/dicttranslate/find_test.go
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package dicttranslate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFindEmpty(t *testing.T) {
|
||||||
|
dict := map[string]string{}
|
||||||
|
_, f := find("", dict, 0)
|
||||||
|
assert.False(t, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindEntry(t *testing.T) {
|
||||||
|
dict := map[string]string{
|
||||||
|
"entry": "value",
|
||||||
|
}
|
||||||
|
val, f := find("entry", dict, 0)
|
||||||
|
assert.True(t, f)
|
||||||
|
assert.Equal(t, "value", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindFromReaderFail(t *testing.T) {
|
||||||
|
_, f := FindFromReader("entry", strings.NewReader("{}"), 0)
|
||||||
|
assert.False(t, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindFromReaderSuccess(t *testing.T) {
|
||||||
|
value, f := FindFromReader("entry", strings.NewReader("{\"entry\":\"value\"}"), 0)
|
||||||
|
assert.True(t, f)
|
||||||
|
assert.Equal(t, "value", value)
|
||||||
|
}
|
||||||
21
internal/dicttranslate/match.go
Normal file
21
internal/dicttranslate/match.go
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
package dicttranslate
|
||||||
|
|
||||||
|
import "github.com/texttheater/golang-levenshtein/levenshtein"
|
||||||
|
|
||||||
|
func match(query string, opts []string, maxDist int) (string, bool) {
|
||||||
|
bestInd := -1
|
||||||
|
bestDist := 0
|
||||||
|
for i, s := range opts {
|
||||||
|
cfg := levenshtein.DefaultOptions
|
||||||
|
cfg.SubCost = 1
|
||||||
|
dist := levenshtein.DistanceForStrings([]rune(s), []rune(query), cfg)
|
||||||
|
if dist <= maxDist && (bestInd == -1 || dist < bestDist) {
|
||||||
|
bestInd = i
|
||||||
|
bestDist = dist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bestInd == -1 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return opts[bestInd], true
|
||||||
|
}
|
||||||
52
internal/dicttranslate/match_test.go
Normal file
52
internal/dicttranslate/match_test.go
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
package dicttranslate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMatch(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
name string
|
||||||
|
query string
|
||||||
|
opts []string
|
||||||
|
shouldFind bool
|
||||||
|
match string
|
||||||
|
}
|
||||||
|
tests := []testCase{
|
||||||
|
{
|
||||||
|
name: "No options",
|
||||||
|
query: "opt",
|
||||||
|
opts: []string{},
|
||||||
|
shouldFind: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Match one",
|
||||||
|
query: "option",
|
||||||
|
opts: []string{"opt1on"},
|
||||||
|
shouldFind: true,
|
||||||
|
match: "opt1on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Match exact",
|
||||||
|
query: "opt1on",
|
||||||
|
opts: []string{"option", "opt1on"},
|
||||||
|
shouldFind: true,
|
||||||
|
match: "opt1on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Do not match bad options",
|
||||||
|
query: "random",
|
||||||
|
opts: []string{"option", "opt1on"},
|
||||||
|
shouldFind: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
val, f := match(test.query, test.opts, 1)
|
||||||
|
assert.Equal(t, test.shouldFind, f)
|
||||||
|
assert.Equal(t, test.match, val)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,13 +4,16 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gitlab.com/flygrounder/go-mtg-vk/caching"
|
|
||||||
"gitlab.com/flygrounder/go-mtg-vk/cardsinfo"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"gitlab.com/flygrounder/go-mtg-vk/internal/caching"
|
||||||
|
"gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var dictPath = "./assets/additional_cards.json"
|
||||||
|
|
||||||
func HandleMessage(c *gin.Context) {
|
func HandleMessage(c *gin.Context) {
|
||||||
var req MessageRequest
|
var req MessageRequest
|
||||||
_ = c.BindJSON(&req)
|
_ = c.BindJSON(&req)
|
||||||
|
|
@ -78,7 +81,8 @@ func getCardNameByCommand(command string) (string, error) {
|
||||||
number := split[2]
|
number := split[2]
|
||||||
name = cardsinfo.GetNameByCardId(set, number)
|
name = cardsinfo.GetNameByCardId(set, number)
|
||||||
default:
|
default:
|
||||||
name = cardsinfo.GetOriginalName(command)
|
dict, _ := os.Open(dictPath)
|
||||||
|
name = cardsinfo.GetOriginalName(command, dict)
|
||||||
}
|
}
|
||||||
return name, nil
|
return name, nil
|
||||||
}
|
}
|
||||||
31
scripts/spoiler_fetcher.py
Normal file
31
scripts/spoiler_fetcher.py
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
from json import dumps
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
URL_TEMPLATE = "https://magic.wizards.com/{}/articles/archive/card-image-gallery/{}"
|
||||||
|
OUTPUT_FILE_TEMPLATE = "{}.json"
|
||||||
|
|
||||||
|
|
||||||
|
def get_card_names(language, set_name):
|
||||||
|
spoiler_url = URL_TEMPLATE.format(language, set_name)
|
||||||
|
response = requests.get(spoiler_url)
|
||||||
|
dom = etree.HTML(response.content.decode())
|
||||||
|
card_names = dom.xpath('//div[@class="resizing-cig"]//p/text()')
|
||||||
|
return [str(name).strip() for name in card_names]
|
||||||
|
|
||||||
|
|
||||||
|
def match_names(keys, values):
|
||||||
|
return dict(zip(keys, values))
|
||||||
|
|
||||||
|
|
||||||
|
set_name = input("Введите сет: ")
|
||||||
|
|
||||||
|
russian_names = get_card_names("ru", set_name)
|
||||||
|
english_names = get_card_names("en", set_name)
|
||||||
|
|
||||||
|
match = match_names(russian_names, english_names)
|
||||||
|
print(match)
|
||||||
|
|
||||||
|
with open(OUTPUT_FILE_TEMPLATE.format(set_name), 'w') as output:
|
||||||
|
output.write(dumps(match))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue