From e845ca3b61d6320440175a7b0d9144191912c621 Mon Sep 17 00:00:00 2001 From: "hoang.tran12" <99.hoangtran@gmail.com> Date: Tue, 2 Jul 2024 15:55:20 +0700 Subject: [PATCH 01/44] fix ava style --- scripts/_ufs_statistic.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/_ufs_statistic.css b/scripts/_ufs_statistic.css index 68ff0c30..281ad85f 100644 --- a/scripts/_ufs_statistic.css +++ b/scripts/_ufs_statistic.css @@ -9,6 +9,10 @@ canvas { max-height: 500px; } +li { + position: relative; +} + li:hover { background: #555; color: white; @@ -16,14 +20,13 @@ li:hover { li a { display: inline-block; - position: relative; } li a img { width: 30px; transition: all 0.2s ease; position: absolute; - left: 0; + right: 0; top: 0; } From 0072fcadf4cc390ce2f624ec1352432c0aeefccf Mon Sep 17 00:00:00 2001 From: HoangTran <99.hoangtran@gmail.com> Date: Wed, 3 Jul 2024 03:38:23 +0700 Subject: [PATCH 02/44] . --- scripts/backup/fb-proxy.js | 39 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/scripts/backup/fb-proxy.js b/scripts/backup/fb-proxy.js index bb388a6c..30a090f7 100644 --- a/scripts/backup/fb-proxy.js +++ b/scripts/backup/fb-proxy.js @@ -1,3 +1,12 @@ +function uuidv4() { + let h = new Date().getTime(); + return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (i) { + let F = (h + 16 * Math.random()) % 16 | 0; + h = Math.floor(h / 16); + return (i == "x" ? F : (3 & F) | 8).toString(16); + }); +} + (function () { "use strict"; (function () { @@ -17,25 +26,11 @@ return code.slice(code.indexOf("{") + 1, code.lastIndexOf("}")) || ""; })(code), fnParams = (function (code) { - let i = code.replace(b, ""), + let i = code.replace(commentRegex, ""), F = i.slice(i.indexOf("(") + 1, i.indexOf(")")).match(s); return F === null && (F = []), F; })(code), - uuid = - "id_" + - (function () { - let h = new Date().getTime(); - return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace( - /[xy]/g, - function (i) { - var F = (h + 16 * Math.random()) % 16 | 0; - return ( - (h = Math.floor(h / 16)), - (i == "x" ? F : (3 & F) | 8).toString(16) - ); - } - ); - })(); + uuid = "id_" + uuidv4(); let y = `window['__fnCache']["${uuid}"]= function(${fnParams}){${fnBody}}`, c = document.createElement("script"); try { @@ -48,7 +43,7 @@ return v.appendChild(c), v.removeChild(c), window.__fnCache[`${uuid}`]; } window.__fnCache = window.__fnCache || {}; - let b = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm, + let commentRegex = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm, s = /([^\s,]+)/g; function m(r, f, u = !1) { const w = f.split(/\.|\[(\d+)\]/).filter(Boolean); @@ -66,19 +61,19 @@ w = {}, y = {}, c = {}; - let v = window.__d; + let modified__d = window.__d; window.__d && - (~v.toString().indexOf("__d_stub") + (~modified__d.toString().indexOf("__d_stub") ? delete window.__d - : (v = new Proxy(window.__d, { + : (modified__d = new Proxy(window.__d, { apply: (e, t, d) => ((d = i(d)), e.apply(t, d)), }))), Object.defineProperty(window, "__d", { get: function () { - return v; + return modified__d; }, set: function (e) { - v = new Proxy(e, { + modified__d = new Proxy(e, { apply: (t, d, p) => ((p = i(p)), t.apply(d, p)), }); }, From 9f986c5d8974cef6d8ce7e6c8a74ed02d71b714b Mon Sep 17 00:00:00 2001 From: "hoang.tran12" <99.hoangtran@gmail.com> Date: Wed, 3 Jul 2024 13:16:40 +0700 Subject: [PATCH 03/44] WIP --- scripts/backup/fb-proxy.js | 710 ++++++++++++++++++++----------------- 1 file changed, 379 insertions(+), 331 deletions(-) diff --git a/scripts/backup/fb-proxy.js b/scripts/backup/fb-proxy.js index 30a090f7..4d0efc85 100644 --- a/scripts/backup/fb-proxy.js +++ b/scripts/backup/fb-proxy.js @@ -1,4 +1,4 @@ -function uuidv4() { +function make_uuid() { let h = new Date().getTime(); return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (i) { let F = (h + 16 * Math.random()) % 16 | 0; @@ -10,15 +10,15 @@ function uuidv4() { (function () { "use strict"; (function () { - function n(r) { - return r + function decodeModuleName(encoded) { + return encoded .split("") .reverse() .map((f) => String.fromCharCode(f.charCodeAt(0) - 1)) .join(""); } - function l(r) { - const [f, u = "default"] = n(r).split("|"); + function getModuleName(encoded) { + const [f, u = "default"] = decodeModuleName(encoded).split("|"); return [f, u]; } function cacheFunction(code) { @@ -30,7 +30,7 @@ function uuidv4() { F = i.slice(i.indexOf("(") + 1, i.indexOf(")")).match(s); return F === null && (F = []), F; })(code), - uuid = "id_" + uuidv4(); + uuid = "id_" + make_uuid(); let y = `window['__fnCache']["${uuid}"]= function(${fnParams}){${fnBody}}`, c = document.createElement("script"); try { @@ -53,20 +53,23 @@ function uuidv4() { if (((y = c), (c = c[w[v]]), c === void 0)) return u ? y : void 0; return u ? y : c; } - ((r) => { + (() => { if (window.GZUAwCFuFf) return; window.GZUAwCFuFf = !0; - const f = {}, + const moduleCached = {}, u = {}, w = {}, - y = {}, + isModuleLoaded = {}, c = {}; let modified__d = window.__d; window.__d && (~modified__d.toString().indexOf("__d_stub") ? delete window.__d : (modified__d = new Proxy(window.__d, { - apply: (e, t, d) => ((d = i(d)), e.apply(t, d)), + apply: (target, thisArg, argumentsList) => ( + (argumentsList = i(argumentsList)), + target.apply(thisArg, argumentsList) + ), }))), Object.defineProperty(window, "__d", { get: function () { @@ -74,89 +77,100 @@ function uuidv4() { }, set: function (e) { modified__d = new Proxy(e, { - apply: (t, d, p) => ((p = i(p)), t.apply(d, p)), + apply: (target, thisArg, argumentsList) => ( + (argumentsList = i(argumentsList)), + target.apply(thisArg, argumentsList) + ), }); }, }); - const h = []; + const moduleNames = []; function i(e) { - let [t, d, p] = e; + let [moduleName, dependencies, callback] = e; return ( - typeof t != "string" || - h.includes(t) || - (h.push(t), - (e[2] = (function (_, S) { - if (!w[S]) return _; - const k = w[S]; + typeof moduleName != "string" || + moduleNames.includes(moduleName) || + (moduleNames.push(moduleName), + (e[2] = (function (orig, _moduleName) { + if (!w[_moduleName]) return orig; + const k = w[_moduleName]; k.sort((a, A) => a.options.order - A.options.order); const E = k.find((a) => a.options.skipOthers); return cacheFunction( E - ? E.replacement(_.toString()) - : k.reduce((a, A) => (a = A.replacement(a)), _.toString()) + ? E.replacement(orig.toString()) + : k.reduce((a, A) => (a = A.replacement(a)), orig.toString()) ); - })(e[2], t)), - (e[2] = (function (_, S) { - return u[S] - ? new Proxy(_, { - apply(k, E, a) { - if (a[5] && a[5].dependencies) - for (let x = 0; x < a[5].dependencies.length; x++) - a.push(a[5].dependencies[x].exports); - const A = k.apply(E, a); + })(e[2], moduleName)), + (e[2] = (function (orig, _moduleName) { + return u[_moduleName] + ? new Proxy(orig, { + apply(target, thisArg, argsList) { + if (argsList[5] && argsList[5].dependencies) + for ( + let i = 0; + i < argsList[5].dependencies.length; + i++ + ) + argsList.push(argsList[5].dependencies[i].exports); + const res = target.apply(thisArg, argsList); return ( - u[S].map((x) => { - x(a); + u[_moduleName].map((x) => { + x(argsList); }), - A + res ); }, }) - : _; - })(e[2], t)), - (e[2] = (function (_, S) { - if (!f[S] || f[S].length === 0) return _; - const k = f[S]; + : orig; + })(e[2], moduleName)), + (e[2] = (function (orig, _moduleName) { + if ( + !moduleCached[_moduleName] || + moduleCached[_moduleName].length === 0 + ) + return orig; + const k = moduleCached[_moduleName]; k.sort((a, A) => a.options.order - A.options.order); const E = k.reduce((a, A) => { const x = A.options.definerPath; return (a[x] = a[x] || []), a[x].push(A), a; }, {}); - return new Proxy(_, { - apply(a, A, x) { - const L = a.apply(A, x); - if (x[5] && x[5].dependencies) - for (let j = 0; j < x[5].dependencies.length; j++) - x.push(x[5].dependencies[j].exports); - const q = x[3], - Q = (0, x[2])("CometErrorBoundary.react"), + return new Proxy(orig, { + apply(target, thisArg, argsList) { + const L = target.apply(thisArg, argsList); + if (argsList[5] && argsList[5].dependencies) + for (let j = 0; j < argsList[5].dependencies.length; j++) + argsList.push(argsList[5].dependencies[j].exports); + const _import = argsList[3], + Q = (0, argsList[2])("CometErrorBoundary.react"), B = (j) => (console.error(j), "Error"); for (let j in E) { - const U = m(x, j, !0), + const U = m(argsList, j, !0), G = j.split(".").pop(), - K = m(x, j); - U[G] = function (...D) { - const Y = K.apply(K, D), - R = D[0], + K = m(argsList, j); + U[G] = function (...callingArgs) { + const sourceCmp = K.apply(K, callingArgs), + payload = callingArgs[0], { useState: M, useEffect: W, jsx: T, Fragment: O, - } = q("react"), + } = _import("react"), [Z, X] = M(0), V = () => { - if (!E[j]) return I(Y); + if (!E[j]) return I(sourceCmp); const g = E[j].find((z) => z.options.skipOthers); if (g && g.component) return T(g.fallback ? Q : O, { fallback: g.fallback, children: T(g.component, { - payload: R, - SourceCmp: Y, - lastCmp: I(Y), - definedArgs: x, - callingArgs: D, + payload: payload, + SourceCmp: sourceCmp, + lastCmp: I(sourceCmp), + definedArgs: argsList, + callingArgs: callingArgs, extraPayloadFromDefiner: g.options.extraPayload, proxyCount: 0, removeThisModuleProxy() { @@ -167,32 +181,34 @@ function uuidv4() { }); let $ = 0; return E[j].reduce( - (z, P) => ( + (lastCmp, P) => ( P.component && - ((z = T(P.fallback ? Q : O, { + ((lastCmp = T(P.fallback ? Q : O, { fallback: P.fallback, children: T(P.component, { - payload: R, - SourceCmp: Y, - lastCmp: z, + payload: payload, + SourceCmp: sourceCmp, + lastCmp: lastCmp, extraPayloadFromDefiner: P.options.extraPayload, proxyCount: $, - definedArgs: x, - callingArgs: D, + definedArgs: argsList, + callingArgs: callingArgs, removeThisModuleProxy() { const N = E[j].indexOf(P); if (~N) { const J = k.indexOf(P); - E[j].splice(N, 1), k.splice(J, 1), C(S); + E[j].splice(N, 1), + k.splice(J, 1), + C(_moduleName); } }, }), })), $++), - z + lastCmp ), - I(Y) + I(sourceCmp) ); }; function I(g) { @@ -202,7 +218,7 @@ function uuidv4() { } return ( W(() => { - const g = F(S, () => { + const g = F(_moduleName, () => { X(Math.random()); }); return () => g(); @@ -217,8 +233,8 @@ function uuidv4() { return L; }, }); - })(e[2], t)), - y[t] && console.log(t, e)), + })(e[2], moduleName)), + isModuleLoaded[moduleName] && console.log(moduleName, e)), e ); } @@ -235,260 +251,289 @@ function uuidv4() { function C(e) { if (c[e]) for (let t of c[e]) t(); } - (r.zKjQYvgSmF = function (e) { - return window.require(n(e)); - }), - (r.zKjQYvcSmF = (e, t, d) => { - const [p, _] = l(e); - f[p] || console.error(`Undefined module ${p} from ${_} #1`); - const S = f[p].find((E) => E.extensionId === _); - if (!S) return console.error(`Undefined module ${p} from ${_} #2`); - const { fallback: k } = d || {}; - (S.component = t), (S.fallback = k), C(p); - }), - (r.zKjQYVcSmF = (e, t) => { - const d = Object.assign( - { - order: 10, - skipOthers: !1, - beforeInject: () => !0, - afterInject: () => {}, - extraPayload: void 0, - definerPath: "[6].default", - }, - t - ), - [p, _] = l(e); - (f[p] = f[p] || []), - f[p].push({ - extensionId: _, - moduleName: p, - options: d, - component: void 0, - fallback: void 0, - }); - }), - (r.zKjQYwcSmF = (e) => { - y[n(e)] = !0; - }), - (r.zKjQYvcSfF = (e, t, d) => { - const p = Object.assign( - { - order: 10, - skipOthers: !1, - }, - d - ), - [_, S] = l(e); - (w[_] = w[_] || []), - w[_].push({ - moduleName: _, - options: p, - replacement: t, - }); - }), - (r.zKGQYvcSmF = (e, t) => { - (e = n(e)), (u[e] = u[e] || []), u[e].push(t); - }), - r.zKjQYvcSfF("umvbgfe}spssf.cg", (e) => - e.replace( - 'debugjs.")', - 'debugjs.");console.error(b.stackFrames.slice(0,10).map(e=>e.text).join("\\n"))' - ) - ), - r.zKjQYvcSfF("umvbgfe}djttbmd/epsq.NPEudbfS", (e) => - e.replace(/Error\(\w\(418\)\)/g, "void 0") - ), - r.zKjQYvcSfF("umvbgfe}fvfvRitjmcvQzbmfS0fsput0fnjuovs.zbmfs", (e) => + window._require = function (e) { + return window.require(decodeModuleName(e)); + }; + window.zKjQYvcSmF = (e, t, d) => { + const [moduleName, _] = getModuleName(e); + moduleCached[moduleName] || + console.error(`Undefined module ${moduleName} from ${_} #1`); + const S = moduleCached[moduleName].find((E) => E.extensionId === _); + if (!S) + return console.error(`Undefined module ${moduleName} from ${_} #2`); + const { fallback } = d || {}; + S.component = t; + S.fallback = fallback; + C(moduleName); + }; + window.zKjQYVcSmF = (e, t) => { + const d = Object.assign( + { + order: 10, + skipOthers: !1, + beforeInject: () => !0, + afterInject: () => {}, + extraPayload: void 0, + definerPath: "[6].default", + }, + t + ); + const [p, _] = getModuleName(e); + moduleCached[p] = moduleCached[p] || []; + moduleCached[p].push({ + extensionId: _, + moduleName: p, + options: d, + component: void 0, + fallback: void 0, + }); + }; + window.zKjQYwcSmF = (e) => { + isModuleLoaded[decodeModuleName(e)] = !0; + }; + window.cheatFbModule_replaceCode = (e, replacement, d) => { + const options = Object.assign( + { + order: 10, + skipOthers: !1, + }, + d + ); + const [moduleName, S] = getModuleName(e); + w[moduleName] = w[moduleName] || []; + w[moduleName].push({ + moduleName: moduleName, + options: options, + replacement: replacement, + }); + }; + window.cheatFbModule_overrideCode = (encodedModuleName, t) => { + encodedModuleName = decodeModuleName(encodedModuleName); + u[encodedModuleName] = u[encodedModuleName] || []; + u[encodedModuleName].push(t); + }; + // 'fb-error|default' + window.cheatFbModule_replaceCode("umvbgfe}spssf.cg", (e) => + e.replace( + 'debugjs.")', + 'debugjs.");console.error(b.stackFrames.slice(0,10).map(e=>e.text).join("\\n"))' + ) + ); + // 'ReactDOM-prod.classic|default' + window.cheatFbModule_replaceCode("umvbgfe}djttbmd/epsq.NPEudbfS", (e) => + e.replace(/Error\(\w\(418\)\)/g, "void 0") + ); + // 'relay-runtime/store/RelayPublishQueue|default' + window.cheatFbModule_replaceCode( + "umvbgfe}fvfvRitjmcvQzbmfS0fsput0fnjuovs.zbmfs", + (e) => e.replace( /,(\w)=new\(b\("relay-runtime\/mutations\/RelayRecordSourceProxy"/, ',$1=window["RlbiULLGWt"]=new(b("relay-runtime/mutations/RelayRecordSourceProxy"' ) - ), - r.zKjQYvcSfF( - "umvbgfe}fvfvRitjmcvQzbmfS0fsput0fnjuovs.zbmfs", - (e) => - (e = e.replace( - /;(\w)\.commitPayload=function\(([\w,]+)\){/, - ";$1.commitPayload=function($2){try{if(arguments[0]){if(arguments[0]?.request?.variables?.__relay_internal__pv__CometUFIReactionEnableShortNamerelayprovider === true) return;};}catch(e){console.log('relayStoreCommitPayload',e)};" - )) - ); - })(window), - ((r) => { - r.vTUNhjwVvX || - ((r.vTUNhjwVvX = !0), - (r.zKjqYvcSmF = (f, u, w) => { - const y = r.RlbiULLGWt, - c = typeof f == "string" ? y.get(f) : f; - if (c === void 0) return c; - let v = ((h = u.replace(/\[(\d+)\]/g, ".$1")), - h.replace(/\((.*?)\.(.*?)\)/g, "($1_*_*_*_*_$2)")).split("."); - var h; - v = v.map((e) => - (function (t) { - return t.replaceAll("_*_*_*_*_", "."); - })(e) - ); - let i = c; - for (let e = 0; e < v.length; e++) { - const t = v[e]; - if (t === "*") return i; - if (t.indexOf("^^") === 0) { - const [d, p] = F(t.substring(2)); - if (((i = i.getLinkedRecords(d, p)), i === void 0)) - return C(t), i; - } else if (t.indexOf("^") === 0) { - const [d, p] = F(t.substring(1)); - if (((i = i.getLinkedRecord(d, p)), i == null)) return C(t), i; - } else if (t.match(/^\d+$/)) { - if (((i = i[parseInt(t)]), i == null)) return C(t), i; - } else { - const [d, p] = F(t); - if (((i = i.getValue(d, p)), i == null)) return C(t), i; - } - } - return i; - function F(e) { - const [t, d] = e.split("{"); - if (!d) return [t, {}]; - if (!w) throw new Error("args undefined"); - return [t, w[d.substring(0, d.length - 1)] || {}]; + ); + // 'relay-runtime/store/RelayPublishQueue|default' + window.cheatFbModule_replaceCode( + "umvbgfe}fvfvRitjmcvQzbmfS0fsput0fnjuovs.zbmfs", + (e) => + (e = e.replace( + /;(\w)\.commitPayload=function\(([\w,]+)\){/, + ";$1.commitPayload=function($2){try{if(arguments[0]){if(arguments[0]?.request?.variables?.__relay_internal__pv__CometUFIReactionEnableShortNamerelayprovider === true) return;};}catch(e){console.log('relayStoreCommitPayload',e)};" + )) + ); + })(); + (() => { + window.vTUNhjwVvX || + ((window.vTUNhjwVvX = !0), + (window.zKjqYvcSmF = (f, u, w) => { + const y = window.RlbiULLGWt, + c = typeof f == "string" ? y.get(f) : f; + if (c === void 0) return c; + let v = ((h = u.replace(/\[(\d+)\]/g, ".$1")), + h.replace(/\((.*?)\.(.*?)\)/g, "($1_*_*_*_*_$2)")).split("."); + var h; + v = v.map((e) => + (function (t) { + return t.replaceAll("_*_*_*_*_", "."); + })(e) + ); + let i = c; + for (let e = 0; e < v.length; e++) { + const t = v[e]; + if (t === "*") return i; + if (t.indexOf("^^") === 0) { + const [d, p] = F(t.substring(2)); + if (((i = i.getLinkedRecords(d, p)), i === void 0)) + return C(t), i; + } else if (t.indexOf("^") === 0) { + const [d, p] = F(t.substring(1)); + if (((i = i.getLinkedRecord(d, p)), i == null)) return C(t), i; + } else if (t.match(/^\d+$/)) { + if (((i = i[parseInt(t)]), i == null)) return C(t), i; + } else { + const [d, p] = F(t); + if (((i = i.getValue(d, p)), i == null)) return C(t), i; } - function C(e) { - ~r.location.search.indexOf("debug") && - console.warn("undefined value", { - id: f, - path: u, - args: w, - currentPath: e, - }); - } - })); - })(window), - ((r) => { - if (window.xmxlgxMDjA) return; - window.xmxlgxMDjA = !0; - let f = {}; - r.zKGQYvcSmF("sf{jmbjsfTbubEfmqnjTsiy", (u) => { - const w = u[4].exports.default; - u[4].exports.default = function (...y) { - const c = y[0].fb_api_req_friendly_name; - return ( - c && f[c] && (y[0] = f[c].reduce((v, h) => (v = h(v)), y[0])), - w.apply(w, y) - ); - }; - }), - (r.zkjQYvcSmF = (u, w) => { - (u = n(u)), (f[u] = f[u] || []), f[u].push(w); - }); - })(window); - })(), - window.zKjQYvcSfF( - "lppcfdbg.spg.offtov}topjujojgfEcpKXBN", - (n) => ( - (n = n.replace( - /markThreadAsRead:function.*?{/, - "markThreadAsRead:function(){return;" - )), - n - ) - ), - window.zKjQYvcSfF( - "lppcfdbg.spg.offtov}fubuThojqzUfsvdfTXBN", - (n) => ((n = n.replaceAll("sendChatStateFromComposer", "none")), n) - ), - window.zKGQYvcSmF("spubdjeoJhojqzUeofTTM", (n) => { - if (n[4].exports) - if (n[4].exports.default) { - const l = n[4].exports.default; - n[4].exports.default = function (...o) { - var b, s; - return ( - (o[2] = !( - (s = - (b = window == null ? void 0 : window.unseen_for_facebook) == - null - ? void 0 - : b.DISABLE_TYPING) != null && s.enable - )), - l.apply(l, o) - ); - }; - } else { - const l = n[4].exports; - n[4].exports = function (...o) { - var b, s; - return ( - (o[2] = !( - (s = - (b = window == null ? void 0 : window.unseen_for_facebook) == - null - ? void 0 - : b.DISABLE_TYPING) != null && s.enable - )), - l.apply(l, o) - ); - }; - } - }), - window.zKGQYvcSmF("3WebfSebfsiUlsbNdjutjnjuqPTM", (n) => { - if (n[4].exports) - if (n[4].exports.default) { - const l = n[4].exports.default; - n[4].exports.default = function (...o) { - var s, m; - let b = o[o.length - 1]; - return (m = - (s = window == null ? void 0 : window.unseen_for_facebook) == null - ? void 0 - : s.DISABLE_READ) != null && m.enable - ? b.resolve([]) - : l.apply(l, o); - }; - } else { - const l = n[4].exports; - n[4].exports = function (...o) { - var s, m; - let b = o[o.length - 1]; - return (m = - (s = window == null ? void 0 : window.unseen_for_facebook) == null - ? void 0 - : s.DISABLE_READ) != null && m.enable - ? b.resolve([]) - : l.apply(l, o); - }; - } - }), - window.zKGQYvcSmF("mqnJ3WebfSebfsiUlsbNdjutjnjuqPTM", (n) => { - if (n[4].exports) - if (n[4].exports.default) { - const l = n[4].exports.default; - n[4].exports.default = function (...o) { - var s, m; - let b = o[o.length - 1]; - return (m = - (s = window == null ? void 0 : window.unseen_for_facebook) == null - ? void 0 - : s.DISABLE_READ) != null && m.enable - ? b.resolve([]) - : l.apply(l, o); - }; - } else { - const l = n[4].exports; - n[4].exports = function (...o) { - var s, m; - let b = o[o.length - 1]; - return (m = - (s = window == null ? void 0 : window.unseen_for_facebook) == null - ? void 0 - : s.DISABLE_READ) != null && m.enable - ? b.resolve([]) - : l.apply(l, o); - }; - } - }), - window.zKGQYvcSmF("cfXmqnJ3WebfSebfsiUlsbNdjutjnjuqPTM", (n) => { + } + return i; + function F(e) { + const [t, d] = e.split("{"); + if (!d) return [t, {}]; + if (!w) throw new Error("args undefined"); + return [t, w[d.substring(0, d.length - 1)] || {}]; + } + function C(e) { + ~window.location.search.indexOf("debug") && + console.warn("undefined value", { + id: f, + path: u, + args: w, + currentPath: e, + }); + } + })); + })(); + (() => { + if (window.xmxlgxMDjA) return; + window.xmxlgxMDjA = !0; + let f = {}; + // 'xhrSimpleDataSerializer' + window.cheatFbModule_overrideCode("sf{jmbjsfTbubEfmqnjTsiy", (u) => { + const w = u[4].exports.default; + u[4].exports.default = function (...y) { + const c = y[0].fb_api_req_friendly_name; + return ( + c && f[c] && (y[0] = f[c].reduce((v, h) => (v = h(v)), y[0])), + w.apply(w, y) + ); + }; + }); + window.zkjQYvcSmF = (u, w) => { + u = decodeModuleName(u); + f[u] = f[u] || []; + f[u].push(w); + }; + })(); + })(); + + // 'MAWJobDefinitions|unseen-for-facebook' + window.cheatFbModule_replaceCode( + "lppcfdbg.spg.offtov}topjujojgfEcpKXBN", + (n) => ( + (n = n.replace( + /markThreadAsRead:function.*?{/, + "markThreadAsRead:function(){return;" + )), + n + ) + ); + + // 'MAWSecureTypingState|unseen-for-facebook' + window.cheatFbModule_replaceCode( + "lppcfdbg.spg.offtov}fubuThojqzUfsvdfTXBN", + (n) => ((n = n.replaceAll("sendChatStateFromComposer", "none")), n) + ); + + // LSSendTypingIndicator + window.cheatFbModule_overrideCode("spubdjeoJhojqzUeofTTM", (n) => { + if (n[4].exports) + if (n[4].exports.default) { + const l = n[4].exports.default; + n[4].exports.default = function (...o) { + var b, s; + return ( + (o[2] = !( + (s = + (b = window == null ? void 0 : window.unseen_for_facebook) == + null + ? void 0 + : b.DISABLE_TYPING) != null && s.enable + )), + l.apply(l, o) + ); + }; + } else { + const l = n[4].exports; + n[4].exports = function (...o) { + var b, s; + return ( + (o[2] = !( + (s = + (b = window == null ? void 0 : window.unseen_for_facebook) == + null + ? void 0 + : b.DISABLE_TYPING) != null && s.enable + )), + l.apply(l, o) + ); + }; + } + }); + + // 'LSOptimisticMarkThreadReadV2' + window.cheatFbModule_overrideCode("3WebfSebfsiUlsbNdjutjnjuqPTM", (n) => { + if (n[4].exports) + if (n[4].exports.default) { + const l = n[4].exports.default; + n[4].exports.default = function (...o) { + var s, m; + let b = o[o.length - 1]; + return (m = + (s = window == null ? void 0 : window.unseen_for_facebook) == null + ? void 0 + : s.DISABLE_READ) != null && m.enable + ? b.resolve([]) + : l.apply(l, o); + }; + } else { + const l = n[4].exports; + n[4].exports = function (...o) { + var s, m; + let b = o[o.length - 1]; + return (m = + (s = window == null ? void 0 : window.unseen_for_facebook) == null + ? void 0 + : s.DISABLE_READ) != null && m.enable + ? b.resolve([]) + : l.apply(l, o); + }; + } + }); + + // 'LSOptimisticMarkThreadReadV2Impl' + window.cheatFbModule_overrideCode("mqnJ3WebfSebfsiUlsbNdjutjnjuqPTM", (n) => { + if (n[4].exports) + if (n[4].exports.default) { + const l = n[4].exports.default; + n[4].exports.default = function (...o) { + var s, m; + let b = o[o.length - 1]; + return (m = + (s = window == null ? void 0 : window.unseen_for_facebook) == null + ? void 0 + : s.DISABLE_READ) != null && m.enable + ? b.resolve([]) + : l.apply(l, o); + }; + } else { + const l = n[4].exports; + n[4].exports = function (...o) { + var s, m; + let b = o[o.length - 1]; + return (m = + (s = window == null ? void 0 : window.unseen_for_facebook) == null + ? void 0 + : s.DISABLE_READ) != null && m.enable + ? b.resolve([]) + : l.apply(l, o); + }; + } + }); + + // 'LSOptimisticMarkThreadReadV2ImplWeb' + window.cheatFbModule_overrideCode( + "cfXmqnJ3WebfSebfsiUlsbNdjutjnjuqPTM", + (n) => { if (n[4].exports) if (n[4].exports.default) { const l = n[4].exports.default; @@ -515,15 +560,18 @@ function uuidv4() { : l.apply(l, o); }; } - }), - window.zKjQYvcSfF( - "lppcfdbg.spg.offtov}udbfs/sfojbuopDufldvCftofqtvTtfjspuT", - (n) => ( - (n = n.replace( - /,onCardSeen:(\w),/g, - ",onCardSeen:window?.unseen_for_facebook?.DISABLE_STORIES_SEEN?.enable ? ()=>{} : $1," - )), - n - ) - ); + } + ); + + // 'StoriesSuspenseBucketContainer.react|unseen-for-facebook' + window.cheatFbModule_replaceCode( + "lppcfdbg.spg.offtov}udbfs/sfojbuopDufldvCftofqtvTtfjspuT", + (n) => ( + (n = n.replace( + /,onCardSeen:(\w),/g, + ",onCardSeen:window?.unseen_for_facebook?.DISABLE_STORIES_SEEN?.enable ? ()=>{} : $1," + )), + n + ) + ); })(); From e0b50f12bc2f1c74cf3f22d093049bb89617654e Mon Sep 17 00:00:00 2001 From: "hoang.tran12" <99.hoangtran@gmail.com> Date: Wed, 3 Jul 2024 18:26:18 +0700 Subject: [PATCH 04/44] new script --- scripts/backup/auto-like-fb.js | 57 ++++++ scripts/backup/fb-proxy.js | 356 ++++++++++++++++----------------- 2 files changed, 235 insertions(+), 178 deletions(-) create mode 100644 scripts/backup/auto-like-fb.js diff --git a/scripts/backup/auto-like-fb.js b/scripts/backup/auto-like-fb.js new file mode 100644 index 00000000..3e22998b --- /dev/null +++ b/scripts/backup/auto-like-fb.js @@ -0,0 +1,57 @@ +javascript: (async function () { + function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + function focusTo(element) { + element.dispatchEvent( + new MouseEvent("pointerover", { + view: window, + bubbles: true, + cancelable: true, + }) + ); + } + + function scrollToBottom() { + window.scrollTo(0, document.body.scrollHeight, { behavior: "smooth" }); + } + + const doneKey = "auto-like-done"; + const btns = []; + while (true) { + if (!btns.length) { + let curBtns = Array.from( + document.querySelectorAll("[aria-label='Bày tỏ cảm xúc']:not(li *)") + ); + let added = 0; + for (let btn of curBtns) { + if (btn.getAttribute(doneKey) === null) { + btns.push(btn); + btn.setAttribute(doneKey, true); + added++; + } + } + if (added === 0) break; + } + + for (let btn of btns) { + btn.scrollIntoView({ + block: "center", + behavior: "smooth", + }); + btn.click(); + await sleep(500); + let loveBtn = document.querySelector("[aria-label='Yêu thích']"); + if (loveBtn) { + focusTo(loveBtn); + await sleep(500); + loveBtn.click(); + await sleep(500); + } + btns.splice(btns.indexOf(btn), 1); + } + scrollToBottom(); + await sleep(1000); + } + alert("xong"); +})(); diff --git a/scripts/backup/fb-proxy.js b/scripts/backup/fb-proxy.js index 4d0efc85..f4b95028 100644 --- a/scripts/backup/fb-proxy.js +++ b/scripts/backup/fb-proxy.js @@ -11,6 +11,7 @@ function make_uuid() { "use strict"; (function () { function decodeModuleName(encoded) { + return encoded; return encoded .split("") .reverse() @@ -18,8 +19,9 @@ function make_uuid() { .join(""); } function getModuleName(encoded) { - const [f, u = "default"] = decodeModuleName(encoded).split("|"); - return [f, u]; + const [moduleName, extensionId = "default"] = + decodeModuleName(encoded).split("|"); + return [moduleName, extensionId]; } function cacheFunction(code) { const fnBody = (function (code) { @@ -87,156 +89,154 @@ function make_uuid() { const moduleNames = []; function i(e) { let [moduleName, dependencies, callback] = e; - return ( - typeof moduleName != "string" || - moduleNames.includes(moduleName) || - (moduleNames.push(moduleName), - (e[2] = (function (orig, _moduleName) { - if (!w[_moduleName]) return orig; - const k = w[_moduleName]; - k.sort((a, A) => a.options.order - A.options.order); - const E = k.find((a) => a.options.skipOthers); - return cacheFunction( - E - ? E.replacement(orig.toString()) - : k.reduce((a, A) => (a = A.replacement(a)), orig.toString()) - ); - })(e[2], moduleName)), - (e[2] = (function (orig, _moduleName) { - return u[_moduleName] - ? new Proxy(orig, { - apply(target, thisArg, argsList) { - if (argsList[5] && argsList[5].dependencies) - for ( - let i = 0; - i < argsList[5].dependencies.length; - i++ - ) - argsList.push(argsList[5].dependencies[i].exports); - const res = target.apply(thisArg, argsList); - return ( - u[_moduleName].map((x) => { - x(argsList); - }), - res - ); - }, - }) - : orig; - })(e[2], moduleName)), - (e[2] = (function (orig, _moduleName) { - if ( - !moduleCached[_moduleName] || - moduleCached[_moduleName].length === 0 - ) - return orig; - const k = moduleCached[_moduleName]; - k.sort((a, A) => a.options.order - A.options.order); - const E = k.reduce((a, A) => { - const x = A.options.definerPath; - return (a[x] = a[x] || []), a[x].push(A), a; - }, {}); - return new Proxy(orig, { + + if (typeof moduleName != "string" || moduleNames.includes(moduleName)) + return; + + moduleNames.push(moduleName); + e[2] = (function (orig, _moduleName) { + if (!w[_moduleName]) return orig; + const k = w[_moduleName]; + k.sort((a, A) => a.options.order - A.options.order); + const E = k.find((a) => a.options.skipOthers); + return cacheFunction( + E + ? E.replacement(orig.toString()) + : k.reduce((a, A) => (a = A.replacement(a)), orig.toString()) + ); + })(e[2], moduleName); + + e[2] = (function (orig, _moduleName) { + return u[_moduleName] + ? new Proxy(orig, { apply(target, thisArg, argsList) { - const L = target.apply(thisArg, argsList); if (argsList[5] && argsList[5].dependencies) - for (let j = 0; j < argsList[5].dependencies.length; j++) - argsList.push(argsList[5].dependencies[j].exports); - const _import = argsList[3], - Q = (0, argsList[2])("CometErrorBoundary.react"), - B = (j) => (console.error(j), "Error"); - for (let j in E) { - const U = m(argsList, j, !0), - G = j.split(".").pop(), - K = m(argsList, j); - U[G] = function (...callingArgs) { - const sourceCmp = K.apply(K, callingArgs), - payload = callingArgs[0], - { - useState: M, - useEffect: W, - jsx: T, - Fragment: O, - } = _import("react"), - [Z, X] = M(0), - V = () => { - if (!E[j]) return I(sourceCmp); - const g = E[j].find((z) => z.options.skipOthers); - if (g && g.component) - return T(g.fallback ? Q : O, { - fallback: g.fallback, - children: T(g.component, { + for (let i = 0; i < argsList[5].dependencies.length; i++) + argsList.push(argsList[5].dependencies[i].exports); + const res = target.apply(thisArg, argsList); + return ( + u[_moduleName].map((x) => { + x(argsList); + }), + res + ); + }, + }) + : orig; + })(e[2], moduleName); + + e[2] = (function (orig, _moduleName) { + if ( + !moduleCached[_moduleName] || + moduleCached[_moduleName].length === 0 + ) + return orig; + const k = moduleCached[_moduleName]; + k.sort((a, A) => a.options.order - A.options.order); + const E = k.reduce((a, A) => { + const x = A.options.definerPath; + return (a[x] = a[x] || []), a[x].push(A), a; + }, {}); + return new Proxy(orig, { + apply(target, thisArg, argsList) { + const L = target.apply(thisArg, argsList); + if (argsList[5] && argsList[5].dependencies) + for (let j = 0; j < argsList[5].dependencies.length; j++) + argsList.push(argsList[5].dependencies[j].exports); + const _import = argsList[3], + Q = (0, argsList[2])("CometErrorBoundary.react"), + B = (j) => (console.error(j), "Error"); + for (let j in E) { + const U = m(argsList, j, !0), + G = j.split(".").pop(), + K = m(argsList, j); + U[G] = function (...callingArgs) { + const sourceCmp = K.apply(K, callingArgs), + payload = callingArgs[0], + { + useState: M, + useEffect: W, + jsx: T, + Fragment: O, + } = _import("react"), + [Z, X] = M(0), + V = () => { + if (!E[j]) return I(sourceCmp); + const g = E[j].find((z) => z.options.skipOthers); + if (g && g.component) + return T(g.fallback ? Q : O, { + fallback: g.fallback, + children: T(g.component, { + payload: payload, + SourceCmp: sourceCmp, + lastCmp: I(sourceCmp), + definedArgs: argsList, + callingArgs: callingArgs, + extraPayloadFromDefiner: g.options.extraPayload, + proxyCount: 0, + removeThisModuleProxy() { + const z = E[j].indexOf(g); + ~z && E[j].splice(z, 1); + }, + }), + }); + let $ = 0; + return E[j].reduce( + (lastCmp, P) => ( + P.component && + ((lastCmp = T(P.fallback ? Q : O, { + fallback: P.fallback, + children: T(P.component, { payload: payload, SourceCmp: sourceCmp, - lastCmp: I(sourceCmp), + lastCmp: lastCmp, + extraPayloadFromDefiner: P.options.extraPayload, + proxyCount: $, definedArgs: argsList, callingArgs: callingArgs, - extraPayloadFromDefiner: g.options.extraPayload, - proxyCount: 0, removeThisModuleProxy() { - const z = E[j].indexOf(g); - ~z && E[j].splice(z, 1); + const N = E[j].indexOf(P); + if (~N) { + const J = k.indexOf(P); + E[j].splice(N, 1), + k.splice(J, 1), + C(_moduleName); + } }, }), - }); - let $ = 0; - return E[j].reduce( - (lastCmp, P) => ( - P.component && - ((lastCmp = T(P.fallback ? Q : O, { - fallback: P.fallback, - children: T(P.component, { - payload: payload, - SourceCmp: sourceCmp, - lastCmp: lastCmp, - extraPayloadFromDefiner: - P.options.extraPayload, - proxyCount: $, - definedArgs: argsList, - callingArgs: callingArgs, - removeThisModuleProxy() { - const N = E[j].indexOf(P); - if (~N) { - const J = k.indexOf(P); - E[j].splice(N, 1), - k.splice(J, 1), - C(_moduleName); - } - }, - }), - })), - $++), - lastCmp - ), - I(sourceCmp) - ); - }; - function I(g) { - return g && g.$1 && typeof g.$1 == "function" - ? T(g, g.props) - : g; - } - return ( - W(() => { - const g = F(_moduleName, () => { - X(Math.random()); - }); - return () => g(); - }, []), - T(Q, { - fallback: B, - children: V(), - }) + })), + $++), + lastCmp + ), + I(sourceCmp) ); }; + function I(g) { + return g && g.$1 && typeof g.$1 == "function" + ? T(g, g.props) + : g; } - return L; - }, - }); - })(e[2], moduleName)), - isModuleLoaded[moduleName] && console.log(moduleName, e)), - e - ); + return ( + W(() => { + const g = F(_moduleName, () => { + X(Math.random()); + }); + return () => g(); + }, []), + T(Q, { + fallback: B, + children: V(), + }) + ); + }; + } + return L; + }, + }); + })(e[2], moduleName); + + isModuleLoaded[moduleName] && console.log(moduleName, e); + return e; } function F(e, t) { return ( @@ -255,12 +255,18 @@ function make_uuid() { return window.require(decodeModuleName(e)); }; window.zKjQYvcSmF = (e, t, d) => { - const [moduleName, _] = getModuleName(e); + const [moduleName, extensionId] = getModuleName(e); moduleCached[moduleName] || - console.error(`Undefined module ${moduleName} from ${_} #1`); - const S = moduleCached[moduleName].find((E) => E.extensionId === _); + console.error( + `Undefined module ${moduleName} from ${extensionId} #1` + ); + const S = moduleCached[moduleName].find( + (E) => E.extensionId === extensionId + ); if (!S) - return console.error(`Undefined module ${moduleName} from ${_} #2`); + return console.error( + `Undefined module ${moduleName} from ${extensionId} #2` + ); const { fallback } = d || {}; S.component = t; S.fallback = fallback; @@ -278,10 +284,10 @@ function make_uuid() { }, t ); - const [p, _] = getModuleName(e); + const [p, extensionId] = getModuleName(e); moduleCached[p] = moduleCached[p] || []; moduleCached[p].push({ - extensionId: _, + extensionId: extensionId, moduleName: p, options: d, component: void 0, @@ -312,29 +318,29 @@ function make_uuid() { u[encodedModuleName] = u[encodedModuleName] || []; u[encodedModuleName].push(t); }; - // 'fb-error|default' - window.cheatFbModule_replaceCode("umvbgfe}spssf.cg", (e) => + + window.cheatFbModule_replaceCode("b-error|default", (e) => e.replace( 'debugjs.")', 'debugjs.");console.error(b.stackFrames.slice(0,10).map(e=>e.text).join("\\n"))' ) ); - // 'ReactDOM-prod.classic|default' - window.cheatFbModule_replaceCode("umvbgfe}djttbmd/epsq.NPEudbfS", (e) => + + window.cheatFbModule_replaceCode("ReactDOM-prod.classic|default", (e) => e.replace(/Error\(\w\(418\)\)/g, "void 0") ); - // 'relay-runtime/store/RelayPublishQueue|default' + window.cheatFbModule_replaceCode( - "umvbgfe}fvfvRitjmcvQzbmfS0fsput0fnjuovs.zbmfs", + "relay-runtime/store/RelayPublishQueue|default", (e) => e.replace( /,(\w)=new\(b\("relay-runtime\/mutations\/RelayRecordSourceProxy"/, ',$1=window["RlbiULLGWt"]=new(b("relay-runtime/mutations/RelayRecordSourceProxy"' ) ); - // 'relay-runtime/store/RelayPublishQueue|default' + window.cheatFbModule_replaceCode( - "umvbgfe}fvfvRitjmcvQzbmfS0fsput0fnjuovs.zbmfs", + "relay-runtime/store/RelayPublishQueue|default", (e) => (e = e.replace( /;(\w)\.commitPayload=function\(([\w,]+)\){/, @@ -396,29 +402,29 @@ function make_uuid() { (() => { if (window.xmxlgxMDjA) return; window.xmxlgxMDjA = !0; - let f = {}; - // 'xhrSimpleDataSerializer' - window.cheatFbModule_overrideCode("sf{jmbjsfTbubEfmqnjTsiy", (u) => { - const w = u[4].exports.default; - u[4].exports.default = function (...y) { - const c = y[0].fb_api_req_friendly_name; + let cache = {}; + window.cheatFbModule_overrideCode("xhrSimpleDataSerializer", (u) => { + const orig = u[4].exports.default; + u[4].exports.default = function (...args) { + const name = args[0].fb_api_req_friendly_name; return ( - c && f[c] && (y[0] = f[c].reduce((v, h) => (v = h(v)), y[0])), - w.apply(w, y) + name && + cache[name] && + (args[0] = cache[name].reduce((v, h) => (v = h(v)), args[0])), + orig.apply(orig, args) ); }; }); window.zkjQYvcSmF = (u, w) => { u = decodeModuleName(u); - f[u] = f[u] || []; - f[u].push(w); + cache[u] = cache[u] || []; + cache[u].push(w); }; })(); })(); - // 'MAWJobDefinitions|unseen-for-facebook' window.cheatFbModule_replaceCode( - "lppcfdbg.spg.offtov}topjujojgfEcpKXBN", + "MAWJobDefinitions|unseen-for-facebook", (n) => ( (n = n.replace( /markThreadAsRead:function.*?{/, @@ -428,14 +434,12 @@ function make_uuid() { ) ); - // 'MAWSecureTypingState|unseen-for-facebook' window.cheatFbModule_replaceCode( - "lppcfdbg.spg.offtov}fubuThojqzUfsvdfTXBN", + "MAWSecureTypingState|unseen-for-facebook", (n) => ((n = n.replaceAll("sendChatStateFromComposer", "none")), n) ); - // LSSendTypingIndicator - window.cheatFbModule_overrideCode("spubdjeoJhojqzUeofTTM", (n) => { + window.cheatFbModule_overrideCode("LSSendTypingIndicator", (n) => { if (n[4].exports) if (n[4].exports.default) { const l = n[4].exports.default; @@ -470,8 +474,7 @@ function make_uuid() { } }); - // 'LSOptimisticMarkThreadReadV2' - window.cheatFbModule_overrideCode("3WebfSebfsiUlsbNdjutjnjuqPTM", (n) => { + window.cheatFbModule_overrideCode("LSOptimisticMarkThreadReadV2", (n) => { if (n[4].exports) if (n[4].exports.default) { const l = n[4].exports.default; @@ -500,8 +503,7 @@ function make_uuid() { } }); - // 'LSOptimisticMarkThreadReadV2Impl' - window.cheatFbModule_overrideCode("mqnJ3WebfSebfsiUlsbNdjutjnjuqPTM", (n) => { + window.cheatFbModule_overrideCode("LSOptimisticMarkThreadReadV2Impl", (n) => { if (n[4].exports) if (n[4].exports.default) { const l = n[4].exports.default; @@ -530,9 +532,8 @@ function make_uuid() { } }); - // 'LSOptimisticMarkThreadReadV2ImplWeb' window.cheatFbModule_overrideCode( - "cfXmqnJ3WebfSebfsiUlsbNdjutjnjuqPTM", + "LSOptimisticMarkThreadReadV2ImplWeb", (n) => { if (n[4].exports) if (n[4].exports.default) { @@ -563,9 +564,8 @@ function make_uuid() { } ); - // 'StoriesSuspenseBucketContainer.react|unseen-for-facebook' window.cheatFbModule_replaceCode( - "lppcfdbg.spg.offtov}udbfs/sfojbuopDufldvCftofqtvTtfjspuT", + "StoriesSuspenseBucketContainer.react|unseen-for-facebook", (n) => ( (n = n.replace( /,onCardSeen:(\w),/g, From a84abacfb9cb44f3b9da9424aad6b2659c8d6ff8 Mon Sep 17 00:00:00 2001 From: "hoang.tran12" <99.hoangtran@gmail.com> Date: Wed, 3 Jul 2024 18:32:45 +0700 Subject: [PATCH 05/44] no smooth --- scripts/backup/auto-like-fb.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/backup/auto-like-fb.js b/scripts/backup/auto-like-fb.js index 3e22998b..e1277934 100644 --- a/scripts/backup/auto-like-fb.js +++ b/scripts/backup/auto-like-fb.js @@ -13,7 +13,9 @@ javascript: (async function () { } function scrollToBottom() { - window.scrollTo(0, document.body.scrollHeight, { behavior: "smooth" }); + window.scrollTo(0, document.body.scrollHeight, { + // behavior: "smooth", + }); } const doneKey = "auto-like-done"; @@ -37,7 +39,7 @@ javascript: (async function () { for (let btn of btns) { btn.scrollIntoView({ block: "center", - behavior: "smooth", + // behavior: "smooth", }); btn.click(); await sleep(500); @@ -51,7 +53,7 @@ javascript: (async function () { btns.splice(btns.indexOf(btn), 1); } scrollToBottom(); - await sleep(1000); + await sleep(3000); } alert("xong"); })(); From e8c28934706efea1cb12e7820616dcdaa037458a Mon Sep 17 00:00:00 2001 From: HoangTran <99.hoangtran@gmail.com> Date: Thu, 4 Jul 2024 00:35:28 +0700 Subject: [PATCH 06/44] WIP --- scripts/backup/m38u_detector.js | 820 ++++++++++++++++++++++++ scripts/fb_downloadWatchingVideo.js | 13 +- scripts/youtube_localDownloader.js | 430 +++++++++++++ scripts/youtube_localDownloader_main.js | 2 +- working_note.md | 6 +- 5 files changed, 1260 insertions(+), 11 deletions(-) create mode 100644 scripts/backup/m38u_detector.js diff --git a/scripts/backup/m38u_detector.js b/scripts/backup/m38u_detector.js new file mode 100644 index 00000000..e0066ae8 --- /dev/null +++ b/scripts/backup/m38u_detector.js @@ -0,0 +1,820 @@ +// ==UserScript== +// @name m3u8视频侦测下载器【自动嗅探】 +// @name:zh-CN m3u8视频侦测下载器【自动嗅探】 +// @name:zh-TW m3u8視頻偵測下載器【自動嗅探】 +// @name:en M3U8 Video Detector and Downloader +// @version 1.4.1 +// @description 自动检测页面m3u8视频并进行完整下载。检测到m3u8链接后会自动出现在页面右上角位置,点击下载即可跳转到m3u8下载器。 +// @description:zh-CN 自动检测页面m3u8视频并进行完整下载。检测到m3u8链接后会自动出现在页面右上角位置,点击下载即可跳转到m3u8下载器。 +// @description:zh-TW 自動檢測頁面m3u8視頻並進行完整下載。檢測到m3u8鏈接後會自動出現在頁面右上角位置,點擊下載即可跳轉到m3u8下載器。 +// @description:en Automatically detect the m3u8 video of the page and download it completely. Once detected the m3u8 link, it will appear in the upper right corner of the page. Click download to jump to the m3u8 downloader. +// @icon https://tools.thatwind.com/favicon.png +// @author allFull +// @namespace https://tools.thatwind.com/ +// @homepage https://tools.thatwind.com/tool/m3u8downloader +// @match *://*/* +// @exclude *://www.diancigaoshou.com/* +// @require https://cdn.jsdelivr.net/npm/m3u8-parser@4.7.1/dist/m3u8-parser.min.js +// @connect * +// @grant unsafeWindow +// @grant GM_openInTab +// @grant GM.openInTab +// @grant GM_getValue +// @grant GM.getValue +// @grant GM_setValue +// @grant GM.setValue +// @grant GM_deleteValue +// @grant GM.deleteValue +// @grant GM_xmlhttpRequest +// @grant GM.xmlHttpRequest +// @grant GM_download +// @run-at document-start +// ==/UserScript== + +(function () { + "use strict"; + + const mgmapi = { + addStyle(s) { + let style = document.createElement("style"); + style.innerHTML = s; + document.documentElement.appendChild(style); + }, + async getValue(name, defaultVal) { + return await (typeof GM_getValue === "function" + ? GM_getValue + : GM.getValue)(name, defaultVal); + }, + async setValue(name, value) { + return await (typeof GM_setValue === "function" + ? GM_setValue + : GM.setValue)(name, value); + }, + async deleteValue(name) { + return await (typeof GM_deleteValue === "function" + ? GM_deleteValue + : GM.deleteValue)(name); + }, + openInTab(url, open_in_background = false) { + return (typeof GM_openInTab === "function" ? GM_openInTab : GM.openInTab)( + url, + open_in_background + ); + }, + xmlHttpRequest(details) { + return ( + typeof GM_xmlhttpRequest === "function" + ? GM_xmlhttpRequest + : GM.xmlHttpRequest + )(details); + }, + download(details) { + return this.openInTab(details.url); + + if (typeof GM_download === "function") { + this.message( + "下载中,请留意浏览器下载弹窗\nDownloading, pay attention to the browser's download pop-up.", + 3000 + ); + return GM_download(details); + } else { + this.openInTab(details.url); + } + }, + copyText(text) { + copyTextToClipboard(text); + function copyTextToClipboard(text) { + // 复制文本 + var copyFrom = document.createElement("textarea"); + copyFrom.textContent = text; + document.body.appendChild(copyFrom); + copyFrom.select(); + document.execCommand("copy"); + copyFrom.blur(); + document.body.removeChild(copyFrom); + } + }, + message(text, disappearTime = 5000) { + const id = "f8243rd238-gm-message-panel"; + let p = document.querySelector(`#${id}`); + if (!p) { + p = document.createElement("div"); + p.id = id; + p.style = ` + position: fixed; + bottom: 20px; + right: 20px; + display: flex; + flex-direction: column; + align-items: end; + z-index: 999999999999999; + `; + (document.body || document.documentElement).appendChild(p); + } + let mdiv = document.createElement("div"); + mdiv.innerText = text; + mdiv.style = ` + padding: 3px 8px; + border-radius: 5px; + background: black; + box-shadow: #000 1px 2px 5px; + margin-top: 10px; + font-size: small; + color: #fff; + text-align: right; + `; + p.appendChild(mdiv); + setTimeout(() => { + p.removeChild(mdiv); + }, disappearTime); + }, + }; + + if ( + location.host === "tools.thatwind.com" || + location.host === "localhost:3000" + ) { + mgmapi.addStyle("#userscript-tip{display:none !important;}"); + + // 对请求做代理 + const _fetch = unsafeWindow.fetch; + unsafeWindow.fetch = async function (...args) { + try { + let response = await _fetch(...args); + if (response.status !== 200) throw new Error(response.status); + return response; + } catch (e) { + // 失败请求使用代理 + if (args.length == 1) { + console.log(`请求代理:${args[0]}`); + return await new Promise((resolve, reject) => { + let referer = new URLSearchParams(location.hash.slice(1)).get( + "referer" + ); + let headers = {}; + if (referer) { + referer = new URL(referer); + headers = { + origin: referer.origin, + referer: referer.href, + }; + } + mgmapi.xmlHttpRequest({ + method: "GET", + url: args[0], + responseType: "arraybuffer", + headers, + onload(r) { + resolve({ + status: r.status, + headers: new Headers( + r.responseHeaders + .split("\n") + .filter((n) => n) + .map((s) => s.split(/:\s*/)) + .reduce((all, [a, b]) => { + all[a] = b; + return all; + }, {}) + ), + async text() { + return r.responseText; + }, + async arrayBuffer() { + return r.response; + }, + }); + }, + onerror() { + reject(new Error()); + }, + }); + }); + } else { + throw e; + } + } + }; + + return; + } + + // iframe 信息交流 + // 目前只用于获取顶部标题 + window.addEventListener("message", async (e) => { + if (e.data === "3j4t9uj349-gm-get-title") { + let name = `top-title-${Date.now()}`; + await mgmapi.setValue(name, document.title); + e.source.postMessage(`3j4t9uj349-gm-top-title-name:${name}`, "*"); + } + }); + + function getTopTitle() { + return new Promise((resolve) => { + window.addEventListener("message", async function l(e) { + if (typeof e.data === "string") { + if (e.data.startsWith("3j4t9uj349-gm-top-title-name:")) { + let name = e.data.slice("3j4t9uj349-gm-top-title-name:".length); + await new Promise((r) => setTimeout(r, 5)); // 等5毫秒 确定 setValue 已经写入 + resolve(await mgmapi.getValue(name)); + mgmapi.deleteValue(name); + window.removeEventListener("message", l); + } + } + }); + window.top.postMessage("3j4t9uj349-gm-get-title", "*"); + }); + } + + { + // 请求检测 + // const _fetch = unsafeWindow.fetch; + // unsafeWindow.fetch = function (...args) { + // if (checkUrl(args[0])) doM3U({ url: args[0] }); + // return _fetch(...args); + // } + + const _r_text = unsafeWindow.Response.prototype.text; + unsafeWindow.Response.prototype.text = function () { + return new Promise((resolve, reject) => { + _r_text + .call(this) + .then((text) => { + resolve(text); + if (checkContent(text)) doM3U({ url: this.url, content: text }); + }) + .catch(reject); + }); + }; + + const _open = unsafeWindow.XMLHttpRequest.prototype.open; + unsafeWindow.XMLHttpRequest.prototype.open = function (...args) { + this.addEventListener("load", () => { + try { + let content = this.responseText; + if (checkContent(content)) doM3U({ url: args[1], content }); + } catch {} + }); + // checkUrl(args[1]); + return _open.apply(this, args); + }; + + function checkUrl(url) { + url = new URL(url, location.href); + if (url.pathname.endsWith(".m3u8") || url.pathname.endsWith(".m3u")) { + // 发现 + return true; + } + } + + function checkContent(content) { + if (content.trim().startsWith("#EXTM3U")) { + return true; + } + } + + // 检查纯视频 + setInterval(doVideos, 1000); + } + + const rootDiv = document.createElement("div"); + rootDiv.style = ` + position: fixed; + z-index: 9999999999999999; + opacity: 0.9; + `; + rootDiv.style.display = "none"; + document.documentElement.appendChild(rootDiv); + + const shadowDOM = rootDiv.attachShadow({ mode: "open" }); + const wrapper = document.createElement("div"); + shadowDOM.appendChild(wrapper); + + // 指示器 + const bar = document.createElement("div"); + bar.style = ` + text-align: right; + `; + bar.innerHTML = ` + + + + `; + + wrapper.appendChild(bar); + + // 样式 + const style = document.createElement("style"); + + style.innerHTML = ` + .number-indicator{ + position:relative; + } + + .number-indicator::after{ + content: attr(data-number); + position: absolute; + bottom: 0; + right: 0; + color: #40a9ff; + font-size: 14px; + font-weight: bold; + background: #000; + border-radius: 10px; + padding: 3px 5px; + } + + .copy-link:active{ + color: #ccc; + } + + .download-btn:hover{ + text-decoration: underline; + } + .download-btn:active{ + opacity: 0.9; + } + + .m3u8-item{ + color: white; + margin-bottom: 5px; + display: flex; + flex-direction: row; + background: black; + padding: 3px 10px; + border-radius: 3px; + font-size: 14px; + user-select: none; + } + + [data-shown="false"] { + opacity: 0.8; + zoom: 0.8; + } + + [data-shown="false"]:hover{ + opacity: 1; + } + + [data-shown="false"] .m3u8-item{ + display: none; + } + + `; + + wrapper.appendChild(style); + + const barBtn = bar.querySelector(".number-indicator"); + + // 关于显隐和移动 + + (async function () { + let shown = await GM_getValue("shown", true); + wrapper.setAttribute("data-shown", shown); + + let x = await GM_getValue("x", 10); + let y = await GM_getValue("y", 10); + + x = Math.min(innerWidth - 50, x); + y = Math.min(innerHeight - 50, y); + + if (x < 0) x = 0; + if (y < 0) y = 0; + + rootDiv.style.top = `${y}px`; + rootDiv.style.right = `${x}px`; + + barBtn.addEventListener("mousedown", (e) => { + let startX = e.pageX; + let startY = e.pageY; + + let moved = false; + + let mousemove = (e) => { + let offsetX = e.pageX - startX; + let offsetY = e.pageY - startY; + if (moved || Math.abs(offsetX) + Math.abs(offsetY) > 5) { + moved = true; + rootDiv.style.top = `${y + offsetY}px`; + rootDiv.style.right = `${x - offsetX}px`; + } + }; + let mouseup = (e) => { + let offsetX = e.pageX - startX; + let offsetY = e.pageY - startY; + + if (moved) { + x -= offsetX; + y += offsetY; + mgmapi.setValue("x", x); + mgmapi.setValue("y", y); + } else { + shown = !shown; + mgmapi.setValue("shown", shown); + wrapper.setAttribute("data-shown", shown); + } + + removeEventListener("mousemove", mousemove); + removeEventListener("mouseup", mouseup); + }; + addEventListener("mousemove", mousemove); + addEventListener("mouseup", mouseup); + }); + })(); + + let count = 0; + let shownUrls = []; + + function doVideos() { + for (let v of Array.from(document.querySelectorAll("video"))) { + if ( + v.duration && + v.src && + v.src.startsWith("http") && + !shownUrls.includes(v.src) + ) { + const src = v.src; + + shownUrls.push(src); + showVideo({ + type: "video", + url: new URL(src), + duration: `${Math.ceil((v.duration * 10) / 60) / 10} mins`, + download() { + const details = { + url: src, + name: (() => { + let name = new URL(src).pathname.split("/").slice(-1)[0]; + if (!/\.\w+$/.test(name)) { + if (name.match(/^\s*$/)) name = Date.now(); + name = name + ".mp4"; + } + return name; + })(), + headers: { + // referer: location.origin, // 不允许该头 + origin: location.origin, + }, + onerror(e) { + mgmapi.openInTab(src); + }, + }; + mgmapi.download(details); + }, + }); + } + } + } + + async function doM3U({ url, content }) { + url = new URL(url); + + if (shownUrls.includes(url.href)) return; + + // 解析 m3u + content = content || (await (await fetch(url)).text()); + + const parser = new m3u8Parser.Parser(); + parser.push(content); + parser.end(); + const manifest = parser.manifest; + + if (manifest.segments) { + let duration = 0; + manifest.segments.forEach((segment) => { + duration += segment.duration; + }); + manifest.duration = duration; + } + + showVideo({ + type: "m3u8", + url, + duration: manifest.duration + ? `${Math.ceil((manifest.duration * 10) / 60) / 10} mins` + : manifest.playlists + ? `多(Multi)(${manifest.playlists.length})` + : "未知(unknown)", + async download() { + mgmapi.openInTab( + `https://tools.thatwind.com/tool/m3u8downloader#${new URLSearchParams( + { + m3u8: url.href, + referer: location.href, + filename: (await getTopTitle()) || "", + } + )}` + ); + }, + }); + } + + async function showVideo({ type, url, duration, download }) { + let div = document.createElement("div"); + div.className = "m3u8-item"; + div.innerHTML = ` + ${type} + + ${duration} + 下载(Download) + `; + + div.querySelector(".copy-link").addEventListener("click", () => { + // 复制链接 + mgmapi.copyText(url.href); + mgmapi.message("已复制链接 (link copied)", 2000); + }); + + div.querySelector(".download-btn").addEventListener("click", download); + + rootDiv.style.display = "block"; + + count++; + + shownUrls.push(url.href); + + bar.querySelector(".number-indicator").setAttribute("data-number", count); + + wrapper.appendChild(div); + } +})(); + +(function () { + "use strict"; + + const reg = /magnet:\?xt=urn:btih:\w{10,}([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; + + let l = navigator.language || "en"; + if (l.startsWith("en-")) l = "en"; + else if (l.startsWith("zh-")) l = "zh-CN"; + else l = "en"; + + const T = { + en: { + play: "Play", + }, + "zh-CN": { + play: "播放", + }, + }[l]; + + whenDOMReady(() => { + addStyle(` + button[data-wtmzjk-mag-url]{ + all: initial; + border: none; + outline: none; + background: none; + background: #f7d308; + background: #08a6f7; + margin: 2px 8px; + border-radius: 3px; + color: white; + cursor: pointer; + display: inline-flex; + height: 1.6em; + padding: 0 .8em; + align-items: center; + justify-content: center; + transition: background .15s; + text-decoration: none; + border-radius: 0.8em; + font-size: small; + } + button[data-wtmzjk-mag-url]>svg{ + height: 60%; + fill: white; + pointer-events: none; + } + button[data-wtmzjk-mag-url]:hover{ + background: #fae157; + background: #39b9f9; + } + button[data-wtmzjk-mag-url]:active{ + background: #dfbe07; + background: #0797df; + } + button[data-wtmzjk-mag-url]>span{ + pointer-events: none; + font-size: small;margin-right: .5em;font-weight:bold;color:white !important; + } + `); + window.addEventListener("click", onEvents, true); + window.addEventListener("mousedown", onEvents, true); + window.addEventListener("mouseup", onEvents, true); + + watchBodyChange(work); + }); + + function onEvents(e) { + if (e.target.hasAttribute("data-wtmzjk-mag-url")) { + e.preventDefault(); + e.stopPropagation(); + if (e.type == "click") { + let a = document.createElement("a"); + a.href = + "https://www.diancigaoshou.com/#" + + new URLSearchParams({ + url: e.target.getAttribute("data-wtmzjk-mag-url"), + }); + a.target = "_blank"; + a.click(); + } + } + } + + function createWatchButton(url, isForPlain = false) { + let button = document.createElement("button"); + button.setAttribute("data-wtmzjk-mag-url", url); + if (isForPlain) button.setAttribute("data-wtmzjk-button-for-plain", ""); + button.innerHTML = `${T.play}`; + return button; + } + + function hasPlainMagUrlThatNotHandled() { + let m = document.body.textContent.match(new RegExp(reg, "g")); + return ( + document.querySelectorAll(`[data-wtmzjk-button-for-plain]`).length != + (m ? m.length : 0) + ); + } + + function work() { + if (!document.body) return; + if (hasPlainMagUrlThatNotHandled()) { + for (let node of getAllTextNodes(document.body)) { + if ( + node.nextSibling && + node.nextSibling.hasAttribute && + node.nextSibling.hasAttribute("data-wtmzjk-mag-url") + ) + continue; + let text = node.nodeValue; + if (!reg.test(text)) continue; + let match = text.match(reg); + if (match) { + let url = match[0]; + let p = node.parentNode; + p.insertBefore( + document.createTextNode(text.slice(0, match.index + url.length)), + node + ); + p.insertBefore(createWatchButton(url, true), node); + p.insertBefore( + document.createTextNode(text.slice(match.index + url.length)), + node + ); + p.removeChild(node); + } + } + } + for (let a of Array.from( + document.querySelectorAll( + [ + "href", + "value", + "data-clipboard-text", + "data-value", + "title", + "alt", + "data-url", + "data-magnet", + "data-copy", + ] + .map((n) => `[${n}*="magnet:?xt=urn:btih:"]`) + .join(",") + ) + )) { + if ( + a.nextSibling && + a.nextSibling.hasAttribute && + a.nextSibling.hasAttribute("data-wtmzjk-mag-url") + ) + continue; // 已经添加 + if (reg.test(a.textContent)) continue; + for (let attr of a.getAttributeNames()) { + let val = a.getAttribute(attr); + if (!reg.test(val)) continue; + let url = val.match(reg)[0]; + a.parentNode.insertBefore(createWatchButton(url), a.nextSibling); + } + } + } + + function watchBodyChange(onchange) { + let timeout; + let observer = new MutationObserver(() => { + if (!timeout) { + timeout = setTimeout(() => { + timeout = null; + onchange(); + }, 200); + } + }); + observer.observe(document.documentElement, { + childList: true, + subtree: true, + attributes: true, + characterData: true, + }); + } + + function getAllTextNodes(parent) { + var re = []; + if ( + [ + "STYLE", + "SCRIPT", + "BASE", + "COMMAND", + "LINK", + "META", + "TITLE", + "XTRANS-TXT", + "XTRANS-TXT-GROUP", + "XTRANS-POPUP", + ].includes(parent.tagName) + ) + return re; + for (let node of parent.childNodes) { + if (node.childNodes.length) re = re.concat(getAllTextNodes(node)); + else if ( + Text.prototype.isPrototypeOf(node) && + !node.nodeValue.match(/^\s*$/) + ) + re.push(node); + } + return re; + } + + function whenDOMReady(f) { + if (document.body) f(); + else window.addEventListener("DOMContentLoaded", f); + } + + function addStyle(s) { + let style = document.createElement("style"); + style.innerHTML = s; + document.documentElement.appendChild(style); + } +})(); diff --git a/scripts/fb_downloadWatchingVideo.js b/scripts/fb_downloadWatchingVideo.js index 9c78dc6a..1e1128fc 100644 --- a/scripts/fb_downloadWatchingVideo.js +++ b/scripts/fb_downloadWatchingVideo.js @@ -31,18 +31,13 @@ export default { let listVideoId = await shared.getListVideoIdInWebsite(); if (!listVideoId?.length > 0) throw Error("Không tìm thấy video"); - for (let videoId of listVideoId) { - if (!videoId) continue; - - setLoadingText("Đang lấy token dtsg..."); - let dtsg = await fb_videoDownloader.getDtsg(); + setLoadingText("Đang lấy token dtsg..."); + let dtsg = await fb_videoDownloader.getDtsg(); + for (let videoId of listVideoId) { setLoadingText("Đang tìm video url..."); let videoUrl = await fb_videoDownloader.getLinkFbVideo(videoId, dtsg); - - if (!videoUrl) continue; - - UfsGlobal.Utils.downloadURL(videoUrl, "fb_video.mp4"); + if (videoUrl) UfsGlobal.Utils.downloadURL(videoUrl, "fb_video.mp4"); } } catch (e) { alert("ERROR: " + e); diff --git a/scripts/youtube_localDownloader.js b/scripts/youtube_localDownloader.js index eeef4ab3..cbb07d30 100644 --- a/scripts/youtube_localDownloader.js +++ b/scripts/youtube_localDownloader.js @@ -1,3 +1,6 @@ +import { UfsGlobal } from "./content-scripts/ufs_global.js"; +const { promiseAllStepN } = UfsGlobal.Utils; + export default { icon: "https://www.youtube.com/s/desktop/accca349/img/favicon_48x48.png", name: { @@ -32,4 +35,431 @@ export default { window.open("/scripts/youtube_localDownloader.html"); }, }, + + pageScript: { + onDocumentEnd: () => { + try { + onDocumentEnd(); + } catch (e) { + console.error(e); + } + }, + }, }; + +async function onDocumentEnd() { + const LANG_FALLBACK = "en"; + const LOCALE = { + en: { + togglelinks: "Show/Hide Links", + stream: "Stream", + adaptive: "Adaptive (No Sound)", + videoid: "Video ID: ", + inbrowser_adaptive_merger: + "Online Adaptive Video & Audio Merger (FFmpeg)", + dlmp4: "Download high-resolution mp4 in one click", + get_video_failed: + "Failed to get video infomation for unknown reason, refresh the page may work.", + live_stream_disabled_message: + "Local YouTube Downloader is not available for live stream", + }, + }; + for (const [lang, data] of Object.entries(LOCALE)) { + if (lang === LANG_FALLBACK) continue; + for (const key of Object.keys(LOCALE[LANG_FALLBACK])) { + if (!(key in data)) { + data[key] = LOCALE[LANG_FALLBACK][key]; + } + } + } + const findLang = (l) => { + l = l.replace("-Hant", ""); // special case for zh-Hant-TW + // language resolution logic: zh-tw --(if not exists)--> zh --(if not exists)--> LANG_FALLBACK(en) + l = l.toLowerCase().replace("_", "-"); + if (l in LOCALE) return l; + else if (l.length > 2) return findLang(l.split("-")[0]); + else return LANG_FALLBACK; + }; + const getLangCode = () => { + const html = document.querySelector("html"); + if (html) { + return html.lang; + } else { + return navigator.language; + } + }; + const $ = (s, x = document) => x.querySelector(s); + const $el = (tag, opts) => { + const el = document.createElement(tag); + Object.assign(el, opts); + return el; + }; + + const load = async (playerResponse) => { + try { + debugger; + const basejs = + (typeof ytplayer !== "undefined" && + "config" in ytplayer && + ytplayer.config.assets + ? "https://" + location.host + ytplayer.config.assets.js + : "web_player_context_config" in ytplayer + ? "https://" + + location.host + + ytplayer.web_player_context_config.jsUrl + : null) || $('script[src$="base.js"]').src; + const res = await fetch(basejs); + const text = await res.text(); + const decsig = parseDecsig(text); + const id = parseQuery(location.search).v; + const data = parseResponse(id, playerResponse, decsig); + console.log("video loaded: %s", id); + app.isLiveStream = + data.playerResponse.playabilityStatus.liveStreamability != null; + app.id = id; + app.stream = data.stream; + app.adaptive = data.adaptive; + app.details = data.details; + + const actLang = getLangCode(); + if (actLang != null) { + const lang = findLang(actLang); + console.log("youtube ui lang: %s", actLang); + console.log("ytdl lang:", lang); + app.lang = lang; + } + } catch (err) { + alert(app.strings.get_video_failed); + console.error("load", err); + } + }; + + const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + + const parseDecsig = (data) => { + try { + if (data.startsWith("var script")) { + // they inject the script via script tag + const obj = {}; + // const document = { + // createElement: () => obj, + // head: { appendChild: () => {} }, + // }; + eval(data); + data = obj.innerHTML; + } + const fnnameresult = /=([a-zA-Z0-9\$_]+?)\(decodeURIComponent/.exec(data); + const fnname = fnnameresult[1]; + const _argnamefnbodyresult = new RegExp( + escapeRegExp(fnname) + "=function\\((.+?)\\){((.+)=\\2.+?)}" + ).exec(data); + const [_, argname, fnbody] = _argnamefnbodyresult; + const helpernameresult = /;([a-zA-Z0-9$_]+?)\..+?\(/.exec(fnbody); + const helpername = helpernameresult[1]; + const helperresult = new RegExp( + "var " + escapeRegExp(helpername) + "={[\\s\\S]+?};" + ).exec(data); + const helper = helperresult[0]; + console.log(`parsedecsig result: %s=>{%s\n%s}`, argname, helper, fnbody); + return new Function([argname], helper + "\n" + fnbody); + } catch (e) { + console.error("parsedecsig error: %o", e); + console.info("script content: %s", data); + console.info( + 'If you encounter this error, please copy the full "script content" to https://pastebin.com/ for me.' + ); + } + }; + const parseQuery = (s) => + [...new URLSearchParams(s).entries()].reduce( + (acc, [k, v]) => ((acc[k] = v), acc), + {} + ); + const parseResponse = (id, playerResponse, decsig) => { + console.log(`video %s playerResponse: %o`, id, playerResponse); + let stream = []; + if (playerResponse.streamingData.formats) { + stream = playerResponse.streamingData.formats.map((x) => + Object.assign({}, x, parseQuery(x.cipher || x.signatureCipher)) + ); + console.log(`video %s stream: %o`, id, stream); + for (const obj of stream) { + if (obj.s) { + obj.s = decsig(obj.s); + obj.url += `&${obj.sp}=${encodeURIComponent(obj.s)}`; + } + } + } + + let adaptive = []; + if (playerResponse.streamingData.adaptiveFormats) { + adaptive = playerResponse.streamingData.adaptiveFormats.map((x) => + Object.assign({}, x, parseQuery(x.cipher || x.signatureCipher)) + ); + console.log(`video %s adaptive: %o`, id, adaptive); + for (const obj of adaptive) { + if (obj.s) { + obj.s = decsig(obj.s); + obj.url += `&${obj.sp}=${encodeURIComponent(obj.s)}`; + } + } + } + console.log(`video %s result: %o`, id, { stream, adaptive }); + return { + stream, + adaptive, + details: playerResponse.videoDetails, + playerResponse, + }; + }; + + // video downloader + const xhrDownloadUint8Array = async ({ url, contentLength }, progressCb) => { + if (typeof contentLength === "string") + contentLength = parseInt(contentLength); + progressCb({ + loaded: 0, + total: contentLength, + speed: 0, + }); + const chunkSize = 65536; + const getBuffer = (start, end) => + fetch(url + `&range=${start}-${end ? end - 1 : ""}`).then((r) => + r.arrayBuffer() + ); + const data = new Uint8Array(contentLength); + let downloaded = 0; + const tasks = []; + const startTime = Date.now(); + + for (let start = 0; start < contentLength; start += chunkSize) { + const exceeded = start + chunkSize > contentLength; + const curChunkSize = exceeded ? contentLength - start : chunkSize; + const end = exceeded ? null : start + chunkSize; + tasks.push(() => { + console.log("dl start", url, start, end); + return getBuffer(start, end) + .then((buf) => { + console.log("dl done", url, start, end); + downloaded += curChunkSize; + data.set(new Uint8Array(buf), start); + const ds = (Date.now() - startTime + 1) / 1000; + progressCb({ + loaded: downloaded, + total: contentLength, + speed: downloaded / ds, + }); + }) + .catch((err) => { + console.error("Download error"); + }); + }); + } + await promiseAllStepN(6, tasks); + return data; + }; + + let ffWorkerLoaded = false, + ffWorker; + const mergeVideo = async (video, audio) => { + if (!ffWorkerLoaded) { + await UfsGlobal.DOM.injectScriptSrcAsync( + "https://unpkg.com/@ffmpeg/ffmpeg@0.6.1/dist/ffmpeg.min.js" + ); + ffWorker = FFmpeg.createWorker({ + logger: (m) => console.log(m.message), + }); + ffWorkerLoaded = true; + } + await ffWorker.write("video.mp4", video); + await ffWorker.write("audio.mp4", audio); + await ffWorker.run("-i video.mp4 -i audio.mp4 -c copy output.mp4", { + input: ["video.mp4", "audio.mp4"], + output: "output.mp4", + }); + const { data } = await ffWorker.read("output.mp4"); + await ffWorker.remove("output.mp4"); + return data; + }; + + // ===================== MAIN ====================== + await UfsGlobal.DOM.injectScriptSrc( + "https://unpkg.com/vue@2.6.10/dist/vue.js" + ); + const template = `
`; + const app = new Vue({ + data() { + return { + hide: true, + id: "", + isLiveStream: false, + stream: [], + adaptive: [], + details: null, + dark: false, + lang: findLang(getLangCode()), + }; + }, + computed: { + strings() { + return LOCALE[this.lang.toLowerCase()]; + }, + }, + methods: { + dlmp4() { + // openDownloadModel(this.adaptive, this.details.title); + }, + formatStreamText(vid) { + return [vid.qualityLabel, vid.quality].filter((x) => x).join(": "); + }, + formatAdaptiveText(vid) { + let str = [vid.qualityLabel, vid.mimeType].filter((x) => x).join(": "); + if (vid.mimeType.includes("audio")) { + str += ` ${Math.round(vid.bitrate / 1000)}kbps`; + } + return str; + }, + }, + template, + }); + + // attach element + const shadowHost = $el("div"); + const shadow = shadowHost.attachShadow + ? shadowHost.attachShadow({ mode: "closed" }) + : shadowHost; // no shadow dom + console.log("shadowHost: %o", shadowHost); + const container = $el("div"); + shadow.appendChild(container); + app.$mount(container); + + // hook fetch response + const ff = fetch; + window.fetch = (...args) => { + if (args[0] instanceof Request) { + return ff(...args).then((resp) => { + if (resp.url.includes("player")) { + debugger; + resp.clone().json().then(load); + } + return resp; + }); + } + return ff(...args); + }; + + // attach element + const it = setInterval(() => { + const el = + $("ytd-watch-metadata") || + $("#info-contents") || + $("#watch-header") || + $(".page-container:not([hidden]) ytm-item-section-renderer>lazy-list"); + if (el && !el.contains(shadowHost)) { + el.appendChild(shadowHost); + clearInterval(it); + } + }, 100); + + // init + const firstResp = window?.ytplayer?.config?.args?.raw_player_response; + debugger; + if (firstResp) { + load(firstResp); + } + + const css = ` +.hide{ +display: none; +} +.t-center{ +text-align: center; +} +.d-flex{ +display: flex; +} +.f-1{ +flex: 1; +} +.fs-14px{ +font-size: 14px; +} +.of-h{ +overflow: hidden; +} +.box{ +padding-top: .5em; +padding-bottom: .5em; +border-bottom: 1px solid var(--yt-border-color); +font-family: Arial; +} +.box-toggle{ +margin: 3px; +user-select: none; +-moz-user-select: -moz-none; +} +.ytdl-link-btn{ +display: block; +border: 1px solid !important; +border-radius: 3px; +text-decoration: none !important; +outline: 0; +text-align: center; +padding: 2px; +margin: 5px; +color: black; +} +a, .div-a{ +text-decoration: none; +color: var(--yt-button-color, inherit); +} +a:hover, .div-a:hover{ +color: var(--yt-spec-call-to-action, blue); +} +.box.dark{ +color: var(--yt-endpoint-color, var(--yt-spec-text-primary)); +} +.box.dark .ytdl-link-btn{ +color: var(--yt-endpoint-color, var(--yt-spec-text-primary)); +} +.box.dark .ytdl-link-btn:hover{ +color: rgba(200, 200, 255, 0.8); +} +.box.dark .box-toggle:hover{ +color: rgba(200, 200, 255, 0.8); +} +.c-pointer{ +cursor: pointer; +} +.lh-20{ +line-height: 20px; +} +`; + shadow.appendChild($el("style", { textContent: css })); +} diff --git a/scripts/youtube_localDownloader_main.js b/scripts/youtube_localDownloader_main.js index a00337d8..c61517f8 100644 --- a/scripts/youtube_localDownloader_main.js +++ b/scripts/youtube_localDownloader_main.js @@ -40,7 +40,7 @@ const xhrDownloadUint8Array = async ({ url, contentLength }, progressCb) => { }); }) .catch((err) => { - console.log("Download error"); + console.error("Download error", err); }); }); } diff --git a/working_note.md b/working_note.md index 98439369..7963f56e 100644 --- a/working_note.md +++ b/working_note.md @@ -1,9 +1,13 @@ # WORKING NOTES -## 30/05/2024 - 01/07/2024 +## 01/07/2024 - ? + +- [ ] check down video${videoDetails.shortDescription}
`; - document.body.appendChild(detailDiv); - - // video - for (let video of videos) { - const button = document.createElement("button"); - button.style = "display:block;margin-bottom:5px"; - button.innerHTML = ` - ${video.qualityLabel} - - ${video.width}x${video.height} - - ${formatSize(video.contentLength, 2)} - ${video.audioQuality ? "" : " (no audio)"}`; - button.onclick = () => { - let data = xhrDownloadUint8Array(video, (progress) => { - console.log(progress); - }); - // saveAs(video.url, "video.mp4", { - // onprogress: (e) => { - // console.log(e); - // }, - // }); - }; - document.body.appendChild(button); - } - - // audio - for (let audio of audios) { - const div = document.createElement("div"); - div.innerHTML = ` - -- ${audio.audioTrack?.displayName || audio.audioQuality} - - ${formatSize(audio.contentLength, 2)} -
- `; - document.body.appendChild(div); - } - - // caption - for (let caption of captions) { - const div = document.createElement("div"); - div.innerHTML = ` -${caption.name?.simpleText}
- - Download - - `; - document.body.appendChild(div); - } -}; From b15dea9a5a507c45b768aa368ccb2d0c6fd25942 Mon Sep 17 00:00:00 2001 From: "hoang.tran12" <99.hoangtran@gmail.com> Date: Fri, 5 Jul 2024 18:40:10 +0700 Subject: [PATCH 10/44] find fb by phone/mail - WIP --- popup/index.js | 2 +- popup/tabs.js | 2 +- scripts/_test.js | 74 ++++++++++++++++++++++++++++++++++++++++ scripts/fb_GLOBAL.js | 39 +++++++++++++++++++++ scripts/helpers/utils.js | 2 +- working_note.md | 4 +++ 6 files changed, 120 insertions(+), 3 deletions(-) diff --git a/popup/index.js b/popup/index.js index 366af5b6..8e9be596 100644 --- a/popup/index.js +++ b/popup/index.js @@ -39,7 +39,7 @@ import { viewScriptSource, } from "./helpers/utils.js"; import { checkPass } from "../scripts/auto_lockWebsite.js"; -import _ from "../md/exportScriptsToMd.js"; +// import _ from "../md/exportScriptsToMd.js"; const settingsBtn = document.querySelector(".settings"); const openInNewTabBtn = document.querySelector(".open-in-newtab"); diff --git a/popup/tabs.js b/popup/tabs.js index c9ff666e..98c5aaa6 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -36,7 +36,7 @@ const tabs = [ { ...CATEGORY.search, scripts: [ - // s._test, + s._test, // s._ufs_statistic, s.similarWeb, s.similarWeb_bypassLimit, diff --git a/scripts/_test.js b/scripts/_test.js index 140501e6..986166a3 100644 --- a/scripts/_test.js +++ b/scripts/_test.js @@ -1,4 +1,5 @@ import { UfsGlobal } from "./content-scripts/ufs_global.js"; +import { fetchGraphQl, getFbdtsg } from "./fb_GLOBAL.js"; export default { icon: "", @@ -12,6 +13,79 @@ export default { }, popupScript: { + onClick: async () => { + function getAverageRGB(img) { + var blockSize = 5, // only visit every 5 pixels + defaultRGB = { r: 0, g: 0, b: 0 }, // for non-supporting envs + canvas = document.createElement("canvas"), + context = canvas.getContext && canvas.getContext("2d"), + data, + width, + height, + i = -4, + length, + rgb = { r: 0, g: 0, b: 0 }, + count = 0; + + if (!context) { + return defaultRGB; + } + + height = canvas.height = + img.naturalHeight || img.offsetHeight || img.height; + width = canvas.width = img.naturalWidth || img.offsetWidth || img.width; + + context.drawImage(img, 0, 0); + + try { + data = context.getImageData(0, 0, width, height); + } catch (e) { + /* security error, img on diff domain */ + return defaultRGB; + } + + length = data.data.length; + + while ((i += blockSize * 4) < length) { + ++count; + rgb.r += data.data[i]; + rgb.g += data.data[i + 1]; + rgb.b += data.data[i + 2]; + } + + // ~~ used to floor values + rgb.r = ~~(rgb.r / count); + rgb.g = ~~(rgb.g / count); + rgb.b = ~~(rgb.b / count); + + return rgb; + } + + function getAverageRGBFromUrl(url) { + return new Promise((resolve, reject) => { + let img = new Image(); + img.src = url; + img.onload = () => { + let rgb = getAverageRGB(img); + resolve(rgb); + }; + img.onerror = (error) => { + alert("Error: " + JSON.stringify(error)); + console.log(error); + reject(); + }; + }); + } + + getAverageRGBFromUrl( + "https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-1/352545274_2285354618338828_3224207586206963955_n.jpg?stp=dst-jpg_p480x480&ccb=1-7&_nc_sid=0ecb9b&_nc_ohc=7D3Usqt8u2UQ7kNvgEeWxht&_nc_ht=scontent.fsgn2-7.fna&oh=00_AYAeunf-6BuCakj2L59wVi8mNA5QuGlLuVQ6eROL5UKC8A&oe=668D93B9" + ).then(console.log); + + getAverageRGBFromUrl( + "https://www.facebook.com/profile/pic.php?cuid=AYjse6TURBs86Oy-7iO2UdCZFqYOhyemrWC2KV8yPo6ABGAHCWi87GNGtXwITHZJRPIOPLMTbuZetu6t3T9WQllYE5xhBm4t5rAZVKC1IGjSqGbJiwr9z4g-bDx6bHAPuqqXgfCaH4Yml-_UAAJgEGdftXSGc4uCKUer8j3oCtpLakjxWAOTYeNAzt-rWWp0fNtY03PE0XzLzPqKEI8leoS_08eYd_V9L4O_P1lwGxHyMA&square_px=64" + ).then(console.log); + }, + // selenium automation get album's images _onClick: async () => { const { openWebAndRunScript } = await import("./helpers/utils.js"); diff --git a/scripts/fb_GLOBAL.js b/scripts/fb_GLOBAL.js index 8efcbe50..d1ce0c11 100644 --- a/scripts/fb_GLOBAL.js +++ b/scripts/fb_GLOBAL.js @@ -119,6 +119,45 @@ export async function getUidFromUrl(url) { } return null; } +export async function searchUser(keyword, exact_match = true) { + const res = await fetchGraphQl( + { + doc_id: 7561210460668291, + variables: { + count: 5, + allow_streaming: false, + args: { + callsite: "COMET_GLOBAL_SEARCH", + config: { + exact_match: exact_match, + high_confidence_config: null, + intercept_config: null, + sts_disambiguation: null, + watch_config: null, + }, + experience: { + client_defined_experiences: [], + encoded_server_defined_params: null, + fbid: null, + type: "PEOPLE_TAB", + }, + filters: [], + text: keyword, + }, + cursor: null, + feedbackSource: 23, + fetch_filters: true, + renderLocation: "search_results_page", + scale: 2, + stream_initial_count: 0, + useDefaultActor: false, + }, + }, + await getFbdtsg() + ); + const json = JSON.parse(res); + console.log(json); +} // ============================================================================= // =================================== Friend ================================== diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index 883de28f..acb7b7b7 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -142,7 +142,7 @@ export function runFunc(fnPath = "", params = [], global = {}) { export async function trackEvent(scriptId) { console.log("trackEvent", scriptId, version); - // return; + return; try { let res = await fetch( // "http://localhost:3000/count", diff --git a/working_note.md b/working_note.md index 07520cd0..cb50c651 100644 --- a/working_note.md +++ b/working_note.md @@ -2,6 +2,10 @@ ## 01/07/2024 - ? +- [ ] get fb profile pic