Browse Source

fix: auto-like feature on new yt design & smaller bug fixes

Sv443 8 months ago
parent
commit
08d8a384d3

+ 1 - 1
assets/icons/auto_like.svg

@@ -1 +1 @@
-<svg height="24" viewBox="0 -960 960 960" width="24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><path fill="#ffffff" d="m 743.11379,-210.30602 c 2.63379,0 5.04524,-1.0974 7.23436,-3.29223 2.19483,-2.18913 3.29224,-4.60059 3.29224,-7.23437 V -541.8299 c 0,-2.63379 -1.09741,-5.04524 -3.29224,-7.23437 -2.18912,-2.19482 -4.60057,-3.29223 -7.23436,-3.29223 H 216.88621 c -2.63379,0 -5.04524,1.09741 -7.23436,3.29223 -2.19483,2.18913 -3.29224,4.60058 -3.29224,7.23437 v 6.04345 82.50915 h -51.30757 v -81.3754 -7.1772 c 0,-17.27926 5.98588,-31.90476 17.95765,-43.87652 11.97177,-11.97177 26.59727,-17.95766 43.87652,-17.95766 h 526.22758 c 17.27925,0 31.90475,5.98589 43.87652,17.95766 11.97177,11.97176 17.95765,26.59726 17.95765,43.87652 v 320.99728 c 0,17.27925 -5.98588,31.90476 -17.95765,43.87653 -11.97177,11.97176 -26.59727,17.95765 -43.87652,17.95765 H 543.65226 l 21.69248,-51.30758 z M 214.91088,-651.02096 v -51.30758 h 530.17824 v 51.30758 z m 102.61514,-98.67302 v -51.30758 h 324.94796 v 51.30758 z" style="stroke-width:0.855127" /><path d="M 444.37543,-104.40272 H 212.34209 v -291.14271 l 137.86733,-138.26669 39.7058,34.32667 c 3.70421,3.2036 6.77024,7.76206 9.19809,13.67535 2.42786,5.91329 3.64179,11.82659 3.64179,17.73988 v 1.56528 l -21.33043,70.95951 h 127.46227 c 16.99496,0 32.16904,6.69593 45.52222,20.0878 13.35319,13.39186 20.02979,28.60991 20.02979,45.65411 v 9.91346 c 0,3.28014 -0.34684,6.79682 -1.04051,10.55002 -0.69367,3.74971 -1.73418,7.01593 -3.12151,9.79866 l -65.55204,156.00658 c -4.8557,11.13091 -13.09305,20.43564 -24.71206,27.91422 -11.61902,7.47857 -23.49814,11.21786 -35.6374,11.21786 z m -180.25578,-53.24191 h 183.0386 l 66.65882,-163.51639 v -21.1425 H 311.75173 l 22.94812,-91.80999 -70.5802,70.75906 z m 0,-205.70982 v 205.70982 z m -51.77756,-32.19098 v 53.24191 h -58.80262 v 184.65889 h 58.80262 v 53.24191 H 100.48746 v -291.14271 z" style="stroke-width:0.521762" /></svg>
+<svg height="24" viewBox="0 -960 960 960" width="24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><path fill="#ffffff" d="m 743.11379,-210.30602 c 2.63379,0 5.04524,-1.0974 7.23436,-3.29223 2.19483,-2.18913 3.29224,-4.60059 3.29224,-7.23437 V -541.8299 c 0,-2.63379 -1.09741,-5.04524 -3.29224,-7.23437 -2.18912,-2.19482 -4.60057,-3.29223 -7.23436,-3.29223 H 216.88621 c -2.63379,0 -5.04524,1.09741 -7.23436,3.29223 -2.19483,2.18913 -3.29224,4.60058 -3.29224,7.23437 v 6.04345 82.50915 h -51.30757 v -81.3754 -7.1772 c 0,-17.27926 5.98588,-31.90476 17.95765,-43.87652 11.97177,-11.97177 26.59727,-17.95766 43.87652,-17.95766 h 526.22758 c 17.27925,0 31.90475,5.98589 43.87652,17.95766 11.97177,11.97176 17.95765,26.59726 17.95765,43.87652 v 320.99728 c 0,17.27925 -5.98588,31.90476 -17.95765,43.87653 -11.97177,11.97176 -26.59727,17.95765 -43.87652,17.95765 H 543.65226 l 21.69248,-51.30758 z M 214.91088,-651.02096 v -51.30758 h 530.17824 v 51.30758 z m 102.61514,-98.67302 v -51.30758 h 324.94796 v 51.30758 z" style="stroke-width:0.855127" /><path fill="#ffffff" d="M 444.37543,-104.40272 H 212.34209 v -291.14271 l 137.86733,-138.26669 39.7058,34.32667 c 3.70421,3.2036 6.77024,7.76206 9.19809,13.67535 2.42786,5.91329 3.64179,11.82659 3.64179,17.73988 v 1.56528 l -21.33043,70.95951 h 127.46227 c 16.99496,0 32.16904,6.69593 45.52222,20.0878 13.35319,13.39186 20.02979,28.60991 20.02979,45.65411 v 9.91346 c 0,3.28014 -0.34684,6.79682 -1.04051,10.55002 -0.69367,3.74971 -1.73418,7.01593 -3.12151,9.79866 l -65.55204,156.00658 c -4.8557,11.13091 -13.09305,20.43564 -24.71206,27.91422 -11.61902,7.47857 -23.49814,11.21786 -35.6374,11.21786 z m -180.25578,-53.24191 h 183.0386 l 66.65882,-163.51639 v -21.1425 H 311.75173 l 22.94812,-91.80999 -70.5802,70.75906 z m 0,-205.70982 v 205.70982 z m -51.77756,-32.19098 v 53.24191 h -58.80262 v 184.65889 h 58.80262 v 53.24191 H 100.48746 v -291.14271 z" style="stroke-width:0.521762" /></svg>

+ 1 - 1
assets/icons/auto_like_enabled.svg

@@ -1 +1 @@
-<svg height="24" viewBox="0 -960 960 960" width="24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><path fill="#ffffff" d="m 743.11379,-210.30602 c 2.63379,0 5.04524,-1.0974 7.23436,-3.29223 2.19483,-2.18913 3.29224,-4.60059 3.29224,-7.23437 V -541.8299 c 0,-2.63379 -1.09741,-5.04524 -3.29224,-7.23437 -2.18912,-2.19482 -4.60057,-3.29223 -7.23436,-3.29223 H 216.88621 c -2.63379,0 -5.04524,1.09741 -7.23436,3.29223 -2.19483,2.18913 -3.29224,4.60058 -3.29224,7.23437 v 6.04345 160.54216 h -51.30757 v -159.40841 -7.1772 c 0,-17.27926 5.98588,-31.90476 17.95765,-43.87652 11.97177,-11.97177 26.59727,-17.95766 43.87652,-17.95766 h 526.22758 c 17.27925,0 31.90475,5.98589 43.87652,17.95766 11.97177,11.97176 17.95765,26.59726 17.95765,43.87652 v 320.99728 c 0,17.27925 -5.98588,31.90476 -17.95765,43.87653 -11.97177,11.97176 -26.59727,17.95765 -43.87652,17.95765 H 389.18357 v -51.30758 z M 214.91088,-651.02096 v -51.30758 h 530.17824 v 51.30758 z m 102.61514,-98.67302 v -51.30758 h 324.94796 v 51.30758 z" style="stroke-width:0.855127" /><path d="m 231.5903,-149.86765 262.37387,-261.27738 -37.20499,-37.20499 -225.16888,225.16888 -102.8928,-102.8928 -36.52517,36.53613 z" style="stroke-width:1.09648" /></svg>
+<svg height="24" viewBox="0 -960 960 960" width="24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><path fill="#ffffff" d="m 743.11379,-210.30602 c 2.63379,0 5.04524,-1.0974 7.23436,-3.29223 2.19483,-2.18913 3.29224,-4.60059 3.29224,-7.23437 V -541.8299 c 0,-2.63379 -1.09741,-5.04524 -3.29224,-7.23437 -2.18912,-2.19482 -4.60057,-3.29223 -7.23436,-3.29223 H 216.88621 c -2.63379,0 -5.04524,1.09741 -7.23436,3.29223 -2.19483,2.18913 -3.29224,4.60058 -3.29224,7.23437 v 6.04345 160.54216 h -51.30757 v -159.40841 -7.1772 c 0,-17.27926 5.98588,-31.90476 17.95765,-43.87652 11.97177,-11.97177 26.59727,-17.95766 43.87652,-17.95766 h 526.22758 c 17.27925,0 31.90475,5.98589 43.87652,17.95766 11.97177,11.97176 17.95765,26.59726 17.95765,43.87652 v 320.99728 c 0,17.27925 -5.98588,31.90476 -17.95765,43.87653 -11.97177,11.97176 -26.59727,17.95765 -43.87652,17.95765 H 389.18357 v -51.30758 z M 214.91088,-651.02096 v -51.30758 h 530.17824 v 51.30758 z m 102.61514,-98.67302 v -51.30758 h 324.94796 v 51.30758 z" style="stroke-width:0.855127" /><path fill="#ffffff" d="m 231.5903,-149.86765 262.37387,-261.27738 -37.20499,-37.20499 -225.16888,225.16888 -102.8928,-102.8928 -36.52517,36.53613 z" style="stroke-width:1.09648" /></svg>

+ 2 - 1
assets/resources.json

@@ -1,6 +1,7 @@
 {
   "css-above_queue_btns": "style/aboveQueueBtns.css",
   "css-anchor_improvements": "style/anchorImprovements.css",
+  "css-auto_like": "style/autoLike.css",
   "css-fix_hdr": "style/fixHDR.css",
   "css-fix_spacing": "style/fixSpacing.css",
   "css-show_votes": "style/showVotes.css",
@@ -34,4 +35,4 @@
   "img-logo_dev": "images/logo/logo_dev_48.png",
   "img-logo": "images/logo/logo_48.png",
   "img-openuserjs": "images/external/openuserjs.png"
-}
+}

+ 4 - 0
assets/style/autoLike.css

@@ -0,0 +1,4 @@
+tp-yt-app-header #page-header yt-flexible-actions-view-model {
+  display: flex;
+  align-items: center;
+}

+ 3 - 2
changelog.md

@@ -4,10 +4,11 @@
 <!-- #region 2.1.0 -->
 ## 2.1.0
 - **Features:**
-  - Auto-like videos and songs of channels where this feature was enabled
-    - Added an auto-like toggle button to the channel pages on YT and YTM
   - Show the amount of likes and dislikes on the currently playing song
   - Show the like and dislike ratio as a colored bar on the currently playing song
+  - Added preview auto-like feature to like songs and videos of certain channels automatically  
+    This feature is still in beta. To enable it, first enable advanced mode in the settings.  
+    The toggle button will only show up on channel pages until the next update. Please report any issues you encounter.
 - **Changes / Fixes:**
   - Now the welcome menu is shown on YT too
   - Changed default settings for these features:

+ 16 - 8
src/features/input.ts

@@ -1,5 +1,5 @@
 import { DataStore, clamp, compress, decompress } from "@sv443-network/userutils";
-import { error, getVideoTime, info, log, warn, getVideoSelector, getDomain, compressionSupported, t, clearNode, resourceAsString, getCurrentChannelId, currentMediaType, sanitizeChannelId } from "../utils/index.js";
+import { error, getVideoTime, info, log, warn, getVideoSelector, getDomain, compressionSupported, t, clearNode, resourceAsString, getCurrentChannelId, currentMediaType, sanitizeChannelId, addStyleFromResource, isValidChannelId } from "../utils/index.js";
 import type { AutoLikeData, Domain } from "../types.js";
 import { disableBeforeUnload } from "./behavior.js";
 import { emitSiteEvent, siteEvents } from "../siteEvents.js";
@@ -166,7 +166,7 @@ export const autoLikeStore = new DataStore<AutoLikeData>({
     2: (oldData: AutoLikeData) => ({
       channels: oldData.channels.map((ch) => ({
         ...ch,
-        id: ch.id.trim().match(/^(UC|@).+$/)
+        id: isValidChannelId(ch.id.trim())
           ? ch.id.trim()
           : `@${ch.id.trim()}`,
       })),
@@ -189,6 +189,8 @@ export async function initAutoLike() {
   try {
     canCompress = await compressionSupported();
     await initAutoLikeStore();
+
+    //#SECTION ytm
     if(getDomain() === "ytm") {
       let timeout: ReturnType<typeof setTimeout>;
       siteEvents.on("songTitleChanged", () => {
@@ -252,7 +254,10 @@ export async function initAutoLike() {
         }
       });
     }
+    //#SECTION yt
     else if(getDomain() === "yt") {
+      addStyleFromResource("css-auto_like");
+
       let timeout: ReturnType<typeof setTimeout>;
       siteEvents.on("watchIdChanged", () => {
         const autoLikeTimeoutMs = (getFeature("autoLikeTimeout") ?? 5) * 1000;
@@ -273,10 +278,10 @@ export async function initAutoLike() {
                   if(likeBtn.getAttribute("aria-pressed") !== "true") {
                     likeBtn.click();
                     getFeature("autoLikeShowToast") && showIconToast({
-                      message: t(`auto_liked_a_channels_${currentMediaType()}`, likeChan.name),
+                      message: t("auto_liked_a_channels_video", likeChan.name),
                       icon: "icon-auto_like",
                     });
-                    log(`Auto-liked ${currentMediaType()} from channel '${likeChan.name}' (${likeChan.id})`);
+                    log(`Auto-liked video from channel '${likeChan.name}' (${likeChan.id})`);
                   }
                 }
               });
@@ -297,15 +302,15 @@ export async function initAutoLike() {
 
           addSelectorListener<0, "yt">("ytAppHeader", "#channel-header-container, #page-header", {
             listener(headerCont) {
-              const titleCont = headerCont.querySelector<HTMLElement>("ytd-channel-name #container");
+              const titleCont = headerCont.querySelector<HTMLElement>("ytd-channel-name #container, yt-dynamic-text-view-model.page-header-view-model-wiz__page-header-title");
               if(!titleCont)
                 return;
 
-              const chanName = titleCont.querySelector<HTMLElement>("yt-formatted-string")?.textContent ?? null;
+              const chanName = titleCont.querySelector<HTMLElement>("yt-formatted-string, span.yt-core-attributed-string")?.textContent ?? null;
 
-              const buttonsCont = headerCont.querySelector<HTMLElement>("#inner-header-container #buttons");
+              const buttonsCont = headerCont.querySelector<HTMLElement>("#inner-header-container #buttons, yt-flexible-actions-view-model");
               if(buttonsCont) {
-                addSelectorListener<0, "yt">("ytAppHeader", "#channel-header-container #other-buttons, yt-subscribe-button-view-model", {
+                addSelectorListener<0, "yt">("ytAppHeader", "#channel-header-container #other-buttons, yt-flexible-actions-view-model .yt-flexible-actions-view-model-wiz__action", {
                   listener: (otherBtns) =>
                     addAutoLikeToggleBtn(otherBtns, chanId, chanName, ["left-margin"]),
                 });
@@ -325,6 +330,9 @@ export async function initAutoLike() {
   }
 }
 
+//#SECTION toggle btn
+
+/** Adds a toggle button to enable or disable auto-liking videos from a channel */
 async function addAutoLikeToggleBtn(siblingEl: HTMLElement, channelId: string, channelName: string | null, extraClasses?: string[]) {
   const chan = autoLikeStore.getData().channels.find((ch) => ch.id === channelId);
 

+ 1 - 1
src/features/songLists.ts

@@ -52,7 +52,7 @@ export async function initQueueButtons() {
       addQueueButtons(itm, ".flex-columns", "genericList", ["bytm-generic-list-queue-btn-container"], "afterParent");
     });
 
-    log(`Added buttons to ${queueItems.length} new "generic song list" ${autoPlural("item", queueItems)}`);
+    log(`Added buttons to ${queueItems.length} new "generic song list" ${autoPlural("item", queueItems)} in list`, listElem);
   };
 
   const listSelector = `\

+ 3 - 0
src/utils/dom.ts

@@ -191,9 +191,12 @@ export function clearNode(element: Element) {
 
 /**
  * Checks if the currently playing media is a song or a video.  
+ * Only works on YTM and will throw on YT!  
  * This function should only be called after awaiting {@linkcode waitVideoElementReady}!
  */
 export function currentMediaType(): "video" | "song" {
+  if(getDomain() === "yt")
+    throw new Error("currentMediaType() is only available on YTM!");
   const songImgElem = document.querySelector("ytmusic-player #song-image");
   if(!songImgElem)
     throw new Error("Couldn't find the song image element. Use this function only after `await waitVideoElementReady()`!");

+ 20 - 13
src/utils/misc.ts

@@ -7,19 +7,19 @@ import langMapping from "../../assets/locales.json" with { type: "json" };
 
 //#region misc
 
-let cachedDomain: Domain; 
+let domain: Domain; 
 
 /**
  * Returns the current domain as a constant string representation
  * @throws Throws if script runs on an unexpected website
  */
 export function getDomain(): Domain {
-  if(cachedDomain)
-    return cachedDomain;
+  if(domain)
+    return domain;
   if(location.hostname.match(/^music\.youtube/))
-    return cachedDomain = "ytm";
+    return domain = "ytm";
   else if(location.hostname.match(/youtube\./))
-    return cachedDomain = "yt";
+    return domain = "yt";
   else
     throw new Error("BetterYTM is running on an unexpected website. Please don't tamper with the @match directives in the userscript header.");
 }
@@ -88,9 +88,9 @@ export function parseChannelIdFromUrl(url: string | URL) {
   try {
     const { pathname } = url instanceof URL ? url : new URL(url);
     if(pathname.includes("/channel/"))
-      return pathname.split("/channel/")[1].split("/")[0];
+      return sanitizeChannelId(pathname.split("/channel/")[1].split("/")[0]);
     else if(pathname.includes("/@"))
-      return pathname.split("/@")[1].split("/")[0];
+      return sanitizeChannelId(pathname.split("/@")[1].split("/")[0]);
     else
       return null;
   }
@@ -99,6 +99,19 @@ export function parseChannelIdFromUrl(url: string | URL) {
   }
 }
 
+/** Sanitizes a channel ID by adding a leading `@` if the ID doesn't start with `UC...` */
+export function sanitizeChannelId(channelId: string) {
+  channelId = String(channelId).trim();
+  return isValidChannelId(channelId)
+    ? channelId
+    : `@${channelId}`;
+}
+
+/** Tests whether a string is a valid channel ID in the format `@User` or `.C...` */
+export function isValidChannelId(channelId: string) {
+  return channelId.match(/^([A-Z]C|@)\w+$/) !== null;
+}
+
 /** Quality identifier for a thumbnail - from highest to lowest res: `maxresdefault` > `sddefault` > `hqdefault` > `mqdefault` > `default` */
 type ThumbQuality = `${"maxres" | "sd" | "hq" | "mq" | ""}default`;
 
@@ -162,12 +175,6 @@ export async function tryToDecompressAndParse<TData = Record<string, unknown>>(i
   return parsed;
 }
 
-/** Sanitizes a channel ID by adding a leading `@` if the ID doesn't start with `UC...` */
-export function sanitizeChannelId(channelId: string) {
-  channelId = String(channelId);
-  return (channelId.startsWith("UC") ? channelId : `@${channelId}`).trim();
-}
-
 //#region resources
 
 /**