package ibd import ( "context" "encoding/json" "fmt" "io" "net/http" "net/url" "time" "github.com/ansg191/ibd-trader/backend/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 } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) if resp.StatusCode != http.StatusOK { content, err := io.ReadAll(resp.Body) if err != nil { return database.Stock{}, fmt.Errorf("failed to read response body: %w", err) } return database.Stock{}, fmt.Errorf( "unexpected status code %d: %s", resp.StatusCode, string(content), ) } var sr searchResponse if err = json.NewDecoder(resp.Body).Decode(&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"` }