Compare commits

...

9 Commits

Author SHA1 Message Date
Simon 1d27545409
bump version 2024-05-15 20:47:38 +02:00
Simon 7b40dc44c2
fix checkVideoExists, check siblings in getNearestLink 2024-05-13 21:53:45 +02:00
Simon 9ba90e4e45
bump version 2024-05-11 17:05:25 +02:00
Simon 0d58ddaaa2
limit cookie domains, #22 (#38) 2024-05-11 22:02:46 +07:00
Vladimir Pouzanov c82e493628
Relocate the injected button to the h3 element (#37) 2024-05-11 22:00:29 +07:00
Simon ca15cc9c0b
fix channel page selector 2024-05-01 22:23:41 +02:00
Simon 190f545ef2
fix format linter 2024-05-01 22:23:26 +02:00
Ritiek Malhotra 761030ca55
Show checkmark for already downloaded currently playing videos (#35)
Looks like this was regressed from v0.2.1 to v0.2.2 in this commit sha:
f8d69f5883

Already downloaded video currently playing in YouTube were still
showing the download icon instead of checkmark icon in TA.

This commit should fix this.
2024-05-02 02:20:34 +07:00
Simon 82a64ff4ba
update roadmap, add shorts pages button 2023-11-10 11:41:30 +07:00
7 changed files with 57 additions and 17 deletions

View File

@ -77,6 +77,7 @@ Symlink/copy the correct manifest file for your browser to the expected location
## Roadmap
Join us on [Discord](https://www.tubearchivist.com/discord) and help us improve and extend this project. This is a list of planned features, in no particular order:
- [ ] Implement download/subscribe button for playlists
- [ ] Add download buttons to the `/shorts/` pages
- [X] Get download and subscribe status from TA to show on the injected buttons
- [X] Implement download button for videos on the YouTube homepage over inline preview
- [X] Implement download button for videos on playlist

View File

@ -208,6 +208,7 @@ function buildCookieLine(cookie) {
async function sendCookies() {
console.log('function sendCookies');
const acceptableDomains = ['.youtube.com', 'youtube.com', 'www.youtube.com'];
let cookieStores = await browserType.cookies.getAllCookieStores();
let cookieLines = [
@ -223,7 +224,9 @@ async function sendCookies() {
});
for (let j = 0; j < allCookiesStore.length; j++) {
const cookie = allCookiesStore[j];
cookieLines.push(buildCookieLine(cookie));
if (acceptableDomains.includes(cookie.domain)) {
cookieLines.push(buildCookieLine(cookie));
}
}
}

View File

@ -14,7 +14,7 @@
<a href="#" id="ta-url" target="_blank">
<img src="/images/logo.png" alt="ta-logo">
</a>
<span>v0.2.2</span>
<span>v0.3.1</span>
</div>
<hr>
<form class="login-form">

View File

@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "TubeArchivist Companion",
"description": "Interact with your selfhosted TA server.",
"version": "0.2.2",
"version": "0.3.1",
"icons": {
"48": "/images/icon.png",
"128": "/images/icon128.png"

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "TubeArchivist Companion",
"description": "Interact with your selfhosted TA server.",
"version": "0.2.2",
"version": "0.3.1",
"icons": {
"128": "/images/icon128.png"
},

View File

@ -83,7 +83,6 @@ document.getElementById('autostart').addEventListener('click', function () {
toggleAutostart();
});
let fullUrlInput = document.getElementById('full-url');
fullUrlInput.addEventListener('change', () => {
browserType.storage.local.set({
@ -200,7 +199,6 @@ function setStatusIcon(connected) {
}
}
// fill in form
document.addEventListener('DOMContentLoaded', async () => {
function onGot(item) {

View File

@ -106,7 +106,7 @@ function getBrowser() {
}
function getChannelContainers() {
const elements = document.querySelectorAll('#inner-header-container, #owner');
const elements = document.querySelectorAll('.yt-flexible-actions-view-model-wiz, #owner');
const channelContainerNodes = [];
elements.forEach(element => {
@ -135,12 +135,14 @@ function ensureTALinks() {
let titleContainerNodes = getTitleContainers();
for (let titleContainer of titleContainerNodes) {
if (titleContainer.hasTA) continue;
let parent = getNearestH3(titleContainer);
if (!parent) continue;
if (parent.hasTA) continue;
let videoButton = buildVideoButton(titleContainer);
if (videoButton == null) continue;
processTitle(titleContainer);
titleContainer.appendChild(videoButton);
titleContainer.hasTA = true;
processTitle(parent);
parent.appendChild(videoButton);
parent.hasTA = true;
}
}
ensureTALinks = throttled(ensureTALinks, 700);
@ -196,7 +198,9 @@ function getChannelHandle(channelContainer) {
const videoOwnerRenderer = channelContainer.querySelector('.ytd-video-owner-renderer');
if (!videoOwnerRenderer) {
const channelHandleContainer = document.querySelector('#channel-handle');
const channelHandleContainer = document.querySelector(
'.yt-content-metadata-view-model-wiz__metadata-text'
);
channelHandle = channelHandleContainer ? channelHandleContainer.innerText : null;
} else {
const href = videoOwnerRenderer.href;
@ -327,6 +331,8 @@ function getTitleContainers() {
}
function getVideoId(titleContainer) {
if (!titleContainer) return undefined;
let href = getNearestLink(titleContainer);
if (!href) return;
@ -383,6 +389,24 @@ function buildVideoButton(titleContainer) {
}
function getNearestLink(element) {
// Check siblings
let sibling = element;
while (sibling) {
sibling = sibling.previousElementSibling;
if (sibling && sibling.tagName === 'A' && sibling.getAttribute('href') !== '#') {
return sibling.getAttribute('href');
}
}
sibling = element;
while (sibling) {
sibling = sibling.nextElementSibling;
if (sibling && sibling.tagName === 'A' && sibling.getAttribute('href') !== '#') {
return sibling.getAttribute('href');
}
}
// Check parent elements
for (let i = 0; i < 5 && element && element !== document; i++) {
if (element.tagName === 'A' && element.getAttribute('href') !== '#') {
return element.getAttribute('href');
@ -392,6 +416,16 @@ function getNearestLink(element) {
return null;
}
function getNearestH3(element) {
for (let i = 0; i < 5 && element && element !== document; i++) {
if (element.tagName === 'H3') {
return element;
}
element = element.parentNode;
}
return null;
}
function processTitle(titleContainer) {
if (titleContainer.hasListener) return;
Object.assign(titleContainer.style, {
@ -437,11 +471,15 @@ function checkVideoExists(taButton) {
console.error(e);
}
if (!taButton.parentElement) return;
let videoId = getVideoId(taButton.parentElement);
taButton.setAttribute('data-id', videoId);
taButton.setAttribute('data-type', 'video');
taButton.title = `TA download video: ${taButton.parentElement.innerText} [${videoId}]`;
let videoId = taButton.dataset.id;
if (!videoId) {
videoId = getVideoId(taButton);
if (videoId) {
taButton.setAttribute('data-id', videoId);
taButton.setAttribute('data-type', 'video');
taButton.title = `TA download video: ${taButton.parentElement.innerText} [${videoId}]`;
}
}
let message = { type: 'videoExists', videoId };
let sending = sendMessage(message);