-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathconsult-web-youtube.el
170 lines (150 loc) · 7.95 KB
/
consult-web-youtube.el
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
;;; consult-web-youtube.el --- Consulting YouTube -*- lexical-binding: t -*-
;; Copyright (C) 2024 Armin Darvish
;; Author: Armin Darvish
;; Maintainer: Armin Darvish
;; Created: 2024
;; Version: 0.1
;; Package-Requires: ((emacs "28.1") (consult "1.1"))
;; Homepage: https://github.com/armindarvish/consult-web
;; Keywords: convenience
;;; Commentary:
;;; Code:
(require 'consult-web)
(defun consult-web-dynamic--youtube-format-candidate (table &optional face &rest args)
"Formats a candidate for `consult-web-youtube' commands.
TABLE is a hashtable with metadata for the candidate as (key value) pairs.
Returns a string (from :title field in TABLE)
with text-properties that conatin
all the key value pairs in the table.
"
(let* ((pl (consult-web-hashtable-to-plist table))
(title (format "%s" (gethash :title table)))
(url (gethash :url table))
(urlobj (if url (url-generic-parse-url url)))
(domain (if (url-p urlobj) (url-domain urlobj)))
(domain (if (stringp domain) (propertize domain 'face 'consult-web-domain-face)))
(channeltitle (gethash :channeltitle table))
(channeltitle (if (stringp channeltitle) (propertize channeltitle 'face 'consult-web-path-face)))
(source (gethash :source table))
(source (if (stringp source) (propertize source 'face 'consult-web-source-face)))
(query (gethash :query table))
(snippet (gethash :snippet table))
(snippet (if (and snippet (stringp snippet) (> (string-width snippet) 25)) (concat (substring snippet 0 22) "...") snippet))
(match-str (if (stringp query) (consult--split-escaped (car (consult--command-split query))) nil))
(title-str (consult-web--set-string-width title (floor (* (frame-width) 0.4))))
(title-str (propertize title-str 'face (or face 'consult-web-default-face)))
(extra-args (consult-web-hashtable-to-plist table '(:title :url :search-url :query :source :snippet :channeltitle :videoid)))
(str (concat title-str
(if domain (format "\t%s" domain))
(if channeltitle (format " - %s" channeltitle))
(if snippet (format "\s\s%s" snippet))
(if source (concat "\t" source))
(if extra-args (propertize (format "\s%s" extra-args) 'face 'consult-web-source-face))))
(str (apply #'propertize str pl))
)
(if consult-web-highlight-matches
(cond
((listp match-str)
(mapcar (lambda (match) (setq str (consult-web--highlight-match match str t))) match-str))
((stringp match-str)
(setq str (consult-web--highlight-match match-str str t)))))
str))
(defvar consult-web-youtube-watch-url "https://www.youtube.com/watch")
(defvar consult-web-youtube-channel-url "https://www.youtube.com/channel/")
(defvar consult-web-youtube-search-results-url "https://www.youtube.com/results")
(defvar consult-web-youtube-search-api-url "https://www.googleapis.com/youtube/v3/search")
(defcustom consult-web-youtube-search-key nil
"Key for YouTube custom search API
See URL `https://developers.google.com/youtube/v3/getting-started'
for details"
:group 'consult-web
:type '(choice (const :tag "API Key" string)
(function :tag "Custom Function")))
(cl-defun consult-web--youtube-fetch-results (input &rest args &key count page order def type vidtype &allow-other-keys)
"Fetches search results for INPUT from “Google custom search” service.
COUNT is passed as num in query parameters.
(* PAGE COUNT) is passed as start in query paramters.
"
(let* ((count (or (and (integerp count) count)
(and count (string-to-number (format "%s" count)))
consult-web-default-count))
(page (or (and (integerp page) page)
(and page (string-to-number (format "%s" page)))
consult-web-default-count))
(def (if (and def (member (format "%s" def) '("any" "standard" "high"))) (format "%s" def) "any"))
(type (if (and type (member (format "%s" type) '("channel" "playlist" "video"))) (format "%s" type) "video"))
(vidtype (if (and type (member (format "%s" vidtype) '("any" "episode" "movie"))) (format "%s" vidtype) "any"))
(count (min count 10))
(page (+ (* page count) 1))
(order (if (and type (member (format "%s" order) '("date" "rating" "relevance" "title" "videoCount" "viewCount"))) (format "%s" vidtype) "relevance"))
(params `(("q" . ,input)
("part" . "snippet")
("order" . ,order)
("type" . ,type)
("maxResults" . ,(format "%s" count))
("videoDefinition" . ,def)
("videoType" . ,vidtype)
("key" . ,(consult-web-expand-variable-function consult-web-youtube-search-key))))
(headers `(("Accept" . "application/json")
("Accept-Encoding" . "gzip")
("User-Agent" . "consult-web (gzip)")
("X-Goog-Api-Key" . ,(consult-web-expand-variable-function consult-web-youtube-search-key )))))
(funcall consult-web-retrieve-backend
consult-web-youtube-search-api-url
:params params
:headers headers
:parser
(lambda ()
(goto-char (point-min))
(let* ((results (json-parse-buffer))
(items (gethash "items" results)))
(cl-loop for a across items
collect
(let* ((table (make-hash-table :test 'equal))
(videoid (gethash "videoId" (gethash "id" a)))
(snippet (gethash "snippet" a))
(channeltitle (gethash "channelTitle" snippet))
(channelid (gethash "channelId" snippet))
(title (gethash "title" snippet))
(date (gethash "publishedAt" snippet))
(date (format-time-string "%Y-%m-%d %R" (date-to-time date)))
(url (cond
(videoid (consult-web--make-url-string consult-web-youtube-watch-url `(("v" . ,videoid))))
(channelid (concat consult-web-youtube-channel-url channelid))))
(search-url (consult-web--make-url-string consult-web-youtube-search-results-url `(("search_query" . ,input))))
(description (gethash "description" snippet)))
(puthash :url
url table)
(puthash :search-url search-url
table)
(puthash :title title
table)
(puthash :videoid videoid
table)
(puthash :channeltitle channeltitle
table)
(puthash :channelid channelid
table)
(puthash :source "YouTube"
table)
(puthash :query input
table)
(puthash :snippet description table)
table
)
))
))))
(consult-web-define-source "YouTube"
:narrow-char ?y
:face 'consult-web-engine-source-face
:request #'consult-web--youtube-fetch-results
:format #'consult-web-dynamic--youtube-format-candidate
:preview-key consult-web-preview-key
:search-history 'consult-web--search-history
:selection-history 'consult-web--selection-history
:dynamic 'both
)
;;; provide `consult-web-youtube' module
(provide 'consult-web-youtube)
(add-to-list 'consult-web-sources-modules-to-load 'consult-web-youtube)
;;; consult-web-youtube.el ends here