aboutsummaryrefslogtreecommitdiff
path: root/backend/internal/ibd/search.go
diff options
context:
space:
mode:
authorGravatar Anshul Gupta <ansg191@anshulg.com> 2024-08-05 18:55:10 -0700
committerGravatar Anshul Gupta <ansg191@anshulg.com> 2024-08-05 18:55:19 -0700
commitb96fcd1a54a46a95f98467b49a051564bc21c23c (patch)
tree93caeeb05f8d6310e241095608ea2428c749b18c /backend/internal/ibd/search.go
downloadibd-trader-b96fcd1a54a46a95f98467b49a051564bc21c23c.tar.gz
ibd-trader-b96fcd1a54a46a95f98467b49a051564bc21c23c.tar.zst
ibd-trader-b96fcd1a54a46a95f98467b49a051564bc21c23c.zip
Initial Commit
Diffstat (limited to 'backend/internal/ibd/search.go')
-rw-r--r--backend/internal/ibd/search.go103
1 files changed, 103 insertions, 0 deletions
diff --git a/backend/internal/ibd/search.go b/backend/internal/ibd/search.go
new file mode 100644
index 0000000..981bd97
--- /dev/null
+++ b/backend/internal/ibd/search.go
@@ -0,0 +1,103 @@
+package ibd
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "time"
+
+ "ibd-trader/internal/database"
+)
+
+const (
+ searchUrl = "https://ibdservices.investors.com/im/api/search"
+)
+
+var ErrSymbolNotFound = fmt.Errorf("symbol not found")
+
+func (c *Client) Search(ctx context.Context, symbol string) (database.Stock, error) {
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchUrl, nil)
+ if err != nil {
+ return database.Stock{}, err
+ }
+
+ _, cookie, err := c.getCookie(ctx, nil)
+ if err != nil {
+ return database.Stock{}, err
+ }
+ req.AddCookie(cookie)
+
+ params := url.Values{}
+ params.Set("key", symbol)
+ req.URL.RawQuery = params.Encode()
+
+ resp, err := c.Do(req)
+ if err != nil {
+ return database.Stock{}, err
+ }
+
+ if resp.Result.StatusCode != http.StatusOK {
+ return database.Stock{}, fmt.Errorf(
+ "unexpected status code %d: %s",
+ resp.Result.StatusCode,
+ resp.Result.Content,
+ )
+ }
+
+ var sr searchResponse
+ if err = json.Unmarshal([]byte(resp.Result.Content), &sr); err != nil {
+ return database.Stock{}, err
+ }
+
+ for _, stock := range sr.StockData {
+ if stock.Symbol == symbol {
+ return database.Stock{
+ Symbol: stock.Symbol,
+ Name: stock.Company,
+ IBDUrl: stock.QuoteUrl,
+ }, nil
+ }
+ }
+
+ return database.Stock{}, ErrSymbolNotFound
+}
+
+type searchResponse struct {
+ Status int `json:"_status"`
+ Timestamp string `json:"_timestamp"`
+ StockData []struct {
+ Id int `json:"id"`
+ Symbol string `json:"symbol"`
+ Company string `json:"company"`
+ PriceDate string `json:"priceDate"`
+ Price float64 `json:"price"`
+ PreviousPrice float64 `json:"previousPrice"`
+ PriceChange float64 `json:"priceChange"`
+ PricePctChange float64 `json:"pricePctChange"`
+ Volume int `json:"volume"`
+ VolumeChange int `json:"volumeChange"`
+ VolumePctChange int `json:"volumePctChange"`
+ QuoteUrl string `json:"quoteUrl"`
+ } `json:"stockData"`
+ News []struct {
+ Title string `json:"title"`
+ Category string `json:"category"`
+ Body string `json:"body"`
+ ImageAlt string `json:"imageAlt"`
+ ImageUrl string `json:"imageUrl"`
+ NewsUrl string `json:"newsUrl"`
+ CategoryUrl string `json:"categoryUrl"`
+ PublishDate time.Time `json:"publishDate"`
+ PublishDateUnixts int `json:"publishDateUnixts"`
+ Stocks []struct {
+ Id int `json:"id"`
+ Index int `json:"index"`
+ Symbol string `json:"symbol"`
+ PricePctChange string `json:"pricePctChange"`
+ } `json:"stocks"`
+ VideoFormat bool `json:"videoFormat"`
+ } `json:"news"`
+ FullUrl string `json:"fullUrl"`
+}