{"id":1115,"date":"2025-12-15T15:15:29","date_gmt":"2025-12-15T20:15:29","guid":{"rendered":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/?p=1115"},"modified":"2025-12-16T22:18:47","modified_gmt":"2025-12-17T03:18:47","slug":"automation-on-a-logged-in-account","status":"publish","type":"post","link":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/automation-on-a-logged-in-account\/","title":{"rendered":"Automation on a logged-in account."},"content":{"rendered":"<body>\n<p> Human-assisted YouTube engagement \u2014 fast, safe, and in your control Engage smarter on YouTube. <strong>YouTube Assist<\/strong> helps you scan channels, queue videos, find relevant comments by keyword or tag, and insert replies using templates \u2014 all in safe assist mode. No auto-posting, no bots, just faster human engagement.<\/p>\n\n\n\n<p> <strong>I had a question for A.I. and lead me to building a tool. You can purchase it for 9.99, or build it yourself by following this post instructions. <\/strong><\/p>\n\n\n\n<h5 class=\"wp-block-heading\">If I am logged into youtube accout, why cant I put a link like https:\/\/www.youtube.com\/@cracked and jave a browser extension, or webpage scan the page , click each link and add comment that auto filled in a panel , semi automated in a sense<\/h5>\n\n\n\n<p>Because once you try to \u201cscan a channel page \u2192 open each video \u2192 post a prefilled comment,\u201d you\u2019re no longer doing normal browsing \u2014 you\u2019re doing <strong>automation on a logged-in account<\/strong>, and YouTube (and browsers) put a lot of friction in the way on purpose.<\/p>\n\n\n\n<p>Here are the big blockers:<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">1) YouTube actively detects and throttles automated commenting<\/h5>\n\n\n\n<p>Even if you\u2019re logged in, bulk\/comment automation looks like spam behavior. YouTube has anti-abuse systems that may:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>require extra verification (captcha \/ \u201care you a bot?\u201d)<\/li>\n\n\n\n<li>shadow-hide comments<\/li>\n\n\n\n<li>rate limit or temporarily block commenting<\/li>\n\n\n\n<li>flag the account for spam-like activity<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">2) A normal webpage cannot \u201cclick around\u201d other pages while logged in<\/h5>\n\n\n\n<p>A regular website you visit <strong>cannot<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>read the DOM of <code>youtube.com<\/code> pages (cross-origin security)<\/li>\n\n\n\n<li>access your logged-in YouTube session cookies<\/li>\n\n\n\n<li>click buttons on other sites<\/li>\n<\/ul>\n\n\n\n<p>That\u2019s by design: otherwise any random site could hijack your logged-in accounts.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">3) A browser extension <em>can<\/em> interact with YouTube \u2014 but it has strict constraints<\/h5>\n\n\n\n<p>Extensions can inject scripts into pages you\u2019re visiting, but:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>it usually only works <strong>on the active tab<\/strong> (unless you build background scripting + tab control)<\/li>\n\n\n\n<li>YouTube uses a dynamic app shell (SPA), so scraping\/element selectors break often<\/li>\n\n\n\n<li>extension stores still reject \u201cspammy automation\u201d behavior, and YouTube can still detect it<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">4) \u201cAuto-commenting\u201d often violates platform rules<\/h5>\n\n\n\n<p>Even \u201csemi automated\u201d can cross the line if it\u2019s doing repetitive posting at scale. If it\u2019s mass engagement, it\u2019s risky.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">Safer ways to get most of what you want (without tripping alarms)<\/h5>\n\n\n\n<h5 class=\"wp-block-heading\">Option A: \u201cAssist mode\u201d (recommended)<\/h5>\n\n\n\n<p>Build an extension that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>collects video links from a channel page<\/li>\n\n\n\n<li>shows them in a side panel<\/li>\n\n\n\n<li>lets you click <strong>Open next video<\/strong><\/li>\n\n\n\n<li>pre-fills a comment box template <strong>for you to submit manually<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This keeps you in control, looks like normal user behavior, and is far less likely to trigger spam systems.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Option B: Use the official YouTube Data API (best for compliance)<\/h4>\n\n\n\n<p>If you own the channel \/ have API access:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>you can fetch uploads via API<\/li>\n\n\n\n<li>you can manage comments via API <strong>within allowed quotas<\/strong><\/li>\n\n\n\n<li>you\u2019ll use OAuth, not cookie hacking<\/li>\n<\/ul>\n\n\n\n<p>But even with the API, mass commenting can still be considered spam depending on behavior.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Option C: Template + clipboard workflow<\/h4>\n\n\n\n<p>Fast and simple:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>extension shows a \u201cCopy comment\u201d button with variable placeholders<\/li>\n\n\n\n<li>you paste + submit manually<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<p>If you tell me which you mean:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Commenting on your own videos<\/strong> (like pinning a standard message), or<\/li>\n\n\n\n<li><strong>Commenting on someone else\u2019s channel\/videos for marketing<\/strong>,<\/li>\n<\/ol>\n\n\n\n<p>\u2026I\u2019ll point you to the safest architecture for that goal (assist-mode vs API), and I can draft a clean extension UI plan (panel, queue, \u201cnext link\u201d, comment templates, delay timers, duplicate detection).<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">option A and Commenting on someone else\u2019s channel\/videos for marketing,<\/h5>\n\n\n\n<p>Got it \u2014 <strong>Option A \u201cassist mode\u201d<\/strong> is the right lane for this, because it can speed you up <strong>without<\/strong> turning into \u201cbot commenting\u201d (which is where accounts get throttled\/flagged).<\/p>\n\n\n\n<p>Here\u2019s a clean, practical way to build it so it\u2019s useful for marketing but still \u201chuman-in-the-loop\u201d:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">What the extension should do (and NOT do)<\/h4>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Do<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Extract video links from a channel\u2019s pages (Videos tab, Shorts tab).<\/li>\n\n\n\n<li>Build a \u201cqueue\u201d in a side panel (with title + thumbnail + timestamp).<\/li>\n\n\n\n<li>Let you pick a <strong>comment template<\/strong> and auto-generate a comment (with variables).<\/li>\n\n\n\n<li>Add a <strong>one-click paste<\/strong> into the YouTube comment box.<\/li>\n\n\n\n<li>Track what you already processed (skip duplicates).<\/li>\n\n\n\n<li>Add \u201ccooldown reminders\u201d so you don\u2019t rapid-fire.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">\u274c Don\u2019t<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Auto-submit comments.<\/li>\n\n\n\n<li>Post the same comment repeatedly across many videos.<\/li>\n\n\n\n<li>Try to bypass rate limits, captchas, or moderation.<\/li>\n\n\n\n<li>Run in the background commenting on tabs you aren\u2019t actively viewing.<\/li>\n<\/ul>\n\n\n\n<p>That\u2019s the difference between \u201cassistant tool\u201d and \u201cspam bot.\u201d<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">The workflow you want (fast + safe)<\/h5>\n\n\n\n<ol class=\"wp-block-list\">\n<li>You open <code>youtube.com\/@cracked\/videos<\/code><\/li>\n\n\n\n<li>You click <strong>\u201cScan Page\u201d<\/strong> in the extension side panel<\/li>\n\n\n\n<li>The panel shows a queue: 50\/100 video links found<\/li>\n\n\n\n<li>You click <strong>Open Next<\/strong><\/li>\n\n\n\n<li>On the video page, the panel shows:\n<ul class=\"wp-block-list\">\n<li>video title \/ channel name<\/li>\n\n\n\n<li>comment template dropdown<\/li>\n\n\n\n<li>generated comment box (editable)<\/li>\n\n\n\n<li>buttons: <strong>Insert<\/strong>, <strong>Copy<\/strong>, <strong>Mark Done<\/strong>, <strong>Skip<\/strong><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>You press <strong>Insert<\/strong>, it fills the comment field<\/li>\n\n\n\n<li>You manually hit <strong>Comment<\/strong> (you\u2019re the one submitting)<\/li>\n<\/ol>\n\n\n\n<p>This stays \u201cnormal user behavior,\u201d but still saves you tons of time.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">Comment templates that won\u2019t get you flagged<\/h5>\n\n\n\n<p>If you do marketing, the #1 anti-spam strategy is <strong>variation + relevance<\/strong>.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Template idea (variable + personalized)<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Pull from the page:\n<ul class=\"wp-block-list\">\n<li>video title<\/li>\n\n\n\n<li>first 1\u20132 hashtags (if visible)<\/li>\n\n\n\n<li>channel name<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Example generator:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u201cThat part about <strong>{keyword from title}<\/strong> was wild \u2014 especially at <strong>{timestamp}<\/strong>. Quick question: <strong>{question}<\/strong>\u201d<\/li>\n<\/ul>\n\n\n\n<p>Then your templates include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>a question<\/li>\n\n\n\n<li>a genuine observation<\/li>\n\n\n\n<li><em>optional<\/em> soft mention of your thing <strong>without links<\/strong>, or very occasional link<\/li>\n<\/ul>\n\n\n\n<p>Hard truth: <strong>dropping links in every comment<\/strong> is a fast way to get shadowed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">Extension architecture (simple &amp; reliable)<\/h5>\n\n\n\n<h5 class=\"wp-block-heading\">Manifest (MV3)<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>permissions<\/code>: <code>storage<\/code>, <code>tabs<\/code>, <code>scripting<\/code>, <code>activeTab<\/code><\/li>\n\n\n\n<li><code>host_permissions<\/code>: <code>https:\/\/www.youtube.com\/*<\/code><\/li>\n\n\n\n<li><code>content_scripts<\/code>: runs on YouTube pages to:\n<ul class=\"wp-block-list\">\n<li>scrape links on channel pages<\/li>\n\n\n\n<li>insert comments on watch pages<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><code>sidePanel<\/code> (Chrome) or <code>popup<\/code> fallback:\n<ul class=\"wp-block-list\">\n<li>Side panel is ideal for this use-case<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Content script responsibilities<\/h5>\n\n\n\n<p><strong>On channel pages<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>detect video grid items<\/li>\n\n\n\n<li>extract URLs (<code>\/watch?v=...<\/code> and <code>\/shorts\/...<\/code>)<\/li>\n\n\n\n<li>collect titles if available<\/li>\n\n\n\n<li>send results to background\/service worker<\/li>\n<\/ul>\n\n\n\n<p><strong>On watch pages<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>find the comment box reliably<\/li>\n\n\n\n<li>wait for YouTube to render it (SPA)<\/li>\n\n\n\n<li>insert text safely (dispatch input events)<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Storage<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>chrome.storage.local<\/code>:\n<ul class=\"wp-block-list\">\n<li>queue list<\/li>\n\n\n\n<li>\u201cdone\u201d set keyed by videoId<\/li>\n\n\n\n<li>template library<\/li>\n\n\n\n<li>per-channel notes<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">Anti-break tactics (YouTube changes a lot)<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Don\u2019t rely on one brittle selector.<\/li>\n\n\n\n<li>Use a \u201cwaitForElement\u201d helper with retries + MutationObserver.<\/li>\n\n\n\n<li>Detect SPA navigation (<code>yt-navigate-finish<\/code> event) and re-run logic.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">Guardrails that protect your account<\/h5>\n\n\n\n<p>Add these features into the panel:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cooldown timer<\/strong> (like \u201cWait 45\u201390s before next comment\u201d)<\/li>\n\n\n\n<li><strong>Duplicate detector<\/strong> (warn if comment is too similar to last 10)<\/li>\n\n\n\n<li><strong>Daily cap counter<\/strong> (\u201cYou did 18 today\u201d)<\/li>\n\n\n\n<li><strong>Link usage limiter<\/strong> (e.g., \u201conly allow link every 10 comments\u201d)<\/li>\n<\/ul>\n\n\n\n<p>These aren\u2019t just \u201cnice.\u201d They\u2019re what keeps you from getting cooked.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">If you want, I can generate the actual code (MV3 + side panel)<\/h5>\n\n\n\n<p>I can write you a working starter extension with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Side panel UI (queue + templates + notes)<\/li>\n\n\n\n<li>Scan channel page \u2192 build queue<\/li>\n\n\n\n<li>Open next video button<\/li>\n\n\n\n<li>Insert comment button (fills comment field, doesn\u2019t submit)<\/li>\n\n\n\n<li>Storage for done\/skip\/templates<\/li>\n<\/ul>\n\n\n\n<p>Just tell me: <strong>Chrome only<\/strong>, or <strong>Chrome + Edge<\/strong> (same code basically).<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">can i target a replay from a certain tag i may see , add that option, because I normally scan the comments and reply to certain tags, often the same comment may need to go to three people they made similar comments<\/h5>\n\n\n\n<p>Yes \u2014 in <strong>assist mode<\/strong> you can absolutely add a \u201ctargeted reply\u201d feature where the panel helps you <strong>find comments matching certain tags\/keywords<\/strong> and then lets you <strong>reply to selected people<\/strong> (with the same reply or slightly varied replies), while you still click <strong>Reply\/Submit<\/strong> yourself.<\/p>\n\n\n\n<p>Here\u2019s how I\u2019d design it.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Feature: Target replies by tag\/keyword<\/h5>\n\n\n\n<h5 class=\"wp-block-heading\">What \u201ctag\u201d can mean (and how to target it)<\/h5>\n\n\n\n<p>On YouTube comments, the most common \u201ctags\u201d you\u2019ll want to target are:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Mentions<\/strong>: <code>@username<\/code> (people tagging others, or you tagging them)<\/li>\n\n\n\n<li><strong>Keywords\/phrases<\/strong>: \u201cwhere can I\u2026\u201d, \u201clink?\u201d, \u201cwhat mic?\u201d, \u201chow do you\u2026\u201d<\/li>\n\n\n\n<li><strong>Hashtags<\/strong>: <code>#something<\/code> (less common in comments but possible)<\/li>\n\n\n\n<li><strong>Sentiment \/ intent<\/strong> (simple heuristics): question marks, \u201canyone know\u201d, \u201chelp\u201d, \u201cwhat is\u201d, etc.<\/li>\n<\/ol>\n\n\n\n<h5 class=\"wp-block-heading\">Panel controls (Reply Finder)<\/h5>\n\n\n\n<p>Add a \u201cReply Finder\u201d section in the side panel:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Match type<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Contains keyword(s)<\/li>\n\n\n\n<li>Matches any of these words<\/li>\n\n\n\n<li>Matches all of these words<\/li>\n\n\n\n<li>Regex (advanced)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Search scope<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Top-level comments only<\/li>\n\n\n\n<li>Replies included too<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Quick toggles<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Only comments with <code>?<\/code><\/li>\n\n\n\n<li>Only comments containing <code>@<\/code><\/li>\n\n\n\n<li>Only comments with \u2265 N likes (optional)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Results list<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Checkbox per matched comment<\/li>\n\n\n\n<li>Shows: author name, snippet, likes, \u201cReply\u201d button<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Feature: One reply to multiple people<\/h5>\n\n\n\n<p>This is perfect for your use case (\u201csame reply may need to go to three people\u201d).<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Safer approach (recommended)<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You select 3 matched comments in the panel<\/li>\n\n\n\n<li>The panel generates <strong>3 slightly varied replies<\/strong> from one template (to reduce repetition)<\/li>\n\n\n\n<li>You click <strong>Reply \u2192 Insert<\/strong> for each one<\/li>\n\n\n\n<li>You manually click <strong>Send\/Reply<\/strong> each time<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Template example (with light variation)<\/h5>\n\n\n\n<p>Template:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u201c@{author} good point about <strong>{topic}<\/strong>. My take: {shortAnswer}. What part are you stuck on?\u201d<\/p>\n<\/blockquote>\n\n\n\n<p>Variation knobs:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>rotate openers: \u201cGood point \/ You\u2019re right \/ I noticed that too\u201d<\/li>\n\n\n\n<li>rotate closers: \u201cWhat do you think? \/ Curious your thoughts \/ Hope that helps\u201d<\/li>\n<\/ul>\n\n\n\n<p>This avoids copy-paste identical replies that can get devalued.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">How the extension finds the \u201cright\u201d reply box<\/h5>\n\n\n\n<p>On a matched comment, the content script can:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Scroll that comment into view<\/li>\n\n\n\n<li>Click the comment\u2019s <strong>Reply<\/strong> button (or you do it)<\/li>\n\n\n\n<li>Wait for the reply editor to appear<\/li>\n\n\n\n<li>Insert your text into the editor (dispatch input events)<\/li>\n\n\n\n<li>Stop there (no auto-submit)<\/li>\n<\/ol>\n\n\n\n<h5 class=\"wp-block-heading\">Practical limitations you should expect<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li>YouTube loads comments dynamically. The extension needs a <strong>\u201cLoad more comments\u201d helper<\/strong> (or you scroll manually).<\/li>\n\n\n\n<li>If you try to reply to a lot of people fast, YouTube may rate-limit you anyway.<\/li>\n\n\n\n<li>Repeating the same promotional pitch to many users (even as replies) can still get filtered. Variation + relevance matters.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Suggested UI layout for your panel<\/h5>\n\n\n\n<p><strong>Tab 1: Queue<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Scan channel \/ videos list<\/li>\n\n\n\n<li>Open next video<\/li>\n<\/ul>\n\n\n\n<p><strong>Tab 2: Reply Finder<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Filters (keywords, @mentions, questions)<\/li>\n\n\n\n<li>Results list + checkboxes<\/li>\n\n\n\n<li>Reply composer (template dropdown + editable text)<\/li>\n\n\n\n<li>Buttons:\n<ul class=\"wp-block-list\">\n<li><strong>Insert reply to selected (one-by-one)<\/strong><\/li>\n\n\n\n<li><strong>Insert next<\/strong><\/li>\n\n\n\n<li><strong>Mark replied \/ Skip<\/strong><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>Tab 3: Templates<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Reply templates<\/li>\n\n\n\n<li>Variation settings<\/li>\n\n\n\n<li>\u201cNo-link mode\u201d toggle (recommended most of the time)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<p>If you want, I can write the full MV3 extension starter that includes this \u201cReply Finder\u201d flow (scan comments \u2192 filter \u2192 select \u2192 insert reply). It\u2019ll work on the page you\u2019re currently viewing and won\u2019t auto-submit.<\/p>\n\n\n\n<p>yes full mv3<\/p>\n\n\n\n<p>Thought for 11s<\/p>\n\n\n\n<p>Below is a <strong>full working Chrome MV3 extension (assist-mode)<\/strong> that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 Scans a channel \u201cVideos\u201d\/\u201cShorts\u201d page and builds a <strong>queue<\/strong><\/li>\n\n\n\n<li>\u2705 Opens <strong>Next video<\/strong> from the queue<\/li>\n\n\n\n<li>\u2705 On a video page, lets you <strong>Insert<\/strong> a prepared <strong>top-level comment<\/strong> (you still click <strong>Comment<\/strong>)<\/li>\n\n\n\n<li>\u2705 On a video page, scans comments for <strong>keywords\/@mentions\/?<\/strong> and lists matches<\/li>\n\n\n\n<li>\u2705 Lets you select multiple matched comments and <strong>open Reply + insert reply text<\/strong> one-by-one (you still click <strong>Reply\/Send<\/strong>)<\/li>\n\n\n\n<li>\u2705 Saves queue + \u201cdone\u201d + templates in <code>chrome.storage.local<\/code><\/li>\n<\/ul>\n\n\n\n<p>It does <strong>not<\/strong> auto-submit anything.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">1) Folder tree<\/h5>\n\n\n\n<p>Create a folder like: <code>yt-assist-mv3\/<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>yt-assist-mv3\/\n  manifest.json\n  service_worker.js\n  content_script.js\n  sidepanel.html\n  sidepanel.js\n  sidepanel.css\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">2) <code>manifest.json<\/code><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"name\": \"YT Assist (Queue + Reply Finder) - MV3\",\n  \"description\": \"Assist-mode helper for scanning YouTube pages, queueing videos, and inserting comments\/replies (no auto-submit).\",\n  \"version\": \"1.0.0\",\n  \"manifest_version\": 3,\n\n  \"permissions\": [\"storage\", \"tabs\", \"scripting\", \"activeTab\"],\n  \"host_permissions\": [\"https:\/\/www.youtube.com\/*\"],\n\n  \"background\": {\n    \"service_worker\": \"service_worker.js\"\n  },\n\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https:\/\/www.youtube.com\/*\"],\n      \"js\": [\"content_script.js\"],\n      \"run_at\": \"document_idle\"\n    }\n  ],\n\n  \"side_panel\": {\n    \"default_path\": \"sidepanel.html\"\n  },\n\n  \"action\": {\n    \"default_title\": \"YT Assist\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">3) <code>service_worker.js<\/code><\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code>const STORAGE_KEYS = {\n  queue: \"ytassist_queue\",\n  done: \"ytassist_done\",\n  templates: \"ytassist_templates\",\n  settings: \"ytassist_settings\"\n};\n\nconst DEFAULT_TEMPLATES = {\n  comments: [\n    \"This part about \u201c{title}\u201d was crazy \u2014 especially around {timestamp}. Quick question: {question}\",\n    \"Solid video, {channel}. The point on \u201c{title}\u201d hit. What made you start doing this style?\"\n  ],\n  replies: [\n    \"@{author} Good point. I noticed that too \u2014 especially in \u201c{title}\u201d. What\u2019s your take on {question}?\",\n    \"@{author} That\u2019s fair. If you mean {topic}, I\u2019d say: {shortAnswer}. Curious what you think.\"\n  ]\n};\n\nconst DEFAULT_SETTINGS = {\n  cooldownSeconds: 60,\n  linkEveryN: 10\n};\n\nasync function getStore(keys) {\n  return await chrome.storage.local.get(keys);\n}\n\nasync function setStore(obj) {\n  return await chrome.storage.local.set(obj);\n}\n\nasync function ensureDefaults() {\n  const st = await getStore([STORAGE_KEYS.templates, STORAGE_KEYS.settings, STORAGE_KEYS.queue, STORAGE_KEYS.done]);\n  const out = {};\n  if (!st[STORAGE_KEYS.templates]) out[STORAGE_KEYS.templates] = DEFAULT_TEMPLATES;\n  if (!st[STORAGE_KEYS.settings]) out[STORAGE_KEYS.settings] = DEFAULT_SETTINGS;\n  if (!st[STORAGE_KEYS.queue]) out[STORAGE_KEYS.queue] = [];\n  if (!st[STORAGE_KEYS.done]) out[STORAGE_KEYS.done] = {};\n  if (Object.keys(out).length) await setStore(out);\n}\n\nchrome.runtime.onInstalled.addListener(() =&gt; {\n  ensureDefaults();\n});\n\nchrome.runtime.onMessage.addListener((msg, sender, sendResponse) =&gt; {\n  (async () =&gt; {\n    await ensureDefaults();\n\n    if (msg?.type === \"STORE_QUEUE_APPEND\") {\n      const { items = [] } = msg;\n      const st = await getStore([STORAGE_KEYS.queue]);\n      const q = st[STORAGE_KEYS.queue] || [];\n\n      \/\/ De-dupe by url\n      const have = new Set(q.map(x =&gt; x.url));\n      const merged = [...q];\n      for (const it of items) {\n        if (!it?.url) continue;\n        if (!have.has(it.url)) {\n          have.add(it.url);\n          merged.push(it);\n        }\n      }\n      await setStore({ [STORAGE_KEYS.queue]: merged });\n      sendResponse({ ok: true, count: merged.length });\n      return;\n    }\n\n    if (msg?.type === \"GET_STATE\") {\n      const st = await getStore([STORAGE_KEYS.queue, STORAGE_KEYS.done, STORAGE_KEYS.templates, STORAGE_KEYS.settings]);\n      sendResponse({ ok: true, state: st });\n      return;\n    }\n\n    if (msg?.type === \"SET_STATE\") {\n      const { patch = {} } = msg;\n      await setStore(patch);\n      sendResponse({ ok: true });\n      return;\n    }\n\n    if (msg?.type === \"QUEUE_POP_NEXT\") {\n      const st = await getStore([STORAGE_KEYS.queue, STORAGE_KEYS.done]);\n      const q = st[STORAGE_KEYS.queue] || [];\n      const done = st[STORAGE_KEYS.done] || {};\n\n      \/\/ find first not done\n      let idx = q.findIndex(x =&gt; x?.url &amp;&amp; !done[x.url]);\n      if (idx === -1) idx = 0;\n\n      const next = q[idx] || null;\n      sendResponse({ ok: true, next });\n      return;\n    }\n\n    if (msg?.type === \"MARK_DONE\") {\n      const { url } = msg;\n      if (!url) return sendResponse({ ok: false, error: \"Missing url\" });\n\n      const st = await getStore([STORAGE_KEYS.done]);\n      const done = st[STORAGE_KEYS.done] || {};\n      done[url] = { at: Date.now() };\n      await setStore({ [STORAGE_KEYS.done]: done });\n      sendResponse({ ok: true });\n      return;\n    }\n\n    sendResponse({ ok: false, error: \"Unknown message type\" });\n  })();\n\n  return true; \/\/ async\n});\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">4) <code>sidepanel.html<\/code><\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!doctype html&gt;\n&lt;html&gt;\n&lt;head&gt;\n  &lt;meta charset=\"utf-8\" \/&gt;\n  &lt;meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" \/&gt;\n  &lt;title&gt;YT Assist&lt;\/title&gt;\n  &lt;link rel=\"stylesheet\" href=\"sidepanel.css\" \/&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;header class=\"top\"&gt;\n    &lt;div class=\"brand\"&gt;\n      &lt;div class=\"dot\"&gt;&lt;\/div&gt;\n      &lt;div&gt;\n        &lt;div class=\"title\"&gt;YT Assist&lt;\/div&gt;\n        &lt;div class=\"sub\"&gt;Queue + Reply Finder (no auto-submit)&lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  &lt;\/header&gt;\n\n  &lt;nav class=\"tabs\"&gt;\n    &lt;button class=\"tab active\" data-tab=\"queue\"&gt;Queue&lt;\/button&gt;\n    &lt;button class=\"tab\" data-tab=\"reply\"&gt;Reply Finder&lt;\/button&gt;\n    &lt;button class=\"tab\" data-tab=\"templates\"&gt;Templates&lt;\/button&gt;\n  &lt;\/nav&gt;\n\n  &lt;main&gt;\n    &lt;!-- QUEUE --&gt;\n    &lt;section class=\"panel active\" id=\"panel-queue\"&gt;\n      &lt;div class=\"row\"&gt;\n        &lt;button id=\"btnScanVideos\" class=\"btn\"&gt;Scan this page for videos&lt;\/button&gt;\n        &lt;button id=\"btnRefreshState\" class=\"btn ghost\"&gt;Refresh&lt;\/button&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"row\"&gt;\n          &lt;button id=\"btnOpenNext\" class=\"btn\"&gt;Open Next&lt;\/button&gt;\n          &lt;button id=\"btnMarkDone\" class=\"btn ghost\"&gt;Mark Current Done&lt;\/button&gt;\n        &lt;\/div&gt;\n\n        &lt;div class=\"row\"&gt;\n          &lt;label&gt;Cooldown:&lt;\/label&gt;\n          &lt;input id=\"cooldown\" type=\"number\" min=\"10\" step=\"5\" class=\"input small\" \/&gt;\n          &lt;span class=\"muted\"&gt;sec&lt;\/span&gt;\n          &lt;button id=\"btnStartCooldown\" class=\"btn ghost\"&gt;Start&lt;\/button&gt;\n        &lt;\/div&gt;\n\n        &lt;div id=\"cooldownStatus\" class=\"muted small\"&gt;&lt;\/div&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"row between\"&gt;\n          &lt;div&gt;\n            &lt;div class=\"h\"&gt;Queue&lt;\/div&gt;\n            &lt;div class=\"muted small\" id=\"queueMeta\"&gt;&lt;\/div&gt;\n          &lt;\/div&gt;\n          &lt;button id=\"btnClearDone\" class=\"btn ghost danger\"&gt;Clear Done&lt;\/button&gt;\n        &lt;\/div&gt;\n        &lt;div id=\"queueList\" class=\"list\"&gt;&lt;\/div&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"h\"&gt;Top-level comment helper&lt;\/div&gt;\n        &lt;textarea id=\"commentBox\" class=\"textarea\" placeholder=\"Write \/ generate a comment here (you will still press Comment).\"&gt;&lt;\/textarea&gt;\n        &lt;div class=\"row\"&gt;\n          &lt;button id=\"btnInsertComment\" class=\"btn\"&gt;Insert into YouTube comment box&lt;\/button&gt;\n          &lt;button id=\"btnCopyComment\" class=\"btn ghost\"&gt;Copy&lt;\/button&gt;\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/section&gt;\n\n    &lt;!-- REPLY FINDER --&gt;\n    &lt;section class=\"panel\" id=\"panel-reply\"&gt;\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"h\"&gt;Find comments to reply to (current video page)&lt;\/div&gt;\n\n        &lt;div class=\"grid2\"&gt;\n          &lt;div&gt;\n            &lt;label class=\"lbl\"&gt;Keywords (comma separated)&lt;\/label&gt;\n            &lt;input id=\"rfKeywords\" class=\"input\" placeholder=\"e.g. link, where, how, mic, @, #\"\n            \/&gt;\n          &lt;\/div&gt;\n          &lt;div&gt;\n            &lt;label class=\"lbl\"&gt;Match mode&lt;\/label&gt;\n            &lt;select id=\"rfMode\" class=\"input\"&gt;\n              &lt;option value=\"any\"&gt;Any keyword&lt;\/option&gt;\n              &lt;option value=\"all\"&gt;All keywords&lt;\/option&gt;\n              &lt;option value=\"contains\"&gt;Contains phrase (exact)&lt;\/option&gt;\n            &lt;\/select&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n\n        &lt;div class=\"row wrap\"&gt;\n          &lt;label class=\"chk\"&gt;&lt;input id=\"rfQOnly\" type=\"checkbox\" \/&gt; Only \u201c?\u201d questions&lt;\/label&gt;\n          &lt;label class=\"chk\"&gt;&lt;input id=\"rfMentions\" type=\"checkbox\" \/&gt; Contains \u201c@\u201d&lt;\/label&gt;\n          &lt;label class=\"chk\"&gt;&lt;input id=\"rfHashtags\" type=\"checkbox\" \/&gt; Contains \u201c#\u201d&lt;\/label&gt;\n        &lt;\/div&gt;\n\n        &lt;div class=\"row\"&gt;\n          &lt;button id=\"btnScanComments\" class=\"btn\"&gt;Scan comments&lt;\/button&gt;\n          &lt;button id=\"btnSelectAll\" class=\"btn ghost\"&gt;Select all&lt;\/button&gt;\n          &lt;button id=\"btnSelectNone\" class=\"btn ghost\"&gt;Select none&lt;\/button&gt;\n        &lt;\/div&gt;\n\n        &lt;div class=\"muted small\" id=\"rfMeta\"&gt;&lt;\/div&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"h\"&gt;Reply composer&lt;\/div&gt;\n        &lt;textarea id=\"replyBox\" class=\"textarea\" placeholder=\"Write your reply. Use @name manually if you want.\"&gt;&lt;\/textarea&gt;\n        &lt;div class=\"row\"&gt;\n          &lt;button id=\"btnInsertReplyNext\" class=\"btn\"&gt;Reply + Insert (next selected)&lt;\/button&gt;\n          &lt;button id=\"btnCopyReply\" class=\"btn ghost\"&gt;Copy&lt;\/button&gt;\n        &lt;\/div&gt;\n        &lt;div class=\"muted small\"&gt;\n          Tip: the tool will open the Reply box and insert text. You still click \u201cReply\u201d.\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"h\"&gt;Matches&lt;\/div&gt;\n        &lt;div id=\"matchList\" class=\"list\"&gt;&lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/section&gt;\n\n    &lt;!-- TEMPLATES --&gt;\n    &lt;section class=\"panel\" id=\"panel-templates\"&gt;\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"h\"&gt;Templates&lt;\/div&gt;\n        &lt;div class=\"muted small\"&gt;Saved locally in your browser (chrome.storage.local).&lt;\/div&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"h\"&gt;Comment templates (one per line)&lt;\/div&gt;\n        &lt;textarea id=\"tplComments\" class=\"textarea\"&gt;&lt;\/textarea&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"h\"&gt;Reply templates (one per line)&lt;\/div&gt;\n        &lt;textarea id=\"tplReplies\" class=\"textarea\"&gt;&lt;\/textarea&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"row\"&gt;\n        &lt;button id=\"btnSaveTemplates\" class=\"btn\"&gt;Save Templates&lt;\/button&gt;\n        &lt;button id=\"btnLoadTemplates\" class=\"btn ghost\"&gt;Reload&lt;\/button&gt;\n      &lt;\/div&gt;\n\n      &lt;div class=\"card\"&gt;\n        &lt;div class=\"h\"&gt;Template variables&lt;\/div&gt;\n        &lt;div class=\"muted small\"&gt;\n          {title}, {channel}, {timestamp}, {question}, {topic}, {shortAnswer}, {author}\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/section&gt;\n  &lt;\/main&gt;\n\n  &lt;script src=\"sidepanel.js\"&gt;&lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">5) <code>sidepanel.css<\/code><\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code>:root{\n  --bg:#0b0c10;\n  --card:#11131a;\n  --text:#eaeef7;\n  --muted:#9aa3b2;\n  --line:#23273a;\n  --accent:#7c5cff;\n  --danger:#ff5c7c;\n}\n\n*{box-sizing:border-box}\nbody{\n  margin:0;\n  font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n  background:var(--bg);\n  color:var(--text);\n}\n.top{\n  padding:12px 12px 8px;\n  border-bottom:1px solid var(--line);\n}\n.brand{\n  display:flex;\n  gap:10px;\n  align-items:center;\n}\n.dot{\n  width:12px;height:12px;border-radius:99px;\n  background:var(--accent);\n  box-shadow:0 0 18px rgba(124,92,255,.65);\n}\n.title{font-weight:700}\n.sub{font-size:12px;color:var(--muted)}\n\n.tabs{\n  display:flex;\n  gap:6px;\n  padding:8px 10px;\n  border-bottom:1px solid var(--line);\n}\n.tab{\n  border:1px solid var(--line);\n  background:transparent;\n  color:var(--text);\n  padding:8px 10px;\n  border-radius:12px;\n  cursor:pointer;\n}\n.tab.active{\n  background:rgba(124,92,255,.15);\n  border-color:rgba(124,92,255,.45);\n}\n\nmain{padding:10px}\n.panel{display:none}\n.panel.active{display:block}\n\n.card{\n  background:var(--card);\n  border:1px solid var(--line);\n  border-radius:16px;\n  padding:10px;\n  margin-bottom:10px;\n}\n.h{font-weight:700;margin-bottom:6px}\n.small{font-size:12px}\n.muted{color:var(--muted)}\n\n.row{display:flex; gap:8px; align-items:center; margin:8px 0}\n.row.between{justify-content:space-between}\n.row.wrap{flex-wrap:wrap}\n.grid2{display:grid; grid-template-columns:1fr 1fr; gap:10px}\n\n.btn{\n  background:var(--accent);\n  color:#fff;\n  border:none;\n  padding:10px 12px;\n  border-radius:12px;\n  cursor:pointer;\n  font-weight:600;\n}\n.btn.ghost{\n  background:transparent;\n  border:1px solid var(--line);\n}\n.btn.danger{\n  border-color:rgba(255,92,124,.5);\n  color:var(--danger);\n}\n.input, select.input{\n  width:100%;\n  background:#0e1017;\n  border:1px solid var(--line);\n  color:var(--text);\n  padding:10px;\n  border-radius:12px;\n}\n.input.small{width:80px}\n.lbl{display:block;font-size:12px;color:var(--muted);margin-bottom:6px}\n.textarea{\n  width:100%;\n  min-height:90px;\n  background:#0e1017;\n  border:1px solid var(--line);\n  color:var(--text);\n  padding:10px;\n  border-radius:12px;\n  resize:vertical;\n}\n\n.list{display:flex; flex-direction:column; gap:8px}\n.item{\n  border:1px solid var(--line);\n  border-radius:14px;\n  padding:8px;\n  background:#0e1017;\n}\n.item .t{font-weight:650}\n.item .s{color:var(--muted); font-size:12px; margin-top:4px}\n.item .actions{display:flex; gap:8px; margin-top:8px; flex-wrap:wrap}\n.badge{\n  font-size:11px;\n  padding:2px 8px;\n  border:1px solid var(--line);\n  border-radius:999px;\n  color:var(--muted);\n}\n.chk{font-size:13px;color:var(--text)}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">6) <code>sidepanel.js<\/code><\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code>const K = {\n  queue: \"ytassist_queue\",\n  done: \"ytassist_done\",\n  templates: \"ytassist_templates\",\n  settings: \"ytassist_settings\"\n};\n\nconst $ = (sel) =&gt; document.querySelector(sel);\nconst $$ = (sel) =&gt; Array.from(document.querySelectorAll(sel));\n\nfunction sleep(ms){ return new Promise(r=&gt;setTimeout(r,ms)); }\n\nasync function getActiveTab() {\n  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });\n  return tab;\n}\n\nasync function sendToActiveTab(payload) {\n  const tab = await getActiveTab();\n  if (!tab?.id) return { ok:false, error:\"No active tab\" };\n  return await chrome.tabs.sendMessage(tab.id, payload);\n}\n\nasync function bg(msg) {\n  return await chrome.runtime.sendMessage(msg);\n}\n\nfunction setTab(name){\n  $$(\".tab\").forEach(b =&gt; b.classList.toggle(\"active\", b.dataset.tab === name));\n  $$(\".panel\").forEach(p =&gt; p.classList.toggle(\"active\", p.id === `panel-${name}`));\n}\n\n$$(\".tab\").forEach(b =&gt; b.addEventListener(\"click\", () =&gt; setTab(b.dataset.tab)));\n\nlet cooldownTimer = null;\nlet cooldownRemaining = 0;\n\nfunction startCooldown(seconds){\n  clearInterval(cooldownTimer);\n  cooldownRemaining = seconds;\n  $(\"#cooldownStatus\").textContent = `Cooldown: ${cooldownRemaining}s`;\n  cooldownTimer = setInterval(() =&gt; {\n    cooldownRemaining--;\n    if (cooldownRemaining &lt;= 0) {\n      clearInterval(cooldownTimer);\n      $(\"#cooldownStatus\").textContent = \"Cooldown finished.\";\n      return;\n    }\n    $(\"#cooldownStatus\").textContent = `Cooldown: ${cooldownRemaining}s`;\n  }, 1000);\n}\n\nfunction escapeHtml(s=\"\"){\n  return s.replace(\/[&amp;&lt;&gt;\"']\/g, c =&gt; ({'&amp;':'&amp;amp;','&lt;':'&amp;lt;','&gt;':'&amp;gt;','\"':'&amp;quot;',\"'\":'&amp;#39;'}[c]));\n}\n\nfunction renderQueue(queue, done){\n  const total = queue.length;\n  const doneCount = queue.filter(x =&gt; done?.[x.url]).length;\n  $(\"#queueMeta\").textContent = `${total} items \u2022 ${doneCount} done`;\n\n  const wrap = $(\"#queueList\");\n  wrap.innerHTML = \"\";\n\n  queue.slice(0, 200).forEach((it, idx) =&gt; {\n    const isDone = !!done?.[it.url];\n    const el = document.createElement(\"div\");\n    el.className = \"item\";\n    el.innerHTML = `\n      &lt;div class=\"t\"&gt;${escapeHtml(it.title || it.url)}&lt;\/div&gt;\n      &lt;div class=\"s\"&gt;${escapeHtml(it.url)}&lt;\/div&gt;\n      &lt;div class=\"actions\"&gt;\n        &lt;span class=\"badge\"&gt;${isDone ? \"DONE\" : \"PENDING\"}&lt;\/span&gt;\n        &lt;button class=\"btn ghost\" data-open=\"${escapeHtml(it.url)}\"&gt;Open&lt;\/button&gt;\n        &lt;button class=\"btn ghost\" data-done=\"${escapeHtml(it.url)}\"&gt;Mark done&lt;\/button&gt;\n      &lt;\/div&gt;\n    `;\n    wrap.appendChild(el);\n  });\n\n  wrap.querySelectorAll(\"[data-open]\").forEach(btn =&gt; btn.addEventListener(\"click\", async () =&gt; {\n    const url = btn.getAttribute(\"data-open\");\n    const tab = await getActiveTab();\n    await chrome.tabs.update(tab.id, { url });\n  }));\n\n  wrap.querySelectorAll(\"[data-done]\").forEach(btn =&gt; btn.addEventListener(\"click\", async () =&gt; {\n    const url = btn.getAttribute(\"data-done\");\n    await bg({ type:\"MARK_DONE\", url });\n    await refresh();\n  }));\n}\n\nfunction renderMatches(matches){\n  $(\"#rfMeta\").textContent = `${matches.length} matches found (select some, then Reply + Insert).`;\n\n  const wrap = $(\"#matchList\");\n  wrap.innerHTML = \"\";\n\n  matches.forEach((m) =&gt; {\n    const el = document.createElement(\"div\");\n    el.className = \"item\";\n    el.innerHTML = `\n      &lt;label class=\"chk\"&gt;\n        &lt;input type=\"checkbox\" class=\"mchk\" data-id=\"${escapeHtml(m.assistId)}\" checked \/&gt;\n        &lt;span class=\"t\"&gt;${escapeHtml(m.author || \"Unknown\")}&lt;\/span&gt;\n      &lt;\/label&gt;\n      &lt;div class=\"s\"&gt;${escapeHtml(m.text || \"\")}&lt;\/div&gt;\n      &lt;div class=\"actions\"&gt;\n        &lt;button class=\"btn ghost\" data-scroll=\"${escapeHtml(m.assistId)}\"&gt;Scroll&lt;\/button&gt;\n      &lt;\/div&gt;\n    `;\n    wrap.appendChild(el);\n  });\n\n  wrap.querySelectorAll(\"[data-scroll]\").forEach(btn =&gt; btn.addEventListener(\"click\", async () =&gt; {\n    const id = btn.getAttribute(\"data-scroll\");\n    await sendToActiveTab({ type:\"SCROLL_TO_MATCH\", assistId:id });\n  }));\n}\n\nasync function refresh(){\n  const res = await bg({ type:\"GET_STATE\" });\n  if (!res?.ok) return;\n\n  const st = res.state;\n  const queue = st[K.queue] || [];\n  const done  = st[K.done]  || {};\n  const templates = st[K.templates] || { comments:[], replies:[] };\n  const settings  = st[K.settings] || { cooldownSeconds:60 };\n\n  $(\"#cooldown\").value = settings.cooldownSeconds ?? 60;\n\n  renderQueue(queue, done);\n  $(\"#tplComments\").value = (templates.comments || []).join(\"\\n\");\n  $(\"#tplReplies\").value  = (templates.replies  || []).join(\"\\n\");\n}\n\n$(\"#btnRefreshState\").addEventListener(\"click\", refresh);\n\n$(\"#btnScanVideos\").addEventListener(\"click\", async () =&gt; {\n  const r = await sendToActiveTab({ type:\"SCAN_VIDEOS_FROM_PAGE\" });\n  if (!r?.ok) {\n    alert(r?.error || \"Scan failed. Make sure you're on a YouTube channel Videos\/Shorts page.\");\n    return;\n  }\n  await bg({ type:\"STORE_QUEUE_APPEND\", items: r.items });\n  await refresh();\n});\n\n$(\"#btnOpenNext\").addEventListener(\"click\", async () =&gt; {\n  const r = await bg({ type:\"QUEUE_POP_NEXT\" });\n  if (!r?.ok || !r.next?.url) return alert(\"No next item.\");\n  const tab = await getActiveTab();\n  await chrome.tabs.update(tab.id, { url: r.next.url });\n});\n\n$(\"#btnMarkDone\").addEventListener(\"click\", async () =&gt; {\n  const tab = await getActiveTab();\n  if (!tab?.url) return;\n  await bg({ type:\"MARK_DONE\", url: tab.url });\n  await refresh();\n});\n\n$(\"#btnClearDone\").addEventListener(\"click\", async () =&gt; {\n  await bg({ type:\"SET_STATE\", patch: { [K.done]: {} }});\n  await refresh();\n});\n\n$(\"#btnStartCooldown\").addEventListener(\"click\", async () =&gt; {\n  const seconds = parseInt($(\"#cooldown\").value || \"60\", 10);\n  startCooldown(Math.max(10, seconds));\n  await bg({ type:\"SET_STATE\", patch: { [K.settings]: { cooldownSeconds: Math.max(10, seconds) } }});\n});\n\n$(\"#btnCopyComment\").addEventListener(\"click\", async () =&gt; {\n  await navigator.clipboard.writeText($(\"#commentBox\").value || \"\");\n});\n\n$(\"#btnInsertComment\").addEventListener(\"click\", async () =&gt; {\n  const text = $(\"#commentBox\").value || \"\";\n  const r = await sendToActiveTab({ type:\"INSERT_TOP_LEVEL_COMMENT_TEXT\", text });\n  if (!r?.ok) alert(r?.error || \"Insert failed.\");\n});\n\n$(\"#btnScanComments\").addEventListener(\"click\", async () =&gt; {\n  const keywords = ($(\"#rfKeywords\").value || \"\").split(\",\").map(s=&gt;s.trim()).filter(Boolean);\n  const mode = $(\"#rfMode\").value;\n  const qOnly = $(\"#rfQOnly\").checked;\n  const mentions = $(\"#rfMentions\").checked;\n  const hashtags = $(\"#rfHashtags\").checked;\n\n  const r = await sendToActiveTab({\n    type:\"SCAN_COMMENTS_FOR_MATCHES\",\n    filters: { keywords, mode, qOnly, mentions, hashtags }\n  });\n\n  if (!r?.ok) {\n    alert(r?.error || \"Comment scan failed. Make sure you're on a video watch page.\");\n    return;\n  }\n  renderMatches(r.matches || []);\n});\n\n$(\"#btnSelectAll\").addEventListener(\"click\", () =&gt; {\n  $$(\"#matchList .mchk\").forEach(c =&gt; c.checked = true);\n});\n$(\"#btnSelectNone\").addEventListener(\"click\", () =&gt; {\n  $$(\"#matchList .mchk\").forEach(c =&gt; c.checked = false);\n});\n\n$(\"#btnCopyReply\").addEventListener(\"click\", async () =&gt; {\n  await navigator.clipboard.writeText($(\"#replyBox\").value || \"\");\n});\n\n$(\"#btnInsertReplyNext\").addEventListener(\"click\", async () =&gt; {\n  const text = $(\"#replyBox\").value || \"\";\n  const selected = $$(\"#matchList .mchk\").filter(c =&gt; c.checked).map(c =&gt; c.dataset.id);\n  if (!selected.length) return alert(\"Select at least one match.\");\n\n  \/\/ take first selected, then uncheck it\n  const id = selected[0];\n  const r = await sendToActiveTab({ type:\"REPLY_AND_INSERT_TEXT\", assistId:id, text });\n  if (!r?.ok) return alert(r?.error || \"Reply insert failed.\");\n\n  const chk = $(`#matchList .mchk[data-id=\"${CSS.escape(id)}\"]`);\n  if (chk) chk.checked = false;\n});\n\n$(\"#btnSaveTemplates\").addEventListener(\"click\", async () =&gt; {\n  const comments = ($(\"#tplComments\").value || \"\").split(\"\\n\").map(s=&gt;s.trim()).filter(Boolean);\n  const replies  = ($(\"#tplReplies\").value  || \"\").split(\"\\n\").map(s=&gt;s.trim()).filter(Boolean);\n\n  await bg({ type:\"SET_STATE\", patch: { [K.templates]: { comments, replies } }});\n  alert(\"Templates saved.\");\n});\n\n$(\"#btnLoadTemplates\").addEventListener(\"click\", refresh);\n\n\/\/ init\nrefresh();\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">7) <code>content_script.js<\/code><\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ YT Assist content script (MV3)\n\/\/ - scans channel pages for videos\n\/\/ - scans watch pages for comments matching filters\n\/\/ - inserts comment\/reply text (no submit)\n\nconst log = (...a) =&gt; console.log(\"[YTAssist]\", ...a);\n\nfunction sleep(ms){ return new Promise(r=&gt;setTimeout(r,ms)); }\n\nasync function waitFor(fn, { timeout=12000, interval=200 } = {}) {\n  const start = Date.now();\n  while (Date.now() - start &lt; timeout) {\n    const v = fn();\n    if (v) return v;\n    await sleep(interval);\n  }\n  return null;\n}\n\nfunction isWatchPage() {\n  return location.pathname === \"\/watch\" || location.pathname.startsWith(\"\/shorts\/\");\n}\n\nfunction isChannelVideoGridPage() {\n  \/\/ covers \/@handle\/videos, \/channel\/...\/videos, \/@handle\/shorts\n  return \/\\\/(videos|shorts)$\/.test(location.pathname) || location.href.includes(\"\/videos\") || location.href.includes(\"\/shorts\");\n}\n\nfunction uniqBy(arr, keyFn) {\n  const seen = new Set();\n  const out = [];\n  for (const x of arr) {\n    const k = keyFn(x);\n    if (!k || seen.has(k)) continue;\n    seen.add(k);\n    out.push(x);\n  }\n  return out;\n}\n\nfunction getVideoIdFromUrl(url) {\n  try {\n    const u = new URL(url);\n    if (u.pathname.startsWith(\"\/watch\")) return u.searchParams.get(\"v\") || \"\";\n    if (u.pathname.startsWith(\"\/shorts\/\")) return u.pathname.split(\"\/shorts\/\")[1]?.split(\/[?&amp;#]\/)[0] || \"\";\n    return \"\";\n  } catch { return \"\"; }\n}\n\nfunction normalizeUrl(href) {\n  if (!href) return null;\n  if (href.startsWith(\"http\")) return href;\n  if (href.startsWith(\"\/\")) return \"https:\/\/www.youtube.com\" + href;\n  return null;\n}\n\nfunction genId() {\n  return \"m_\" + Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nfunction setEditableText(el, text) {\n  \/\/ YouTube uses contenteditable; this pattern triggers React-ish listeners\n  el.focus();\n  document.execCommand(\"selectAll\", false, null);\n  document.execCommand(\"insertText\", false, text);\n\n  el.dispatchEvent(new InputEvent(\"input\", { bubbles: true, data: text, inputType: \"insertText\" }));\n  el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n}\n\nasync function ensureCommentsLoaded() {\n  \/\/ scroll to comments area\n  window.scrollTo({ top: 900, behavior: \"smooth\" });\n  await sleep(500);\n\n  \/\/ wait for comments container\n  const comments = await waitFor(() =&gt;\n    document.querySelector(\"ytd-comments#comments\") ||\n    document.querySelector(\"ytd-item-section-renderer#sections\")\n  , { timeout: 12000 });\n\n  if (!comments) return false;\n\n  \/\/ Light autoload: scroll a bit to trigger initial render\n  for (let i=0;i&lt;3;i++){\n    window.scrollBy({ top: 800, behavior: \"smooth\" });\n    await sleep(450);\n  }\n  return true;\n}\n\nfunction findTopLevelCommentBox() {\n  \/\/ Several layouts exist; try common patterns\n  \/\/ 1) Standard watch page comment box:\n  const a = document.querySelector(\"ytd-comment-simplebox-renderer #contenteditable-root\");\n  if (a) return a;\n\n  \/\/ 2) Alternate:\n  const b = document.querySelector(\"ytd-commentbox #contenteditable-root\");\n  if (b) return b;\n\n  \/\/ 3) Shorts sometimes:\n  const c = document.querySelector(\"ytd-comment-simplebox-renderer [contenteditable='true']\");\n  if (c) return c;\n\n  return null;\n}\n\nasync function openTopLevelCommentBoxIfNeeded() {\n  \/\/ Sometimes needs click on placeholder\n  const placeholder =\n    document.querySelector(\"ytd-comment-simplebox-renderer #placeholder-area\") ||\n    document.querySelector(\"ytd-comment-simplebox-renderer tp-yt-paper-input\") ||\n    document.querySelector(\"ytd-comment-simplebox-renderer\");\n\n  const box = findTopLevelCommentBox();\n  if (box) return box;\n\n  if (placeholder) placeholder.click();\n  await sleep(250);\n\n  return findTopLevelCommentBox();\n}\n\nfunction collectVideoLinksFromGrid() {\n  \/\/ Channel \u201cVideos\/Shorts\u201d grid usually uses ytd-rich-grid-media\n  const anchors = Array.from(document.querySelectorAll(\"a#thumbnail[href], a#video-title-link[href]\"));\n  const items = anchors\n    .map(a =&gt; {\n      const url = normalizeUrl(a.getAttribute(\"href\"));\n      if (!url) return null;\n\n      const vid = getVideoIdFromUrl(url);\n      if (!vid) return null;\n\n      \/\/ title can be near; try closest rich item\n      const card = a.closest(\"ytd-rich-grid-media, ytd-grid-video-renderer, ytd-rich-item-renderer\");\n      let title = \"\";\n      if (card) {\n        const t =\n          card.querySelector(\"#video-title\") ||\n          card.querySelector(\"#video-title-link\") ||\n          card.querySelector(\"a#video-title-link\") ||\n          card.querySelector(\"yt-formatted-string#video-title\");\n        title = (t?.textContent || \"\").trim();\n      }\n      return { url, title };\n    })\n    .filter(Boolean);\n\n  return uniqBy(items, x =&gt; x.url);\n}\n\nfunction getCommentElements() {\n  \/\/ Top-level comments:\n  const nodes = Array.from(document.querySelectorAll(\"ytd-comment-thread-renderer\"));\n  return nodes;\n}\n\nfunction extractCommentText(threadEl) {\n  const content = threadEl.querySelector(\"#content-text\");\n  const author  = threadEl.querySelector(\"#author-text span\") || threadEl.querySelector(\"#author-text\");\n  const txt = (content?.textContent || \"\").trim();\n  const who = (author?.textContent || \"\").trim();\n  return { txt, who };\n}\n\nfunction passesFilters(text, filters) {\n  const t = (text || \"\").toLowerCase();\n  const {\n    keywords = [],\n    mode = \"any\",\n    qOnly = false,\n    mentions = false,\n    hashtags = false\n  } = filters || {};\n\n  if (qOnly &amp;&amp; !t.includes(\"?\")) return false;\n  if (mentions &amp;&amp; !t.includes(\"@\")) return false;\n  if (hashtags &amp;&amp; !t.includes(\"#\")) return false;\n\n  if (!keywords.length) return true;\n\n  const ks = keywords.map(k =&gt; k.toLowerCase());\n\n  if (mode === \"contains\") {\n    \/\/ treat keywords joined as a phrase if multiple; else single\n    const phrase = ks.join(\" \").trim();\n    return phrase ? t.includes(phrase) : true;\n  }\n\n  if (mode === \"all\") {\n    return ks.every(k =&gt; t.includes(k));\n  }\n\n  \/\/ any\n  return ks.some(k =&gt; t.includes(k));\n}\n\nasync function scrollToAssistId(assistId) {\n  const el = document.querySelector(`[data-ytassist-id=\"${CSS.escape(assistId)}\"]`);\n  if (!el) return false;\n  el.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n  return true;\n}\n\nasync function clickReplyOnThread(threadEl) {\n  \/\/ reply button inside comment action bar\n  const replyBtn =\n    threadEl.querySelector(\"#reply-button-end #button\") ||\n    threadEl.querySelector(\"ytd-button-renderer#reply-button-end button\") ||\n    threadEl.querySelector(\"tp-yt-paper-button#reply-button-end\");\n\n  if (replyBtn) replyBtn.click();\n  else {\n    \/\/ fallback: find button with aria-label\n    const btn = Array.from(threadEl.querySelectorAll(\"button\")).find(b =&gt; \/reply\/i.test(b.textContent || b.getAttribute(\"aria-label\") || \"\"));\n    if (btn) btn.click();\n  }\n\n  \/\/ wait for reply editor\n  const editor = await waitFor(() =&gt;\n    threadEl.querySelector(\"ytd-commentbox #contenteditable-root\") ||\n    threadEl.querySelector(\"ytd-commentbox [contenteditable='true']\") ||\n    threadEl.querySelector(\"ytd-commentbox\")\n  , { timeout: 8000 });\n\n  \/\/ Try to return actual contenteditable root\n  const root =\n    threadEl.querySelector(\"ytd-commentbox #contenteditable-root\") ||\n    threadEl.querySelector(\"ytd-commentbox [contenteditable='true']\");\n  return root || null;\n}\n\nchrome.runtime.onMessage.addListener((msg, sender, sendResponse) =&gt; {\n  (async () =&gt; {\n    try {\n      if (msg?.type === \"SCAN_VIDEOS_FROM_PAGE\") {\n        if (!isChannelVideoGridPage()) {\n          sendResponse({ ok:false, error:\"Go to a channel's \/videos or \/shorts page first.\" });\n          return;\n        }\n\n        \/\/ give the grid a moment to populate\n        await sleep(400);\n\n        \/\/ Encourage scroll to load more before scan (light)\n        for (let i=0;i&lt;3;i++){\n          window.scrollBy({ top: 1200, behavior:\"smooth\" });\n          await sleep(350);\n        }\n\n        const items = collectVideoLinksFromGrid();\n        sendResponse({ ok:true, items });\n        return;\n      }\n\n      if (msg?.type === \"INSERT_TOP_LEVEL_COMMENT_TEXT\") {\n        if (!isWatchPage()) {\n          sendResponse({ ok:false, error:\"Open a YouTube video (\/watch or \/shorts) first.\" });\n          return;\n        }\n\n        const text = (msg.text || \"\").trim();\n        if (!text) {\n          sendResponse({ ok:false, error:\"No text provided.\" });\n          return;\n        }\n\n        await ensureCommentsLoaded();\n\n        const box = await openTopLevelCommentBoxIfNeeded();\n        if (!box) {\n          sendResponse({ ok:false, error:\"Couldn't find the top-level comment box. Scroll to comments and try again.\" });\n          return;\n        }\n\n        setEditableText(box, text);\n        sendResponse({ ok:true });\n        return;\n      }\n\n      if (msg?.type === \"SCAN_COMMENTS_FOR_MATCHES\") {\n        if (!isWatchPage()) {\n          sendResponse({ ok:false, error:\"Open a YouTube video (\/watch or \/shorts) first.\" });\n          return;\n        }\n\n        const ok = await ensureCommentsLoaded();\n        if (!ok) {\n          sendResponse({ ok:false, error:\"Couldn't load comments container. Try scrolling down to comments first.\" });\n          return;\n        }\n\n        \/\/ Attempt to load more a bit\n        for (let i=0;i&lt;4;i++){\n          window.scrollBy({ top: 1200, behavior:\"smooth\" });\n          await sleep(350);\n        }\n\n        const threads = getCommentElements();\n        const matches = [];\n\n        for (const th of threads) {\n          const { txt, who } = extractCommentText(th);\n          if (!txt) continue;\n\n          if (!passesFilters(txt, msg.filters)) continue;\n\n          \/\/ tag element with temporary id for later targeting\n          let id = th.getAttribute(\"data-ytassist-id\");\n          if (!id) {\n            id = genId();\n            th.setAttribute(\"data-ytassist-id\", id);\n          }\n\n          matches.push({\n            assistId: id,\n            author: who,\n            text: txt.slice(0, 240)\n          });\n\n          \/\/ keep list manageable\n          if (matches.length &gt;= 80) break;\n        }\n\n        sendResponse({ ok:true, matches });\n        return;\n      }\n\n      if (msg?.type === \"SCROLL_TO_MATCH\") {\n        const ok = await scrollToAssistId(msg.assistId);\n        sendResponse({ ok });\n        return;\n      }\n\n      if (msg?.type === \"REPLY_AND_INSERT_TEXT\") {\n        if (!isWatchPage()) {\n          sendResponse({ ok:false, error:\"Open a YouTube video first.\" });\n          return;\n        }\n\n        const text = (msg.text || \"\").trim();\n        if (!text) return sendResponse({ ok:false, error:\"No reply text provided.\" });\n\n        const th = document.querySelector(`[data-ytassist-id=\"${CSS.escape(msg.assistId)}\"]`);\n        if (!th) return sendResponse({ ok:false, error:\"That matched comment is no longer available. Re-scan comments.\" });\n\n        th.scrollIntoView({ behavior:\"smooth\", block:\"center\" });\n        await sleep(300);\n\n        const editor = await clickReplyOnThread(th);\n        if (!editor) return sendResponse({ ok:false, error:\"Couldn't open reply editor. Try clicking Reply manually once, then press again.\" });\n\n        setEditableText(editor, text);\n        sendResponse({ ok:true });\n        return;\n      }\n\n      sendResponse({ ok:false, error:\"Unknown message type.\" });\n    } catch (e) {\n      sendResponse({ ok:false, error: String(e?.message || e) });\n    }\n  })();\n\n  return true;\n});\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">8) Load it in Chrome<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Go to <code>chrome:\/\/extensions<\/code><\/li>\n\n\n\n<li>Enable <strong>Developer mode<\/strong><\/li>\n\n\n\n<li>Click <strong>Load unpacked<\/strong><\/li>\n\n\n\n<li>Select the <code>yt-assist-mv3\/<\/code> folder<\/li>\n\n\n\n<li>Open YouTube, then open the <strong>Side panel<\/strong> (Chrome side panel button), choose <strong>YT Assist<\/strong><\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h4 class=\"wp-block-heading\">How to use (your exact use case)<\/h4>\n\n\n\n<h4 class=\"wp-block-heading\">Queue mode (channel scanning)<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Go to: <code>https:\/\/www.youtube.com\/@cracked\/videos<\/code> (or <code>\/shorts<\/code>)<\/li>\n\n\n\n<li>In the side panel \u2192 <strong>Queue<\/strong> \u2192 <strong>Scan this page for videos<\/strong><\/li>\n\n\n\n<li>Then <strong>Open Next<\/strong><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Reply Finder mode (target certain tags\/keywords)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>While on a video page:<\/li>\n\n\n\n<li>Side panel \u2192 <strong>Reply Finder<\/strong><\/li>\n\n\n\n<li>Put keywords like: <code>link, where, how, @, #<\/code><\/li>\n\n\n\n<li>Toggle <strong>Only \u201c?\u201d<\/strong> if you want question-type leads<\/li>\n\n\n\n<li><strong>Scan comments<\/strong><\/li>\n\n\n\n<li>Select multiple matches<\/li>\n\n\n\n<li>Write your reply<\/li>\n\n\n\n<li>Click <strong>Reply + Insert (next selected)<\/strong> (repeat)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">Important guardrail (keeps you from getting cooked)<\/h3>\n\n\n\n<p>Even in assist mode, avoid blasting identical replies. Keep it:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>relevant to what they said<\/li>\n\n\n\n<li>slightly varied<\/li>\n\n\n\n<li>not link-heavy<\/li>\n<\/ul>\n\n\n\n<p>If you want, I can extend this build with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u201cAuto-variation\u201d (rotating openers\/closers)<\/li>\n\n\n\n<li>A per-video \u201calready replied\u201d tracker<\/li>\n\n\n\n<li>A \u201clink every N replies\u201d limiter<\/li>\n\n\n\n<li>A \u201cload more comments\u201d helper button (scroll + wait + re-scan)<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">I got an error, here\u2019s how I worked through it. <\/h5>\n\n\n\n<h5 class=\"wp-block-heading\">the extension installed but side panel doesnt work . tried it on web at .. https:\/\/studio1live.com\/YoutubeXXXengage\/yt-assist-mv3\/sidepanel.html looks nice but neither buttons work local folder on extension , or on web . somethings missing<\/h5>\n\n\n\n<p>Yep \u2014 <strong>two separate things are happening<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>The web version<\/strong> at <code>https:\/\/studio1live.com\/...\/sidepanel.html<\/code> will <em>never<\/em> work as-is, because it calls <strong>Chrome Extension APIs<\/strong> like <code>chrome.tabs<\/code>, <code>chrome.runtime<\/code>, <code>chrome.storage<\/code>. Those only exist inside an installed extension page (chrome-extension:\/\/\u2026), not on a normal website.<\/li>\n\n\n\n<li>In the <strong>installed extension<\/strong>, your buttons can <em>look<\/em> dead if <code>chrome.tabs.sendMessage()<\/code> throws (common when you\u2019re not on a YouTube tab, or the content script didn\u2019t inject). In MV3, an unhandled promise rejection can stop the click handler flow.<\/li>\n<\/ol>\n\n\n\n<p>So what\u2019s \u201cmissing\u201d is mainly:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>a <strong>fallback UI launcher<\/strong> (popup) so you can open it reliably<\/li>\n\n\n\n<li><strong>error handling<\/strong> so you <em>see<\/em> why it\u2019s failing instead of \u201cnothing happens\u201d<\/li>\n\n\n\n<li>plus a quick sanity checklist (YouTube tab active, content script present, etc.)<\/li>\n<\/ul>\n\n\n\n<p>Below is the fix that makes it work <strong>as an extension<\/strong>, and makes failures show a clear message.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">A) Why the web copy won\u2019t work<\/h5>\n\n\n\n<p>Your hosted URL can show the UI, but <strong>no buttons can use <code>chrome.*<\/code><\/strong> because a website cannot access your browser\u2019s extension APIs or your YouTube session. That\u2019s browser security by design.<\/p>\n\n\n\n<p>If you want a web-hosted UI, it must talk to an extension via <strong>native messaging \/ external connect<\/strong>, which is a whole different build.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">B) Make the extension UI open reliably (add popup fallback)<\/h5>\n\n\n\n<h5 class=\"wp-block-heading\">1) Update <code>manifest.json<\/code><\/h5>\n\n\n\n<p>Add <code>default_popup<\/code> so clicking the extension icon opens the same UI even if side panel isn\u2019t enabled\/visible:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"name\": \"YT Assist (Queue + Reply Finder) - MV3\",\n  \"description\": \"Assist-mode helper for scanning YouTube pages, queueing videos, and inserting comments\/replies (no auto-submit).\",\n  \"version\": \"1.0.1\",\n  \"manifest_version\": 3,\n\n  \"permissions\": [\"storage\", \"tabs\", \"scripting\", \"activeTab\"],\n  \"host_permissions\": [\"https:\/\/www.youtube.com\/*\"],\n\n  \"background\": { \"service_worker\": \"service_worker.js\" },\n\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https:\/\/www.youtube.com\/*\"],\n      \"js\": [\"content_script.js\"],\n      \"run_at\": \"document_idle\"\n    }\n  ],\n\n  \"side_panel\": { \"default_path\": \"sidepanel.html\" },\n\n  \"action\": {\n    \"default_title\": \"YT Assist\",\n    \"default_popup\": \"sidepanel.html\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Then go to <code>chrome:\/\/extensions<\/code> \u2192 hit <strong>Reload<\/strong> on the extension.<\/p>\n\n\n\n<p>Now you can open the UI by clicking the extension icon (works everywhere).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">C) Fix \u201cbuttons do nothing\u201d (add hard error handling)<\/h5>\n\n\n\n<p>Replace your <code>sidepanel.js<\/code> with this <strong>drop-in patched<\/strong> version (same features, but it <em>alerts you<\/em> when the content script isn\u2019t reachable):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const K = {\n  queue: \"ytassist_queue\",\n  done: \"ytassist_done\",\n  templates: \"ytassist_templates\",\n  settings: \"ytassist_settings\"\n};\n\nconst $ = (sel) =&gt; document.querySelector(sel);\nconst $$ = (sel) =&gt; Array.from(document.querySelectorAll(sel));\n\nfunction sleep(ms){ return new Promise(r=&gt;setTimeout(r,ms)); }\n\nfunction showErr(msg){\n  console.error(\"[YTAssist UI]\", msg);\n  alert(msg);\n}\n\nasync function getActiveTab() {\n  const tabs = await chrome.tabs.query({ active: true, currentWindow: true });\n  return tabs?.[0] || null;\n}\n\nasync function sendToActiveTab(payload) {\n  try {\n    const tab = await getActiveTab();\n    if (!tab?.id) return { ok:false, error:\"No active tab found.\" };\n\n    \/\/ If you're not on youtube.com, the content script won't exist\n    if (!String(tab.url || \"\").startsWith(\"https:\/\/www.youtube.com\/\")) {\n      return { ok:false, error:\"Open a YouTube tab first (youtube.com), then try again.\" };\n    }\n\n    \/\/ If no receiver exists, Chrome throws. Catch it and show a friendly error.\n    const res = await chrome.tabs.sendMessage(tab.id, payload);\n    return res || { ok:false, error:\"No response from content script.\" };\n  } catch (e) {\n    return {\n      ok:false,\n      error:\n        \"Could not reach the YouTube helper script.\\n\\n\" +\n        \"Fix checklist:\\n\" +\n        \"1) Make sure the ACTIVE tab is a youtube.com page.\\n\" +\n        \"2) Reload the YouTube tab (Ctrl+R) after installing\/reloading the extension.\\n\" +\n        \"3) On chrome:\/\/extensions \u2192 Inspect views \u2192 Service worker \/ errors.\\n\\n\" +\n        \"Technical: \" + (e?.message || String(e))\n    };\n  }\n}\n\nasync function bg(msg) {\n  try {\n    return await chrome.runtime.sendMessage(msg);\n  } catch (e) {\n    return { ok:false, error: \"Background not responding: \" + (e?.message || String(e)) };\n  }\n}\n\nfunction setTab(name){\n  $$(\".tab\").forEach(b =&gt; b.classList.toggle(\"active\", b.dataset.tab === name));\n  $$(\".panel\").forEach(p =&gt; p.classList.toggle(\"active\", p.id === `panel-${name}`));\n}\n\n$$(\".tab\").forEach(b =&gt; b.addEventListener(\"click\", () =&gt; setTab(b.dataset.tab)));\n\nlet cooldownTimer = null;\nlet cooldownRemaining = 0;\n\nfunction startCooldown(seconds){\n  clearInterval(cooldownTimer);\n  cooldownRemaining = seconds;\n  $(\"#cooldownStatus\").textContent = `Cooldown: ${cooldownRemaining}s`;\n  cooldownTimer = setInterval(() =&gt; {\n    cooldownRemaining--;\n    if (cooldownRemaining &lt;= 0) {\n      clearInterval(cooldownTimer);\n      $(\"#cooldownStatus\").textContent = \"Cooldown finished.\";\n      return;\n    }\n    $(\"#cooldownStatus\").textContent = `Cooldown: ${cooldownRemaining}s`;\n  }, 1000);\n}\n\nfunction escapeHtml(s=\"\"){\n  return s.replace(\/[&amp;&lt;&gt;\"']\/g, c =&gt; ({'&amp;':'&amp;amp;','&lt;':'&amp;lt;','&gt;':'&amp;gt;','\"':'&amp;quot;',\"'\":'&amp;#39;'}[c]));\n}\n\nfunction renderQueue(queue, done){\n  const total = queue.length;\n  const doneCount = queue.filter(x =&gt; done?.[x.url]).length;\n  $(\"#queueMeta\").textContent = `${total} items \u2022 ${doneCount} done`;\n\n  const wrap = $(\"#queueList\");\n  wrap.innerHTML = \"\";\n\n  queue.slice(0, 200).forEach((it) =&gt; {\n    const isDone = !!done?.[it.url];\n    const el = document.createElement(\"div\");\n    el.className = \"item\";\n    el.innerHTML = `\n      &lt;div class=\"t\"&gt;${escapeHtml(it.title || it.url)}&lt;\/div&gt;\n      &lt;div class=\"s\"&gt;${escapeHtml(it.url)}&lt;\/div&gt;\n      &lt;div class=\"actions\"&gt;\n        &lt;span class=\"badge\"&gt;${isDone ? \"DONE\" : \"PENDING\"}&lt;\/span&gt;\n        &lt;button class=\"btn ghost\" data-open=\"${escapeHtml(it.url)}\"&gt;Open&lt;\/button&gt;\n        &lt;button class=\"btn ghost\" data-done=\"${escapeHtml(it.url)}\"&gt;Mark done&lt;\/button&gt;\n      &lt;\/div&gt;\n    `;\n    wrap.appendChild(el);\n  });\n\n  wrap.querySelectorAll(\"[data-open]\").forEach(btn =&gt; btn.addEventListener(\"click\", async () =&gt; {\n    const url = btn.getAttribute(\"data-open\");\n    const tab = await getActiveTab();\n    if (!tab?.id) return showErr(\"No active tab.\");\n    await chrome.tabs.update(tab.id, { url });\n  }));\n\n  wrap.querySelectorAll(\"[data-done]\").forEach(btn =&gt; btn.addEventListener(\"click\", async () =&gt; {\n    const url = btn.getAttribute(\"data-done\");\n    const r = await bg({ type:\"MARK_DONE\", url });\n    if (!r?.ok) return showErr(r?.error || \"Failed to mark done.\");\n    await refresh();\n  }));\n}\n\nfunction renderMatches(matches){\n  $(\"#rfMeta\").textContent = `${matches.length} matches found. Select some, then Reply + Insert.`;\n\n  const wrap = $(\"#matchList\");\n  wrap.innerHTML = \"\";\n\n  matches.forEach((m) =&gt; {\n    const el = document.createElement(\"div\");\n    el.className = \"item\";\n    el.innerHTML = `\n      &lt;label class=\"chk\"&gt;\n        &lt;input type=\"checkbox\" class=\"mchk\" data-id=\"${escapeHtml(m.assistId)}\" checked \/&gt;\n        &lt;span class=\"t\"&gt;${escapeHtml(m.author || \"Unknown\")}&lt;\/span&gt;\n      &lt;\/label&gt;\n      &lt;div class=\"s\"&gt;${escapeHtml(m.text || \"\")}&lt;\/div&gt;\n      &lt;div class=\"actions\"&gt;\n        &lt;button class=\"btn ghost\" data-scroll=\"${escapeHtml(m.assistId)}\"&gt;Scroll&lt;\/button&gt;\n      &lt;\/div&gt;\n    `;\n    wrap.appendChild(el);\n  });\n\n  wrap.querySelectorAll(\"[data-scroll]\").forEach(btn =&gt; btn.addEventListener(\"click\", async () =&gt; {\n    const id = btn.getAttribute(\"data-scroll\");\n    const r = await sendToActiveTab({ type:\"SCROLL_TO_MATCH\", assistId:id });\n    if (!r?.ok) showErr(r?.error || \"Scroll failed.\");\n  }));\n}\n\nasync function refresh(){\n  const res = await bg({ type:\"GET_STATE\" });\n  if (!res?.ok) return showErr(res?.error || \"Failed to load state.\");\n\n  const st = res.state;\n  const queue = st[K.queue] || [];\n  const done  = st[K.done]  || {};\n  const templates = st[K.templates] || { comments:[], replies:[] };\n  const settings  = st[K.settings] || { cooldownSeconds:60 };\n\n  $(\"#cooldown\").value = settings.cooldownSeconds ?? 60;\n\n  renderQueue(queue, done);\n  $(\"#tplComments\").value = (templates.comments || []).join(\"\\n\");\n  $(\"#tplReplies\").value  = (templates.replies  || []).join(\"\\n\");\n}\n\n$(\"#btnRefreshState\").addEventListener(\"click\", refresh);\n\n$(\"#btnScanVideos\").addEventListener(\"click\", async () =&gt; {\n  const r = await sendToActiveTab({ type:\"SCAN_VIDEOS_FROM_PAGE\" });\n  if (!r?.ok) return showErr(r?.error || \"Scan failed.\");\n\n  const store = await bg({ type:\"STORE_QUEUE_APPEND\", items: r.items });\n  if (!store?.ok) return showErr(store?.error || \"Could not store queue.\");\n  await refresh();\n});\n\n$(\"#btnOpenNext\").addEventListener(\"click\", async () =&gt; {\n  const r = await bg({ type:\"QUEUE_POP_NEXT\" });\n  if (!r?.ok || !r.next?.url) return showErr(\"No next item found.\");\n\n  const tab = await getActiveTab();\n  if (!tab?.id) return showErr(\"No active tab.\");\n  await chrome.tabs.update(tab.id, { url: r.next.url });\n});\n\n$(\"#btnMarkDone\").addEventListener(\"click\", async () =&gt; {\n  const tab = await getActiveTab();\n  if (!tab?.url) return showErr(\"No active tab URL.\");\n  const r = await bg({ type:\"MARK_DONE\", url: tab.url });\n  if (!r?.ok) return showErr(r?.error || \"Failed to mark done.\");\n  await refresh();\n});\n\n$(\"#btnClearDone\").addEventListener(\"click\", async () =&gt; {\n  const r = await bg({ type:\"SET_STATE\", patch: { [K.done]: {} }});\n  if (!r?.ok) return showErr(r?.error || \"Failed to clear done.\");\n  await refresh();\n});\n\n$(\"#btnStartCooldown\").addEventListener(\"click\", async () =&gt; {\n  const seconds = parseInt($(\"#cooldown\").value || \"60\", 10);\n  startCooldown(Math.max(10, seconds));\n  const r = await bg({ type:\"SET_STATE\", patch: { [K.settings]: { cooldownSeconds: Math.max(10, seconds) } }});\n  if (!r?.ok) showErr(r?.error || \"Failed to save settings.\");\n});\n\n$(\"#btnCopyComment\").addEventListener(\"click\", async () =&gt; {\n  try { await navigator.clipboard.writeText($(\"#commentBox\").value || \"\"); }\n  catch { showErr(\"Clipboard blocked. Try copying manually.\"); }\n});\n\n$(\"#btnInsertComment\").addEventListener(\"click\", async () =&gt; {\n  const text = ($(\"#commentBox\").value || \"\").trim();\n  if (!text) return showErr(\"Comment box is empty.\");\n  const r = await sendToActiveTab({ type:\"INSERT_TOP_LEVEL_COMMENT_TEXT\", text });\n  if (!r?.ok) showErr(r?.error || \"Insert failed.\");\n});\n\n$(\"#btnScanComments\").addEventListener(\"click\", async () =&gt; {\n  const keywords = ($(\"#rfKeywords\").value || \"\").split(\",\").map(s=&gt;s.trim()).filter(Boolean);\n  const mode = $(\"#rfMode\").value;\n  const qOnly = $(\"#rfQOnly\").checked;\n  const mentions = $(\"#rfMentions\").checked;\n  const hashtags = $(\"#rfHashtags\").checked;\n\n  const r = await sendToActiveTab({\n    type:\"SCAN_COMMENTS_FOR_MATCHES\",\n    filters: { keywords, mode, qOnly, mentions, hashtags }\n  });\n\n  if (!r?.ok) return showErr(r?.error || \"Comment scan failed.\");\n  renderMatches(r.matches || []);\n});\n\n$(\"#btnSelectAll\").addEventListener(\"click\", () =&gt; {\n  $$(\"#matchList .mchk\").forEach(c =&gt; c.checked = true);\n});\n$(\"#btnSelectNone\").addEventListener(\"click\", () =&gt; {\n  $$(\"#matchList .mchk\").forEach(c =&gt; c.checked = false);\n});\n\n$(\"#btnCopyReply\").addEventListener(\"click\", async () =&gt; {\n  try { await navigator.clipboard.writeText($(\"#replyBox\").value || \"\"); }\n  catch { showErr(\"Clipboard blocked. Try copying manually.\"); }\n});\n\n$(\"#btnInsertReplyNext\").addEventListener(\"click\", async () =&gt; {\n  const text = ($(\"#replyBox\").value || \"\").trim();\n  if (!text) return showErr(\"Reply box is empty.\");\n\n  const selected = $$(\"#matchList .mchk\").filter(c =&gt; c.checked).map(c =&gt; c.dataset.id);\n  if (!selected.length) return showErr(\"Select at least one match.\");\n\n  const id = selected[0];\n  const r = await sendToActiveTab({ type:\"REPLY_AND_INSERT_TEXT\", assistId:id, text });\n  if (!r?.ok) return showErr(r?.error || \"Reply insert failed.\");\n\n  const chk = $(`#matchList .mchk[data-id=\"${CSS.escape(id)}\"]`);\n  if (chk) chk.checked = false;\n});\n\n$(\"#btnSaveTemplates\").addEventListener(\"click\", async () =&gt; {\n  const comments = ($(\"#tplComments\").value || \"\").split(\"\\n\").map(s=&gt;s.trim()).filter(Boolean);\n  const replies  = ($(\"#tplReplies\").value  || \"\").split(\"\\n\").map(s=&gt;s.trim()).filter(Boolean);\n\n  const r = await bg({ type:\"SET_STATE\", patch: { [K.templates]: { comments, replies } }});\n  if (!r?.ok) return showErr(r?.error || \"Failed to save templates.\");\n  alert(\"Templates saved.\");\n});\n\n$(\"#btnLoadTemplates\").addEventListener(\"click\", refresh);\n\nrefresh();\n<\/code><\/pre>\n\n\n\n<p>Reload extension after replacing.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">D) Quick checklist to test (takes 30 seconds)<\/h5>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open a YouTube tab:\n<ul class=\"wp-block-list\">\n<li><code>https:\/\/www.youtube.com\/@cracked\/videos<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Reload that tab<\/strong> (Ctrl+R) after reloading the extension<\/li>\n\n\n\n<li>Click your extension icon \u2192 UI opens (popup)<\/li>\n\n\n\n<li>Press <strong>Scan this page for videos<\/strong>\n<ul class=\"wp-block-list\">\n<li>If it fails, you\u2019ll now get a clear alert telling you why.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h5 class=\"wp-block-heading\">E) Where to see the real error (if it still fails)<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>chrome:\/\/extensions<\/code> \u2192 your extension \u2192 <strong>Inspect views<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u201cservice worker\u201d (background)<\/li>\n\n\n\n<li>(and if visible) the panel\/popup page<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Also:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>On YouTube tab \u2192 F12 \u2192 Console \u2192 look for <code>[YTAssist]<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<p>If you paste me the exact alert message you get after this patch (even 1 line), I\u2019ll pinpoint the exact cause (usually: not on youtube tab, content script not injected, or YouTube page type mismatch like \u201cHome\u201d vs \u201cVideos\u201d).<\/p>\n\n\n\n<p>write a quickmet description for youtube assit ext tool<\/p>\n\n\n\n<p>Here are a few <strong>quick, clean description options<\/strong> you can use (pick the tone you want). These are sized to work for a Chrome extension listing or internal project page.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">Option 1 \u2014 Clean &amp; Professional<\/h3>\n\n\n\n<p><strong>YouTube Assist<\/strong> is a human-in-the-loop engagement tool that helps creators and marketers efficiently interact with YouTube content. It scans channel pages and video comments, builds a smart queue, and assists with inserting comments or replies \u2014 while keeping the user in full control. No auto-posting. No bots. Just faster, smarter engagement.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">Option 2 \u2014 Marketing-Focused<\/h3>\n\n\n\n<p><strong>YouTube Assist<\/strong> helps you engage faster on YouTube without triggering spam filters. Scan channels, queue videos, find comments by keyword or tag, and reply with pre-written templates \u2014 all in assist mode so <em>you<\/em> decide when to post. Designed for safe, organic outreach and audience growth.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">Option 3 \u2014 Developer \/ Power-User Tone<\/h3>\n\n\n\n<p><strong>YouTube Assist<\/strong> is an MV3 Chrome extension that provides assisted YouTube engagement. Features include channel scanning, video queues, keyword-based comment discovery, and comment\/reply insertion \u2014 all without automated submission. Built for creators, marketers, and researchers who want speed without violating platform behavior norms.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">Option 4 \u2014 Short Store-Ready Blurb (Recommended)<\/h3>\n\n\n\n<p>Engage smarter on YouTube. <strong>YouTube Assist<\/strong> helps you scan channels, queue videos, find relevant comments by keyword or tag, and insert replies using templates \u2014 all in safe assist mode. No auto-posting, no bots, just faster human engagement.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">Ultra-Short (Tagline)<\/h3>\n\n\n\n<p><strong>Human-assisted YouTube engagement \u2014 fast, safe, and in your control.<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<p>If you want, I can also:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Write the <strong>Chrome Web Store long description<\/strong><\/li>\n\n\n\n<li>Generate <strong>feature bullets<\/strong><\/li>\n\n\n\n<li>Add a <strong>\u201cNot a bot \/ Assist Mode\u201d compliance disclaimer<\/strong><\/li>\n\n\n\n<li>Brand it under <strong>Studio1Live \/ YouTubeXXXengage<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Author of this page give reader authority to take this code and make their own, modify as you like, rebrand and sale as you like, you have everything you need. <\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/fixyourowncredit.studio1live.com\/downloads\/product\/youtube-assist\/\">download tool <\/a><\/div>\n<\/div>\n\n\n\n<!-- ========================= -->\n<!-- EDUCATIONAL RESOURCES & TOOLS -->\n<!-- ========================= -->\n<section class=\"s1l-blog-footer\">\n  <hr>\n\n  <h2>Learn More &amp; Take Action<\/h2>\n\n  <p>\n    Understanding money, credit, and financial systems is the first step toward\n    reclaiming economic power. If you found this breakdown helpful, explore the\n    tools and resources below to continue building financial literacy, credit\n    strength, and digital independence.\n  <\/p>\n\n  <ul class=\"s1l-resource-links\">\n    <li>\n      \ud83d\udd39 <a href=\"https:\/\/studio1live.com\/templates\/\" target=\"_blank\" rel=\"noopener\">\n        Studio1Live Templates Hub\n      <\/a><br>\n      <small>Ready-to-use website templates, tools, and digital builds for businesses,\n      creators, and entrepreneurs.<\/small>\n    <\/li>\n\n    <li>\n      \ud83d\udd39 <a href=\"https:\/\/studio1live.com\/templates\/blog\" target=\"_blank\" rel=\"noopener\">\n        Studio1Live Blog Templates\n      <\/a><br>\n      <small>Pre-built blog and content layouts designed for SEO, authority, and monetization.<\/small>\n    <\/li>\n\n    <li>\n      \ud83d\udd39 <a href=\"https:\/\/studio1live.com\" target=\"_blank\" rel=\"noopener\">\n        Studio1Live.com\n      <\/a><br>\n      <small>The main hub for digital tools, educational resources, and independent platforms.<\/small>\n    <\/li>\n\n    <li>\n      \ud83d\udd39 <a href=\"https:\/\/studio1live.com\/legal\" target=\"_blank\" rel=\"noopener\">\n        Legal AI Coach\n      <\/a><br>\n      <small>Educational legal tools and document guidance for self-advocacy and compliance.<\/small>\n    <\/li>\n\n    <li>\n      \ud83d\udd39 <a href=\"https:\/\/studio1live.com\/picks\" target=\"_blank\" rel=\"noopener\">\n        Studio1Live Picks &amp; Data Tools\n      <\/a><br>\n      <small>Data-driven insights, analytics, and independent research tools.<\/small>\n    <\/li>\n  <\/ul>\n\n  <p>\n    <strong>Disclaimer:<\/strong> This content is for educational purposes only and does not\n    constitute financial or legal advice. Always conduct your own research or consult\n    qualified professionals before making financial decisions.\n  <\/p>\n\n  <p class=\"s1l-signoff\">\n    \u270d\ufe0f Published by <strong>Studio1Live<\/strong> \u2014 building tools, knowledge, and systems\n    for economic independence.\n  <\/p>\n<\/section>\n\n\n\n<p>#CFB #ConferenceChampionship #CFP #Miami #ACC #SEC #Big12 #CollegeFootballPlayoff<\/p>\n\n\n\n<p><strong>Shoutouts:<\/strong>\u00a0@CFBPlayoff, @ESPNCFB, @CollegeGameDay, #CFB, #ConferenceChampionship, #CollegeFootballPlayoff<\/p>\n\n\n\n<p><strong>Follow:<\/strong>\u00a0@herudaguru for more unfiltered college football breakdowns, rants, and picks.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/studio1live.com\/picks\" target=\"_blank\" rel=\"noreferrer noopener\">More picks &amp; articles on Studio1Live<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Support the Studio1Live Sports Family<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Download our Basketball App (Live Scores &amp; News):<\/strong>\u00a0<a href=\"https:\/\/apps.apple.com\/us\/app\/basketball-live-scores-news\/id6468638694\" target=\"_blank\" rel=\"noreferrer noopener\">iOS App Store<\/a>\u00a0|\u00a0<a href=\"https:\/\/play.google.com\/store\/apps\/details?id=com.it.basktball&amp;pli=1\" target=\"_blank\" rel=\"noreferrer noopener\">Google Play<\/a><\/li>\n\n\n\n<li><strong>Play poker online &amp; win big:<\/strong>\u00a0<a href=\"https:\/\/orgsignup.blackchippoker.eu\/RAF-BCP-HERUDAGURU\/https%3A%2F%2Fplay.blackchippoker.eu\" target=\"_blank\" rel=\"noreferrer noopener\">BlackChip Poker \u2013 HeruDaGuru Link<\/a><\/li>\n\n\n\n<li><strong>Free daily picks:<\/strong>\u00a0<a href=\"https:\/\/studio1live.com\/picks\" target=\"_blank\" rel=\"noreferrer noopener\">Studio1Live Picks Page<\/a><\/li>\n\n\n\n<li><strong>Soccer blog &amp; analysis:<\/strong>\u00a0<a href=\"https:\/\/studio1live.com\/soccer\/#\" target=\"_blank\" rel=\"noreferrer noopener\">Studio1Live Soccer Blog<\/a><\/li>\n\n\n\n<li><strong>Soccer odds &amp; sportsbook-style view:<\/strong>\u00a0<a href=\"https:\/\/sportspick.site\/app-sports\/#\/sportsbook\/odds\" target=\"_blank\" rel=\"noreferrer noopener\">SportsPick \u2013 Soccer Odds Board<\/a><\/li>\n\n\n\n<li><strong>Deep-dive soccer stats &amp; datasets:<\/strong>\u00a0<a href=\"https:\/\/ras.football\/\" target=\"_blank\" rel=\"noreferrer noopener\">RAS.Football<\/a>\u00a0|\u00a0<a href=\"https:\/\/sports-statistics.com\/sports-data\/soccer-datasets\/\" target=\"_blank\" rel=\"noreferrer noopener\">Soccer Data Sets<\/a><\/li>\n\n\n\n<li><strong>Watch the \u201cAfrica Is First Civilization\u201d Debate:<\/strong>\u00a0<a href=\"https:\/\/youtu.be\/zlaT6mStfhM?si=dBPlDRfCotwvJ8U9\" target=\"_blank\" rel=\"noreferrer noopener\">HeruDaGuru vs The Voice of the Aborigines (YouTube)<\/a><\/li>\n\n\n\n<li><strong>Book \u2013 What happens after you die? Will you be reborn?<\/strong>\u00a0<a href=\"https:\/\/www.amazon.com\/dp\/B0DZ754846\" target=\"_blank\" rel=\"noreferrer noopener\">Get the book on Amazon<\/a>\u00a0\u2013 or follow the author page:\u00a0<a href=\"https:\/\/www.amazon.com\/author\/herudaguru\" target=\"_blank\" rel=\"noreferrer noopener\">amazon.com\/author\/herudaguru<\/a><\/li>\n\n\n\n<li><strong>Help our Jr Olympians reach their goals:<\/strong>\u00a0<a href=\"https:\/\/gofund.me\/27030a17\" target=\"_blank\" rel=\"noreferrer noopener\">Jr Olympians GoFundMe \u2013 Travel &amp; Training Support<\/a><\/li>\n\n\n\n<li><strong>Aloha Fly Apparel \u2013 coming to Florida:<\/strong>\u00a0Hawaii\u2019s top sports &amp; swimwear brand expanding to Florida. Bamboo dresses, linen fits, active leggings, mesh tops, seamless bikinis, sports shorts &amp; more (Aloha Fly collection launch coming soon).<\/li>\n<\/ul>\n\n\n\n<p><strong>Tags:<\/strong>\u00a0#herudaguru\u00a0#soccergod\u00a0#studio1live\u00a0#MiamiHurricanes\u00a0#CFP\u00a0#CollegeFootball\u00a0#CFPCommittee\u00a0#SportsPicks\u00a0#SportsBetting<strong>Community Shoutouts &amp; YouTube Tags:<\/strong><\/p>\n\n\n\n<p>@AngelSerrano, @MrOvadose101, @Hurricane357, @Normal\u00a0Guy, @Slug\u00a0Bruce, @Black\u00a0Panther\u00a0JackieBrown, @Darvis\u00a0Baylock, @Aniyunwiya_Nike903, @FOH, @Angel\u00a0Serrano, @Timothy\u00a0Brown:Tru-Shu:\u00a0Shu, @KillSwitch\u00a0R6, @Dre\u00a0Light, @Saint_Louis, @Kosmon\u00a0Cal\u00a0tv, @Crisjamie\u00a0Mac, @Nonya\u00a0Bidness, @Shaquile\u00a0Oatmeal, @TassCo\u00a0The\u00a0C.E.O, @JJ\u00a0The\u00a0Enlightened\u00a0One, @Jeramiah\u00a0Myers, @Sunshine, @inthehighest1, @Siemon\u00a0The\u00a0atheistkilla, @James\u00a0Smith, @SunofdeBeach, @Vitamin\u00a0C, @Mohamed\u00a0Hussain, @Anthony\u00a0Manzano, @B\u00a0Correa, @818CaliCane, @Jorge\u00a0Mayorga, @Rich\u00a0Andrews, @El_rico88, @Scuba\u00a0Steve, @Ryder\u00a0Boy, @jrgodfatha88, @ChiTown\u00a0Cane, @The\u00a0Dulci\u00a0Effect, @Live\u00a0and\u00a0Learn, @IcebergSlim38, @SipAmazin, @Yanik-\u00a0Alahim\u00a0D\u2019orsey\u00a0Bey, @KARMACOMING2C0113CT, @Zac\u00a0Pac\u00a0\u2013\u00a0Dizzies\u00a0Be\u00a0Dizzy, @Bailioso, @Beast\u00a0Of\u00a0Burden, @MoneyLineRay, @KDUB\u2019S\u00a0WORLD, @blackwhileindian, @SHAWN\u00a0P\u00a0DIDDY, @BIG\u00a0CHIEF\u00a0TOILET\u00a0PAPER, @LACONIC, @Master\u00a0of\u00a0Self, @Big\u00a0Chief\u00a0All\u00a0American, @Michelle\u00a0R, @I\u00a0Am\u00a0Scorpion, @PatrickGeneLeBlancHardy, @Black\u00a0Hole\u00a0Sun, @Motivated\u00a0Dedicated, @EL\u00a0Gumbo, @Migo_critt, @Coinlito\u2019s\u00a0Way, @David\u00a0Williams, @KMS_929, @Talking\u00a0Trash\u00a0With\u00a0the\u00a0Steelers\u00a0Gang!, @Daniel\u00a0Berri\u00a0Sports\u00a0Highlights, @Shard, @Billy\u00a0DeLuLu, @BangkokVice<\/p>\n<\/body>","protected":false},"excerpt":{"rendered":"<p>Human-assisted YouTube engagement \u2014 fast, safe, and in your control Engage smarter on YouTube. YouTube Assist helps you scan channels, queue videos, find relevant comments by keyword or tag, and insert replies using templates \u2014 all in safe assist mode. No auto-posting, no bots, just faster human engagement. I had a question for A.I. and &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/fixyourowncredit.studio1live.com\/downloads\/automation-on-a-logged-in-account\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Automation on a logged-in account.&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1115","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/posts\/1115","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/comments?post=1115"}],"version-history":[{"count":2,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/posts\/1115\/revisions"}],"predecessor-version":[{"id":1118,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/posts\/1115\/revisions\/1118"}],"wp:attachment":[{"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/media?parent=1115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/categories?post=1115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/tags?post=1115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}