120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
import { request } from "$lib/api/client";
|
|
import type { FileShare, FileShareHit, ShareSubject } from "$lib/api/types";
|
|
import { accounts } from "$lib/stores/accounts.svelte";
|
|
|
|
export interface ShareSettings {
|
|
expiresInSeconds: number | null;
|
|
keepExpiry?: boolean;
|
|
maxDownloads: number | null;
|
|
}
|
|
|
|
function subjectQuery(subject: ShareSubject): Record<string, number | string> {
|
|
const query: Record<string, number | string> = { kind: subject.kind };
|
|
if (subject.mediaId !== undefined) {
|
|
query.media_id = subject.mediaId;
|
|
}
|
|
if (subject.versionId !== undefined) {
|
|
query.version_id = subject.versionId;
|
|
}
|
|
if (subject.peerId !== undefined) {
|
|
query.peer_id = subject.peerId;
|
|
}
|
|
if (subject.storyId !== undefined) {
|
|
query.story_id = subject.storyId;
|
|
}
|
|
return query;
|
|
}
|
|
|
|
export function listShares(activeOnly = false): Promise<FileShare[]> {
|
|
return request<FileShare[]>("/shares", {
|
|
account: true,
|
|
query: { active_only: activeOnly, limit: 200 },
|
|
});
|
|
}
|
|
|
|
export function lookupShare(subject: ShareSubject): Promise<FileShare | null> {
|
|
return request<FileShare | null>("/shares/lookup", {
|
|
account: true,
|
|
query: subjectQuery(subject),
|
|
});
|
|
}
|
|
|
|
export function createShare(
|
|
subject: ShareSubject,
|
|
settings: ShareSettings
|
|
): Promise<FileShare> {
|
|
return request<FileShare>("/shares", {
|
|
method: "POST",
|
|
body: {
|
|
account_id: accounts.selectedId,
|
|
kind: subject.kind,
|
|
media_id: subject.mediaId ?? null,
|
|
version_id: subject.versionId ?? null,
|
|
peer_id: subject.peerId ?? null,
|
|
story_id: subject.storyId ?? null,
|
|
expires_in_seconds: settings.expiresInSeconds,
|
|
max_downloads: settings.maxDownloads,
|
|
},
|
|
});
|
|
}
|
|
|
|
export function updateShare(
|
|
id: number,
|
|
settings: ShareSettings
|
|
): Promise<FileShare> {
|
|
return request<FileShare>(`/shares/${id}`, {
|
|
method: "PATCH",
|
|
body: {
|
|
expires_in_seconds: settings.expiresInSeconds,
|
|
keep_expiry: settings.keepExpiry ?? false,
|
|
max_downloads: settings.maxDownloads,
|
|
},
|
|
});
|
|
}
|
|
|
|
export function revokeShare(id: number): Promise<FileShare> {
|
|
return request<FileShare>(`/shares/${id}/revoke`, { method: "POST" });
|
|
}
|
|
|
|
export function reissueShare(id: number): Promise<FileShare> {
|
|
return request<FileShare>(`/shares/${id}/reissue`, { method: "POST" });
|
|
}
|
|
|
|
export function deleteShare(id: number): Promise<void> {
|
|
return request<void>(`/shares/${id}`, { method: "DELETE" });
|
|
}
|
|
|
|
export function listShareHits(id: number): Promise<FileShareHit[]> {
|
|
return request<FileShareHit[]>(`/shares/${id}/hits`, {
|
|
query: { limit: 50 },
|
|
});
|
|
}
|
|
|
|
const TRAILING_SLASH = /\/$/;
|
|
|
|
export function shareUrl(share: FileShare): string {
|
|
const origin =
|
|
typeof window === "undefined"
|
|
? ""
|
|
: window.location.origin.replace(TRAILING_SLASH, "");
|
|
return `${origin}/f/${share.token}`;
|
|
}
|
|
|
|
export function shareState(
|
|
share: FileShare
|
|
): "active" | "revoked" | "expired" | "exhausted" {
|
|
if (share.revoked_at) {
|
|
return "revoked";
|
|
}
|
|
if (share.expires_at && Date.parse(share.expires_at) <= Date.now()) {
|
|
return "expired";
|
|
}
|
|
if (
|
|
share.max_downloads !== null &&
|
|
share.download_count >= share.max_downloads
|
|
) {
|
|
return "exhausted";
|
|
}
|
|
return "active";
|
|
}
|