channel-worker 2.5.26 → 2.5.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/warmup_youtube.js +25 -26
package/package.json
CHANGED
|
@@ -114,36 +114,34 @@ async function collectResultVideoUrls(page) {
|
|
|
114
114
|
// skippable ad; non-skippable ads have no button (we wait them out). Multiple
|
|
115
115
|
// pre-rolls can chain, so this is called every tick of the watch loop.
|
|
116
116
|
async function trySkipAd(page) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
for (const b of document.querySelectorAll('button, .ytp-ad-skip-button-text')) {
|
|
133
|
-
const t = (b.innerText || b.textContent || '').trim();
|
|
134
|
-
if (t && phrases.test(t) && b.offsetParent !== null) { b.click(); return true; }
|
|
117
|
+
// Use Playwright's real .click() (trusted pointer event) — a synthetic
|
|
118
|
+
// el.click() from page.evaluate is ignored by YouTube's player, so the ad
|
|
119
|
+
// never actually skipped (saw 52 "skips" with the ad still playing). The
|
|
120
|
+
// skip button only becomes clickable ~5s into the ad; an early click times
|
|
121
|
+
// out → return false → retried next tick.
|
|
122
|
+
const sels = [
|
|
123
|
+
'.ytp-ad-skip-button-modern',
|
|
124
|
+
'.ytp-ad-skip-button',
|
|
125
|
+
'.ytp-skip-ad-button',
|
|
126
|
+
'.ytp-ad-skip-button-container button',
|
|
127
|
+
];
|
|
128
|
+
for (const s of sels) {
|
|
129
|
+
const loc = page.locator(s).first();
|
|
130
|
+
if (await loc.isVisible().catch(() => false)) {
|
|
131
|
+
try { await loc.click({ timeout: 1500 }); return true; } catch { /* not yet clickable */ }
|
|
135
132
|
}
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
138
135
|
}
|
|
139
136
|
|
|
140
|
-
// True while an ad is playing
|
|
141
|
-
//
|
|
137
|
+
// True while an ad is ACTUALLY playing (pre/mid-roll). Relies on the player's
|
|
138
|
+
// `ad-showing` class — the canonical signal YouTube toggles only during ad
|
|
139
|
+
// playback. Do NOT key off .ytp-ad-module (a persistent container that exists
|
|
140
|
+
// even with no ad → false positive that pinned the watch loop at "0s real").
|
|
142
141
|
async function isAdShowing(page) {
|
|
143
142
|
return page.evaluate(() => {
|
|
144
143
|
const player = document.querySelector('#movie_player, .html5-video-player');
|
|
145
|
-
|
|
146
|
-
return !!document.querySelector('.ytp-ad-player-overlay, .ytp-ad-module, .ad-showing');
|
|
144
|
+
return !!(player && player.classList.contains('ad-showing'));
|
|
147
145
|
}).catch(() => false);
|
|
148
146
|
}
|
|
149
147
|
|
|
@@ -165,7 +163,7 @@ async function watchVideo(page, url, minSec, maxSec, log) {
|
|
|
165
163
|
log('info', `[warmup] watching ${url.slice(-11)} for ~${Math.round(watchMs / 1000)}s of REAL video (skipping ads)`);
|
|
166
164
|
|
|
167
165
|
const TICK = 1000;
|
|
168
|
-
const MAX_AD_WAIT_MS =
|
|
166
|
+
const MAX_AD_WAIT_MS = 60_000; // cap total ad-waiting so a non-skippable ad reel can't hang the session
|
|
169
167
|
let realWatched = 0; // ms of actual (non-ad) playback counted
|
|
170
168
|
let adWaited = 0; // ms spent sitting through/again skipping ads
|
|
171
169
|
let scrolled = false;
|
|
@@ -185,7 +183,8 @@ async function watchVideo(page, url, minSec, maxSec, log) {
|
|
|
185
183
|
await page.waitForTimeout(TICK);
|
|
186
184
|
}
|
|
187
185
|
if (skips) log('info', `[warmup] ${url.slice(-11)} — skipped ${skips} ad tick(s), real watch ${Math.round(realWatched/1000)}s`);
|
|
188
|
-
|
|
186
|
+
// Only count as a watched video if real (non-ad) content actually played.
|
|
187
|
+
return realWatched > 0;
|
|
189
188
|
} catch (e) {
|
|
190
189
|
log('warn', `[warmup] watch failed (${url.slice(-11)}): ${String(e.message || e).slice(0, 100)}`);
|
|
191
190
|
return false;
|