summaryrefslogtreecommitdiff
path: root/src/gizmo/wasp-youtube.el
blob: 1a8f558694864ef142b74d251953fa450100a2a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
;;; wasp-youtube --- YouTube integration -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:

(require 's)
(require 'dash)
(require 'ht)
(require 'wasp-utils)
(require 'selector)

(defcustom w/youtube-mpv-process "wasp-mpv-search"
  "Name of process running MPV player for YouTube videos."
  :type '(string)
  :group 'wasp)

(defcustom w/youtube-search-process "wasp-youtube-search"
  "Name of process running YouTube search."
  :type '(string)
  :group 'wasp)

(defcustom w/youtube-search-buffer " *wasp-youtube-search*"
  "Name of buffer used to store YouTube search results."
  :type '(string)
  :group 'wasp)

(defun w/youtube-search (query k)
  "Search YouTube for QUERY and pass the resulting list of title-URL pairs to K."
  (let ((buf (generate-new-buffer w/youtube-search-buffer)))
    (make-process
     :name w/youtube-search-process
     :buffer buf
     :command
     (list
      "yt-dlp" "--dump-json" (format "ytsearch20:%s" query)
      "--skip-download" "--no-playlist" "--default-search" "ytsearch"
      "--no-check-certificate" "--geo-bypass" "--flat-playlist"
      "--quiet" "--ignore-errors")
     :sentinel
     (lambda (_ _)
       (with-current-buffer buf
         (funcall
          k
          (->>
           (buffer-string)
           (s-lines)
           (-map #'s-trim)
           (-filter #'s-present?)
           (-map #'json-parse-string)
           (--map (cons (ht-get it "title") (ht-get it "url"))))))))))

(defun w/youtube-play (url)
  "Play the YouTube video at URL."
  (message (format "Opening video at %s" url))
  (make-process
   :name w/youtube-mpv-process
   :command (list "mpv" "--force-window=yes" url)))

(defun w/youtube ()
  "Interactively search for and play a YouTube video."
  (interactive)
  (let ((query (read-string "YouTube: ")))
    (w/youtube-search
     query
     (lambda (results)
       (selector
        (list
         (selector-source-create
          (format "YouTube search: %s" query)
          :candidates
          (--map (selector-candidate-create (car it) :value (cdr it)) results)
          :actions
          '(w/youtube-play))))))))

(provide 'wasp-youtube)
;;; wasp-youtube.el ends here