Skip to content

Commit

Permalink
fix(dashboard): users request count
Browse files Browse the repository at this point in the history
closes #210
  • Loading branch information
RaunoT authored Aug 5, 2024
1 parent 357ca3c commit 842b103
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 55 deletions.
9 changes: 6 additions & 3 deletions src/app/api/image/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ export async function GET(request: Request) {
const url = searchParams.get('url')

if (!url) {
return new Response('URL parameter is missing', { status: 400 })
return new Response('[IMAGE PROXY] - URL parameter is missing', {
status: 400,
})
}

const res = await fetch(url)

if (!res.ok) {
return new Response('Failed to fetch the image', {
return new Response('[IMAGE PROXY] - Failed to fetch the image', {
status: res.status,
})
}
Expand All @@ -22,7 +24,8 @@ export async function GET(request: Request) {
status: res.status,
headers: headers,
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
return new Response('An error occurred', { status: 500 })
return new Response('[IMAGE PROXY] - An error occurred', { status: 500 })
}
}
6 changes: 3 additions & 3 deletions src/app/dashboard/users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { DashboardSearchParams } from '@/types/dashboard'
import { Settings } from '@/types/settings'
import { TautulliItem, TautulliUser } from '@/types/tautulli'
import {
fetchOverseerrStats,
fetchOverseerrUserId,
fetchPaginatedOverseerrStats,
} from '@/utils/fetchOverseerr'
import fetchTautulli, { getLibrariesByType } from '@/utils/fetchTautulli'
import { secondsToTime, timeToSeconds } from '@/utils/formatting'
Expand Down Expand Up @@ -66,7 +66,7 @@ async function getUsers(
usersRequestsCounts = await Promise.all(
overseerrUserIds.map(async (overseerrId) => {
if (overseerrId) {
const userTotal = await fetchPaginatedOverseerrStats(
const userTotal = await fetchOverseerrStats(
`user/${overseerrId}/requests`,
requestsPeriod,
)
Expand Down Expand Up @@ -182,7 +182,7 @@ async function getTotalRequests(period: string, settings: Settings) {
settings.dashboard.activeTotalStatistics.includes('requests') &&
isOverseerrActive
) {
const requests = await fetchPaginatedOverseerrStats('request', period)
const requests = await fetchOverseerrStats('request', period)

return requests.length.toString()
}
Expand Down
1 change: 0 additions & 1 deletion src/app/settings/rewind/_components/RewindSettingsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export default function RewindSettingsForm({ settings, users }: Props) {
<li key={user.user_id}>
<Link
href={`/rewind?userId=${user.user_id}`}
target='_blank'
className='button button-sm'
>
{user.friendly_name}
Expand Down
4 changes: 1 addition & 3 deletions src/types/dashboard.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { PERIODS } from '@/utils/constants'

export type DashboardSearchParams = {
period?: keyof typeof PERIODS
period?: '7days' | '30days' | 'thisYear' | 'pastYear' | 'allTime' | 'custom'
personal?: 'true'
}
2 changes: 1 addition & 1 deletion src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const ALL_TIME: Date = new Date(
env('NEXT_PUBLIC_STATISTICS_START_DATE') || '2018-01-01',
)

type Period = {
export type Period = {
date: string
string: string
daysAgo: number
Expand Down
131 changes: 92 additions & 39 deletions src/utils/fetchOverseerr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,21 @@ type OverseerrResponse<T> = {
results: number
page: number
}
results: T
results: T[]
}

type OverseerrUser = {
id: number
plexId: number
plexUsername: string
}

type OverseerrRequestItem = {
createdAt: string
type: string
requestedBy: {
plexId: number
}
}

export default async function fetchOverseerr<T>(
Expand Down Expand Up @@ -42,12 +56,14 @@ export default async function fetchOverseerr<T>(
revalidate: cache ? 3600 : 0,
},
})

if (!res.ok) {
console.error(
`[OVERSEERR] - API request failed! The endpoint was '${endpoint}'.\n`,
res.status,
res.statusText,
)
return null
}

return res.json()
Expand All @@ -60,52 +76,89 @@ export default async function fetchOverseerr<T>(
}
}

type User = {
id: number
plexId: number
plexUsername: string
export async function fetchOverseerrStats(
req: string,
timeframe: string,
): Promise<OverseerrRequestItem[]> {
const pageSize = 10
let requestsArr: OverseerrRequestItem[] = []

async function fetchRequests(
page: number,
): Promise<OverseerrResponse<OverseerrRequestItem> | null> {
return await fetchOverseerr<OverseerrResponse<OverseerrRequestItem>>(
`${req}?skip=${pageSize * (page - 1)}`,
)
}

// Fetch the first page to determine total pages
const firstPage = await fetchRequests(1)

if (!firstPage || !firstPage.results) {
console.error('[OVERSEERR] - No requests data found!')
return []
}

const totalPages = firstPage.pageInfo.pages
const promises = []

// Fetch remaining pages in parallel
for (let page = 2; page <= totalPages; page++) {
promises.push(fetchRequests(page))
}

const results = await Promise.all(promises)
const allRequests = [firstPage, ...results].flatMap(
(res) => res?.results || [],
)
const filteredRequests = allRequests.filter(
(request) => new Date(request.createdAt) > new Date(timeframe),
)

requestsArr = [...requestsArr, ...filteredRequests]

return requestsArr
}

export async function fetchOverseerrUserId(
plexId: string,
): Promise<number | null> {
const users = await fetchOverseerr<OverseerrResponse<User[]>>('user', true)
const user = users?.results?.find((user) => String(user.plexId) === plexId)
const pageSize = 10
let userId: number | null = null

async function fetchUsers(
page: number,
): Promise<OverseerrResponse<OverseerrUser> | null> {
return await fetchOverseerr<OverseerrResponse<OverseerrUser>>(
`user?skip=${pageSize * (page - 1)}`,
)
}

return user ? user.id : null
}
// Fetch the first page to determine total pages
const firstPage = await fetchUsers(1)

type PaginatedRequestItem = {
createdAt: string
type: string
requestedBy: {
plexId: number
if (!firstPage || !firstPage.results) {
console.error(`[OVERSEERR] - No user data found!`)
return null
}
}

export async function fetchPaginatedOverseerrStats(
req: string,
timeframe: string,
): Promise<PaginatedRequestItem[]> {
let requestsArr: PaginatedRequestItem[] = []
let currentPage = 1
let totalPages = 1
let reqUrl = req

do {
const requestsData =
await fetchOverseerr<OverseerrResponse<PaginatedRequestItem[]>>(reqUrl)

if (requestsData && requestsData.results) {
const requestsDataFiltered = requestsData.results.filter(
(request) => request.createdAt > timeframe,
)
requestsArr = [...requestsDataFiltered, ...requestsArr]
totalPages = requestsData.pageInfo.pages
currentPage = requestsData.pageInfo.page
reqUrl = `${req}?skip=${requestsData.pageInfo.pageSize * currentPage}`
}
} while (currentPage < totalPages)
const totalPages = firstPage.pageInfo.pages
const promises = []

return requestsArr
// Fetch remaining pages in parallel
for (let page = 2; page <= totalPages; page++) {
promises.push(fetchUsers(page))
}

const results = await Promise.all(promises)
const allUsers = [firstPage, ...results].flatMap((res) => res?.results || [])
const user = allUsers.find((user) => String(user.plexId) === plexId)

if (user) {
userId = user.id
} else {
console.error(`[OVERSEERR] - No matching user found for plexId ${plexId}!`)
}

return userId
}
7 changes: 2 additions & 5 deletions src/utils/getRewind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
TautulliMediaType,
} from '@/types/tautulli'
import { PERIODS } from './constants'
import { fetchPaginatedOverseerrStats } from './fetchOverseerr'
import { fetchOverseerrStats } from './fetchOverseerr'
import fetchTautulli from './fetchTautulli'
import { secondsToTime, timeToSeconds } from './formatting'
import getMediaAdditionalData from './getMediaAdditionalData'
Expand Down Expand Up @@ -197,10 +197,7 @@ export async function getTopMediaItems(
}

export async function getRequestsTotals(userId: string) {
const requests = await fetchPaginatedOverseerrStats(
'request',
PERIODS.pastYear.date,
)
const requests = await fetchOverseerrStats('request', PERIODS.pastYear.date)

return {
total: requests.length,
Expand Down

0 comments on commit 842b103

Please sign in to comment.