~nature/yt-cli

0f6eb8178fa3f1a2fc4283c0785655aec187bcf0 — LordNature 1 year, 5 months ago eef54d4
main.go: Re-factored and added features.

- Added ability to add channel to a sub file.
- Added a constant that stores the sub filename.
- Added ability to read subs from file.
- Added a getVideos() function which retrieves videos from subs.
- Added the ability to play videos through mpv.
- Added a comparison function, so we do not have to include ID in dmenu list.
- Prettified dmenu list compared to the shell version.
- Made addSub() function check for existing files and handle accordingly.
1 files changed, 113 insertions(+), 27 deletions(-)

M main.go
M main.go => main.go +113 -27
@@ 30,15 30,35 @@ list               Lists all videos from subscriptions.
help               Prints usage.
`

// implement xdg standard
const SUB_FILENAME = ".subs"

func main() {
	name := os.Args[0]
	fmt.Println(name)
	var channels []Channel

	// this will err out if no args, fix it.
	switch os.Args[1] {
	case "add":
		test, _ := readSubs()
		addChannel(test)
		if err := addSub(os.Args[2]); err != nil {
			panic(err)
		}
	case "list":
		subs, _ := readSubs()
		for _, k := range subs {
			ch, err := getVideos(k)
			if err != nil {
				panic(err)
			}
			channels = append(channels, ch)
		}
		vid, err := listVideos(channels)
		if err != nil {
			panic(err)
		}
		err = playVideo(vid)
		if err != nil {
			panic(err)
		}
	case "help":
		fallthrough
	default:


@@ 46,50 66,116 @@ func main() {
	}
}

func readSubs() (channels []string, err error) {
	// hardcoded for now
	data, err := ioutil.ReadFile("subs")
// Appends subscription to file
func addSub(id string) (err error) {
	// Check if file subscription exists
	if _, err = os.Stat(SUB_FILENAME); os.IsNotExist(err) {
		err = ioutil.WriteFile(SUB_FILENAME, nil, 0644)
		if err != nil {
			return
		}
	}

	// Open file in append mode only
	file, err := os.OpenFile(SUB_FILENAME, os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		return
	}
	defer file.Close()

	channels = strings.Split(string(data), "\n")
	// Append the new subscription
	_, err = file.WriteString(id + "\n")
	if err != nil {
		return
	}

	return
}

func addChannel(subs []string) {
	for _, k := range subs {
		fmt.Println(k)
// Reads subcriptions from file
func readSubs() (subs []string, err error) {
	data, err := ioutil.ReadFile(SUB_FILENAME)
	if err != nil {
		return
	}
	subs = strings.Split(string(data), "\n")
	return
}

	url := "https://www.youtube.com/feeds/videos.xml?channel_id=ID_HERE"
	req, _ := http.NewRequest("GET", url, nil)
	res, _ := http.DefaultClient.Do(req)
// Gets videos for subscription
func getVideos(chID string) (ch Channel, err error) {
	url := "https://www.youtube.com/feeds/videos.xml?channel_id=" + chID
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return
	}
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return
	}
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return
	}

	var channel Channel
	xml.Unmarshal(body, &channel)
	xml.Unmarshal(body, &ch)
	return
}


	var test string
	for _, v := range channel.Videos {
		fmt.Printf("[%.10s] %.20s - %.50s\n", v.Date, channel.Name, v.Title)
		test += v.ID + "\n"
func listVideos(chs []Channel) (vid string, err error) {
	var input string
	for _, c := range chs {
		for i, v := range c.Videos {
			if i > 4 {
				break
			}
			input += fmt.Sprintf("[%.10s] %.20s - %.50s\n", v.Date, c.Name, v.Title)
		}
	}
	dmenuList(test)
	vid, err = dmenuList(input)
	if err != nil {
		return
	}
	// this is trash and needs to be fixed.
	for _, c := range chs {
		for i, v := range c.Videos {
			if i > 4 {
				break
			}
			orig := fmt.Sprintf("[%.10s] %.20s - %.50s\n", v.Date, c.Name, v.Title)
			if orig == vid {
				vid = v.ID
				break
			}
		}
	}
	return
}

func dmenuList(input string) {
	cmd := exec.Command("dmenu", "-l", "10")
	stdin, _ := cmd.StdinPipe()
func dmenuList(input string) (output string, err error) {
	cmd := exec.Command("dmenu", "-l", "10",)
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return
	}
	go func() {
		defer stdin.Close()
		io.WriteString(stdin, input)
	}()

	out, _ := cmd.CombinedOutput()
	out, err := cmd.CombinedOutput()
	if err != nil {
		return
	}

	fmt.Printf("%s\n", out)
	output = string(out)
	return
}

func playVideo(id string) (err error) {
	cmd := exec.Command("mpv", "https://youtube.com/watch?v=" + id)
	err = cmd.Run()
	return
}