diff --git a/browser-extension/README.md b/browser-extension/README.md new file mode 100644 index 0000000..df92c05 --- /dev/null +++ b/browser-extension/README.md @@ -0,0 +1,5 @@ +# OTOMADB Browser Extension + +## Disclaimer + +Code is heavily inspired from lachrymaLF/otodb. diff --git a/browser-extension/icons/512.png b/browser-extension/icons/512.png new file mode 100644 index 0000000..508c05e Binary files /dev/null and b/browser-extension/icons/512.png differ diff --git a/browser-extension/main.js b/browser-extension/main.js new file mode 100644 index 0000000..4bbffa5 --- /dev/null +++ b/browser-extension/main.js @@ -0,0 +1,132 @@ +async function injectContainer(inject) { + const $container = document.createElement('div'); + $container.id = 'otomadb-container'; + + const $containerTitle = document.createElement('p'); + $containerTitle.innerText = "OTOMADB Data"; + $containerTitle.setAttribute("class", "otomadb-title"); + $container.appendChild($containerTitle); + + const $status = document.createElement('p'); + $status.innerText = "Fetching..."; + $container.appendChild($status); + + inject($container); + + const apiUrl = new URL("/api/extension", "http:localhost:5173"); + apiUrl.searchParams.set("url", window.location.toString()); + + const res = await fetch(apiUrl.toString(), { mode: 'cors' }); + if (!res.ok) { + $status.innerText = "Not found"; + inject($container); + return; + } + + const data = await res.json(); + $status.remove(); + + console.dir(data.status); + + switch (data.status) { + case "source_not_registered": { + console.log("Source not registered"); + } break; + case "otomad_not_registered": { + console.log("Source registed, but otomad not registered"); + } break; + case "ok": { + console.log("Otomad registed") + const { otomad, originalSource } = data.data; + + const $title = document.createElement('p'); + $title.setAttribute("class", "otomadb-otomad-title"); + const $titleLink = document.createElement('a'); + $titleLink.innerText = otomad.title; + $titleLink.setAttribute("href", new URL("/otomad/" + otomad.serial, "http://localhost:5173").toString()); + // $titleLink.setAttribute("target", "_blank"); + // $titleLink.setAttribute("rel", "noopener noreferrer"); + $titleLink.setAttribute("lang", otomad.titleLang); + $title.appendChild($titleLink); + $container.appendChild($title); + + + const $taggings = document.createElement('div'); + $taggings.setAttribute("class", "otomadb-otomad-taggings"); + for (const { tag } of otomad.taggings) { + const $tagging = document.createElement("a"); + $tagging.innerText = tag.name + $tagging.setAttribute("class", "otomadb-otomad-tagging"); + $tagging.setAttribute("href", new URL("/tags/" + tag.serial, "http://localhost:5173").toString()); + // $tagging.setAttribute("target", "_blank"); + // $tagging.setAttribute("rel", "noopener noreferrer"); + $tagging.setAttribute("lang", tag.nameLang); + $taggings.appendChild($tagging); + } + $container.appendChild($taggings); + + const $sources = document.createElement('div'); + $sources.setAttribute("class", "otomadb-otomad-sources"); + for (const source of otomad.sources) { + const $source = document.createElement('a'); + $source.innerText = `${source.platform}`; + $source.setAttribute("class", "otomadb-otomad-source"); + $source.setAttribute("href", new URL(source.url)); + // $source.setAttribute("target", "_blank"); + // $source.setAttribute("rel", "noopener noreferrer"); + $sources.appendChild($source); + } + $container.appendChild($sources); + } break; + } + +} + +function waitForTarget(get_target, mutation_props, mutation_host = document) { + return new Promise(resolve => { + let t = get_target([]); + if (t) return resolve(t); + + const observer = new MutationObserver((records, observer) => { + let target = get_target(records); + if (target) { + resolve(target); + observer.disconnect(); + } + }); + observer.observe(mutation_host, mutation_props); + }); +} + +async function init() { + console.log("Init"); + + switch (window.location.hostname) { + case "www.nicovideo.jp": { + const $target = await waitForTarget(records => document.getElementsByClassName('grid-area_[meta]')[0]?.firstElementChild, { subtree: true, childList: true }); + await injectContainer( + $container => $target.insertAdjacentElement('afterend', $container), + ); + } + break; + case "www.bilibili.com": { + await injectContainer( + $container => document.querySelector('.video-desc-container').insertAdjacentElement('afterend', $container), + ); + } + break; + case "www.youtube.com": { + const $target = await waitForTarget(records => document.querySelector('#bottom-row'), { subtree: true, childList: true }); + await injectContainer( + $container => $target.insertAdjacentElement('afterend', $container), + ); + } + break; + } +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); +} else { + init() +} diff --git a/browser-extension/manifest.json b/browser-extension/manifest.json new file mode 100644 index 0000000..5ffe0bc --- /dev/null +++ b/browser-extension/manifest.json @@ -0,0 +1,27 @@ +{ + "manifest_version": 3, + "name": "OTOMADB Browser Extension", + "version": "1.0", + "description": "-", + "icons": { + "512": "icons/512.png" + }, + "content_scripts": [ + { + "matches": [ + "*://*.bilibili.com/video*", + "*://*.nicovideo.jp/watch*", + "*://*.youtube.com/watch*" + ], + "js": [ + "main.js" + ], + "css": [ + "style.css" + ] + } + ], + "host_permissions": [ + "*://localhost/*" + ] +} \ No newline at end of file diff --git a/browser-extension/style.css b/browser-extension/style.css new file mode 100644 index 0000000..a56fb0d --- /dev/null +++ b/browser-extension/style.css @@ -0,0 +1,68 @@ +#otomadb-container { + padding: 12px 16px; + margin: 8px 0; + background: #252525; + border-radius: 8px; +} + +#otomadb-container .otomadb-title { + font-family: sans-serif; + font-size: 12px; + color: white; + margin-bottom: 8px; +} + +#otomadb-container .otomadb-otomad-title { + font-family: sans-serif; + color: white; + margin-bottom: 8px; +} + +#otomadb-container .otomadb-otomad-title>a { + color: white; + font-size: 24px; + font-weight: bold; + text-decoration: none; +} + +#otomadb-container .otomadb-otomad-taggings { + display: flex; + flex-wrap: wrap; + column-gap: 4px; +} + +#otomadb-container .otomadb-otomad-tagging { + display: block; + font-family: sans-serif; + font-size: 14px; + padding: 2px 8px; + color: #2f2f2f; + border: 1px solid #2f2f2f; + border-radius: 4px; + background-color: #f0f0f0; + text-decoration: none; +} + +#otomadb-container .otomadb-otomad-tagging:hover { + background: #c2c2c2; +} + + +#otomadb-container .otomadb-otomad-sources { + display: flex; + flex-wrap: wrap; + column-gap: 8px; + margin-top: 16px; +} + +#otomadb-container .otomadb-otomad-source { + display: block; + font-family: sans-serif; + color: white; + font-size: 12px; + text-decoration: none; +} + +#otomadb-container .otomadb-otomad-source:hover { + text-decoration: underline; +} \ No newline at end of file