Переглянути джерело

feat: utils for opening thumbnail & more

Sv443 1 рік тому
батько
коміт
270ad0bcb3
3 змінених файлів з 42 додано та 1 видалено
  1. 1 0
      src/tools/post-build.ts
  2. 2 1
      src/utils/dom.ts
  3. 39 0
      src/utils/misc.ts

+ 1 - 0
src/tools/post-build.ts

@@ -107,6 +107,7 @@ ${localizedDescriptions ? "\n" + localizedDescriptions : ""}\
 // @grant             GM.getResourceUrl
 // @grant             GM.setClipboard
 // @grant             GM.xmlHttpRequest
+// @grant             GM.openInTab
 // @grant             unsafeWindow
 // @noframes\
 ${resourcesDirectives ? "\n" + resourcesDirectives : ""}\

+ 2 - 1
src/utils/dom.ts

@@ -137,7 +137,8 @@ function clearNode(element: Element) {
 }
 
 /**
- * Adds generic, accessible interaction listeners to the passed element
+ * Adds generic, accessible interaction listeners to the passed element.  
+ * All listeners have the default behavior prevented and stop immediate propagation.
  * @param listenerOptions Provide a {@linkcode listenerOptions} object to configure the listeners
  */
 export function onInteraction<TElem extends HTMLElement>(elem: TElem, listener: (evt: MouseEvent | KeyboardEvent) => void, listenerOptions?: AddEventListenerOptions) {

+ 39 - 0
src/utils/misc.ts

@@ -65,6 +65,45 @@ export function arrayWithSeparators<TArray>(array: TArray[], separator = ", ", l
     return `${arr.slice(0, -1).join(separator)}${lastSeparator}${arr.at(-1)!}`;
 }
 
+/** Returns the watch ID of the current video or null if not on a video page */
+export function getWatchId() {
+  const { searchParams, pathname } = new URL(location.href);
+  return pathname.includes("/watch") ? searchParams.get("v") : null;
+}
+
+type ThumbQuality = `${"" | "hq" | "mq" | "sd" | "maxres"}default`;
+
+/** Returns the thumbnail URL for a video with the given watch ID and quality (defaults to "hqdefault") */
+export function getThumbnailUrl(watchId: string, quality?: ThumbQuality): string
+/** Returns the thumbnail URL for a video with the given watch ID and index */
+export function getThumbnailUrl(watchId: string, index: 0 | 1 | 2 | 3): string
+/** Returns the thumbnail URL for a video with either a given quality identifier or index */
+export function getThumbnailUrl(watchId: string, qualityOrIndex: ThumbQuality | 0 | 1 | 2 | 3 = "hqdefault") {
+  return `https://i.ytimg.com/vi/${watchId}/${qualityOrIndex}.jpg`;
+}
+
+/** Returns the best available thumbnail URL for a video with the given watch ID */
+export async function getBestThumbnailUrl(watchId: string) {
+  const priorityList = ["maxresdefault", "sddefault", 0];
+
+  for(const quality of priorityList) {
+    const url = getThumbnailUrl(watchId, quality as ThumbQuality);
+    let response: Response | undefined;
+    try {
+      response = await fetchAdvanced(url, { method: "HEAD", timeout: 5000 });
+    }
+    catch(e) {
+      void e;
+    }
+    if(response?.ok)
+      return url;
+  }
+}
+
+/** Copies a JSON-serializable object */
+export function reserialize<T>(data: T): T {
+  return JSON.parse(JSON.stringify(data));
+}
 
 //#SECTION resources