package command import ( "context" "fmt" "net/url" "os" "strings" "github.com/StevanFreeborn/gator/internal/database" "github.com/StevanFreeborn/gator/internal/state" "golang.org/x/term" ) func normalizeFeedURL(raw string) (string, error) { u, err := url.Parse(raw) if err != nil { return "", err } u.Scheme = strings.ToLower(u.Scheme) u.Host = strings.ToLower(u.Host) if (u.Scheme == "http" && u.Port() == "80") || (u.Scheme == "https" && u.Port() == "443") { u.Host = u.Hostname() } if len(u.Path) > 1 { u.Path = strings.TrimSuffix(u.Path, "/") } u.Fragment = "" return u.String(), nil } func resolveFeedByNameOrURL(s *state.State, identifier string) (database.Feed, error) { if strings.TrimSpace(identifier) == "" { return database.Feed{}, fmt.Errorf("Feed identifier cannot be empty") } feeds, err := s.Database.GetAllFeeds(context.Background()) if err != nil { return database.Feed{}, fmt.Errorf("Failed to load feeds") } var matches []database.Feed for _, feed := range feeds { if strings.EqualFold(feed.Name, identifier) { matches = append(matches, feed) } } if len(matches) == 1 { return matches[0], nil } if len(matches) > 1 { return database.Feed{}, fmt.Errorf("Multiple feeds match name '%s'; use a url instead", identifier) } normalizedURL, err := normalizeFeedURL(identifier) if err != nil { return database.Feed{}, fmt.Errorf("No feed found matching name or url '%s'", identifier) } feed, err := s.Database.GetFeedByUrl(context.Background(), normalizedURL) if err != nil { return database.Feed{}, fmt.Errorf("No feed found matching name or url '%s'", identifier) } return feed, nil } func enableKeypressExit(cancel context.CancelFunc) (func(), error) { oldState, err := term.MakeRaw(int(os.Stdin.Fd())) if err != nil { return nil, fmt.Errorf("Failed to enable raw mode: %v", err) } go func() { buf := make([]byte, 1) for { n, err := os.Stdin.Read(buf) if err != nil || n == 0 { return } if buf[0] == 'q' || buf[0] == 'Q' || buf[0] == 3 { cancel() return } } }() return func() { term.Restore(int(os.Stdin.Fd()), oldState) }, nil }