157 行
3.4 KiB
Go
157 行
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.0"
|
|||
|
|
|||
|
func help () {
|
|||
|
fmt.Println("使い方")
|
|||
|
fmt.Println("wofi-youtube -i :動画IDを使ってMPVで再生する")
|
|||
|
fmt.Println("wofi-youtube -v :バージョンを表示")
|
|||
|
fmt.Println("wofi-youtube -s :動画を検索して、再生する")
|
|||
|
fmt.Println("wofi-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 := wofi("動画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 := wofi("動画を検索して下さい", nil)
|
|||
|
|
|||
|
vids := fetch(q)
|
|||
|
|
|||
|
var tits []string
|
|||
|
for _, v := range vids {
|
|||
|
tits = append(tits, v.Title)
|
|||
|
}
|
|||
|
|
|||
|
stit := wofi("動画を選択して下さい", 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 wofi (prompt string, options []string) string {
|
|||
|
cmd := exec.Command("wofi", "--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("wofiを実行に失敗: %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("wofi-youtube-" + version)
|
|||
|
return
|
|||
|
} else if args[1] == "-s" {
|
|||
|
search()
|
|||
|
return
|
|||
|
} else if args[1] == "-h" {
|
|||
|
help()
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
help()
|
|||
|
return
|
|||
|
}
|