156 lines
3.4 KiB
Go
156 lines
3.4 KiB
Go
package main
|
||
|
||
import (
|
||
"bufio"
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"os/exec"
|
||
"strings"
|
||
|
||
"net/http"
|
||
"net/url"
|
||
)
|
||
|
||
var version = "1.0.1"
|
||
|
||
func help () {
|
||
fmt.Println("使い方")
|
||
fmt.Println("rofi-youtube -i :動画IDを使ってMPVで再生する")
|
||
fmt.Println("rofi-youtube -v :バージョンを表示")
|
||
fmt.Println("rofi-youtube -s :動画を検索して、再生する")
|
||
fmt.Println("rofi-youtube -h :ヘルプを表示")
|
||
}
|
||
|
||
type Video struct {
|
||
Type string `json:"type"`
|
||
Title string `json:"title"`
|
||
VideoID string `json:"videoId"`
|
||
Author string `json:"author"`
|
||
AuthorID string `json:"authorId"`
|
||
AuthorURL string `json:"authorUrl"`
|
||
VideoThumbnails []struct {
|
||
Quality string `json:"quality"`
|
||
URL string `json:"url"`
|
||
Width int `json:"width"`
|
||
Height int `json:"height"`
|
||
} `json:"videoThumbnails"`
|
||
Description string `json:"description"`
|
||
DescriptionHTML string `json:"descriptionHtml"`
|
||
ViewCount int `json:"viewCount"`
|
||
Published int64 `json:"published"`
|
||
PublishedText string `json:"publishedText"`
|
||
LengthSeconds int `json:"lengthSeconds"`
|
||
LiveNow bool `json:"liveNow"`
|
||
Paid bool `json:"paid"`
|
||
Premium bool `json:"premium"`
|
||
}
|
||
|
||
func id () {
|
||
vid := rofi("動画IDを入力して下さい", nil)
|
||
|
||
if vid != "" {
|
||
if strings.Contains(vid, "watch?v=") {
|
||
vid = strings.Split(vid, "=")[1]
|
||
}
|
||
url := fmt.Sprintf("https://www.youtube.com/watch?v=%s", vid)
|
||
cmd := exec.Command("mpv", url)
|
||
err := cmd.Start()
|
||
if err != nil {
|
||
log.Fatalf("失敗: %v", err)
|
||
}
|
||
}
|
||
}
|
||
|
||
func search () {
|
||
q := rofi("動画を検索して下さい", nil)
|
||
|
||
vids := fetch(q)
|
||
|
||
var tits []string
|
||
for _, v := range vids {
|
||
tits = append(tits, v.Title)
|
||
}
|
||
|
||
stit := rofi("動画を選択して下さい", tits)
|
||
|
||
var vid *Video
|
||
for _, v := range vids {
|
||
if v.Title == stit {
|
||
vid = &v
|
||
break
|
||
}
|
||
}
|
||
|
||
if vid != nil {
|
||
url := fmt.Sprintf("https://www.youtube.com/watch?v=%s", vid.VideoID)
|
||
cmd := exec.Command("mpv", url)
|
||
err := cmd.Start()
|
||
if err != nil {
|
||
log.Fatalf("失敗: %v", err)
|
||
}
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
func rofi (prompt string, options []string) string {
|
||
cmd := exec.Command("rofi", "-dmenu", "-p", prompt)
|
||
|
||
var out bytes.Buffer
|
||
cmd.Stdout = &out
|
||
|
||
if options != nil {
|
||
cmd.Stdin = strings.NewReader(strings.Join(options, "\n"))
|
||
}
|
||
|
||
err := cmd.Run()
|
||
if err != nil {
|
||
log.Fatalf("rofiを実行に失敗: %v", err)
|
||
}
|
||
|
||
return strings.TrimSpace(out.String())
|
||
}
|
||
|
||
func fetch (q string) []Video {
|
||
url := fmt.Sprintf("https://youtube.owacon.moe/api/v1/search?q=%s&page=1&type=video®ion=JP", url.QueryEscape(q))
|
||
|
||
resp, err := http.Get(url)
|
||
if err != nil {
|
||
log.Fatalf("検索に失敗: %v", err)
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
var vres []Video
|
||
dec := json.NewDecoder(bufio.NewReader(resp.Body))
|
||
err = dec.Decode(&vres)
|
||
if err != nil {
|
||
log.Fatalf("デコードに失敗: %v", err)
|
||
}
|
||
|
||
return vres
|
||
}
|
||
|
||
func main () {
|
||
args := os.Args
|
||
if len(args) == 2 {
|
||
if args[1] == "-i" {
|
||
id()
|
||
return
|
||
} else if args[1] == "-v" {
|
||
fmt.Println("rofi-youtube-" + version)
|
||
return
|
||
} else if args[1] == "-s" {
|
||
search()
|
||
return
|
||
} else if args[1] == "-h" {
|
||
help()
|
||
return
|
||
}
|
||
}
|
||
|
||
help()
|
||
return
|
||
}
|