nodebb-plugin-ezoic-infinite 1.9.4 → 1.9.6
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/library.js +28 -13
- package/package.json +1 -1
- package/public/client.js +7 -6
package/library.js
CHANGED
|
@@ -101,6 +101,7 @@ async function getSettings() {
|
|
|
101
101
|
messageIntervalPosts: Math.max(1, parseInt(s.messageIntervalPosts, 10) || 3),
|
|
102
102
|
excludedGroups: normalizeExcludedGroups(s.excludedGroups),
|
|
103
103
|
};
|
|
104
|
+
data.excludedSet = new Set(data.excludedGroups);
|
|
104
105
|
if (_settingsGen === gen) {
|
|
105
106
|
_settingsCacheAt = Date.now();
|
|
106
107
|
_settingsCache = data;
|
|
@@ -113,7 +114,7 @@ async function getSettings() {
|
|
|
113
114
|
return _settingsInflight;
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
async function isUserExcluded(uid, excludedGroups) {
|
|
117
|
+
async function isUserExcluded(uid, excludedGroups, excludedSet) {
|
|
117
118
|
if (!uid || !excludedGroups.length) return false;
|
|
118
119
|
|
|
119
120
|
const key = `${uid}|${excludedGroups.join('|')}`;
|
|
@@ -121,16 +122,21 @@ async function isUserExcluded(uid, excludedGroups) {
|
|
|
121
122
|
const hit = _excludeCache.get(key);
|
|
122
123
|
if (hit && (t - hit.at) < EXCLUDE_TTL) return hit.value;
|
|
123
124
|
|
|
124
|
-
const excludedSet = new Set(excludedGroups);
|
|
125
125
|
const userGroups = await groups.getUserGroups([uid]);
|
|
126
126
|
const value = (userGroups[0] || []).some(g => excludedSet.has(g.name));
|
|
127
127
|
|
|
128
128
|
_excludeCache.set(key, { value, at: Date.now() });
|
|
129
129
|
if (_excludeCache.size > 1000) {
|
|
130
|
-
|
|
131
|
-
for (const k of _excludeCache
|
|
132
|
-
if (
|
|
133
|
-
|
|
130
|
+
const expire = Date.now() - EXCLUDE_TTL;
|
|
131
|
+
for (const [k, v] of _excludeCache) {
|
|
132
|
+
if (v.at < expire) _excludeCache.delete(k);
|
|
133
|
+
}
|
|
134
|
+
if (_excludeCache.size > 900) {
|
|
135
|
+
let n = 100;
|
|
136
|
+
for (const k of _excludeCache.keys()) {
|
|
137
|
+
if (!n--) break;
|
|
138
|
+
_excludeCache.delete(k);
|
|
139
|
+
}
|
|
134
140
|
}
|
|
135
141
|
}
|
|
136
142
|
|
|
@@ -148,16 +154,13 @@ function clearCaches() {
|
|
|
148
154
|
_excludeCache.clear();
|
|
149
155
|
_inlineCfgNormal = null;
|
|
150
156
|
_inlineCfgExcluded = null;
|
|
151
|
-
|
|
152
|
-
_allGroupsCache = null;
|
|
153
|
-
_allGroupsCacheAt = 0;
|
|
154
|
-
_allGroupsInflight = null;
|
|
157
|
+
// _allGroupsCache is NOT cleared: the group list is independent of plugin settings.
|
|
155
158
|
}
|
|
156
159
|
|
|
157
160
|
// ── Client config ────────────────────────────────────────────────────────────
|
|
158
161
|
|
|
159
162
|
function buildClientConfig(settings, excluded) {
|
|
160
|
-
const { excludedGroups, ...rest } = settings;
|
|
163
|
+
const { excludedGroups, excludedSet, ...rest } = settings;
|
|
161
164
|
return { excluded, ...rest };
|
|
162
165
|
}
|
|
163
166
|
|
|
@@ -168,12 +171,24 @@ function serializeInlineConfig(cfg) {
|
|
|
168
171
|
// ── Head injection ───────────────────────────────────────────────────────────
|
|
169
172
|
|
|
170
173
|
const HEAD_PRECONNECTS = [
|
|
174
|
+
// Preload blocking scripts so the download starts before the parser reaches <script> tags
|
|
175
|
+
'<link rel="preload" as="script" href="https://cmp.gatekeeperconsent.com/min.js" crossorigin>',
|
|
176
|
+
'<link rel="preload" as="script" href="https://the.gatekeeperconsent.com/cmp.min.js" crossorigin>',
|
|
177
|
+
'<link rel="preload" as="script" href="https://www.ezojs.com/ezoic/sa.min.js" crossorigin>',
|
|
178
|
+
// Ezoic ad serving
|
|
171
179
|
'<link rel="preconnect" href="https://g.ezoic.net" crossorigin>',
|
|
172
180
|
'<link rel="preconnect" href="https://go.ezoic.net" crossorigin>',
|
|
173
181
|
'<link rel="preconnect" href="https://securepubads.g.doubleclick.net" crossorigin>',
|
|
174
182
|
'<link rel="preconnect" href="https://pagead2.googlesyndication.com" crossorigin>',
|
|
183
|
+
// Synchronous blocking scripts — preconnect to establish TCP+TLS before the parser reaches them
|
|
184
|
+
'<link rel="preconnect" href="https://cmp.gatekeeperconsent.com" crossorigin>',
|
|
185
|
+
'<link rel="preconnect" href="https://the.gatekeeperconsent.com" crossorigin>',
|
|
186
|
+
'<link rel="preconnect" href="https://www.ezojs.com" crossorigin>',
|
|
175
187
|
'<link rel="dns-prefetch" href="https://g.ezoic.net">',
|
|
176
188
|
'<link rel="dns-prefetch" href="https://securepubads.g.doubleclick.net">',
|
|
189
|
+
'<link rel="dns-prefetch" href="https://cmp.gatekeeperconsent.com">',
|
|
190
|
+
'<link rel="dns-prefetch" href="https://the.gatekeeperconsent.com">',
|
|
191
|
+
'<link rel="dns-prefetch" href="https://www.ezojs.com">',
|
|
177
192
|
].join('\n');
|
|
178
193
|
|
|
179
194
|
// Working config: sa.min.js loaded synchronously (no async).
|
|
@@ -219,7 +234,7 @@ plugin.injectEzoicHead = async (data) => {
|
|
|
219
234
|
|
|
220
235
|
const settings = await getSettings();
|
|
221
236
|
const uid = data.req?.uid ?? 0;
|
|
222
|
-
const excluded = await isUserExcluded(uid, settings.excludedGroups);
|
|
237
|
+
const excluded = await isUserExcluded(uid, settings.excludedGroups, settings.excludedSet);
|
|
223
238
|
|
|
224
239
|
if (!_inlineCfgNormal) {
|
|
225
240
|
_inlineCfgNormal = serializeInlineConfig(buildClientConfig(settings, false));
|
|
@@ -274,7 +289,7 @@ plugin.init = async ({ router, middleware }) => {
|
|
|
274
289
|
router.get('/api/plugins/ezoic-infinite/config', async (req, res) => {
|
|
275
290
|
try {
|
|
276
291
|
const settings = await getSettings();
|
|
277
|
-
const excluded = await isUserExcluded(req.uid, settings.excludedGroups);
|
|
292
|
+
const excluded = await isUserExcluded(req.uid, settings.excludedGroups, settings.excludedSet);
|
|
278
293
|
res.json(buildClientConfig(settings, excluded));
|
|
279
294
|
} catch (err) {
|
|
280
295
|
console.error('[ezoic-infinite] config API error:', err.message);
|
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
BURST_COOLDOWN_MS: 200,
|
|
33
33
|
BLOCK_DURATION_MS: 1_000,
|
|
34
34
|
SHOW_TIMEOUT_MS: 4_500,
|
|
35
|
-
SHOW_RELEASE_MS:
|
|
35
|
+
SHOW_RELEASE_MS: 50,
|
|
36
36
|
RECYCLE_DELAY_MS: 50,
|
|
37
37
|
UNCOLLAPSE_CHECK_MS: [500, 5_000],
|
|
38
38
|
};
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
const MAX_BURST_STEPS = 8;
|
|
43
43
|
const BURST_WINDOW_MS = 2_000;
|
|
44
44
|
|
|
45
|
-
const IO_MARGIN_DESKTOP = '
|
|
46
|
-
const IO_MARGIN_MOBILE = '
|
|
45
|
+
const IO_MARGIN_DESKTOP = '1500px 0px 1500px 0px';
|
|
46
|
+
const IO_MARGIN_MOBILE = '2000px 0px 2000px 0px';
|
|
47
47
|
|
|
48
48
|
const SEL = {
|
|
49
49
|
post: '[component="post"][data-pid]',
|
|
@@ -491,7 +491,7 @@
|
|
|
491
491
|
const id = pickId(poolKey);
|
|
492
492
|
if (id) {
|
|
493
493
|
const w = insertAfter(el, id, klass, key);
|
|
494
|
-
if (w) { observePh(id); inserted++; }
|
|
494
|
+
if (w) { observePh(id); enqueueShow(id); inserted++; }
|
|
495
495
|
} else {
|
|
496
496
|
if (!recycleWrap(klass, el, key)) break;
|
|
497
497
|
inserted++;
|
|
@@ -580,7 +580,8 @@
|
|
|
580
580
|
scheduleEmptyCheck(id, t);
|
|
581
581
|
setTimeout(() => { clearTimeout(timer); release(); }, TIMING.SHOW_RELEASE_MS);
|
|
582
582
|
};
|
|
583
|
-
|
|
583
|
+
const ezReady = ez.loadingStatus === 'complete';
|
|
584
|
+
typeof ez.cmd?.push === 'function' && !ezReady ? ez.cmd.push(doShow) : doShow();
|
|
584
585
|
} catch (_) { clearTimeout(timer); release(); }
|
|
585
586
|
}
|
|
586
587
|
|
|
@@ -694,7 +695,7 @@
|
|
|
694
695
|
S.burstCount++;
|
|
695
696
|
scheduleRun(n => {
|
|
696
697
|
if (!n && !S.pending.size) { S.burstActive = false; return; }
|
|
697
|
-
setTimeout(step, n > 0 ?
|
|
698
|
+
setTimeout(step, n > 0 ? 50 : 100);
|
|
698
699
|
});
|
|
699
700
|
};
|
|
700
701
|
step();
|