Skip to content

Commit

Permalink
feat: Replace torrents with magnet links (#108)
Browse files Browse the repository at this point in the history
* feat: add discord release yml

* chore(main): release 0.13.0 (#101)

* chore: removed a sponsor

* fix: update discord notification

* chore: fix notification breaking syntax

* fix: add new states to the frontend (#106)

* add new states to frontend

* lint the previous commit

* add new states to summary view

* lint the workflow at request of @AyushSehrawat

* fix: minor statistics page improvement

* chore(main): release 0.13.1 (#102)

* feat: enable adding torrent with magnet links

* feat: add folder information to manage sheet

* style: make the button text clearer

* refactor: cleanup debug code

* feat: magnet link add for shows

* feat: improve error messages

* feat: information about the selected episode/season

* refactor: remove debug property

* style: formatting

---------

Co-authored-by: Ayush Sehrawat <[email protected]>
Co-authored-by: Spoked <[email protected]>
  • Loading branch information
3 people authored Sep 26, 2024
1 parent 22ddbb3 commit a6bf0e1
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# These are supported funding model platforms

github: [AyushSehrawat, dreulavelle]
github: [AyushSehrawat]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/discord-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
on:
release:
types: [published]

jobs:
github-releases-to-discord:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Github Releases To Discord
uses: SethCohen/[email protected] # latest version breaks syntax in discord. stick to 1.13.1
with:
webhook_url: ${{ secrets.WEBHOOK_URL }}
color: '2105893'
username: 'Release Changelog'
avatar_url: 'https://raw.githubusercontent.com/rivenmedia/riven/main/assets/riven-light.png'
# content: "||@everyone||"
footer_title: 'Riven (Frontend) Changelog'
footer_icon_url: 'https://raw.githubusercontent.com/rivenmedia/riven/main/assets/riven-light.png'
footer_timestamp: true
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## [0.13.1](https://github.com/rivenmedia/riven-frontend/compare/v0.13.0...v0.13.1) (2024-09-25)


### Bug Fixes

* add new states to the frontend ([#106](https://github.com/rivenmedia/riven-frontend/issues/106)) ([6d3911b](https://github.com/rivenmedia/riven-frontend/commit/6d3911b0d40f663e26aa966d58e961d8e1de914e))
* minor statistics page improvement ([b6d8a2a](https://github.com/rivenmedia/riven-frontend/commit/b6d8a2a29daa94483a6c73933c46482c23b2dde6))
* update discord notification ([25f1348](https://github.com/rivenmedia/riven-frontend/commit/25f13485e3ffda595d1e667b2eeb6abfdb5e9dfb))

## [0.13.0](https://github.com/rivenmedia/riven-frontend/compare/v0.12.1...v0.13.0) (2024-09-22)


### Features

* add discord release yml ([2801328](https://github.com/rivenmedia/riven-frontend/commit/28013285eb57d00b5da824b349d0b27c798796a9))

## [0.12.1](https://github.com/rivenmedia/riven-frontend/compare/v0.12.0...v0.12.1) (2024-09-16)


Expand Down
4 changes: 3 additions & 1 deletion src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export const statesName: Record<string, string> = {
Symlinked: 'Symlinked',
Completed: 'Completed',
PartiallyCompleted: 'Partially Completed',
Failed: 'Failed'
Failed: 'Failed',
Ongoing: 'Ongoing',
Unreleased: 'Unreleased'
};

export const servicesObject: Record<string, string> = {
Expand Down
23 changes: 23 additions & 0 deletions src/routes/[type]/[id]/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@ export const load = (async ({ params, locals }) => {
.where('tmdb_id', '=', String(id))
.executeTakeFirst();

if (dbData && dbData.type === 'show') {
const seasons = await locals.db
.selectFrom('MediaItem as seasonItem')
.selectAll()
.innerJoin('Season as season', 'seasonItem._id', 'season._id')
.where('type', '=', 'season')
.where('season.parent_id', '=', dbData._id)
.orderBy('seasonItem.number', 'asc')
.execute();
dbData.seasons = seasons;
for (const season of seasons) {
const episodes = await locals.db
.selectFrom('MediaItem as episodeItem')
.selectAll()
.innerJoin('Episode as episode', 'episodeItem._id', 'episode._id')
.where('type', '=', 'episode')
.where('episode.parent_id', '=', season._id)
.orderBy('episodeItem.number', 'asc')
.execute();
season.episodes = episodes;
}
}

return {
db: dbData
};
Expand Down
102 changes: 101 additions & 1 deletion src/routes/[type]/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
Wrench,
RotateCcw,
CirclePower,
Clipboard
Clipboard,
Magnet,
LoaderCircle
} from 'lucide-svelte';
import * as Carousel from '$lib/components/ui/carousel/index.js';
import { Button } from '$lib/components/ui/button';
Expand All @@ -24,10 +26,18 @@
import { toast } from 'svelte-sonner';
import { goto, invalidateAll } from '$app/navigation';
import ItemRequest from '$lib/components/item-request.svelte';
import { Input } from '$lib/components/ui/input';
import * as Select from '$lib/components/ui/select';
import type { Selected } from 'bits-ui';
export let data: PageData;
let productionCompanies = 4;
let magnetLink = '';
let magnetLoading = false;
let isShow = data.db ? data.db.type === 'show' : false;
let selectedMagnetItem: Selected<{ _id: number; file?: string; folder?: string }>;
$: buttonEnabled = magnetLink && !magnetLoading && (isShow ? selectedMagnetItem : true);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function filterSpecial(seasons: any) {
Expand Down Expand Up @@ -82,6 +92,33 @@
day: 'numeric'
});
}
async function addMagnetLink(_id: number, magnet: string) {
if (!magnet) {
toast.error('Magnet link cannot be empty');
return;
}
if (isShow && !selectedMagnetItem) {
toast.error('Select a season/episode');
return;
}
if (magnetLoading) return;
magnetLoading = true;
const id = isShow ? selectedMagnetItem.value._id : _id;
const response = await fetch(`/api/media/${id}/magnet`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ magnet })
});
magnetLoading = false;
if (!response.ok) {
toast.error((await response.json()).error ?? 'Unknown error');
return;
}
toast.success('Magnet link added successfully');
}
</script>

<svelte:head>
Expand Down Expand Up @@ -206,6 +243,69 @@
<p>Requested at: {getTime(data.db.requested_at.getTime())}</p>
{/if}
<p>Symlinked: {data.db.symlinked}</p>
{#if data.db.folder}
<p>Folder: {data.db.folder}</p>
{/if}
{#if isShow && selectedMagnetItem && selectedMagnetItem.value.file}
<p>Selected item file: {selectedMagnetItem.value.file}</p>
{:else if isShow && selectedMagnetItem && selectedMagnetItem.value.folder}
<p>Selected item folder: {selectedMagnetItem.value.folder}</p>
{/if}

<div class="mt-1"></div>

{#if isShow}
<Select.Root portal={null} bind:selected={selectedMagnetItem}>
<Select.Trigger>
<Select.Value placeholder="Select a season/episode" />
</Select.Trigger>
<Select.Content class="max-h-[600px] overflow-y-scroll sm:max-h-[300px]">
<Select.Group>
{#each data.db.seasons as season}
<Select.Label>Season {season.number}</Select.Label>
<Select.Item value={season}>
All episodes in season {season.number}
</Select.Item>
{#each season.episodes as episode}
<Select.Item value={episode}>
S{season.number.toString().padStart(2, '0')}E{episode.number
.toString()
.padStart(2, '0')}
{episode.title}
</Select.Item>
{/each}
{/each}
</Select.Group>
</Select.Content>
<Select.Input name="favoriteFruit" />
</Select.Root>
{/if}

<Input bind:value={magnetLink} placeholder="Paste in the magnet link" />

<Tooltip.Root>
<Tooltip.Trigger class="mb-2">
<Button
class="flex w-full items-center gap-1"
disabled={!buttonEnabled}
on:click={async () => {
if (data.db && magnetLink) {
await addMagnetLink(data.db._id, magnetLink);
}
}}
>
{#if magnetLoading}
<LoaderCircle class="size-4 animate-spin" />
{:else}
<Magnet class="size-4" />
{/if}
<span>Replace torrent</span>
</Button>
</Tooltip.Trigger>
<Tooltip.Content>
<p>Replaces the current torrent with the magnet link</p>
</Tooltip.Content>
</Tooltip.Root>

<Tooltip.Root>
<Tooltip.Trigger>
Expand Down
69 changes: 69 additions & 0 deletions src/routes/api/media/[id]/magnet/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import type { RequestHandler } from './$types';

export const POST: RequestHandler = async ({ params, locals, request }) => {
const id = params.id;
const magnet = (await request.json())['magnet'];

if (!magnet) {
return new Response(
JSON.stringify({
error: 'No magnet provided'
}),
{
status: 400,
headers: {
'Content-Type': 'application/json'
}
}
);
}

const url = new URL(`${locals.BACKEND_URL}/items/${id}/set_torrent_rd_magnet`);
url.searchParams.set('magnet', magnet);

try {
const response = await fetch(url, {
method: 'POST'
});

const data = await response.json();
if (response.ok) {
return new Response(
JSON.stringify({
success: 'Magnet link added',
data
}),
{
status: 200,
headers: {
'Content-Type': 'application/json'
}
}
);
} else {
return new Response(
JSON.stringify({
error: data.detail
}),
{
status: 500,
headers: {
'Content-Type': 'application/json'
}
}
);
}
} catch {
return new Response(
JSON.stringify({
error: 'Failed to reach backend'
}),
{
status: 500,
headers: {
'Content-Type': 'application/json'
}
}
);
}
};
22 changes: 8 additions & 14 deletions src/routes/summary/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { PageServerLoad } from './$types';
import { error } from '@sveltejs/kit';
import { statesName } from '$lib/constants';

export const load = (async ({ locals }) => {
const statistics = await locals.db
Expand All @@ -24,25 +25,18 @@ export const load = (async ({ locals }) => {
Symlinked: number;
PartiallyCompleted: number;
Unknown: number;
Unreleased: number;
Ongoing: number;
[key: string]: number; // Index signature
};

const states = (await locals.db
.selectFrom('MediaItem')
.select(({ fn }) => [
fn.count<number>('_id').filterWhere('last_state', '=', 'Completed').as('Completed'),
fn.count<number>('_id').filterWhere('last_state', '=', 'Failed').as('Failed'),
fn.count<number>('_id').filterWhere('last_state', '=', 'Requested').as('Requested'),
fn.count<number>('_id').filterWhere('last_state', '=', 'Indexed').as('Indexed'),
fn.count<number>('_id').filterWhere('last_state', '=', 'Scraped').as('Scraped'),
fn.count<number>('_id').filterWhere('last_state', '=', 'Downloaded').as('Downloaded'),
fn.count<number>('_id').filterWhere('last_state', '=', 'Symlinked').as('Symlinked'),
fn
.count<number>('_id')
.filterWhere('last_state', '=', 'PartiallyCompleted')
.as('PartiallyCompleted'),
fn.count<number>('_id').filterWhere('last_state', '=', 'Unknown').as('Unknown')
])
.select(({ fn }) =>
Object.keys(statesName).map((state) =>
fn.count<number>('_id').filterWhere('last_state', '=', state).as(state)
)
)
.executeTakeFirst()) as States;

async function getServices() {
Expand Down
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.12.1
0.13.1

0 comments on commit a6bf0e1

Please sign in to comment.