mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2025-12-24 10:49:30 -05:00
Compare commits
1 Commits
preview-fi
...
fix-librar
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac33fe75b6 |
@@ -7,10 +7,9 @@ type RateLimiteState<T extends (...args: Parameters<T>) => Promise<U>, U> = {
|
||||
queue: {
|
||||
args: Parameters<T>;
|
||||
resolve: (value: U) => void;
|
||||
reject: (reason?: unknown) => void;
|
||||
}[];
|
||||
lastTimestamps: number[];
|
||||
timeout: ReturnType<typeof setTimeout>;
|
||||
activeRequests: number;
|
||||
timer: NodeJS.Timeout | null;
|
||||
};
|
||||
|
||||
const rateLimitById: Record<string, unknown> = {};
|
||||
@@ -28,40 +27,46 @@ export default function rateLimit<
|
||||
>(fn: T, options: RateLimitOptions): (...args: Parameters<T>) => Promise<U> {
|
||||
const state: RateLimiteState<T, U> = (rateLimitById[
|
||||
options.id || ''
|
||||
] as RateLimiteState<T, U>) || { queue: [], lastTimestamps: [] };
|
||||
] as RateLimiteState<T, U>) || { queue: [], activeRequests: 0, timer: null };
|
||||
if (options.id) {
|
||||
rateLimitById[options.id] = state;
|
||||
}
|
||||
|
||||
const processQueue = () => {
|
||||
// remove old timestamps
|
||||
state.lastTimestamps = state.lastTimestamps.filter(
|
||||
(timestamp) => Date.now() - timestamp < 1000
|
||||
);
|
||||
if (state.queue.length === 0) {
|
||||
if (state.timer) {
|
||||
clearInterval(state.timer);
|
||||
state.timer = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.lastTimestamps.length < options.maxRPS) {
|
||||
// process requests if RPS not exceeded
|
||||
while (state.activeRequests < options.maxRPS) {
|
||||
state.activeRequests++;
|
||||
const item = state.queue.shift();
|
||||
if (!item) return;
|
||||
state.lastTimestamps.push(Date.now());
|
||||
const { args, resolve, reject } = item;
|
||||
if (!item) break;
|
||||
const { args, resolve } = item;
|
||||
fn(...args)
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
processQueue();
|
||||
} else {
|
||||
// rerun once the oldest item in queue is older than 1s
|
||||
if (state.timeout) clearTimeout(state.timeout);
|
||||
state.timeout = setTimeout(
|
||||
processQueue,
|
||||
1000 - (Date.now() - state.lastTimestamps[0])
|
||||
);
|
||||
.finally(() => {
|
||||
state.activeRequests--;
|
||||
if (state.queue.length > 0) {
|
||||
if (!state.timer) {
|
||||
state.timer = setInterval(processQueue, 1000);
|
||||
}
|
||||
} else {
|
||||
if (state.timer) {
|
||||
clearInterval(state.timer);
|
||||
state.timer = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (...args: Parameters<T>): Promise<U> => {
|
||||
return new Promise<U>((resolve, reject) => {
|
||||
state.queue.push({ args, resolve, reject });
|
||||
return new Promise<U>((resolve) => {
|
||||
state.queue.push({ args, resolve });
|
||||
processQueue();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -50,7 +50,7 @@ const DiscoverTvNetwork = () => {
|
||||
{firstResultData?.network.logoPath ? (
|
||||
<div className="mb-6 flex justify-center">
|
||||
<Image
|
||||
src={`https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)${firstResultData.network.logoPath}`}
|
||||
src={`//image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)${firstResultData.network.logoPath}`}
|
||||
alt={firstResultData.network.name}
|
||||
className="max-h-24 sm:max-h-32"
|
||||
fill
|
||||
|
||||
@@ -50,7 +50,7 @@ const DiscoverMovieStudio = () => {
|
||||
{firstResultData?.studio.logoPath ? (
|
||||
<div className="mb-6 flex justify-center">
|
||||
<Image
|
||||
src={`https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)${firstResultData.studio.logoPath}`}
|
||||
src={`//image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)${firstResultData.studio.logoPath}`}
|
||||
alt={firstResultData.studio.name}
|
||||
className="max-h-24 sm:max-h-32"
|
||||
fill
|
||||
|
||||
@@ -181,9 +181,6 @@ const IssueComment = ({
|
||||
`/api/v1/issueComment/${comment.id}`,
|
||||
{
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ message: values.newMessage }),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -126,9 +126,6 @@ const IssueDetails = () => {
|
||||
try {
|
||||
const res = await fetch(`/api/v1/issueComment/${firstComment.id}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ message: newMessage }),
|
||||
});
|
||||
if (!res.ok) throw new Error();
|
||||
@@ -504,9 +501,6 @@ const IssueDetails = () => {
|
||||
`/api/v1/issue/${issueData?.id}/comment`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ message: values.message }),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -59,9 +59,6 @@ const AddEmailModal: React.FC<AddEmailModalProps> = ({
|
||||
try {
|
||||
const res = await fetch('/api/v1/auth/jellyfin', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: username,
|
||||
password: password,
|
||||
|
||||
@@ -45,9 +45,6 @@ const Login = () => {
|
||||
try {
|
||||
const res = await fetch('/api/v1/auth/plex', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ authToken }),
|
||||
});
|
||||
if (!res.ok) throw new Error();
|
||||
|
||||
@@ -57,48 +57,44 @@ const ShowMoreCard = ({ url, posters }: ShowMoreCardProps) => {
|
||||
>
|
||||
<div style={{ paddingBottom: '150%' }}>
|
||||
<div className="absolute inset-0 flex h-full w-full flex-col items-center p-2">
|
||||
<div className="relative z-10 grid h-full w-full grid-cols-2 items-center justify-center gap-2 opacity-30">
|
||||
<div className="relative z-10 flex h-full flex-wrap items-center justify-center opacity-30">
|
||||
{posters[0] && (
|
||||
<div className="">
|
||||
<div className="w-1/2 p-1">
|
||||
<Image
|
||||
src={`https://image.tmdb.org/t/p/w300_and_h450_face${posters[0]}`}
|
||||
src={`//image.tmdb.org/t/p/w300_and_h450_face${posters[0]}`}
|
||||
alt=""
|
||||
className="rounded-md"
|
||||
width={300}
|
||||
height={450}
|
||||
className="w-full rounded-md"
|
||||
fill
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{posters[1] && (
|
||||
<div className="">
|
||||
<div className="w-1/2 p-1">
|
||||
<Image
|
||||
src={`https://image.tmdb.org/t/p/w300_and_h450_face${posters[1]}`}
|
||||
src={`//image.tmdb.org/t/p/w300_and_h450_face${posters[1]}`}
|
||||
alt=""
|
||||
className="rounded-md"
|
||||
width={300}
|
||||
height={450}
|
||||
className="w-full rounded-md"
|
||||
fill
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{posters[2] && (
|
||||
<div className="">
|
||||
<div className="w-1/2 p-1">
|
||||
<Image
|
||||
src={`https://image.tmdb.org/t/p/w300_and_h450_face${posters[2]}`}
|
||||
src={`//image.tmdb.org/t/p/w300_and_h450_face${posters[2]}`}
|
||||
alt=""
|
||||
className="rounded-md"
|
||||
width={300}
|
||||
height={450}
|
||||
className="w-full rounded-md"
|
||||
fill
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{posters[3] && (
|
||||
<div className="">
|
||||
<div className="w-1/2 p-1">
|
||||
<Image
|
||||
src={`https://image.tmdb.org/t/p/w300_and_h450_face${posters[3]}`}
|
||||
src={`//image.tmdb.org/t/p/w300_and_h450_face${posters[3]}`}
|
||||
alt=""
|
||||
className="rounded-md"
|
||||
width={300}
|
||||
height={450}
|
||||
className="w-full rounded-md"
|
||||
fill
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user