diff --git a/internal/caching/cache.go b/internal/caching/cache.go index 6804779..415d9d6 100644 --- a/internal/caching/cache.go +++ b/internal/caching/cache.go @@ -1,9 +1,12 @@ package caching import ( + "encoding/json" "time" "github.com/go-redis/redis" + "github.com/pkg/errors" + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" ) type CacheClient struct { @@ -22,10 +25,17 @@ func NewClient(addr string, passwd string, expiration time.Duration, db int) *Ca } } -func (client *CacheClient) Set(key string, value string) { +func (client *CacheClient) Set(key string, prices []cardsinfo.ScgCardPrice) { + value, _ := json.Marshal(prices) client.Storage.Set(key, value, client.Expiration) } -func (client *CacheClient) Get(key string) (string, error) { - return client.Storage.Get(key).Result() +func (client *CacheClient) Get(key string) ([]cardsinfo.ScgCardPrice, error) { + c, err := client.Storage.Get(key).Result() + if err != nil { + return nil, errors.Wrap(err, "No such key in cache") + } + var prices []cardsinfo.ScgCardPrice + json.Unmarshal([]byte(c), &prices) + return prices, nil } diff --git a/internal/caching/cache_test.go b/internal/caching/cache_test.go index d434102..94074da 100644 --- a/internal/caching/cache_test.go +++ b/internal/caching/cache_test.go @@ -8,6 +8,7 @@ import ( "github.com/alicebob/miniredis/v2" "github.com/go-redis/redis" "github.com/stretchr/testify/assert" + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" ) func TestGetClient(t *testing.T) { @@ -23,7 +24,13 @@ func TestGetSet(t *testing.T) { defer s.Close() keyName := "test_key" - value := "test_value" + value := []cardsinfo.ScgCardPrice{ + { + Price: "1", + Edition: "Alpha", + Link: "scg", + }, + } client.Set(keyName, value) val, err := client.Get(keyName) assert.Nil(t, err) @@ -36,11 +43,11 @@ func TestExpiration(t *testing.T) { client.Expiration = time.Millisecond keyName := "test_key" - value := "test_value" + var value []cardsinfo.ScgCardPrice client.Set(keyName, value) s.FastForward(time.Millisecond * 2) val, err := client.Get(keyName) - assert.Zero(t, val) + assert.Nil(t, val) assert.NotNil(t, err) } diff --git a/internal/cardsinfo/card.go b/internal/cardsinfo/card.go index a8c6543..a7b9748 100644 --- a/internal/cardsinfo/card.go +++ b/internal/cardsinfo/card.go @@ -1,18 +1,13 @@ package cardsinfo import ( - "fmt" "strings" ) -type scgCardPrice struct { - price string - edition string - link string -} - -func (s *scgCardPrice) format() string { - return fmt.Sprintf("%v: %v\n%v\n", s.edition, s.price, s.link) +type ScgCardPrice struct { + Price string + Edition string + Link string } type card struct { diff --git a/internal/cardsinfo/format.go b/internal/cardsinfo/format.go deleted file mode 100644 index 9f65007..0000000 --- a/internal/cardsinfo/format.go +++ /dev/null @@ -1,24 +0,0 @@ -package cardsinfo - -import ( - "fmt" -) - -func (f *Fetcher) GetFormattedCardPrices(name string) (string, error) { - prices, err := f.getPrices(name) - if err != nil { - return "", err - } - return f.formatCardPrices(name, prices), nil -} - -func (f *Fetcher) formatCardPrices(name string, prices []scgCardPrice) string { - message := fmt.Sprintf("Оригинальное название: %v\n\n", name) - for i, v := range prices { - message += fmt.Sprintf("%v. %v", i+1, v.format()) - } - if len(prices) == 0 { - message += "Цен не найдено\n" - } - return message -} diff --git a/internal/cardsinfo/format_test.go b/internal/cardsinfo/format_test.go deleted file mode 100644 index c7cdbab..0000000 --- a/internal/cardsinfo/format_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package cardsinfo - -import ( - "net/http" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "gopkg.in/h2non/gock.v1" -) - -func TestFetcher_GetFormattedCardPrices_Error(t *testing.T) { - defer gock.Off() - - gock.New(scgSearchUrlTemplate + "card").Reply(http.StatusInternalServerError) - f := &Fetcher{} - _, err := f.GetFormattedCardPrices("card") - assert.NotNil(t, err) -} - -func TestFetcher_GetFormattedCardPrices_Empty(t *testing.T) { - defer gock.Off() - - resp, _ := os.Open("test_data/EmptyTest.html") - gock.New(scgSearchUrlTemplate + "card").Reply(http.StatusOK).Body(resp) - f := &Fetcher{} - msg, err := f.GetFormattedCardPrices("card") - assert.Nil(t, err) - assert.Equal(t, "Оригинальное название: card\n\nЦен не найдено\n", msg) -} - -func TestFormatCardPrices(t *testing.T) { - f := &Fetcher{} - formatted := f.formatCardPrices("card", []scgCardPrice{ - { - price: "1.5$", - edition: "ED", - link: "scg.com", - }, - }) - assert.Equal(t, "Оригинальное название: card\n\n1. ED: 1.5$\nscg.com\n", formatted) -} diff --git a/internal/cardsinfo/prices.go b/internal/cardsinfo/prices.go index 785c76b..ea41abc 100644 --- a/internal/cardsinfo/prices.go +++ b/internal/cardsinfo/prices.go @@ -11,7 +11,7 @@ import ( const scgDomain = "https://starcitygames.com" const scgSearchUrlTemplate = "https://starcitygames.hawksearch.com/sites/starcitygames/?search_query=" -func (f *Fetcher) getPrices(name string) ([]scgCardPrice, error) { +func (f *Fetcher) GetPrices(name string) ([]ScgCardPrice, error) { prices, err := getPricesScg(name) if err != nil { return nil, err @@ -22,7 +22,7 @@ func (f *Fetcher) getPrices(name string) ([]scgCardPrice, error) { return prices, nil } -func getPricesScg(name string) ([]scgCardPrice, error) { +func getPricesScg(name string) ([]ScgCardPrice, error) { escapedName := url.QueryEscape(name) searchUrl := scgSearchUrlTemplate + escapedName node, err := htmlquery.LoadURL(searchUrl) @@ -30,18 +30,18 @@ func getPricesScg(name string) ([]scgCardPrice, error) { return nil, errors.Wrap(err, "cannot load url") } blocks := htmlquery.Find(node, "//div[@class=\"hawk-results-item\"]") - var results []scgCardPrice + var results []ScgCardPrice for _, block := range blocks { - price := scgCardPrice{} + price := ScgCardPrice{} linkNode := htmlquery.FindOne(block, "//h2/a") - price.link = scgDomain + htmlquery.SelectAttr(linkNode, "href") + price.Link = scgDomain + htmlquery.SelectAttr(linkNode, "href") editionNode := htmlquery.FindOne(block, "//p[@class=\"hawk-results-item__category\"]/a") if !strings.HasPrefix(htmlquery.SelectAttr(editionNode, "href"), "/shop/singles/") { continue } - price.edition = editionNode.FirstChild.Data + price.Edition = editionNode.FirstChild.Data priceNode := htmlquery.FindOne(block, "//span[@class='hawk-old-price']|//div[contains(concat(' ',normalize-space(@class),' '),' hawk-results-item__options-table-cell--price ')]") - price.price = priceNode.FirstChild.Data + price.Price = priceNode.FirstChild.Data results = append(results, price) } return results, nil diff --git a/internal/cardsinfo/prices_test.go b/internal/cardsinfo/prices_test.go index 8b367a1..9f0e723 100644 --- a/internal/cardsinfo/prices_test.go +++ b/internal/cardsinfo/prices_test.go @@ -16,33 +16,33 @@ func TestGetPrices_Ok(t *testing.T) { file, _ := os.Open("test_data/AcademyRuinsTest.html") gock.New(scgSearchUrlTemplate + "card").Reply(http.StatusOK).Body(file) f := &Fetcher{} - prices, err := f.getPrices("card") + prices, err := f.GetPrices("card") assert.Nil(t, err) - assert.Equal(t, []scgCardPrice{ + assert.Equal(t, []ScgCardPrice{ { - price: "$6.99", - edition: "Double Masters", - link: "https://starcitygames.com/academy-ruins-sgl-mtg-2xm-309-enn/?sku=SGL-MTG-2XM-309-ENN1", + Price: "$6.99", + Edition: "Double Masters", + Link: "https://starcitygames.com/academy-ruins-sgl-mtg-2xm-309-enn/?sku=SGL-MTG-2XM-309-ENN1", }, { - price: "$9.99", - edition: "Double Masters (Foil)", - link: "https://starcitygames.com/academy-ruins-sgl-mtg-2xm-309-enf/?sku=SGL-MTG-2XM-309-ENF1", + Price: "$9.99", + Edition: "Double Masters (Foil)", + Link: "https://starcitygames.com/academy-ruins-sgl-mtg-2xm-309-enf/?sku=SGL-MTG-2XM-309-ENF1", }, { - price: "$11.99", - edition: "Double Masters - Variants", - link: "https://starcitygames.com/academy-ruins-sgl-mtg-2xm2-369-enn/?sku=SGL-MTG-2XM2-369-ENN1", + Price: "$11.99", + Edition: "Double Masters - Variants", + Link: "https://starcitygames.com/academy-ruins-sgl-mtg-2xm2-369-enn/?sku=SGL-MTG-2XM2-369-ENN1", }, { - price: "$14.99", - edition: "Double Masters - Variants (Foil)", - link: "https://starcitygames.com/academy-ruins-sgl-mtg-2xm2-369-enf/?sku=SGL-MTG-2XM2-369-ENF1", + Price: "$14.99", + Edition: "Double Masters - Variants (Foil)", + Link: "https://starcitygames.com/academy-ruins-sgl-mtg-2xm2-369-enf/?sku=SGL-MTG-2XM2-369-ENF1", }, { - price: "$7.99", - edition: "Modern Masters: 2013 Edition", - link: "https://starcitygames.com/academy-ruins-sgl-mtg-mma-219-enn/?sku=SGL-MTG-MMA-219-ENN1", + Price: "$7.99", + Edition: "Modern Masters: 2013 Edition", + Link: "https://starcitygames.com/academy-ruins-sgl-mtg-mma-219-enn/?sku=SGL-MTG-MMA-219-ENN1", }, }, prices) } @@ -52,7 +52,7 @@ func TestGetPrices_Unavailable(t *testing.T) { gock.New(scgSearchUrlTemplate + "card").Reply(http.StatusBadGateway) f := &Fetcher{} - _, err := f.getPrices("card") + _, err := f.GetPrices("card") assert.NotNil(t, err) } @@ -62,7 +62,7 @@ func TestGetPrices_Empty(t *testing.T) { file, _ := os.Open("test_data/EmptyTest.html") gock.New(scgSearchUrlTemplate + "card").Reply(http.StatusOK).Body(file) f := &Fetcher{} - prices, err := f.getPrices("card") + prices, err := f.GetPrices("card") assert.Nil(t, err) assert.Nil(t, prices) } @@ -73,33 +73,33 @@ func TestGetPrices_FilterNonCards(t *testing.T) { file, _ := os.Open("test_data/NonCards.html") gock.New(scgSearchUrlTemplate + "card").Reply(http.StatusOK).Body(file) f := &Fetcher{} - prices, err := f.getPrices("card") + prices, err := f.GetPrices("card") assert.Nil(t, err) - expected := []scgCardPrice{ + expected := []ScgCardPrice{ { - price: "$72.99", - edition: "3rd Edition - Black Border", - link: "https://starcitygames.com/sol-ring-sgl-mtg-3bb-274-frn/?sku=SGL-MTG-3BB-274-FRN3", + Price: "$72.99", + Edition: "3rd Edition - Black Border", + Link: "https://starcitygames.com/sol-ring-sgl-mtg-3bb-274-frn/?sku=SGL-MTG-3BB-274-FRN3", }, { - price: "$24.99", - edition: "3rd Edition/Revised", - link: "https://starcitygames.com/sol-ring-sgl-mtg-3ed-274-enn/?sku=SGL-MTG-3ED-274-ENN1", + Price: "$24.99", + Edition: "3rd Edition/Revised", + Link: "https://starcitygames.com/sol-ring-sgl-mtg-3ed-274-enn/?sku=SGL-MTG-3ED-274-ENN1", }, { - price: "$1,999.99", - edition: "Alpha", - link: "https://starcitygames.com/sol-ring-sgl-mtg-lea-269-enn/?sku=SGL-MTG-LEA-269-ENN1", + Price: "$1,999.99", + Edition: "Alpha", + Link: "https://starcitygames.com/sol-ring-sgl-mtg-lea-269-enn/?sku=SGL-MTG-LEA-269-ENN1", }, { - price: "$1,199.99", - edition: "Beta", - link: "https://starcitygames.com/sol-ring-sgl-mtg-leb-270-enn/?sku=SGL-MTG-LEB-270-ENN1", + Price: "$1,199.99", + Edition: "Beta", + Link: "https://starcitygames.com/sol-ring-sgl-mtg-leb-270-enn/?sku=SGL-MTG-LEB-270-ENN1", }, { - price: "$99.99", - edition: "Collectors' Edition", - link: "https://starcitygames.com/sol-ring-sgl-mtg-ced-270-enn/?sku=SGL-MTG-CED-270-ENN1", + Price: "$99.99", + Edition: "Collectors' Edition", + Link: "https://starcitygames.com/sol-ring-sgl-mtg-ced-270-enn/?sku=SGL-MTG-CED-270-ENN1", }, } assert.Equal(t, expected, prices) diff --git a/internal/scenario/scenario.go b/internal/scenario/scenario.go index f09d052..e6bdecd 100644 --- a/internal/scenario/scenario.go +++ b/internal/scenario/scenario.go @@ -4,6 +4,8 @@ import ( "errors" "log" "strings" + + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" ) const ( @@ -13,10 +15,10 @@ const ( ) type Scenario struct { - Sender Sender - Logger *log.Logger - InfoFetcher CardInfoFetcher - Cache CardCache + Sender Sender + Logger *log.Logger + InfoFetcher CardInfoFetcher + Cache CardCache } type UserMessage struct { @@ -25,18 +27,19 @@ type UserMessage struct { } type CardCache interface { - Get(cardName string) (string, error) - Set(cardName string, message string) + Get(cardName string) ([]cardsinfo.ScgCardPrice, error) + Set(cardName string, prices []cardsinfo.ScgCardPrice) } type CardInfoFetcher interface { - GetFormattedCardPrices(name string) (string, error) GetNameByCardId(set string, number string) string GetOriginalName(name string) string + GetPrices(name string) ([]cardsinfo.ScgCardPrice, error) } type Sender interface { Send(userId int64, message string) + SendPrices(userId int64, cardName string, prices []cardsinfo.ScgCardPrice) } func (s *Scenario) HandleSearch(msg *UserMessage) { @@ -48,29 +51,22 @@ func (s *Scenario) HandleSearch(msg *UserMessage) { s.Sender.Send(msg.UserId, cardNotFoundMessage) s.Logger.Printf("[info] Could not find card. User input: %s", msg.Body) } else { - message, err := s.getMessage(cardName) + prices, err := s.Cache.Get(cardName) + if err == nil { + s.Sender.SendPrices(msg.UserId, cardName, prices) + return + } + prices, err = s.InfoFetcher.GetPrices(cardName) if err != nil { s.Sender.Send(msg.UserId, pricesUnavailableMessage) s.Logger.Printf("[error] Could not find SCG prices. Message: %s card name: %s", err.Error(), cardName) return } - s.Sender.Send(msg.UserId, message) + s.Cache.Set(cardName, prices) + s.Sender.SendPrices(msg.UserId, cardName, prices) } } -func (s *Scenario) getMessage(cardName string) (string, error) { - val, err := s.Cache.Get(cardName) - if err != nil { - message, err := s.InfoFetcher.GetFormattedCardPrices(cardName) - if err != nil { - return "", err - } - s.Cache.Set(cardName, message) - return message, nil - } - return val, nil -} - func (s *Scenario) getCardNameByCommand(command string) (string, error) { var name string switch { diff --git a/internal/scenario/scenario_test.go b/internal/scenario/scenario_test.go index 195d3b9..4b038b7 100644 --- a/internal/scenario/scenario_test.go +++ b/internal/scenario/scenario_test.go @@ -10,8 +10,8 @@ import ( func TestScenario_HandleSearch_BadCommand(t *testing.T) { testCtx := GetTestScenarioCtx() testCtx.Scenario.HandleSearch(&UserMessage{ - Body: "!s", - UserId: 1, + Body: "!s", + UserId: 1, }) assert.Equal(t, []testMessage{ { @@ -25,8 +25,8 @@ func TestScenario_HandleSearch_BadCommand(t *testing.T) { func TestScenario_HandleSearch_GoodCommand(t *testing.T) { testCtx := GetTestScenarioCtx() testCtx.Scenario.HandleSearch(&UserMessage{ - Body: "!s grn 228", - UserId: 1, + Body: "!s grn 228", + UserId: 1, }) assert.Equal(t, []testMessage{ { @@ -39,8 +39,8 @@ func TestScenario_HandleSearch_GoodCommand(t *testing.T) { func TestScenario_HandleSearch_NotFoundCard(t *testing.T) { testCtx := GetTestScenarioCtx() testCtx.Scenario.HandleSearch(&UserMessage{ - Body: "absolutely_random_card", - UserId: 1, + Body: "absolutely_random_card", + UserId: 1, }) assert.Equal(t, []testMessage{ { @@ -54,8 +54,8 @@ func TestScenario_HandleSearch_NotFoundCard(t *testing.T) { func TestScenario_HandleSearch_BadCard(t *testing.T) { testCtx := GetTestScenarioCtx() testCtx.Scenario.HandleSearch(&UserMessage{ - Body: "bad", - UserId: 1, + Body: "bad", + UserId: 1, }) assert.Equal(t, []testMessage{ { @@ -68,8 +68,8 @@ func TestScenario_HandleSearch_BadCard(t *testing.T) { func TestScenario_HandleSearch_Uncached(t *testing.T) { testCtx := GetTestScenarioCtx() testCtx.Scenario.HandleSearch(&UserMessage{ - Body: "uncached", - UserId: 1, + Body: "uncached", + UserId: 1, }) assert.Equal(t, []testMessage{ { @@ -77,6 +77,6 @@ func TestScenario_HandleSearch_Uncached(t *testing.T) { message: "uncached", }, }, testCtx.Sender.sent) - msg, _ := testCtx.Scenario.Cache.Get("uncached") - assert.Equal(t, "uncached", msg) + _, err := testCtx.Scenario.Cache.Get("uncached") + assert.Nil(t, err) } diff --git a/internal/scenario/test_cache.go b/internal/scenario/test_cache.go index 9646096..5ddc215 100644 --- a/internal/scenario/test_cache.go +++ b/internal/scenario/test_cache.go @@ -1,19 +1,23 @@ package scenario -import "errors" +import ( + "errors" + + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" +) type testCache struct { - table map[string]string + table map[string][]cardsinfo.ScgCardPrice } -func (t *testCache) Get(cardName string) (string, error) { +func (t *testCache) Get(cardName string) ([]cardsinfo.ScgCardPrice, error) { msg, ok := t.table[cardName] if !ok { - return "", errors.New("test") + return nil, errors.New("test") } return msg, nil } -func (t *testCache) Set(cardName string, message string) { - t.table[cardName] = message +func (t *testCache) Set(cardName string, prices []cardsinfo.ScgCardPrice) { + t.table[cardName] = prices } diff --git a/internal/scenario/test_ctx.go b/internal/scenario/test_ctx.go index 95c6818..d6ff388 100644 --- a/internal/scenario/test_ctx.go +++ b/internal/scenario/test_ctx.go @@ -3,6 +3,8 @@ package scenario import ( "bytes" "log" + + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" ) type TestScenarioCtx struct { @@ -21,8 +23,14 @@ func GetTestScenarioCtx() TestScenarioCtx { Logger: log.New(buf, "", 0), InfoFetcher: &testInfoFetcher{}, Cache: &testCache{ - table: map[string]string{ - "good": "good", + table: map[string][]cardsinfo.ScgCardPrice{ + "good": { + { + Price: "1", + Edition: "alpha", + Link: "scg", + }, + }, }, }, }, diff --git a/internal/scenario/test_info_fetcher.go b/internal/scenario/test_info_fetcher.go index 0241d3f..88dcd95 100644 --- a/internal/scenario/test_info_fetcher.go +++ b/internal/scenario/test_info_fetcher.go @@ -2,15 +2,17 @@ package scenario import ( "errors" + + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" ) type testInfoFetcher struct{} -func (t *testInfoFetcher) GetFormattedCardPrices(name string) (string, error) { +func (t *testInfoFetcher) GetPrices(name string) ([]cardsinfo.ScgCardPrice, error) { if name == "good" || name == "uncached" { - return name, nil + return nil, nil } - return "", errors.New("test") + return nil, errors.New("test") } func (t *testInfoFetcher) GetNameByCardId(_ string, _ string) string { diff --git a/internal/scenario/test_sender.go b/internal/scenario/test_sender.go index 64daf7a..e4a5d8f 100644 --- a/internal/scenario/test_sender.go +++ b/internal/scenario/test_sender.go @@ -1,9 +1,18 @@ package scenario +import "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" + type testSender struct { sent []testMessage } +func (s *testSender) SendPrices(userId int64, cardName string, prices []cardsinfo.ScgCardPrice) { + s.sent = append(s.sent, testMessage{ + userId: userId, + message: cardName, + }) +} + type testMessage struct { userId int64 message string diff --git a/internal/telegram/sender.go b/internal/telegram/sender.go index e7e6bed..0f8afde 100644 --- a/internal/telegram/sender.go +++ b/internal/telegram/sender.go @@ -1,16 +1,38 @@ package telegram import ( + "fmt" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" ) type Sender struct { - API *tgbotapi.BotAPI + API *tgbotapi.BotAPI +} + +func (s *Sender) SendPrices(userId int64, cardName string, prices []cardsinfo.ScgCardPrice) { + msg := formatCardPrices(cardName, prices) + s.Send(userId, msg) } func (h *Sender) Send(userId int64, message string) { - msg := tgbotapi.NewMessage(userId, message) - msg.DisableWebPagePreview = true - h.API.Send(msg) + msg := tgbotapi.NewMessage(userId, message) + msg.DisableWebPagePreview = true + h.API.Send(msg) } +func formatCardPrices(name string, prices []cardsinfo.ScgCardPrice) string { + message := fmt.Sprintf("Оригинальное название: %v\n\n", name) + for i, v := range prices { + message += fmt.Sprintf("%v. %v", i+1, formatPrice(v)) + } + if len(prices) == 0 { + message += "Цен не найдено\n" + } + return message +} + +func formatPrice(s cardsinfo.ScgCardPrice) string { + return fmt.Sprintf("[%v](%v): %v\n", s.Edition, s.Link, s.Price) +} diff --git a/internal/telegram/sender_test.go b/internal/telegram/sender_test.go new file mode 100644 index 0000000..1fd260d --- /dev/null +++ b/internal/telegram/sender_test.go @@ -0,0 +1,25 @@ +package telegram + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" +) + +func Test_formatCardPrices(t *testing.T) { + prices := []cardsinfo.ScgCardPrice{ + { + Price: "1", + Edition: "Alpha", + Link: "scg1", + }, + { + Price: "2", + Edition: "Beta", + Link: "scg2", + }, + } + result := formatCardPrices("card", prices) + assert.Equal(t, "Оригинальное название: card\n\n1. [Alpha](scg1): 1\n2. [Beta](scg2): 2\n", result) +} diff --git a/internal/vk/format.go b/internal/vk/format.go new file mode 100644 index 0000000..c0e73be --- /dev/null +++ b/internal/vk/format.go @@ -0,0 +1,22 @@ +package vk + +import ( + "fmt" + + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" +) + +func formatCardPrices(name string, prices []cardsinfo.ScgCardPrice) string { + message := fmt.Sprintf("Оригинальное название: %v\n\n", name) + for i, v := range prices { + message += fmt.Sprintf("%v. %v", i+1, formatPrice(v)) + } + if len(prices) == 0 { + message += "Цен не найдено\n" + } + return message +} + +func formatPrice(s cardsinfo.ScgCardPrice) string { + return fmt.Sprintf("%v: %v\n%v\n", s.Edition, s.Price, s.Link) +} diff --git a/internal/vk/format_test.go b/internal/vk/format_test.go new file mode 100644 index 0000000..5a7be6d --- /dev/null +++ b/internal/vk/format_test.go @@ -0,0 +1,19 @@ +package vk + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" +) + +func TestFormatCardPrices(t *testing.T) { + formatted := formatCardPrices("card", []cardsinfo.ScgCardPrice{ + { + Price: "1.5$", + Edition: "ED", + Link: "scg.com", + }, + }) + assert.Equal(t, "Оригинальное название: card\n\n1. ED: 1.5$\nscg.com\n", formatted) +} diff --git a/internal/vk/sender.go b/internal/vk/sender.go index 27a7665..214de34 100644 --- a/internal/vk/sender.go +++ b/internal/vk/sender.go @@ -9,6 +9,8 @@ import ( "net/url" "strconv" "strings" + + "gitlab.com/flygrounder/go-mtg-vk/internal/cardsinfo" ) const sendMessageUrl = "https://api.vk.com/method/messages.send" @@ -22,6 +24,11 @@ type ApiSender struct { Logger *log.Logger } +func (s *ApiSender) SendPrices(userId int64, cardName string, prices []cardsinfo.ScgCardPrice) { + msg := formatCardPrices(cardName, prices) + s.Send(userId, msg) +} + type sendMessageResponse struct { Error errorResponse `json:"error"` }