Implemented Invidious import
This commit is contained in:
@@ -274,8 +274,11 @@ export async function notificationsMarkAsRead(fetchOptions: RequestInit = {}) {
|
||||
await fetchErrorHandle(await fetch(path, { ...buildAuthHeaders(), ...fetchOptions }));
|
||||
}
|
||||
|
||||
export async function getSubscriptions(fetchOptions: RequestInit = {}): Promise<Subscription[]> {
|
||||
if (isYTBackend()) {
|
||||
export async function getSubscriptions(
|
||||
fetchOptions: RequestInit = {},
|
||||
bypassYTBackend: boolean = false
|
||||
): Promise<Subscription[]> {
|
||||
if (isYTBackend() && !bypassYTBackend) {
|
||||
return getSubscriptionsYTjs();
|
||||
}
|
||||
const resp = await fetchErrorHandle(
|
||||
@@ -304,8 +307,12 @@ export async function amSubscribed(
|
||||
}
|
||||
}
|
||||
|
||||
export async function postSubscribe(authorId: string, fetchOptions: RequestInit = {}) {
|
||||
if (isYTBackend()) {
|
||||
export async function postSubscribe(
|
||||
authorId: string,
|
||||
fetchOptions: RequestInit = {},
|
||||
bypassYTBackend: boolean = false
|
||||
) {
|
||||
if (isYTBackend() && !bypassYTBackend) {
|
||||
return postSubscribeYTjs(authorId);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,13 +24,19 @@ export async function amSubscribedYTjs(authorId: string): Promise<boolean> {
|
||||
return (await localDb.channelSubscriptions.where('channelId').equals(authorId).count()) > 0;
|
||||
}
|
||||
|
||||
export async function postSubscribeYTjs(authorId: string) {
|
||||
const channel = await getChannelYTjs(authorId);
|
||||
export async function postSubscribeYTjs(
|
||||
authorId: string,
|
||||
authorName: string | undefined = undefined
|
||||
) {
|
||||
if (!authorName) {
|
||||
const channel = await getChannelYTjs(authorId);
|
||||
authorName = channel.author;
|
||||
}
|
||||
|
||||
try {
|
||||
await localDb.channelSubscriptions.add({
|
||||
channelId: authorId,
|
||||
channelName: channel.author,
|
||||
channelName: authorName,
|
||||
lastRSSFetch: new Date(0)
|
||||
});
|
||||
} catch {
|
||||
@@ -147,16 +153,17 @@ export async function getFeedYTjs(): Promise<Feed> {
|
||||
await Promise.all(toUpdatePromises);
|
||||
}
|
||||
|
||||
const videos = await localDb.subscriptionFeed.toArray();
|
||||
let videos = await localDb.subscriptionFeed.toArray();
|
||||
videos.sort((a, b) => b.published - a.published);
|
||||
|
||||
const cullAfter = get(engineCullYTStore);
|
||||
|
||||
if (videos.length > cullAfter) {
|
||||
const videosToDelete = videos.slice(cullAfter);
|
||||
const videoIdsToDelete = videosToDelete.map((video) => video.videoId);
|
||||
await localDb.subscriptionFeed.where('videoId').anyOf(videoIdsToDelete).delete();
|
||||
|
||||
await localDb.subscriptionFeed.where('id').anyOf(videoIdsToDelete).delete();
|
||||
// Don't display culled videos.
|
||||
videos = videos.slice(0, cullAfter);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { isYTBackend } from '$lib/misc';
|
||||
import { _ } from '$lib/i18n';
|
||||
import { engineCooldownYTStore, engineCullYTStore, engineFallbacksStore } from '$lib/store';
|
||||
import {
|
||||
authStore,
|
||||
engineCooldownYTStore,
|
||||
engineCullYTStore,
|
||||
engineFallbacksStore,
|
||||
instanceStore
|
||||
} from '$lib/store';
|
||||
import { useEngineFallback, type EngineFallback } from '$lib/api/misc';
|
||||
import { get } from 'svelte/store';
|
||||
import { getSubscriptions } from '$lib/api';
|
||||
import { postSubscribeYTjs } from '$lib/api/youtubejs/subscriptions';
|
||||
import { addToast } from '../Toast.svelte';
|
||||
|
||||
const engineFallbacks: EngineFallback[] = [
|
||||
'Channel',
|
||||
@@ -33,6 +42,29 @@
|
||||
|
||||
engineFallbacksStore.set(enabledFallbacks);
|
||||
}
|
||||
|
||||
async function importInvidiousSubs() {
|
||||
const importedSubs = await getSubscriptions({}, true);
|
||||
|
||||
addToast({
|
||||
data: {
|
||||
text: $_('layout.backendEngine.importingToMaterialious')
|
||||
}
|
||||
});
|
||||
|
||||
const subPromises: Promise<void>[] = [];
|
||||
importedSubs.forEach((sub) => {
|
||||
subPromises.push(postSubscribeYTjs(sub.authorId, sub.author));
|
||||
});
|
||||
|
||||
await Promise.all(subPromises);
|
||||
|
||||
addToast({
|
||||
data: {
|
||||
text: $_('layout.backendEngine.importingToMaterialiousFinished')
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<article class="error-container">
|
||||
@@ -40,7 +72,7 @@
|
||||
</article>
|
||||
|
||||
{#if isYTBackend()}
|
||||
<h4>Feed</h4>
|
||||
<h6>Feed</h6>
|
||||
<div class="field label prefix border">
|
||||
<i>view_stream</i>
|
||||
<input
|
||||
@@ -65,8 +97,25 @@
|
||||
/>
|
||||
<label for="cull">{$_('layout.backendEngine.cooldown')}</label>
|
||||
</div>
|
||||
|
||||
{#if $authStore && $instanceStore}
|
||||
<h6>{$_('layout.backendEngine.importExport')}</h6>
|
||||
<div class="space"></div>
|
||||
|
||||
<button class="surface-container-highest">
|
||||
<i>upload</i>
|
||||
<div>{$_('layout.backendEngine.exportToInvidious')}</div>
|
||||
</button>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
<button onclick={importInvidiousSubs} class="surface-container-highest">
|
||||
<i>download</i>
|
||||
<div>{$_('layout.backendEngine.importToMaterialious')}</div>
|
||||
</button>
|
||||
{/if}
|
||||
{:else}
|
||||
<h4>{$_('layout.backendEngine.fallbacks')}</h4>
|
||||
<h6>{$_('layout.backendEngine.fallbacks')}</h6>
|
||||
{#each engineFallbacks as fallback (fallback)}
|
||||
<nav class="no-padding">
|
||||
<div class="max">
|
||||
|
||||
@@ -179,7 +179,12 @@
|
||||
"warning": "Advanced settings! For experienced users only. Do not change unless you know what you’re doing.",
|
||||
"cull": "Max feed items",
|
||||
"cooldown": "Re-fetch channel hour cooldown",
|
||||
"fallbacks": "Fallbacks"
|
||||
"fallbacks": "Fallbacks",
|
||||
"importExport": "Import/Export subscriptions",
|
||||
"exportToInvidious": "Export to Invidious from Materialious",
|
||||
"importToMaterialious": "Import from Invidious to Materialious",
|
||||
"importingToMaterialious": "Importing to Materialious began",
|
||||
"importingToMaterialiousFinished": "Importing to Materialious finished"
|
||||
},
|
||||
"player": {
|
||||
"title": "Player",
|
||||
|
||||
@@ -315,7 +315,7 @@ export const deArrowThumbnailInstanceStore = persist(
|
||||
);
|
||||
|
||||
export const engineCullYTStore: Writable<number> = persist(
|
||||
writable(1000),
|
||||
writable(500),
|
||||
createStorage(),
|
||||
'engineCullYT'
|
||||
);
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
setTheme();
|
||||
setAmoledTheme();
|
||||
|
||||
if (isLoggedIn) {
|
||||
if (isLoggedIn && !isYTBackend()) {
|
||||
loadNotifications().catch(() => authStore.set(null));
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@
|
||||
<i class:primary-text={$syncPartyPeerStore}>group</i>
|
||||
<div class="tooltip bottom">{$_('layout.syncParty')}</div>
|
||||
</button>
|
||||
{#if isLoggedIn}
|
||||
{#if isLoggedIn && !isYTBackend()}
|
||||
<button
|
||||
class="circle large transparent"
|
||||
onclick={() => {
|
||||
|
||||
Reference in New Issue
Block a user