Added export support
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { _ } from '$lib/i18n';
|
||||
import { importSubscriptionsFromFile } from '$lib/importExport';
|
||||
import { exportSubscriptionsAsFile, importSubscriptionsFromFile } from '$lib/importExport';
|
||||
import { addToast, toaster } from '../Toast.svelte';
|
||||
</script>
|
||||
|
||||
@@ -36,3 +36,20 @@
|
||||
/>
|
||||
</div>
|
||||
<p><i>info</i> {$_('layout.export.importSubSupported')}</p>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
<div>
|
||||
<button>
|
||||
<i>file_export</i>
|
||||
<span>{$_('layout.export.exportSub')}</span>
|
||||
</button>
|
||||
<menu>
|
||||
<li role="presentation" onclick={() => exportSubscriptionsAsFile('InvidiousJSON')}>
|
||||
Invidious JSON
|
||||
</li>
|
||||
<li role="presentation" onclick={() => exportSubscriptionsAsFile('OPML')}>
|
||||
FreeTube/NewPipe/YouTube OPML
|
||||
</li>
|
||||
</menu>
|
||||
</div>
|
||||
|
||||
@@ -276,7 +276,8 @@
|
||||
"importSub": "Import subscriptions",
|
||||
"importSubSupported": "YouTube CSV/OPML, Invidious OPML/JSON, Freetube database & NewPipe JSON supported",
|
||||
"importing": "Importing subscriptions (this will take a moment)",
|
||||
"importingCompleted": "Subscriptions successfully imported"
|
||||
"importingCompleted": "Subscriptions successfully imported",
|
||||
"exportSub": "Export subscriptions"
|
||||
},
|
||||
"deArrow": {
|
||||
"title": "DeArrow",
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import z from 'zod';
|
||||
import type { Subscription } from './api/model';
|
||||
import { getChannel, postSubscribe } from './api';
|
||||
import { getChannel, getSubscriptions, postSubscribe } from './api';
|
||||
import Papa from 'papaparse';
|
||||
import { downloadStringAsFile } from './misc';
|
||||
|
||||
const zInvidiousSubs = z.object({
|
||||
subscriptions: z.array(z.string())
|
||||
@@ -166,3 +167,61 @@ export async function importSubscriptionsFromFile(file: File) {
|
||||
|
||||
throw new Error('Unable to determine imported file type');
|
||||
}
|
||||
|
||||
export async function exportSubscriptionsAsFile(exportType: 'InvidiousJSON' | 'OPML') {
|
||||
const subscriptions = await getSubscriptions();
|
||||
|
||||
let data: string | undefined;
|
||||
|
||||
if (exportType === 'InvidiousJSON') {
|
||||
const subIds = [];
|
||||
|
||||
for (const sub of subscriptions) {
|
||||
subIds.push(sub.authorId);
|
||||
}
|
||||
|
||||
data = JSON.stringify({
|
||||
subscriptions: subIds
|
||||
});
|
||||
} else {
|
||||
const xmlDoc = document.implementation.createDocument('', '', null);
|
||||
|
||||
const opml = xmlDoc.createElement('opml');
|
||||
opml.setAttribute('version', '1.1');
|
||||
|
||||
const body = xmlDoc.createElement('body');
|
||||
|
||||
const mainOutline = xmlDoc.createElement('outline');
|
||||
mainOutline.setAttribute('text', 'YouTube Subscriptions');
|
||||
mainOutline.setAttribute('title', 'YouTube Subscriptions');
|
||||
|
||||
body.appendChild(mainOutline);
|
||||
|
||||
for (const sub of subscriptions) {
|
||||
const outline = xmlDoc.createElement('outline');
|
||||
outline.setAttribute('text', sub.author);
|
||||
outline.setAttribute('title', sub.author);
|
||||
outline.setAttribute('type', 'rss');
|
||||
outline.setAttribute(
|
||||
'xmlUrl',
|
||||
`https://www.youtube.com/feeds/videos.xml?channel_id=${sub.authorId}`
|
||||
);
|
||||
|
||||
body.appendChild(outline);
|
||||
}
|
||||
|
||||
opml.appendChild(body);
|
||||
xmlDoc.appendChild(opml);
|
||||
|
||||
const serializer = new XMLSerializer();
|
||||
|
||||
data = serializer.serializeToString(xmlDoc);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
downloadStringAsFile(
|
||||
data,
|
||||
`materialious-export-${new Date().toDateString().replaceAll(' ', '')}.${exportType === 'InvidiousJSON' ? 'json' : 'opml'}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,3 +118,17 @@ export function isUnrestrictedPlatform(): boolean {
|
||||
export function isYTBackend(): boolean {
|
||||
return get(backendInUseStore) === 'yt' && isUnrestrictedPlatform();
|
||||
}
|
||||
|
||||
export function downloadStringAsFile(content: string, filename: string) {
|
||||
const blob = new Blob([content]);
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user