From 1b2cca4f3b6b7f61573700961ccf845f815c7cc2 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Mon, 28 Nov 2022 20:52:56 +0700 Subject: [PATCH 001/164] fix find shared account --- scripts/search_sharedAccount.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/search_sharedAccount.js b/scripts/search_sharedAccount.js index 8f57ff53..647ef54a 100644 --- a/scripts/search_sharedAccount.js +++ b/scripts/search_sharedAccount.js @@ -38,7 +38,8 @@ export default { alert("Lỗi: Không tìm thấy url trang web."); return; } - var url = providers[choice].getLink(escape(tab.url)); + let { hostname } = new URL(tab.url); + var url = providers[choice].getLink(hostname); w = open( url, "w", From 850bdbbfd008b482d4d20973b86f3ee329db5c7d Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Tue, 29 Nov 2022 03:20:59 +0700 Subject: [PATCH 002/164] update --- popup/tabs.js | 8 +- scripts/douyin_downloadAllVideoUser.js | 82 +++++++++++++++++ scripts/douyin_downloadVideo.js | 40 --------- scripts/douyin_downloadWachingVideo.js | 17 ++++ scripts/enableTextSelection.js | 2 + scripts/helpers/utils.js | 24 +++-- scripts/index.js | 18 +++- scripts/insta_getAllUserMedia.js | 88 +++++++++---------- .../{download_audio.js => showTheAudios.js} | 0 scripts/showTheVideos.js | 50 +++++++++++ 10 files changed, 232 insertions(+), 97 deletions(-) create mode 100644 scripts/douyin_downloadAllVideoUser.js delete mode 100644 scripts/douyin_downloadVideo.js create mode 100644 scripts/douyin_downloadWachingVideo.js rename scripts/{download_audio.js => showTheAudios.js} (100%) create mode 100644 scripts/showTheVideos.js diff --git a/popup/tabs.js b/popup/tabs.js index 15b37eb9..c13b8177 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -55,11 +55,12 @@ const tabs = [ s.getLinkLuanxt, s.getFavicon, createTitle("--- Music ---", "--- Nhạc ---"), - s.download_audio, + s.showTheAudios, s.nhaccuatui_downloader, s.zingmp3_downloadMusic, s.zingmp3_oldLayout, createTitle("--- Videos ---", "--- Video ---"), + s.showTheVideos, s.download_video, s.download_video2, createTitle("--- Photos ---", "--- Ảnh ---"), @@ -136,8 +137,11 @@ const tabs = [ { ...CATEGORY.tiktok, scripts: [ + createTitle("--- Tiktok ---", "--- Tiktok ---"), s.tiktok_downloadVideo, - s.douyin_downloadVideo, + createTitle("--- Douyin ---", "--- Douyin ---"), + s.douyin_downloadWachingVideo, + s.douyin_downloadAllVideoUser, createTitle("--- Doutu.be ---", "--- Doutu.be ---"), s.doutube_enableDownloadVideo, s.doutube_downloadWatchingVideo, diff --git a/scripts/douyin_downloadAllVideoUser.js b/scripts/douyin_downloadAllVideoUser.js new file mode 100644 index 00000000..0025df89 --- /dev/null +++ b/scripts/douyin_downloadAllVideoUser.js @@ -0,0 +1,82 @@ +import { downloadData, getCurrentTab, showLoading } from "./helpers/utils.js"; + +export default { + icon: "https://www.tiktok.com/favicon.ico", + name: { + en: "Douyin - Download all user videos", + vi: "Douyin - Tải mọi video của user", + }, + description: { + en: "", + vi: "", + }, + runInExtensionContext: true, + + func: function () { + // Original source code from: https://github.com/N-X-T/Download-All-Video-User-Douyin/blob/main/DownloadAllVideoDouyin.js?fbclid=IwAR3ne_fDNpRpduM23kLJxOpDaQjI2-V3CA3iZ0BA0gvCgGdnMCfemyoMyO8 + // Modified by Hoang Tran + + async function getPostData(uid, max_cursor) { + let API_ENDPOINT = + "https://www.iesdouyin.com/web/api/v2/aweme/post/?sec_uid=" + + uid + + "&count=10&max_cursor=" + + max_cursor; + let data = await fetch(API_ENDPOINT, { + headers: { + accept: "application/json", + "user-agent": + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)", + }, + method: "GET", + }); + data = await data.json(); + return data; + } + async function parsePostData(postData) { + let data = postData.aweme_list.map((item) => ({ + id: item.aweme_id, + src: item.video.play_addr.url_list[0], + desc: item.desc, + })); + + if (postData["has_more"] || postData["aweme_list"].length != 0) + return [data, postData["max_cursor"]]; + else return [data, 0]; + } + async function run() { + let { closeLoading, setLoadingText } = showLoading("Đang tìm uid..."); + try { + let tab = await getCurrentTab(); + let uid = + /https:\/\/www\.douyin\.com\/user\/([^?]+)/gm.exec(tab.url)?.[1] || + prompt("Nhập uid: "); + + if (!uid) return; + + setLoadingText(`Đang thu thập thông tin...`); + let max_cursor = 0; + let all_data = []; + while (1) { + let postData = await getPostData(uid, max_cursor); + let [data, cursor] = await parsePostData(postData); + max_cursor = cursor; + all_data.push(...data); + setLoadingText(`Đang thu thập douyin videos... (${all_data.length} video)`); + if (!max_cursor) break; + } + console.log(all_data); + downloadData( + all_data.map((_) => _.src).join("\n"), + "douyin_" + uid, + "txt" + ); + } catch (e) { + alert("ERROR: " + e); + } finally { + closeLoading(); + } + } + run(); + }, +}; diff --git a/scripts/douyin_downloadVideo.js b/scripts/douyin_downloadVideo.js deleted file mode 100644 index 9658d0e2..00000000 --- a/scripts/douyin_downloadVideo.js +++ /dev/null @@ -1,40 +0,0 @@ -export default { - icon: "https://www.douyin.com/favicon.ico", - name: { - en: "Douyin - Download videos", - vi: "Douyin - Tải videos", - }, - description: { - en: "Show all downloadable videos in current douyin webpage", - vi: "Hiển thị mọi video có thể tải trong trang douyin hiện tại", - }, - blackList: [], - whiteList: ["https://www.douyin.com/*"], - - func: function () { - let videos = Array.from(document.querySelectorAll("video")); - - if (!videos.length) { - alert("Không tìm thấy video nào."); - return; - } - - let html = ` -
-
- ${videos - .map((video) => { - return ``; - }) - .join("
")} - -
-
`; - - let div = document.createElement("div"); - div.innerHTML = html; - document.body.appendChild(div); - }, -}; diff --git a/scripts/douyin_downloadWachingVideo.js b/scripts/douyin_downloadWachingVideo.js new file mode 100644 index 00000000..be87d62e --- /dev/null +++ b/scripts/douyin_downloadWachingVideo.js @@ -0,0 +1,17 @@ +import showTheVideos from "./showTheVideos.js"; + +export default { + icon: "https://www.tiktok.com/favicon.ico", + name: { + en: "Douyin - Download watching video", + vi: "Douyin - Tải video đang xem", + }, + description: { + en: "Show all downloadable videos in current douyin webpage", + vi: "Hiển thị mọi video có thể tải trong trang douyin hiện tại", + }, + blackList: [], + whiteList: ["https://www.douyin.com/*"], + + func: showTheVideos.func, +}; diff --git a/scripts/enableTextSelection.js b/scripts/enableTextSelection.js index 6618a60e..62688ee3 100644 --- a/scripts/enableTextSelection.js +++ b/scripts/enableTextSelection.js @@ -28,5 +28,7 @@ export default { R("mousedown"); R("mouseup"); R("selectstart"); + + alert("Đã bật lại text selection.\nText selection enabled."); }, }; diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index c8d42f50..ab6546f8 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -169,6 +169,24 @@ export function downloadURI(uri, name) { document.body.removeChild(link); } +export function downloadData(data, filename, type) { + var file = new Blob([data], { type: type }); + if (window.navigator.msSaveOrOpenBlob) + window.navigator.msSaveOrOpenBlob(file, filename); + else { + var a = document.createElement("a"), + url = URL.createObjectURL(file); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + setTimeout(function () { + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + }, 0); + } +} + // Merge image uri // https://stackoverflow.com/a/50658710/11898496 // https://stackoverflow.com/a/50658710/11898496 @@ -367,11 +385,7 @@ export function showPopup(title = "", innerHTML = "") { let html = ` - - `; let div = document.createElement("div"); div.innerHTML = html; @@ -396,38 +368,6 @@ export function showPopup(title = "", innerHTML = "") {

${title}

${innerHTML} - - `; let div = document.createElement("div"); div.innerHTML = html; diff --git a/scripts/insta_storySaver.js b/scripts/insta_storySaver.js index dd253db8..d445e187 100644 --- a/scripts/insta_storySaver.js +++ b/scripts/insta_storySaver.js @@ -15,8 +15,7 @@ export default { // Source code extracted from: https://chrome.google.com/webstore/detail/story-saver/mafcolokinicfdmlidhaebadidhdehpk let videos = document.querySelectorAll("video"); - let videoUrl = null, - imgUrl = null; + let storyUrl = null; for (let i = videos.length - 1; i >= 0; i--) { if (videos[i].offsetHeight === 0) continue; let reactKey = ""; @@ -29,63 +28,63 @@ export default { } try { //prettier-ignore - videoUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children.props.children.props.implementations[0].data.hdSrc; + storyUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children.props.children.props.implementations[0].data.hdSrc; } catch (e) {} - if (videoUrl == null) { + if (storyUrl == null) { try { //prettier-ignore - videoUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children[0].props.children.props.implementations[1].data.hdSrc; + storyUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children[0].props.children.props.implementations[1].data.hdSrc; } catch (e) {} } - if (videoUrl == null) { + if (storyUrl == null) { try { //prettier-ignore - videoUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children.props.children.props.implementations[0].data.sdSrc; + storyUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children.props.children.props.implementations[0].data.sdSrc; } catch (e) {} } - if (videoUrl == null) { + if (storyUrl == null) { try { //prettier-ignore - videoUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children[0].props.children.props.implementations[1].data.sdSrc; + storyUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children[0].props.children.props.implementations[1].data.sdSrc; } catch (e) {} } - if (videoUrl == null) { + if (storyUrl == null) { try { //prettier-ignore - videoUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children.props.children.props.implementations[1].data.hdSrc; + storyUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children.props.children.props.implementations[1].data.hdSrc; } catch (e) {} } - if (videoUrl == null) { + if (storyUrl == null) { try { //prettier-ignore - videoUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children.props.children.props.implementations[1].data.sdSrc; + storyUrl = videos[i].parentElement.parentElement.parentElement.parentElement['__reactProps' + reactKey].children.props.children.props.implementations[1].data.sdSrc; } catch (e) {} } - if (videoUrl == null) { + if (storyUrl == null) { try { //prettier-ignore - videoUrl = videos[i]['__reactFiber' + reactKey].return.stateNode.props.videoData.$1.hd_src; + storyUrl = videos[i]['__reactFiber' + reactKey].return.stateNode.props.videoData.$1.hd_src; } catch (e) {} } - if (videoUrl == null) { + if (storyUrl == null) { try { //prettier-ignore - videoUrl = videos[i]['__reactFiber' + reactKey].return.stateNode.props.videoData.$1.sd_src; + storyUrl = videos[i]['__reactFiber' + reactKey].return.stateNode.props.videoData.$1.sd_src; } catch (e) {} } - if (videoUrl != null) break; + if (storyUrl != null) break; } - if (!videoUrl) { + if (!storyUrl) { let video = null; for (let i = 0; i < videos.length; i++) { if (videos[i].offsetHeight !== 0) video = videos[i]; } - videoUrl = video?.children[0]?.src; + storyUrl = video?.children[0]?.src; } - if (!videoUrl) { + if (!storyUrl) { let imgs = document.querySelectorAll("img"); for (let img of imgs) { if ( @@ -98,8 +97,7 @@ export default { } } - if (videoUrl) window.open(videoUrl); - else if (imgUrl) window.open(imgUrl); + if (storyUrl) window.open(storyUrl); else alert("Không tìm thấy instagram story nào trong trang web."); }, }; From 0a8450c0879240c22e257543cc6e4a23ed5367a0 Mon Sep 17 00:00:00 2001 From: "hoang.tran12" Date: Wed, 30 Nov 2022 17:49:58 +0700 Subject: [PATCH 008/164] . --- popup/tabs.js | 1 + 1 file changed, 1 insertion(+) diff --git a/popup/tabs.js b/popup/tabs.js index b8234cb1..0b4138f1 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -89,6 +89,7 @@ const tabs = [ s.fb_videoDownloader, s.fb_downloadCommentVideo, s.fb_getAvatarFromUid, + createTitle("--- Bulk Download ---", "--- Tải hàng loạt ---"), s.fb_downloadAlbumMedia, createTitle("--- Access Token ---", "--- Access Token ---"), s.fb_checkToken, From 0c2403721c39e116358973de883d398313cffea6 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Thu, 1 Dec 2022 09:00:30 +0700 Subject: [PATCH 009/164] studyphim + scribd --- popup/tabs.js | 2 + scripts/backup/scripts.js | 3 ++ scripts/content-scripts/document_start.js | 3 ++ scripts/content-scripts/scripts/studyphim.js | 39 ++++++++++++++++++++ scripts/index.js | 2 + scripts/scribd_downloadDocuments.js | 21 +++++++++++ 6 files changed, 70 insertions(+) create mode 100644 scripts/content-scripts/scripts/studyphim.js create mode 100644 scripts/scribd_downloadDocuments.js diff --git a/popup/tabs.js b/popup/tabs.js index 0b4138f1..2f939a95 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -67,6 +67,8 @@ const tabs = [ s.whatApp_storySaver, s.showTheImages, s.download_image, + createTitle("--- Document ---", "--- Tài liệu ---"), + s.scribd_downloadDocuments, ], }, { diff --git a/scripts/backup/scripts.js b/scripts/backup/scripts.js index 6f7cffbb..4ab57252 100644 --- a/scripts/backup/scripts.js +++ b/scripts/backup/scripts.js @@ -491,3 +491,6 @@ function getLinkFCode() { getDataDownload($("#linkcode").attr("value")); } + +// easy downloader +// https://github.com/nguy3n47/easy-download-extension/blob/master/index.js \ No newline at end of file diff --git a/scripts/content-scripts/document_start.js b/scripts/content-scripts/document_start.js index 701be1d9..82dc51ba 100644 --- a/scripts/content-scripts/document_start.js +++ b/scripts/content-scripts/document_start.js @@ -12,6 +12,9 @@ if (location.hostname === "www.instagram.com") injectCss(baseURL + "instagram.css"); + if (location.hostname === "www.studyphim.vn") + injectScript(baseURL + "studyphim.js"); + // if (location.hostname === "luanxt.com") // injectScriptFile("//code.jquery.com/jquery-3.6.1.min.js", true); })(); diff --git a/scripts/content-scripts/scripts/studyphim.js b/scripts/content-scripts/scripts/studyphim.js new file mode 100644 index 00000000..d8dc6e80 --- /dev/null +++ b/scripts/content-scripts/scripts/studyphim.js @@ -0,0 +1,39 @@ +// Source: https://github.com/gys-dev/Unlimited-Stdphim + +deleteElements( + ".overlay.playable.hide, .overlay.playable, #topchapter, #wrapper_header" +); + +function deleteElements(selector) { + // in case the content script was injected after the page is partially loaded + doDelete(document.querySelectorAll(selector)); + + var mo = new MutationObserver(process); + mo.observe(document, { subtree: true, childList: true }); + document.addEventListener("DOMContentLoaded", function () { + mo.disconnect(); + }); + + function process(mutations) { + for (var i = 0; i < mutations.length; i++) { + var nodes = mutations[i].addedNodes; + for (var j = 0; j < nodes.length; j++) { + var n = nodes[j]; + if (n.nodeType != 1) + // only process Node.ELEMENT_NODE + continue; + doDelete(n.matches(selector) ? [n] : n.querySelectorAll(selector)); + } + } + } + function doDelete(nodes) { + [].forEach.call(nodes, function (node) { + node.remove(); + console.log("Useful-scripts: studyphim - removed ", node); + }); + } +} + +// Chrome pre-34 +if (!Element.prototype.matches) + Element.prototype.matches = Element.prototype.webkitMatchesSelector; diff --git a/scripts/index.js b/scripts/index.js index d01a1810..16b91322 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -120,6 +120,7 @@ import insta_storySaver from "./insta_storySaver.js"; import whatApp_storySaver from "./whatApp_storySaver.js"; import send_shareFiles from "./send_shareFiles.js"; import fb_downloadCommentVideo from "./fb_downloadCommentVideo.js"; +import scribd_downloadDocuments from "./scribd_downloadDocuments.js"; // inject badges const allScripts = { @@ -255,6 +256,7 @@ const allScripts = { whatApp_storySaver: addBadge(whatApp_storySaver, BADGES.new), send_shareFiles: addBadge(send_shareFiles, BADGES.new), fb_downloadCommentVideo: addBadge(fb_downloadCommentVideo, BADGES.new), + scribd_downloadDocuments: addBadge(scribd_downloadDocuments, BADGES.new), }; // inject id to all scripts diff --git a/scripts/scribd_downloadDocuments.js b/scripts/scribd_downloadDocuments.js new file mode 100644 index 00000000..3e8f72b9 --- /dev/null +++ b/scripts/scribd_downloadDocuments.js @@ -0,0 +1,21 @@ +export default { + icon: "https://documents-downloader.pages.dev/apple-icon-57x57.png", + name: { + en: "Scribd - Download documents", + vi: "Scribd - Tải documents", + }, + description: { + en: "Download document on Scribd for free", + vi: "Tải miễn phí document trên Scribd", + }, + whiteList: ["https://www.scribd.com/document/*"], + runInExtensionContext: false, + + func: function () { + // Source: https://chrome.google.com/webstore/detail/documents-downloader/ikecplijfhabpahaolhdgglbbafknkdo?utm_source=j2team&utm_medium=url_shortener&utm_campaign=documents-downloader + + window.open( + "https://documents-downloader.pages.dev/?documentUrl=" + location.href + ); + }, +}; From 1c466f87e28d732484bb3e04cb72e3373a6fc337 Mon Sep 17 00:00:00 2001 From: "hoang.tran12" Date: Thu, 1 Dec 2022 14:28:45 +0700 Subject: [PATCH 010/164] . --- popup/tabs.js | 2 + scripts/_test.js | 21 ++++++++++ scripts/content-scripts/utils.js | 1 + scripts/fb_hideNewFeed.js | 22 ++++++++++ scripts/fb_toggleLight.js | 5 +-- scripts/fb_videoDownloader.js | 71 ++++++++++++++++---------------- scripts/helpers/utils.js | 53 +++++++++++++++--------- scripts/index.js | 4 ++ 8 files changed, 120 insertions(+), 59 deletions(-) create mode 100644 scripts/_test.js create mode 100644 scripts/fb_hideNewFeed.js diff --git a/popup/tabs.js b/popup/tabs.js index 2f939a95..3a7a1edb 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -36,6 +36,7 @@ const tabs = [ { ...CATEGORY.search, scripts: [ + s._test, s.whatFont, s.similarWeb, s.search_sharedAccount, @@ -86,6 +87,7 @@ const tabs = [ scripts: [ createTitle("--- UI ---", "--- Giao diện ---"), s.fb_toggleLight, + s.fb_hideNewFeed, createTitle("--- Download ---", "--- Tải xuống ---"), s.fb_storySaver, s.fb_videoDownloader, diff --git a/scripts/_test.js b/scripts/_test.js new file mode 100644 index 00000000..84477285 --- /dev/null +++ b/scripts/_test.js @@ -0,0 +1,21 @@ +import { runScriptInCurrentTab } from "./helpers/utils.js"; + +export default { + icon: "", + name: { + en: "Test script", + vi: "Test script", + }, + description: { + en: "", + vi: "", + }, + runInExtensionContext: true, + + func: async function () { + let dtsg = await runScriptInCurrentTab(() => { + return require("DTSGInitialData").token; + }); + alert(dtsg); + }, +}; diff --git a/scripts/content-scripts/utils.js b/scripts/content-scripts/utils.js index c7304601..1cf63b0d 100644 --- a/scripts/content-scripts/utils.js +++ b/scripts/content-scripts/utils.js @@ -21,6 +21,7 @@ export function injectScript(filePathOrUrl, isExternal = false) { } } +// TODO: https://developer.chrome.com/docs/extensions/reference/scripting/#method-insertCSS // https://stackoverflow.com/a/17840622 export function injectCss(cssfileOrCode, isFile = true) { if (isFile) { diff --git a/scripts/fb_hideNewFeed.js b/scripts/fb_hideNewFeed.js new file mode 100644 index 00000000..a91ca351 --- /dev/null +++ b/scripts/fb_hideNewFeed.js @@ -0,0 +1,22 @@ +export default { + icon: '', + name: { + en: "Hide/Show Newfeed facebook", + vi: "Ẩn/Hiện Newfeed facebook", + }, + description: { + en: "Hide/Show Newfeed facebook for better focus to work", + vi: "Ẩn/Hiện Newfeed facebook để tập trung làm việc", + }, + whiteList: ["https://www.facebook.com*"], + runInExtensionContext: false, + + func: function () { + let div = document.querySelector("#ssrb_feed_end")?.parentElement; + + if (!div) alert("Không tìm thấy NewFeed."); + else { + div.style.display = div.style.display === "none" ? "block" : "none"; + } + }, +}; diff --git a/scripts/fb_toggleLight.js b/scripts/fb_toggleLight.js index bbfeecad..7612a371 100644 --- a/scripts/fb_toggleLight.js +++ b/scripts/fb_toggleLight.js @@ -18,10 +18,7 @@ export default { ].forEach((_) => { let dom = document.querySelector(_); if (dom) { - let current = dom.style.opacity || 1; - let newValue = current == 1 ? 0 : 1; - dom.style.opacity = newValue; - dom.style.pointerEvents = newValue ? "" : "none"; + dom.style.display = dom.style.display === "none" ? "block" : "none"; } else alert("ERROR: Cannot find element" + _); }); }, diff --git a/scripts/fb_videoDownloader.js b/scripts/fb_videoDownloader.js index dd81d360..3075fc6f 100644 --- a/scripts/fb_videoDownloader.js +++ b/scripts/fb_videoDownloader.js @@ -15,6 +15,34 @@ export default { func: function () { // Original source code: https://gist.github.com/monokaijs/270e29620c46cabec1caca8c3746729d + function stringifyVariables(d, e) { + let f = [], + a; + for (a in d) + if (d.hasOwnProperty(a)) { + let g = e ? e + "[" + a + "]" : a, + b = d[a]; + f.push( + null !== b && "object" == typeof b + ? stringifyVariables(b, g) + : encodeURIComponent(g) + "=" + encodeURIComponent(b) + ); + } + return f.join("&"); + } + function fetchGraphQl(doc_id, variables) { + return fetch("https://www.facebook.com/api/graphql/", { + method: "POST", + headers: { "content-type": "application/x-www-form-urlencoded" }, + body: stringifyVariables({ + doc_id: doc_id, + variables: JSON.stringify(variables), + fb_dtsg: require("DTSGInitialData").token, + server_timestamps: !0, + }), + }); + } + let url = prompt("Nhập link video/reel/watch:", location.href); let videoId = url.match(/\/(?:videos|reel|watch)(?:\/?)(?:\?v=)?(\d+)/); if (!videoId || videoId.length < 2) { @@ -23,33 +51,6 @@ export default { ); return; } - let stringifyVariables = function (d, e) { - let f = [], - a; - for (a in d) - if (d.hasOwnProperty(a)) { - let g = e ? e + "[" + a + "]" : a, - b = d[a]; - f.push( - null !== b && "object" == typeof b - ? stringifyVariables(b, g) - : encodeURIComponent(g) + "=" + encodeURIComponent(b) - ); - } - return f.join("&"); - }, - fetchGraphQl = function (doc_id, variables) { - return fetch("https://www.facebook.com/api/graphql/", { - method: "POST", - headers: { "content-type": "application/x-www-form-urlencoded" }, - body: stringifyVariables({ - doc_id: doc_id, - variables: JSON.stringify(variables), - fb_dtsg: require("DTSGInitialData").token, - server_timestamps: !0, - }), - }); - }; fetchGraphQl("5279476072161634", { UFI2CommentsProvider_commentsKey: "CometTahoeSidePaneQuery", @@ -72,16 +73,14 @@ export default { }) .then((res) => res.text()) .then((text) => { - try { - let a = JSON.parse(text.split("\n")[0]), - link = - a.data.video.playable_url_quality_hd || a.data.video.playable_url; + let a = JSON.parse(text.split("\n")[0]), + link = + a.data.video.playable_url_quality_hd || a.data.video.playable_url; - if (link) { - window.open(link); - } - } catch (e) { - alert("Lỗi: " + e); + if (link) { + window.open(link); + } else { + throw Error("Không tìm thấy link"); } }) .catch((e) => { diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index 5c90f552..5b6f59cc 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -35,32 +35,50 @@ export function closeTab(tab) { return chrome.tabs.remove(tab.id); } -export const runScript = async (func, tabId) => { - return chrome.scripting.executeScript({ - target: { tabId: tabId }, - func: func, - world: chrome.scripting.ExecutionWorld.MAIN, +export const runScript = async ({ func, tabId, args = [] }) => { + return new Promise((resolve, reject) => { + chrome.scripting.executeScript( + { + target: { tabId: tabId }, + func: func, + args: args, + world: chrome.scripting.ExecutionWorld.MAIN, + }, + (injectionResults) => { + // https://developer.chrome.com/docs/extensions/reference/scripting/#handling-results + resolve(injectionResults.find((_) => _.result)?.result); + } + ); }); }; -export const runScriptFile = (scriptFile, tabId) => { - return chrome.scripting.executeScript({ - target: { tabId: tabId }, - files: [scriptFile], - world: chrome.scripting.ExecutionWorld.MAIN, +export const runScriptFile = ({ scriptFile, tabId, args = [] }) => { + return new Promise((resolve, reject) => { + chrome.scripting.executeScript( + { + target: { tabId: tabId }, + files: [scriptFile], + args: args, + world: chrome.scripting.ExecutionWorld.MAIN, + }, + (injectionResults) => { + // https://developer.chrome.com/docs/extensions/reference/scripting/#handling-results + resolve(injectionResults.find((_) => _.result)?.result); + } + ); }); }; -export const runScriptInCurrentTab = async (func) => { +export const runScriptInCurrentTab = async (func, args) => { const tab = await getCurrentTab(); focusToTab(tab); - return await runScript(func, tab.id); + return await runScript({ func, args, tabId: tab.id }); }; -export const runScriptFileInCurrentTab = async (scriptFile) => { +export const runScriptFileInCurrentTab = async (scriptFile, args) => { const tab = await getCurrentTab(); focusToTab(); - return await runScriptFile(scriptFile, tab.id); + return await runScriptFile({ scriptFile, args, tabId: tab.id }); }; export async function getAvailableScripts() { @@ -71,7 +89,6 @@ export async function getAvailableScripts() { avai.push(script); } } - return avai; } @@ -102,13 +119,11 @@ export async function checkBlackWhiteList(script, url = null) { export function isUrlMatchPattern(url, pattern) { let curIndex = 0, visiblePartsInPattern = pattern.split("*").filter((_) => _ !== ""); - for (let p of visiblePartsInPattern) { let index = url.indexOf(p, curIndex); if (index < 0) return false; curIndex = index + p.length; } - return true; } @@ -337,8 +352,8 @@ export function showLoading(text = "") { let html = `
-
- ${text && `

${text}

`} +

+

${text}

`; diff --git a/scripts/index.js b/scripts/index.js index 16b91322..e3ab7b34 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -1,5 +1,6 @@ import { addBadge, BADGES } from "../popup/helpers/badge.js"; +import _test from "./_test.js"; import fb_toggleLight from "./fb_toggleLight.js"; import fb_getTokenBusinessStudio from "./fb_getTokenBusinessStudio.js"; import fb_getTokenFacebook from "./fb_getTokenFacebook.js"; @@ -121,9 +122,11 @@ import whatApp_storySaver from "./whatApp_storySaver.js"; import send_shareFiles from "./send_shareFiles.js"; import fb_downloadCommentVideo from "./fb_downloadCommentVideo.js"; import scribd_downloadDocuments from "./scribd_downloadDocuments.js"; +import fb_hideNewFeed from "./fb_hideNewFeed.js"; // inject badges const allScripts = { + _test, fb_toggleLight: fb_toggleLight, fb_getTokenBusinessStudio: addBadge(fb_getTokenBusinessStudio, BADGES.hot), fb_getTokenFacebook: addBadge(fb_getTokenFacebook, BADGES.hot), @@ -257,6 +260,7 @@ const allScripts = { send_shareFiles: addBadge(send_shareFiles, BADGES.new), fb_downloadCommentVideo: addBadge(fb_downloadCommentVideo, BADGES.new), scribd_downloadDocuments: addBadge(scribd_downloadDocuments, BADGES.new), + fb_hideNewFeed: addBadge(fb_hideNewFeed, BADGES.new), }; // inject id to all scripts From cd94515785329ecefbd1446c008521fece77bf50 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Thu, 1 Dec 2022 21:24:59 +0700 Subject: [PATCH 011/164] fix story saver --- scripts/fb_storySaver.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/fb_storySaver.js b/scripts/fb_storySaver.js index 2dec9edc..79990bc8 100644 --- a/scripts/fb_storySaver.js +++ b/scripts/fb_storySaver.js @@ -67,9 +67,9 @@ export default { } } - let storyImgUrl = document.querySelector( - 'div[data-id] img[draggable="false"]' - )?.src; + let storyImgUrl = Array.from( + document.querySelectorAll('div[data-id] img[draggable="false"]') + ).find((_) => _.alt)?.src; if (storyImgUrl) { listUrls.push({ url: storyImgUrl, type: "img" }); } From 5406d44cab3f94f9d6de6e17725d4dd3b5e46d56 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Thu, 1 Dec 2022 21:59:49 +0700 Subject: [PATCH 012/164] update unlock text selection with css --- scripts/enableTextSelection.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scripts/enableTextSelection.js b/scripts/enableTextSelection.js index 62688ee3..89349227 100644 --- a/scripts/enableTextSelection.js +++ b/scripts/enableTextSelection.js @@ -10,6 +10,7 @@ export default { }, func: function () { + // events function R(a) { ona = "on" + a; if (window.addEventListener) @@ -29,6 +30,19 @@ export default { R("mouseup"); R("selectstart"); + // css userSelect + let cssTag = document.createElement("style"); + cssTag.innerHTML = ` + * { + -webkit-touch-callout: auto !important; + -webkit-user-select: auto !important; + -moz-user-select: auto !important; + -ms-user-select: auto !important; + user-select: auto !important; + } + `; + document.body.appendChild(cssTag); + alert("Đã bật lại text selection.\nText selection enabled."); }, }; From 1122eff1ab16a0fb553949b98d7685925c9386dd Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Fri, 2 Dec 2022 02:27:09 +0700 Subject: [PATCH 013/164] new scripts --- popup/helpers/category.js | 7 ++ popup/index.js | 8 +- popup/tabs.js | 23 ++++- scripts/backup/yt-playlist-maker.js | 51 +++++++++++ scripts/donotBlockMe.js | 22 +++++ scripts/envato_previewBypass.js | 22 +++++ scripts/fb_storyInfo.js | 135 ++++++++++++++++++++++++++++ scripts/fb_toggleLight.js | 14 ++- scripts/ggdrive_downloadVideo.js | 73 +++++++++++++++ scripts/helpers/utils.js | 6 +- scripts/index.js | 10 +++ scripts/scribd_downloadDocuments.js | 1 + scripts/shopee_topVariation.js | 124 +++++++++++++++++++++++++ 13 files changed, 479 insertions(+), 17 deletions(-) create mode 100644 scripts/backup/yt-playlist-maker.js create mode 100644 scripts/donotBlockMe.js create mode 100644 scripts/envato_previewBypass.js create mode 100644 scripts/fb_storyInfo.js create mode 100644 scripts/ggdrive_downloadVideo.js create mode 100644 scripts/shopee_topVariation.js diff --git a/popup/helpers/category.js b/popup/helpers/category.js index cccb6729..f16fd426 100644 --- a/popup/helpers/category.js +++ b/popup/helpers/category.js @@ -89,6 +89,13 @@ export const CATEGORY = { vi: ` Tiktok`, }, }, + shopee: { + id: "shopee", + name: { + en: ` Shopee`, + vi: ` Shopee`, + }, + }, github: { id: "github", name: { diff --git a/popup/index.js b/popup/index.js index a9836240..5896df71 100644 --- a/popup/index.js +++ b/popup/index.js @@ -1,5 +1,6 @@ import { checkBlackWhiteList, + getCurrentTab, GlobalBlackList, isExtensionInSeperatedPopup, openExtensionInSeparatedPopup, @@ -243,7 +244,8 @@ function createScriptButton(script, isFavorite = false) { } async function runScript(script) { - let willRun = await checkBlackWhiteList(script); + let tab = await getCurrentTab(); + let willRun = await checkBlackWhiteList(script, tab.url); if (willRun) { recentScriptsSaver.add(script); if (script.runInExtensionContext) script.func(); @@ -254,8 +256,8 @@ async function runScript(script) { openModal( t({ - en: `Script not supported in current website`, - vi: `Script không hỗ trợ website hiện tại`, + en: `Script not supported in current website (${tab.url})`, + vi: `Script không hỗ trợ website hiện tại (${tab.url})`, }), t({ en: diff --git a/popup/tabs.js b/popup/tabs.js index 3a7a1edb..c239631f 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -75,7 +75,9 @@ const tabs = [ { ...CATEGORY.google, scripts: [ - // s.google_downloadDriveVideo, + createTitle("--- Download ---", "--- Tải xuống ---"), + s.ggdrive_downloadVideo, + createTitle("--- More ---", "--- Khác ---"), s.search_totalIndexedPages, s.search_googleSite, s.googleShortcuts, @@ -93,6 +95,7 @@ const tabs = [ s.fb_videoDownloader, s.fb_downloadCommentVideo, s.fb_getAvatarFromUid, + s.fb_storyInfo, createTitle("--- Bulk Download ---", "--- Tải hàng loạt ---"), s.fb_downloadAlbumMedia, createTitle("--- Access Token ---", "--- Access Token ---"), @@ -159,6 +162,10 @@ const tabs = [ s.doutube_getAllVideoInUserProfile, ], }, + { + ...CATEGORY.shopee, + scripts: [s.shopee_topVariation], + }, { ...CATEGORY.github, scripts: [s.github_goToFirstCommit, s.githubdev, s.github1s], @@ -189,9 +196,11 @@ const tabs = [ { ...CATEGORY.unlock, scripts: [ + s.donotBlockMe, s.shortenURL, s.unshorten, s.viewBrowserInfo, + s.envato_previewBypass, s.showHiddenFields, s.viewCookies, s.removeCookies, @@ -301,6 +310,18 @@ const recommendTab = { }, link: "https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb", }, + { + icon: "https://lh3.googleusercontent.com/M_2Q8eJAj1ejsRg30LuJs_Q94Jk7d-6ZbE5cyddULweH5LrfsVJtjK8zbpSjwA3G9oHwZeyHyrYrr971kqLwtNNP=w128-h128-e365-rj-sc0x00ffffff", + name: { + en: "NSFW Filter: Hide NSFW content", + vi: "NSFW Filter: Ẩn nội dung 18+", + }, + description: { + en: "Hide NSFW content from websites using this extension powered by AI", + vi: "Ẩn mọi nội dung 18+ trên website, sử dụng trí tuệ nhân tạo", + }, + link: "https://chrome.google.com/webstore/detail/nsfw-filter/kmgagnlkckiamnenbpigfaljmanlbbhh", + }, { icon: "https://lh3.googleusercontent.com/_l4UaD5Gwub2AwFZdomRpfMD2737y0Ow6k2sfVuWdm0fQ0iGSdEfhd9X77taeQ-0VM6Wi3HnpecLWUAI9uHq11TSktw=w128-h128-e365-rj-sc0x00ffffff", name: { diff --git a/scripts/backup/yt-playlist-maker.js b/scripts/backup/yt-playlist-maker.js new file mode 100644 index 00000000..3cb1ec05 --- /dev/null +++ b/scripts/backup/yt-playlist-maker.js @@ -0,0 +1,51 @@ +// https://gist.github.com/J2TEAM/d8380866bb28dfb8a7f1ab72059658b0 + +/* Developed by Juno_okyo */ +(function (e, b) { + function f(a, b) { + var d = fetch, + e = + "sej=" + + encodeURIComponent( + JSON.stringify({ + playlistEditEndpoint: { + playlistId: a, + actions: [ + { + addedVideoId: b, + action: "ACTION_ADD_VIDEO", + }, + ], + }, + clickTrackingParams: "juno_okyo_j2team_community", + commandMetadata: { + webCommandMetadata: { + url: "/service_ajax", + sendPost: !0, + }, + }, + }) + ) + + "&session_token=", + f = encodeURIComponent; + var c = /"XSRF_TOKEN":"([^"]+)"/.exec(document.head.innerHTML); + c = null !== c ? c[1] : !1; + return d("https://www.youtube.com/service_ajax?name=playlistEditEndpoint", { + method: "POST", + credentials: "same-origin", + headers: { + "content-type": "application/x-www-form-urlencoded", + }, + body: e + f(c), + }); + } + + function d() { + var a = b.pop(); + a = new URL(a).searchParams.get("v"); + f(e, a).then(function (a) { + 0 < b.length && setTimeout(d, 500); + }); + } + d(); +})("YOUR_PLAYLIST_ID", "YOUR_VIDEO_URLS_IN_ARRAY"); diff --git a/scripts/donotBlockMe.js b/scripts/donotBlockMe.js new file mode 100644 index 00000000..c93703aa --- /dev/null +++ b/scripts/donotBlockMe.js @@ -0,0 +1,22 @@ +import { getCurrentTab } from "./helpers/utils.js"; + +export default { + icon: '', + name: { + en: "View blocked websites", + vi: "Truy cập các trang web bị chặn", + }, + description: { + en: "View website that being blocked. (eg. Medium)", + vi: "Xem các website đang bị chặn bởi nhà mạng. (ví dụ: Medium)", + }, + runInExtensionContext: true, + + func: async function () { + // Post: https://www.facebook.com/groups/j2team.community/posts/1772972649701514/ + + let tab = await getCurrentTab(); + let url = prompt("Nhập trang web bị chặn mà bạn muốn truy cập:", tab?.url); + if (url != null) window.open("https://donotblock.me/" + url); + }, +}; diff --git a/scripts/envato_previewBypass.js b/scripts/envato_previewBypass.js new file mode 100644 index 00000000..e47b54cb --- /dev/null +++ b/scripts/envato_previewBypass.js @@ -0,0 +1,22 @@ +export default { + icon: "https://elements.envato.com/favicon.ico", + name: { + en: "Envato - preview bypass", + vi: "Envato - bypass khung xem trước", + }, + description: { + en: "Remove preview iframe on Envato sites (Themeforest, Codecanyon)", + vi: "Bypass khung preview khi xem demo trong trang web Envato (Themeforest, Codecanyon)", + }, + blackList: [], + whiteList: [], + runInExtensionContext: false, + + func: function () { + // Source code: https://gist.github.com/J2TEAM/f79f950c31cc9fe4ed705515385ed75f + + let url = document.querySelector(".full-screen-preview__frame")?.src; + if (url) window.open(url); + else alert("Không tìm thấy link để bypass preview Envato"); + }, +}; diff --git a/scripts/fb_storyInfo.js b/scripts/fb_storyInfo.js new file mode 100644 index 00000000..77499e00 --- /dev/null +++ b/scripts/fb_storyInfo.js @@ -0,0 +1,135 @@ +import { + getCurrentTab, + runScriptInCurrentTab, + showLoading, +} from "./helpers/utils.js"; + +export default { + icon: "", + name: { + en: "View Facebook Story information", + vi: "Xem thông tin của Facebook Story", + }, + description: { + en: "", + vi: "", + }, + blackList: [], + whiteList: [], + runInExtensionContext: true, + + func: async function () { + // Source: https://pastebin.com/CNvUxpfc + + let tab = await getCurrentTab(); + let url = prompt("Nhập link story: ", tab.url); + if (url == null) return; + + const { closeLoading } = showLoading("Đang lấy thông tin story..."); + let result = await runScriptInCurrentTab( + (_url) => { + let dtsg = require("DTSGInitialData").token || window.fb_dtsg; + let bucketID = _url.split("stories/")[1].split("/")[0]; + + return new Promise((resolve, reject) => { + let data = + "__a=1&fb_dtsg=" + + dtsg + + "&variables=%7B%22bucketID%22%3A%22" + + bucketID + + "%22%2C%22initialLoad%22%3Afalse%2C%22scale%22%3A1%7D&doc_id=2586853698032602"; + + console.log("Đang tải thông tin..."); + let xhr = new XMLHttpRequest(); + xhr.withCredentials = true; + xhr.addEventListener("readystatechange", function () { + if (this.readyState === 4) { + try { + data = JSON.parse(this.responseText).data.bucket; + console.info(data); + + resolve({ + "Story ID": data.id, + "Author ID": data.owner.id, + "Author name": data.owner.name, + "Author profile picture": data.owner.profile_picture.uri, + "Author profile URL": data.owner.url, + Objects: data.unified_stories.edges.map((_) => { + return { + "Picture blured": + _.edges[i].node.attachments[0].media.blurredImage.uri, + + "Picture preview url": + _.edges[i].node.attachments[0].media.previewImage.uri, + + "Total reaction feedback": + _.edges[i].node.story_card_info.feedback_summary + .total_reaction_count, + + "Background CSS": + _.edges[i].node.story_default_background.color, + + "Background CSS3": + _.edges[i].node.story_default_background.gradient.css, + + ..._( + _.edges[i].node.attachments[0].media.__typename == + "Photo" + ? { + Caption: + _.edges[i].node.attachments[0].media + .accessibility_caption, + + Image: + _.edges[i].node.attachments[0].media.image.uri, + } + : _.edges[i].node.attachments[0].media.__typename == + "Video" + ? { + "Permalink video url": + data.unified_stories.edges[i].node + .attachments[0].media.permalink_url, + + "Playable_url url": + data.unified_stories.edges[i].node + .attachments[0].media.playable_url, + + "playable_url_dash url": + data.unified_stories.edges[0].node + .attachments[0].media.playable_url_dash, + + "playableUrlHdString url": + data.unified_stories.edges[i].node + .attachments[0].media.playableUrlHdString, + + "playable_url_quality_hd url": + data.unified_stories.edges[i].node + .attachments[0].media.playable_url_quality_hd, + } + : null + ), + }; + }), + }); + } catch (e) { + alert("ERROR: " + e); + resolve({}); + } + } + }); + + xhr.open("POST", "https://www.facebook.com/api/graphql/"); + xhr.setRequestHeader( + "Content-Type", + "application/x-www-form-urlencoded" + ); + xhr.send(data); + }); + }, + [url] + ); + closeLoading(); + + console.log(result); + }, +}; diff --git a/scripts/fb_toggleLight.js b/scripts/fb_toggleLight.js index 7612a371..7a98f7ec 100644 --- a/scripts/fb_toggleLight.js +++ b/scripts/fb_toggleLight.js @@ -13,15 +13,11 @@ export default { func: function () { [ - "div[role='navigation'].x9f619.x1ja2u2z.xnp8db0.x112wk31", - "div[role='complementary'].x9f619.x1ja2u2z.xnp8db0.x112wk31", - ].forEach((_) => { - let dom = document.querySelector(_); - if (dom) { - dom.style.display = dom.style.display === "none" ? "block" : "none"; - } else alert("ERROR: Cannot find element" + _); + document.querySelectorAll('[role="navigation"]')?.[2], + document.querySelectorAll('[role="complementary"]')?.[0], + ].forEach((el) => { + if (el) el.style.display = el.style.display === "none" ? "block" : "none"; + else alert("ERROR: Cannot find element"); }); }, }; - -// //*[@id="mount_0_0_Rc"]/div[1]/div[1]/div/div[3]/div/div/div/div[1]/div[1]/div/div[1] diff --git a/scripts/ggdrive_downloadVideo.js b/scripts/ggdrive_downloadVideo.js new file mode 100644 index 00000000..bc8526c3 --- /dev/null +++ b/scripts/ggdrive_downloadVideo.js @@ -0,0 +1,73 @@ +export default { + icon: "https://drive.google.com/favicon.ico", + name: { + en: "GG Drive - Download video", + vi: "GG Drive - Tải video", + }, + description: { + en: "Download google drive video that dont have download button", + vi: "Tải video không có nút download trên google drive", + }, + blackList: [], + whiteList: [], + runInExtensionContext: false, + + func: async function () { + // Post: https://www.facebook.com/groups/j2team.community/posts/974953859503401/ + + function parse(e) { + var result = {}; + return ( + e.split("&").forEach(function (e) { + result[decodeURIComponent(e.substring(0, e.indexOf("=")))] = + decodeURIComponent(e.substring(e.indexOf("=") + 1)); + }), + result + ); + } + + function parseStream(e) { + var d = []; + return ( + e.split(",").forEach(function (e) { + d.push(parse(e)); + }), + d + ); + } + + async function getVideoLinkFromDocId(docid) { + let res = await fetch( + "https://drive.google.com/get_video_info?docid=" + docid + ); + + let text = await res.text(); + let json = parse(text); + + json.url_encoded_fmt_stream_map = parseStream( + json.url_encoded_fmt_stream_map + ); + + let result = json.url_encoded_fmt_stream_map.map(function (stream) { + let name = json.title.replace(/\+/g, " "); + return { + idfile: docid, + name: name, + quality: stream.quality, + url: stream.url, + }; + }); + + console.log(result); + return result; + } + + try { + let { id, title } = window.viewerData.config; + console.log("get link..."); + await getVideoLinkFromDocId(id); + } catch (e) { + alert("ERROR: " + e); + } + }, +}; diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index 5b6f59cc..195e5de0 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -93,10 +93,8 @@ export async function getAvailableScripts() { } export const GlobalBlackList = ["edge://*", "chrome://*"]; -export async function checkBlackWhiteList(script, url = null) { - if (!url) { - url = (await getCurrentTab()).url; - } +export async function checkBlackWhiteList(script, url) { + if (!url) return false; let w = script.whiteList, b = script.blackList, diff --git a/scripts/index.js b/scripts/index.js index e3ab7b34..0413fcec 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -123,6 +123,11 @@ import send_shareFiles from "./send_shareFiles.js"; import fb_downloadCommentVideo from "./fb_downloadCommentVideo.js"; import scribd_downloadDocuments from "./scribd_downloadDocuments.js"; import fb_hideNewFeed from "./fb_hideNewFeed.js"; +import fb_storyInfo from "./fb_storyInfo.js"; +import envato_previewBypass from "./envato_previewBypass.js"; +import shopee_topVariation from "./shopee_topVariation.js"; +import donotBlockMe from "./donotBlockMe.js"; +import ggdrive_downloadVideo from "./ggdrive_downloadVideo.js"; // inject badges const allScripts = { @@ -261,6 +266,11 @@ const allScripts = { fb_downloadCommentVideo: addBadge(fb_downloadCommentVideo, BADGES.new), scribd_downloadDocuments: addBadge(scribd_downloadDocuments, BADGES.new), fb_hideNewFeed: addBadge(fb_hideNewFeed, BADGES.new), + fb_storyInfo: addBadge(fb_storyInfo, BADGES.new), + envato_previewBypass: addBadge(envato_previewBypass, BADGES.new), + shopee_topVariation: addBadge(shopee_topVariation, BADGES.new), + donotBlockMe: addBadge(donotBlockMe, BADGES.new), + ggdrive_downloadVideo: addBadge(ggdrive_downloadVideo, BADGES.new), }; // inject id to all scripts diff --git a/scripts/scribd_downloadDocuments.js b/scripts/scribd_downloadDocuments.js index 3e8f72b9..64ebad6f 100644 --- a/scripts/scribd_downloadDocuments.js +++ b/scripts/scribd_downloadDocuments.js @@ -12,6 +12,7 @@ export default { runInExtensionContext: false, func: function () { + // Post: https://www.facebook.com/groups/j2team.community/posts/1642123806119733/ // Source: https://chrome.google.com/webstore/detail/documents-downloader/ikecplijfhabpahaolhdgglbbafknkdo?utm_source=j2team&utm_medium=url_shortener&utm_campaign=documents-downloader window.open( diff --git a/scripts/shopee_topVariation.js b/scripts/shopee_topVariation.js new file mode 100644 index 00000000..760531e7 --- /dev/null +++ b/scripts/shopee_topVariation.js @@ -0,0 +1,124 @@ +export default { + icon: "https://shopee.vn/favicon.ico", + name: { + en: "Shopee - Top variation", + vi: "Shopee - Loại hàng mua nhiều nhất", + }, + description: { + en: "See how many times each product variant was purchased", + vi: "Thống kê xem tùy chọn sản phẩm nào được mọi người mua nhiều nhất", + }, + blackList: [], + whiteList: [], + runInExtensionContext: false, + + func: function () { + // Source: https://gist.github.com/J2TEAM/bc5d9a1f3e648d6a3d679edf8689e5de + // Post: https://www.facebook.com/groups/j2team.community/posts/1730753827256730/ + + var $jscomp = $jscomp || {}; + $jscomp.scope = {}; + $jscomp.createTemplateTagFirstArg = function (a) { + return (a.raw = a); + }; + $jscomp.createTemplateTagFirstArgWithRaw = function (a, d) { + a.raw = d; + return a; + }; + $jscomp.arrayIteratorImpl = function (a) { + var d = 0; + return function () { + return d < a.length ? { done: !1, value: a[d++] } : { done: !0 }; + }; + }; + $jscomp.arrayIterator = function (a) { + return { next: $jscomp.arrayIteratorImpl(a) }; + }; + $jscomp.makeIterator = function (a) { + var d = + "undefined" != typeof Symbol && Symbol.iterator && a[Symbol.iterator]; + return d ? d.call(a) : $jscomp.arrayIterator(a); + }; + (function () { + function a(b) { + b.forEach(function (c) { + c.product_items && + c.product_items.forEach(function (e) { + f[e.model_name] ? f[e.model_name]++ : (f[e.model_name] = 1); + }); + }); + } + function d() { + var b = Object.fromEntries( + Object.entries(f).sort(function (c, e) { + var g = $jscomp.makeIterator(c); + g.next(); + g = g.next().value; + var m = $jscomp.makeIterator(e); + m.next(); + return m.next().value - g; + }) + ); + console.info("Đã hoàn tất. Kết quả:"); + console.table(b); + } + function run() { + var url = + "https://shopee.vn/api/v2/item/get_ratings?filter=0&flag=1&itemid=" + + itemId + + "&limit=50&offset=" + + offset + + "&shopid=" + + shopId + + "&type=0"; + console.log("Đang quét trang " + page + "..."); + fetch(url, { + headers: { + "x-api-source": "pc", + "x-requested-with": "XMLHttpRequest", + "x-shopee-language": "vi", + }, + method: "GET", + mode: "cors", + credentials: "include", + }) + .then(function (res) { + return res.json(); + }) + .then(function (json) { + json.error || !json.data || 0 === json.data.ratings.length + ? 1 < page && d() + : (a(json.data.ratings), + 50 > page ? ((offset += 50), page++, run()) : d()); + }); + } + var f = {}, + offset = 0, + page = 1, + shopId = null, + itemId = null; + console.info( + "Chia sẻ bởi Mạnh Tuấn từ nhóm J2TEAM Community - https://www.facebook.com/groups/j2team.community" + ); + (function () { + var b = new URL(window.top.location.href); + if (!b.hostname.includes("shopee.vn")) + throw Error("Đoạn mã này chỉ có thể sử dụng trên web Shopee.vn"); + if ((b = /.+-i\.([0-9]+).([0-9]+)/.exec(b.pathname))) + (shopId = b[1]), (itemId = b[2]); + else + throw Error( + "Trang bạn đang xem không phải là một trang sản phẩm của Shopee." + ); + })(); + console.info( + "Bắt đầu phân tích với Shop ID " + + shopId + + " và mã sản phẩm " + + itemId + + "..." + ); + run(); + })(); + }, +}; From e7705e69290adb7a296dc99d71b398f8ece440f4 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Fri, 2 Dec 2022 07:48:43 +0700 Subject: [PATCH 014/164] . --- scripts/ggdrive_downloadVideo.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/ggdrive_downloadVideo.js b/scripts/ggdrive_downloadVideo.js index bc8526c3..5736a201 100644 --- a/scripts/ggdrive_downloadVideo.js +++ b/scripts/ggdrive_downloadVideo.js @@ -36,6 +36,10 @@ export default { ); } + function downloadVideo(videoInfo) { + window.open(videoInfo.url + "&filename=" + videoInfo.name); + } + async function getVideoLinkFromDocId(docid) { let res = await fetch( "https://drive.google.com/get_video_info?docid=" + docid From 17205f861bfcf43b97c19a10b8e1f5dfe1e79531 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Sat, 3 Dec 2022 00:09:48 +0700 Subject: [PATCH 015/164] snaptikvideo - download tiktok video --- .../generated_indexed_rulesets/_ruleset1 | Bin 579 -> 851 bytes popup/tabs.js | 3 +- scripts/helpers/utils.js | 8 +- scripts/index.js | 6 +- scripts/net-request-rules/rules.json | 26 +++ ..._downloadVideo.js => tiktok_snaptikApp.js} | 0 scripts/tiktok_snaptikVideo.js | 171 ++++++++++++++++++ 7 files changed, 209 insertions(+), 5 deletions(-) rename scripts/{tiktok_downloadVideo.js => tiktok_snaptikApp.js} (100%) create mode 100644 scripts/tiktok_snaptikVideo.js diff --git a/_metadata/generated_indexed_rulesets/_ruleset1 b/_metadata/generated_indexed_rulesets/_ruleset1 index f6d3b65b4e50a32ffd90656df5c6b3e9e81176fd..ef7e0b4031304c51b15e274b25f0975871cb9f51 100644 GIT binary patch literal 851 zcma)4!AiqG6nxRN4N@eB3LYxtAmSyBh@cd`Rp?QqNN=Us*e-38kZkSMkMaZj1kWBl z`4z^QZ34wA8koGd`}WPw?5^(@-(8qyDvqvB&l@6g-S6Fs?1(G2I8sL@(gd6W2(kqn z^+1CaX?_&{$Rv7IGaBZ6K=_&H#6 zj2?j^5thl#dIvf*`d-%dJ;6M+@FTYe(8E4JkJLsU*0}E3?AtIq)KO)v^gx~KT!$EY z!0&vvS?_?8tvoC8l^h(?E5~o2W{u^-2*>1{Xq{y3AXqM!tt=WQT1_9-D2!Y8@f>B@ zUGZ9W(R1)ePk_1y=M|~4{oBVIc8wpYdgffH&m1g*50rX_iQ3Q;WZH+m0MPL?7|pQW z#R)r7Lq^}O;Y3Qg8|P5o(|h5G_i+JGX`HIDijbJMSOe$kEn>prI^H37NyCRQ4O7`e uUTR%L*(6SN7`2pM`EUNqKi>v*mj0O@0YCE2hbjujp&rcQXgpY?F#iSg33)sK delta 164 zcmcc2c9^AJ7Y4#oi;6Sz^K6aGB^VeOTq8n)fD{mLF$gfQFmN#N09gzSAUO^w22u=+ zKr8|zn1S>TAkF|{79dXe|NlQLkQM;q0H_#{0_$}E(l$VB0mMQwK*9isb%0m{h*cOS Ru9Rc)VVrn!+T?JiKLGiJ6%+sf diff --git a/popup/tabs.js b/popup/tabs.js index c239631f..ae8e1838 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -151,7 +151,8 @@ const tabs = [ ...CATEGORY.tiktok, scripts: [ createTitle("--- Tiktok ---", "--- Tiktok ---"), - s.tiktok_downloadVideo, + s.tiktok_snaptikApp, + s.tiktok_snaptikVideo, createTitle("--- Douyin ---", "--- Douyin ---"), s.douyin_downloadWachingVideo, s.douyin_downloadAllVideoUser, diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index 195e5de0..c9e3a5af 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -397,8 +397,12 @@ export function showPopup(title = "", innerHTML = "") { }; } -export function openPopupWithHtml(html) { - let win = window.open("", "", "scrollbars=yes"); +export function openPopupWithHtml(html, width = 300, height = 300) { + let win = window.open( + "", + "", + `scrollbars=yes,width=${width},height=${height}` + ); win.document.write(html); } diff --git a/scripts/index.js b/scripts/index.js index 0413fcec..ec3a74f0 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -111,7 +111,7 @@ import screenshotFullPage from "./screenshotFullPage.js"; import visualEvent from "./visualEvent.js"; import fb_videoDownloader from "./fb_videoDownloader.js"; import viewBrowserInfo from "./viewBrowserInfo.js"; -import tiktok_downloadVideo from "./tiktok_downloadVideo.js"; +import tiktok_snaptikApp from "./tiktok_snaptikApp.js"; import douyin_downloadWachingVideo from "./douyin_downloadWachingVideo.js"; import instantgram from "./instantgram.js"; import douyin_downloadAllVideoUser from "./douyin_downloadAllVideoUser.js"; @@ -128,6 +128,7 @@ import envato_previewBypass from "./envato_previewBypass.js"; import shopee_topVariation from "./shopee_topVariation.js"; import donotBlockMe from "./donotBlockMe.js"; import ggdrive_downloadVideo from "./ggdrive_downloadVideo.js"; +import tiktok_snaptikVideo from "./tiktok_snaptikVideo.js"; // inject badges const allScripts = { @@ -248,7 +249,7 @@ const allScripts = { visualEvent: addBadge(visualEvent, BADGES.new), fb_videoDownloader: addBadge(fb_videoDownloader, BADGES.new), viewBrowserInfo: addBadge(viewBrowserInfo, BADGES.new), - tiktok_downloadVideo: addBadge(tiktok_downloadVideo, BADGES.new), + tiktok_snaptikApp: addBadge(tiktok_snaptikApp, BADGES.new), douyin_downloadWachingVideo: addBadge( douyin_downloadWachingVideo, BADGES.new @@ -271,6 +272,7 @@ const allScripts = { shopee_topVariation: addBadge(shopee_topVariation, BADGES.new), donotBlockMe: addBadge(donotBlockMe, BADGES.new), ggdrive_downloadVideo: addBadge(ggdrive_downloadVideo, BADGES.new), + tiktok_snaptikVideo: addBadge(tiktok_snaptikVideo, BADGES.new), }; // inject id to all scripts diff --git a/scripts/net-request-rules/rules.json b/scripts/net-request-rules/rules.json index 12791432..310e8011 100644 --- a/scripts/net-request-rules/rules.json +++ b/scripts/net-request-rules/rules.json @@ -24,5 +24,31 @@ "xmlhttprequest" ] } + }, + { + "id": 2, + "priority": 1, + "action": { + "type": "modifyHeaders", + "requestHeaders": [ + { + "header": "referer", + "operation": "set", + "value": "https://www.snaptikvideo.com/" + }, + { + "header": "origin", + "operation": "set", + "value": "https://www.snaptikvideo.com" + } + ] + }, + "condition": { + "domain": "extension://*", + "urlFilter": "https://api.snaptikvideo.com/st-tik/tiktok/dl", + "resourceTypes": [ + "xmlhttprequest" + ] + } } ] \ No newline at end of file diff --git a/scripts/tiktok_downloadVideo.js b/scripts/tiktok_snaptikApp.js similarity index 100% rename from scripts/tiktok_downloadVideo.js rename to scripts/tiktok_snaptikApp.js diff --git a/scripts/tiktok_snaptikVideo.js b/scripts/tiktok_snaptikVideo.js new file mode 100644 index 00000000..1c98e35d --- /dev/null +++ b/scripts/tiktok_snaptikVideo.js @@ -0,0 +1,171 @@ +import { openPopupWithHtml, showLoading } from "./helpers/utils.js"; + +export default { + icon: "https://www.snaptikvideo.com/favicon.ico", + name: { + en: "Tiktok - Download video (snaptikvideo)", + vi: "Tiktok - Tải video (snaptikvideo)", + }, + description: { + en: "", + vi: "", + }, + runInExtensionContext: true, + + func: async function () { + async function fetchSnaptikVideo(url) { + let res = await fetch( + "https://api.snaptikvideo.com/st-tik/tiktok/dl?url=" + url, + { + // Kèm thêm config rules ở net-request-rules thì fetch này mới chạy được + } + ); + return await res.json(); + } + + const { closeLoading, setLoadingText } = showLoading( + "Đang chờ bạn nhập url..." + ); + try { + let url = prompt("Nhập link tiktok video: ", ""); + if (url == null) return; + + setLoadingText("Đang tải thông tin từ snaptikvideo..."); + let data = await fetchSnaptikVideo(url); + if (data?.code != 200) throw Error(data?.msg || "Lỗi không xác định"); + if (!data?.result) throw Error("Kết quả trả về không có thông tin."); + console.log(data); + const { + author, + cover, + desc, + duration, + mp3, + music, + thumb, + waterMarkMp4, + waterMarkVideo, + withoutWaterMarkMp4, + withoutWaterMarkVideo, + } = data.result; + + let listLink = [ + { + name: "Video (no watermark)", + value: withoutWaterMarkMp4 || withoutWaterMarkVideo, + }, + { name: "MP4", value: waterMarkMp4 }, + { name: "MP3 🎵", value: mp3 || music }, + { name: "HD Video", value: waterMarkVideo }, + { name: "Profile Picture", value: thumb }, + ] + .map(({ name, value }) => { + if (value) { + return `${name}`; + } + }) + .join(""); + + openPopupWithHtml( + `
+ +
+
+ +
${author}
+
+
${desc}
+
+
+ ${listLink} +
+
+
+
+ + + `, + 900, + 600 + ); + } catch (e) { + prompt( + "Lỗi: " + e + "\n\nBạn có thể mở trang web sau để thử lại:", + "https://www.snaptikvideo.com/" + ); + } finally { + closeLoading(); + } + }, +}; From 4b398440712d0700808bdb9c50e1c8a4056c384a Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Sat, 3 Dec 2022 00:14:09 +0700 Subject: [PATCH 016/164] . --- scripts/tiktok_snaptikVideo.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/tiktok_snaptikVideo.js b/scripts/tiktok_snaptikVideo.js index 1c98e35d..ba2be468 100644 --- a/scripts/tiktok_snaptikVideo.js +++ b/scripts/tiktok_snaptikVideo.js @@ -55,7 +55,8 @@ export default { value: withoutWaterMarkMp4 || withoutWaterMarkVideo, }, { name: "MP4", value: waterMarkMp4 }, - { name: "MP3 🎵", value: mp3 || music }, + { name: "MP3 🎵", value: mp3 }, + { name: "Music 🎵", value: music }, { name: "HD Video", value: waterMarkVideo }, { name: "Profile Picture", value: thumb }, ] From 08e38f8e291240cae6aedecac73030b5ddd98e8d Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Sat, 3 Dec 2022 00:15:50 +0700 Subject: [PATCH 017/164] . --- scripts/tiktok_snaptikVideo.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/tiktok_snaptikVideo.js b/scripts/tiktok_snaptikVideo.js index ba2be468..5253330a 100644 --- a/scripts/tiktok_snaptikVideo.js +++ b/scripts/tiktok_snaptikVideo.js @@ -7,8 +7,8 @@ export default { vi: "Tiktok - Tải video (snaptikvideo)", }, description: { - en: "", - vi: "", + en: "Download tiktok video (mp4/mp3/no watermark) using snaptikvideo API", + vi: "Tải video tiktok (mp4/mp3/không watermark) dùng API snaptikvideo", }, runInExtensionContext: true, From 86915e02b2b53ea5483ae74efcd18bb5bcde2fe4 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Sat, 3 Dec 2022 05:03:48 +0700 Subject: [PATCH 018/164] tiktok --- popup/tabs.js | 2 + scripts/google_downloadAllYourData.js | 12 ++++ scripts/helpers/utils.js | 9 +-- scripts/index.js | 7 ++ scripts/tiktok_downloadWatchingVideo.js | 90 +++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 scripts/google_downloadAllYourData.js create mode 100644 scripts/tiktok_downloadWatchingVideo.js diff --git a/popup/tabs.js b/popup/tabs.js index ae8e1838..1eded947 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -77,6 +77,7 @@ const tabs = [ scripts: [ createTitle("--- Download ---", "--- Tải xuống ---"), s.ggdrive_downloadVideo, + s.google_downloadAllYourData, createTitle("--- More ---", "--- Khác ---"), s.search_totalIndexedPages, s.search_googleSite, @@ -151,6 +152,7 @@ const tabs = [ ...CATEGORY.tiktok, scripts: [ createTitle("--- Tiktok ---", "--- Tiktok ---"), + s.tiktok_downloadWatchingVideo, s.tiktok_snaptikApp, s.tiktok_snaptikVideo, createTitle("--- Douyin ---", "--- Douyin ---"), diff --git a/scripts/google_downloadAllYourData.js b/scripts/google_downloadAllYourData.js new file mode 100644 index 00000000..8c7d27f9 --- /dev/null +++ b/scripts/google_downloadAllYourData.js @@ -0,0 +1,12 @@ +export default { + icon: "https://www.google.com/favicon.ico", + name: { + en: "Google - Download all your data", + vi: "Google - Tải xuống dữ liệu của bạn", + }, + description: { + en: "Download all your data on Google", + vi: "Tải xuống thông tin của bạn trên Google", + }, + link: "https://takeout.google.com/settings/takeout", +}; diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index c9e3a5af..8139a13f 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -134,13 +134,10 @@ export async function openWebAndRunScript({ closeAfterRunScript = false, }) { let tab = await chrome.tabs.create({ active: false, url: url }); - await chrome.scripting.executeScript({ - target: { tabId: tab.id }, - func: func, - args: args, - }); - focusAfterRunScript && focusToTab(tab); + let res = await runScript({ func, tabId: tab.id, args }); + !closeAfterRunScript && focusAfterRunScript && focusToTab(tab); closeAfterRunScript && closeTab(tab); + return res; } export function attachDebugger(tab) { diff --git a/scripts/index.js b/scripts/index.js index ec3a74f0..ed3a7006 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -129,6 +129,8 @@ import shopee_topVariation from "./shopee_topVariation.js"; import donotBlockMe from "./donotBlockMe.js"; import ggdrive_downloadVideo from "./ggdrive_downloadVideo.js"; import tiktok_snaptikVideo from "./tiktok_snaptikVideo.js"; +import google_downloadAllYourData from "./google_downloadAllYourData.js"; +import tiktok_downloadWatchingVideo from "./tiktok_downloadWatchingVideo.js"; // inject badges const allScripts = { @@ -273,6 +275,11 @@ const allScripts = { donotBlockMe: addBadge(donotBlockMe, BADGES.new), ggdrive_downloadVideo: addBadge(ggdrive_downloadVideo, BADGES.new), tiktok_snaptikVideo: addBadge(tiktok_snaptikVideo, BADGES.new), + google_downloadAllYourData: addBadge(google_downloadAllYourData, BADGES.new), + tiktok_downloadWatchingVideo: addBadge( + tiktok_downloadWatchingVideo, + BADGES.new + ), }; // inject id to all scripts diff --git a/scripts/tiktok_downloadWatchingVideo.js b/scripts/tiktok_downloadWatchingVideo.js new file mode 100644 index 00000000..00b7c227 --- /dev/null +++ b/scripts/tiktok_downloadWatchingVideo.js @@ -0,0 +1,90 @@ +import { openWebAndRunScript, showLoading } from "./helpers/utils.js"; + +export default { + icon: "https://www.tiktok.com/favicon.ico", + name: { + en: "Tiktok - Download watching video", + vi: "Tiktok - Tải video đang xem", + }, + description: { + en: "Download tiktok video that you are watching (include watermark)", + vi: "Tải video tiktok bạn đang xem (có watermark)", + }, + runInExtensionContext: false, + + func: async function () { + let el = document.querySelector("video")?.parentElement.parentElement, + keyFiber = "", + keyProp = ""; + + for (let k of Object.keys(el)) { + if (k.indexOf("__reactFiber") === 0) { + keyFiber = k; + } + if (k.indexOf("__reactProps") === 0) { + keyProp = k; + } + } + + let url = + el[keyFiber].child?.memoizedProps?.url || + el[keyFiber].firstEffect?.memoizedProps?.url || + el[keyProp].children?.[0]?.props?.url; + url ? window.open(url) : alert("Không tìm thấy link video"); + }, +}; + +async function backup() { + // =================== Tải video (watermark) từ link video =================== + let url = prompt("Nhập link tiktok video: "); + if (url != null) { + const { closeLoading } = showLoading("Đang get link video..."); + try { + let res = await openWebAndRunScript({ + url, + closeAfterRunScript: true, + focusAfterRunScript: false, + func: () => { + return window.SIGI_STATE; + }, + }); + if (!res) { + alert("Không lấy được dữ liệu."); + return; + } + let videoKey = Object.keys(res.ItemModule)?.[0]; + let videoData = res.ItemModule[videoKey]; + console.log(videoData); + window.open(videoData?.video?.downloadAddr || videoData?.video?.playAddr); + } catch (e) { + alert("ERROR: " + e); + } finally { + closeLoading(); + } + } + + // =================== Tải về mọi video trong user tiktok =================== + let containers = Array.from( + document.querySelectorAll(".tiktok-x6y88p-DivItemContainerV2.e19c29qe7") + ); + let videos = []; + + for (let c of containers) { + // find react fiber key + let key = ""; + for (let k of Object.keys(c)) { + if (k.indexOf("__reactFiber") === 0) { + key = k; + break; + } + } + let video = + c[key].firstEffect?.memoizedProps || + c[key].lastEffect?.memoizedProps || + c[key].return?.alternate?.firstEffect?.memoizedProps; + + videos.push(video); + } + + console.log(videos); +} From 47ab5c6eca83ac632289e873c5b5bd9978c7c714 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Sat, 3 Dec 2022 06:11:02 +0700 Subject: [PATCH 019/164] gg drive download --- scripts/ggdrive_downloadVideo.js | 136 ++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 46 deletions(-) diff --git a/scripts/ggdrive_downloadVideo.js b/scripts/ggdrive_downloadVideo.js index 5736a201..94a75e6d 100644 --- a/scripts/ggdrive_downloadVideo.js +++ b/scripts/ggdrive_downloadVideo.js @@ -1,3 +1,10 @@ +import { + getCurrentTab, + openPopupWithHtml, + runScriptInCurrentTab, + showLoading, +} from "./helpers/utils.js"; + export default { icon: "https://drive.google.com/favicon.ico", name: { @@ -10,68 +17,105 @@ export default { }, blackList: [], whiteList: [], - runInExtensionContext: false, + runInExtensionContext: true, func: async function () { // Post: https://www.facebook.com/groups/j2team.community/posts/974953859503401/ - function parse(e) { - var result = {}; - return ( - e.split("&").forEach(function (e) { - result[decodeURIComponent(e.substring(0, e.indexOf("=")))] = - decodeURIComponent(e.substring(e.indexOf("=") + 1)); - }), - result - ); - } + async function getLinkVideoGDrive(docid) { + function parse(e) { + var result = {}; + return ( + e.split("&").forEach(function (e) { + result[decodeURIComponent(e.substring(0, e.indexOf("=")))] = + decodeURIComponent(e.substring(e.indexOf("=") + 1)); + }), + result + ); + } - function parseStream(e) { - var d = []; - return ( - e.split(",").forEach(function (e) { - d.push(parse(e)); - }), - d - ); - } + function parseStream(e) { + var d = []; + return ( + e.split(",").forEach(function (e) { + d.push(parse(e)); + }), + d + ); + } - function downloadVideo(videoInfo) { - window.open(videoInfo.url + "&filename=" + videoInfo.name); - } + async function getVideoLinkFromDocId(docid) { + let res = await fetch( + "https://drive.google.com/get_video_info?docid=" + docid + ); - async function getVideoLinkFromDocId(docid) { - let res = await fetch( - "https://drive.google.com/get_video_info?docid=" + docid - ); + let text = await res.text(); + let json = parse(text); - let text = await res.text(); - let json = parse(text); + json.url_encoded_fmt_stream_map = parseStream( + json.url_encoded_fmt_stream_map + ); - json.url_encoded_fmt_stream_map = parseStream( - json.url_encoded_fmt_stream_map - ); + let result = json.url_encoded_fmt_stream_map.map(function (stream) { + let name = json.title.replace(/\+/g, " "); + return { + idfile: docid, + name: name, + quality: stream.quality, + url: stream.url, + }; + }); - let result = json.url_encoded_fmt_stream_map.map(function (stream) { - let name = json.title.replace(/\+/g, " "); - return { - idfile: docid, - name: name, - quality: stream.quality, - url: stream.url, - }; - }); + console.log(result); + return result; + } + + // let { id, title } = window?.viewerData?.config; + return await getVideoLinkFromDocId(docid); + } - console.log(result); - return result; + // https://stackoverflow.com/a/16840612 + function getIdFromUrl(url) { + return url.match(/[-\w]{25,}(?!.*[-\w]{25,})/); } + let { closeLoading } = showLoading("Đang tìm link video..."); try { - let { id, title } = window.viewerData.config; - console.log("get link..."); - await getVideoLinkFromDocId(id); + let docid = await runScriptInCurrentTab(() => { + return window?.viewerData?.config?.id; + }); + + if (!docid) { + let tab = await getCurrentTab(); + let url = prompt("Nhập link google drive video: ", tab.url); + if (url == null) return; + docid = getIdFromUrl(url); + if (!docid) + throw Error("Link không hợp lệ. Không tìm thấy id trong link."); + } + + let res = await getLinkVideoGDrive(docid); + if (!res?.length) throw Error("Không tìm được link video."); + console.log(res); + + openPopupWithHtml( + `

${res[0].name}

+ ${res + .map((_) => { + let name = _.name.replace(/ /g, "_"); + return `
+

${_.quality}

+
`; + }) + .join("
")}`, + 700, + 700 + ); } catch (e) { alert("ERROR: " + e); + } finally { + closeLoading(); } }, }; From 2921c3feccd4620db3f7e53999ca4c32a1fb0ca0 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Sat, 3 Dec 2022 16:18:13 +0700 Subject: [PATCH 020/164] . --- popup/tabs.js | 1 + scripts/alert.js | 89 +++++++++++++++++++++++++++ scripts/fb_storyInfo.js | 92 +++++++++++++++------------- scripts/google_downloadDriveVideo.js | 30 --------- scripts/index.js | 4 +- 5 files changed, 140 insertions(+), 76 deletions(-) create mode 100644 scripts/alert.js delete mode 100644 scripts/google_downloadDriveVideo.js diff --git a/popup/tabs.js b/popup/tabs.js index 1eded947..5306aea8 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -36,6 +36,7 @@ const tabs = [ { ...CATEGORY.search, scripts: [ + s.alert, s._test, s.whatFont, s.similarWeb, diff --git a/scripts/alert.js b/scripts/alert.js new file mode 100644 index 00000000..7352a8be --- /dev/null +++ b/scripts/alert.js @@ -0,0 +1,89 @@ +import { + runScript, + runScriptInCurrentTab, + showLoading, +} from "./helpers/utils.js"; + +export default { + icon: "", + name: { + en: "Alert something", + vi: "Alert something", + }, + description: { + en: "...", + vi: "....", + }, + blackList: [], + whiteList: [], + runInExtensionContext: true, + + func: async function () { + const { closeLoading, setLoadingText } = showLoading( + "Đang thu thập video link của user..." + ); + + let urls = await runScriptInCurrentTab(() => { + // var videoDes = Array.from( + // document.querySelectorAll( + // "div.tiktok-1qb12g8-DivThreeColumnContainer.eegew6e2 > div > div > div > a" + // ) + // ).map((items) => items.innerText); + // console.log(videoDes); + return Array.from( + document.querySelectorAll( + "div.tiktok-1qb12g8-DivThreeColumnContainer > div > div > div > div > div > a" + ), + (element) => element.href + ); + }); + + async function getVideoURL(link) { + const API_URL = `https://api19-core-useast5.us.tiktokv.com/aweme/v1/feed/?aweme_id=${link}&version_code=262&app_name=musical_ly&channel=App&device_id=null&os_version=14.4.2&device_platform=iphone&device_type=iPhone9`; + const request = await fetch(API_URL, { + method: "GET", + headers: { + "Content-Type": "application/json", + "User-Agent": + "TikTok 26.2.0 rv:262018 (iPhone; iOS 14.4.2; en_US) Cronet", + }, + }); + const res = await request.json(); + console.log(res); + const getvideourl = res.aweme_list[0].video.play_addr.url_list[0]; + return getvideourl; + } + + function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + let videoUrls = []; + for (var i = 0; i < urls.length; i++) { + let link = urls[i].slice(-19).toString(); + setLoadingText(`Đang get link [${i}] ${link} ...`); + const videoURL = await getVideoURL(link); + videoUrls.push(videoURL); + + let t = 500; + setLoadingText(`Get link [${i}] xong. Đang chờ ${t}ms...`); + await sleep(t); + } + console.log(videoUrls); + closeLoading(); + }, +}; + +async function backup() { + const getRedirectUrl = async (url) => { + if (url.includes("vm.tiktok.com") || url.includes("vt.tiktok.com")) { + url = await fetch(url, { + redirect: "follow", + follow: 10, + }); + url = url.url; + console.log(chalk.green("[*] Redirecting to: " + url)); + } + return url; + }; +} diff --git a/scripts/fb_storyInfo.js b/scripts/fb_storyInfo.js index 77499e00..6a7c3d2c 100644 --- a/scripts/fb_storyInfo.js +++ b/scripts/fb_storyInfo.js @@ -54,60 +54,64 @@ export default { "Author name": data.owner.name, "Author profile picture": data.owner.profile_picture.uri, "Author profile URL": data.owner.url, - Objects: data.unified_stories.edges.map((_) => { + Objects: data.unified_stories.edges.map((_, i) => { + console.log(_); return { "Picture blured": - _.edges[i].node.attachments[0].media.blurredImage.uri, + data.unified_stories.edges[i].node.attachments[0].media + .blurredImage.uri, "Picture preview url": - _.edges[i].node.attachments[0].media.previewImage.uri, + data.unified_stories.edges[i].node.attachments[0].media + .previewImage.uri, "Total reaction feedback": - _.edges[i].node.story_card_info.feedback_summary - .total_reaction_count, + data.unified_stories.edges[i].node.story_card_info + .feedback_summary.total_reaction_count, "Background CSS": - _.edges[i].node.story_default_background.color, + data.unified_stories.edges[i].node + .story_default_background.color, "Background CSS3": - _.edges[i].node.story_default_background.gradient.css, - - ..._( - _.edges[i].node.attachments[0].media.__typename == - "Photo" - ? { - Caption: - _.edges[i].node.attachments[0].media - .accessibility_caption, - - Image: - _.edges[i].node.attachments[0].media.image.uri, - } - : _.edges[i].node.attachments[0].media.__typename == - "Video" - ? { - "Permalink video url": - data.unified_stories.edges[i].node - .attachments[0].media.permalink_url, - - "Playable_url url": - data.unified_stories.edges[i].node - .attachments[0].media.playable_url, - - "playable_url_dash url": - data.unified_stories.edges[0].node - .attachments[0].media.playable_url_dash, - - "playableUrlHdString url": - data.unified_stories.edges[i].node - .attachments[0].media.playableUrlHdString, - - "playable_url_quality_hd url": - data.unified_stories.edges[i].node - .attachments[0].media.playable_url_quality_hd, - } - : null - ), + data.unified_stories.edges[i].node + .story_default_background.gradient.css, + + ...(data.unified_stories.edges[i].node.attachments[0] + .media.__typename == "Photo" + ? { + Caption: + data.unified_stories.edges[i].node.attachments[0] + .media.accessibility_caption, + + Image: + data.unified_stories.edges[i].node.attachments[0] + .media.image.uri, + } + : data.unified_stories.edges[i].node.attachments[0] + .media.__typename == "Video" + ? { + "Permalink video url": + data.unified_stories.edges[i].node.attachments[0] + .media.permalink_url, + + "Playable_url url": + data.unified_stories.edges[i].node.attachments[0] + .media.playable_url, + + "playable_url_dash url": + data.unified_stories.edges[0].node.attachments[0] + .media.playable_url_dash, + + "playableUrlHdString url": + data.unified_stories.edges[i].node.attachments[0] + .media.playableUrlHdString, + + "playable_url_quality_hd url": + data.unified_stories.edges[i].node.attachments[0] + .media.playable_url_quality_hd, + } + : null), }; }), }); diff --git a/scripts/google_downloadDriveVideo.js b/scripts/google_downloadDriveVideo.js deleted file mode 100644 index ee8f7890..00000000 --- a/scripts/google_downloadDriveVideo.js +++ /dev/null @@ -1,30 +0,0 @@ -export default { - icon: ``, - name: { - en: "Download google drive video", - vi: "Tải video google drive", - }, - description: { - en: "For video that doesn't have download button in google drive", - vi: "Dành cho video không có nút 'tải về' do chủ sở hữu đã giới hạn quyền", - }, - blackList: [], - whiteList: ["*://drive.google.com/"], - - func: function () { - let iframe = document.querySelector("iframe"); - if (!iframe) { - alert("Iframe Video not found / Không thấy video nào."); - } else { - let innerDoc = iframe.contentDocument || iframe.contentWindow.document; - console.log(innerDoc); - let videos = Array.from(innerDoc.querySelectorAll("video")); - - if (videos.length === 0) { - alert("Video not found / Không thấy video nào."); - } else { - window.open(videos[0].src); - } - } - }, -}; diff --git a/scripts/index.js b/scripts/index.js index ed3a7006..c02b27a9 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -81,7 +81,6 @@ import downDetector from "./downDetector.js"; import fb_getTokenFfb from "./fb_getTokenFfb.js"; import youtube_popupPlayer from "./youtube_popupPlayer.js"; import googleShortcuts from "./googleShortcuts.js"; -import google_downloadDriveVideo from "./google_downloadDriveVideo.js"; import paywallKiller from "./paywallKiller.js"; import archiveToday from "./archiveToday.js"; import download_video2 from "./download_video2.js"; @@ -131,6 +130,7 @@ import ggdrive_downloadVideo from "./ggdrive_downloadVideo.js"; import tiktok_snaptikVideo from "./tiktok_snaptikVideo.js"; import google_downloadAllYourData from "./google_downloadAllYourData.js"; import tiktok_downloadWatchingVideo from "./tiktok_downloadWatchingVideo.js"; +import alert from "./alert.js"; // inject badges const allScripts = { @@ -218,7 +218,6 @@ const allScripts = { fb_getTokenFfb: addBadge(fb_getTokenFfb, BADGES.new), youtube_popupPlayer: addBadge(youtube_popupPlayer, BADGES.beta), googleShortcuts: addBadge(googleShortcuts, BADGES.new), - google_downloadDriveVideo: addBadge(google_downloadDriveVideo, BADGES.beta), paywallKiller: addBadge(paywallKiller, BADGES.beta), archiveToday: archiveToday, download_video2: addBadge(download_video2, BADGES.hot), @@ -280,6 +279,7 @@ const allScripts = { tiktok_downloadWatchingVideo, BADGES.new ), + alert: addBadge(alert, BADGES.new), }; // inject id to all scripts From 93c811e73aa82533887036d171dc17361fc8e481 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Sun, 4 Dec 2022 01:50:56 +0700 Subject: [PATCH 021/164] shared + tiktok download --- empty_script.js | 3 + popup/tabs.js | 4 +- scripts/_test.js | 11 +- scripts/alert.js | 89 ------- .../scripts/useful-scripts-utils.js | 18 ++ scripts/helpers/utils.js | 18 ++ scripts/index.js | 10 +- scripts/scrollToVeryEnd.js | 22 +- scripts/tiktok_downloadUserVideos.js | 222 ++++++++++++++++++ scripts/tiktok_downloadVideoNoWM.js | 66 ++++++ scripts/tiktok_downloadWatchingVideo.js | 96 ++++---- 11 files changed, 407 insertions(+), 152 deletions(-) delete mode 100644 scripts/alert.js create mode 100644 scripts/tiktok_downloadUserVideos.js create mode 100644 scripts/tiktok_downloadVideoNoWM.js diff --git a/empty_script.js b/empty_script.js index fa7fc9f2..8782cc56 100644 --- a/empty_script.js +++ b/empty_script.js @@ -21,3 +21,6 @@ export default { func: function () {}, }; + +// Những thuộc tính/hàm có thể chia sẻ cho cách scripts khác sử dụng sẽ được viết vào đây +export const shared = {}; diff --git a/popup/tabs.js b/popup/tabs.js index 5306aea8..8f0d8fa6 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -36,7 +36,6 @@ const tabs = [ { ...CATEGORY.search, scripts: [ - s.alert, s._test, s.whatFont, s.similarWeb, @@ -152,8 +151,11 @@ const tabs = [ { ...CATEGORY.tiktok, scripts: [ + createTitle("--- Bulk Download ---", "--- Tải hàng loạt ---"), + s.tiktok_downloadUserVideos, createTitle("--- Tiktok ---", "--- Tiktok ---"), s.tiktok_downloadWatchingVideo, + s.tiktok_downloadVideoNoWM, s.tiktok_snaptikApp, s.tiktok_snaptikVideo, createTitle("--- Douyin ---", "--- Douyin ---"), diff --git a/scripts/_test.js b/scripts/_test.js index 84477285..aa3ce19e 100644 --- a/scripts/_test.js +++ b/scripts/_test.js @@ -1,4 +1,5 @@ import { runScriptInCurrentTab } from "./helpers/utils.js"; +import scrollToVeryEnd from "./scrollToVeryEnd.js"; export default { icon: "", @@ -13,9 +14,11 @@ export default { runInExtensionContext: true, func: async function () { - let dtsg = await runScriptInCurrentTab(() => { - return require("DTSGInitialData").token; - }); - alert(dtsg); + // let dtsg = await runScriptInCurrentTab(() => { + // return require("DTSGInitialData").token; + // }); + // alert(dtsg); + await runScriptInCurrentTab(scrollToVeryEnd.func); + alert("xong"); }, }; diff --git a/scripts/alert.js b/scripts/alert.js deleted file mode 100644 index 7352a8be..00000000 --- a/scripts/alert.js +++ /dev/null @@ -1,89 +0,0 @@ -import { - runScript, - runScriptInCurrentTab, - showLoading, -} from "./helpers/utils.js"; - -export default { - icon: "", - name: { - en: "Alert something", - vi: "Alert something", - }, - description: { - en: "...", - vi: "....", - }, - blackList: [], - whiteList: [], - runInExtensionContext: true, - - func: async function () { - const { closeLoading, setLoadingText } = showLoading( - "Đang thu thập video link của user..." - ); - - let urls = await runScriptInCurrentTab(() => { - // var videoDes = Array.from( - // document.querySelectorAll( - // "div.tiktok-1qb12g8-DivThreeColumnContainer.eegew6e2 > div > div > div > a" - // ) - // ).map((items) => items.innerText); - // console.log(videoDes); - return Array.from( - document.querySelectorAll( - "div.tiktok-1qb12g8-DivThreeColumnContainer > div > div > div > div > div > a" - ), - (element) => element.href - ); - }); - - async function getVideoURL(link) { - const API_URL = `https://api19-core-useast5.us.tiktokv.com/aweme/v1/feed/?aweme_id=${link}&version_code=262&app_name=musical_ly&channel=App&device_id=null&os_version=14.4.2&device_platform=iphone&device_type=iPhone9`; - const request = await fetch(API_URL, { - method: "GET", - headers: { - "Content-Type": "application/json", - "User-Agent": - "TikTok 26.2.0 rv:262018 (iPhone; iOS 14.4.2; en_US) Cronet", - }, - }); - const res = await request.json(); - console.log(res); - const getvideourl = res.aweme_list[0].video.play_addr.url_list[0]; - return getvideourl; - } - - function sleep(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); - } - - let videoUrls = []; - for (var i = 0; i < urls.length; i++) { - let link = urls[i].slice(-19).toString(); - setLoadingText(`Đang get link [${i}] ${link} ...`); - const videoURL = await getVideoURL(link); - videoUrls.push(videoURL); - - let t = 500; - setLoadingText(`Get link [${i}] xong. Đang chờ ${t}ms...`); - await sleep(t); - } - console.log(videoUrls); - closeLoading(); - }, -}; - -async function backup() { - const getRedirectUrl = async (url) => { - if (url.includes("vm.tiktok.com") || url.includes("vt.tiktok.com")) { - url = await fetch(url, { - redirect: "follow", - follow: 10, - }); - url = url.url; - console.log(chalk.green("[*] Redirecting to: " + url)); - } - return url; - }; -} diff --git a/scripts/content-scripts/scripts/useful-scripts-utils.js b/scripts/content-scripts/scripts/useful-scripts-utils.js index 5ee9364f..b6dbc60c 100644 --- a/scripts/content-scripts/scripts/useful-scripts-utils.js +++ b/scripts/content-scripts/scripts/useful-scripts-utils.js @@ -118,4 +118,22 @@ window.UsefulScriptsUtils = { JSON.parse('"' + str.replace(/\"/g, '\\"') + '"') ); }, + + // https://stackoverflow.com/a/8649003 + searchParamsToObject(search) { + // let d = {}; + // decodeURI(search) + // .split("&") + // .map((_) => _.split("=")) + // .forEach((_) => (d[_[0]] = _[1])); + // return d; + + search = search || location.search.substring(1); + return JSON.parse( + '{"' + search.replace(/&/g, '","').replace(/=/g, '":"') + '"}', + function (key, value) { + return key === "" ? value : decodeURIComponent(value); + } + ); + }, }; diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index 8139a13f..003b5724 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -176,8 +176,26 @@ export async function captureVisibleTab(options = {}, willDownload = true) { // #endregion +// #region String Utils + +export function encodeQueryString(obj) { + var str = []; + for (var p in obj) + if (obj.hasOwnProperty(p)) { + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); + } + return str.join("&"); +} + +// #endregion + // #region Download Utils +// https://stackoverflow.com/a/39914235 +export function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + // https://stackoverflow.com/a/15832662/11898496 // TODO: chrome.downloads: https://developer.chrome.com/docs/extensions/reference/downloads/#method-download export function downloadURI(uri, name) { diff --git a/scripts/index.js b/scripts/index.js index c02b27a9..67d9e4c0 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -130,7 +130,8 @@ import ggdrive_downloadVideo from "./ggdrive_downloadVideo.js"; import tiktok_snaptikVideo from "./tiktok_snaptikVideo.js"; import google_downloadAllYourData from "./google_downloadAllYourData.js"; import tiktok_downloadWatchingVideo from "./tiktok_downloadWatchingVideo.js"; -import alert from "./alert.js"; +import tiktok_downloadUserVideos from "./tiktok_downloadUserVideos.js"; +import tiktok_downloadVideoNoWM from "./tiktok_downloadVideoNoWM.js"; // inject badges const allScripts = { @@ -268,9 +269,9 @@ const allScripts = { fb_downloadCommentVideo: addBadge(fb_downloadCommentVideo, BADGES.new), scribd_downloadDocuments: addBadge(scribd_downloadDocuments, BADGES.new), fb_hideNewFeed: addBadge(fb_hideNewFeed, BADGES.new), - fb_storyInfo: addBadge(fb_storyInfo, BADGES.new), + fb_storyInfo: addBadge(fb_storyInfo, BADGES.beta), envato_previewBypass: addBadge(envato_previewBypass, BADGES.new), - shopee_topVariation: addBadge(shopee_topVariation, BADGES.new), + shopee_topVariation: addBadge(shopee_topVariation, BADGES.beta), donotBlockMe: addBadge(donotBlockMe, BADGES.new), ggdrive_downloadVideo: addBadge(ggdrive_downloadVideo, BADGES.new), tiktok_snaptikVideo: addBadge(tiktok_snaptikVideo, BADGES.new), @@ -279,7 +280,8 @@ const allScripts = { tiktok_downloadWatchingVideo, BADGES.new ), - alert: addBadge(alert, BADGES.new), + tiktok_downloadUserVideos: addBadge(tiktok_downloadUserVideos, BADGES.beta), + tiktok_downloadVideoNoWM: addBadge(tiktok_downloadVideoNoWM, BADGES.new), }; // inject id to all scripts diff --git a/scripts/scrollToVeryEnd.js b/scripts/scrollToVeryEnd.js index fb7d046d..a982043e 100644 --- a/scripts/scrollToVeryEnd.js +++ b/scripts/scrollToVeryEnd.js @@ -10,12 +10,12 @@ export default { }, func: function () { - let height = () => - (document.scrollingElement || document.body).scrollHeight; - let down = () => window.scrollTo({ left: 0, top: height() }); - let sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise(async (resolve, reject) => { + let height = () => + (document.scrollingElement || document.body).scrollHeight; + let down = () => window.scrollTo({ left: 0, top: height() }); + let sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); - (async () => { let lastScroll = { time: Date.now(), top: 0, @@ -25,7 +25,7 @@ export default { let clickToCancel = () => { running = false; document.removeEventListener("click", clickToCancel); - alert("scroll to very end STOPPED by user click"); + // alert("scroll to very end STOPPED by user click"); }; document.addEventListener("click", clickToCancel); @@ -37,12 +37,12 @@ export default { lastScroll.time = Date.now(); } else if (Date.now() - lastScroll.time > 5000) { running = false; - alert("scroll to very end DONE"); + // alert("scroll to very end DONE"); } - - if (!running) break; - else await sleep(100); + await sleep(100); } - })(); + + resolve(); + }); }, }; diff --git a/scripts/tiktok_downloadUserVideos.js b/scripts/tiktok_downloadUserVideos.js new file mode 100644 index 00000000..3c19107e --- /dev/null +++ b/scripts/tiktok_downloadUserVideos.js @@ -0,0 +1,222 @@ +import { + downloadData, + runScriptInCurrentTab, + showLoading, + sleep, +} from "./helpers/utils.js"; +import scrollToVeryEnd from "./scrollToVeryEnd.js"; +import * as tiktok_downloadVideoNoWM from "./tiktok_downloadVideoNoWM.js"; + +export default { + icon: "https://www.tiktok.com/favicon.ico", + name: { + en: "Tiktok - Download all user videos", + vi: "Tiktok - Tải tất cả video người dùng", + }, + description: { + en: "Download all videos in tiktok user profile.", + vi: "Tải tất cả video trong trang cá nhân của người dùng tiktok.", + }, + blackList: [], + whiteList: [], + runInExtensionContext: true, + + func: async function () { + // Source code: https://github.com/karim0sec/tiktokdl + + const generateProfileUrl = (username) => { + return "https://www.tiktok.com/@" + username.replace("@", ""); + }; + + let { closeLoading, setLoadingText } = showLoading( + "Đang scroll trang web xuống cuối..." + ); + try { + await runScriptInCurrentTab(scrollToVeryEnd.func); + + setLoadingText("Đang lấy danh sách video..."); + let urls = await runScriptInCurrentTab(() => { + // var videoDes = Array.from( + // document.querySelectorAll( + // "div.tiktok-1qb12g8-DivThreeColumnContainer.eegew6e2 > div > div > div > a" + // ) + // ).map((items) => items.innerText); + // console.log(videoDes); + return Array.from( + document.querySelectorAll( + "div.tiktok-1qb12g8-DivThreeColumnContainer > div > div > div > div > div > a" + ), + (element) => element.href + ); + }); + + console.log(urls); + alert("Tìm thấy " + urls.length + " video. Bấm ok để tiếp tục."); + + let videoUrls = []; + let errorCount = 0; + for (var i = 0; i < urls.length; i++) { + try { + let aweme_id = urls[i].slice(-19).toString(); + setLoadingText( + `

+ Đang get link ${i}/${urls.length}...
+ ${urls[i]}
+ Lỗi: ${errorCount} links +

` + ); + let videoURL = + await tiktok_downloadVideoNoWM.shared.getVideoNoWaterMark(urls[i]); + videoUrls.push(videoURL); + } catch (e) { + console.error(e); + errorCount++; + } + + // let t = 500; + // setLoadingText( + // `Get link xong [${i}/${urls.length}]...
Đang chờ ${t}ms...` + // ); + // await sleep(t); + } + console.log(videoUrls); + if (videoUrls.length) + downloadData(videoUrls.join("\n"), "tiktok-user-videos", ".txt"); + else alert("Không tìm được video nào"); + } catch (e) { + alert("ERROR: " + e); + } finally { + closeLoading(); + } + }, +}; + +async function backup() { + // =================== Tải về mọi video trong user tiktok (có watermark) =================== + let containers = Array.from( + document.querySelectorAll(".tiktok-x6y88p-DivItemContainerV2.e19c29qe7") + ); + let videos = []; + + for (let c of containers) { + // find react fiber key + let key = ""; + for (let k of Object.keys(c)) { + if (k.indexOf("__reactFiber") === 0) { + key = k; + break; + } + } + let video = + c[key].firstEffect?.memoizedProps || + c[key].lastEffect?.memoizedProps || + c[key].return?.alternate?.firstEffect?.memoizedProps; + + videos.push(video); + } + + console.log(videos); + + // =========================================================================== + const getRedirectUrl = async (url) => { + if (url.includes("vm.tiktok.com") || url.includes("vt.tiktok.com")) { + url = await fetch(url, { + redirect: "follow", + follow: 10, + }); + url = url.url; + console.log(chalk.green("[*] Redirecting to: " + url)); + } + return url; + }; + + let data = { + device_platform: "web_pc", + screen_width: "0", + focus_state: "false", + tz_name: "Asia/Saigon", + from_page: "user", + webcast_language: "en", + history_len: "9", + is_fullscreen: "false", + _signature: "_02B4Z6wo00001uk-.ygAAIDDN0injBoKKDbpPvuAANnRdf", + os: "windows", + priority_region: "", + aid: "1988", + app_language: "en", + app_name: "tiktok_web", + battery_info: "1", + browser_language: "en-US", + browser_name: "Mozilla", + browser_online: "true", + browser_platform: "Win32", + browser_version: + "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.62", + channel: "tiktok_web", + region: "VN", + device_id: "431432143153214321", + screen_height: "864", + }; + + // x-tt-params 4mOJhGnMOdadxrLEy2bkmGSR2R38w8nZC8MQKREioTAU76aXIbW + // https://www.tiktok.com/api/post/item_list/? + + encrypt = (e) => { + const t = []; + return ( + Object.keys(e).forEach((i) => { + const o = `${i}=${e[i]}`; + t.push(o); + }), + t.push("is_encryption=1"), + ((e, t) => { + const i = ((e, t) => { + let i = e.toString(); + const o = i.length; + return ( + o < 16 + ? (i = new Array(16 - o + 1).join("0") + i) + : o > 16 && (i = i.slice(0, 16)), + i + ); + })("webapp1.0+20210628"), + n = o.enc.Utf8.parse(i); + return o.AES.encrypt(e, n, { + iv: n, + mode: o.mode.CBC, + padding: o.pad.Pkcs7, + }).toString(); + })(t.join("&")) + ); + }; + + encrypt = (searchParams) => { + const path = []; + Object.keys(searchParams).forEach((recipient) => { + const testFilePath = `${recipient}=${searchParams[recipient]}`; + path.push(testFilePath); + }); + path.push("is_encryption=1"); + pathStr = path.join("&"); + + // let pathStr = new URLSearchParams({ + // ...searchParams, + // is_encryption: 1, + // }).toString(); + + const key = ((e, t) => { + let i = e.toString(); + const o = i.length; + // prettier-ignore + return o < 16 ? i = new Array(16 - o + 1).join("0") + i : o > 16 && (i = i.slice(0, 16)), + i + })("webapp1.0+20210628"); + + const nonce = o.enc.Utf8.parse(key); + return o.AES.encrypt(pathStr, nonce, { + iv: nonce, + mode: o.mode.CBC, + padding: o.pad.Pkcs7, + }).toString(); + }; +} diff --git a/scripts/tiktok_downloadVideoNoWM.js b/scripts/tiktok_downloadVideoNoWM.js new file mode 100644 index 00000000..3366732c --- /dev/null +++ b/scripts/tiktok_downloadVideoNoWM.js @@ -0,0 +1,66 @@ +import { runScriptInCurrentTab, showLoading } from "./helpers/utils.js"; + +export default { + icon: "https://www.tiktok.com/favicon.ico", + name: { + en: "Tiktok - Download video (API)", + vi: "Tiktok - Tải video (API)", + }, + description: { + en: "Download tiktok video from url (no watermark)", + vi: "Tải video tiktok từ link (không watermark)", + }, + runInExtensionContext: true, + + func: async function () { + let url = prompt( + "Nhập link tiktok video: ", + await runScriptInCurrentTab(() => location.href) + ); + + if (url == null) return; + let { closeLoading } = showLoading( + "Đang lấy link video không watermark..." + ); + try { + let videoNoWM = await shared.getVideoNoWaterMark(url); + if (videoNoWM) window.open(videoNoWM); + else throw Error("Không tìm được video không watermark"); + } catch (e) { + alert("ERROR: " + e); + } finally { + closeLoading(); + } + }, +}; + +export const shared = { + // Source code: https://github.com/karim0sec/tiktokdl + getVideoId(url) { + // return urls[i].slice(-19).toString() + if (!url.includes("/video/")) return null; + let idVideo = url.substring(url.indexOf("/video/") + 7, url.length); + return idVideo.length > 19 + ? idVideo.substring(0, idVideo.indexOf("?")) + : idVideo; + }, + + getVideoNoWaterMark: async function (video_url, isVideoId = false) { + let videoId = isVideoId ? video_url : shared.getVideoId(video_url); + if (!videoId) throw Error("Video URL không đúng định dạng"); + + let API_URL = `https://api19-core-useast5.us.tiktokv.com/aweme/v1/feed/?aweme_id=${videoId}&version_code=262&app_name=musical_ly&channel=App&device_id=null&os_version=14.4.2&device_platform=iphone&device_type=iPhone9`; + let request = await fetch(API_URL, { + method: "GET", + headers: { + "Content-Type": "application/json", + "User-Agent": + "TikTok 26.2.0 rv:262018 (iPhone; iOS 14.4.2; en_US) Cronet", + }, + }); + let res = await request.json(); + console.log(res); + let url = res.aweme_list[0].video.play_addr.url_list[0]; + return url; + }, +}; diff --git a/scripts/tiktok_downloadWatchingVideo.js b/scripts/tiktok_downloadWatchingVideo.js index 00b7c227..53d88423 100644 --- a/scripts/tiktok_downloadWatchingVideo.js +++ b/scripts/tiktok_downloadWatchingVideo.js @@ -1,4 +1,9 @@ -import { openWebAndRunScript, showLoading } from "./helpers/utils.js"; +import { + openWebAndRunScript, + runScriptInCurrentTab, + showLoading, +} from "./helpers/utils.js"; +import * as tiktok_downloadVideoNoWM from "./tiktok_downloadVideoNoWM.js"; export default { icon: "https://www.tiktok.com/favicon.ico", @@ -7,30 +12,60 @@ export default { vi: "Tiktok - Tải video đang xem", }, description: { - en: "Download tiktok video that you are watching (include watermark)", - vi: "Tải video tiktok bạn đang xem (có watermark)", + en: "Download tiktok video you are watching (no/have watermark)", + vi: "Tải video tiktok bạn đang xem (không/có watermark)", }, - runInExtensionContext: false, + runInExtensionContext: true, func: async function () { - let el = document.querySelector("video")?.parentElement.parentElement, - keyFiber = "", - keyProp = ""; + async function getWatchingVideoNoWM() { + let videoId = await runScriptInCurrentTab(() => + document + .querySelector("video") + ?.parentElement?.id?.split?.("-") + ?.at?.(-1) + ); - for (let k of Object.keys(el)) { - if (k.indexOf("__reactFiber") === 0) { - keyFiber = k; - } - if (k.indexOf("__reactProps") === 0) { - keyProp = k; + return await tiktok_downloadVideoNoWM.shared.getVideoNoWaterMark( + videoId, + true + ); + } + + function getWatchingVideo() { + let el = document.querySelector("video")?.parentElement.parentElement, + keyFiber = "", + keyProp = ""; + for (let k of Object.keys(el)) { + if (k.startsWith("__reactFiber")) keyFiber = k; + if (k.startsWith("__reactProps")) keyProp = k; } + return ( + el[keyFiber].child?.memoizedProps?.url || + el[keyFiber].firstEffect?.memoizedProps?.url || + el[keyProp].children?.[0]?.props?.url + ); } - let url = - el[keyFiber].child?.memoizedProps?.url || - el[keyFiber].firstEffect?.memoizedProps?.url || - el[keyProp].children?.[0]?.props?.url; - url ? window.open(url) : alert("Không tìm thấy link video"); + let choice = prompt( + "Chọn loại video:\n" + " 0: Có watermark\n" + " 1: Không watermark", + 0 + ); + if (choice == null) return; + + let { closeLoading } = showLoading("Đang get link video..."); + try { + let url; + if (choice == 0) url = await runScriptInCurrentTab(getWatchingVideo); + if (choice == 1) url = await getWatchingVideoNoWM(); + + if (url) window.open(url); + else throw Error("Không tìm được video"); + } catch (e) { + alert("ERROR: " + e); + } finally { + closeLoading(); + } }, }; @@ -62,29 +97,4 @@ async function backup() { closeLoading(); } } - - // =================== Tải về mọi video trong user tiktok =================== - let containers = Array.from( - document.querySelectorAll(".tiktok-x6y88p-DivItemContainerV2.e19c29qe7") - ); - let videos = []; - - for (let c of containers) { - // find react fiber key - let key = ""; - for (let k of Object.keys(c)) { - if (k.indexOf("__reactFiber") === 0) { - key = k; - break; - } - } - let video = - c[key].firstEffect?.memoizedProps || - c[key].lastEffect?.memoizedProps || - c[key].return?.alternate?.firstEffect?.memoizedProps; - - videos.push(video); - } - - console.log(videos); } From e59dc94cf0daa42670b85a9936a0ace326dccacb Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Sun, 4 Dec 2022 02:25:05 +0700 Subject: [PATCH 022/164] tiktok api unofficial --- scripts/helpers/tiktok.js | 5 +++++ scripts/tiktok_downloadVideoNoWM.js | 9 +++------ 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 scripts/helpers/tiktok.js diff --git a/scripts/helpers/tiktok.js b/scripts/helpers/tiktok.js new file mode 100644 index 00000000..5b78d58a --- /dev/null +++ b/scripts/helpers/tiktok.js @@ -0,0 +1,5 @@ +// Source code from https://github.com/davidteather/TikTok-Api/blob/master/TikTokApi/browser_utilities/get_acrawler.py +// prettier-ignore +export function genXTTParams(e){ + var t=t||function(e,t){var r={},n=r.lib={},i=n.Base=function(){function e(){}return{extend:function(t){e.prototype=this;var r=new e;return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var e=this.extend();return e.init.apply(e,arguments),e},init:function(){},mixIn:function(e){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);e.hasOwnProperty("toString")&&(this.toString=e.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),c=n.WordArray=i.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length},toString:function(e){return(e||f).stringify(this)},concat:function(e){var t=this.words,r=e.words,n=this.sigBytes,i=e.sigBytes;if(this.clamp(),n%4)for(var c=0;c>>2]>>>24-c%4*8&255;t[n+c>>>2]|=o<<24-(n+c)%4*8}else if(r.length>65535)for(c=0;c>>2]=r[c>>>2];else t.push.apply(t,r);return this.sigBytes+=i,this},clamp:function(){var t=this.words,r=this.sigBytes;t[r>>>2]&=4294967295<<32-r%4*8,t.length=e.ceil(r/4)},clone:function(){var e=i.clone.call(this);return e.words=this.words.slice(0),e},random:function(t){for(var r,n=[],i=function(t){var r=987654321,n=4294967295;return function(){var i=((r=36969*(65535&r)+(r>>16)&n)<<16)+(t=18e3*(65535&t)+(t>>16)&n)&n;return i/=4294967296,(i+=.5)*(e.random()>.5?1:-1)}},o=0;o>>2]>>>24-i%4*8&255;n.push((c>>>4).toString(16)),n.push((15&c).toString(16))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n>>3]|=parseInt(e.substr(n,2),16)<<24-n%8*4;return new c.init(r,t/2)}},a=o.Latin1={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i>>2]>>>24-i%4*8&255;n.push(String.fromCharCode(c))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n>>2]|=(255&e.charCodeAt(n))<<24-n%4*8;return new c.init(r,t)}},s=o.Utf8={stringify:function(e){try{return decodeURIComponent(escape(a.stringify(e)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(e){return a.parse(unescape(encodeURIComponent(e)))}},d=n.BufferedBlockAlgorithm=i.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=s.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(t){var r=this._data,n=r.words,i=r.sigBytes,o=this.blockSize,f=i/(4*o),a=(f=t?e.ceil(f):e.max((0|f)-this._minBufferSize,0))*o,s=e.min(4*a,i);if(a){for(var d=0;d>>2]>>>24-c%4*8&255)<<16|(t[c+1>>>2]>>>24-(c+1)%4*8&255)<<8|t[c+2>>>2]>>>24-(c+2)%4*8&255,f=0;f<4&&c+.75*f>>6*(3-f)&63));var a=n.charAt(64);if(a)for(;i.length%4;)i.push(a);return i.join("")},parse:function(e){var t=e.length,n=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var c=0;c>>6-o%4*2;i[c>>>2]|=(f|a)<<24-c%4*8,c++}return r.create(i,c)}(e,t,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}(),t.lib.Cipher||function(e){var r=t,n=r.lib,i=n.Base,c=n.WordArray,o=n.BufferedBlockAlgorithm,f=r.enc,a=(f.Utf8,f.Base64),s=r.algo.EvpKDF,d=n.Cipher=o.extend({cfg:i.extend(),createEncryptor:function(e,t){return this.create(this._ENC_XFORM_MODE,e,t)},createDecryptor:function(e,t){return this.create(this._DEC_XFORM_MODE,e,t)},init:function(e,t,r){this.cfg=this.cfg.extend(r),this._xformMode=e,this._key=t,this.reset()},reset:function(){o.reset.call(this),this._doReset()},process:function(e){return this._append(e),this._process()},finalize:function(e){return e&&this._append(e),this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function e(e){return"string"==typeof e?g:b}return function(t){return{encrypt:function(r,n,i){return e(n).encrypt(t,r,n,i)},decrypt:function(r,n,i){return e(n).decrypt(t,r,n,i)}}}}()}),u=(n.StreamCipher=d.extend({_doFinalize:function(){return this._process(!0)},blockSize:1}),r.mode={}),l=n.BlockCipherMode=i.extend({createEncryptor:function(e,t){return this.Encryptor.create(e,t)},createDecryptor:function(e,t){return this.Decryptor.create(e,t)},init:function(e,t){this._cipher=e,this._iv=t}}),p=u.CBC=function(){var e=l.extend();function t(e,t,r){var n=this._iv;if(n){var i=n;this._iv=undefined}else i=this._prevBlock;for(var c=0;c>>2];e.sigBytes-=t}},y=(n.BlockCipher=d.extend({cfg:d.cfg.extend({mode:p,padding:h}),reset:function(){d.reset.call(this);var e=this.cfg,t=e.iv,r=e.mode;if(this._xformMode==this._ENC_XFORM_MODE)var n=r.createEncryptor;else n=r.createDecryptor,this._minBufferSize=1;this._mode&&this._mode.__creator==n?this._mode.init(this,t&&t.words):(this._mode=n.call(r,this,t&&t.words),this._mode.__creator=n)},_doProcessBlock:function(e,t){this._mode.processBlock(e,t)},_doFinalize:function(){var e=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){e.pad(this._data,this.blockSize);var t=this._process(!0)}else t=this._process(!0),e.unpad(t);return t},blockSize:4}),n.CipherParams=i.extend({init:function(e){this.mixIn(e)},toString:function(e){return(e||this.formatter).stringify(this)}})),v=(r.format={}).OpenSSL={stringify:function(e){var t=e.ciphertext,r=e.salt;if(r)var n=c.create([1398893684,1701076831]).concat(r).concat(t);else n=t;return n.toString(a)},parse:function(e){var t=a.parse(e),r=t.words;if(1398893684==r[0]&&1701076831==r[1]){var n=c.create(r.slice(2,4));r.splice(0,4),t.sigBytes-=16}return y.create({ciphertext:t,salt:n})}},b=n.SerializableCipher=i.extend({cfg:i.extend({format:v}),encrypt:function(e,t,r,n){n=this.cfg.extend(n);var i=e.createEncryptor(r,n),c=i.finalize(t),o=i.cfg;return y.create({ciphertext:c,key:r,iv:o.iv,algorithm:e,mode:o.mode,padding:o.padding,blockSize:e.blockSize,formatter:n.format})},decrypt:function(e,t,r,n){return n=this.cfg.extend(n),t=this._parse(t,n.format),e.createDecryptor(r,n).finalize(t.ciphertext)},_parse:function(e,t){return"string"==typeof e?t.parse(e,this):e}}),_=(r.kdf={}).OpenSSL={execute:function(e,t,r,n){n||(n=c.random(8));var i=s.create({keySize:t+r}).compute(e,n),o=c.create(i.words.slice(t),4*r);return i.sigBytes=4*t,y.create({key:i,iv:o,salt:n})}},g=n.PasswordBasedCipher=b.extend({cfg:b.cfg.extend({kdf:_}),encrypt:function(e,t,r,n){var i=(n=this.cfg.extend(n)).kdf.execute(r,e.keySize,e.ivSize);n.iv=i.iv;var c=b.encrypt.call(this,e,t,i.key,n);return c.mixIn(i),c},decrypt:function(e,t,r,n){n=this.cfg.extend(n),t=this._parse(t,n.format);var i=n.kdf.execute(r,e.keySize,e.ivSize,t.salt);return n.iv=i.iv,b.decrypt.call(this,e,t,i.key,n)}})}(),t.mode.ECB=function(){var e=t.lib.BlockCipherMode.extend();return e.Encryptor=e.extend({processBlock:function(e,t){this._cipher.encryptBlock(e,t)}}),e.Decryptor=e.extend({processBlock:function(e,t){this._cipher.decryptBlock(e,t)}}),e}(),function(){var e=t,r=e.lib.BlockCipher,n=e.algo,i=[],c=[],o=[],f=[],a=[],s=[],d=[],u=[],l=[],p=[];!function(){for(var e=[],t=0;t<256;t++)e[t]=t<128?t<<1:t<<1^283;var r=0,n=0;for(t=0;t<256;t++){var h=n^n<<1^n<<2^n<<3^n<<4;h=h>>>8^255&h^99,i[r]=h,c[h]=r;var y=e[r],v=e[y],b=e[v],_=257*e[h]^16843008*h;o[r]=_<<24|_>>>8,f[r]=_<<16|_>>>16,a[r]=_<<8|_>>>24,s[r]=_,_=16843009*b^65537*v^257*y^16843008*r,d[h]=_<<24|_>>>8,u[h]=_<<16|_>>>16,l[h]=_<<8|_>>>24,p[h]=_,r?(r=y^e[e[e[b^y]]],n^=e[e[n]]):r=n=1}}();var h=[0,1,2,4,8,16,32,64,128,27,54],y=n.AES=r.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var e=this._keyPriorReset=this._key,t=e.words,r=e.sigBytes/4,n=4*((this._nRounds=r+6)+1),c=this._keySchedule=[],o=0;o6&&o%r==4&&(f=i[f>>>24]<<24|i[f>>>16&255]<<16|i[f>>>8&255]<<8|i[255&f]):(f=i[(f=f<<8|f>>>24)>>>24]<<24|i[f>>>16&255]<<16|i[f>>>8&255]<<8|i[255&f],f^=h[o/r|0]<<24),c[o]=c[o-r]^f}for(var a=this._invKeySchedule=[],s=0;s>>24]]^u[i[f>>>16&255]]^l[i[f>>>8&255]]^p[i[255&f]]}},encryptBlock:function(e,t){this._doCryptBlock(e,t,this._keySchedule,o,f,a,s,i)},decryptBlock:function(e,t){var r=e[t+1];e[t+1]=e[t+3],e[t+3]=r,this._doCryptBlock(e,t,this._invKeySchedule,d,u,l,p,c),r=e[t+1],e[t+1]=e[t+3],e[t+3]=r},_doCryptBlock:function(e,t,r,n,i,c,o,f){for(var a=this._nRounds,s=e[t]^r[0],d=e[t+1]^r[1],u=e[t+2]^r[2],l=e[t+3]^r[3],p=4,h=1;h>>24]^i[d>>>16&255]^c[u>>>8&255]^o[255&l]^r[p++],v=n[d>>>24]^i[u>>>16&255]^c[l>>>8&255]^o[255&s]^r[p++],b=n[u>>>24]^i[l>>>16&255]^c[s>>>8&255]^o[255&d]^r[p++],_=n[l>>>24]^i[s>>>16&255]^c[d>>>8&255]^o[255&u]^r[p++];s=y,d=v,u=b,l=_}y=(f[s>>>24]<<24|f[d>>>16&255]<<16|f[u>>>8&255]<<8|f[255&l])^r[p++],v=(f[d>>>24]<<24|f[u>>>16&255]<<16|f[l>>>8&255]<<8|f[255&s])^r[p++],b=(f[u>>>24]<<24|f[l>>>16&255]<<16|f[s>>>8&255]<<8|f[255&d])^r[p++],_=(f[l>>>24]<<24|f[s>>>16&255]<<16|f[d>>>8&255]<<8|f[255&u])^r[p++],e[t]=y,e[t+1]=v,e[t+2]=b,e[t+3]=_},keySize:8});e.AES=r._createHelper(y)}();var r,n={};n.CryptoJS=t,window._$jsvmprt=function(e,t,r){function n(e,t,r){return(n=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}()?Reflect.construct:function(e,t,r){var n=[null];n.push.apply(n,t);var i=new(Function.bind.apply(e,n));return r&&function(e,t){(Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}(i,r.prototype),i}).apply(null,arguments)}function i(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t>7==0)return[1,i];if(i>>6==2){var c=parseInt(""+e[++t]+e[++t],16);return i&=63,[2,c=(i<<=8)+c]}if(i>>6==3){var o=parseInt(""+e[++t]+e[++t],16),f=parseInt(""+e[++t]+e[++t],16);return i&=63,[3,f=(i<<=16)+(o<<=8)+f]}},d=function(e,t){var r=parseInt(""+e[t]+e[t+1],16);return r>127?-256+r:r},u=function(e,t){var r=parseInt(""+e[t]+e[t+1]+e[t+2]+e[t+3],16);return r>32767?-65536+r:r},l=function(e,t){var r=parseInt(""+e[t]+e[t+1]+e[t+2]+e[t+3]+e[t+4]+e[t+5]+e[t+6]+e[t+7],16);return r>2147483647?0+r:r},p=function(e,t){return parseInt(""+e[t]+e[t+1],16)},h=function(e,t){return parseInt(""+e[t]+e[t+1]+e[t+2]+e[t+3],16)},y=y||this||window,v=(Object.keys,e.length,0),b="",_=v;_>=2,O>2)O=3&S,S>>=2,O<1?(O=S)<4?(g=x[B--],x[B]=x[B]-g):O<6?(g=x[B--],x[B]=x[B]===g):O<15&&(g=x[B],x[B]=x[B-1],x[B-1]=g):O<2?(O=S)<5&&(w=p(e,C),C+=2,g=l[w],x[++B]=g):O<3?(O=S)<6||(O<8?g=x[B--]:O<12&&(w=u(e,C),f[++a]=[[C+4,w-3],0,0],C+=2*w-2)):(O=S)<2?(g=x[B--],x[B]=x[B]1)if(O=3&S,S>>=2,O>2)(O=S)>5?(w=p(e,C),C+=2,x[++B]=l["$"+w]):O>3&&(w=u(e,C),f[a][0]&&!f[a][2]?f[a][1]=[C+4,w-3]:f[a++]=[0,[C+4,w-3],0],C+=2*w-2);else if(O>1){if((O=S)>2)if(x[B--])C+=4;else{if((w=u(e,C))<0){_=1,$(e,t,2*r),C+=2*w-2;break}C+=2*w-2}else if(O>0){for(w=h(e,C),g="",A=c.q[w][0];A0?(O=S)>1?(g=x[B--],x[B]=x[B]+g):O>-1&&(x[++B]=y):(O=S)>9?(w=p(e,C),C+=2,g=x[B--],l[w]=g):O>7?(w=h(e,C),C+=4,m=B+1,x[B-=w-1]=w?x.slice(B,m):[]):O>0&&(g=x[B--],x[B]=x[B]>g);else if(O>0){if(O=3&S,S>>=2,O<1){if((O=S)>9);else if(O>5)w=p(e,C),C+=2,x[B-=w]=0===w?new x[B]:n(x[B],i(x.slice(B+1,B+w+1)));else if(O>3){w=u(e,C);try{if(f[a][2]=1,1==(g=N(e,C+4,w-3,[],l,v,null,0))[0])return g}catch(b){if(f[a]&&f[a][1]&&1==(g=N(e,f[a][1][0],f[a][1][1],[],l,v,b,0))[0])return g}finally{if(f[a]&&f[a][0]&&1==(g=N(e,f[a][0][0],f[a][0][1],[],l,v,null,0))[0])return g;f[a]=0,a--}C+=2*w-2}}else if(O<2){if((O=S)>12)x[++B]=d(e,C),C+=2;else if(O>8){for(w=h(e,C),O="",A=c.q[w][0];A11?(g=x[B],x[++B]=g):O>0&&(x[++B]=g);else if((O=S)<1)x[B]=!x[B];else if(O<3){if((w=u(e,C))<0){_=1,$(e,t,2*r),C+=2*w-2;break}C+=2*w-2}}else if(O=3&S,S>>=2,O>2)(O=S)<1&&(x[++B]=null);else if(O>1){if((O=S)<9){for(g=x[B--],w=h(e,C),O="",A=c.q[w][0];A0)(O=S)<4?(m=x[B--],(O=x[B]).x===N?O.y>=1?x[B]=U(e,O.c,O.l,[m],O.z,k,null,1):(x[B]=U(e,O.c,O.l,[m],O.z,k,null,0),O.y++):x[B]=O(m)):O<6&&(x[B-=1]=x[B][x[B+1]]);else{if((O=S)<1)return[1,x[B--]];O<14?(m=x[B--],k=x[B--],(O=x[B--]).x===N?O.y>=1?x[++B]=U(e,O.c,O.l,m,O.z,k,null,1):(x[++B]=U(e,O.c,O.l,m,O.z,k,null,0),O.y++):x[++B]=O.apply(k,m)):O<16&&(w=u(e,C),(I=function t(){var r=arguments;return t.y>0||t.y++,U(e,t.c,t.l,r,t.z,this,null,0)}).c=C+4,I.l=w-2,I.x=N,I.y=0,I.z=l,x[B]=I,C+=2*w-2)}}if(_)for(;C>=2,O<1)if(O=3&S,S>>=2,O>2)(O=S)<1&&(x[++B]=null);else if(O>1){if((O=S)<9){for(g=x[B--],w=T[C],O="",A=c.q[w][0];A0)(O=S)<4?(m=x[B--],(O=x[B]).x===N?O.y>=1?x[B]=U(e,O.c,O.l,[m],O.z,k,null,1):(x[B]=U(e,O.c,O.l,[m],O.z,k,null,0),O.y++):x[B]=O(m)):O<6&&(x[B-=1]=x[B][x[B+1]]);else{var I;if((O=S)>14)w=T[C],(I=function t(){var r=arguments;return t.y>0||t.y++,U(e,t.c,t.l,r,t.z,this,null,0)}).c=C+4,I.l=w-2,I.x=N,I.y=0,I.z=l,x[B]=I,C+=2*w-2;else if(O>12)m=x[B--],k=x[B--],(O=x[B--]).x===N?O.y>=1?x[++B]=U(e,O.c,O.l,m,O.z,k,null,1):(x[++B]=U(e,O.c,O.l,m,O.z,k,null,0),O.y++):x[++B]=O.apply(k,m);else if(O>-1)return[1,x[B--]]}else if(O<2)if(O=3&S,S>>=2,O>2)(O=S)<1?x[B]=!x[B]:O<3&&(C+=2*(w=T[C])-2);else if(O>1)(O=S)<2?x[++B]=g:O<13&&(g=x[B],x[++B]=g);else if(O>0)if((O=S)<10){for(w=T[C],O="",A=c.q[w][0];A>=2,O<1)(O=S)>9?(w=T[C],C+=2,g=x[B--],l[w]=g):O>7?(w=T[C],C+=4,m=B+1,x[B-=w-1]=w?x.slice(B,m):[]):O>0&&(g=x[B--],x[B]=x[B]>g);else if(O<2)(O=S)>1?(g=x[B--],x[B]=x[B]+g):O>-1&&(x[++B]=y);else if(O<3)if((O=S)<2){for(w=T[C],g="",A=c.q[w][0];A5?(w=T[C],C+=2,x[++B]=l["$"+w]):O>3&&(w=T[C],f[a][0]&&!f[a][2]?f[a][1]=[C+4,w-3]:f[a++]=[0,[C+4,w-3],0],C+=2*w-2);else O=3&S,S>>=2,O<1?(O=S)<4?(g=x[B--],x[B]=x[B]-g):O<6?(g=x[B--],x[B]=x[B]===g):O<15&&(g=x[B],x[B]=x[B-1],x[B-1]=g):O<2?(O=S)<5&&(w=T[C],C+=2,g=l[w],x[++B]=g):O<3?(O=S)>10?(w=T[C],f[++a]=[[C+4,w-3],0,0],C+=2*w-2):O>6&&(g=x[B--]):(O=S)<2?(g=x[B--],x[B]=x[B] 19 - ? idVideo.substring(0, idVideo.indexOf("?")) - : idVideo; + if (url.includes("@") && url.includes("/video/")) + return url.split("/video/")[1].split("?")[0]; + throw Error("URL video tiktok không đúng địng dạng"); }, getVideoNoWaterMark: async function (video_url, isVideoId = false) { From 50be00b542b12fc54edb1c8c5f10bb807b96d7e2 Mon Sep 17 00:00:00 2001 From: "hoang.tran12" Date: Tue, 6 Dec 2022 13:48:03 +0700 Subject: [PATCH 023/164] . --- scripts/ggdrive_downloadVideo.js | 2 ++ scripts/tiktok_downloadUserVideos.js | 13 +++++++++++-- scripts/tiktok_downloadVideoNoWM.js | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/ggdrive_downloadVideo.js b/scripts/ggdrive_downloadVideo.js index 94a75e6d..c4964b12 100644 --- a/scripts/ggdrive_downloadVideo.js +++ b/scripts/ggdrive_downloadVideo.js @@ -119,3 +119,5 @@ export default { } }, }; + +export const shared = {}; diff --git a/scripts/tiktok_downloadUserVideos.js b/scripts/tiktok_downloadUserVideos.js index 3c19107e..1998d036 100644 --- a/scripts/tiktok_downloadUserVideos.js +++ b/scripts/tiktok_downloadUserVideos.js @@ -51,7 +51,14 @@ export default { }); console.log(urls); - alert("Tìm thấy " + urls.length + " video. Bấm ok để tiếp tục."); + if ( + !confirm( + "Tìm thấy " + + urls.length + + " video.\nBấm OK để tiếp tục tải.\nBâm Cancel để huỷ tải." + ) + ) + return; let videoUrls = []; let errorCount = 0; @@ -82,7 +89,7 @@ export default { console.log(videoUrls); if (videoUrls.length) downloadData(videoUrls.join("\n"), "tiktok-user-videos", ".txt"); - else alert("Không tìm được video nào"); + else throw "Không tìm được video nào"; } catch (e) { alert("ERROR: " + e); } finally { @@ -92,6 +99,8 @@ export default { }; async function backup() { + // MUST READ: https://github.com/davidteather/TikTok-Api + // =================== Tải về mọi video trong user tiktok (có watermark) =================== let containers = Array.from( document.querySelectorAll(".tiktok-x6y88p-DivItemContainerV2.e19c29qe7") diff --git a/scripts/tiktok_downloadVideoNoWM.js b/scripts/tiktok_downloadVideoNoWM.js index 4d4456c1..822a9a7d 100644 --- a/scripts/tiktok_downloadVideoNoWM.js +++ b/scripts/tiktok_downloadVideoNoWM.js @@ -17,8 +17,8 @@ export default { "Nhập link tiktok video: ", await runScriptInCurrentTab(() => location.href) ); - if (url == null) return; + let { closeLoading } = showLoading( "Đang lấy link video không watermark..." ); From 6642f46498358f7f0229dd6c40a7e1792950a57e Mon Sep 17 00:00:00 2001 From: "hoang.tran12" Date: Tue, 6 Dec 2022 18:28:24 +0700 Subject: [PATCH 024/164] ggdrive download video --- popup/tabs.js | 2 + scripts/ggDrive_downloadAllVideosInFolder.js | 68 ++++++++++ scripts/ggdrive_downloadVideo.js | 131 ++++++++++--------- scripts/index.js | 5 + 4 files changed, 141 insertions(+), 65 deletions(-) create mode 100644 scripts/ggDrive_downloadAllVideosInFolder.js diff --git a/popup/tabs.js b/popup/tabs.js index 8f0d8fa6..b6287a81 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -78,6 +78,8 @@ const tabs = [ createTitle("--- Download ---", "--- Tải xuống ---"), s.ggdrive_downloadVideo, s.google_downloadAllYourData, + createTitle("--- Bulk Download ---", "--- Tải hàng loạt ---"), + s.ggDrive_downloadAllVideosInFolder, createTitle("--- More ---", "--- Khác ---"), s.search_totalIndexedPages, s.search_googleSite, diff --git a/scripts/ggDrive_downloadAllVideosInFolder.js b/scripts/ggDrive_downloadAllVideosInFolder.js new file mode 100644 index 00000000..7786cd3f --- /dev/null +++ b/scripts/ggDrive_downloadAllVideosInFolder.js @@ -0,0 +1,68 @@ +import { runScriptInCurrentTab, showLoading } from "./helpers/utils.js"; +import { shared as ggdrive_downloadVideo } from "./ggdrive_downloadVideo.js"; + +export default { + icon: "https://drive.google.com/favicon.ico", + name: { + en: "GGDrive - Download all videos in folder", + vi: "GGDrive - Tải mọi video trong folder", + }, + description: { + en: "Download all videos in folder of google drive (bypass download permission)", + vi: "Tải tất cả video trong thư mục google drive (tải được video không cho phép tải)", + }, + blackList: [], + whiteList: [], + runInExtensionContext: true, + + func: async function () { + // Post: https://www.facebook.com/groups/j2team.community/posts/974953859503401/ + + let { closeLoading, setLoadingText } = showLoading( + "Đang tìm tất cả video trong folder..." + ); + let allDocIds = await runScriptInCurrentTab(() => + Array.from(document.querySelectorAll(".iZmuQc .WYuW0e")).map( + (_) => _.dataset.id + ) + ); + if (!allDocIds?.length) { + alert("Không tìm được video nào."); + return; + } + + let errors = []; + let result = []; + for (let i = 0; i < allDocIds.length; i++) { + let docId = allDocIds[i]; + setLoadingText( + `Tìm thấy ${allDocIds.length} videos.
` + + `Đang tìm link video ${i + 1}...
${docId}

` + + `Lỗi: ${errors.length} video
` + + errors.map(({ id, e }) => id).join("
") + ); + try { + let videoInfo = await ggdrive_downloadVideo.getLinkVideoGDriveFromDocId( + docId + ); + result.push(videoInfo); + } catch (e) { + errors.push({ id: docId, e }); + } + } + closeLoading(); + + let html = ` + + + + + + +
#TitleVideos
+ `; + console.log(result); + }, +}; + +export const shared = {}; diff --git a/scripts/ggdrive_downloadVideo.js b/scripts/ggdrive_downloadVideo.js index c4964b12..0fefb549 100644 --- a/scripts/ggdrive_downloadVideo.js +++ b/scripts/ggdrive_downloadVideo.js @@ -20,81 +20,20 @@ export default { runInExtensionContext: true, func: async function () { - // Post: https://www.facebook.com/groups/j2team.community/posts/974953859503401/ - - async function getLinkVideoGDrive(docid) { - function parse(e) { - var result = {}; - return ( - e.split("&").forEach(function (e) { - result[decodeURIComponent(e.substring(0, e.indexOf("=")))] = - decodeURIComponent(e.substring(e.indexOf("=") + 1)); - }), - result - ); - } - - function parseStream(e) { - var d = []; - return ( - e.split(",").forEach(function (e) { - d.push(parse(e)); - }), - d - ); - } - - async function getVideoLinkFromDocId(docid) { - let res = await fetch( - "https://drive.google.com/get_video_info?docid=" + docid - ); - - let text = await res.text(); - let json = parse(text); - - json.url_encoded_fmt_stream_map = parseStream( - json.url_encoded_fmt_stream_map - ); - - let result = json.url_encoded_fmt_stream_map.map(function (stream) { - let name = json.title.replace(/\+/g, " "); - return { - idfile: docid, - name: name, - quality: stream.quality, - url: stream.url, - }; - }); - - console.log(result); - return result; - } - - // let { id, title } = window?.viewerData?.config; - return await getVideoLinkFromDocId(docid); - } - - // https://stackoverflow.com/a/16840612 - function getIdFromUrl(url) { - return url.match(/[-\w]{25,}(?!.*[-\w]{25,})/); - } - let { closeLoading } = showLoading("Đang tìm link video..."); try { - let docid = await runScriptInCurrentTab(() => { - return window?.viewerData?.config?.id; - }); + let docid = await shared.getDocIdFromWebsite(); if (!docid) { let tab = await getCurrentTab(); let url = prompt("Nhập link google drive video: ", tab.url); if (url == null) return; - docid = getIdFromUrl(url); + docid = shared.getDocIdFromUrl(url); if (!docid) throw Error("Link không hợp lệ. Không tìm thấy id trong link."); } - let res = await getLinkVideoGDrive(docid); + let res = await shared.getLinkVideoGDriveFromDocId(docid); if (!res?.length) throw Error("Không tìm được link video."); console.log(res); @@ -120,4 +59,66 @@ export default { }, }; -export const shared = {}; +export const shared = { + // https://stackoverflow.com/a/16840612 + getDocIdFromUrl(url) { + return url.match(/[-\w]{25,}(?!.*[-\w]{25,})/); + }, + + async getDocIdFromWebsite() { + return await runScriptInCurrentTab(() => { + return window?.viewerData?.config?.id; + }); + }, + + // Post: https://www.facebook.com/groups/j2team.community/posts/974953859503401/ + async getLinkVideoGDriveFromDocId(docid) { + function parse(e) { + var result = {}; + return ( + e.split("&").forEach(function (e) { + result[decodeURIComponent(e.substring(0, e.indexOf("=")))] = + decodeURIComponent(e.substring(e.indexOf("=") + 1)); + }), + result + ); + } + + function parseStream(e) { + var d = []; + return ( + e.split(",").forEach(function (e) { + d.push(parse(e)); + }), + d + ); + } + + async function getLink(docid) { + let res = await fetch( + "https://drive.google.com/get_video_info?docid=" + docid + ); + + let text = await res.text(); + let json = parse(text); + + json.url_encoded_fmt_stream_map = parseStream( + json.url_encoded_fmt_stream_map + ); + + let result = json.url_encoded_fmt_stream_map.map(function (stream) { + let name = json.title.replace(/\+/g, " "); + return { + idfile: docid, + name: name, + quality: stream.quality, + url: stream.url, + }; + }); + + return result; + } + + return await getLink(docid); + }, +}; diff --git a/scripts/index.js b/scripts/index.js index 67d9e4c0..ea0d64da 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -132,6 +132,7 @@ import google_downloadAllYourData from "./google_downloadAllYourData.js"; import tiktok_downloadWatchingVideo from "./tiktok_downloadWatchingVideo.js"; import tiktok_downloadUserVideos from "./tiktok_downloadUserVideos.js"; import tiktok_downloadVideoNoWM from "./tiktok_downloadVideoNoWM.js"; +import ggDrive_downloadAllVideosInFolder from "./ggDrive_downloadAllVideosInFolder.js"; // inject badges const allScripts = { @@ -282,6 +283,10 @@ const allScripts = { ), tiktok_downloadUserVideos: addBadge(tiktok_downloadUserVideos, BADGES.beta), tiktok_downloadVideoNoWM: addBadge(tiktok_downloadVideoNoWM, BADGES.new), + ggDrive_downloadAllVideosInFolder: addBadge( + ggDrive_downloadAllVideosInFolder, + BADGES.new + ), }; // inject id to all scripts From 0babdd592da16fde91a6245965bb00a57b0f571d Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Wed, 7 Dec 2022 03:13:54 +0700 Subject: [PATCH 025/164] download video fb, best --- .../generated_indexed_rulesets/_ruleset1 | Bin 851 -> 1011 bytes popup/tabs.js | 1 + scripts/_test.js | 51 +++- scripts/fb_downloadCommentVideo.js | 16 +- scripts/fb_downloadWatchingVideo.js | 80 +++++++ scripts/fb_videoDownloader.js | 158 +++++++++---- scripts/getAllEmailsInWeb.js | 16 +- scripts/ggdrive_downloadVideo.js | 6 +- scripts/helpers/xmlParser.js | 218 ++++++++++++++++++ scripts/index.js | 2 + scripts/net-request-rules/rules.json | 26 +++ scripts/tiktok_downloadVideoNoWM.js | 2 +- 12 files changed, 512 insertions(+), 64 deletions(-) create mode 100644 scripts/fb_downloadWatchingVideo.js create mode 100644 scripts/helpers/xmlParser.js diff --git a/_metadata/generated_indexed_rulesets/_ruleset1 b/_metadata/generated_indexed_rulesets/_ruleset1 index ef7e0b4031304c51b15e274b25f0975871cb9f51..c9a3b2271ff3b6ad2f1fe35918121299bc23fe23 100644 GIT binary patch delta 396 zcmYk2y-EX75QWd`nkF7AabS367Xd<1(NOA8-B zuoWwd^kOHj-^3em;JfF}%+B1yzSchL<>Dl^1{e8JdcL-_GB0U;ySs@HvuY|-qy{%B zhRB0x8lI=5$3R*J%SUhrA+)Qinn9az30AYP9T}9T92>9zJ=g_ncHxEL2HMFp=TP?R zn`7kbRv!BL2PPt(iN#0@~q0>mEw|NmzN(gHx70TlyMVEqw5Is}LVfY{3fNO%CT3lM`0 zw*lf8K+QZr+N!vqqy$I<&1Xmf5*$F|IKU2K06K|*0VEAF93=0;H1XxM&Hov{FaiKZ Cl^(GG diff --git a/popup/tabs.js b/popup/tabs.js index b6287a81..a79508bc 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -96,6 +96,7 @@ const tabs = [ createTitle("--- Download ---", "--- Tải xuống ---"), s.fb_storySaver, s.fb_videoDownloader, + s.fb_downloadWatchingVideo, s.fb_downloadCommentVideo, s.fb_getAvatarFromUid, s.fb_storyInfo, diff --git a/scripts/_test.js b/scripts/_test.js index aa3ce19e..6d061087 100644 --- a/scripts/_test.js +++ b/scripts/_test.js @@ -11,14 +11,51 @@ export default { en: "", vi: "", }, - runInExtensionContext: true, + runInExtensionContext: false, func: async function () { - // let dtsg = await runScriptInCurrentTab(() => { - // return require("DTSGInitialData").token; - // }); - // alert(dtsg); - await runScriptInCurrentTab(scrollToVeryEnd.func); - alert("xong"); + function stringifyVariables(d, e) { + let f = [], + a; + for (a in d) + if (d.hasOwnProperty(a)) { + let g = e ? e + "[" + a + "]" : a, + b = d[a]; + f.push( + null !== b && "object" == typeof b + ? stringifyVariables(b, g) + : encodeURIComponent(g) + "=" + encodeURIComponent(b) + ); + } + return f.join("&"); + } + function fetchGraphQl(body) { + return fetch("https://www.facebook.com/api/graphql/", { + method: "POST", + headers: { + "content-type": "application/x-www-form-urlencoded", + }, + body: body, + }); + } + + // get video from group? + // let res = await fetchGraphQl( + // stringifyVariables({ + // doc_id: "3972944316164299", + // variables: JSON.stringify({ + // groupID: 364997627165697, + // count: 8, + // useCometPhotoViewerPlaceholderFrag: !0, + // scale: 1.5, + // }), + // fb_dtsg: require("DTSGInitialData").token, + // fb_api_caller_class: "RelayModern", + // fb_api_req_friendly_name: "GroupsCometMediaVideosTabGridQuery", + // }) + // ); + // let text = await res.json(); + + // console.log(text); }, }; diff --git a/scripts/fb_downloadCommentVideo.js b/scripts/fb_downloadCommentVideo.js index a8a19a7c..8220ba73 100644 --- a/scripts/fb_downloadCommentVideo.js +++ b/scripts/fb_downloadCommentVideo.js @@ -1,7 +1,7 @@ import fb_storySaver from "./fb_storySaver.js"; export default { - icon: "https://www.facebook.com/favicon.ico", + icon: '', name: { en: "Download facebook comment video", vi: "Tải video trong comment facebook", @@ -15,3 +15,17 @@ export default { func: fb_storySaver.func, }; + +async function backup() { + // DYL extension: Get video from comment id (quality: SD) + let commendId = "2009814422684001"; + let access_token = "..."; + let res = await fetch( + "https://graph.facebook.com/v8.0/" + + commendId + + "?fields=attachment&access_token=" + + access_token + ); + let json = await res.json(); + return json.attachment.media.source; +} diff --git a/scripts/fb_downloadWatchingVideo.js b/scripts/fb_downloadWatchingVideo.js new file mode 100644 index 00000000..798e5f66 --- /dev/null +++ b/scripts/fb_downloadWatchingVideo.js @@ -0,0 +1,80 @@ +import { runScriptInCurrentTab } from "./helpers/utils.js"; +import { parseXml, xml2json } from "./helpers/xmlParser.js"; + +export default { + icon: '', + name: { + en: "Facebook - Download watching video", + vi: "Facebook - Tải video đang xem", + }, + description: { + en: "", + vi: "", + }, + blackList: [], + whiteList: ["https://www.facebook.com/*"], + runInExtensionContext: true, + + func: async function () { + let listXml = await runScriptInCurrentTab(() => { + // https://stackoverflow.com/a/7557433 + function isElementInViewport(el) { + var rect = el.getBoundingClientRect(); + return !( + rect.bottom < 0 || + rect.top > + (window.innerHeight || document.documentElement.clientHeight) + ); + } + + let allVideos = Array.from(document.querySelectorAll("video")); + let result = []; + for (let video of allVideos) { + try { + let key = ""; + for (let k in video.parentElement) { + if (k.startsWith("__reactProps")) { + key = k; + break; + } + } + result.push({ + inViewPort: isElementInViewport(video), + xml: video.parentElement[key].children.props.manifest, + }); + console.log(video, isElementInViewport(video)); + } catch (e) { + console.log("ERROR on get video manifest: ", e); + } + } + + return result; + }); + + let urls = listXml + .map(({ inViewPort, xml }) => { + try { + let json = JSON.parse( + xml2json(parseXml(xml)).replace("undefined", "") + ); + let urls = json.MPD.Period.AdaptationSet[0].Representation.map( + (_) => ({ + quality: _["@FBQualityLabel"], + url: _.BaseURL.replaceAll("&", "&"), + }) + ); + return { + inViewPort, + urls, + }; + } catch (e) { + return null; + } + }) + .filter((_) => _); + + console.log(urls); + }, +}; + +export const shared = {}; diff --git a/scripts/fb_videoDownloader.js b/scripts/fb_videoDownloader.js index 3075fc6f..9058d3cc 100644 --- a/scripts/fb_videoDownloader.js +++ b/scripts/fb_videoDownloader.js @@ -1,3 +1,9 @@ +import { + getCurrentTab, + runScriptInCurrentTab, + showLoading, +} from "./helpers/utils.js"; + export default { icon: "https://www.facebook.com/favicon.ico", name: { @@ -10,49 +16,81 @@ export default { }, blackList: [], whiteList: ["https://www.facebook.com/*"], - runInExtensionContext: false, + runInExtensionContext: true, - func: function () { - // Original source code: https://gist.github.com/monokaijs/270e29620c46cabec1caca8c3746729d + func: async function () { + let tab = await getCurrentTab(); + let url = prompt("Nhập link video/reel/watch:", tab.url); + let videoId = shared.extractFbVideoIdFromUrl(url); + if (!videoId) { + alert( + "Link không đúng định dạng, không tìm thấy video/reel/watch id trong link." + ); + return; + } - function stringifyVariables(d, e) { - let f = [], - a; - for (a in d) - if (d.hasOwnProperty(a)) { - let g = e ? e + "[" + a + "]" : a, - b = d[a]; - f.push( - null !== b && "object" == typeof b - ? stringifyVariables(b, g) - : encodeURIComponent(g) + "=" + encodeURIComponent(b) - ); - } - return f.join("&"); + let { closeLoading, setLoadingText } = showLoading("Đang lấy token..."); + try { + let dtsg = await shared.getDtsg(); + setLoadingText("Đang get link video..."); + let link = + (await shared.getLinkFbVideo2(videoId, dtsg)) || + (await shared.getLinkFbVideo(videoId, dtsg)); + if (link) window.open(link); + else throw Error("Không tìm thấy link"); + } catch (e) { + alert("ERROR: " + e); + } finally { + closeLoading(); } + }, +}; + +export const shared = { + extractFbVideoIdFromUrl: function (url) { + return url.match(/\/(?:videos|reel|watch)(?:\/?)(?:\?v=)?(\d+)/)?.[1]; + }, + + getDtsg: async function () { + return await runScriptInCurrentTab(() => { + return require("DTSGInitialData").token; + }); + }, + + // Original source code: https://gist.github.com/monokaijs/270e29620c46cabec1caca8c3746729d + // Cần thêm rule trong rule.jsons để hàm này có thể chạy trong extension context + stringifyVariables: function (d, e) { + let f = [], + a; + for (a in d) + if (d.hasOwnProperty(a)) { + let g = e ? e + "[" + a + "]" : a, + b = d[a]; + f.push( + null !== b && "object" == typeof b + ? stringifyVariables(b, g) + : encodeURIComponent(g) + "=" + encodeURIComponent(b) + ); + } + return f.join("&"); + }, + getLinkFbVideo: async function (videoId, dtsg) { function fetchGraphQl(doc_id, variables) { return fetch("https://www.facebook.com/api/graphql/", { method: "POST", - headers: { "content-type": "application/x-www-form-urlencoded" }, - body: stringifyVariables({ + headers: { + "content-type": "application/x-www-form-urlencoded", + }, + body: shared.stringifyVariables({ doc_id: doc_id, variables: JSON.stringify(variables), - fb_dtsg: require("DTSGInitialData").token, + fb_dtsg: dtsg, server_timestamps: !0, }), }); } - let url = prompt("Nhập link video/reel/watch:", location.href); - let videoId = url.match(/\/(?:videos|reel|watch)(?:\/?)(?:\?v=)?(\d+)/); - if (!videoId || videoId.length < 2) { - alert( - "Link không đúng định dạng, không tìm thấy video/reel/watch id trong link." - ); - return; - } - - fetchGraphQl("5279476072161634", { + let res = await fetchGraphQl("5279476072161634", { UFI2CommentsProvider_commentsKey: "CometTahoeSidePaneQuery", caller: "CHANNEL_VIEW_FROM_PAGE_TIMELINE", displayCommentsContextEnableComment: null, @@ -69,22 +107,50 @@ export default { streamChainingSection: !1, useDefaultActor: !1, videoChainingContext: null, - videoID: videoId[1], - }) - .then((res) => res.text()) - .then((text) => { - let a = JSON.parse(text.split("\n")[0]), - link = - a.data.video.playable_url_quality_hd || a.data.video.playable_url; + videoID: videoId, + }); + let text = await res.text(); - if (link) { - window.open(link); - } else { - throw Error("Không tìm thấy link"); - } - }) - .catch((e) => { - alert("Lỗi: " + e); - }); + let a = JSON.parse(text.split("\n")[0]), + link = a.data.video.playable_url_quality_hd || a.data.video.playable_url; + + return link; + }, + + // DYL extension: faster + getLinkFbVideo2: async function (videoId, dtsg) { + let res = await fetch( + "https://www.facebook.com/video/video_data_async/?video_id=" + videoId, + { + method: "POST", + headers: { "content-type": "application/x-www-form-urlencoded" }, + body: shared.stringifyVariables({ + __a: "1", + fb_dtsg: dtsg, + }), + } + ); + + let text = await res.text(); + console.log(text); + text = text.replace("for (;;);", ""); + let json = JSON.parse(text); + + const { hd_src, hd_src_no_ratelimit, sd_src, sd_src_no_ratelimit } = + json?.payload || {}; + + return hd_src_no_ratelimit || hd_src || sd_src_no_ratelimit || sd_src; + }, + + // DYL extension: use access token + getLinkFbVideo3: async function (videoId, access_token) { + let res = await fetch( + "https://graph.facebook.com/v8.0/" + + videoId + + "?fields=source&access_token=" + + access_token + ); + let json = await res.json(); + return json.source; }, }; diff --git a/scripts/getAllEmailsInWeb.js b/scripts/getAllEmailsInWeb.js index 6cae93cf..c9e73d67 100644 --- a/scripts/getAllEmailsInWeb.js +++ b/scripts/getAllEmailsInWeb.js @@ -14,14 +14,18 @@ export default { func: function () { // source code from: https://bookmarklet.vercel.app/ - var StrObj = document.body.innerHTML; - var haystack = StrObj.toString(); - var regex = + let StrObj = document.body.innerHTML; + let haystack = StrObj.toString(); + let regex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/g; - var found = haystack.match(regex); + let found = haystack.match(regex); if (found !== null && found !== "") { - mailz = found.join("\r\n
"); - w = window.open("", "mailz", "scrollbars,resizable,width=400,height=600"); + let mailz = found.join("\r\n
"); + let w = window.open( + "", + "mailz", + "scrollbars,resizable,width=400,height=600" + ); w.document.write(mailz); } else { alert("No emails found on page"); diff --git a/scripts/ggdrive_downloadVideo.js b/scripts/ggdrive_downloadVideo.js index 0fefb549..656f3c5a 100644 --- a/scripts/ggdrive_downloadVideo.js +++ b/scripts/ggdrive_downloadVideo.js @@ -61,18 +61,18 @@ export default { export const shared = { // https://stackoverflow.com/a/16840612 - getDocIdFromUrl(url) { + getDocIdFromUrl: function (url) { return url.match(/[-\w]{25,}(?!.*[-\w]{25,})/); }, - async getDocIdFromWebsite() { + getDocIdFromWebsite: async function () { return await runScriptInCurrentTab(() => { return window?.viewerData?.config?.id; }); }, // Post: https://www.facebook.com/groups/j2team.community/posts/974953859503401/ - async getLinkVideoGDriveFromDocId(docid) { + getLinkVideoGDriveFromDocId: async function (docid) { function parse(e) { var result = {}; return ( diff --git a/scripts/helpers/xmlParser.js b/scripts/helpers/xmlParser.js new file mode 100644 index 00000000..fbea7fd5 --- /dev/null +++ b/scripts/helpers/xmlParser.js @@ -0,0 +1,218 @@ +// https://stackoverflow.com/a/1773571 + +export function parseXml(xml) { + var dom = null; + if (window.DOMParser) { + try { + dom = new DOMParser().parseFromString(xml, "text/xml"); + } catch (e) { + dom = null; + } + } else if (window.ActiveXObject) { + try { + dom = new ActiveXObject("Microsoft.XMLDOM"); + dom.async = false; + if (!dom.loadXML(xml)) + // parse error .. + + window.alert(dom.parseError.reason + dom.parseError.srcText); + } catch (e) { + dom = null; + } + } else alert("cannot parse xml string!"); + return dom; +} + +export function xml2json(xml, tab) { + var X = { + toObj: function (xml) { + var o = {}; + if (xml.nodeType == 1) { + // element node .. + if (xml.attributes.length) + // element with attributes .. + for (var i = 0; i < xml.attributes.length; i++) + o["@" + xml.attributes[i].nodeName] = ( + xml.attributes[i].nodeValue || "" + ).toString(); + if (xml.firstChild) { + // element has child nodes .. + var textChild = 0, + cdataChild = 0, + hasElementChild = false; + for (var n = xml.firstChild; n; n = n.nextSibling) { + if (n.nodeType == 1) hasElementChild = true; + else if (n.nodeType == 3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) + textChild++; // non-whitespace text + else if (n.nodeType == 4) cdataChild++; // cdata section node + } + if (hasElementChild) { + if (textChild < 2 && cdataChild < 2) { + // structured element with evtl. a single text or/and cdata node .. + X.removeWhite(xml); + for (var n = xml.firstChild; n; n = n.nextSibling) { + if (n.nodeType == 3) + // text node + o["#text"] = X.escape(n.nodeValue); + else if (n.nodeType == 4) + // cdata node + o["#cdata"] = X.escape(n.nodeValue); + else if (o[n.nodeName]) { + // multiple occurence of element .. + if (o[n.nodeName] instanceof Array) + o[n.nodeName][o[n.nodeName].length] = X.toObj(n); + else o[n.nodeName] = [o[n.nodeName], X.toObj(n)]; + } // first occurence of element.. + else o[n.nodeName] = X.toObj(n); + } + } else { + // mixed content + if (!xml.attributes.length) o = X.escape(X.innerXml(xml)); + else o["#text"] = X.escape(X.innerXml(xml)); + } + } else if (textChild) { + // pure text + if (!xml.attributes.length) o = X.escape(X.innerXml(xml)); + else o["#text"] = X.escape(X.innerXml(xml)); + } else if (cdataChild) { + // cdata + if (cdataChild > 1) o = X.escape(X.innerXml(xml)); + else + for (var n = xml.firstChild; n; n = n.nextSibling) + o["#cdata"] = X.escape(n.nodeValue); + } + } + if (!xml.attributes.length && !xml.firstChild) o = null; + } else if (xml.nodeType == 9) { + // document.node + o = X.toObj(xml.documentElement); + } else alert("unhandled node type: " + xml.nodeType); + return o; + }, + toJson: function (o, name, ind) { + var json = name ? '"' + name + '"' : ""; + if (o instanceof Array) { + for (var i = 0, n = o.length; i < n; i++) + o[i] = X.toJson(o[i], "", ind + "\t"); + json += + (name ? ":[" : "[") + + (o.length > 1 + ? "\n" + ind + "\t" + o.join(",\n" + ind + "\t") + "\n" + ind + : o.join("")) + + "]"; + } else if (o == null) json += (name && ":") + "null"; + else if (typeof o == "object") { + var arr = []; + for (var m in o) arr[arr.length] = X.toJson(o[m], m, ind + "\t"); + json += + (name ? ":{" : "{") + + (arr.length > 1 + ? "\n" + ind + "\t" + arr.join(",\n" + ind + "\t") + "\n" + ind + : arr.join("")) + + "}"; + } else if (typeof o == "string") + json += (name && ":") + '"' + o.toString() + '"'; + else json += (name && ":") + o.toString(); + return json; + }, + innerXml: function (node) { + var s = ""; + if ("innerHTML" in node) s = node.innerHTML; + else { + var asXml = function (n) { + var s = ""; + if (n.nodeType == 1) { + s += "<" + n.nodeName; + for (var i = 0; i < n.attributes.length; i++) + s += + " " + + n.attributes[i].nodeName + + '="' + + (n.attributes[i].nodeValue || "").toString() + + '"'; + if (n.firstChild) { + s += ">"; + for (var c = n.firstChild; c; c = c.nextSibling) s += asXml(c); + s += ""; + } else s += "/>"; + } else if (n.nodeType == 3) s += n.nodeValue; + else if (n.nodeType == 4) s += ""; + return s; + }; + for (var c = node.firstChild; c; c = c.nextSibling) s += asXml(c); + } + return s; + }, + escape: function (txt) { + return txt + .replace(/[\\]/g, "\\\\") + .replace(/[\"]/g, '\\"') + .replace(/[\n]/g, "\\n") + .replace(/[\r]/g, "\\r"); + }, + removeWhite: function (e) { + e.normalize(); + for (var n = e.firstChild; n; ) { + if (n.nodeType == 3) { + // text node + if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { + // pure whitespace text node + var nxt = n.nextSibling; + e.removeChild(n); + n = nxt; + } else n = n.nextSibling; + } else if (n.nodeType == 1) { + // element node + X.removeWhite(n); + n = n.nextSibling; + } // any other node + else n = n.nextSibling; + } + return e; + }, + }; + if (xml.nodeType == 9) + // document node + xml = xml.documentElement; + var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t"); + return ( + "{\n" + + tab + + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + + "\n}" + ); +} + +export function json2xml(o, tab) { + var toXml = function (v, name, ind) { + var xml = ""; + if (v instanceof Array) { + for (var i = 0, n = v.length; i < n; i++) + xml += ind + toXml(v[i], name, ind + "\t") + "\n"; + } else if (typeof v == "object") { + var hasChild = false; + xml += ind + "<" + name; + for (var m in v) { + if (m.charAt(0) == "@") + xml += " " + m.substr(1) + '="' + v[m].toString() + '"'; + else hasChild = true; + } + xml += hasChild ? ">" : "/>"; + if (hasChild) { + for (var m in v) { + if (m == "#text") xml += v[m]; + else if (m == "#cdata") xml += ""; + else if (m.charAt(0) != "@") xml += toXml(v[m], m, ind + "\t"); + } + xml += + (xml.charAt(xml.length - 1) == "\n" ? ind : "") + ""; + } + } else { + xml += ind + "<" + name + ">" + v.toString() + ""; + } + return xml; + }, + xml = ""; + for (var m in o) xml += toXml(o[m], m, ""); + return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, ""); +} diff --git a/scripts/index.js b/scripts/index.js index ea0d64da..439de4ee 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -133,6 +133,7 @@ import tiktok_downloadWatchingVideo from "./tiktok_downloadWatchingVideo.js"; import tiktok_downloadUserVideos from "./tiktok_downloadUserVideos.js"; import tiktok_downloadVideoNoWM from "./tiktok_downloadVideoNoWM.js"; import ggDrive_downloadAllVideosInFolder from "./ggDrive_downloadAllVideosInFolder.js"; +import fb_downloadWatchingVideo from "./fb_downloadWatchingVideo.js"; // inject badges const allScripts = { @@ -287,6 +288,7 @@ const allScripts = { ggDrive_downloadAllVideosInFolder, BADGES.new ), + fb_downloadWatchingVideo: addBadge(fb_downloadWatchingVideo, BADGES.new), }; // inject id to all scripts diff --git a/scripts/net-request-rules/rules.json b/scripts/net-request-rules/rules.json index 310e8011..965e4251 100644 --- a/scripts/net-request-rules/rules.json +++ b/scripts/net-request-rules/rules.json @@ -50,5 +50,31 @@ "xmlhttprequest" ] } + }, + { + "id": 3, + "priority": 1, + "action": { + "type": "modifyHeaders", + "requestHeaders": [ + { + "header": "referer", + "operation": "set", + "value": "https://www.facebook.com" + }, + { + "header": "origin", + "operation": "set", + "value": "https://www.facebook.com" + } + ] + }, + "condition": { + "domain": "extension://*", + "urlFilter": "https://www.facebook.com", + "resourceTypes": [ + "xmlhttprequest" + ] + } } ] \ No newline at end of file diff --git a/scripts/tiktok_downloadVideoNoWM.js b/scripts/tiktok_downloadVideoNoWM.js index 822a9a7d..120133f5 100644 --- a/scripts/tiktok_downloadVideoNoWM.js +++ b/scripts/tiktok_downloadVideoNoWM.js @@ -36,7 +36,7 @@ export default { export const shared = { // Source code: https://github.com/karim0sec/tiktokdl - getVideoId(url) { + getVideoId: function (url) { if (url.includes("@") && url.includes("/video/")) return url.split("/video/")[1].split("?")[0]; throw Error("URL video tiktok không đúng địng dạng"); From 815465381be2b6da4bf87c9407057784e41d186f Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Wed, 7 Dec 2022 04:06:44 +0700 Subject: [PATCH 026/164] update fb download watching video --- popup/tabs.js | 2 +- scripts/fb_downloadWatchingVideo.js | 146 ++++++++++++++++++++-------- scripts/fb_getAvatarFromUid.js | 1 + scripts/fb_videoDownloader.js | 6 +- 4 files changed, 109 insertions(+), 46 deletions(-) diff --git a/popup/tabs.js b/popup/tabs.js index a79508bc..3cac09da 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -95,9 +95,9 @@ const tabs = [ s.fb_hideNewFeed, createTitle("--- Download ---", "--- Tải xuống ---"), s.fb_storySaver, - s.fb_videoDownloader, s.fb_downloadWatchingVideo, s.fb_downloadCommentVideo, + s.fb_videoDownloader, s.fb_getAvatarFromUid, s.fb_storyInfo, createTitle("--- Bulk Download ---", "--- Tải hàng loạt ---"), diff --git a/scripts/fb_downloadWatchingVideo.js b/scripts/fb_downloadWatchingVideo.js index 798e5f66..a6efacf5 100644 --- a/scripts/fb_downloadWatchingVideo.js +++ b/scripts/fb_downloadWatchingVideo.js @@ -1,29 +1,59 @@ -import { runScriptInCurrentTab } from "./helpers/utils.js"; +import { runScriptInCurrentTab, showLoading } from "./helpers/utils.js"; import { parseXml, xml2json } from "./helpers/xmlParser.js"; +import { shared as fb_videoDownloader } from "./fb_videoDownloader.js"; export default { - icon: '', + icon: "https://www.facebook.com/favicon.ico", name: { - en: "Facebook - Download watching video", - vi: "Facebook - Tải video đang xem", + en: "Download watching facebook video", + vi: "Tải video facebook đang xem", }, description: { - en: "", - vi: "", + en: "Download facebook video that you are watching", + vi: "Tải video facebook bạn đang xem", }, blackList: [], whiteList: ["https://www.facebook.com/*"], runInExtensionContext: true, func: async function () { - let listXml = await runScriptInCurrentTab(() => { - // https://stackoverflow.com/a/7557433 - function isElementInViewport(el) { + let { closeLoading, setLoadingText } = showLoading( + "Đang lấy videoId từ trang web..." + ); + try { + let listVideoId = await shared.getListVideoIdInWebsite(); + let watchingVideoId = listVideoId[0]; + if (!watchingVideoId) throw Error("Không tìm thấy video nào"); + + setLoadingText("Đang lấy token dtsg..."); + let dtsg = await fb_videoDownloader.getDtsg(); + + setLoadingText("Đang tìm video url..."); + let videoUrl = await fb_videoDownloader.getLinkFbVideo2( + watchingVideoId, + dtsg + ); + + if (videoUrl) window.open(videoUrl); + else throw Error("Không tìm được video link"); + } catch (e) { + alert("ERROR: " + e); + } finally { + closeLoading(); + } + }, +}; + +export const shared = { + getListVideoIdInWebsite: async function () { + return await runScriptInCurrentTab(() => { + function getOverlapScore(el) { var rect = el.getBoundingClientRect(); - return !( - rect.bottom < 0 || - rect.top > - (window.innerHeight || document.documentElement.clientHeight) + return ( + Math.min( + rect.bottom, + window.innerHeight || document.documentElement.clientHeight + ) - Math.max(0, rect.top) ); } @@ -39,42 +69,74 @@ export default { } } result.push({ - inViewPort: isElementInViewport(video), - xml: video.parentElement[key].children.props.manifest, + overlapScore: getOverlapScore(video), + videoId: video.parentElement[key].children.props.videoFBID, }); - console.log(video, isElementInViewport(video)); } catch (e) { - console.log("ERROR on get video manifest: ", e); + console.log("ERROR on get videoFBID: ", e); } } - return result; + return result + .sort((a, b) => b.overlapScore - a.overlapScore) + .map((_) => _.videoId); }); + }, +}; - let urls = listXml - .map(({ inViewPort, xml }) => { - try { - let json = JSON.parse( - xml2json(parseXml(xml)).replace("undefined", "") - ); - let urls = json.MPD.Period.AdaptationSet[0].Representation.map( - (_) => ({ - quality: _["@FBQualityLabel"], - url: _.BaseURL.replaceAll("&", "&"), - }) - ); - return { - inViewPort, - urls, - }; - } catch (e) { - return null; +async function backup() { + // Get video urls from manifest (no audio) + let listXml = await runScriptInCurrentTab(() => { + // https://stackoverflow.com/a/7557433 + function isElementInViewport(el) { + var rect = el.getBoundingClientRect(); + return !( + rect.bottom < 0 || + rect.top > (window.innerHeight || document.documentElement.clientHeight) + ); + } + + let allVideos = Array.from(document.querySelectorAll("video")); + let result = []; + for (let video of allVideos) { + try { + let key = ""; + for (let k in video.parentElement) { + if (k.startsWith("__reactProps")) { + key = k; + break; + } } - }) - .filter((_) => _); + result.push({ + inViewPort: isElementInViewport(video), + xml: video.parentElement[key].children.props.manifest, + }); + } catch (e) { + console.log("ERROR on get video manifest: ", e); + } + } - console.log(urls); - }, -}; + return result; + }); + + let urls = listXml + .map(({ inViewPort, xml }) => { + try { + let json = JSON.parse(xml2json(parseXml(xml)).replace("undefined", "")); + console.log(json); + let urls = json.MPD.Period.AdaptationSet[0].Representation.map((_) => ({ + quality: _["@FBQualityLabel"], + url: _.BaseURL.replaceAll("&", "&"), + })); + return { + inViewPort, + urls, + }; + } catch (e) { + return null; + } + }) + .filter((_) => _ && _.inViewPort); -export const shared = {}; + console.log(urls); +} diff --git a/scripts/fb_getAvatarFromUid.js b/scripts/fb_getAvatarFromUid.js index d5fb135a..e55f290d 100644 --- a/scripts/fb_getAvatarFromUid.js +++ b/scripts/fb_getAvatarFromUid.js @@ -1,6 +1,7 @@ import { downloadData, showLoading } from "./helpers/utils.js"; export default { + icon: '', name: { en: "Get avatar from fb user id", vi: "Tải avatar từ fb user id", diff --git a/scripts/fb_videoDownloader.js b/scripts/fb_videoDownloader.js index 9058d3cc..912cf74a 100644 --- a/scripts/fb_videoDownloader.js +++ b/scripts/fb_videoDownloader.js @@ -5,10 +5,10 @@ import { } from "./helpers/utils.js"; export default { - icon: "https://www.facebook.com/favicon.ico", + icon: '', name: { - en: "Facebook - Download video/reel/watch", - vi: "Facebook - Tải video/reel/watch", + en: "Download facebook video/reel/watch", + vi: "Tải video/reel/watch facebook", }, description: { en: "Download facebook video/reel/watch", From eb1f05b1908d515c2247d00fcd8d74d88a78951a Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Wed, 7 Dec 2022 04:55:30 +0700 Subject: [PATCH 027/164] update name scripts --- popup/tabs.js | 2 +- scripts/fb_downloadCommentVideo.js | 4 ++-- scripts/fb_downloadWatchingVideo.js | 8 ++++---- scripts/fb_storySaver.js | 4 ++-- scripts/fb_videoDownloader.js | 4 ++-- scripts/instantgram.js | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/popup/tabs.js b/popup/tabs.js index 3cac09da..7f27352e 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -94,8 +94,8 @@ const tabs = [ s.fb_toggleLight, s.fb_hideNewFeed, createTitle("--- Download ---", "--- Tải xuống ---"), - s.fb_storySaver, s.fb_downloadWatchingVideo, + s.fb_storySaver, s.fb_downloadCommentVideo, s.fb_videoDownloader, s.fb_getAvatarFromUid, diff --git a/scripts/fb_downloadCommentVideo.js b/scripts/fb_downloadCommentVideo.js index 8220ba73..1170e2ee 100644 --- a/scripts/fb_downloadCommentVideo.js +++ b/scripts/fb_downloadCommentVideo.js @@ -7,8 +7,8 @@ export default { vi: "Tải video trong comment facebook", }, description: { - en: "Download facebook comment video that you are watching", - vi: "Tải video trong comment facebook bạn đang xem", + en: "Download video in facebook comment that you are watching", + vi: "Tải video trong bình luận bạn đang xem", }, whiteList: [], runInExtensionContext: false, diff --git a/scripts/fb_downloadWatchingVideo.js b/scripts/fb_downloadWatchingVideo.js index a6efacf5..9c2f023f 100644 --- a/scripts/fb_downloadWatchingVideo.js +++ b/scripts/fb_downloadWatchingVideo.js @@ -5,12 +5,12 @@ import { shared as fb_videoDownloader } from "./fb_videoDownloader.js"; export default { icon: "https://www.facebook.com/favicon.ico", name: { - en: "Download watching facebook video", - vi: "Tải video facebook đang xem", + en: "Download watching fb video", + vi: "Tải video fb đang xem", }, description: { - en: "Download facebook video that you are watching", - vi: "Tải video facebook bạn đang xem", + en: "Download fb video that you are watching (watch/story/comment)", + vi: "Tải video fb bạn đang xem (watch/story/comment)", }, blackList: [], whiteList: ["https://www.facebook.com/*"], diff --git a/scripts/fb_storySaver.js b/scripts/fb_storySaver.js index 79990bc8..c93865ae 100644 --- a/scripts/fb_storySaver.js +++ b/scripts/fb_storySaver.js @@ -1,8 +1,8 @@ export default { icon: "https://lh3.googleusercontent.com/e8gqesNOLhN-0xivFcaAlwGaoftfxEJcZXcXJ1F2bhoqrozs3mCYgLhPC0qJ9izdGYRnHwfXegimH9fjj3IBwlby9ZA=w128-h128-e365-rj-sc0x00ffffff", name: { - en: "Download watching Facebook Story", - vi: "Tải Story Facebook đang xem", + en: "Download watching fb Story", + vi: "Tải Story fb đang xem", }, description: { en: "Download facebook story that you are watching", diff --git a/scripts/fb_videoDownloader.js b/scripts/fb_videoDownloader.js index 912cf74a..786baad1 100644 --- a/scripts/fb_videoDownloader.js +++ b/scripts/fb_videoDownloader.js @@ -7,8 +7,8 @@ import { export default { icon: '', name: { - en: "Download facebook video/reel/watch", - vi: "Tải video/reel/watch facebook", + en: "Download fb video/reel/watch from url", + vi: "Tải video/reel/watch fb từ url", }, description: { en: "Download facebook video/reel/watch", diff --git a/scripts/instantgram.js b/scripts/instantgram.js index c037287a..ef759923 100644 --- a/scripts/instantgram.js +++ b/scripts/instantgram.js @@ -1,8 +1,8 @@ export default { icon: "https://www.instagram.com/favicon.ico", name: { - en: "Instantgram - Download watching photo/video/story", - vi: "Instantgram - Tải ảnh/video/story đang xem", + en: "Download watching insta photo/video/story", + vi: "Tải ảnh/video/story insta đang xem", }, description: { en: "Download full-size instagram image/video/story in 1 click", From 31f930a21203d07569084fa0fa4fbfd1be1419f4 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Wed, 7 Dec 2022 05:21:26 +0700 Subject: [PATCH 028/164] . --- scripts/_test.js | 62 +++++++++----------------- scripts/insta_downloadWatchingVideo.js | 26 +++++++++++ scripts/instantgram.js | 8 ++-- 3 files changed, 52 insertions(+), 44 deletions(-) create mode 100644 scripts/insta_downloadWatchingVideo.js diff --git a/scripts/_test.js b/scripts/_test.js index 6d061087..c6d9f931 100644 --- a/scripts/_test.js +++ b/scripts/_test.js @@ -14,48 +14,30 @@ export default { runInExtensionContext: false, func: async function () { - function stringifyVariables(d, e) { - let f = [], - a; - for (a in d) - if (d.hasOwnProperty(a)) { - let g = e ? e + "[" + a + "]" : a, - b = d[a]; - f.push( - null !== b && "object" == typeof b - ? stringifyVariables(b, g) - : encodeURIComponent(g) + "=" + encodeURIComponent(b) - ); - } - return f.join("&"); - } - function fetchGraphQl(body) { - return fetch("https://www.facebook.com/api/graphql/", { - method: "POST", - headers: { - "content-type": "application/x-www-form-urlencoded", - }, - body: body, - }); + function getOverlapScore(el) { + var rect = el.getBoundingClientRect(); + return ( + Math.min( + rect.bottom, + window.innerHeight || document.documentElement.clientHeight + ) - Math.max(0, rect.top) + ); } - // get video from group? - // let res = await fetchGraphQl( - // stringifyVariables({ - // doc_id: "3972944316164299", - // variables: JSON.stringify({ - // groupID: 364997627165697, - // count: 8, - // useCometPhotoViewerPlaceholderFrag: !0, - // scale: 1.5, - // }), - // fb_dtsg: require("DTSGInitialData").token, - // fb_api_caller_class: "RelayModern", - // fb_api_req_friendly_name: "GroupsCometMediaVideosTabGridQuery", - // }) - // ); - // let text = await res.json(); + let videos = document.querySelectorAll("video"); + let urls = []; + for (let video of videos) { + let key = ""; + for (let k in video) { + if (k.startsWith("__reactProps$")) { + key = k; + break; + } + } + + urls.push(video[key].src); + } - // console.log(text); + console.log(urls); }, }; diff --git a/scripts/insta_downloadWatchingVideo.js b/scripts/insta_downloadWatchingVideo.js new file mode 100644 index 00000000..8782cc56 --- /dev/null +++ b/scripts/insta_downloadWatchingVideo.js @@ -0,0 +1,26 @@ +export default { + icon: "", + name: { + en: "", + vi: "", + }, + description: { + en: "", + vi: "", + }, + + // Chọn 1 trong 2 cách, xoá cách không dùng: + + // Cách 1: Mở link web trong tab mới, không cần dùng func + link: "", + + // Cách 2: Chạy script + blackList: [], + whiteList: [], + runInExtensionContext: false, + + func: function () {}, +}; + +// Những thuộc tính/hàm có thể chia sẻ cho cách scripts khác sử dụng sẽ được viết vào đây +export const shared = {}; diff --git a/scripts/instantgram.js b/scripts/instantgram.js index ef759923..e00b144f 100644 --- a/scripts/instantgram.js +++ b/scripts/instantgram.js @@ -1,12 +1,12 @@ export default { icon: "https://www.instagram.com/favicon.ico", name: { - en: "Download watching insta photo/video/story", - vi: "Tải ảnh/video/story insta đang xem", + en: "Download watching insta photo/story", + vi: "Tải ảnh/story insta đang xem", }, description: { - en: "Download full-size instagram image/video/story in 1 click", - vi: "Tải ảnh/video/story instagram nhanh chóng bằng 1 click", + en: "Download full-size instagram image/story in 1 click", + vi: "Tải ảnh/story instagram nhanh chóng bằng 1 click", }, blackList: [], whiteList: [], From ede0822ff250b257e09c41cdb73dae011297f7ea Mon Sep 17 00:00:00 2001 From: "hoang.tran12" Date: Wed, 7 Dec 2022 11:47:40 +0700 Subject: [PATCH 029/164] update (WIP) bypass-all-shortlink --- popup/tabs.js | 3 +- scripts/content-scripts/document_start.js | 5 + .../scripts/bypass_all_shortlink.js | 630 ++++++++++++++++++ scripts/content-scripts/scripts/studocu.css | 9 + scripts/content-scripts/utils.js | 12 +- scripts/helpers/utils.js | 3 + scripts/index.js | 2 + scripts/insta_getAllImagesInNewFeed.js | 48 +- scripts/insta_getToken.js | 10 + scripts/studocu_downloader.js | 23 + scripts/tiktok_downloadUserVideos.js | 9 +- 11 files changed, 702 insertions(+), 52 deletions(-) create mode 100644 scripts/content-scripts/scripts/bypass_all_shortlink.js create mode 100644 scripts/content-scripts/scripts/studocu.css create mode 100644 scripts/studocu_downloader.js diff --git a/popup/tabs.js b/popup/tabs.js index 7f27352e..f4db6966 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -70,6 +70,7 @@ const tabs = [ s.download_image, createTitle("--- Document ---", "--- Tài liệu ---"), s.scribd_downloadDocuments, + s.studocu_downloader, ], }, { @@ -128,10 +129,10 @@ const tabs = [ { ...CATEGORY.instagram, scripts: [ - // s.insta_reloaded, s.insta_getToken, s.insta_getUserInfo, createTitle("--- Download ---", "--- Tải xuống ---"), + s.insta_reloaded, s.instantgram, s.insta_storySaver, createTitle("--- Bulk Download ---", "--- Tải hàng loạt ---"), diff --git a/scripts/content-scripts/document_start.js b/scripts/content-scripts/document_start.js index 82dc51ba..a2303770 100644 --- a/scripts/content-scripts/document_start.js +++ b/scripts/content-scripts/document_start.js @@ -6,6 +6,8 @@ // injectScript(baseURL + "globals_debugger.js"); injectScript(baseURL + "useful-scripts-utils.js"); + injectScript(baseURL + "bypass_all_shortlink.js"); + if (location.hostname === "mp3.zing.vn") injectScript(baseURL + "mp3.zing.vn.js"); @@ -15,6 +17,9 @@ if (location.hostname === "www.studyphim.vn") injectScript(baseURL + "studyphim.js"); + if (location.hostname === "www.studocu.com") + injectCss(baseURL + "studocu.css"); + // if (location.hostname === "luanxt.com") // injectScriptFile("//code.jquery.com/jquery-3.6.1.min.js", true); })(); diff --git a/scripts/content-scripts/scripts/bypass_all_shortlink.js b/scripts/content-scripts/scripts/bypass_all_shortlink.js new file mode 100644 index 00000000..d54378e0 --- /dev/null +++ b/scripts/content-scripts/scripts/bypass_all_shortlink.js @@ -0,0 +1,630 @@ +// https://greasyfork.org/en/scripts/431691-bypass-all-shortlinks/code +function userScriptConfigToObject(config) { + let a = config.split("\n"); + let b = { + includes: [], + exclude: [], + match: [], + }; + a.forEach((_) => { + let value = _.split(" ").at(-1); + if (_.includes("@include")) { + b.includes.push(value); + } else if (_.includes("@exclude")) { + b.exclude.push(value); + } else if (_.includes("@match")) { + b.match.push(value); + } + }); +} + +let config = { + includes: [ + "/^(https?://)(tmearn|additionalgamer|makemoneywithurl|shrinkearn|techcyan|aghtas|soltoshindo|link4m|kingsleynyc|healthy4pepole|kiktu|1bitspace|skip-url|pennbookcenter|publicananker|mikl4forex|michaelemad|miklpro|zirof|forex-golds|nawahi1|mosqam|semawur|forex-trnd|hoshilink|taiwancnan|bit-url|megurus|cuts-url|popimed|rayusmedya|enburl|pickhopes|toryxlink|aduzz|lycoslink|cdrab|ibrabucks|zenshort|ethiomi|shortenbuddy|kiemlua|smoner|djbhojpurisongs|urlty|sakastau|modsbase|ac.totsugeki|bcvc2|earnwithshortlink|bitzite|link1s|diadiemcheckin|tudiendanhngon|chooyomi|staaker|lucidcam|forexlap|forexmab|linkjust|admediaflex|hoclamdaubep|rekonise|forex-articles|ponselharian|liinkat|thegoneapp|mobi2c|studyuo|hookeaudio|thehostingmentor|intlinki|linkshortify|shopsixseven|mohtawaa|msarzone|foodhear|fc-lc|expertvn|downphanmem|healdad|ez4mods|try2link|tmker|soft3arbi|techyadjectives|ex-foary|examtadka|bablyfeed|crypto4tun|blogmado|itsguider|coin-free|1xfaucet|dash-free|usdshort|cafenau|techacode|ls2earn|sevenjournals|7misr4day|trflink|sama-pro|s.ume24|shtfly|bestmobilenew|onlineincoms|modsfire|adneow|short.clickscoin|samaa-pro|techrfour|ez4short|topnewsnew|gawishpro|dz4link|skincarie|gaminplay|infinitycoupon|videoslyrics|shortlite|bitefaucet|techrayzer|shorteet|donnaleehunt|puggygaming|link2end|tranquangchuan|blogginglass|1shorten|lensabicara|tieutietkiem|yummy-reciepes|doctor-groups|link.bigboxnet|bioinflu|chamcuuhoc|litexblog|7nything|gamalk-sehetk|adsafelink|cbshort|bellurl|abcshort|checkscoin|llinkon|links.apksvip|nguyenvanbao|cloudgetlink|techloadz|atglinks|nulledsafe|dreamcheeky|cutpaid|fidlarmusic|rodjulian|anhdep24|money.alyoumeg|sl.claimfreebits|sl-1.btcbunch|sl-2.btcbunch|earncryptowrs|short-zero|insurancevela|poketoonworld|arahtekno|mopahealth|nghiencar|sl-3.btcbunch|apk.miuiku|bitlya|ecwizon|oncehelp|sportsmediaz|big2short|techymozo|loptelink|2shrt|charexempire|coindoog|shotzon|novelsapps|webhostingpost|tremamnon|tirailangit|intercelestial|tribuntekno|bestcash2020|hoxiin|fooot-map|priefy|dz-linkk|fauxlink|chinhnhacoban|autodime|cortaly|link.3dmili|1adlink|indianshortner|donia-tech|donia2tech|donia2link|short1s|cr3zyblog|btafile|pdiskshortener|urlsopen|1shortlink|linkerload|filenext|shrinkmoney|doodshort|paid4link|kienthucrangmieng|wiki-topia|aljoodm98|newworldnew|sahityt|mkomsel|niinga|bclikeqt|youssefsayed|fx4vip|shortzon|get4links|crickblaze|nostralink|clkmein|101desire|memangbau|hosting4lifetime|mesho-link|up4cash|newsharsh|examkhata|linksht|note1s|adclickersbot|mobitaak|btcwalk|99faucet|modebaca|paylinnk|olhonagrana|chedrive|teknosimple|discordserv|link-yz|apkadmin|ayelads|gawbne|mshortener|cutdomain|usersdrive|uptobox|1fichier|uploadrar|bayfiles|krakenfiles|post.copydev|icutlink|zegtrends|anonfiles|sharemods|ddownload|uppit|userscloud|newsnowbd|link.nulldown|asideway|url.namaidani|url.magmint|mp4upload|myshrinker|apkshrt|link.turkdown|drive.google|safe.intipanime|trylinko|uploadhaven|manga2day|shortyearn|workupload|filedm|themorningtribune|beingtek|sub2get|ex-load|campki|social-unlock|teerclub|short-jambo|link.bitmagge|nerdiess|best-cpm|clicksfly|megaupto|maqal360|foodboth|ufacw|techcartz|softechbharat|okrzone|informaxonline|shopdorod|short.skalbayrak|adshnk|sub2unlock|smarcrm|cryptomeloud|blog-everything|ikrey|tipsli|urlpayout|urlpoints|hocbeauty|95news|link.get4llink|twitonet|shrinklo|xemsport|cutwin|pubgquotes|examsteacher|adpaylink|yxoshort|mdiskurl|shrt10|imgbsr|linknih|lessurl|pureshort|adrinolinks|wikitraveltips|techkeshri|uploadsoon|shrinkgold|itechmafiia|link4earn|team.pastehosting|educur|3rabsnews)(.com)(/.*)/", + "/^(https?://)(.+)?(zolomix|cararegistrasi|5golink|birdurls|snkra|artiskini|sh2rt|byboe|medcpu|nousdecor|restorbio|bdnewsx|upshrink|gifans|jardima|jobswd|gkqnaexam|imperialstudy|ovlinks|imagenesderopaparaperros|yofaurls|digiromotion|wingifta|rancah|coinadfly|delishwell|zippyshare|solidfiles|ourtecads|zubatecno|covemarkets|disheye|eda-ah|blog-forall|techymedies|gamelopte|allcryptotips|claimclicks|snowurl|riadcrypto|askpaccosi|linktrims|gets4link|visflakes|apk4do|dineroshare|elwatanelyoum|ledifha|claimfey|shrinkito|panylink|wrbloggers|tokenoto|saly-cash|upload-4ever|shortenn|admediaflex|btcpany|assettoworld|vikashmewada|linkyearn|appsbull|gam3ah|tinybc|diudemy|file-upload|shorterall|tribuncrypto|cempakajaya|safelinkduit|nadersoft7|adshorturl|linkbnao|phsensei|4shared|ta2deem7arbya|lrshortner|tinycmd|cloudshrinker|proviralhost|technicalatg|v2links|ytsubme|rainurl|arahlink|m4cut|teachsansar|web9academy|shortxlinks|flyrar|pythondunyasi|meykmen|on-scroll|shrtfly|i-polls|sonicbtc|cutln|menjelajahi|almontsf|crypturls|zombiebtc|sekilastekno|techwhom|hereofamily|cash4share|linkwards)(.com)(/.*)/", + "/^(https?://)(ahyblogs|ourcoincash|1manga|watchdoge|arenaboard|ccsl|shrinkpay|adsgo|shon|crypto-faucet|bingeflix|studystar|liongiv|lokagames|3vw|short-cash2|wizzly|mgnet|crypteen|dogeen|fauceteen|cutdl|sportawy|fexkomin|technemo|zoomcrypto|techboyz|cblinks|99links|kartunik|post.nites-tv|shortplus|stores.filmyzilla-in|expresscoins|claimcoinsfree|short1|swzz|acortame|alghtas|wizly|horanews|a1link|short2fly|bcvc|healthbloog|post.movies-near-me|st.kleaco|playlink|q8c|sh0rt1|cars-1year|nabits|welovecrypto|worldappsstore|0uq|sh.tripledownloader|short2url|zeroshort|bitsyield|egstar|uscity|monsterurlshortner|bflinks|gibit|playdisk|studyis|kukslincs|magictoshi)(.xyz)(/.*)/", + "/^(https?://)(.+)?(senuansatechno|insurglobal|claimercorner|shortly|dexlink|doctorcoin|speedynews|1apple|ffworld|textpage|fidovy|egfly|insurance-space|crypto-blog|sapica|earnfacut|urlbharat|dropz|chainfo|megano-coin|techleets|earnl)(.xyz)(/.*)/", + "/^(https?://)(neonlink|techydino|world-trips|yoshare|lets.5get|crypto-fi|wpcheap|coinmasterx|catcut|aztravels|dulichkhanhhoa|sub2unlock|forex-gold|techtrickonline|7apple|ccurl|luckydice|link1s|url.namaidani|cryptowidgets|dogeclick|adskip|hurirk|usfinf|xervoo|sport4you|hexupload|eloism|cutt|forexshare|blog.cryptowidgets|neexulro|dailyuploads|douploads|simfileshare|fir3|magybu|racaty|linegee|blogesque|thuocdangian|altblogger|letsboost|cut-y|megadb|conghuongtu|vinaurl|tecmundo|try2link|cpmlink)(.net)(/.*)/", + "/^(https?://)(.+)?(digitalnaz|owllink|mozlink|cryptosats|rocklinks|celinks|jiotech|bitcomarket|illink|jemari|fire-link|linkrex|urlw|paid4link|link3s|boscoin|pilinks|linkshortify)(.net)(/.*)/", + "/^(https?://)(tnlink|jrlinks|qualitystudymaterial|cuturl|missionhight|wpking|zagl|ls2earn|streamshort|shareus|referus|megafly|megaurl|cutp|earnmoj|riadshot|urlmoney|cplink|cryptomonitor|technoflip|linkshortify|htlinks|techlearningtube|urlfly|linkocean|financeflix|uttan|jazbaat|djxmaza|bildirim|techy4you|battlechamp|sahilsumra|kerdlinfo|urlcut|insurancevlog|itechlogic|videolyrics|tekcrypt|missionhight|gplinks|moddingzone|adybrands|gpflix|gz2|dulink|aclinks|hidelinks|shortearn|siteblog|u.apgy|du-link|ouoi|by6|adrinolinks|rklinks|mymobilehub|techdaze|link4earn|rupamobile|examsolution)(.in)(/.*)/", + "/^(https?://)(.+)?(cashurl|linkad|bitcoinly|crazyblog|zolomix|technologylover|expertlinks|largestpanel|linkres|rsrlink|linkstream|xmod|short2url|99links|rplinks|enit|adloot|url2go|tnvalue|pvidly|apurl|earnspace|urlinked|mdlink|gamerfang|writedroid|teckypress|fixno|paisakamalo|inkik|shrinkforearn|easysky|ajlinks|mdiskplayer|akcartoons)(.in)(/.*)?/", + "/^(https?://)(aylink|linkszia|mynewsmedia|gtlink|adfloz|linksly|droplink|123link|linksfy|adshorti|hxfile|dosya|veganal|takem|ezimg|eng.ezimg|dausel|9-animie|veganho|nulledmod|veganac|dealprice|modlink|arabplus2|cut-y)(.co)(/.*)/", + "/^(https?://)(.+)?(takez|linksfire|vosan|tinygo|veganab)(.co)(/.*)/", + "/^(https?://)(ctbl|girls-like|gobits|zoss|shrinke|tlin|terafly|petafly|gigafly|adnews|papanews|panyflay|mozzfly|shortus|short.croclix|best-news|mega-news|wildblog|specx|dddrive|linkpoi|sh24|m.newhit|mboost|linkshorts|exafly|nonofly|lozzfly|uptomega|stfly|adbull|youshort|health-and|cutx|adsk|shorter.earn-hub|linkfly|pkin)(.me)(/.*)/", + "/^(https?://)(.+)?(theconomy|richlink)(.me)(/.*)/", + "/^(https?://)(sitr|flylink|downfile|savelink|linkshortify|shareus|promo-visits|mobileprice)(.site)(/.*)/", + "/^(https?://)(.+)?(cekip|link4rev|coin-city)(.site)(/.*)/", + "/^(https?://)(earnme|sanoybonito|automotur|kooza|1link|zentum|mytop5|forexwaw|megatube)(.club)(/.*)/", + "/^(https?://)(.+)?(usanewstoday|kadal|webhostingtips)(.club)(/.*)/", + "/^(https?://)(adrev|paid4|yousm|coinpayz|tr|yocto|clk.dti|besturl|boostme|takefile|appo|pureshort|linkshortifyx)(.link)(/.*)/", + "/^(https?://)(.+)?(vshort|stex|cash4|zuba)(.link)(/.*)/", + "/^(https?://)(shurt|shortit|adsy|bitlinks|clik|playstore|megalink)(.pw)(/.*)/", + "/^(https?://)(.+)?(prz|pong)(.pw)(/.*)/", + "/^(https?://)(bloogerspoot|vsbl)(.ga)(/.*)/", + "/^(https?://)(bloogerspoot|linkshor|cortlink)(.tk)(/.*)/", + "/^(https?://)(.+)?(madfaucet|mineshor|futureshor)(.tk)(/.*)/", + "/^(https?://)(bloogerspoot|urlchanger|arearn|360shortlink)(.ml)(/.*)/", + "/^(https?://)(onimports|link.encurtaon|economiarelevante)(.com.br)(/.*)/", + "/^(https?://)(exee|onlineteori|punyablog|activity|massive|caview)(.my.id)(/.*)/", + "/^(https?://)(.+)?(mycut|apasih)(.my.id)(/.*)/", + "/^(https?://)(.+)?(suratresmi|carapedi|salink)(.id)(/.*)/", + "/^(https?://)(link.skm4u|linkwards)(.co.in)(/.*)/", + "/^(https?://)(.+)?(droplink)(.co.in)(/.*)/", + "/^(https?://)(kiiw|passgen|wordcounter|shrink|revcot|clickzu|shortzu)(.icu)(/.*)/", + "/^(https?://)(newforex|wplink|nbyts|wealthystyle|clicksfly|happy-living|earn-cash|yourtechnology|apks|network-earn|teacherana|earnow|battleroyal)(.online)(/.*)/", + "/^(https?://)(.+)?(adslinkfly|readi|linkmumet)(.online)(/.*)/", + "/^(https?://)(exey|ezlinks|techmody|ouo|ex-e|saly|cuty|evoload|oke|letsupload|eio|oii|exe)(.io)(/.*)/", + "/^(https?://)(.+)?(linkfly|usalink)(.io)(/.*)/", + "/^(https?://)(tny|tinyurl)(.so)(/.*)/", + "/^(https?://)(zshort|claimcrypto|cashearn|1ink|linkpay|moneylink|intnews|openload|linkspy|letsupload|myasietv)(.cc)(/.*)/", + "/^(https?://)(cryptoad|wikile|uploadev|mega4up|doibihar|cshort|payskip|homeairquality|shortearn|sl.btc25|earnsfly)(.org)(/.*)/", + "/^(https?://)(.+)?(medipost|shrinkurl|keeplinks|rajdlsg)(.org)(/.*)/", + "/^(https?://)(jameeltips|mitly|adfoc|link4fun)(.us)(/.*)/", + "/^(https?://)(.+)?(yalla-shoot-now|forexeen|jaelink)(.us)(/.*)/", + "/^(https?://)(noweconomy|deportealdia|adshort|ay|pngit|pndx)(.live)(/.*)/", + "/^(https?://)(earnads|genpassword|shrlink|mshort|punyamerk|shortnow|short.freeltc)(.top)(/.*)/", + "/^(https?://)(zagl|scratch247|siyn|portablesusb|children-learningreading|azmath|mobilereview|inform3tion|mobilism|machicon-akihabara|cooklike|videoclip|bitcrypto|shortlinkto|uptobhai|brbushare|fanclup)(.info)(/.*)/", + "/^(https?://)(faucetcrypto|bildirim)(.eu)(/.*)/", + "/^(https?://)(nex-url|olamovies|atrologyrex)(.cyou)(/.*)/", + "/^(https?://)(antonimos|blog.hostratgeber)(.de)(/.*)/", + "/^(https?://)(freelitecoin|uplinkto|1Link)(.vip)(/.*)/", + "/^(https?://)(.+)?(flyad|lootcash)(.vip)(/.*)/", + "/^(https?://)(romania|met|warp)(.bz)(/.*)/", + "/^(https?://)(2ad|viya|17o)(.ir)(/.*)/", + "/^(https?://)(adshrink|cutin)(.it)(/.*)/", + "/^(https?://)(pingit|files|upo)(.im)(/.*)/", + "/^(https?://)(clk|9xupload)(.asia)(/.*)/", + "/^(https?://)(iir|tei|ier|ckk)(.ai)(/.*)/", + "/^(https?://)(aii|clk|oko)(.sh)(/.*)/", + "/^(https?://)(.+)?(i8l|clk|pi-l|bcvc|modli)(.ink)(/.*)/", + "/^(https?://)(.+)?(upload|prx)(.ee)(/.*)/", + "/^(https?://)(.+)?(mirrored|clicknupload)(.to)(/.*)/", + "/^(https?://)(.+)?(ouo|forextrader|daga88)(.today)(/.*)/", + "/^(https?://)(.+)?(techgeek|adsgo)(.digital)(/.*)/", + "/^(https?://)(mhma12|surflink|techtrim)(.tech)(/.*)/", + "/^(https?://)(kiw|redir.123file)(.li)(/.*)/", + "/^(https?://)(zonearn|theprice|nhacremix|doanvanhai|hynews)(.biz)(/.*)/", + "/^(https?://)(.+)?(123link)(.biz)(/.*)/", + "/^(https?://)(.+)?(exe|exee|exep|upfiles|cutty|linkfly)(.app)(/.*)/", + "/^(https?://)(adshort|1bit|2the|careerhunter|galaxy-link)(.space)(/.*)/", + "/^(https?://)(makeeasybtc|softindex|techus)(.website)(/.*)/", + "/^(https?://)(linka|xtrabits|skipads)(.click)(/.*)/", + "/^(https?://)(.+)?(shortlinks|easysl|adlink|adzilla|urlcash)(.click)(/.*)/", + "/^(https?://)(.+)?(hamody|nathanaeldan|freddyoctavio|davisonbarker|clks|cryptosh|bestfonts|gitlink|openurl)(.pro)(/.*)/", + "/^(https?://)(up-load|zcash|mdisk)(.one)(/.*)/", + "/^(https?://)(1dogecoin|faucet)(.work)(/.*)/", + "/^(https?://)(sh.feyorra|fey.feyorra|claim|surelink|chuksblog|superlink|pricenews)(.fun)(/.*)/", + "/^(https?://)(go|blog|go2|tech|test|blg)(.madshiba.fun)(/.*)/", + "/^(https?://)(linkati|zenshort|curto|sh.kiddypay)(.win)(/.*)/", + "/^(https?://)(cool-time|movies|anime|tech)(.dutchycorp.space)(/.*)/", + "/^https://linkvertise.com/(1|2|3|4|5|6|7|8|9)/", + "/^https://cryptofans.club/(short|next|other|step)/", + "/^(https?://)(.+)?(mediafire)(.com)/(download|file)/", + "/^(https?://)(.+)?(cryptocurrencytracker|freefaucet)(.biz)/(link)/", + "/^(https?://)(.+)?(freebitcoin)(.fun)/(topsites|view)/", + "/^(https?://)(.+)?(clickscoin|freefeyorra|reddcoineveryday|cryptotyphoon|softairbay)(.com)/(short)/", + ], + exclude: [ + "/^https://claimclicks.com/(btc|ltc|doge|trx|faucetlist|ptclist)/", + "/^https://claimercorner.xyz/(claimer/dashboard|claimer/advertise|claimer/ptc|claimer/deposit|claimer/transfer|claimer/tasks|claimer/offerwall|claimer/profile|claimer/auto|claimer/mining|claimer/wheel|claimer/login)/", + "/^https://cryptosats.net/(cryptosats/dashboard|cryptosats/advertise|cryptosats/ptc|cryptosats/deposit|cryptosats/transfer|cryptosats/tasks|cryptosats/offerwall|cryptosats/profile|cryptosats/auto|cryptosats/mining|cryptosats/wheel|cryptosats/login)/", + "/^https://99faucet|faucet.cempakajaya.com/(dashboard|advertise|ptc|deposit|transfer|tasks|offerwall|profile|auto|mining|dice|lottery|faucet|login)/", + "/^https://free.tribuncrypto.com/(dashboard|advertise|ptc|deposit|transfer|tasks|offerwall|profile|auto|mining|dice|lottery|faucet|login)/", + "*://*.vosan.co/", + ], + match: [ + "*://dutchycorp.space/s*/*", + "*://dutchycorp.ovh/s*/*", + "*://shorts.lu/*", + "*://adx.wiki/*", + "*://adx.cx/*", + "*://al.ly/*", + "*://za.gl/*", + "*://goo.st/*", + "*://c2g.at/*", + "*://fcc.lc/*", + "*://adz.moe/*", + "*://coin.mg/*", + "*://send.cm/*", + "*://kimo.ma/*", + "*://goads.ly/*", + "*://mdn.rest/*", + "*://*.mdn.lol/*", + "*://*.rota.cc/*", + "*://ouo.press/*", + "*://7cc.96.lt/*", + "*://*.flyzu.icu/*", + "*://tinyurl.is/*", + "*://*.mdn.world/*", + "*://nail.edu.pl/*", + "*://lolabits.se/*", + "*://3shorturl.gq/*", + "*://litecoin.host/*", + "*://*.goto.com.np/*", + "*://z-cash.xyz/ad/*", + "*://drop.download/*", + "*://cryptofuns.ru/*", + "*://gosixs.com/s/*", + "*://linkshrink.ca/*", + "*://short.express/*", + "*://arbweb.info/sl/*", + "*://*.cizgifilm.tv/*", + "*://faucethub.ly/hs/*", + "*://faucetpay.io/ptc*", + "*://*.trangchu.news/*", + "*://webmobile.store/*", + "*://*.adz7short.space/*", + "*://docs.google.com/uc*", + "*://starfaucet.net/sl/*", + "*://solarchaine.com/sl/*", + "*://shrt.cryptofuns.ru/*", + "*://iqfaucet.com/link3/*", + "*://horrorbitcoin.com/?*", + "*://satoshi-win.xyz/url/*", + "*://cryptonetos.ru/page/*", + "*://faucet.gold/BTC/?step*", + "*://faucet.gold/ETH/?step*", + "*://adbtc.top/surf/browse/*", + "*://anonym.ninja/download/*", + "*://claimsolana.xyz/short/*", + "*://faucetcrypto.net/short/*", + "*://stationbit.xyz/autolink/*", + "*://cryptoaffiliates.store/sh*", + "*://konstantinova.net/verify/*", + "*://playnano.online/watch-and*", + "*://adbtc.top/surfiat/browse/*", + "*://rotator.nurul-huda.sch.id/*", + "*://*api-secure.solvemedia.com/*", + "*://faucetcrypto.com/claim/step/*", + "*://linkvertise.download/download/*", + "*://*.racedepartment.com/downloads/*", + "*://cryptorotator.website/sh_live/*", + "*://cryptonetos.ru/page/redirect*", + "*://galerybits.com/protectlink/*", + "*://earnultimate.space/short/*", + "*://bas.nurul-huda.or.id/*", + ], +}; + +let url = location.href; +let willRun = false; + +if (willRun) { + // prettier-ignore + (function() { + 'use strict'; + const RexBp = new RegExp(/^\?([^&]+)/); + const bp = query => document.querySelector(query); + const elementExists = query => bp(query) !== null; + const domainCheck = domains => new RegExp(domains).test(location.host); + function click(query) {bp(query).click();} + function submit(query) {bp(query).submit();} + function clickIfElementExists(query, timeInSec = 1, funcName = 'setTimeout') {if (elementExists(query)) {window[funcName](function() {click(query);}, timeInSec * 1000);}} + function Captchasub(query, act = 'submit', timeInSec = 0.5) {if (elementExists(query)) {var timer = setInterval(function() {if (window.grecaptcha && !!window.grecaptcha.getResponse?.()) {bp(query)[act](); clearInterval(timer);}}, timeInSec * 1000);}} + function Captchaklik(query, act = 'click', timeInSec = 1) {if (elementExists(query)) {var timer = setInterval(function() {if (window.grecaptcha && !!window.grecaptcha.getResponse?.()) {bp(query)[act](); clearInterval(timer);}}, timeInSec * 1000);}} + function redirect(url, blog = true) {location = blog ? 'https://rotator.nurul-huda.sch.id/?url=' + url : url;} + function BypassedByBloggerPemula(re_domain, data, blog) { if (!re_domain.test(location.host)) return; + if (typeof data === 'function') return data(); + if (Array.isArray(data)) data = {'/': data}; + if (!(location.pathname in data)) return; + const [key, value] = data[location.pathname]; + if (typeof key === 'object' && key.test(location.search)) return redirect(value + RegExp.$1, blog); + const searchParams = new URLSearchParams(location.search); + if (searchParams.has(key)) redirect(value + searchParams.get(key), blog);} + function BloggerPemula(domains, data, url, blog, use = null) {const searchParams = new URLSearchParams(location.search); + if (!domainCheck(domains)) return; + if (typeof data === 'string' && data.split(',').every(p => searchParams.has(p))) {use ??= data.split(',')[0]; + redirect(url + searchParams.get(use), blog);} else if (typeof data === 'object') {const o = data[location.pathname]; + if (!o) return; BloggerPemula(domains, ...o);}} + function meta(href) {document.head.appendChild(Object.assign(document.createElement('meta'), { name: 'referrer', content: 'origin'})); + Object.assign(document.createElement('a'), {href}).click();} + function waitForElm(query, callback) {setTimeout(function() {if (elementExists(query)) {callback(bp(query));} else {waitForElm(query, callback);}}, 1000);} + function notify(txt, width = 780) { const m = document.createElement('div'); + m.style.padding = '5px'; m.style.zIndex = 99999999; m.style.position = 'fixed'; m.style.boxSizing = 'border-box'; + m.style.width = `${width}px`; m.style.top = '100px'; m.style.left = `${innerWidth / 2 - width / 2}px`; m.style.font = 'normal bold 20px sans-serif'; + m.style.backgroundColor = 'white'; m.innerText = txt; document.body.appendChild(m);} + // There will be a Special Tricks and Bypass Codes only for Good Users (Anyone who have good attitude , Good Feedback, will be invited to my group) + BloggerPemula('sport4you.net|nadersoft7.com|manga2day.com|pickhopes.com|gam3ah.com|cars-1year.xyz|m4cut.com', 'link', '', false); + BloggerPemula('rupamobile.in', 'go', 'https://mdisk.one/', false); + BloggerPemula('rsrlink.in', 'link', 'https://go.rsrlink.in/', false); + BloggerPemula('itechmafiia.com', 'link', 'https://v.earnl.xyz/', false); + BloggerPemula('veganab.co', 'link', 'https://techy.veganab.co/', false); + BloggerPemula('siteblog.in', 'link', 'https://go.droplink.co.in/', false); + BloggerPemula('tr.link|fauceteen.xyz|adpaylink.com', 'url,api', '', false); + BloggerPemula('dealprice.co', 'adlinkfly', 'https://pricenews.fun/', false); + BloggerPemula('ww1.linktrims.com', 'link', 'https://linktrims.com/', false); + BloggerPemula('akcartoons.in', 'link', 'https://back.expertlinks.in/', false); + BloggerPemula('missionhight.in', 'link', 'https://playdisk.url2go.in/', false); + BloggerPemula('tech.techwhom.com', 'jeton', 'https://we.techwhom.com/', false); + BloggerPemula('linkshortifyx.link', 'link', 'https://yo.linkshortify.net/', false); + BloggerPemula('ffworld.xyz|doibihar.org', 'link', 'https://go.linkbnao.com/', false); + BloggerPemula('team.pastehosting.com', 'adlinkfly', 'https://shortxlinks.com/', false); + BypassedByBloggerPemula(/7apple.net/, {'/verify/': [RexBp, 'http://illink.net/'],}, false); + BypassedByBloggerPemula(/techdaze.in/, {'/': [RexBp, 'https://web.mdiskplayer.in/'],}, false); + BypassedByBloggerPemula(/rklinks.in/, {'/verify/': [RexBp, 'https://blog.inkik.in/'],}, false); + BypassedByBloggerPemula(/jemari.net/, {'/verify/': [RexBp, 'http://skip.jemari.net/'],}, false); + BypassedByBloggerPemula(/mymobilehub.in/, {'/safe.php': ['link', 'https://modlink.co/'],}, false); + BypassedByBloggerPemula(/medipost.org/, {'/verify/': [RexBp, 'http://go.theconomy.me/?'],}, false); + BypassedByBloggerPemula(/theconomy.me/, {'/verify/': [RexBp, 'http://links.medipost.org/'],}, false); + BypassedByBloggerPemula(/shopsixseven.com/, {'/verify/': [RexBp, 'http://safelinkduit.com/'],}, false); + BypassedByBloggerPemula(/linkwards.co.in/, {'/verify/': [RexBp, 'http://ads.linkwards.com/'],}, false); + BypassedByBloggerPemula(/uploadsoon.com/, {'/safe.php': ['link', 'https://shrinkforearn.in/'],}, false); + BypassedByBloggerPemula(/link.linksfire.co/, function() {location = location.href.replace('link', 'blog');}); + BypassedByBloggerPemula(/speedynews.xyz/, {'/blog/verify/': [RexBp, 'https://links.speedynews.xyz/'],}, false); + //BypassedByBloggerPemula(/blogs.egfly.xyz/, function() {location = location.href.replace('blogs.', 'link.');}); + BypassedByBloggerPemula(/studyuo.com/, {'/pro2/verify/': [RexBp, 'https://speedynews.xyz/blog/verify/?'],}, false); + BypassedByBloggerPemula(/short.rainurl.com|short.snowurl.com/, function() {location = location.href.replace('short.', '');}); + BypassedByBloggerPemula(/teachsansar.com/, () => waitForElm("#wpsafegenerate > #wpsafe-link > a[href]", safe => redirect(safe.href))); + BypassedByBloggerPemula(/go.birdurls.com|go.owllink.net|go.illink.net|go.pong.pw/, function() {location = location.href.replace('go.', '');}); + const sl = (h => {switch (h.host) { + case 'mobileprice.site': if (h.searchParams.has('alex')) { return 'https://msarzone.com/p/' + h.searchParams.get('alex');} break; + case 'bestmobilenew.com': if (h.searchParams.has('get')) { return 'https://link2end.com/p/' + h.searchParams.get('get').substring(1);} break; + case 'adlink.bitcomarket.net': if (h.searchParams.has('go')) { return 'https://adshorti.co/' + h.searchParams.get('go').substring(1);} break; + case 'theconomy.me': case 'blog.medipost.org': if (h.pathname === '/' && /^\?([^&]+)/.test(h.search)) { meta('https://links.medipost.org/' + RegExp.$1);} break; + default: break;} })(new URL(location.href)); if (sl) {location.href = sl; } + BypassedByBloggerPemula(/adbtc.top/, function() {let count =0; setInterval(function(){if(bp("div.col.s4> a") && !bp("div.col.s4> a").className.includes("hide")){count = 0;bp("div.col.s4> a").click();}else{count = count + 1;}},5000); + window.onbeforeunload = function() {if (unsafeWindow.myWindow) {unsafeWindow.myWindow.close();}if (unsafeWindow.coinwin) {let popc = unsafeWindow.coinwin;unsafeWindow.coinwin = {};popc.close();}};}); + BypassedByBloggerPemula(/dropz.xyz/, function() {if (window.location.href.includes('/captcha')&& !window.location.href.includes('/roll')) {}else if (window.location.href.includes('/site-friends')) {let windowName = "";let currentwindowOpenFunction = unsafeWindow.open;function newwindowOpenFunction(params1, params2) {if (!params2 || params2 == "_blank") {windowName = "popUpWindowMyDropz";} else {windowName = params2;} return currentwindowOpenFunction(params1, windowName);};unsafeWindow.open = newwindowOpenFunction;unsafeWindow.onbeforeunload = function() {currentwindowOpenFunction('', windowName).close();}; + function endsWithNumber(str){return isNaN(str.slice(-1)) ? false : true;}let clicked = false;setInterval(function(){for(let i=0; i< document.querySelectorAll(".btn.btn-info").length; i++){if(!clicked && !endsWithNumber(document.querySelectorAll(".btn.btn-info")[i].getAttribute('id')) && !document.querySelectorAll(".btn.btn-info")[i].innerText.includes("Submits")){document.querySelectorAll(".btn.btn-info")[i].click();break;}}},10000);} else {}}); + // Injecting from start document coded by @JustOlaf + if (location.host === 'techcyan.com'){delete window.document.referrer; window.document.__defineGetter__('referrer', function () {return "https://google.com/";});} + // Injecting from start document code by https://gist.github.com/lenivene + if (['magybu.net', 'xervoo.net', 'hurirk.net', 'usfinf.net', 'eloism.net', 'neexulro.net'].indexOf(location.host) > -1){Object.defineProperty(window,"ysmm",{set:function(b){var a=b,c="",d="";for(b=0;bd&&(a[b]=d),b=c,c=a.length);a=a.join("");a=window.atob(a);a=a.substring(a.length-(a.length-16));!(b=a=a.substring(0,a.length-16))||0!==b.indexOf("http://")&&0!==b.indexOf("https://")||(document.write("\x3c!--"),window.stop(),window.onbeforeunload=null,window.location=b);}});} + // Injecting code from start and the end of document coded by @Konf + if (['interactive', 'complete'].includes(document.readyState)) {onHtmlLoaded();} else {document.addEventListener('DOMContentLoaded', onHtmlLoaded);} function onHtmlLoaded() {if (['bas.nurul-huda.or.id', 'rotator.nurul-huda.sch.id'].indexOf(location.host) > -1){ } else { const listhide = document.querySelectorAll('#frame,.adb,#iframe,#particles-js,#canvas,.floawing-banner,#orquidea-slideup,.floating-banner,#wcfloatDiv4,#preloader,.vanta-canvas,.particles-js-canvas-el,#s65c,#ofc9,#overlay,#footerads,#d7b2,#_m_a_,#masthead_,.oulcsy,.sticky-bottom,.sticky-bottom1,.sticky-bottom2,.sticky-bottom3,.bElNbEFRL3JvbG89,.separator,html body iframe,html iframe,#cookie-pop,.vmyor,.tnjmvneldp,.full_post_area.rh-container,.sc-content-aside,#ofc9,.floawing-banner,div.demand-supply,.the_content,.alternative-ad'); for (const element of listhide) {element.remove();}} + if (['up4cash.com', 'app.menjelajahi.com', 'blog.menjelajahi.com'].indexOf(location.host) > -1){ } else { const listre = document.querySelectorAll('.banner-inner'); for (const element of listre) {element.remove();}} + if (['taiwancnan.com', 'blog.disheye.com'].indexOf(location.host) > -1){ } else { const listr = document.querySelectorAll('.blog-item'); for (const element of listr) {element.remove();}} + if (['patak.dropz.xyz', 'my.dropz.xyz'].indexOf(location.host) > -1){ } else { const listd = document.querySelectorAll('.text-left'); for (const element of listd) {element.remove();}} + if (location.host === 'jardima.com'){ } else { const listj = document.querySelectorAll('.td-ss-main-content'); for (const element of listj) {element.remove();}} + if(location.href.indexOf("diudemy.com") != -1 || location.href.indexOf("djxmaza.in") != -1 || location.href.indexOf("on-scroll.com") != -1 || location.href.indexOf("blog-everything.com") != -1 || location.href.indexOf("proviralhost.com") != -1 ) { + (function() {let FastInt = '{{1}}';if ( FastInt === '{{1}}' ) { FastInt = ''; }let delayArg = '{{2}}';if ( delayArg === '{{2}}' ) { delayArg = ''; }let boostArg = '{{3}}';if ( boostArg === '{{3}}' ) { boostArg = ''; } + if ( FastInt === '' ) {FastInt = '.?';} else if ( FastInt.charAt(0) === '/' && FastInt.slice(-1) === '/' ) {FastInt = FastInt.slice(1, -1);} else {FastInt = FastInt.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');}const FastInter = new RegExp(FastInt); + let delay = delayArg !== '*' ? parseInt(delayArg, 10) : -1;if ( isNaN(delay) || isFinite(delay) === false ) { delay = 1000; } + let boost = parseFloat(boostArg);boost = isNaN(boost) === false && isFinite(boost) ? Math.min(Math.max(boost, 0.02), 50) : 0.05; self.setInterval = new Proxy(self.setInterval, {apply: function(target, thisArg, args) {const [ a, b ] = args; + if ((delay === -1 || b === delay) && FastInter.test(a.toString())) {args[1] = b * boost;}return target.apply(thisArg, args);}});})();} + // ============================================ + // Captcha Mode + // ============================================ + let captchaMode = ['#_mform', '#userForm', '#link-view', '#frmprotect', '#ShortLinkId', '#submit-form', '#lview > form', '#file-captcha', '#btget > form', 'div#login form', 'F1', '#short-captcha-form', '#wpsafelink-landing', '.col-12 > form:nth-child(1)', '.col-md-4 > form:nth-child(1)', '.col-md-6 > form:nth-child(4)', '.contenido > form:nth-child(2)', '#main > div:nth-child(4) > form:nth-child(1)', 'div.col-md-12:nth-child(3) > form:nth-child(1)', '.content > div:nth-child(4) > form:nth-child(1)', '#showMe > center:nth-child(4) > form:nth-child(1)', '.sect > div:nth-child(1) > center:nth-child(7) > form:nth-child(1)', '#showMe > center:nth-child(1) > center:nth-child(4) > form:nth-child(1)', '#adb-not-enabled > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(5) > form:nth-child(1)', 'button#continue.btn.btn-primary.btn-captcha', '.m-2.btn-captcha.btn-outline-primary.btn', '#yuidea-btn-before.yu-btn.yu-blue', '#yuidea-btn-after.yu-blue.yu-btn', '#fauform']; + for (let i = 0; i < captchaMode.length; i++) {Captchasub(captchaMode[i]);} + let klikMode = ['button#continue.btn.btn-primary.btn-captcha', '.m-2.btn-captcha.btn-outline-primary.btn', '#yuidea-btn-before.yu-btn.yu-blue', '#yuidea-btn-after.yu-blue.yu-btn', '#submitBtn']; + for (let i = 0; i < klikMode.length; i++) {Captchaklik(klikMode[i]);} + // ============================================ + // SetTimeout Mode + // ============================================ + let timeoutMode = { + '2': ['.gobut'], + '3': ['p.getlink', 'button.jeje', '.yu-blue.yu-btn', 'button#btn-get-link', '#links > a:nth-child(2)', 'button.btn-main.get-link', 'button#btn6.yu-btn.yu-go', '.mb-3 > .btn-primary.btn', 'input[name="method_free"]', 'div#wpsafe-generate a img', 'button#mdt.custom-btn.btn-7', 'button#btn-main.btn.btn-main', 'button#bt.btn.btn-info.btn-lg', 'button#article.btn.btn-success', 'input#btn-main.btn.btn-primary', 'button#getlink.getlink.disabled', '#link1s-snp > button:nth-child(1)', '#link1s-snp > button:nth-child(1)', 'button#showTimerText.btn.btn-accent', '#wpsafelinkhuman > img:nth-child(1)', 'button#submit-button.btn.btn-primary', '.next-button.text-white.btn-info.btn', 'button#btn6.g-recaptcha.btn.btn-primary', '#cl1 > a:nth-child(2) > font:nth-child(1)', '#cl1 > center:nth-child(1) > a:nth-child(1)', '.next-button.btn-lg.text-white.btn-info.btn', 'button#btn6.btn.btn-outline-primary.btn-captcha.m-2', '.col-md-8 > form:nth-child(17) > button:nth-child(3)', 'div.box-main:nth-child(2) > div:nth-child(4) > a:nth-child(1)', 'div.column:nth-child(2) > font:nth-child(2) > a:nth-child(8)'], + '4': ['.exclude-popad.open-continue-btn-org.btn-primary.btn'], + '5': ['#yuidea-btmbtn', 'div.complete a.btn', 'button#g-recaptcha.gobt', '#molien > a:nth-child(1)', 'a#surl1.btn-main.get-link', '#wpsafe-snp > a:nth-child(1)', '.close-ad-modal-go-ahead.close', 'button#invisibleCaptchaShortlink.btn-main.get-link', 'button#invisibleCaptchaShortlink.btn.ybtn.ybtn-accent-color.btn-captcha', 'button#invisibleCaptchaShortlink.btn.btn-outline-primary.btn-lg.btn-block.btn-captcha'], + '7': ['button#invisibleCaptchaShortlink.btn.btn-primary.btn-goo.btn-captcha'], + '9': ['div.lds-ellipsis']}; + let _timeoutMode = Object.keys(timeoutMode); + for (let i = 0; i < _timeoutMode.length; i++) {for (let j = 0; j < timeoutMode[_timeoutMode[i]].length; j++) {clickIfElementExists(timeoutMode[_timeoutMode[i]][j], +_timeoutMode[i]);}} + // ============================================ + // setInterval Mode + // ============================================ + let intervalMode = { + '3': ['#slu-link', '#makingdifferenttimer', 'a#finalx22.btn.btnstep1', '#wg-form > .btnstep1.btn', '#myButtonn > span:nth-child(1)', 'input.g-recaptcha.btn.btn-primary', '#mdt.btn.btn-primary.text-white.next-button', 'div.column:nth-child(2) > font:nth-child(2) > a:nth-child(8)', 'button#main-button.claim-button.btn.btn-lg.btn-accent', 'a.get-link.bg-red-600.px-8.py-2.rounded-md.inline-block'], + '5': ['a.btn-main.get-link', 'a.btn.m-2.btn-success', '.btn-danger.btn-raised', '#link1s.btn-primary.btn', '.close-me > a:nth-child(1)', 'button#link.btn.btn-primary', '#btn6.btn-captcha.btn-primary.btn', 'a.btn.btn-primary.get-link.text-white', '#makingdifferenttimer9 > .btn-success.btn'], + '7': ['#nextButton', 'button#get_link.btn.btn-primary.btn-sm']}; + let _intervalMode = Object.keys(intervalMode); + for (let i = 0; i < _intervalMode.length; i++) {for (let j = 0; j < intervalMode[_intervalMode[i]].length; j++) {clickIfElementExists(intervalMode[_intervalMode[i]][j], +_intervalMode[i], 'setInterval');}} + waitForElm('div#wpsafe-link > a', function(element) {const regex = /redirect=(.*)',/; + const m = regex.exec(element.onclick.toString())[1]; location.href = JSON.parse(atob(m)).safelink;}); + if (typeof hcaptcha=="object" && typeof apiCounter=="object") { window.app_country_visitor=""; + window.hcaptcha.getResponse=()=>{}; + window.apiCounter.generateURL(); + window.apiCounter.redirectTo(bp("button.button-element-verification"));} + if (typeof tokenURL=="string") { redirect(atob(window.tokenURL));} + if (elementExists('#before-captcha')) { setTimeout(function() {bp('#before-captcha').submit();}, 3000);} + if (elementExists('#surl')) { setInterval(function() { bp('#surl.btn-success.m-2.btn').click();}, 5000);} + if (elementExists('#url_qu')) { setTimeout(function() {bp('.ad-banner.btn-captcha.btn-primary.btn').click();}, 3000);} + if (bp('#link-view > div[style="display: none;"]')) {bp('#link-view > div[style="display: none;"]').style.display = '';} + if (elementExists('a#firststep-btn.btn.btnstep1')) { setTimeout(function() {bp('button#getlink.btn.m-2.btn-success.disabled').click();}, 3000);} + if (location.host === 'faucetpay.io') {} else {Captchasub('form.text-center');} + if (['www.4shared.com', 'stfly.me'].indexOf(location.host) > -1) {} else {Captchasub("form[action='']");} + if (location.host === 'www.upload-4ever.com') {} else {clickIfElementExists('.btn-outline-white.btn', 3);} + if (location.host === 'uploadhaven.com') {} else {clickIfElementExists('button.btn-block.btn-success', 5, 'setInterval');} + if (['ctbl.me', 'zshort.cc'].indexOf(location.host) > -1 && location.search === '') {location = 'https://mdn.rest/?url8j=' + location.href;} + if (location.host === 'fc-lc.com') {window.top != window.self;} else {clickIfElementExists('button#submitbtn.g-recaptcha.btn.btn-primary', 3);} + if (['uploadhaven.com', 'patak.dropz.xyz', 'my.dropz.xyz'].indexOf(location.host) > -1) {} else {clickIfElementExists('button.btn.btn-success', 7);} + if (['paid4.link', 'ponselharian.com'].indexOf(location.host) > -1) {window.top != window.self;} else {clickIfElementExists('.btn-captcha.btn-sm.btn-primary.btn', 5);} + if (['www.solidfiles.com', 'usersdrive.com', 'workupload.com'].indexOf(location.host) > -1) {} else {clickIfElementExists('.btn-sm.btn-default.btn', 5, 'setInterval');} + if (['konstantinova.net', 'mobilereview.info'].indexOf(location.host) > -1) {} else {if (elementExists('#makingdifferenttimer')) { setInterval(function() { bp('#url_qu > a:nth-child(1)').click();}, 3000);}} + if (['coin.mg', 'rancah.com'].indexOf(location.host) > -1) {window.top != window.self;} else {if (elementExists('#links')) { setInterval(function() { bp('#links > form:nth-child(2)').submit();}, 3000);}} + if (['rancah.com','trangchu.news', 'techacode.com','downfile.site','upload-4ever.com'].includes(window.location.hostname) > -1) {window.top != window.self;} else {clickIfElementExists('input.btn.btn-primary', 5);} + if (location.host === 'teknosimple.com' && bp('.slu-captcha') !== null) {var ts = function() {if (window.grecaptcha.getResponse?.().length > 0) {bp('#slu-continue.slu-button').click(); clearInterval(ks);}};var ks = setInterval(ts, 500);} + if (['trangchu.news', 'downfile.site', 'techacode.com'].includes(window.location.hostname) > -1 && bp('.captcha') !== null) {var o = function() {if (window.grecaptcha.getResponse?.().length > 0) {bp('#proceed').click(); clearInterval(k);}};var k = setInterval(o, 500);} + if (location.host === 'faucetpay.io' && bp('.h-captcha') !== null) {var fp = function() {if (window.grecaptcha.getResponse?.().length > 0) {bp('.btn-danger.btn-lg.btn').click(); clearInterval(fcp);}};var fcp = setInterval(fp, 500);} + if (['blogmado.com','fc-lc.com', 'chooyomi.com','paid4.link','usersdrive.com', 'zentum.club', 'patak.dropz.xyz', 'my.dropz.xyz', 'workupload.com', 'taiwancnan.com','solarchaine.com','shortit.pw','djxmaza.in'].indexOf(location.host) > -1) {window.top != window.self;} else {clickIfElementExists('button.btn:nth-child(4)', 2, 'setInterval');} + if (['bitlinks.pw','ayelads.com', 'apkadmin.com','cashearn.cc','rancah.com','digitalnaz.net','upload-4ever.com','hexupload.net','upfiles.app','cut-y.co','keeplinks.org','fileshare.adshorturl.com','bowfile.com','letsupload.io','workupload.com'].includes(window.location.hostname) > -1) {} else {if (elementExists('div.col-md-4:nth-child(2)')) { setInterval(function() { bp('div.col-md-4:nth-child(2) > span:nth-child(1) > img:nth-child(1)').click();}, 5000);}} + let Numcode = bp('input.captcha_code'); let DigitNum; + function getLeft (d) {return parseInt(d.style.paddingLeft);} + if (Numcode) {DigitNum = Numcode.parentElement.previousElementSibling.children[0].children; + Numcode.value = [].slice.call(DigitNum).sort(function (d1, d2) {return getLeft(d1) - getLeft(d2);}).map(function(d){return d.textContent;}).join('');} + let $ = window.jQuery; let respect = 'https://bas.nurul-huda.or.id/?url='; // Don't use My Scripts if You Change/Remove My Blogs, Except You Make Donations!!!. + if (location.host === 'www.4shared.com') {if (elementExists('.d3topTitle')) {$('.premium').text('IMPORTANT TRICKS By BloggerPemula : Wait 5 Second or more , Dont Close this Page ,Right Click Here Link Above, Open Link in New Tab, Close the Tabs if Your File not Downloaded, Try again the Right Click Methods, at This Time i Dont have Idea to Make it Auto , Do the Same Trick for All File Type in 4shared Site . Regards...');}} + if (['short.croclix.me','www.adz7short.space'].indexOf(location.host) > -1) {function fireMouseEvents(query) { const element = document.querySelector(query); + if (!element) return; ['mouseover', 'mousedown', 'mouseup', 'click'].forEach(eventName => {if (element.fireEvent) { element.fireEvent('on' + eventName);} else { const eventObject = document.createEvent('MouseEvents'); + eventObject.initEvent(eventName, true, false); element.dispatchEvent(eventObject);}});} + setInterval(function() { if ($("#link").length > 0) { fireMouseEvents("#link");}}, 500); + setInterval(function() { if ($("input#continue").length > 0) {fireMouseEvents("input#continue");} + if ($("a#continue.button").length > 0) {fireMouseEvents("a#continue.button");}}, 9000); setTimeout(function() {if ($("#btn-main").length < 0) return; fireMouseEvents("#btn-main");}, 5000);} + if (['upfiles.app', 'cut-y.co'].indexOf(location.host) > -1) {clickIfElementExists('.get-link.btn-download.btn-primary.btn', 7);} else if (location.host === 'rodjulian.com') {clickIfElementExists('a.btn.btn-primary.btn-lg.get-link', 5, 'setInterval');} else if (location.href.indexOf("ay.live") != -1 || location.href.indexOf("aylink.co") != -1 || location.href.indexOf("gitlink.pro") != -1) { var form = $('#go-link'); + $.ajax({type: 'POST', async: true, url: form.attr('action'), data: form.serialize(), dataType: 'json', success: function(data) {redirect(data.url);}});} else if (elementExists('#go-link')) {$("#go-link").unbind().submit(function(e) {e.preventDefault(); var form = $(this); var url = form.attr('action'); const pesan = form.find('button'); const notforsale = $(".navbar-collapse.collapse"); const blogger = $(".main-header"); const pemula = $(".col-sm-6.hidden-xs"); + $.ajax({type: "POST", url: url, data: form.serialize(), beforeSend: function(xhr) { pesan.attr("disabled", "disabled"); $('a.get-link').text('Bypassed by Bloggerpemula'); + notforsale.replaceWith(''); + blogger.replaceWith(''); + pemula.replaceWith('');}, success: function(result, xhr) {location.href=respect+result.url;}});});} + const bas = (h => { const result = { isNotifyNeeded: false, redirectDelay: 0, link: undefined }; + switch (h.host) {case 'bas.nurul-huda.or.id': case 'rotator.nurul-huda.sch.id': if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('sn')) { + result.link = h.searchParams.get('url') + '&sn=' + h.searchParams.get('sn').replace('&m=1', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('sub_id') && h.searchParams.has('site_id') && h.searchParams.has('ip_address')) { + result.link = h.searchParams.get('url') + '&sub_id=' + h.searchParams.get('sub_id') + '&site_id=' + h.searchParams.get('site_id') + '&ip_address=' + h.searchParams.get('ip_address'); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('X-Amz-Algorithm') && h.searchParams.has('X-Amz-Credential') && h.searchParams.has('X-Amz-Date') && h.searchParams.has('X-Amz-SignedHeaders') && h.searchParams.has('X-Amz-Expires') && h.searchParams.has('X-Amz-Signature')) { + result.link = h.searchParams.get('url') + '&X-Amz-Algorithm=' + h.searchParams.get('X-Amz-Algorithm') + '&X-Amz-Credential=' + h.searchParams.get('X-Amz-Credential') + '&X-Amz-Date=' + h.searchParams.get('X-Amz-Date') + '&X-Amz-SignedHeaders=' + h.searchParams.get('X-Amz-SignedHeaders') + '&X-Amz-Expires=' + h.searchParams.get('X-Amz-Expires') + '&X-Amz-Signature=' + h.searchParams.get('X-Amz-Signature'); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('ssa') && h.searchParams.has('id')) { + result.link = h.searchParams.get('url') + '&ssa=' + h.searchParams.get('ssa') + '&id=' + h.searchParams.get('id').replace('&m=1', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('id')) { + result.link = h.searchParams.get('url') + '&id=' + h.searchParams.get('id').replace('&m=1', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('article')) { + result.link = h.searchParams.get('url') + '&article=' + h.searchParams.get('article').replace('&m=1', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('antibot')) { + result.link = h.searchParams.get('url') + '&antibot=' + h.searchParams.get('antibot').replace('&m=1', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('code')) { + result.link = h.searchParams.get('url') + '&code=' + h.searchParams.get('code').replace('&m=1', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.searchParams.has('viewed')) { + result.link = h.searchParams.get('url') + '&viewed=' + h.searchParams.get('viewed').replace('&m=1', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.pathname === '/shortlink.php' && h.searchParams.has('sl')) { + result.link = h.searchParams.get('url') + 'sl' + h.searchParams.get('sl').replace('&m=1', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.href.includes('#')) { + result.link = h.searchParams.get('url') + $(location).attr('hash'); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; + } else if (h.pathname === '/' && h.searchParams.has('url') && h.href.includes('bloogerspoot.')) {window.location.assign('https://softindex.website'+ (location.search).substring(27)); + } else if (h.pathname === '/' && h.searchParams.has('url') && h.href.includes('gos2.urlcash')) {window.location.assign('https://urlcash.click'+ (location.search).substring(31)); + } else if (h.pathname === '/' && h.searchParams.has('url')) { + result.link = h.searchParams.get('url').replace('&m=1', '').replace('
', ''); result.redirectDelay = 5; result.isNotifyNeeded = true; return result; } break; + default: break;}})(new URL(location.href)); + if (bas) { const { isNotifyNeeded, redirectDelay, link } = bas; + if (isNotifyNeeded) { notify(`Please Wait a moment .....You will be Redirected to Your Destination in ${redirectDelay} seconds`);} + setTimeout(() => {location.href = link;}, redirectDelay * 1000);} + const l = (h => {const b = h.pathname === '/verify/' && /^\?([^&]+)/.test(h.search); const p = h.pathname === '/blog3/verify/' && /^\?([^&]+)/.test(h.search); + switch (h.host) {case 'okrzone.com': if (b) { meta('https://gtlink.co/' + RegExp.$1);} break; + case 'ezimg.co': if (b) { meta('https://eng.ezimg.co/' + RegExp.$1);} break; + case 'educur.com': if (b) { meta('https://blog.flyrar.com/' + RegExp.$1);} break; + case 'tecmundo.net': if (b) { meta('https://go.jaelink.us/' + RegExp.$1);} break; + case 'examkhata.com': if (b) { meta('https://playlink.xyz/' + RegExp.$1);} break; + case 'examsolution.in': if (b) { meta('https://kukslincs.xyz/' + RegExp.$1);} break; + case 'mytop5.club': if (b) { meta('https://technemo.xyz/blog/' + RegExp.$1);} break; + case 'ledifha.com': if (b) { meta('https://process.ledifha.com/' + RegExp.$1);} break; + case 'adybrands.in': if (b) { meta('https://mytop5.club/verify/?' + RegExp.$1);} break; + case 'forexshare.net': if (b) { meta('https://shorturl.sh2rt.com/' + RegExp.$1);} break; + case 'www.lootcash.vip': if (b) { meta('https://ads.lootcash.vip/' + RegExp.$1);} break; + case 'www.allcryptotips.com': if (b) { meta('https://zenshort.com/' + RegExp.$1);} break; + case 'gamerfang.in': if (b) { meta('https://faux.gamerfang.in/tech/' + RegExp.$1);} break; + case 'economiarelevante.com.br': if (b) { meta('https://shrinkgold.com/' + RegExp.$1);} break; + case 'techrayzer.com': if (b) { meta('https://techrayzer.com/insurance/' + RegExp.$1);} break; + case 'teerclub.com': if (b) { meta('https://www.allcryptotips.com/verify/?' + RegExp.$1);} break; + case 'techboyz.xyz': case 'studystar.xyz': if (b) { meta('https://short2fly.xyz/' + RegExp.$1);} break; + case 'zuba.link': if (/^\/([^\/]+)/.test(h.pathname)) { return 'https://go.zuba.link/' + RegExp.$1; } break; + case 'faucethub.ly': if (/^\/hs\/\/([^\/]+)/.test(h.pathname)) {return 'https://goads.ly/' + RegExp.$1;}break; + case 'cekip.site': case 'www.cekip.site': if (/^\/go\/([^\/]+)/.test(h.pathname)) { meta(atob(RegExp.$1));} break; + case 'sl.easysl.click': if (/^\/step1\/([^\/]+)/.test(h.pathname)) {return 'https://easysl.click/' + RegExp.$1;}break; + case 'www.gifans.com': if (/^\/link\/([^\/]+)/.test(h.pathname)) {return 'https://shortlink.prz.pw/' + RegExp.$1;}break; + case 'zonearn.biz': if (/^\/(.+)/.test(h.pathname) && h.searchParams.has('tok')) {return h.searchParams.get('tok');}break; + case 'nulledsafe.com': if (/^\/link\/([^\/]+)/.test(h.pathname)) {return 'https://golink.nulledsafe.com/' + RegExp.$1;}break; + case 'step0.shortlinks.click': if (/^\/([^\/]+)/.test(h.pathname)) { return 'https://shortlinks.click/' + RegExp.$1; } break; + case 'crypto-faucet.xyz': if (/^\/bitco\/link\/([^\/]+)/.test(h.pathname)) {return 'https://doctor-groups.com/link/' + RegExp.$1;}break; + case 'www.meykmen.com': if (h.searchParams.has('url')) {return 'https://arabplus2.co/' + h.searchParams.get('url').substring(22);} break; + //case 'studyuo.com': if (h.pathname === '/pro2/verify/' && /^\?([^&]+)/.test(h.search)) { meta('https://csd.xmod.in/' + RegExp.$1);} break; + case 'horrorbitcoin.com': if (h.searchParams.has('dex')) { meta('https://panylink.com//' + h.searchParams.get('dex').substring(1));} break; + case 'techmody.io': if (h.pathname === '/' && h.searchParams.has('check')) { meta(decodeURIComponent(h.searchParams.get('check')));} break; + case 'froggyreviews.com': if (h.searchParams.has('mflink')) { meta('https://froggyreviews.com/go/' + h.searchParams.get('mflink'));} break; + case 'xmod.in': if (h.pathname === '/blog/verify/' && /^\?([^&]+)/.test(h.search)) { meta('https://mytop5.club/verify/?' + RegExp.$1);} break; + case 'bingeflix.xyz': if (h.pathname === '/' && h.searchParams.has('link')) {meta ('https://linkyearn.com/' + h.searchParams.get('link'));}break; + case 'hosting4lifetime.com': if (h.pathname === '/blog/verify/' && /^\?([^&]+)/.test(h.search)) { meta('https://abcshort.com/' + RegExp.$1);} break; + case 'acortame.xyz': if (window.location.hash) {location.href ="https://rotator.nurul-huda.sch.id/?url="+(atob(window.location.hash.substr(1)));} break; + case 'blog.textpage.xyz': if (h.searchParams.has('ajhvgadhdhgkdsvkd')) { meta('https://short.url2go.in/' + h.searchParams.get('ajhvgadhdhgkdsvkd'));} break; + case 'my.dropz.xyz': if ( h.href.includes('/checkpoint') && location.search === '') { return 'https://my.dropz.xyz/checkpoint?redir=/site-friends'; } break; + case 'gadgets.techymedies.com': if (h.pathname === '/' && h.searchParams.has('token')) { meta('https://blog.disheye.com/' + h.searchParams.get('token'));} break; + case 'short.clickscoin.com': case 'watchdoge.xyz': case 'dogeclick.net': if (/^\/ccsl\/([^/]+)/.test(h.pathname)) {return 'https://ccsl.xyz/' + RegExp.$1;}break; + case 'patak.dropz.xyz': if ( h.href.includes('/checkpoint') && location.search === '') { return 'https://patak.dropz.xyz/checkpoint?redir=/site-friends'; } break; + case 'jrlinks.in': if (h.pathname === '/safe2.php' && h.searchParams.has('link')) { meta('https://internet.webhostingtips.club/' + h.searchParams.get('link'));} break; + case 'crazyblog.in': case 'www.crazyblog.in': if (h.pathname === '/xhod/verify/' && /^\?([^&]+)/.test(h.search)) { meta('https://redd.crazyblog.in/' + RegExp.$1);} break; + case 'blog.urlbharat.xyz': if (h.pathname === '/safe.php' && h.searchParams.has('link')) { return 'https://get.urlbharat.xyz/safe.php?link=' + h.searchParams.get('link');} break; + case 'short2fly.xyz': case 'cbshort.com': if ( h.searchParams.has('url') && h.href.includes('bloogerspoot.') ) {window.location.assign('https://softindex.website'+ (location.search).substring(147));} break; + case 'dogeclick.net': if (/^\/short\/([^/]+)/.test(h.pathname)) {return 'https://short.clickscoin.com/' + RegExp.$1;} else if (/^\/ccsl\/([^/]+)/.test(h.pathname)) {return 'https://ccsl.xyz/' + RegExp.$1;}break; + case 'clickscoin.com': if (/^\/short\/([^/]+)/.test(h.pathname)) { return 'https://short.clickscoin.com/' + RegExp.$1;} else if (/^\/shortccsl\/([^/]+)/.test(h.pathname)) { return 'https://ccsl.xyz/' + RegExp.$1;} break; + case 'blog.crazyblog.in': if (/^\/step\d+?\/([^/]+)$/.test(h.pathname)) {return 'https://wplink.online/' + RegExp.$1;} else if (/^\/visit\d+?\/step\d+?\/([^/]+)$/.test(h.pathname)) {return 'https://cblink.crazyblog.in/' + RegExp.$1;}break; + case 'anime.dutchycorp.space': case 'movies.dutchycorp.space': case 'tech.dutchycorp.space': case 'cool-time.dutchycorp.space': if (/^\/redir[^.]+?\.php$/.test(h.pathname) && h.searchParams.has('code')) {return h.searchParams.get('code') + '?verif=0';}break; + case 'kiiw.icu': if (h.pathname === '/check.php' && h.searchParams.has('alias')&& h.searchParams.has('wis')&& h.searchParams.has('siw')){ return 'https://kiiw.icu/' + h.searchParams.get('alias')+ '?wis=' + h.searchParams.get('wis')+ '&siw=' + h.searchParams.get('siw');} break; + case 'ls2earn.in': if ( h.searchParams.has('url') && h.href.includes('bloogerspoot.') ) {window.location.assign('https://softindex.website'+ (location.search).substring(130));} else if (h.searchParams.has('api') && h.searchParams.has('url')) {return h.searchParams.get('url');} break; + case 'ls2earn.com': case 'besturl.link': if ( h.searchParams.has('url') && h.href.includes('bloogerspoot.') ) {window.location.assign('https://softindex.website'+ (location.search).substring(144));} else if (h.searchParams.has('api') && h.searchParams.has('url')) {return h.searchParams.get('url');} break; + case 'shrinkearn.com': case 'clk.sh': if ( h.searchParams.has('url') && h.href.includes('bloogerspoot.') ) {window.location.assign('https://softindex.website'+ h.searchParams.get('url').substring(22));} else if (h.searchParams.has('api') && h.searchParams.has('url')) {return h.searchParams.get('url');} break; + case 'birdurls.com': case 'linkrex.net': case 'softindex.website': case 'dash-free.com': case 'owllink.net': case 'exe.io': if (h.searchParams.has('url') && h.href.indexOf('#')) { return 'https://' + h.searchParams.get('url') + h.href.substr(h.href.indexOf('#')); } else if (h.searchParams.has('api') && h.searchParams.has('url')) {return h.searchParams.get('url');} break; + case 'usalink.io': if ( h.searchParams.has('url') && h.href.includes('bloogerspoot.') ) {window.location.assign('https://softindex.website'+ (location.search).substring(219));} else if (h.searchParams.has('url') && h.href.includes('mineshor.')) {return 'https://' + h.searchParams.get('url');} else if (h.searchParams.has('url') && h.href.indexOf('#')) { return 'https://' + h.searchParams.get('url') + h.href.substr(h.href.indexOf('#')); } else if (h.searchParams.has('api') && h.searchParams.has('url')) {return h.searchParams.get('url');} break; + default: break;} })(new URL(location.href)); if (l) {location.href = l; } + let apiBypassVip = {selectors: ['#stepid', '.locked', '#steps', '#link', '#targetbtn', '#theLinkID', '.locked-button'], + re: /mboost\.me|letsboost\.net|social-unlock\.com|boostme\.link|sub2unlock\.net|sub2unlock\.com/,}; + for (let i = 0; i < apiBypassVip.selectors.length; i++) {BypassedByBloggerPemula(apiBypassVip.re, function() {if (elementExists(apiBypassVip.selectors[i])) {fetch('https://api.bypass.vip/',{"headers": {"content-type":"application/x-www-form-urlencoded; charset=UTF-8","x-requested-with":"XMLHttpRequest"},"body":new URLSearchParams({url:document.URL}),"method":"POST",}).then(res=>res.json()).then(res=>{if(res.status!=="success") {redirect(res.destination);}});}});} + BloggerPemula('kienthucrangmieng.com|coindoog.com|tieutietkiem.com|askpaccosi.com|shopsixseven.com|hoclamdaubep.com|thuocdangian.net|chinhnhacoban.com|coin-free.com|fanclup.info|chamcuuhoc.com|nhacremix.biz|doanvanhai.biz|conghuongtu.net|95news.com|tremamnon.com|hynews.biz', 'wpsafelink', '', false); + BloggerPemula('soft3arbi.com', 'link', '', false); + BloggerPemula('7apple.net', 'go', 'https://illink.net/', false); + BloggerPemula('niinga.com', 'get', 'https://liinkat.com/', false); + BloggerPemula('m.newhit.me', 'link', 'https://link3s.net/', false); + BloggerPemula('wpking.in', 'link', 'https://o.ovlinks.com/', false); + BloggerPemula('jazbaat.in', 'link', 'https://go.rplinks.in/', false); + BloggerPemula('itechlogic.in', 'link', 'https://go.apurl.in/', false); + BloggerPemula('blog.hostratgeber.de', 'go', 'https://c2g.at/', false); + BloggerPemula('autodime.com', 'go', 'https://go.linkrex.net/', false); + BloggerPemula('techcartz.com', 'link', 'https://ads.mdlink.in/', false); + BloggerPemula('1apple.xyz', 'link', 'https://link.turkdown.com/', false); + BloggerPemula('kerdlinfo.in', 'link', 'https://go.lrshortner.com/', false); + BloggerPemula('forextrader.today', 'get', 'https://link2end.com/p/', false); + BloggerPemula('apasih.my.id', 'link', 'https://link.get4llink.com/', false); + BloggerPemula('crickblaze.com', 'getlink', 'https://go.coinadfly.com/', false); + BloggerPemula('videoslyrics.com', 'postid', 'https://ser3.crazyblog.in/', false); + BloggerPemula('claimfey.com|zubatecno.com', 'link', 'https://go.zuba.link/', false); + BloggerPemula('cryptomeloud.com', 'adlinkfly', 'https://links.crypturls.com/', false); + BloggerPemula('crazyblog.in|newsharsh.com', 'postid', 'https://hr.vikashmewada.com//', false); + BloggerPemula('qualitystudymaterial.in', 'link', 'https://thehostingmentor.com/mylink/', false); + BloggerPemula('techloadz.com|sportsmediaz.com', 'link', 'https://link.cloudshrinker.com//', false); + BypassedByBloggerPemula(/ouo.today/, function() {location.href = nextUrl;}); + BypassedByBloggerPemula(/yoshare.net/, function() { bp('#yuidea').submit();}); + BypassedByBloggerPemula(/sharemods.com/, function() { $('#dForm').submit();}); + BypassedByBloggerPemula(/upload.ee/, function() {clickIfElementExists('#d_l', 2);}); + BypassedByBloggerPemula(/specx.me/, function() {clickIfElementExists('.butt', 2);}); + BypassedByBloggerPemula(/tmker.com/, function() { bp('#submit_first_page').submit();}); + BypassedByBloggerPemula(/prx.ee/, function() {clickIfElementExists('#final_link', 1);}); + BypassedByBloggerPemula(/1ink.cc/, function() {clickIfElementExists('#countingbtn', 1);}); + BypassedByBloggerPemula(/up-load.one/, function() {clickIfElementExists('#submitbtn', 1);}); + BypassedByBloggerPemula(/makemoneywithurl.com/, function() { bp('#hidden form').submit();}); + BypassedByBloggerPemula(/evoload.io/, function() {clickIfElementExists('#generatebtn', 1);}); + BypassedByBloggerPemula(/cryptosh.pro/, function() {clickIfElementExists('#EarnButton', 2);}); + BypassedByBloggerPemula(/keeplinks.org/, function() {clickIfElementExists('#btnchange', 2);}); + BypassedByBloggerPemula(/theconomy.me/, {'/': ['link', 'https://link.theconomy.me/'],}, false); + BypassedByBloggerPemula(/punyablog.my.id/, {'/safe.php': ['link', 'https://q8c.xyz/'],}, false); + BypassedByBloggerPemula(/mkomsel.com/, function() {clickIfElementExists('#downloadfile', 12);}); + BypassedByBloggerPemula(/drop.download/, function() {clickIfElementExists('.btn-download', 2);}); + BypassedByBloggerPemula(/jardima.com/, function() {clickIfElementExists('.btn-primary.btn', 3);}); + BypassedByBloggerPemula(/playstore.pw/, function() { $('.col-md- > form:nth-child(1)').submit();}); + BypassedByBloggerPemula(/1shortlink.com/, function() {clickIfElementExists('#redirect-link', 3);}); + BypassedByBloggerPemula(/file-upload.com/, function() {clickIfElementExists('#download-btn', 2);}); + BypassedByBloggerPemula(/mirrored.to/, function() {clickIfElementExists('.larger.secondary', 2);}); + BypassedByBloggerPemula(/forex-trnd.com|gawbne.com/, function() { bp('#exfoary-form').submit();}); + BypassedByBloggerPemula(/modebaca.com/, function() {clickIfElementExists('.btn-success.btn', 1);}); + BypassedByBloggerPemula(/modsfire.com/, function() {clickIfElementExists('.download-button', 2);}); + BypassedByBloggerPemula(/sahityt.com/, {'/verify/': [RexBp, 'https://google.v2links.com/'],}, false); + BypassedByBloggerPemula(/dddrive.me/, function() {clickIfElementExists('.btn-outline-primary', 2);}); + BypassedByBloggerPemula(/medipost.org/, {'/verify/': [RexBp, 'http://links.medipost.org/'],}, false); + BypassedByBloggerPemula(/videolyrics.in/, {'/verify/': [RexBp, 'http://ser3.crazyblog.in/'],}, false); + BypassedByBloggerPemula(/jameeltips.us/, function() {clickIfElementExists('#continue_button_1', 1);}); + BypassedByBloggerPemula(/antonimos.de/, function() {clickIfElementExists('#cbt', 5, 'setInterval');}); + BypassedByBloggerPemula(/techyadjectives.com/, {'/check/': [RexBp, 'https://demo.pvidly.in/'],}, false); + BypassedByBloggerPemula(/usersdrive.com/, function() {clickIfElementExists('.btn-download.btn', 1);}); + BypassedByBloggerPemula(/post.copydev.com/, function() {clickIfElementExists('.btn-success.btn', 6);}); + BypassedByBloggerPemula(/uppit.com/, function() {clickIfElementExists('.btn-primary.btn-xl.btn', 2);}); + BypassedByBloggerPemula(/krakenfiles.com/, function() {clickIfElementExists('.download-now-text', 2);}); + BypassedByBloggerPemula(/go.insurglobal.xyz/, {'/': ['link', 'https://link.insurglobal.xyz/'],}, false); + BypassedByBloggerPemula(/adsy.pw|linkpay.cc|wi.cr|pndx.live/, function() { bp('#link-view').submit();}); + BypassedByBloggerPemula(/linegee.net/, function() {clickIfElementExists('.btn-xs.btn-primary.btn', 2);}); + BypassedByBloggerPemula(/zippyshare.com|filedm.com/, function() {clickIfElementExists('#dlbutton', 3);}); + BypassedByBloggerPemula(/bildirim.in|bildirim.eu/, function() {clickIfElementExists('#btnPermission', 1);}); + BypassedByBloggerPemula(/userscloud.com|dosya.co/, function() {clickIfElementExists('#btn_download', 2);}); + BypassedByBloggerPemula(/hexupload.net/, function() {clickIfElementExists('.btn-success.btn-lg.btn', 1);}); + BypassedByBloggerPemula(/solidfiles.com/, function() {clickIfElementExists('.btn-sm.btn-primary.btn', 2);}); + BypassedByBloggerPemula(/faucetpay.io/, function() {clickIfElementExists('.btn-block.btn-primary.btn', 3);}); + BypassedByBloggerPemula(/get.urlbharat.xyz/, {'/safe.php': ['link', 'https://video.earnspace.in/'],}, false); + BypassedByBloggerPemula(/insurance-space.xyz/, {'/': ['link', 'https://link.insurance-space.xyz/'],}, false); + BypassedByBloggerPemula(/dailyuploads.net/, function() {clickIfElementExists('.inner > a:nth-child(9)', 2);}); + BypassedByBloggerPemula(/files.im/, function() {clickIfElementExists('.btn-dow.btn', 2);bp('#F1').submit();}); + BypassedByBloggerPemula(/cooklike.info|model-tas-terbaru.com/, {'/': ['link', 'https://yousm.link/'],}, false); + BypassedByBloggerPemula(/lets.5get.net/, function() {clickIfElementExists('.jump_link > a:nth-child(1)', 2);}); + BypassedByBloggerPemula(/cshort.org/, function() {clickIfElementExists('.timer.redirect', 3, 'setInterval');}); + BypassedByBloggerPemula(/megaupto.com/, function() {clickIfElementExists('#direct_link > a:nth-child(1)', 2);}); + BypassedByBloggerPemula(/blog-everything.com/, function() {clickIfElementExists('button.btn.btn-warning', 3);}); + BypassedByBloggerPemula(/delishwell.com|artiskini.com/, {'/': ['link', 'https://link.paid4link.net/'],}, false); + BypassedByBloggerPemula(/tinyurl.so/, function() {clickIfElementExists('.btn.btn-secondary', 3, 'setInterval');}); + BypassedByBloggerPemula(/douploads.net/, function() {clickIfElementExists('.btn-primary.btn-lg.btn-block.btn', 2);}); + BypassedByBloggerPemula(/takem.co|themorningtribune.com/, {'/verify/': [RexBp, 'https://push.bdnewsx.com/'],}, false); + BypassedByBloggerPemula(/informaxonline.com|gaminplay.com/, {'/': ['link', 'https://go.adslinkfly.online/'],}, false); + BypassedByBloggerPemula(/webhostingtips.club/, {'/safe.php': ['link', 'https://jrlinks.in/safe2.php?link='],}, false); + BypassedByBloggerPemula(/litecoin.host|skipads.click/, function() {clickIfElementExists('#wBtn', 3, 'setInterval');}); + BypassedByBloggerPemula(/ponselharian.com/, function() {if (elementExists('#link-view')) {window.scrollTo(0,9999);}}); + BypassedByBloggerPemula(/techrfour.com|veganal.co|veganho.co/, {'/go/': [RexBp, 'https://push.bdnewsx.com/'],}, false); + BypassedByBloggerPemula(/linkerload.com/, function() {clickIfElementExists("#download form input[id='button1']", 2);}); + BypassedByBloggerPemula(/ayelads.com/, function() {clickIfElementExists('.btn-bl.btn-primary.btn', 5, 'setInterval');}); + BypassedByBloggerPemula(/mp4upload.com/, function() {clickIfElementExists('#todl', 2);$("form[name='F1']").submit();}); + BypassedByBloggerPemula(/adfoc.us/, function() {if (elementExists('#skip')) {let adf = bp('.skip').href;redirect(adf);}}); + BypassedByBloggerPemula(/wp.sekilastekno.com/, function() {clickIfElementExists('div > div > button', 3, 'setInterval');}); + BypassedByBloggerPemula(/letsupload.io/, function() {clickIfElementExists('button.btn.btn--primary.type--uppercase', 1);}); + BypassedByBloggerPemula(/informaxonline.com|gaminplay.com/, {'/verify/': [RexBp, 'https://go.adslinkfly.online/'],}, false); + BypassedByBloggerPemula(/largestpanel.in|earnme.club|usanewstoday.club/, function() {clickIfElementExists('#tp-snp2', 1);}); + BypassedByBloggerPemula(/healdad.com|gamalk-sehetk.com/, function() {clickIfElementExists('.submitBtn', 3, 'setInterval');}); + BypassedByBloggerPemula(/assettoworld.com/, function() {clickIfElementExists('.text-capitalize.btn-outline-success.btn', 3);}); + BypassedByBloggerPemula(/chooyomi.com|blogmado.com/, () => waitForElm(".get-link > a:nth-child(1)", cho => redirect(cho.href))); + BypassedByBloggerPemula(/bestfonts.pro/, () => waitForElm(".download-font-button > a:nth-child(1)", pro => redirect(pro.href))); + BypassedByBloggerPemula(/cutt.net|cut-y.net|cutty.app/, function() {clickIfElementExists('#submit-button', 5, 'setInterval');}); + BypassedByBloggerPemula(/docs.google.com/, function() {if (elementExists('#uc-dl-icon')) {bp('#downloadForm').submit();} else {}}); + BypassedByBloggerPemula(/workupload.com/, function() {if (elementExists('#download')) {clickIfElementExists('.btn-prio.btn', 2);}}); + BypassedByBloggerPemula(/techus.website/, function() { $('.code-block-4.code-block > form').submit();$('.topnav > form').submit();}); + BypassedByBloggerPemula(/1link.club/, function() {$("a[target='_blank']").removeAttr("target");clickIfElementExists('#download', 1);}); + BypassedByBloggerPemula(/zegtrends.com/, function() {clickIfElementExists('#go', 3);clickIfElementExists('.bsub', 3, 'setInterval');}); + BypassedByBloggerPemula(/forex-articles.com|forexlap.com|forexmab.com/, function() {clickIfElementExists('.oto > a:nth-child(1)', 1);}); + BypassedByBloggerPemula(/linkspy.cc/, function() {if (elementExists('.skipButton')) {let lsp = bp('.skipButton').href;redirect(lsp);}}); + BypassedByBloggerPemula(/automotur.club|sanoybonito.club/, function() {clickIfElementExists('.g-recaptcha', 3);bp('#page2').submit();}); + BypassedByBloggerPemula(/uploadhaven.com/, function() {clickIfElementExists('.alert > a:nth-child(1)', 2);bp('#form-download').submit();}); + BypassedByBloggerPemula(/cashearn.cc|bitlinks.pw/, function() {clickIfElementExists('.next-button.btn-lg.btn-info.btn', 3, 'setInterval');}); + BypassedByBloggerPemula(/upfiles.app|cut-y.co/, function() {if (elementExists('#captchaDownload')) {}else{bp('form.text-center').submit();}}); + BypassedByBloggerPemula(/pythondunyasi.com/, () => waitForElm("#countdown3 > span:nth-child(1) > a:nth-child(1)", pit => redirect(pit.href))); + BypassedByBloggerPemula(/litexblog.com/, function() {if (elementExists('.g-recaptcha')) {}else{clickIfElementExists('.bg-primary.btn', 5);}}); + BypassedByBloggerPemula(/bcvc.xyz|bcvc.ink/, function() {clickIfElementExists('.js-scroll-trigger.btn-xl.btn-outline.btn', 3, 'setInterval');}); + BypassedByBloggerPemula(/racedepartment.com/, function() {$("a[target='_blank']").removeAttr("target");clickIfElementExists('.button--cta', 2);}); + BypassedByBloggerPemula(/hxfile.co|ex-load.com|megadb.net/, function() {clickIfElementExists('.btn-dow.btn', 2);bp("form[name='F1']").submit();}); + BypassedByBloggerPemula(/tinyurl.is/, function() {if (elementExists('ul > li > a')) {const link = bp('a[id^=newskip-btn]').href;redirect(link);}}); + BypassedByBloggerPemula(/mega4up.org/, function() {clickIfElementExists('input.btn.btn-info.btn-sm', 2);clickIfElementExists('.btn-dark.btn', 2);}); + BypassedByBloggerPemula(/uploadev.org/, function() {clickIfElementExists('#dspeed > input:nth-child(3)', 1); clickIfElementExists('.directl', 1);}); + BypassedByBloggerPemula(/bayfiles.com|anonfiles.com|openload.cc|lolabits.se|letsupload.cc/, function() {clickIfElementExists('#download-url', 2);}); + BypassedByBloggerPemula(/fx4vip.com/, function() {$("a #button1[disabled='disabled']").removeAttr("disabled");clickIfElementExists('#button1', 2);}); + BypassedByBloggerPemula(/altblogger.net/, function() {clickIfElementExists('.form-send.m-2.btn-captcha.btn-outline-primary.btn', 3, 'setInterval');}); + BypassedByBloggerPemula(/satoshi-win.xyz|shorterall.com|promo-visits.site/, function() {clickIfElementExists('.box-main > button:nth-child(3)', 1);}); + BypassedByBloggerPemula(/mynewsmedia.co/, function() {clickIfElementExists('#myBtn.cssBtn.myBtn', 3);clickIfElementExists('#nxBtn.cssBtn.nxBtn', 5);}); + BypassedByBloggerPemula(/btcpany.com|zombiebtc.com|blog.zubatecno.com|news.claimfey.com|battleroyal.online/, function() { bp('#link1s-form').submit();}); + BypassedByBloggerPemula(/send.cm|racaty.net|files.im|sharemods.com|clicknupload.to|modsbase.com/, function() {clickIfElementExists('#downloadbtn', 1);}); + BypassedByBloggerPemula(/sub2get.com/, function() {if (elementExists('#butunlock')) {let subt = bp('#butunlock > a:nth-child(1)').href;redirect(subt);}}); + BypassedByBloggerPemula(/takefile.link/, function() {if (elementExists('#F1')) {bp('div.no-gutter:nth-child(2) > form:nth-child(1)').submit();} else {}}); + BypassedByBloggerPemula(/claimclicks.com/, function() {clickIfElementExists('div.col-md-12:nth-child(2) > form:nth-child(11) > button:nth-child(4)', 2);}); + BypassedByBloggerPemula(/ac.totsugeki.com/, function() {$("a[target='_blank']").removeAttr("target");clickIfElementExists('.btn-lg.btn-success.btn', 2);}); + BypassedByBloggerPemula(/fexkomin.xyz/, function() {$("a[target='_blank']").removeAttr("target");clickIfElementExists('.btn-captcha.btn-danger.btn', 3);}); + BypassedByBloggerPemula(/uptobhai.info|shortlinkto.info|uplinkto.vip|brbushare.info/, function() {clickIfElementExists('.btn-block.btn-primary.btn', 2);}); + BypassedByBloggerPemula(/rancah.com|menjelajahi.com|shortly.xyz/, function() {clickIfElementExists('.get-link.btn-lg.btn-success.btn', 5, 'setInterval');}); + BypassedByBloggerPemula(/shortit.pw/, function() {clickIfElementExists('.pulse.btn-primary.btn', 5);clickIfElementExists('a#btn2.btn.btn-primary.pulse', 3);}); + BypassedByBloggerPemula(/theprice.biz|massive.my.id|activity.my.id|caview.my.id/, function() {clickIfElementExists('a.btn.btn-primary.m-2.btn-captcha', 6);}); + BypassedByBloggerPemula(/upload-4ever.com/, function() {clickIfElementExists("input[name='method_free']", 2);clickIfElementExists('#downLoadLinkButton', 5);}); + BypassedByBloggerPemula(/fileshare.adshorturl.com/, function() {clickIfElementExists('.download-timer > a:nth-child(1) > span:nth-child(1)', 4, 'setInterval');}); + BypassedByBloggerPemula(/1fichier.com/, function() {if (elementExists('#pass')){}else {clickIfElementExists('.btn-orange.btn-general.ok', 1);bp('.alc').submit();}}); + BypassedByBloggerPemula(/proviralhost.com|examtadka.com/, function() {clickIfElementExists('#wait1button', 3);clickIfElementExists('#wait2button', 5, 'setInterval');}); + BypassedByBloggerPemula(/healdad.com|gamalk-sehetk.com|newforex.online|forex-gold.net|world-trips.net|mobi2c.com/, function() {clickIfElementExists('.submitBtn', 2);}); + BypassedByBloggerPemula(/adsgo.digital|newsnowbd.com|techus.website/, function() {clickIfElementExists('.myButton', 2); $('.code-block-1.code-block > form').submit();}); + BypassedByBloggerPemula(/anonym.ninja/, function() {var fd = window.location.href.split('/').slice(-1)[0];redirect(`https://anonym.ninja/download/file/request/${fd}`);}); + BypassedByBloggerPemula(/uptobox.com/, function() {clickIfElementExists('a.big-button-green:nth-child(1)', 2); clickIfElementExists('.download-btn', 3, 'setInterval');}); + BypassedByBloggerPemula(/on-scroll.com|diudemy.com/, function() {clickIfElementExists('.blog_btn.show_btn', 3);waitForElm("#next", roll => redirect(roll.href, false));}); + BypassedByBloggerPemula(/stfly.me/, function() {if (elementExists('.g-recaptcha')) {}else{clickIfElementExists('.form-send.m-2.btn-captcha.btn-outline-primary.btn', 3);}}); + BypassedByBloggerPemula(/i-polls.com/, function() {clickIfElementExists('button#btn', 2);clickIfElementExists('#anchor_button', 2);clickIfElementExists('a#safe_link', 30);}); + BypassedByBloggerPemula(/suratresmi.id/, function() {clickIfElementExists('button#hmn.btn-more', 3, 'setInterval');clickIfElementExists('a#hmn.btn-more',3, 'setInterval');}); + BypassedByBloggerPemula(/blog-forall.com/, function(){var bypasslinks = atob(`aH${bp("#landing [name='go']").value.split("aH").slice(1).join("aH")}`); redirect(bypasslinks);}); + BypassedByBloggerPemula(/olamovies.cyou/, function() {let omo = document.getElementsByTagName("script")[1].innerText.split("\n")[8].split(" ")[3].split("\"")[1];redirect(omo);}); + BypassedByBloggerPemula(/apkadmin.com/, function() {clickIfElementExists('.text > a:nth-child(4) > img:nth-child(1)', 1);bp('.download-file-button > form:nth-child(1)').submit();}); + BypassedByBloggerPemula(/newsharsh.com/, {'/box-office/verify/': [RexBp, 'https://hr.vikashmewada.com/'],'/english/verify/': [RexBp, 'https://crazyblog.in/harsh/verify/?'],}, false); + BypassedByBloggerPemula(/writedroid.in/, function() {clickIfElementExists('#shortPostLink', 5);clickIfElementExists('#showModalAds', 3);clickIfElementExists('#shortGoToLink.button', 5);}); + BypassedByBloggerPemula(/vosan.co/, function() {$("a[target='_blank']").removeAttr("target");clickIfElementExists('.elementor-size-lg', 2);clickIfElementExists('.wpdm-download-link', 2);}); + BypassedByBloggerPemula(/4shared.com/, function() {clickIfElementExists('.jsDownloadButton', 2);if (elementExists('.freeDownloadButton')) {bp("form[name^='redirectToD3Form']").submit();}}); + BypassedByBloggerPemula(/riadcrypto.com|donia2tech.com/, function() {var form = document.getElementById('wpsafelink-landing'); redirect(JSON.parse(atob(form.newwpsafelink.value)).linkr);}); + BypassedByBloggerPemula(/mobi2c.com|newforex.online|world-trips.net|forex-gold.net|healdad.com|gamalk-sehetk.com|mobitaak.com/, function() {clickIfElementExists('#go_d', 3, 'setInterval');}); + BypassedByBloggerPemula(/enit.in|clk.asia|clicksfly.com/, function() {var linkbypass = atob(`aH${bp("#link-view [name='token']").value.split("aH").slice(1).join("aH")}`);redirect(linkbypass);}); + BypassedByBloggerPemula(/daga88.today/, function() {if (elementExists('#traffic-countdown-1s')) {const daga = document.querySelectorAll('#wrapper'); for (const element of daga) {element.remove();}}}); + BypassedByBloggerPemula(/solarchaine.com/, function() {if (elementExists('#captchaShortlink')) {clickIfElementExists('button.btn:nth-child(4)', 2);} else {bp('.box-body > form:nth-child(2)').submit();}}); + BypassedByBloggerPemula(/rodjulian.com/, function() {if (elementExists('#traffic-countdown-1s')) {const roju = document.querySelectorAll('.site-content'); for (const element of roju) {element.remove();}}}); + BypassedByBloggerPemula(/uploadrar.com|chedrive.com|uptomega.me/, function() {clickIfElementExists('.mngez-free-download', 2);clickIfElementExists('#direct_link > a:nth-child(1)', 2);$('#downloadbtn').click();}); + BypassedByBloggerPemula(/azmath.info|aztravels.net|techacode.com/, () =>{if (elementExists('#megaurl-verified-captcha')) {clickIfElementExists('button.h-captcha', 3);} else {submit("#megaurl-banner-page", 5);}}); + BypassedByBloggerPemula(/studyuo.com/, {'/pro/': ['link', 'https://shrinkpay.crazyblog.in'],'/short/verify/': [RexBp, 'https://redd.crazyblog.in'], '/blog/verify/': [RexBp, 'https://speedynews.xyz/verify/?'],}, false); + BypassedByBloggerPemula(/crazyblog.in/, { '/finance/': ['link', 'https://shrinkpay.crazyblog.in'],'/hars/verify/': [RexBp, 'https://redd.crazyblog.in'], '/harsh/verify/': [RexBp, 'https://ser3.crazyblog.in/'],}, false); + BypassedByBloggerPemula(/9xupload.asia/, function() {clickIfElementExists('#container > table:nth-child(15) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(1) > a:nth-child(1)', 2);$("form[name='F1']").submit();}); + BypassedByBloggerPemula(/nathanaeldan.pro|freddyoctavio.pro|davisonbarker.pro/, function() { var urls = new URL(document.URL); var dest = urls.searchParams.get("dest"); var decoded = decodeURI(dest);redirect(decoded);}); + BypassedByBloggerPemula(/rekonise.com/, ()=>{let xhr=new XMLHttpRequest();xhr.onload=()=>redirect(JSON.parse(xhr.responseText).url);xhr.open("GET","https://api.rekonise.com/unlocks"+location.pathname,true);xhr.send();}); + BypassedByBloggerPemula(/wrbloggers.com/, () => {if (elementExists('div.col-sm-4')){clickIfElementExists('.btn-danger.btn-block.btn', 2);}else{var ju = setInterval( () => {click("#nextpagelink"); clearInterval(ju);},3000);}}); + BypassedByBloggerPemula(/cutin.it/, function() {let tin = [...document.getElementsByTagName("script")].filter(elem => elem.innerText !== "")[3].innerText.split("\n")[14].split(" ")[9].replace(";", "").replaceAll("\"", "");redirect(tin);}); + BypassedByBloggerPemula(/playnano.online/, function() {clickIfElementExists('#watch-link', 2);clickIfElementExists('.watch-next-btn.btn-primary.button', 2);clickIfElementExists('button.button.btn-primary.watch-next-btn', 5, 'setInterval');}); + BypassedByBloggerPemula(/wiki-topia.com/, function() {if (elementExists('.g-recaptcha')) {}else{clickIfElementExists("input[style^='font-weight: 700']", 2, 'setInterval');clickIfElementExists("input[style^='font-weight: 500']", 3, 'setInterval');}}); + BypassedByBloggerPemula(/mediafire.com/, function() {var bass; var md = function closeWindows(){window.close(); clearInterval(bass);};var mf = bp('.download_link .input').getAttribute('href'); console.log(mf); location.replace(mf); bass = setInterval(md, 1000 * 5);}); + BypassedByBloggerPemula(/dutchycorp.space|dutchycorp.ovh|gtlink.co|fc-lc.com|mdn.rest|antonimos.de|ctbl.me|zshort.cc|feyyora.fun|twitonet.com|oii.io/, function() {var ticker = setInterval(function(){ try{window.grecaptcha.execute(); clearInterval(ticker);} catch(e) {}},3000);}); + BypassedByBloggerPemula(/ytsubme.com/, function() {if (elementExists('.cont1')) {let ytsub = bp("#msg-box3-o > div > div > div.col-md-4.text-center > div > div > div > div.col-md-8.col-md-offset-2.text-xs-center > div > div > script").innerHTML.split(';')[7].split('=')[1].replaceAll('\'', "");redirect(ytsub);}}); + BypassedByBloggerPemula(/faucet.work|techlearningtube.in|wildblog.me|blogginglass.com|technoflip.in|arahtekno.com|mopahealth.com|welovecrypto.xyz|crypto-blog.xyz|jiotech.net|crypto4tun.com|adshorturl.com|digitalnaz.net/, function() {var el = document.querySelector("input[name=newwpsafelink]");redirect(JSON.parse(atob(el.value)).linkr);}); + BypassedByBloggerPemula(/linkvertise.com|linkvertise.download/, function() {var linkver = new XMLHttpRequest; linkver.responseType = 'json'; linkver.open('GET', `https://main-bypass-server.tk/v3?${document.location.href.slice(0,-1)}`, !0); linkver.onload = function(n) {4 === linkver.readyState && redirect(this.response.destination);}; linkver.send(null);}); + BypassedByBloggerPemula(/drive.google.com/, function() {var dg = window.location.href.split('/').slice(-2)[0];if (window.location.href.includes('drive.google.com/file/d/')) {redirect(`https://drive.google.com/u/0/uc?id=${dg}&export=download`).replace('
', '');} else if (window.location.href.includes('drive.google.com/u/0/uc?id')) {bp('#downloadForm').submit();} else {}}); + BypassedByBloggerPemula(/adshnk.com|adshrink.it/, () => {let adsh =setInterval(()=>{if(typeof _sharedData=="object"&&0 in _sharedData&&"destination"in _sharedData[0]){clearInterval(adsh);document.write(_sharedData[0].destination);redirect(document.body.textContent);}else if(typeof ___reactjsD!="undefined"&&typeof window[___reactjsD.o]=="object"&&typeof window[___reactjsD.o].dest=="string"){clearInterval(adsh);redirect(window[___reactjsD.o].dest);}});}); + BypassedByBloggerPemula(/99faucet.com|readi.online|cempakajaya.com|freebitcoin.fun|onlineteori.my.id|xtrabits.click|onlineincoms.com|punyablog.my.id|9-animie.co|tribuncrypto.com|bitzite.com|nivaprofit.xyz|videoclip.info|punyamerk.top|lycoslink.com|aduzz.com|soltoshindo.com|techleets.xyz|moddingzone.in|crypto-fi.net|claimcrypto.cc|ourcoincash.xyz|poketoonworld.com|sapica.xyz|chuksblog.fun|liongiv.xyz|bioinflu.com|sonicbtc.com|healthbloog.xyz|pubgquotes.com|m.linkmumet.online|web9academy.com|studyis.xyz/, function(){var bypasslink = atob(`aH${bp("#landing [name='go']").value.split("aH").slice(1).join("aH")}`); redirect(bypasslink, false);}); + if (window.location.hostname==('solvemedia.com') != -1 ){let PHRASES=["1.21 gigawatts","4 8 15 16 23 42","5 dollar shake","6 feet of snow","8th chevron","a wild captcha appears","abelian grape","abide with me","abracadabra","absent without leave","absolute zero","accidentally on purpose","ace of spades","across the board","adapt improve","adapt improve succeed","against the grain","agree to disagree","al capone","all dancing","all grown up","all of the above","all singing","all your base","allergic reaction","almost got it","always there","am i happy","anchors away","and that's the way it is","angel food","another castle","anti dentite","apple juice","apple pie","apple sauce","april may","april showers","are we there yet","are you ready","are you the keymaster","army training","army training sir","around here","as i see it","as you wish","ask questions","attila the hun","auto driving","awesome dude","awesome sauce","azgoths of kria","babel fish","baby blues","baby boomer","baby steps","back to basics","back track","background noise","bacon and eggs","bad books","bad egg","bait the line","baked in a pie","bald eagle","ball of confusion","banana bread","banana split","banana stand","bangers and mash","barber chair","barking mad","basket case","bated breath","bath towel","bath water","battle royale","bazinga","be careful","be mine","be my friend","be nice","be nimble be quick","be serious now","beach ball","bean town","beans and rice","beautiful friendship","bee line","been there","beer in a bottle","beer in the bottle","bees knees","beg the question","believe me","belt up","berlin wall","best fit line","best seller","better call saul","better half","better next time","beyond me","big brother","big kahuna burger","big nose","big screen","bigger in texas","bike rider","bird cage","birthday boy","birthday girl","bizarro jerry","black and white","black coffee","black gold","black jack","black monday","blahblahblah","blaze a trail","bless you","blinded by science","blog this","blood type","blue cheese","blue ribbon","blue sky","bob loblaw","body surfing","boiled cabbage","bon voyage","bond james bond","bone dry","bonus points","bonus round","book reading","book worm","boomerang","born to run","bots are bad m'kay","bottled water","bowties are cool","box jelly fish","box kitty","box of chocolates","braaains","brand spanking new","bread of life","break the ice","brick house","broken heart","broken record","bruce lee","brush your teeth","buckle your shoe","buffalo wing","bunny rabbit","burger with fries","burning oil","burnt sienna","butler did it","butter side down","button fly","buy some time","by and large","by the board","by the book","by the seashore","cabbage borsht","cabbage stew","caesar salad","call me","call me maybe","can i love","can you see","candy apple","candy cane","capital gain","captcha in the rye","car trouble","carbon copy","carbon footprint","card sharp","card-sharp","carpe diem","carry a towel","carry on","cary grant","case closed","cat got your tongue","catch the man","cats and dogs","cats pajamas","chaise lounge","challenge accepted","change the world","change yourself","channel surfing","charley horse","charlie bit me","charm offensive","charmed life","check your coat","check your work","cheese burger","cheese fries","cheese steak","cherry on top","chicken feed","chicken noodle","chicken salad","chicken soup","chin boy","chit chat","choco lazer boom","chocolate cookie","chocolate milk","chow down","chuck norris","circle of life","civil war","clean and shiny","clean hands","clear blue water","clear sailing","click, click, click","cliff hanger","clod hopper","close quarters","cloud nine","clown around","coffee can","cold comfort","cold feet","cold hat","cold shoulder","cold turkey","coleslaw","collaborate and listen","colored paper","come along","come along pond","come back","come clean","come on down","come what may","comfort zone","comma comma","common law","complex number","construction ahead","cookie cutter","cool heads prevail","cop an attitude","cor blimey","cordon bleu","corned beef","cotton on","count your change","counting sheep","covered bridge","crab cake","crayola","cream and sugar","create new things","creative process","creative vision","creepy crawler","crime of passion","crocodile tears","crop up","cross the road","cross the rubicon","cubic spline","cucumber sandwich","cup cake","cupid's arrow","curate's egg","curry favour","cut and run","cut the mustard","dalek asylum","dallas texas","dance all night","danish robot dancers","dark horse","das oontz","david after dentist","dead battery","dead ringer","deal me in","dear cookie","dear mr vernon","dear sir","deep thought","deep waters","dharma initiative","diced onion","diddly squat","digital clock","ding a ling","dinner bell","dinosaur spaceship","dish water","do a little dance","do be do be do","do it now","do more situps","do not touch","do or do not","do unto others","do wah ditty","do you believe in miracles","do you love me","doctor caligari","doctor who","doctor who?","doe a deer","dog days","dog's breakfast","dog's dinner","dogapus","dogs and cats living together","dollar bill","dollar signs","dollars to donuts","domestic spying","don't be late","don't count on it","don't dawdle","don't stop","don't waste time","done that","donkey's years","doodah man","double cross","double crossed","double dutch","double jump","double rainbow","double time","double whammy","down the hatch","down the rabbit hole","downward slope","drag race","dragon with matches","dragonfly","dramatic chipmunk","draw a blank","drawing board","dream big","drink milk","drive me to firenze","drop table users","drumhead","drummer boy","dry clean only","dueling banjos","dusk till dawn","dust bunny","dust up","duvet day","dynamo clock","ear candy","ear mark","ear muffs","easy as cake","easy as pie","easy peasy","easy street","eat cous cous","eat out","eat your dinner","eat your veggies","eat your vitamins","ecks why zee","edgar degas","egg on","eggs ter minate","eighty six","electro head","elevator going up","emperor's clothes","empire state of mind","end of story","english muffin","enjoy life","ermahgerd capcher","evil eye","evil genius","exceedingly well read","exclamation","exercise more","extra cheese","face the music","face to face","fade away","fair and square","fair play","fairy godmother","fairy tale","fait accompli","fall guy","falling pianos","fancy free","fancy pants","far away","farsical aquatic ceremony","fashion victim","fast and loose","fast asleep","father time","father uncle","fathom out","fava beans","feeding frenzy","feeling blue","fellow traveller","fezes are cool","field day","fifth column","fill it up","filthy dirty mess","filthy rich","finagle's law","final answer","finger lickin good","fire brim stone","firecracker","first contact","first post","first water","first world","fish and chips","fish on","fishy smell","flag day","flat foot","flat out","flat tire","flipadelphia","flipflops","flux capacitor","follow me","folsom prison","fool's paradise","fools gold","for keeps","for sure","for the birds","for the gripper","forbidden fruit","foregone conclusion","forget this","forget you","fork knife spoon","forty two","foul play","four by two","frabjous day","france","frankly my dear","free hat","freezing temperatures","french fried","french fries","french phrases","fresh water","fried ices","fried rice","friend zone","frozen peas","fruit salad","fuddy duddy","full house","full monty","full of stars","full stop","full tilt","fun with flags","funny farm","fusilli jerry","fuzzy wuzzy","gadzooks","game is up","gangnam style","garden of eden","garlic yum","gathers moss","gee louise","gee whiz","geez louise","gene parmesan","general tso","generation x","genghis khan","george washington","get out","get over it","get well","get your goat","giant bunny rabbit","giant panda","giddy goat","gift horse","gimme pizza","ginger bread","give or take","glass ceiling","glazed donut","global warming","go berserk","go further","go gadget go","goes to eleven","gold medal","gold record","golly jeepers","gone dolally","gone fishing","good afternoon","good as gold","good buddy","good day","good evening","good for nothing","good grief","good job","good luck","good morning","good night","good night and good luck","good riddance","good samaritan","good work","goody goody gumdrops","goody gumdrop","goody two shoes","goosebumps","gordon bennett","got my mojo","gotham city","gothic arch","gothic church","grain of salt","grand slam","grape soda","grass up","graveyard shift","gravy train","grease the skids","greased lightning","great scott","great unwashed","gregory peck","gridlock","grilled cheese","groundhog day","grumpy cat","guinea pig","guitar player","gum shoe","gung ho","habsons choice","had a great fall","had me at hello","hairy eyeball","halcyon days","half done","half empty","half full","half inch","hallowed ground","halp meh","ham and cheese","hamburger bun","hammer time","hand over fist","hands down","hangers and mash","happy anniversary","happy blessings","happy clappy","happy retirement","happy trails","hard captcha is hard","hard cheese","hard lines","hard sharp","hardened prestoopnicks","harp on","haste makes waste","hat head","hat trick","have a purpose","have an inkling","have courage","have fun","he loves her","head case","head honcho","head over heels","heads up","health food","healthy food","hear hear","hear me roar","heart break","heart strings","heart's content","heartache","heat up","heated debate","heavens to betsy","heavy metal","heebie jeebies","hello newman","hello sweetie","hello watson","hello world","here or there","here's johnny","hey brother","higgledy piggledy","higgs boson","high def","high five","high flyer","high horse","high sleeper","high time","him with her","hissy fit","history repeats itself","hit the hay","hit the sack","hoagie roll","hobby horse","hobson's choice","hocus pocus","hoi polloi","hoity-toity","hold your horses","hold your tongue","home james","honey mustard","hooray henry","hops a daisy","horse and cart","horse's mouth","hot blooded","hot diggity dog","hot dog roll","hot pola","hot sauce","hover hand","how about lunch","how about that","how are you","how interesting","how now, brown cow","how quaint","how sweet","how's it going","howdy partner","hug me","huggle muggle","hulk smash","hunky-dory","hush puppies","i am captcha","i am fine","i am here","i can do this","i can fix it","i have fallen","i know nothing","i like humans","i like people","i like turtles","i like you","i love deadlines","i love lamp","i love you","i made tea","i moustache you why","i saw that","i see","i think i am","i think i can","i think so","i want control","i'll make tea","i'm batman","i'm blessed","i'm blushing","i'm cold brr","i'm only human","i'm so cold","i'm sorry","i'm sorry dave","i'm yours","ice to meet you","idk my bff jill","if it fits","im cold. brr","imagine inspire create","in a box","in limbo","in over my head","in spades","in stitches","in the air","in the box","in the cart","in the club","in the doldrums","in the limelight","industrial revolution","infra dig","inside out","is it enough","is it hot","is it hot?","is it hot in here","is it plugged in","is low","it doesn't count","it happens","it hurts","it is certain","it is enough","it will pass","it's over","it's super effective","ivory tower","jabber wocky","jack be nimble","jam tomorrow","jay gatsby","jerk store","jerry built","jimmy cricket","jimmy horner","john lennon","john steinbeck","jump higher","jump over","jump the candlestick","jump the gun","jumping jack","june july","just dance","just deserts","just drive","just friends","just in time","kangaroo count","karma points","keep calm","keyboard","keyboard cat","khyber pass","kick the can","kick your heels","kindness of strangers","king arthur","kiss me","kitten mittens","kitty kat","klatu berada nikto","knick knack","knock at the door","knock back","knock knock knock penny","knock off","knock on wood","know the ropes","know thy self","know your paradoxes","know your rights","knuckle down","kosher dill","kundalini express","labour of love","ladies first","lager frenzy","lame duck","lardy-dardy","lark about","laser beams","last straw","later gator","laugh at me","law of sines","lawn giland","lazy sunday","leap higher","leaps and bounds","learn challenge improve","learn from mistakes","learn succeed","learn the ropes","learn, advance","leave britney alone","leave me alone","left or right","left right","lefty loosey","less is more","let go","let it be","let me know","let me out","lets eat","level playing field","liberty bell","library book","lickety split","lie low","light sleeper","like a boss","like the dickens","linear algebra","little bird told me","little bobby tables","little did he know","little sister","live free","live in the moment","live in the now","live life","live long + prosper","live love internet","live love type","live transmission","live with purpose","live your dream","living daylights","living things","lizard poisons spock","lo and behold","loaf of bread","local derby","lol cat","lollerskates","lolly pop","london calling","long division","long in the tooth","look away","look before crossing","look both ways","looking glass","lose face","lost love","loud music","love is automatic","love is blind","love life","love me","love you","love-hate","lovey dovey","lucille 2","lucky you","ludwig van","lumpy gravy","lunatic fridge","lunch time","lunch tuesday","mad hatter","mad science","magic decoder ring","magic eight ball","magical realism","magnetic monopole","main chance","major intersection","make a bee line","make haste","make it so","make my day","many happy returns","many wishes","maple syrup","marble rye","marcia marcia marcia","mare's nest","margin of error","mark it zero","market forces","marry me","mars rover","math test","mayan ruins","mea culpa","meat and drink","meat with gravy","meddling kids","media frenzy","melody pond","men in suits","mend fences","meow meow","metropolis","mexican wave","mickey finn","miles to go","milk was a bad choice","milkshake","million dollars","miloko plus","miloko plus vellocet","mimsy borogoves","minced oaths","mind the gap","minty fresh","mish-mash","miss you","mister wilson","modern love","moe's tavern","mom and dad","money lender","moo shoo pork","moon cheese","moot point","more better","more chocolate","more coffee","more cow bell","more internets","morning person","most interesting man","most likely","mother country","mother earth","motley crew","mouth watering","move along","move mountains","move over","moveable feast","movers and shakers","movie star","mrs robinson","muffled rap music","multi pass","mum's the word","mumbo jumbo","murphy's law","mushy peas","music machine","mustachioed","my bad","my beating heart","my better half","my dear watson","my friends can't dance","my mind's eye","my sources say no","naise cain","namby-pamby","name drop","nanoo nanoo","nap time","narrow minded","nautical phrases","ne regrets","near tannhauser gate","neart strings","neckbeard","need a bigger boat","needs must","nercolas cerg","nest egg","never give up","never gonna give you up","never mind","never quit","new york city","nice job","nice marmot","nice to meet you","night owl","nip and tuck","nitty gritty","no brainer","no crying in baseball","no dice","no friend of mine","no holds barred","no means no","no regrets","no soup for you","no spoon","no stinking badges","no time to explain","no way","nobody home","none of the above","nope chuck testa","nose bleed","nosy parker","not a bot","not in kansas","not yet","now and forever","now look here","nth degree","nul points","numa numa","nut case","nutrition","nyan cat","nyquist rate","of course","off the record","oh brother","oh em gee","oh hai","oh sigh","oh so close","oh yes","oh you","oh,you","oh, wait","okey dokey","old hat","old man winter","old shoe","om nom nom","on a boat","on cloud nine","on the ball","on the qt","on-off","once again","once upon a time","one day more","one fell swoop","one hit wonder","one small step for man","one stop shop","one way","one way street","one, two, three","only way to be sure","oontz oontz","oops a daisy","open season","open sesame","orange juice","other worldly","out of sorts","out of toner","outlook good","over the hill","over the moon","over the top","over there","oxford university","oxo cube","paint it red","pandora's box","pants on the ground","paper jam","paper plate","partial derivative","partly cloudy","party on garth","passing lane","patch of grass","path less taken","patience child","patty cake","pay the ferryman","pea brain","pearly whites","peg out","pell mell","penny loafer","people like me","pepe silvia","pepper pot","pepperoni pizza","peppers and onions","perfect world","pester power","peter out","philadelphia","phone home","pick me","pick up sticks","pickle juice","pickled peppers","picture perfect","pie are round","pie are squared","pie chart","piece of cake","pig's ear","piggyback","pin money","pipe down","pipe dream","piping hot","pitter patter","pizza topping","plain sailing","play a game","play again","play ball","play hookey","play it again sam","pleased as punch","plenty of time","plugged nickel","plus or minus","pocket sized","pod bay doors","poetic justice","point blank","point to point","points dont matter","points font matter","poison apple","political party","politicaly correct","poly's cracker","pond life","pool boy","pool hall","pool house","poor house","pork pies","pound cake","power dressing","power tool","practice makes perfect","press into service","prime time","primrose path","print out","print paper","printer paper","propane accessories","public good","pudding pops","puffy shirt","pumpkin pie","puppy dog","puppy love","push harder","push on","push the edge","push the envelope","pyrrhic victory","quality time","queen nefertiti","queen of hearts","queen's yacht","question everything","question mark","quid pro quo","quotations","rack and ruin","rack your brains","rain go away","rain tonight","rainy days","raise cain","raspberry tart","reach higher","read all over","read me, write me","read my mail","ready set go","real hoopy frood","real mccoy","red herring","red tape","red white and blue","red-handed","reduplicated phrases","remain calm","rent-a-swag","respect me","return to sender","reverse the polarity","rhino beetle","rhodeisland","rhyme nor reason","rhyming slang","rice and beans","rice job","ride the subway","riff-raff","right hand turn","right left","righty tighty","ring fencing","ring fenring","rinky-dink","rise and shine","river song","river styx","road apples","road less travelled","roast beef","robe of saffron","rocket science","rodents of unusual size","roflcopter","roll again","roll over","roller skates","rolling stone","rooftop","room for activities","roommate agreement","root beer float","rope burn","rosebud","rosie lea","rough diamond","round one","round robin","round tab1e","route one","row boat","roy g biv","royal flush","rubicon crossed","rule of chomio","rule of thumb","rum do","run amok","run away","run farther","run the gauntlet","run through","runny nose","saber tooth","sacred cow","safe streets","safer streets","safety first","salad days","salt and pepper","salty cheese","same same","sandy beach","saturday detention","saucy","sauer kraut","sausages","save face","save it","save our bluths","savoir faire","sax and violins","say cheese","school is cool","science class","science fair","science it works","science project","scot free","screw driver","sea change","sea shell","sea shore","seattle","see red","see ya","see-saw","seek beauty","seems legit","seize the day","select from table","send packing","senior citizen","seven ate nine","seven signs","seze the day","shake a leg","shaken not stirred","shakers and movers","shane come back","sharp pencil","sharp stick","she loves him","she sells","she sells seashells","she's a witch","sheldon alpha five","shilly-shally","ship shape","shoe shine","shoes shine","shoot through","shoulder of orion","show down","shuffle the deck","sick puppy","signal your turns","signs point to yes","silence is golden","silver bells","silver bullet","silver hoing","silver lining","silver spoon","sin cos tan","since when","sing a song","sixes and sevens","sixteen point turn","skidrow","skip a turn","sky's the limit","skynet is watching","skynet knows","skynet watches","sleep tight","sleepy hollow","slimy goop","slippery slope","sloane ranger","slow down","slow milenky lizards","slush fund","slythy toves","small fries","small fry","smart casual","smart phone","smashed potato","smell that","smelling salt","smoked salmon","snake eyes","snapshot","snare drum","sneezing baby panda","snoop lion","snow drift","snow flurry","snow shovel","so far away","so life like","so so","sod's law","soft kitty warm kitty","soft kitty, warm kitty","somebody that i used to know","sonic screw driver","sorry dave","sorry sight","souffle girl","sound bite","sound of sirens","sound out","sour grapes","space is big","space plumber","spangled banner","speeding bullet","spelling bee","spend time","spick and span","spicy","spicy hot","spin doctor","spitting feathers","spitting image","spoilers","spread the net","spring water","spruce up","square meal","square one","squeaky clean","squirrel friend","st johns bay","stalla stella","stand and deliver","stand by me","stand up guy","star spangled","star wars kid","start from scratch","stay safe","steak and eggs","steam punk","steering wheel","step back","step over","steve holt","steve jobs","sticky wicket","sting like a bee","stinking rich","stinky feet","stone soup","stone's throw","stony hearted","stool pigeon","stop waisting time","stranger danger","streams of oceanus","strike a match","strike three","string along","string cheese","stuck in mud","stump up","sudo make sandwich","sulphur smell","summon inglip","sun tzu says","sunday","sunshine","super star","surf and turf","surface integral","swan song","sweet dreams","sweety pie","swirling vortex of entropy","taco tuesday","take a look","take an umbrella","take care","take it all","take out food","take potluck","take the cake","take umbrage","take wrong turns","taken aback","talk the talk","talk to strangers","talk turkey","tall building","tall story","tastes good","tastes like chicken","tea earl gray hot","tea leaf","tea with jam","tea with milk","tear us apart","technicolor yawn","teflon president","teh inter webs","ten four","tesla coil","thank you","thank you, come again","that escalated quickly","that hurts","that will not work","that's a fact jack","that's all folks","that's enough","that's hot","that's it","that's my spot","that's right","the bee's knees","the bible","the big apple","the big cheese","the big easy","the cat lady","the cats cradle","the dennis system","the dude abides","the extra mile","the next level","the nightman cometh","the one eyed man is a king","the other side","the tribe has spoken","the yellow king","there is no spoon","there is only zul","there once was","these parts","they are watching","they ate it","thick and thin","thin air","think create do","think green","think hard","think twice","thinking cap","third degree","thirty one days","this is it","this is not fake","this is sparta","this or that","this statement is false","three short words","three strikes","through the grapevine","thumbs up","thunder storm","ticked off","tickle the ivories","tickled ivories","tickled pink","tide over","tight lipped","time and paper","time circuits","time flies","time is an illusion","time lord","time machine","time will tell","times square","tinker's dam","to boot","toast points","toe the line","toe-curling","together again","too bad","too late","too many cooks","too many secrets","too salty","toodle oo","top dog","top drawer","top notch","top ten","topsy turvy","topsy-turvy","total shamble","towel dry","tower of strength","toy soldier","traffic jam","traffic light","train surfing","travel size","treat yoself","trick or treat","trickle down","trolololol","true blue","true life","trust me","tuckered out","tuna fish","tune in","turkey sandwich","turn signal","turn the tables","turn up trumps","twenty eight days","twenty four seven","twenty one","twenty three","two cents worth","two hands","two left feet","two tone","u jelly","umbrella corporation","uncharted island","uncle leo","under the sea","underpants","union jack","unlimited wishes","untied laces","until next time","until tomorrow","until tonight","up and away","up or down","upper crust","upper hand","ups a daisy","upside down","upvote this","upward slope","urban myth","usual suspects","uu dd lr lr ba","van surfing","vanilla ice cream","veg out","vegan diet","vegan zombie wants grains","vegetarian","very doubtful","very nice","vice versa","vicious cycle","video tape","vienna calling","virtue of necessity","vis a vis","vocal minority","vogon poetry","voigt kampf","vorpal sword","vote pancakes","wake of the flood","walk free","walk the plank","walk the walk","want more","warp speed","wash whites separately","watch c-beams glitter","watch me","watch out","water gate","wax poetic","way to go","way to go donny","we go forwards","we like the moon","weakest link","weasel words","welcome to earth","well done","well heeled","well isn't that special","well now","well read","weylan yutani","what even","what ever","what for","what if","what is for dinner","what is your quest","what should we call me","what to see","what's that","wheel group","when where","where to go","whet your appetite","whistle and flute","white as snow","white bread","white elephant","white rabbit","who am i","who are you","who is it","who you gonna call","who, what, where","whoa there","whole nine yards","whole shebang","whoopee cushion","whoops a daisy","wicked witch","wide berth","wild and crazy guys","wild and woolly","wild goose chase","wild west","willy nilly","win hands down","window dressing","wing it","winning","winter is coming","winter snow","wisdom of inglip","wisdom teeth","wishy-washy","with bells on","without a doubt","woof woof","word for word","words of wisdom","work out","would you believe","wright flyer","writing desk","x all the y","xylophone","yada yada","yadda yadda yadda","yeah right","year dot","yee haw","yelling goat","yellow belly","yes definitely","yes ma'am","yes sir","yes this is dog","you are happy","you are here","you can do this","you don't say","you first","you good","you have my stapler","you rock","you the man","you win","you're in my spot","you're not listening","you're welcome","zig zag","zombie attack","zombie prom","who what where",]; + function solvemed(b){var a=document.createElement("datalist");a.setAttribute("id","adcopy_phrases");for(var c=0;c -1){document.body.addEventListener("keydown",function c(a){if(/^adcopy_response/.test(a.target.id)){this.removeEventListener(a.type,c);var b=a.target;solvemed(b);b.blur();b.focus();}});break;}} +}})(); +} diff --git a/scripts/content-scripts/scripts/studocu.css b/scripts/content-scripts/scripts/studocu.css new file mode 100644 index 00000000..2eaf997a --- /dev/null +++ b/scripts/content-scripts/scripts/studocu.css @@ -0,0 +1,9 @@ +.page-content { + filter: none !important; +} + +._de9e5fdb76af, +._869f7c361ca9, +span.l { + display: none !important; +} \ No newline at end of file diff --git a/scripts/content-scripts/utils.js b/scripts/content-scripts/utils.js index 1cf63b0d..8a8f618c 100644 --- a/scripts/content-scripts/utils.js +++ b/scripts/content-scripts/utils.js @@ -28,17 +28,13 @@ export function injectCss(cssfileOrCode, isFile = true) { var css = document.createElement("link"); css.rel = "stylesheet"; css.href = chrome.runtime.getURL(cssfileOrCode); - window.onload = () => { - document.body.appendChild(css); - console.log("Useful-scripts injected " + css.href); - }; + document.head.appendChild(css); + console.log("Useful-scripts injected " + css.href); } else { var css = document.createElement("style"); if ("textContent" in css) css.textContent = cssText; else css.innerText = cssText; - window.onload = () => { - document.body.appendChild(css); - console.log("Useful-scripts injected " + css); - }; + document.head.appendChild(css); + console.log("Useful-scripts injected " + css); } } diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index 003b5724..1d17b6b3 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -114,7 +114,10 @@ export async function checkBlackWhiteList(script, url) { return willRun; } +// https://stackoverflow.com/a/874722 export function isUrlMatchPattern(url, pattern) { + // let reg = new RegExp(pattern.replaceAll("/", "\\/")); + // return url.match(reg); let curIndex = 0, visiblePartsInPattern = pattern.split("*").filter((_) => _ !== ""); for (let p of visiblePartsInPattern) { diff --git a/scripts/index.js b/scripts/index.js index 439de4ee..e95b6b5d 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -134,6 +134,7 @@ import tiktok_downloadUserVideos from "./tiktok_downloadUserVideos.js"; import tiktok_downloadVideoNoWM from "./tiktok_downloadVideoNoWM.js"; import ggDrive_downloadAllVideosInFolder from "./ggDrive_downloadAllVideosInFolder.js"; import fb_downloadWatchingVideo from "./fb_downloadWatchingVideo.js"; +import studocu_downloader from "./studocu_downloader.js"; // inject badges const allScripts = { @@ -289,6 +290,7 @@ const allScripts = { BADGES.new ), fb_downloadWatchingVideo: addBadge(fb_downloadWatchingVideo, BADGES.new), + studocu_downloader: addBadge(studocu_downloader, BADGES.new), }; // inject id to all scripts diff --git a/scripts/insta_getAllImagesInNewFeed.js b/scripts/insta_getAllImagesInNewFeed.js index 9f1115f6..a7af4437 100644 --- a/scripts/insta_getAllImagesInNewFeed.js +++ b/scripts/insta_getAllImagesInNewFeed.js @@ -11,49 +11,27 @@ export default { whiteList: ["*://*.instagram.com"], func: async function () { - function renderInNewWindow({ link, url } = {}) { - if (!link?.length) { - alert("Not found image"); - return; - } - let win = window.open( - "", - "All images from " + url, - "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=500,top=50,left=50" - ); - let rows = link - ?.map((_, i) => { - return ` - ${i} - ${_} - - `; - }) - .join(""); + const getAllImgTag = () => + Array.from(document.querySelectorAll("img[sizes*=px]")) || []; + const sleep = (milliseconds) => + new Promise((resolve) => setTimeout(resolve, milliseconds)); - let html = ` - - - - - - ${rows} -
#LinkImage
`; - win.document.body.innerHTML = html; + // https://greasyfork.org/en/scripts/14755-instagram-reloaded + function getBestImage(imgEl) { + try { + return imgEl.srcset.split("w,")[0].split(" ")[0]; + } catch (e) { + return imgEl.src; + } } - const getAllImgTag = () => - Array.from(document.querySelectorAll("img[sizes*=px]")) || []; - const sleep = (milliseconds) => { - return new Promise((resolve) => setTimeout(resolve, milliseconds)); - }; const img_srcs = []; const done = []; const img_queue = getAllImgTag(); while (img_queue.length > 0) { const first = img_queue.shift(); first.scrollIntoView(); - const src = first.src; + const src = getBestImage(first); img_srcs.push(src); console.log(src); done.push(first); @@ -63,7 +41,7 @@ export default { img_queue.push(...new_img); await sleep(300); } + console.log(img_srcs); - renderInNewWindow({ link: img_srcs, url: location.href }); }, }; diff --git a/scripts/insta_getToken.js b/scripts/insta_getToken.js index d5ee3e06..70097dd0 100644 --- a/scripts/insta_getToken.js +++ b/scripts/insta_getToken.js @@ -31,3 +31,13 @@ export default { } }, }; + +function backup() { + // https://greasyfork.org/en/scripts/14755-instagram-reloaded + function get_csrf_token() { + return document.body.innerHTML + .match(/\"csrf_token\":(?:"[^"]*"|^[^"]*$)/)[0] + .replace(/\"/g, "") + .split(":")[1]; + } +} diff --git a/scripts/studocu_downloader.js b/scripts/studocu_downloader.js new file mode 100644 index 00000000..5c4b8710 --- /dev/null +++ b/scripts/studocu_downloader.js @@ -0,0 +1,23 @@ +export default { + icon: "https://d20ohkaloyme4g.cloudfront.net/img/favicon.ico", + name: { + en: "Studocu - Download documents", + vi: "Studocu - Tải documents", + }, + description: { + en: "Download document pdf on Studocu.com for free", + vi: "Tải PDF document trên Studocu.com miễn phí", + }, + blackList: [], + whiteList: ["https://www.studocu.com/*"], + runInExtensionContext: false, + + func: function () { + let url = new URL(location.href); + url.hostname = "www.downstudocu.com"; + window.open(url); + }, +}; + +// Những thuộc tính/hàm có thể chia sẻ cho cách scripts khác sử dụng sẽ được viết vào đây +export const shared = {}; diff --git a/scripts/tiktok_downloadUserVideos.js b/scripts/tiktok_downloadUserVideos.js index 1998d036..7a117542 100644 --- a/scripts/tiktok_downloadUserVideos.js +++ b/scripts/tiktok_downloadUserVideos.js @@ -108,14 +108,7 @@ async function backup() { let videos = []; for (let c of containers) { - // find react fiber key - let key = ""; - for (let k of Object.keys(c)) { - if (k.indexOf("__reactFiber") === 0) { - key = k; - break; - } - } + let key = Object.keys(c).find((k) => k.startsWith("__reactFiber")); let video = c[key].firstEffect?.memoizedProps || c[key].lastEffect?.memoizedProps || From f0102c56342a6360a7e55e9f01b0bcd758c39e5d Mon Sep 17 00:00:00 2001 From: "hoang.tran12" Date: Wed, 7 Dec 2022 14:05:20 +0700 Subject: [PATCH 030/164] insta ... --- popup/tabs.js | 2 +- scripts/content-scripts/document_start.js | 6 +- .../scripts/bypass_all_shortlink.js | 1 + .../scripts/instagram_downloadBtn.js | 640 ++++++++++++++++++ scripts/helpers/utils.js | 66 +- scripts/index.js | 4 +- scripts/insta_reloaded.js | 254 ------- scripts/insta_storySaver.js | 26 + scripts/search_userscript.js | 19 + 9 files changed, 756 insertions(+), 262 deletions(-) create mode 100644 scripts/content-scripts/scripts/instagram_downloadBtn.js delete mode 100644 scripts/insta_reloaded.js create mode 100644 scripts/search_userscript.js diff --git a/popup/tabs.js b/popup/tabs.js index f4db6966..233466b1 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -37,6 +37,7 @@ const tabs = [ ...CATEGORY.search, scripts: [ s._test, + s.search_userscript, s.whatFont, s.similarWeb, s.search_sharedAccount, @@ -132,7 +133,6 @@ const tabs = [ s.insta_getToken, s.insta_getUserInfo, createTitle("--- Download ---", "--- Tải xuống ---"), - s.insta_reloaded, s.instantgram, s.insta_storySaver, createTitle("--- Bulk Download ---", "--- Tải hàng loạt ---"), diff --git a/scripts/content-scripts/document_start.js b/scripts/content-scripts/document_start.js index a2303770..b844b6d7 100644 --- a/scripts/content-scripts/document_start.js +++ b/scripts/content-scripts/document_start.js @@ -6,13 +6,15 @@ // injectScript(baseURL + "globals_debugger.js"); injectScript(baseURL + "useful-scripts-utils.js"); - injectScript(baseURL + "bypass_all_shortlink.js"); + // injectScript(baseURL + "bypass_all_shortlink.js"); if (location.hostname === "mp3.zing.vn") injectScript(baseURL + "mp3.zing.vn.js"); - if (location.hostname === "www.instagram.com") + if (location.hostname === "www.instagram.com") { injectCss(baseURL + "instagram.css"); + injectScript(baseURL + "instagram_downloadBtn.js"); + } if (location.hostname === "www.studyphim.vn") injectScript(baseURL + "studyphim.js"); diff --git a/scripts/content-scripts/scripts/bypass_all_shortlink.js b/scripts/content-scripts/scripts/bypass_all_shortlink.js index d54378e0..eb2f4a22 100644 --- a/scripts/content-scripts/scripts/bypass_all_shortlink.js +++ b/scripts/content-scripts/scripts/bypass_all_shortlink.js @@ -188,6 +188,7 @@ let config = { let url = location.href; let willRun = false; +// TODO : calculate willRun if (willRun) { // prettier-ignore diff --git a/scripts/content-scripts/scripts/instagram_downloadBtn.js b/scripts/content-scripts/scripts/instagram_downloadBtn.js new file mode 100644 index 00000000..91dd291a --- /dev/null +++ b/scripts/content-scripts/scripts/instagram_downloadBtn.js @@ -0,0 +1,640 @@ +// ==UserScript== +// @name Instagram Download Button +// @name:zh-TW Instagram 下載器 +// @name:zh-CN Instagram 下载器 +// @name:ja Instagram ダウンローダー +// @name:ko Instagram 다운로더 +// @name:es Descargador de Instagram +// @name:fr Téléchargeur Instagram +// @name:hi इंस्टाग्राम डाउनलोडर +// @name:ru Загрузчик Instagram +// @namespace https://github.com/y252328/Instagram_Download_Button +// @version 1.15.3 +// @compatible chrome +// @compatible firefox +// @compatible edge +// @description Add the download button and the open button to download or open profile picture and media in the posts, stories, and highlights in Instagram +// @description:zh-TW 在Instagram頁面加入下載按鈕與開啟按鈕,透過這些按鈕可以下載或開啟大頭貼與貼文、限時動態、Highlight中的照片或影片 +// @description:zh-CN 在Instagram页面加入下载按钮与开启按钮,透过这些按钮可以下载或开启大头贴与贴文、限时动态、Highlight中的照片或影片 +// @description:ja メディアをダウンロードまたは開くためのボタンを追加します +// @description:ko 미디어를 다운로드하거나 여는 버튼을 추가합니다 +// @description:es Agregue botones para descargar o abrir medios +// @description:fr Ajoutez des boutons pour télécharger ou ouvrir des médias +// @description:hi मीडिया को डाउनलोड या खोलने के लिए बटन जोड़ें। +// @description:ru Добавьте кнопки для загрузки или открытия медиа +// @author ZhiYu +// @match https://www.instagram.com/* +// @grant none +// @license MIT +// ==/UserScript== + +// prettier-ignore +(function () { + 'use strict'; + + // ================= + // = Options = + // ================= + // Old method is faster than new method, but not work or unable get highest resolution media sometime + const disableNewUrlFetchMethod = false; + const prefetchAndAttachLink = true; // add link into the button elements + const postFilenameTemplate = '%id%-%datetime%-%medianame%'; + const storyFilenameTemplate = postFilenameTemplate; + const replaceJpegWithJpg = false; + + // ================== + + const postIdPattern = /^\/p\/([^/]+)\//; + function yyyymmdd(date) { + // ref: https://stackoverflow.com/questions/3066586/get-string-in-yyyymmdd-format-from-js-date-object?page=1&tab=votes#tab-top + var mm = date.getMonth() + 1; // getMonth() is zero-based + var dd = date.getDate(); + + return [date.getFullYear(), (mm > 9 ? '' : '0') + mm, (dd > 9 ? '' : '0') + dd].join(''); + } + + var svgDownloadBtn = ` + + + + + + +`; + + var svgNewtabBtn = ` + +`; + + document.addEventListener('keydown', keyDownHandler); + + function keyDownHandler(event) { + if (window.location.href === 'https://www.instagram.com/') return; + + const mockEventTemplate = { + stopPropagation: function(){}, + preventDefault: function(){} + }; + + if (event.altKey && event.key === 'k') { + let buttons = document.getElementsByClassName('download-btn'); + if (buttons.length > 0) { + let mockEvent = { ...mockEventTemplate }; + mockEvent.currentTarget = buttons[buttons.length - 1]; + if (prefetchAndAttachLink) onMouseInHandler(mockEvent); + onClickHandler(mockEvent); + } + } + if (event.altKey && event.key === 'i') { + let buttons = document.getElementsByClassName('newtab-btn'); + if (buttons.length > 0) { + let mockEvent = { ...mockEventTemplate }; + mockEvent.currentTarget = buttons[buttons.length - 1]; + if (prefetchAndAttachLink) onMouseInHandler(mockEvent); + onClickHandler(mockEvent); + } + } + + if (event.altKey && event.key === 'l') { + // right arrow + let buttons = document.getElementsByClassName('coreSpriteRightChevron'); + if (buttons.length > 0) { + buttons[0].click(); + } + } + + if (event.altKey && event.key === 'j') { + // left arrow + let buttons = document.getElementsByClassName('coreSpriteLeftChevron'); + if (buttons.length > 0) { + buttons[0].click(); + } + } + } + + var checkExistTimer = setInterval(function () { + let sharePostSelector = 'article section span button'; + let storySelector = 'header button > div'; + let profileSelector = 'header section svg circle'; + // Thanks for Jenie providing color check code + // https://greasyfork.org/zh-TW/scripts/406535-instagram-download-button/discussions/122185 + let iconColor = getComputedStyle(document.body).backgroundColor === 'rgb(0, 0, 0)' ? 'white' : 'black'; + + // check profile + if (document.getElementsByClassName('custom-btn').length === 0) { + if (document.querySelector(profileSelector)) { + addCustomBtn(document.querySelector(profileSelector), iconColor, append2Header); + } + } + + // check post + let articleList = document.querySelectorAll('article'); + for (let i = 0; i < articleList.length; i++) { + if (articleList[i].querySelector(sharePostSelector) && articleList[i].getElementsByClassName('custom-btn').length === 0) { + addCustomBtn(articleList[i].querySelector(sharePostSelector), iconColor, append2Post); + } + } + + // check story + if (document.getElementsByClassName('custom-btn').length === 0) { + if (document.querySelector(storySelector)) { + addCustomBtn(document.querySelector(storySelector), 'white', append2Post); + } + } + }, 500); + + function append2Header(node, btn) { + node.parentNode.parentNode.parentNode.appendChild(btn, node.parentNode.parentNode); + } + + function append2Post(node, btn) { + node.parentNode.parentNode.appendChild(btn); + } + + function addCustomBtn(node, iconColor, appendNode) { + // add download button and set event handlers + // add newtab button + let newtabBtn = createCustomBtn(svgNewtabBtn, iconColor, 'newtab-btn', '16px'); + appendNode(node, newtabBtn); + + // add download button + let downloadBtn = createCustomBtn(svgDownloadBtn, iconColor, 'download-btn', '14px'); + appendNode(node, downloadBtn); + + if (prefetchAndAttachLink) { + onMouseInHandler({ currentTarget: newtabBtn }); + onMouseInHandler({ currentTarget: downloadBtn }); + } + } + + function createCustomBtn(svg, iconColor, className, marginLeft) { + let newBtn = document.createElement('a'); + newBtn.innerHTML = svg.replace('%color', iconColor); + newBtn.setAttribute('class', 'custom-btn ' + className); + newBtn.setAttribute('target', '_blank'); + newBtn.setAttribute('style', 'cursor: pointer;margin-left: ' + marginLeft + ';margin-top: 8px;z-index: 999;'); + newBtn.onclick = onClickHandler; + if (prefetchAndAttachLink) newBtn.onmouseenter = onMouseInHandler; + if (className.includes('newtab')) { + newBtn.setAttribute('title', 'Open in new tab'); + } else { + newBtn.setAttribute('title', 'Download'); + } + return newBtn; + } + + function onClickHandler(e) { + // handle button click + let target = e.currentTarget; + e.stopPropagation(); + e.preventDefault(); + if (window.location.pathname.includes('stories')) { + storyOnClicked(target); + } else if (document.querySelector('header') && document.querySelector('header').contains(target)) { + profileOnClicked(target); + } else { + postOnClicked(target); + } + } + + function onMouseInHandler(e) { + let target = e.currentTarget; + if (!prefetchAndAttachLink) return; + if (window.location.pathname.includes('stories')) { + storyOnMouseIn(target); + } else if (document.querySelector('header') && document.querySelector('header').contains(target)) { + profileOnMouseIn(target); + } else { + postOnMouseIn(target); + } + } + + // ================================ + // ==== Profile ==== + // ================================ + function profileOnMouseIn(target) { + let url = profileGetUrl(target); + target.setAttribute('href', url); + } + + function profileOnClicked(target) { + // extract profile picture url and download or open it + let url = profileGetUrl(target); + + if (url.length > 0) { + // check url + if (target.getAttribute('class').includes('download-btn')) { + // generate filename + const filename = document.querySelector('header h2').textContent; + downloadResource(url, filename); + } else { + // open url in new tab + openResource(url); + } + } + } + + function profileGetUrl(target) { + let img = document.querySelector('header img'); + let url = img.getAttribute('src'); + return url; + } + + // ================================ + // ==== Post ==== + // ================================ + async function postOnMouseIn(target) { + let articleNode = postGetArticleNode(target); + let { url } = await postGetUrl(target, articleNode); + target.setAttribute('href', url); + } + + async function postOnClicked(target) { + // extract url from target post and download or open it + let articleNode = postGetArticleNode(target); + let { url, mediaIndex } = await postGetUrl(target, articleNode); + + // download or open media url + if (url.length > 0) { + // check url + if (target.getAttribute('class').includes('download-btn')) { + let mediaName = url + .split('?')[0] + .split('\\') + .pop() + .split('/') + .pop(); + mediaName = mediaName.substring(0, mediaName.lastIndexOf('.')); + let datetime = new Date(articleNode.querySelector('time').getAttribute('datetime')); + datetime = + yyyymmdd(datetime) + + '_' + + datetime + .toTimeString() + .split(' ')[0] + .replace(/:/g, ''); + let posterName = articleNode + .querySelector('header a') + .getAttribute('href') + .replace(/\//g, ''); + let postId = articleNode + .querySelector('a time') + .closest('a') + .getAttribute('href') + .match(postIdPattern)[1]; + let filename = filenameFormat(postFilenameTemplate, posterName, datetime, mediaName, postId, mediaIndex); + downloadResource(url, filename); + } else { + // open url in new tab + openResource(url); + } + } + } + + function postGetArticleNode(target) { + let articleNode = target; + while (articleNode && articleNode.tagName !== 'ARTICLE') { + articleNode = articleNode.parentNode; + } + return articleNode; + } + + async function postGetUrl(target, articleNode) { + // meta[property="og:video"] + let list = articleNode.querySelectorAll('li[style][class]'); + let url = null; + let mediaIndex = 0; + if (list.length === 0) { + // single img or video + if (!disableNewUrlFetchMethod) url = await getUrlFromInfoApi(articleNode); + if (url === null) { + if (articleNode.querySelector('article div > video')) { + // media type is video + let videoElem = articleNode.querySelector('article div > video'); + url = videoElem.getAttribute('src'); + if (videoElem.hasAttribute('videoURL')) { + url = videoElem.getAttribute('videoURL'); + } else if (url === null || url.includes('blob')) { + url = await fetchVideoURL(articleNode, videoElem); + } + } else if (articleNode.querySelector('article div[role] div > img')) { + // media type is image + url = articleNode.querySelector('article div[role] div > img').getAttribute('src'); + } else { + console.log('Err: not find media at handle post single'); + } + } + } else { + // multiple imgs or videos + const postView = location.pathname.startsWith('/p/'); + const dotsElements = [...articleNode.querySelector(`:scope > div > div:nth-child(${postView ? 1 : 2}) > div > div:nth-child(2)`).children]; + mediaIndex = [...dotsElements].reduce((result, element, index) => (element.classList.length === 2 ? index : result), null); + + if (!disableNewUrlFetchMethod) url = await getUrlFromInfoApi(articleNode, mediaIndex); + if (url === null) { + const listElements = [...articleNode.querySelectorAll(`:scope > div > div:nth-child(${postView ? 1 : 2}) > div > div:nth-child(1) ul li[style*="translateX"]`)]; + const listElementWidth = Math.max(...listElements.map(element => element.clientWidth)); + + const positionsMap = listElements.reduce((result, element) => { + // console.log(Number(element.style.transform.match(/-?(\d+)/)[1])); + const position = Math.round(Number(element.style.transform.match(/-?(\d+)/)[1]) / listElementWidth); + return { ...result, [position]: element }; + }, {}); + + console.log({ dotsElements, listElements, listElementWidth, positionsMap }); + + const node = positionsMap[mediaIndex]; + if (node.querySelector('video')) { + // media type is video + let videoElem = node.querySelector('video'); + url = videoElem.getAttribute('src'); + if (videoElem.hasAttribute('videoURL')) { + url = videoElem.getAttribute('videoURL'); + } else if (url === null || url.includes('blob')) { + url = await fetchVideoURL(articleNode, videoElem); + } + } else if (node.querySelector('img')) { + // media type is image + url = node.querySelector('img').getAttribute('src'); + } + } + } + return { url, mediaIndex }; + } + + let infoCache = {}; // key: media id, value: info json + let mediaIdCache = {}; // key: post id, value: media id + async function getUrlFromInfoApi(articleNode, mediaIdx = 0) { + // return media url if found else return null + // fetch flow: + // 1. find post id + // 2. use step1 post id to send request to get post page + // 3. find media id from the reponse text of step2 + // 4. find app id in clicked page + // 5. send info api request with media id and app id + // 6. get media url from response json + try { + const appIdPattern = /"X-IG-App-ID":"([\d]+)"/ + const mediaIdPattern = /instagram:\/\/media\?id=(\d+)|["' ]media_id["' ]:["' ](\d+)["' ]/ + function findAppId() { + let bodyScripts = document.querySelectorAll("body > script"); + for (let i = 0; i < bodyScripts.length; ++i) { + let match = bodyScripts[i].text.match(appIdPattern); + if (match) return match[1]; + } + console.log("Cannot find app id"); + return null; + } + + function findPostId() { + const timeSelector = 'time._aaqe'; + let nodeWalker = articleNode.querySelector(timeSelector); + if (nodeWalker) { + for (let i = 0; i < 10 && nodeWalker.parentNode; ++i) { + nodeWalker = nodeWalker.parentNode; + if (nodeWalker.tagName === "A") { + break; + } + } + if (nodeWalker.tagName === "A") { + let link = nodeWalker.getAttribute('href'); + let match = link.match(postIdPattern); + if (match) return match[1]; + } + } + return null; + } + + async function findMediaId() { + let match = window.location.href.match(/www.instagram.com\/stories\/[^\/]+\/(\d+)/) + if (match) return match[1]; + + let postId = await findPostId(); + if (!postId) { + console.log("Cannot find post id"); + return null; + } + if (!(postId in mediaIdCache)) { + let postUrl = `https://www.instagram.com/p/${postId}/`; + let resp = await fetch(postUrl); + let text = await resp.text(); + let idMatch = text.match(mediaIdPattern); + let mediaId = null; + for (let i = 0; i < idMatch.length; ++i) { + if (idMatch[i]) mediaId = idMatch[i]; + } + if (!mediaId) return null; + mediaIdCache[postId] = mediaId; + } + return mediaIdCache[postId]; + } + + function getImgOrVideoUrl(item) { + if ("video_versions" in item) { + return item.video_versions[0].url; + } else { + return item.image_versions2.candidates[0].url; + } + } + + let appId = findAppId(); + if (!appId) return null; + let headers = { + method: 'GET', + headers: { + Accept: '*/*', + 'X-IG-App-ID': appId + }, + credentials: 'include', + mode: 'cors' + }; + + let mediaId = await findMediaId(); + if (!mediaId) { + console.log("Cannot find media id"); + return null; + } + if (!(mediaId in infoCache)) { + let url = 'https://i.instagram.com/api/v1/media/' + mediaId + '/info/'; + let resp = await fetch(url, headers); + if (resp.status !== 200) { + console.log(`Fetch info API failed with status code: ${resp.status}`); + return null; + } + let respJson = await resp.json(); + infoCache[mediaId] = respJson; + } + let infoJson = infoCache[mediaId]; + if ('carousel_media' in infoJson.items[0]) { + // multi-media post + return getImgOrVideoUrl(infoJson.items[0].carousel_media[mediaIdx]); + } else { + // single media post + return getImgOrVideoUrl(infoJson.items[0]); + } + } catch (e) { + // console.log(`Uncatched in getUrlFromInfoApi(): ${e}\n${e.stack}`); + return null; + } + } + + async function fetchVideoURL(articleNode, videoElem) { + let poster = videoElem.getAttribute('poster'); + let timeNodes = articleNode.querySelectorAll('time'); + // special thanks 孙年忠 (https://greasyfork.org/en/scripts/406535-instagram-download-button/discussions/120159) + let posterUrl = timeNodes[timeNodes.length - 1].parentNode.parentNode.href; + const posterPattern = /\/([^\/?]*)\?/; + let posterMatch = poster.match(posterPattern); + let postFileName = posterMatch[1]; + let resp = await fetch(posterUrl); + let content = await resp.text(); + // special thanks to 孙年忠 for the pattern (https://greasyfork.org/zh-TW/scripts/406535-instagram-download-button/discussions/116675) + const pattern = new RegExp(`${postFileName}.*?video_versions.*?url":("[^"]*")`, 's'); + let match = content.match(pattern); + let videoUrl = JSON.parse(match[1]); + videoUrl = videoUrl.replace(/^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/?\n]+)/g, 'https://scontent.cdninstagram.com'); + videoElem.setAttribute('videoURL', videoUrl); + return videoUrl; + } + + // ================================ + // ==== Story ==== + // ================================ + async function storyOnMouseIn(target) { + let sectionNode = storyGetSectionNode(target); + let url = await storyGetUrl(target, sectionNode); + target.setAttribute('href', url); + } + + async function storyOnClicked(target) { + // extract url from target story and download or open it + let sectionNode = storyGetSectionNode(target); + let url = await storyGetUrl(target, sectionNode); + + // download or open media url + if (target.getAttribute('class').includes('download-btn')) { + let mediaName = url + .split('?')[0] + .split('\\') + .pop() + .split('/') + .pop(); + mediaName = mediaName.substring(0, mediaName.lastIndexOf('.')); + let datetime = new Date(sectionNode.querySelector('time').getAttribute('datetime')); + datetime = + yyyymmdd(datetime) + + '_' + + datetime + .toTimeString() + .split(' ')[0] + .replace(/:/g, ''); + let posterName = sectionNode + .querySelector('header a') + .getAttribute('href') + .replace(/\//g, ''); + + let filename = filenameFormat(storyFilenameTemplate, posterName, datetime, mediaName); + downloadResource(url, filename); + } else { + // open url in new tab + openResource(url); + } + } + + function storyGetSectionNode(target) { + let sectionNode = target; + while (sectionNode && sectionNode.tagName !== 'SECTION') { + sectionNode = sectionNode.parentNode; + } + return sectionNode; + } + + async function storyGetUrl(target, sectionNode) { + let url = null; + if (!disableNewUrlFetchMethod) url = await getUrlFromInfoApi(target); + + if (!url) { + if (sectionNode.querySelector('video > source')) { + url = sectionNode.querySelector('video > source').getAttribute('src'); + } else if (sectionNode.querySelector('img[decoding="sync"]')) { + let img = sectionNode.querySelector('img[decoding="sync"]'); + url = img.srcset.split(/ \d+w/g)[0].trim(); // extract first src from srcset attr. of img + if (url.length > 0) { + return url; + } + url = sectionNode.querySelector('img[decoding="sync"]').getAttribute('src'); + } else if (sectionNode.querySelector('video')) { + url = sectionNode.querySelector('video').getAttribute('src'); + } + } + return url; + } + + function filenameFormat(template, id, datetime, medianame, postId = +new Date(), mediaIndex = '0') { + let filename = template; + filename = filename.replace(/%id%/g, id); + filename = filename.replace(/%datetime%/g, datetime); + filename = filename.replace(/%medianame%/g, medianame); + filename = filename.replace(/%postId%/g, postId) + filename = filename.replace(/%mediaIndex%/g, mediaIndex); + return filename; + } + + function openResource(url) { + // open url in new tab + var a = document.createElement('a'); + a.href = url; + a.setAttribute('target', '_blank'); + document.body.appendChild(a); + a.click(); + a.remove(); + } + + function forceDownload(blob, filename, extension) { + // ref: https://stackoverflow.com/questions/49474775/chrome-65-blocks-cross-origin-a-download-client-side-workaround-to-force-down + var a = document.createElement('a'); + if (replaceJpegWithJpg) extension = extension.replace('jpeg', 'jpg') + a.download = filename + '.' + extension; + a.href = blob; + // For Firefox https://stackoverflow.com/a/32226068 + document.body.appendChild(a); + a.click(); + a.remove(); + } + + // Current blob size limit is around 500MB for browsers + function downloadResource(url, filename) { + if (url.startsWith('blob:')) { + forceDownload(url, filename, 'mp4'); + return; + } + console.log(`Dowloading ${url}`); + // ref: https://stackoverflow.com/questions/49474775/chrome-65-blocks-cross-origin-a-download-client-side-workaround-to-force-down + if (!filename) { + filename = url + .split('\\') + .pop() + .split('/') + .pop(); + } + fetch(url, { + headers: new Headers({ + Origin: location.origin, + }), + mode: 'cors', + }) + .then(response => response.blob()) + .then(blob => { + const extension = blob.type.split('/').pop(); + let blobUrl = window.URL.createObjectURL(blob); + forceDownload(blobUrl, filename, extension); + }) + .catch(e => console.error(e)); + } +})(); diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js index 1d17b6b3..59fdf823 100644 --- a/scripts/helpers/utils.js +++ b/scripts/helpers/utils.js @@ -114,10 +114,7 @@ export async function checkBlackWhiteList(script, url) { return willRun; } -// https://stackoverflow.com/a/874722 export function isUrlMatchPattern(url, pattern) { - // let reg = new RegExp(pattern.replaceAll("/", "\\/")); - // return url.match(reg); let curIndex = 0, visiblePartsInPattern = pattern.split("*").filter((_) => _ !== ""); for (let p of visiblePartsInPattern) { @@ -424,4 +421,67 @@ export function openPopupWithHtml(html, width = 300, height = 300) { win.document.write(html); } +/*--- waitForKeyElements(): A utility function, for Greasemonkey scripts, + that detects and handles AJAXed content. Forked for use without JQuery. + Usage example: + waitForKeyElements ( + "div.comments" + , commentCallbackFunction + ); + //--- Page-specific function to do what we want when the node is found. + function commentCallbackFunction (element) { + element.text ("This comment changed by waitForKeyElements()."); + } + + IMPORTANT: Without JQuery, this fork does not look into the content of + iframes. +*/ +export function waitForKeyElements( + selectorTxt /* Required: The selector string that specifies the desired element(s).*/, + actionFunction /* Required: The code to run when elements are found. It is passed a jNode to the matched element.*/, + bWaitOnce /* Optional: If false, will continue to scan for new elements even after the first match is found.*/ +) { + var targetNodes, btargetsFound; + targetNodes = document.querySelectorAll(selectorTxt); + + if (targetNodes && targetNodes.length > 0) { + btargetsFound = true; + /*--- Found target node(s). Go through each and act if they are new. */ + targetNodes.forEach(function (element) { + var alreadyFound = + element.dataset.found == "alreadyFound" ? "alreadyFound" : false; + + if (!alreadyFound) { + //--- Call the payload function. + var cancelFound = actionFunction(element); + if (cancelFound) btargetsFound = false; + else element.dataset.found = "alreadyFound"; + } + }); + } else { + btargetsFound = false; + } + + //--- Get the timer-control variable for this selector. + var controlObj = waitForKeyElements.controlObj || {}; + var controlKey = selectorTxt.replace(/[^\w]/g, "_"); + var timeControl = controlObj[controlKey]; + + //--- Now set or clear the timer as appropriate. + if (btargetsFound && bWaitOnce && timeControl) { + //--- The only condition where we need to clear the timer. + clearInterval(timeControl); + delete controlObj[controlKey]; + } else { + //--- Set a timer, if needed. + if (!timeControl) { + timeControl = setInterval(function () { + waitForKeyElements(selectorTxt, actionFunction, bWaitOnce); + }, 300); + controlObj[controlKey] = timeControl; + } + } + waitForKeyElements.controlObj = controlObj; +} + // #endregion diff --git a/scripts/index.js b/scripts/index.js index e95b6b5d..37465a5e 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -91,7 +91,6 @@ import showTheImages from "./showTheImages.js"; import showHiddenFields from "./showHiddenFields.js"; import cssSelectorViewer from "./cssSelectorViewer.js"; import youtube_nonstop from "./youtube_nonstop.js"; -import insta_reloaded from "./insta_reloaded.js"; import zingmp3_downloadMusic from "./zingmp3_downloadMusic.js"; import showTheAudios from "./showTheAudios.js"; import nhaccuatui_downloader from "./nhaccuatui_downloader.js"; @@ -135,6 +134,7 @@ import tiktok_downloadVideoNoWM from "./tiktok_downloadVideoNoWM.js"; import ggDrive_downloadAllVideosInFolder from "./ggDrive_downloadAllVideosInFolder.js"; import fb_downloadWatchingVideo from "./fb_downloadWatchingVideo.js"; import studocu_downloader from "./studocu_downloader.js"; +import search_userscript from "./search_userscript.js"; // inject badges const allScripts = { @@ -232,7 +232,6 @@ const allScripts = { showHiddenFields: showHiddenFields, cssSelectorViewer: cssSelectorViewer, youtube_nonstop: addBadge(youtube_nonstop, BADGES.new), - insta_reloaded: addBadge(insta_reloaded, BADGES.beta), zingmp3_downloadMusic: addBadge(zingmp3_downloadMusic, BADGES.new), showTheAudios: showTheAudios, nhaccuatui_downloader: addBadge(nhaccuatui_downloader, BADGES.new), @@ -291,6 +290,7 @@ const allScripts = { ), fb_downloadWatchingVideo: addBadge(fb_downloadWatchingVideo, BADGES.new), studocu_downloader: addBadge(studocu_downloader, BADGES.new), + search_userscript: addBadge(search_userscript, BADGES.new), }; // inject id to all scripts diff --git a/scripts/insta_reloaded.js b/scripts/insta_reloaded.js deleted file mode 100644 index a669789d..00000000 --- a/scripts/insta_reloaded.js +++ /dev/null @@ -1,254 +0,0 @@ -export default { - icon: "https://www.google.com/s2/favicons?domain=instagram.com", - name: { - en: "Instagram reloaded - Download video/image", - vi: "Instagram reloaded - Tải video/ảnh", - }, - description: { - en: "View or download the full-size Instagram image/video", - vi: "Xem và tải ảnh/video instagram chất lượng cao", - }, - blackList: [], - whiteList: ["*://*.instagram.com/*"], - - func: function () { - // Original source code: https://greasyfork.org/en/scripts/14755-instagram-reloaded - // Modified by Hoang Tran - - // ==UserScript== - // @name Instagram Reloaded - // @namespace http://despecial.de - // @homepageURL https://greasyfork.org/en/scripts/14755-instagram-reloaded - // @version 2.30 - // @description View or download the full-size Instagram image/video. Super simple: press alt+f or shift & click to view media - alt & click saves file. Read for more options. - // @author despecial - // @match *://*.instagram.com/* - // @icon https://www.google.com/s2/favicons?domain=instagram.com - // @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js - // @grant GM_download - // @grant GM_xmlhttpRequest - // ==/UserScript== - - var ig = - '#react-root section main article header ~ div._97aPb > div[role="button"] .FFVAD'; // single photo - ig += ", #react-root section main article .tWeCl"; // single video - ig += ', div[role="dialog"] article ._97aPb > div[role="button"] .FFVAD'; // popup photo - ig += ', div[role="dialog"] article .tWeCl'; // popup video - ig += ", #react-root section main article .vi798"; // new carousel photo - ig += ', div[role="dialog"] .vi798'; // new popup carousel photo - // ig+= ', #react-root section main article video'; // igtv video - // ig+= ', div[role="dialog"] article header + div > div div div div video'; // popup igtv video - ig += ",.EmbedFrame.EmbedMedia"; - var alt_trigger = ig; - alt_trigger += - ', #react-root section main article[role="presentation"] div[aria-label="Control"]'; // click fix for videos - alt_trigger += - ', div[role="dialog"] article[role="presentation"] div[aria-label="Control"]'; // click fix for popup video - - (function ($) { - function despecial_ig(e, $this, a) { - if (!e) e = window.event; - if ((e.shiftKey && e.altKey) || a == "rm") { - var p, v, vf, bloburl; - e.preventDefault(); - - // carousel photos - if ($(".vi798 .Ckrof img.FFVAD").length) { - var curr = getCurrentItem(); - var carouselImages = $(".Ckrof img.FFVAD"); - var currpos = curr == $(".Yi5aA").length ? 2 : 1; - p = - curr + 1 <= 2 - ? getBestImage(carouselImages[curr]) - : getBestImage(carouselImages[currpos]); - } - // get single photo - else { - if ($this.is("img")) { - p = getBestImage($this); - } - } - - var parent = $this.parent(); - if ( - $('div[role="dialog"] article header + div').length && - a == "rm" - ) { - if (parent.find("video + img").length) return; // only visible video - v = parent.find("video").attr("videourl"); - if (!v) v = parent.find("video").attr("src"); - if (!v) vf = parent.find("video"); - if (!p) p = parent.find("img").last().attr("src"); - } else { - if (parent.find("video + img").length) return; // only visible video - v = parent.find("video").attr("videourl"); - if (!v) v = parent.find("video").attr("src"); - if (!v) v = $("meta[property='og:video']").attr("content"); - if (!v) vf = $this.closest("div").find("video"); - if (!v && !vf.attr("poster") && !p) - p = $this.siblings().find("img").attr("src"); - } - var ep = $this.find(".efImage").css("background-image"), - rplcd = new Array("XXXXXX"), - t = e.altKey ? "_self" : "_blank", - fs = - typeof ep === "string" || ep instanceof String - ? ep.replace(/^url\(['"]?([^'"]+)['"]?\)/, "$1") - : p; - for (var i = 0; i < rplcd.length; ++i) { - var r = new RegExp(rplcd[i], "ig"); - if (r.test(fs)) fs = fs.replace(r, ""); - } - var isChrome = !!window.chrome && !!window.chrome.webstore; - if (isChrome && e.altKey) { - if (fs) direct_download(fs); - if (vf) video_download(vf); - console.log("Chrome"); - } else { - if (v) { - if (!v.startsWith("blob")) { - window.open(v, t); - window.setTimeout(stopVideo, 100); - console.log("Video opening"); - } else { - bloburl = fetchVideoURL( - window.location.href, - $this.parent().find("video")[0], - t - ); - console.log("Blob video loading"); - } - } - if (!v && vf.isArray) { - if (!vf[0].getAttribute("src").startsWith("blob")) { - video_download(vf); - console.log("Video2 opening"); - } else { - bloburl = fetchVideoURL( - window.location.href, - $this.parent().find("video")[0], - t - ); - console.log("Blob2 video loading"); - } - } - if (fs && !v && !bloburl) { - window.open(fs, t); - console.log("FS"); - } - } - } - } - - /* dynamic download link */ - function direct_download(url) { - var filename = url.match("[^/]*$")[0]; - var arg = { url: url, name: filename }; - GM_download(arg); - } - - var csrf_token = $("body") - .html() - .match(/\"csrf_token\":(?:"[^"]*"|^[^"]*$)/)[0] - .replace(/\"/g, "") - .split(":")[1]; - - function video_download(obj) { - $.ajax({ - url: window.location, - type: "GET", - success: function (res) { - var video = $(res) - .filter("meta[property='og:video']") - .attr("content"); - if (video) { - $("video").each(function () { - $(this).get(0).pause(); - $(this).get(0).currentTime = 0; - }); - window.open(video, "_blank"); - } - }, - error: function (res) { - console.log(res); - }, - }); - } - - function getBestImage(el) { - el = el.jquery ? el : $(el); - var img; - var srcset = el.attr("srcset").split("w,"); - if (srcset) { - img = srcset.slice(-1)[0].split(" ")[0]; - // console.log("SrcSet P",img); - } else { - img = el.attr("src"); - // console.log("Normal P",img); - } - return img; - } - - function cleanFilename(file) { - return file.replace("jpg", "mp4").split("?")[0].split("/").pop(); - } - - function stopVideo() { - $("video").each(function () { - $(this).get(0).pause(); - $(this).get(0).currentTime = 0; - }); - } - - /* credits: @jomifepe */ - function getCurrentItem(el) { - var allitems = document.querySelectorAll(".Yi5aA"); - for (let i = 0; i < allitems.length; i++) { - if (allitems[i].classList.contains("XCodT")) { - return i; - } - } - return -1; - } - - function fetchVideoURL(baseUrl, videoElem, t) { - GM_xmlhttpRequest({ - method: "GET", - url: baseUrl.split("?")[0] + "?__a=1", - synchronous: false, - onload: function (response) { - var result = JSON.parse(response.responseText); - let postData = result?.graphql?.shortcode_media; - var current = getCurrentItem(); - if (current >= 0) - postData = - postData?.edge_sidecar_to_children?.edges?.[current]?.node; - if (!postData) throw "No post data found"; - if (!postData.is_video) throw "Post is not a video"; - if (!postData.video_url) throw "No video url found"; - let videoUrl = postData.video_url; - videoElem.setAttribute("videoURL", videoUrl); - window.open(videoUrl, t); - return true; - }, - }); - } - - /* left-click and hold shift key to open desired item */ - $(document).on("click", alt_trigger, function (e, a) { - e = window.event ? event : e; - if (e.shiftKey) despecial_ig(e, $(this), "rm"); - }); - - /* keyboard shortcut alt+f(ullsize) works on video popup, single photo, single video pages */ - $(document).on("ig_press", ig, function (e, a) { - despecial_ig(e, $(this), a); - }); - - document.addEventListener("keydown", function (e) { - e = window.event ? event : e; - if (e.keyCode == 70 && e.altKey) $(ig).trigger("ig_press", ["rm"]); - }); - })(jQuery); - }, -}; diff --git a/scripts/insta_storySaver.js b/scripts/insta_storySaver.js index d445e187..d0de9bf2 100644 --- a/scripts/insta_storySaver.js +++ b/scripts/insta_storySaver.js @@ -101,3 +101,29 @@ export default { else alert("Không tìm thấy instagram story nào trong trang web."); }, }; + +function backup() { + // https://greasyfork.org/en/scripts/404535-ig-helper/code + async function getStories(userId) { + let url = `https://www.instagram.com/graphql/query/?query_hash=15463e8449a83d3d60b06be7e90627c7&variables=%7B%22reel_ids%22:%5B%22${userId}%22%5D,%22precomposed_overlay%22:false%7D`; + let res = await fetch(url); + let json = await res.json(); + return json; + } + + async function getUserId(username) { + let url = `https://www.instagram.com/web/search/topsearch/?query=${username}`; + let res = await feetch(url); + let json = await res.json(); + return json.users[0]; + } + + // postPath example: /p/CixHwr6AxZ9/ + async function getBlobMedia(postPath) { + let postShortCode = postPath.substring(3, postPath.length - 1); + let url = `https://www.instagram.com/graphql/query/?query_hash=2c4c2e343a8f64c625ba02b2aa12c7f8&variables=%7B%22shortcode%22:%22${postShortCode}%22}`; + let res = await fetch(url); + let json = await res.json(); + return json.data; + } +} diff --git a/scripts/search_userscript.js b/scripts/search_userscript.js new file mode 100644 index 00000000..d23e35c0 --- /dev/null +++ b/scripts/search_userscript.js @@ -0,0 +1,19 @@ +export default { + icon: "https://www.tampermonkey.net/favicon.ico", + name: { + en: "Search Userscripts", + vi: "Tìm Userscripts", + }, + description: { + en: "Search Userscripts on Usersript.zone", + vi: "Tìm Userscripts trên Usersript.zone", + }, + runInExtensionContext: true, + + func: function () { + let search = prompt("Search for Userscripts:", ""); + if (search != null) { + window.open("https://www.userscript.zone/search?q=" + search); + } + }, +}; From 33b4da75f4508410a69beb54052a2e8db09995e1 Mon Sep 17 00:00:00 2001 From: "hoang.tran12" Date: Wed, 7 Dec 2022 17:00:38 +0700 Subject: [PATCH 031/164] vue not good + search --- manifest.json | 34 +- popup/helpers/category.js | 8 + popup/index.js | 36 + popup/popup.html | 5 + popup/styles/style.css | 21 +- popup/tabs.js | 40 +- scripts/backup/vue-test/index.html | 39 - scripts/backup/vue-test/index.js | 34 - scripts/backup/vue-test/vue.dev.js | 11894 --------------------------- scripts/backup/vue-test/vue.min.js | 11 - scripts/helpers/utils.js | 19 + 11 files changed, 115 insertions(+), 12026 deletions(-) delete mode 100644 scripts/backup/vue-test/index.html delete mode 100644 scripts/backup/vue-test/index.js delete mode 100644 scripts/backup/vue-test/vue.dev.js delete mode 100644 scripts/backup/vue-test/vue.min.js diff --git a/manifest.json b/manifest.json index 8472550a..acc13230 100644 --- a/manifest.json +++ b/manifest.json @@ -23,36 +23,22 @@ "declarativeNetRequestFeedback", "declarativeNetRequestWithHostAccess" ], - "host_permissions": [ - "" - ], + "host_permissions": [""], "options_page": "./pages/options/options.html", "content_scripts": [ { - "matches": [ - "" - ], - "js": [ - "scripts/content-scripts/document_start.js" - ], + "matches": [""], + "js": ["scripts/content-scripts/document_start.js"], "run_at": "document_start" }, { - "matches": [ - "" - ], - "js": [ - "scripts/content-scripts/document_idle.js" - ], + "matches": [""], + "js": ["scripts/content-scripts/document_idle.js"], "run_at": "document_idle" }, { - "matches": [ - "" - ], - "js": [ - "scripts/content-scripts/document_end.js" - ], + "matches": [""], + "js": ["scripts/content-scripts/document_end.js"], "run_at": "document_end" } ], @@ -62,9 +48,7 @@ "scripts/content-scripts/*.js", "scripts/content-scripts/*.css" ], - "matches": [ - "" - ] + "matches": [""] } ], "declarative_net_request": { @@ -76,4 +60,4 @@ } ] } -} \ No newline at end of file +} diff --git a/popup/helpers/category.js b/popup/helpers/category.js index f16fd426..3d4803eb 100644 --- a/popup/helpers/category.js +++ b/popup/helpers/category.js @@ -15,6 +15,14 @@ export const CATEGORY = { vi: ` Gần đây`, }, }, + all: { + id: "all", + style: { textDecoration: "underline" }, + name: { + en: ` All`, + vi: ` Tất cả`, + }, + }, available: { id: "available", showCount: true, diff --git a/popup/index.js b/popup/index.js index 5896df71..53b1df79 100644 --- a/popup/index.js +++ b/popup/index.js @@ -4,6 +4,7 @@ import { GlobalBlackList, isExtensionInSeperatedPopup, openExtensionInSeparatedPopup, + removeAccents, runScriptInCurrentTab, } from "../scripts/helpers/utils.js"; import { allScripts } from "../scripts/index.js"; @@ -29,6 +30,7 @@ const tabDiv = document.querySelector("div.tab"); const contentDiv = document.querySelector("div.content"); const flagImg = document.querySelector("img#flag"); const openInNewTabBtn = document.querySelector("#open-in-new-tab"); +const searchInput = document.querySelector(".search input"); async function initLanguage() { flagImg.setAttribute("src", await getFlag()); @@ -84,9 +86,16 @@ async function createTabs() { // open tab let activeTabId = await activeTabIdSaver.get(); activeTabId && openTab(allTabs.find((tab) => tab.id === activeTabId)); + + // change lang search + searchInput.placeholder = t({ + vi: "Tìm chức năng (tên, loại, mô tả...)", + en: "Search for function (name, desc, badge...)", + }); } async function openTab(tab) { + searchInput.value = ""; activeTabIdSaver.set(tab.id); createTabContent(tab); @@ -283,8 +292,35 @@ function initOpenInNewTabBtn() { } } +function doSearch(keyword) { + contentDiv.querySelectorAll("button.tooltip").forEach((button) => { + let willShow = true; + let btnText = removeAccents(button.innerText.toLowerCase()); + let searchStr = removeAccents(keyword.toLowerCase()) + .split(" ") + .filter((_) => _); + + for (let s of searchStr) { + if (!btnText.includes(s)) { + willShow = false; + break; + } + } + // button.style.opacity = willShow ? 1 : 0.1; + button.style.display = willShow ? "block" : "none"; + }); +} + +function initSearch() { + searchInput.addEventListener("input", (event) => { + let search = event.target.value; + doSearch(search); + }); +} + (async function () { initOpenInNewTabBtn(); + initSearch(); await initLanguage(); await createTabs(); await checkForUpdate(); diff --git a/popup/popup.html b/popup/popup.html index 4a49d4a5..bdeac313 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -26,6 +26,11 @@

+ + +
diff --git a/popup/styles/style.css b/popup/styles/style.css index db9102c7..6939723e 100644 --- a/popup/styles/style.css +++ b/popup/styles/style.css @@ -120,6 +120,25 @@ a:hover { background-color: #a8a8a8; } +/* ---------- Search --------- */ +.search { + text-align: center; + padding: 5px; + position: sticky; + top: 0; + z-index: 5; + background-color: inherit; +} + +.search input[type='text'] { + border: none; + padding: 5px 10px; + width: 50%; + text-align: center; + background-color: #f5f5f5; + width: 100%; +} + /* ---------- Content & content button ---------- */ .tabcontent { padding: 6px; @@ -134,7 +153,7 @@ a:hover { .section-title { padding: 10px 0 5px; position: sticky; - top: 0; + top: 30px; background-color: #e6e6e6; z-index: 1; margin-top: 15px; diff --git a/popup/tabs.js b/popup/tabs.js index 233466b1..b365d90f 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -19,15 +19,7 @@ const specialTabs = [ scripts: [], }, { - ...CATEGORY.hot, - scripts: [], - }, - { - ...CATEGORY.new, - scripts: [], - }, - { - ...CATEGORY.available, + ...CATEGORY.all, scripts: [], }, ]; @@ -476,21 +468,25 @@ async function refreshSpecialTabs() { // ==== special badge tab ==== let allScriptsArr = Object.values(s); - console.log(allScriptsArr); - let hotTab = specialTabs.find((tab) => tab.id === CATEGORY.hot.id); - if (hotTab) - hotTab.scripts = sortScriptsByTab( - getScriptsWithBadgeId(allScriptsArr, BADGES.hot.id), - tabs - ); + let allTab = specialTabs.find((tab) => tab.id === CATEGORY.all.id); + if (allTab) { + allTab.scripts = sortScriptsByTab(allScriptsArr, tabs); + } + + // let hotTab = specialTabs.find((tab) => tab.id === CATEGORY.hot.id); + // if (hotTab) + // hotTab.scripts = sortScriptsByTab( + // getScriptsWithBadgeId(allScriptsArr, BADGES.hot.id), + // tabs + // ); - let newTab = specialTabs.find((tab) => tab.id === CATEGORY.new.id); - if (newTab) - newTab.scripts = sortScriptsByTab( - getScriptsWithBadgeId(allScriptsArr, BADGES.new.id), - tabs - ); + // let newTab = specialTabs.find((tab) => tab.id === CATEGORY.new.id); + // if (newTab) + // newTab.scripts = sortScriptsByTab( + // getScriptsWithBadgeId(allScriptsArr, BADGES.new.id), + // tabs + // ); } function getAllTabs() { diff --git a/scripts/backup/vue-test/index.html b/scripts/backup/vue-test/index.html deleted file mode 100644 index 8d1380d1..00000000 --- a/scripts/backup/vue-test/index.html +++ /dev/null @@ -1,39 +0,0 @@ - -
- - - -
- - - -
-

{{ message }}

- - - - - -

- Hover your mouse over me for a few seconds - to see my dynamically bound title! -

- -

Now you see me

- -
    - - -
- -
    -
  1. - {{ todo.text }} -
  2. -
-
- - - - - \ No newline at end of file diff --git a/scripts/backup/vue-test/index.js b/scripts/backup/vue-test/index.js deleted file mode 100644 index 0e543328..00000000 --- a/scripts/backup/vue-test/index.js +++ /dev/null @@ -1,34 +0,0 @@ -// Define a new component called todo-item -Vue.component("todo-item", { - props: ["todo"], - template: "
  • {{ todo.text }}
  • ", -}); - -var app = new Vue({ - el: "#app", - data: { - message: "Hello Vue!", - title: "You loaded this page on " + new Date().toLocaleString(), - seen: true, - - todos: [ - { text: "Learn JavaScript" }, - { text: "Learn Vue" }, - { text: "Build something awesome" }, - ], - - groceryList: [ - { id: 0, text: "Vegetables" }, - { id: 1, text: "Cheese" }, - { id: 2, text: "Whatever else humans are supposed to eat" }, - ], - }, - - methods: { - reverseMessage: function () { - this.message = this.message.split("").reverse().join(""); - }, - }, -}); - -document.onclick = () => app.todos.push({ text: "New item " + new Date() }); diff --git a/scripts/backup/vue-test/vue.dev.js b/scripts/backup/vue-test/vue.dev.js deleted file mode 100644 index 04bcb375..00000000 --- a/scripts/backup/vue-test/vue.dev.js +++ /dev/null @@ -1,11894 +0,0 @@ -/*! - * Vue.js v2.7.13 - * (c) 2014-2022 Evan You - * Released under the MIT License. - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Vue = factory()); -})(this, (function () { 'use strict'; - - var emptyObject = Object.freeze({}); - var isArray = Array.isArray; - // These helpers produce better VM code in JS engines due to their - // explicitness and function inlining. - function isUndef(v) { - return v === undefined || v === null; - } - function isDef(v) { - return v !== undefined && v !== null; - } - function isTrue(v) { - return v === true; - } - function isFalse(v) { - return v === false; - } - /** - * Check if value is primitive. - */ - function isPrimitive(value) { - return (typeof value === 'string' || - typeof value === 'number' || - // $flow-disable-line - typeof value === 'symbol' || - typeof value === 'boolean'); - } - function isFunction(value) { - return typeof value === 'function'; - } - /** - * Quick object check - this is primarily used to tell - * objects from primitive values when we know the value - * is a JSON-compliant type. - */ - function isObject(obj) { - return obj !== null && typeof obj === 'object'; - } - /** - * Get the raw type string of a value, e.g., [object Object]. - */ - var _toString = Object.prototype.toString; - function toRawType(value) { - return _toString.call(value).slice(8, -1); - } - /** - * Strict object type check. Only returns true - * for plain JavaScript objects. - */ - function isPlainObject(obj) { - return _toString.call(obj) === '[object Object]'; - } - function isRegExp(v) { - return _toString.call(v) === '[object RegExp]'; - } - /** - * Check if val is a valid array index. - */ - function isValidArrayIndex(val) { - var n = parseFloat(String(val)); - return n >= 0 && Math.floor(n) === n && isFinite(val); - } - function isPromise(val) { - return (isDef(val) && - typeof val.then === 'function' && - typeof val.catch === 'function'); - } - /** - * Convert a value to a string that is actually rendered. - */ - function toString(val) { - return val == null - ? '' - : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) - ? JSON.stringify(val, null, 2) - : String(val); - } - /** - * Convert an input value to a number for persistence. - * If the conversion fails, return original string. - */ - function toNumber(val) { - var n = parseFloat(val); - return isNaN(n) ? val : n; - } - /** - * Make a map and return a function for checking if a key - * is in that map. - */ - function makeMap(str, expectsLowerCase) { - var map = Object.create(null); - var list = str.split(','); - for (var i = 0; i < list.length; i++) { - map[list[i]] = true; - } - return expectsLowerCase ? function (val) { return map[val.toLowerCase()]; } : function (val) { return map[val]; }; - } - /** - * Check if a tag is a built-in tag. - */ - var isBuiltInTag = makeMap('slot,component', true); - /** - * Check if an attribute is a reserved attribute. - */ - var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); - /** - * Remove an item from an array. - */ - function remove$2(arr, item) { - var len = arr.length; - if (len) { - // fast path for the only / last item - if (item === arr[len - 1]) { - arr.length = len - 1; - return; - } - var index = arr.indexOf(item); - if (index > -1) { - return arr.splice(index, 1); - } - } - } - /** - * Check whether an object has the property. - */ - var hasOwnProperty = Object.prototype.hasOwnProperty; - function hasOwn(obj, key) { - return hasOwnProperty.call(obj, key); - } - /** - * Create a cached version of a pure function. - */ - function cached(fn) { - var cache = Object.create(null); - return function cachedFn(str) { - var hit = cache[str]; - return hit || (cache[str] = fn(str)); - }; - } - /** - * Camelize a hyphen-delimited string. - */ - var camelizeRE = /-(\w)/g; - var camelize = cached(function (str) { - return str.replace(camelizeRE, function (_, c) { return (c ? c.toUpperCase() : ''); }); - }); - /** - * Capitalize a string. - */ - var capitalize = cached(function (str) { - return str.charAt(0).toUpperCase() + str.slice(1); - }); - /** - * Hyphenate a camelCase string. - */ - var hyphenateRE = /\B([A-Z])/g; - var hyphenate = cached(function (str) { - return str.replace(hyphenateRE, '-$1').toLowerCase(); - }); - /** - * Simple bind polyfill for environments that do not support it, - * e.g., PhantomJS 1.x. Technically, we don't need this anymore - * since native bind is now performant enough in most browsers. - * But removing it would mean breaking code that was able to run in - * PhantomJS 1.x, so this must be kept for backward compatibility. - */ - /* istanbul ignore next */ - function polyfillBind(fn, ctx) { - function boundFn(a) { - var l = arguments.length; - return l - ? l > 1 - ? fn.apply(ctx, arguments) - : fn.call(ctx, a) - : fn.call(ctx); - } - boundFn._length = fn.length; - return boundFn; - } - function nativeBind(fn, ctx) { - return fn.bind(ctx); - } - // @ts-expect-error bind cannot be `undefined` - var bind$1 = Function.prototype.bind ? nativeBind : polyfillBind; - /** - * Convert an Array-like object to a real Array. - */ - function toArray(list, start) { - start = start || 0; - var i = list.length - start; - var ret = new Array(i); - while (i--) { - ret[i] = list[i + start]; - } - return ret; - } - /** - * Mix properties into target object. - */ - function extend(to, _from) { - for (var key in _from) { - to[key] = _from[key]; - } - return to; - } - /** - * Merge an Array of Objects into a single Object. - */ - function toObject(arr) { - var res = {}; - for (var i = 0; i < arr.length; i++) { - if (arr[i]) { - extend(res, arr[i]); - } - } - return res; - } - /* eslint-disable no-unused-vars */ - /** - * Perform no operation. - * Stubbing args to make Flow happy without leaving useless transpiled code - * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/). - */ - function noop(a, b, c) { } - /** - * Always return false. - */ - var no = function (a, b, c) { return false; }; - /* eslint-enable no-unused-vars */ - /** - * Return the same value. - */ - var identity = function (_) { return _; }; - /** - * Generate a string containing static keys from compiler modules. - */ - function genStaticKeys$1(modules) { - return modules - .reduce(function (keys, m) { - return keys.concat(m.staticKeys || []); - }, []) - .join(','); - } - /** - * Check if two values are loosely equal - that is, - * if they are plain objects, do they have the same shape? - */ - function looseEqual(a, b) { - if (a === b) - return true; - var isObjectA = isObject(a); - var isObjectB = isObject(b); - if (isObjectA && isObjectB) { - try { - var isArrayA = Array.isArray(a); - var isArrayB = Array.isArray(b); - if (isArrayA && isArrayB) { - return (a.length === b.length && - a.every(function (e, i) { - return looseEqual(e, b[i]); - })); - } - else if (a instanceof Date && b instanceof Date) { - return a.getTime() === b.getTime(); - } - else if (!isArrayA && !isArrayB) { - var keysA = Object.keys(a); - var keysB = Object.keys(b); - return (keysA.length === keysB.length && - keysA.every(function (key) { - return looseEqual(a[key], b[key]); - })); - } - else { - /* istanbul ignore next */ - return false; - } - } - catch (e) { - /* istanbul ignore next */ - return false; - } - } - else if (!isObjectA && !isObjectB) { - return String(a) === String(b); - } - else { - return false; - } - } - /** - * Return the first index at which a loosely equal value can be - * found in the array (if value is a plain object, the array must - * contain an object of the same shape), or -1 if it is not present. - */ - function looseIndexOf(arr, val) { - for (var i = 0; i < arr.length; i++) { - if (looseEqual(arr[i], val)) - return i; - } - return -1; - } - /** - * Ensure a function is called only once. - */ - function once(fn) { - var called = false; - return function () { - if (!called) { - called = true; - fn.apply(this, arguments); - } - }; - } - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#polyfill - function hasChanged(x, y) { - if (x === y) { - return x === 0 && 1 / x !== 1 / y; - } - else { - return x === x || y === y; - } - } - - var SSR_ATTR = 'data-server-rendered'; - var ASSET_TYPES = ['component', 'directive', 'filter']; - var LIFECYCLE_HOOKS = [ - 'beforeCreate', - 'created', - 'beforeMount', - 'mounted', - 'beforeUpdate', - 'updated', - 'beforeDestroy', - 'destroyed', - 'activated', - 'deactivated', - 'errorCaptured', - 'serverPrefetch', - 'renderTracked', - 'renderTriggered' - ]; - - var config = { - /** - * Option merge strategies (used in core/util/options) - */ - // $flow-disable-line - optionMergeStrategies: Object.create(null), - /** - * Whether to suppress warnings. - */ - silent: false, - /** - * Show production mode tip message on boot? - */ - productionTip: true, - /** - * Whether to enable devtools - */ - devtools: true, - /** - * Whether to record perf - */ - performance: false, - /** - * Error handler for watcher errors - */ - errorHandler: null, - /** - * Warn handler for watcher warns - */ - warnHandler: null, - /** - * Ignore certain custom elements - */ - ignoredElements: [], - /** - * Custom user key aliases for v-on - */ - // $flow-disable-line - keyCodes: Object.create(null), - /** - * Check if a tag is reserved so that it cannot be registered as a - * component. This is platform-dependent and may be overwritten. - */ - isReservedTag: no, - /** - * Check if an attribute is reserved so that it cannot be used as a component - * prop. This is platform-dependent and may be overwritten. - */ - isReservedAttr: no, - /** - * Check if a tag is an unknown element. - * Platform-dependent. - */ - isUnknownElement: no, - /** - * Get the namespace of an element - */ - getTagNamespace: noop, - /** - * Parse the real tag name for the specific platform. - */ - parsePlatformTagName: identity, - /** - * Check if an attribute must be bound using property, e.g. value - * Platform-dependent. - */ - mustUseProp: no, - /** - * Perform updates asynchronously. Intended to be used by Vue Test Utils - * This will significantly reduce performance if set to false. - */ - async: true, - /** - * Exposed for legacy reasons - */ - _lifecycleHooks: LIFECYCLE_HOOKS - }; - - /** - * unicode letters used for parsing html tags, component names and property paths. - * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname - * skipping \u10000-\uEFFFF due to it freezing up PhantomJS - */ - var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/; - /** - * Check if a string starts with $ or _ - */ - function isReserved(str) { - var c = (str + '').charCodeAt(0); - return c === 0x24 || c === 0x5f; - } - /** - * Define a property. - */ - function def(obj, key, val, enumerable) { - Object.defineProperty(obj, key, { - value: val, - enumerable: !!enumerable, - writable: true, - configurable: true - }); - } - /** - * Parse simple path. - */ - var bailRE = new RegExp("[^".concat(unicodeRegExp.source, ".$_\\d]")); - function parsePath(path) { - if (bailRE.test(path)) { - return; - } - var segments = path.split('.'); - return function (obj) { - for (var i = 0; i < segments.length; i++) { - if (!obj) - return; - obj = obj[segments[i]]; - } - return obj; - }; - } - - // can we use __proto__? - var hasProto = '__proto__' in {}; - // Browser environment sniffing - var inBrowser = typeof window !== 'undefined'; - var UA = inBrowser && window.navigator.userAgent.toLowerCase(); - var isIE = UA && /msie|trident/.test(UA); - var isIE9 = UA && UA.indexOf('msie 9.0') > 0; - var isEdge = UA && UA.indexOf('edge/') > 0; - UA && UA.indexOf('android') > 0; - var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA); - UA && /chrome\/\d+/.test(UA) && !isEdge; - UA && /phantomjs/.test(UA); - var isFF = UA && UA.match(/firefox\/(\d+)/); - // Firefox has a "watch" function on Object.prototype... - // @ts-expect-error firebox support - var nativeWatch = {}.watch; - var supportsPassive = false; - if (inBrowser) { - try { - var opts = {}; - Object.defineProperty(opts, 'passive', { - get: function () { - /* istanbul ignore next */ - supportsPassive = true; - } - }); // https://github.com/facebook/flow/issues/285 - window.addEventListener('test-passive', null, opts); - } - catch (e) { } - } - // this needs to be lazy-evaled because vue may be required before - // vue-server-renderer can set VUE_ENV - var _isServer; - var isServerRendering = function () { - if (_isServer === undefined) { - /* istanbul ignore if */ - if (!inBrowser && typeof global !== 'undefined') { - // detect presence of vue-server-renderer and avoid - // Webpack shimming the process - _isServer = - global['process'] && global['process'].env.VUE_ENV === 'server'; - } - else { - _isServer = false; - } - } - return _isServer; - }; - // detect devtools - var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; - /* istanbul ignore next */ - function isNative(Ctor) { - return typeof Ctor === 'function' && /native code/.test(Ctor.toString()); - } - var hasSymbol = typeof Symbol !== 'undefined' && - isNative(Symbol) && - typeof Reflect !== 'undefined' && - isNative(Reflect.ownKeys); - var _Set; // $flow-disable-line - /* istanbul ignore if */ if (typeof Set !== 'undefined' && isNative(Set)) { - // use native Set when available. - _Set = Set; - } - else { - // a non-standard Set polyfill that only works with primitive keys. - _Set = /** @class */ (function () { - function Set() { - this.set = Object.create(null); - } - Set.prototype.has = function (key) { - return this.set[key] === true; - }; - Set.prototype.add = function (key) { - this.set[key] = true; - }; - Set.prototype.clear = function () { - this.set = Object.create(null); - }; - return Set; - }()); - } - - var currentInstance = null; - /** - * This is exposed for compatibility with v3 (e.g. some functions in VueUse - * relies on it). Do not use this internally, just use `currentInstance`. - * - * @internal this function needs manual type declaration because it relies - * on previously manually authored types from Vue 2 - */ - function getCurrentInstance() { - return currentInstance && { proxy: currentInstance }; - } - /** - * @internal - */ - function setCurrentInstance(vm) { - if (vm === void 0) { vm = null; } - if (!vm) - currentInstance && currentInstance._scope.off(); - currentInstance = vm; - vm && vm._scope.on(); - } - - /** - * @internal - */ - var VNode = /** @class */ (function () { - function VNode(tag, data, children, text, elm, context, componentOptions, asyncFactory) { - this.tag = tag; - this.data = data; - this.children = children; - this.text = text; - this.elm = elm; - this.ns = undefined; - this.context = context; - this.fnContext = undefined; - this.fnOptions = undefined; - this.fnScopeId = undefined; - this.key = data && data.key; - this.componentOptions = componentOptions; - this.componentInstance = undefined; - this.parent = undefined; - this.raw = false; - this.isStatic = false; - this.isRootInsert = true; - this.isComment = false; - this.isCloned = false; - this.isOnce = false; - this.asyncFactory = asyncFactory; - this.asyncMeta = undefined; - this.isAsyncPlaceholder = false; - } - Object.defineProperty(VNode.prototype, "child", { - // DEPRECATED: alias for componentInstance for backwards compat. - /* istanbul ignore next */ - get: function () { - return this.componentInstance; - }, - enumerable: false, - configurable: true - }); - return VNode; - }()); - var createEmptyVNode = function (text) { - if (text === void 0) { text = ''; } - var node = new VNode(); - node.text = text; - node.isComment = true; - return node; - }; - function createTextVNode(val) { - return new VNode(undefined, undefined, undefined, String(val)); - } - // optimized shallow clone - // used for static nodes and slot nodes because they may be reused across - // multiple renders, cloning them avoids errors when DOM manipulations rely - // on their elm reference. - function cloneVNode(vnode) { - var cloned = new VNode(vnode.tag, vnode.data, - // #7975 - // clone children array to avoid mutating original in case of cloning - // a child. - vnode.children && vnode.children.slice(), vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory); - cloned.ns = vnode.ns; - cloned.isStatic = vnode.isStatic; - cloned.key = vnode.key; - cloned.isComment = vnode.isComment; - cloned.fnContext = vnode.fnContext; - cloned.fnOptions = vnode.fnOptions; - cloned.fnScopeId = vnode.fnScopeId; - cloned.asyncMeta = vnode.asyncMeta; - cloned.isCloned = true; - return cloned; - } - - /* not type checking this file because flow doesn't play well with Proxy */ - var initProxy; - { - var allowedGlobals_1 = makeMap('Infinity,undefined,NaN,isFinite,isNaN,' + - 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + - 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' + - 'require' // for Webpack/Browserify - ); - var warnNonPresent_1 = function (target, key) { - warn$2("Property or method \"".concat(key, "\" is not defined on the instance but ") + - 'referenced during render. Make sure that this property is reactive, ' + - 'either in the data option, or for class-based components, by ' + - 'initializing the property. ' + - 'See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target); - }; - var warnReservedPrefix_1 = function (target, key) { - warn$2("Property \"".concat(key, "\" must be accessed with \"$data.").concat(key, "\" because ") + - 'properties starting with "$" or "_" are not proxied in the Vue instance to ' + - 'prevent conflicts with Vue internals. ' + - 'See: https://v2.vuejs.org/v2/api/#data', target); - }; - var hasProxy_1 = typeof Proxy !== 'undefined' && isNative(Proxy); - if (hasProxy_1) { - var isBuiltInModifier_1 = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact'); - config.keyCodes = new Proxy(config.keyCodes, { - set: function (target, key, value) { - if (isBuiltInModifier_1(key)) { - warn$2("Avoid overwriting built-in modifier in config.keyCodes: .".concat(key)); - return false; - } - else { - target[key] = value; - return true; - } - } - }); - } - var hasHandler_1 = { - has: function (target, key) { - var has = key in target; - var isAllowed = allowedGlobals_1(key) || - (typeof key === 'string' && - key.charAt(0) === '_' && - !(key in target.$data)); - if (!has && !isAllowed) { - if (key in target.$data) - warnReservedPrefix_1(target, key); - else - warnNonPresent_1(target, key); - } - return has || !isAllowed; - } - }; - var getHandler_1 = { - get: function (target, key) { - if (typeof key === 'string' && !(key in target)) { - if (key in target.$data) - warnReservedPrefix_1(target, key); - else - warnNonPresent_1(target, key); - } - return target[key]; - } - }; - initProxy = function initProxy(vm) { - if (hasProxy_1) { - // determine which proxy handler to use - var options = vm.$options; - var handlers = options.render && options.render._withStripped ? getHandler_1 : hasHandler_1; - vm._renderProxy = new Proxy(vm, handlers); - } - else { - vm._renderProxy = vm; - } - }; - } - - /****************************************************************************** - Copyright (c) Microsoft Corporation. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */ - - var __assign = function() { - __assign = Object.assign || function __assign(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); - }; - - var uid$2 = 0; - var pendingCleanupDeps = []; - var cleanupDeps = function () { - for (var i = 0; i < pendingCleanupDeps.length; i++) { - var dep = pendingCleanupDeps[i]; - dep.subs = dep.subs.filter(function (s) { return s; }); - dep._pending = false; - } - pendingCleanupDeps.length = 0; - }; - /** - * A dep is an observable that can have multiple - * directives subscribing to it. - * @internal - */ - var Dep = /** @class */ (function () { - function Dep() { - // pending subs cleanup - this._pending = false; - this.id = uid$2++; - this.subs = []; - } - Dep.prototype.addSub = function (sub) { - this.subs.push(sub); - }; - Dep.prototype.removeSub = function (sub) { - // #12696 deps with massive amount of subscribers are extremely slow to - // clean up in Chromium - // to workaround this, we unset the sub for now, and clear them on - // next scheduler flush. - this.subs[this.subs.indexOf(sub)] = null; - if (!this._pending) { - this._pending = true; - pendingCleanupDeps.push(this); - } - }; - Dep.prototype.depend = function (info) { - if (Dep.target) { - Dep.target.addDep(this); - if (info && Dep.target.onTrack) { - Dep.target.onTrack(__assign({ effect: Dep.target }, info)); - } - } - }; - Dep.prototype.notify = function (info) { - // stabilize the subscriber list first - var subs = this.subs.filter(function (s) { return s; }); - if (!config.async) { - // subs aren't sorted in scheduler if not running async - // we need to sort them now to make sure they fire in correct - // order - subs.sort(function (a, b) { return a.id - b.id; }); - } - for (var i = 0, l = subs.length; i < l; i++) { - var sub = subs[i]; - if (info) { - sub.onTrigger && - sub.onTrigger(__assign({ effect: subs[i] }, info)); - } - sub.update(); - } - }; - return Dep; - }()); - // The current target watcher being evaluated. - // This is globally unique because only one watcher - // can be evaluated at a time. - Dep.target = null; - var targetStack = []; - function pushTarget(target) { - targetStack.push(target); - Dep.target = target; - } - function popTarget() { - targetStack.pop(); - Dep.target = targetStack[targetStack.length - 1]; - } - - /* - * not type checking this file because flow doesn't play well with - * dynamically accessing methods on Array prototype - */ - var arrayProto = Array.prototype; - var arrayMethods = Object.create(arrayProto); - var methodsToPatch = [ - 'push', - 'pop', - 'shift', - 'unshift', - 'splice', - 'sort', - 'reverse' - ]; - /** - * Intercept mutating methods and emit events - */ - methodsToPatch.forEach(function (method) { - // cache original method - var original = arrayProto[method]; - def(arrayMethods, method, function mutator() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var result = original.apply(this, args); - var ob = this.__ob__; - var inserted; - switch (method) { - case 'push': - case 'unshift': - inserted = args; - break; - case 'splice': - inserted = args.slice(2); - break; - } - if (inserted) - ob.observeArray(inserted); - // notify change - { - ob.dep.notify({ - type: "array mutation" /* TriggerOpTypes.ARRAY_MUTATION */, - target: this, - key: method - }); - } - return result; - }); - }); - - var rawMap = new WeakMap(); - function reactive(target) { - makeReactive(target, false); - return target; - } - /** - * Return a shallowly-reactive copy of the original object, where only the root - * level properties are reactive. It also does not auto-unwrap refs (even at the - * root level). - */ - function shallowReactive(target) { - makeReactive(target, true); - def(target, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true); - return target; - } - function makeReactive(target, shallow) { - // if trying to observe a readonly proxy, return the readonly version. - if (!isReadonly(target)) { - { - if (isArray(target)) { - warn$2("Avoid using Array as root value for ".concat(shallow ? "shallowReactive()" : "reactive()", " as it cannot be tracked in watch() or watchEffect(). Use ").concat(shallow ? "shallowRef()" : "ref()", " instead. This is a Vue-2-only limitation.")); - } - var existingOb = target && target.__ob__; - if (existingOb && existingOb.shallow !== shallow) { - warn$2("Target is already a ".concat(existingOb.shallow ? "" : "non-", "shallow reactive object, and cannot be converted to ").concat(shallow ? "" : "non-", "shallow.")); - } - } - var ob = observe(target, shallow, isServerRendering() /* ssr mock reactivity */); - if (!ob) { - if (target == null || isPrimitive(target)) { - warn$2("value cannot be made reactive: ".concat(String(target))); - } - if (isCollectionType(target)) { - warn$2("Vue 2 does not support reactive collection types such as Map or Set."); - } - } - } - } - function isReactive(value) { - if (isReadonly(value)) { - return isReactive(value["__v_raw" /* ReactiveFlags.RAW */]); - } - return !!(value && value.__ob__); - } - function isShallow(value) { - return !!(value && value.__v_isShallow); - } - function isReadonly(value) { - return !!(value && value.__v_isReadonly); - } - function isProxy(value) { - return isReactive(value) || isReadonly(value); - } - function toRaw(observed) { - var raw = observed && observed["__v_raw" /* ReactiveFlags.RAW */]; - return raw ? toRaw(raw) : observed; - } - function markRaw(value) { - if (isObject(value)) { - rawMap.set(value, true); - } - return value; - } - /** - * @internal - */ - function isCollectionType(value) { - var type = toRawType(value); - return (type === 'Map' || type === 'WeakMap' || type === 'Set' || type === 'WeakSet'); - } - - var arrayKeys = Object.getOwnPropertyNames(arrayMethods); - var NO_INIITIAL_VALUE = {}; - /** - * In some cases we may want to disable observation inside a component's - * update computation. - */ - var shouldObserve = true; - function toggleObserving(value) { - shouldObserve = value; - } - // ssr mock dep - var mockDep = { - notify: noop, - depend: noop, - addSub: noop, - removeSub: noop - }; - /** - * Observer class that is attached to each observed - * object. Once attached, the observer converts the target - * object's property keys into getter/setters that - * collect dependencies and dispatch updates. - */ - var Observer = /** @class */ (function () { - function Observer(value, shallow, mock) { - if (shallow === void 0) { shallow = false; } - if (mock === void 0) { mock = false; } - this.value = value; - this.shallow = shallow; - this.mock = mock; - // this.value = value - this.dep = mock ? mockDep : new Dep(); - this.vmCount = 0; - def(value, '__ob__', this); - if (isArray(value)) { - if (!mock) { - if (hasProto) { - value.__proto__ = arrayMethods; - /* eslint-enable no-proto */ - } - else { - for (var i = 0, l = arrayKeys.length; i < l; i++) { - var key = arrayKeys[i]; - def(value, key, arrayMethods[key]); - } - } - } - if (!shallow) { - this.observeArray(value); - } - } - else { - /** - * Walk through all properties and convert them into - * getter/setters. This method should only be called when - * value type is Object. - */ - var keys = Object.keys(value); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - defineReactive(value, key, NO_INIITIAL_VALUE, undefined, shallow, mock); - } - } - } - /** - * Observe a list of Array items. - */ - Observer.prototype.observeArray = function (value) { - for (var i = 0, l = value.length; i < l; i++) { - observe(value[i], false, this.mock); - } - }; - return Observer; - }()); - // helpers - /** - * Attempt to create an observer instance for a value, - * returns the new observer if successfully observed, - * or the existing observer if the value already has one. - */ - function observe(value, shallow, ssrMockReactivity) { - if (value && hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { - return value.__ob__; - } - if (shouldObserve && - (ssrMockReactivity || !isServerRendering()) && - (isArray(value) || isPlainObject(value)) && - Object.isExtensible(value) && - !value.__v_skip /* ReactiveFlags.SKIP */ && - !rawMap.has(value) && - !isRef(value) && - !(value instanceof VNode)) { - return new Observer(value, shallow, ssrMockReactivity); - } - } - /** - * Define a reactive property on an Object. - */ - function defineReactive(obj, key, val, customSetter, shallow, mock) { - var dep = new Dep(); - var property = Object.getOwnPropertyDescriptor(obj, key); - if (property && property.configurable === false) { - return; - } - // cater for pre-defined getter/setters - var getter = property && property.get; - var setter = property && property.set; - if ((!getter || setter) && - (val === NO_INIITIAL_VALUE || arguments.length === 2)) { - val = obj[key]; - } - var childOb = !shallow && observe(val, false, mock); - Object.defineProperty(obj, key, { - enumerable: true, - configurable: true, - get: function reactiveGetter() { - var value = getter ? getter.call(obj) : val; - if (Dep.target) { - { - dep.depend({ - target: obj, - type: "get" /* TrackOpTypes.GET */, - key: key - }); - } - if (childOb) { - childOb.dep.depend(); - if (isArray(value)) { - dependArray(value); - } - } - } - return isRef(value) && !shallow ? value.value : value; - }, - set: function reactiveSetter(newVal) { - var value = getter ? getter.call(obj) : val; - if (!hasChanged(value, newVal)) { - return; - } - if (customSetter) { - customSetter(); - } - if (setter) { - setter.call(obj, newVal); - } - else if (getter) { - // #7981: for accessor properties without setter - return; - } - else if (!shallow && isRef(value) && !isRef(newVal)) { - value.value = newVal; - return; - } - else { - val = newVal; - } - childOb = !shallow && observe(newVal, false, mock); - { - dep.notify({ - type: "set" /* TriggerOpTypes.SET */, - target: obj, - key: key, - newValue: newVal, - oldValue: value - }); - } - } - }); - return dep; - } - function set(target, key, val) { - if ((isUndef(target) || isPrimitive(target))) { - warn$2("Cannot set reactive property on undefined, null, or primitive value: ".concat(target)); - } - if (isReadonly(target)) { - warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly.")); - return; - } - var ob = target.__ob__; - if (isArray(target) && isValidArrayIndex(key)) { - target.length = Math.max(target.length, key); - target.splice(key, 1, val); - // when mocking for SSR, array methods are not hijacked - if (ob && !ob.shallow && ob.mock) { - observe(val, false, true); - } - return val; - } - if (key in target && !(key in Object.prototype)) { - target[key] = val; - return val; - } - if (target._isVue || (ob && ob.vmCount)) { - warn$2('Avoid adding reactive properties to a Vue instance or its root $data ' + - 'at runtime - declare it upfront in the data option.'); - return val; - } - if (!ob) { - target[key] = val; - return val; - } - defineReactive(ob.value, key, val, undefined, ob.shallow, ob.mock); - { - ob.dep.notify({ - type: "add" /* TriggerOpTypes.ADD */, - target: target, - key: key, - newValue: val, - oldValue: undefined - }); - } - return val; - } - function del(target, key) { - if ((isUndef(target) || isPrimitive(target))) { - warn$2("Cannot delete reactive property on undefined, null, or primitive value: ".concat(target)); - } - if (isArray(target) && isValidArrayIndex(key)) { - target.splice(key, 1); - return; - } - var ob = target.__ob__; - if (target._isVue || (ob && ob.vmCount)) { - warn$2('Avoid deleting properties on a Vue instance or its root $data ' + - '- just set it to null.'); - return; - } - if (isReadonly(target)) { - warn$2("Delete operation on key \"".concat(key, "\" failed: target is readonly.")); - return; - } - if (!hasOwn(target, key)) { - return; - } - delete target[key]; - if (!ob) { - return; - } - { - ob.dep.notify({ - type: "delete" /* TriggerOpTypes.DELETE */, - target: target, - key: key - }); - } - } - /** - * Collect dependencies on array elements when the array is touched, since - * we cannot intercept array element access like property getters. - */ - function dependArray(value) { - for (var e = void 0, i = 0, l = value.length; i < l; i++) { - e = value[i]; - if (e && e.__ob__) { - e.__ob__.dep.depend(); - } - if (isArray(e)) { - dependArray(e); - } - } - } - - /** - * @internal - */ - var RefFlag = "__v_isRef"; - function isRef(r) { - return !!(r && r.__v_isRef === true); - } - function ref$1(value) { - return createRef(value, false); - } - function shallowRef(value) { - return createRef(value, true); - } - function createRef(rawValue, shallow) { - if (isRef(rawValue)) { - return rawValue; - } - var ref = {}; - def(ref, RefFlag, true); - def(ref, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, shallow); - def(ref, 'dep', defineReactive(ref, 'value', rawValue, null, shallow, isServerRendering())); - return ref; - } - function triggerRef(ref) { - if (!ref.dep) { - warn$2("received object is not a triggerable ref."); - } - { - ref.dep && - ref.dep.notify({ - type: "set" /* TriggerOpTypes.SET */, - target: ref, - key: 'value' - }); - } - } - function unref(ref) { - return isRef(ref) ? ref.value : ref; - } - function proxyRefs(objectWithRefs) { - if (isReactive(objectWithRefs)) { - return objectWithRefs; - } - var proxy = {}; - var keys = Object.keys(objectWithRefs); - for (var i = 0; i < keys.length; i++) { - proxyWithRefUnwrap(proxy, objectWithRefs, keys[i]); - } - return proxy; - } - function proxyWithRefUnwrap(target, source, key) { - Object.defineProperty(target, key, { - enumerable: true, - configurable: true, - get: function () { - var val = source[key]; - if (isRef(val)) { - return val.value; - } - else { - var ob = val && val.__ob__; - if (ob) - ob.dep.depend(); - return val; - } - }, - set: function (value) { - var oldValue = source[key]; - if (isRef(oldValue) && !isRef(value)) { - oldValue.value = value; - } - else { - source[key] = value; - } - } - }); - } - function customRef(factory) { - var dep = new Dep(); - var _a = factory(function () { - { - dep.depend({ - target: ref, - type: "get" /* TrackOpTypes.GET */, - key: 'value' - }); - } - }, function () { - { - dep.notify({ - target: ref, - type: "set" /* TriggerOpTypes.SET */, - key: 'value' - }); - } - }), get = _a.get, set = _a.set; - var ref = { - get value() { - return get(); - }, - set value(newVal) { - set(newVal); - } - }; - def(ref, RefFlag, true); - return ref; - } - function toRefs(object) { - if (!isReactive(object)) { - warn$2("toRefs() expects a reactive object but received a plain one."); - } - var ret = isArray(object) ? new Array(object.length) : {}; - for (var key in object) { - ret[key] = toRef(object, key); - } - return ret; - } - function toRef(object, key, defaultValue) { - var val = object[key]; - if (isRef(val)) { - return val; - } - var ref = { - get value() { - var val = object[key]; - return val === undefined ? defaultValue : val; - }, - set value(newVal) { - object[key] = newVal; - } - }; - def(ref, RefFlag, true); - return ref; - } - - var rawToReadonlyMap = new WeakMap(); - var rawToShallowReadonlyMap = new WeakMap(); - function readonly(target) { - return createReadonly(target, false); - } - function createReadonly(target, shallow) { - if (!isPlainObject(target)) { - { - if (isArray(target)) { - warn$2("Vue 2 does not support readonly arrays."); - } - else if (isCollectionType(target)) { - warn$2("Vue 2 does not support readonly collection types such as Map or Set."); - } - else { - warn$2("value cannot be made readonly: ".concat(typeof target)); - } - } - return target; - } - // already a readonly object - if (isReadonly(target)) { - return target; - } - // already has a readonly proxy - var map = shallow ? rawToShallowReadonlyMap : rawToReadonlyMap; - var existingProxy = map.get(target); - if (existingProxy) { - return existingProxy; - } - var proxy = Object.create(Object.getPrototypeOf(target)); - map.set(target, proxy); - def(proxy, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, true); - def(proxy, "__v_raw" /* ReactiveFlags.RAW */, target); - if (isRef(target)) { - def(proxy, RefFlag, true); - } - if (shallow || isShallow(target)) { - def(proxy, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true); - } - var keys = Object.keys(target); - for (var i = 0; i < keys.length; i++) { - defineReadonlyProperty(proxy, target, keys[i], shallow); - } - return proxy; - } - function defineReadonlyProperty(proxy, target, key, shallow) { - Object.defineProperty(proxy, key, { - enumerable: true, - configurable: true, - get: function () { - var val = target[key]; - return shallow || !isPlainObject(val) ? val : readonly(val); - }, - set: function () { - warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly.")); - } - }); - } - /** - * Returns a reactive-copy of the original object, where only the root level - * properties are readonly, and does NOT unwrap refs nor recursively convert - * returned properties. - * This is used for creating the props proxy object for stateful components. - */ - function shallowReadonly(target) { - return createReadonly(target, true); - } - - function computed(getterOrOptions, debugOptions) { - var getter; - var setter; - var onlyGetter = isFunction(getterOrOptions); - if (onlyGetter) { - getter = getterOrOptions; - setter = function () { - warn$2('Write operation failed: computed value is readonly'); - } - ; - } - else { - getter = getterOrOptions.get; - setter = getterOrOptions.set; - } - var watcher = isServerRendering() - ? null - : new Watcher(currentInstance, getter, noop, { lazy: true }); - if (watcher && debugOptions) { - watcher.onTrack = debugOptions.onTrack; - watcher.onTrigger = debugOptions.onTrigger; - } - var ref = { - // some libs rely on the presence effect for checking computed refs - // from normal refs, but the implementation doesn't matter - effect: watcher, - get value() { - if (watcher) { - if (watcher.dirty) { - watcher.evaluate(); - } - if (Dep.target) { - if (Dep.target.onTrack) { - Dep.target.onTrack({ - effect: Dep.target, - target: ref, - type: "get" /* TrackOpTypes.GET */, - key: 'value' - }); - } - watcher.depend(); - } - return watcher.value; - } - else { - return getter(); - } - }, - set value(newVal) { - setter(newVal); - } - }; - def(ref, RefFlag, true); - def(ref, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, onlyGetter); - return ref; - } - - var mark; - var measure; - { - var perf_1 = inBrowser && window.performance; - /* istanbul ignore if */ - if (perf_1 && - // @ts-ignore - perf_1.mark && - // @ts-ignore - perf_1.measure && - // @ts-ignore - perf_1.clearMarks && - // @ts-ignore - perf_1.clearMeasures) { - mark = function (tag) { return perf_1.mark(tag); }; - measure = function (name, startTag, endTag) { - perf_1.measure(name, startTag, endTag); - perf_1.clearMarks(startTag); - perf_1.clearMarks(endTag); - // perf.clearMeasures(name) - }; - } - } - - var normalizeEvent = cached(function (name) { - var passive = name.charAt(0) === '&'; - name = passive ? name.slice(1) : name; - var once = name.charAt(0) === '~'; // Prefixed last, checked first - name = once ? name.slice(1) : name; - var capture = name.charAt(0) === '!'; - name = capture ? name.slice(1) : name; - return { - name: name, - once: once, - capture: capture, - passive: passive - }; - }); - function createFnInvoker(fns, vm) { - function invoker() { - var fns = invoker.fns; - if (isArray(fns)) { - var cloned = fns.slice(); - for (var i = 0; i < cloned.length; i++) { - invokeWithErrorHandling(cloned[i], null, arguments, vm, "v-on handler"); - } - } - else { - // return handler return value for single handlers - return invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler"); - } - } - invoker.fns = fns; - return invoker; - } - function updateListeners(on, oldOn, add, remove, createOnceHandler, vm) { - var name, cur, old, event; - for (name in on) { - cur = on[name]; - old = oldOn[name]; - event = normalizeEvent(name); - if (isUndef(cur)) { - warn$2("Invalid handler for event \"".concat(event.name, "\": got ") + String(cur), vm); - } - else if (isUndef(old)) { - if (isUndef(cur.fns)) { - cur = on[name] = createFnInvoker(cur, vm); - } - if (isTrue(event.once)) { - cur = on[name] = createOnceHandler(event.name, cur, event.capture); - } - add(event.name, cur, event.capture, event.passive, event.params); - } - else if (cur !== old) { - old.fns = cur; - on[name] = old; - } - } - for (name in oldOn) { - if (isUndef(on[name])) { - event = normalizeEvent(name); - remove(event.name, oldOn[name], event.capture); - } - } - } - - function mergeVNodeHook(def, hookKey, hook) { - if (def instanceof VNode) { - def = def.data.hook || (def.data.hook = {}); - } - var invoker; - var oldHook = def[hookKey]; - function wrappedHook() { - hook.apply(this, arguments); - // important: remove merged hook to ensure it's called only once - // and prevent memory leak - remove$2(invoker.fns, wrappedHook); - } - if (isUndef(oldHook)) { - // no existing hook - invoker = createFnInvoker([wrappedHook]); - } - else { - /* istanbul ignore if */ - if (isDef(oldHook.fns) && isTrue(oldHook.merged)) { - // already a merged invoker - invoker = oldHook; - invoker.fns.push(wrappedHook); - } - else { - // existing plain hook - invoker = createFnInvoker([oldHook, wrappedHook]); - } - } - invoker.merged = true; - def[hookKey] = invoker; - } - - function extractPropsFromVNodeData(data, Ctor, tag) { - // we are only extracting raw values here. - // validation and default values are handled in the child - // component itself. - var propOptions = Ctor.options.props; - if (isUndef(propOptions)) { - return; - } - var res = {}; - var attrs = data.attrs, props = data.props; - if (isDef(attrs) || isDef(props)) { - for (var key in propOptions) { - var altKey = hyphenate(key); - { - var keyInLowerCase = key.toLowerCase(); - if (key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase)) { - tip("Prop \"".concat(keyInLowerCase, "\" is passed to component ") + - "".concat(formatComponentName( - // @ts-expect-error tag is string - tag || Ctor), ", but the declared prop name is") + - " \"".concat(key, "\". ") + - "Note that HTML attributes are case-insensitive and camelCased " + - "props need to use their kebab-case equivalents when using in-DOM " + - "templates. You should probably use \"".concat(altKey, "\" instead of \"").concat(key, "\".")); - } - } - checkProp(res, props, key, altKey, true) || - checkProp(res, attrs, key, altKey, false); - } - } - return res; - } - function checkProp(res, hash, key, altKey, preserve) { - if (isDef(hash)) { - if (hasOwn(hash, key)) { - res[key] = hash[key]; - if (!preserve) { - delete hash[key]; - } - return true; - } - else if (hasOwn(hash, altKey)) { - res[key] = hash[altKey]; - if (!preserve) { - delete hash[altKey]; - } - return true; - } - } - return false; - } - - // The template compiler attempts to minimize the need for normalization by - // statically analyzing the template at compile time. - // - // For plain HTML markup, normalization can be completely skipped because the - // generated render function is guaranteed to return Array. There are - // two cases where extra normalization is needed: - // 1. When the children contains components - because a functional component - // may return an Array instead of a single root. In this case, just a simple - // normalization is needed - if any child is an Array, we flatten the whole - // thing with Array.prototype.concat. It is guaranteed to be only 1-level deep - // because functional components already normalize their own children. - function simpleNormalizeChildren(children) { - for (var i = 0; i < children.length; i++) { - if (isArray(children[i])) { - return Array.prototype.concat.apply([], children); - } - } - return children; - } - // 2. When the children contains constructs that always generated nested Arrays, - // e.g.