package main import ( "errors" "fmt" "io" "net/http" "os" "sort" "strings" "time" ) func appendToFile(filename, data string) error { f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) if err != nil { return err } f.WriteString(data) f.Close() return nil } func prependToFile(filename, data string) error { ogData, err := os.ReadFile(filename) if err != nil { return err } fileData := string(ogData[:]) f, err := os.Create(filename) if err != nil { return err } f.WriteString(data + fileData) f.Close() return nil } func Post(twt, feedFile string, ascend bool) error { fileInfo, err := os.Stat(feedFile) if err != nil { os.Create(feedFile) } else if fileInfo.IsDir() { return errors.New("Feed file is a directory") } if ascend { return appendToFile(feedFile, time.Now().Format(time.RFC3339)+"\t"+twt+"\n") } return prependToFile(feedFile, time.Now().Format(time.RFC3339)+"\t"+twt+"\n") } func buildFeedFromUrl(feed *Feed, nick, url string) error { resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return err } return buildFeed(feed, nick, string(body[:])) } func buildFeedFromPath(feed *Feed, nick, filename string) error { f, err := os.ReadFile(filename) if err != nil { return err } return buildFeed(feed, nick, string(f[:])) } func buildFeed(feed *Feed, nick, data string) error { lines := strings.Split(data, "\n") for _, l := range lines { parts := strings.Split(l, "\t") t, err := time.Parse(time.RFC3339, parts[0]) if err != nil { continue } *feed = append(*feed, FeedEntry{ Nick: nick, Timestamp: t, Post: parts[1], }) } return nil } func printFeed(feed *Feed, max int64) { sort.Sort(*feed) for i, entry := range *feed { if int64(i) >= max { return } fmt.Printf("[%s] <%s> %s\n", entry.Timestamp.Format(time.Stamp), entry.Nick, entry.Post) } } func GetFeed(friend, friendsFile string, max int64) error { feed := &Feed{} f, err := os.ReadFile(friendsFile) if err != nil { return err } fileData := string(f[:]) lines := strings.Split(fileData, "\n") for _, l := range lines { if len(l) == 0 { continue } if !strings.Contains(l, " ") { return errors.New("Malformed friends file not in the format 'FRIEND_NAME https://friend.site/path/to/feed.txt'") } kvp := strings.Split(l, " ") k := kvp[0] v := kvp[1] if k == friend || len(friend) == 0 { err = buildFeedFromUrl(feed, k, v) if err != nil { return err } if len(friend) > 0 { break } } } printFeed(feed, max) return nil } func GetOwnFeed(nick, feedFile string, max int64) error { feed := &Feed{} err := buildFeedFromPath(feed, nick, feedFile) if err != nil { return err } printFeed(feed, max) return nil }