From 8587bdf360de90bccdd1a2e03bea672822a831d9 Mon Sep 17 00:00:00 2001 From: Hazel Noack Date: Wed, 8 Oct 2025 10:27:16 +0200 Subject: [PATCH] shell setup --- go.mod | 2 + go.sum | 2 + internal/cli/shell.go | 47 +++++++++ internal/common/user_input.go | 27 +++++ internal/scraper/session.go | 181 ++++++++++++++++++++++++++++++++++ main.go | 32 +----- 6 files changed, 262 insertions(+), 29 deletions(-) create mode 100644 go.sum create mode 100644 internal/cli/shell.go create mode 100644 internal/scraper/session.go diff --git a/go.mod b/go.mod index ae32033..c9c1222 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module gitea.elara.ws/Hazel/music-kraken go 1.24.2 + +require golang.org/x/net v0.45.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7b7b26c --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= diff --git a/internal/cli/shell.go b/internal/cli/shell.go new file mode 100644 index 0000000..f3e1fe9 --- /dev/null +++ b/internal/cli/shell.go @@ -0,0 +1,47 @@ +package cli + +import ( + "bufio" + "fmt" + "log" + "os" + + "gitea.elara.ws/Hazel/music-kraken/internal/data" + "gitea.elara.ws/Hazel/music-kraken/internal/plugin" +) + +func printResults(musicObjects []data.MusicObject) { + for _, m := range musicObjects { + if a, ok := m.(data.Artist); ok { + fmt.Println("artist: " + a.Name) + } else if a, ok := m.(data.Album); ok { + fmt.Println("release: " + a.Name) + } else if a, ok := m.(data.Song); ok { + fmt.Println("track: " + a.Name) + } + } +} + +func Shell() { + plugin.RegisterPlugin(plugin.Musify{}) + + for { + fmt.Print("> ") + + reader := bufio.NewReader(os.Stdin) + line, err := reader.ReadString('\n') + if err != nil { + log.Fatal(err) + return + } + + searchResults, err := plugin.Search(line, plugin.SearchConfig{IgnoreErrors: false}) + if err != nil { + fmt.Println(err) + fmt.Println() + } + + fmt.Println() + printResults(searchResults) + } +} diff --git a/internal/common/user_input.go b/internal/common/user_input.go index a8e41c2..75c484f 100644 --- a/internal/common/user_input.go +++ b/internal/common/user_input.go @@ -1,7 +1,11 @@ package common import ( + "bufio" "errors" + "fmt" + "log" + "os" "strings" ) @@ -116,3 +120,26 @@ func NewQuery(search string) (Query, error) { return query, nil } + +func TestQueryParsing() { + for { + fmt.Print("> ") + + reader := bufio.NewReader(os.Stdin) + line, err := reader.ReadString('\n') + if err != nil { + log.Fatal(err) + return + } + + query, err := NewQuery(line) + if err != nil { + fmt.Println(err) + } + fmt.Println("search: '" + query.Search + "'") + fmt.Println("artist: '" + query.Artist + "'") + fmt.Println("album: '" + query.Album + "'") + fmt.Println("song: '" + query.Song + "'") + fmt.Println() + } +} diff --git a/internal/scraper/session.go b/internal/scraper/session.go new file mode 100644 index 0000000..b17d5a5 --- /dev/null +++ b/internal/scraper/session.go @@ -0,0 +1,181 @@ +package scraper + +import ( + "bytes" + "encoding/json" + "log" + "net/http" + "net/http/cookiejar" + "net/url" + "time" + + "golang.org/x/net/publicsuffix" +) + +// Session represents a persistent HTTP session +type Session struct { + client *http.Client + headers map[string]string + baseURL string + UserAgent string +} + +// NewSession creates a new session with browser-like headers +func NewSession() *Session { + // Create cookie jar first + jar, err := cookiejar.New(&cookiejar.Options{ + PublicSuffixList: publicsuffix.List, + }) + if err != nil { + log.Fatal(err) + } + + return &Session{ + client: &http.Client{ + Timeout: 30 * time.Second, + Jar: jar, // Set the cookie jar + }, + headers: map[string]string{ + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Language": "en-US,en;q=0.5", + "Accept-Encoding": "gzip, deflate, br", + "Connection": "keep-alive", + "Upgrade-Insecure-Requests": "1", + }, + UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", + } +} + +// SetHeader sets a header for all subsequent requests +func (s *Session) SetHeader(key, value string) { + s.headers[key] = value +} + +// SetHeaders sets multiple headers at once +func (s *Session) SetHeaders(headers map[string]string) { + for key, value := range headers { + s.headers[key] = value + } +} + +// SetBaseURL sets the base URL for relative paths +func (s *Session) SetBaseURL(baseURL string) { + s.baseURL = baseURL +} + +// Get performs a GET request +func (s *Session) Get(url string, headers ...map[string]string) (*http.Response, error) { + // Use base URL if set and url is relative + fullURL := s.buildURL(url) + + req, err := http.NewRequest("GET", fullURL, nil) + if err != nil { + return nil, err + } + + s.setDefaultHeaders(req) + + // Add any additional headers provided + if len(headers) > 0 { + for key, value := range headers[0] { + req.Header.Set(key, value) + } + } + + return s.client.Do(req) +} + +// Post performs a POST request with form data +func (s *Session) Post(url string, data map[string]string, headers ...map[string]string) (*http.Response, error) { + fullURL := s.buildURL(url) + + // This is the corrected line - url.Values is from net/url package + formData := make(url.Values) + for key, value := range data { + formData.Add(key, value) + } + + req, err := http.NewRequest("POST", fullURL, bytes.NewBufferString(formData.Encode())) + if err != nil { + return nil, err + } + + s.setDefaultHeaders(req) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + // Add any additional headers provided + if len(headers) > 0 { + for key, value := range headers[0] { + req.Header.Set(key, value) + } + } + + return s.client.Do(req) +} + +// PostJSON performs a POST request with JSON data +func (s *Session) PostJSON(url string, data interface{}, headers ...map[string]string) (*http.Response, error) { + fullURL := s.buildURL(url) + + jsonData, err := json.Marshal(data) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", fullURL, bytes.NewBuffer(jsonData)) + if err != nil { + return nil, err + } + + s.setDefaultHeaders(req) + req.Header.Set("Content-Type", "application/json") + + // Add any additional headers provided + if len(headers) > 0 { + for key, value := range headers[0] { + req.Header.Set(key, value) + } + } + + return s.client.Do(req) +} + +// buildURL constructs the full URL using baseURL if set +func (s *Session) buildURL(path string) string { + if s.baseURL != "" && !isAbsoluteURL(path) { + return s.baseURL + path + } + return path +} + +// isAbsoluteURL checks if the URL is absolute +func isAbsoluteURL(urlStr string) bool { + u, err := url.Parse(urlStr) + return err == nil && u.Scheme != "" && u.Host != "" +} + +// setDefaultHeaders sets the default browser-like headers +func (s *Session) setDefaultHeaders(req *http.Request) { + for key, value := range s.headers { + req.Header.Set(key, value) + } +} + +// GetCookies returns cookies for a given URL +func (s *Session) GetCookies(urlStr string) []*http.Cookie { + u, err := url.Parse(urlStr) + if err != nil { + return nil + } + return s.client.Jar.Cookies(u) +} + +// SetCookies sets cookies for a given URL +func (s *Session) SetCookies(urlStr string, cookies []*http.Cookie) { + u, err := url.Parse(urlStr) + if err != nil { + return + } + s.client.Jar.SetCookies(u, cookies) +} diff --git a/main.go b/main.go index 4b777cf..8f74df4 100644 --- a/main.go +++ b/main.go @@ -1,39 +1,13 @@ package main import ( - "bufio" "fmt" - "log" - "os" - "gitea.elara.ws/Hazel/music-kraken/internal/common" + "gitea.elara.ws/Hazel/music-kraken/internal/cli" ) -func testQuery() { - for { - fmt.Print("> ") - - reader := bufio.NewReader(os.Stdin) - line, err := reader.ReadString('\n') - if err != nil { - log.Fatal(err) - return - } - - query, err := common.NewQuery(line) - if err != nil { - fmt.Println(err) - } - fmt.Println("search: '" + query.Search + "'") - fmt.Println("artist: '" + query.Artist + "'") - fmt.Println("album: '" + query.Album + "'") - fmt.Println("song: '" + query.Song + "'") - fmt.Println() - } -} - func main() { - fmt.Println("music kraken") + fmt.Println("welcome to music kraken") - testQuery() + cli.Shell() }