diff --git a/popup/tabs.js b/popup/tabs.js index 98c5aaa6..cc8f5929 100644 --- a/popup/tabs.js +++ b/popup/tabs.js @@ -499,6 +499,7 @@ const tabs = [ ...CATEGORY.youtube, scripts: [ s.youtube_downloadVideo, + s.youtube_downloadVideoUI, s.youtube_getVideoThumbnail, s.youtube_getVideoCaption, s.youtube_toggleLight, diff --git a/scripts/_index.js b/scripts/_index.js index b6885f8a..2a6047d3 100644 --- a/scripts/_index.js +++ b/scripts/_index.js @@ -167,5 +167,7 @@ export { default as showImageOnHoverLink } from "./showImageOnHoverLink.js"; export { default as fb_allInOne } from "./fb_allInOne.js"; export { default as fb_getPostReactionCount } from "./fb_getPostReactionCount.js"; export { default as bypass_learnAnything } from "./bypass_learnAnything.js"; +export { default as youtube_downloadVideoUI } from "./youtube_downloadVideoUI.js"; +export { default as youglish_search } from "./youglish_search.js"; export { default as youtube_getVideoThumbnail } from "./youtube_getVideoThumbnail.js"; export { default as youtube_getVideoCaption } from "./youtube_getVideoCaption.js"; diff --git a/scripts/youglish_search.js b/scripts/youglish_search.js new file mode 100644 index 00000000..36d6e7da --- /dev/null +++ b/scripts/youglish_search.js @@ -0,0 +1,47 @@ +import { BADGES } from './helpers/badge.js'; + +const contextMenuId = 'youglish-search'; + +export default { + icon: '', + name: { + en: 'YouGlish search', + vi: 'Tìm kiếm trên YouGlish', + }, + description: { + en: "Master English pronunciation naturally! Learn how to pronounce tricky sounds like a native with YouGlish's real-world clips. No more dictionary confusion, just real English in context. (from 'youglish.com')", + vi: 'Làm chủ phát âm tiếng Anh một cách tự nhiên! Học cách phát âm những âm thanh khó khăn như người bản xứ với các đoạn video thực tế từ YouGlish. Không còn bối rối với từ điển, chỉ có tiếng Anh thực sự trong ngữ cảnh. (từ "youglish.com")', + }, + badges: [BADGES.new], + changeLogs: { + '2024-07-06': 'init', + }, + + popupScript: { + onClick: () => window.close(), + }, + + backgroundScript: { + runtime: { + onInstalled: () => { + chrome.contextMenus.create({ + title: 'YouGlish Search', + contexts: ['selection'], + id: contextMenuId, + parentId: 'root', + }); + }, + }, + contextMenus: { + onClicked: ({ info }, context) => { + if (info.menuItemId == contextMenuId) { + const content = (info.selectionText || '').trim().toLowerCase(); + if (!content.length) return; + + const link = `https://youglish.com/pronounce/${content}/english`; + chrome.tabs.create({ url: link }); + } + }, + }, + }, +}; diff --git a/scripts/youtube_downloadVideoUI.js b/scripts/youtube_downloadVideoUI.js new file mode 100644 index 00000000..a9c22a7b --- /dev/null +++ b/scripts/youtube_downloadVideoUI.js @@ -0,0 +1,114 @@ +import { BADGES } from './helpers/badge.js'; + +export default { + icon: `https://www.youtube.com/s/desktop/ff71ea81/img/favicon_48x48.png`, + name: { + en: 'Render buttons to download youtube video/audio', + vi: 'Tạo các nút để tải video/audio youtube', + }, + description: { + en: 'Bypass age restriction, without login', + vi: 'Tải cả video giới hạn độ tuổi, không cần đăng nhập', + }, + badges: [BADGES.new], + + contentScript: { + onDocumentIdle: () => { + setTimeout(function () { + // https://stackoverflow.com/a/8260383/11898496 + function getIdFromYoutubeURL(url) { + let regExp = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/; + let match = url.match(regExp); + return match && match[1].length == 11 ? match[1] : false; + } + + const colors = { + default: '#272727', + green: '#2fb024', + red: '#e62e2e', + blue: '#3034bd', + }; + + const providers = [ + { + name: 'savefrom.net', + color: colors.green, + func: (url) => url.replace('youtube', 'ssyoutube'), + }, + { + name: '10downloader.com', + color: colors.blue, + func: (url) => url.replace('youtube', '000tube'), + }, + { + name: 'y2mate.com', + color: colors.red, + func: (url) => url.replace('youtube', 'youtubepp'), + }, + { + name: 'yt5s.com', + color: colors.blue, + func: (url) => url.replace('youtube', 'youtube5s'), + }, + { + name: 'yt1s.com', + color: colors.red, + func: (url) => 'https://yt1s.com/vi/youtube-to-mp4?q=' + url, + }, + { + name: 'tubemp3.to', + color: colors.default, + func: (url) => 'https://tubemp3.to/' + url, + }, + { + name: '10downloader.com', + color: colors.default, + func: (url) => 'https://10downloader.com/download?v=' + url, + }, + { + name: '9xbuddy.com', + color: colors.default, + func: (url) => 'https://9xbuddy.com/process?url=' + url, + }, + { + name: 'ymp4.com', + color: colors.default, + func: (url) => 'https://ymp4.download/en50/?url=' + url, + }, + { + name: 'getlinks.vip', + color: colors.default, + func: (url) => 'https://getlinks.vip/vi/youtube/' + getIdFromYoutubeURL(url), + }, + ]; + + const videoUrl = window.location.href; + + const genDownloadLinkFromProvider = (provider, url) => + /* html */ + `${provider.name}`; + + let intervalId = setInterval(function () { + const container = document.querySelector('#above-the-fold #title > h1'); + if (!container) return; + + clearInterval(intervalId); + + const links = providers.map((provider) => genDownloadLinkFromProvider(provider, videoUrl)); + + container.insertAdjacentHTML( + 'afterend', + /* html */ + `