mirror of
https://github.com/sussy-code/smov.git
synced 2026-04-24 09:53:21 +00:00
136 lines
3.6 KiB
TypeScript
136 lines
3.6 KiB
TypeScript
import { MWEmbed, MWEmbedScraper, MWEmbedType } from "@/backend/helpers/embed";
|
|
import { getEmbeds } from "@/backend/helpers/register";
|
|
import { runEmbedScraper } from "@/backend/helpers/run";
|
|
import { MWStream } from "@/backend/helpers/streams";
|
|
import { Button } from "@/components/Button";
|
|
import { Navigation } from "@/components/layout/Navigation";
|
|
import { ArrowLink } from "@/components/text/ArrowLink";
|
|
import { Title } from "@/components/text/Title";
|
|
import { useLoading } from "@/hooks/useLoading";
|
|
import { ReactNode, useCallback, useEffect, useMemo, useState } from "react";
|
|
|
|
interface MediaSelectorProps {
|
|
embedType: MWEmbedType;
|
|
onSelect: (meta: MWEmbed) => void;
|
|
}
|
|
|
|
interface EmbedScraperSelectorProps {
|
|
onSelect: (embedScraperId: string) => void;
|
|
}
|
|
|
|
interface MediaScraperProps {
|
|
embed: MWEmbed;
|
|
scraper: MWEmbedScraper;
|
|
}
|
|
|
|
function MediaSelector(props: MediaSelectorProps) {
|
|
const [url, setUrl] = useState("");
|
|
|
|
const select = useCallback(
|
|
(urlSt: string) => {
|
|
props.onSelect({
|
|
type: props.embedType,
|
|
url: urlSt,
|
|
});
|
|
},
|
|
[props]
|
|
);
|
|
|
|
return (
|
|
<div className="flex flex-col space-y-4">
|
|
<Title className="mb-8">Input embed url</Title>
|
|
<div className="mb-4 flex gap-4">
|
|
<input
|
|
type="text"
|
|
placeholder="embed url here..."
|
|
value={url}
|
|
onChange={(e) => setUrl(e.target.value)}
|
|
/>
|
|
<Button onClick={() => select(url)}>Run scraper</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function MediaScraper(props: MediaScraperProps) {
|
|
const [results, setResults] = useState<MWStream | null>(null);
|
|
const [percentage, setPercentage] = useState(0);
|
|
|
|
const [scrape, loading, error] = useLoading(async (url: string) => {
|
|
const data = await runEmbedScraper(props.scraper, {
|
|
url,
|
|
progress(num) {
|
|
console.log(`SCRAPING AT ${num}%`);
|
|
setPercentage(num);
|
|
},
|
|
});
|
|
console.log("got data", data);
|
|
setResults(data);
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (props.embed) {
|
|
scrape(props.embed.url);
|
|
}
|
|
}, [props.embed, scrape]);
|
|
|
|
if (loading) return <p>Scraping... ({percentage}%)</p>;
|
|
if (error) return <p>Errored, check console</p>;
|
|
|
|
return (
|
|
<div>
|
|
<Title className="mb-8">Output data</Title>
|
|
<code>
|
|
<pre>{JSON.stringify(results, null, 2)}</pre>
|
|
</code>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function EmbedScraperSelector(props: EmbedScraperSelectorProps) {
|
|
const embedScrapers = getEmbeds();
|
|
|
|
return (
|
|
<div className="flex flex-col space-y-4">
|
|
<Title className="mb-8">Choose embed scraper</Title>
|
|
{embedScrapers.map((v) => (
|
|
<ArrowLink
|
|
key={v.id}
|
|
onClick={() => props.onSelect(v.id)}
|
|
direction="right"
|
|
linkText={v.displayName}
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function EmbedTesterView() {
|
|
const [embed, setEmbed] = useState<MWEmbed | null>(null);
|
|
const [embedScraperId, setEmbedScraperId] = useState<string | null>(null);
|
|
const embedScraper = useMemo(
|
|
() => getEmbeds().find((v) => v.id === embedScraperId),
|
|
[embedScraperId]
|
|
);
|
|
|
|
let content: ReactNode = null;
|
|
if (!embedScraperId || !embedScraper) {
|
|
content = <EmbedScraperSelector onSelect={(id) => setEmbedScraperId(id)} />;
|
|
} else if (!embed) {
|
|
content = (
|
|
<MediaSelector
|
|
embedType={embedScraper.for}
|
|
onSelect={(v) => setEmbed(v)}
|
|
/>
|
|
);
|
|
} else {
|
|
content = <MediaScraper scraper={embedScraper} embed={embed} />;
|
|
}
|
|
|
|
return (
|
|
<div className="py-48">
|
|
<Navigation />
|
|
<div className="mx-8 overflow-x-auto">{content}</div>
|
|
</div>
|
|
);
|
|
}
|