This repository was archived by the owner on Feb 15, 2026. It is now read-only.
File tree Expand file tree Collapse file tree
components/Settings/SettingsJobsCache Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -2,6 +2,7 @@ import type { PlexDevice } from '@server/interfaces/api/plexInterfaces';
22import cacheManager from '@server/lib/cache' ;
33import { getSettings } from '@server/lib/settings' ;
44import logger from '@server/logger' ;
5+ import { randomUUID } from 'node:crypto' ;
56import xml2js from 'xml2js' ;
67import ExternalAPI from './externalapi' ;
78
@@ -363,6 +364,24 @@ class PlexTvAPI extends ExternalAPI {
363364 } ;
364365 }
365366 }
367+
368+ public async pingToken ( ) {
369+ try {
370+ const response = await this . axios . get ( '/api/v2/ping' , {
371+ headers : {
372+ 'X-Plex-Client-Identifier' : randomUUID ( ) ,
373+ } ,
374+ } ) ;
375+ if ( ! response ?. data ?. pong ) {
376+ throw new Error ( 'No pong response' ) ;
377+ }
378+ } catch ( e ) {
379+ logger . error ( 'Failed to ping token' , {
380+ label : 'Plex Refresh Token' ,
381+ errorMessage : e . message ,
382+ } ) ;
383+ }
384+ }
366385}
367386
368387export default PlexTvAPI ;
Original file line number Diff line number Diff line change 11import availabilitySync from '@server/lib/availabilitySync' ;
22import downloadTracker from '@server/lib/downloadtracker' ;
33import ImageProxy from '@server/lib/imageproxy' ;
4+ import refreshToken from '@server/lib/refreshToken' ;
45import { plexFullScanner , plexRecentScanner } from '@server/lib/scanners/plex' ;
56import { radarrScanner } from '@server/lib/scanners/radarr' ;
67import { sonarrScanner } from '@server/lib/scanners/sonarr' ;
@@ -168,5 +169,19 @@ export const startJobs = (): void => {
168169 } ) ,
169170 } ) ;
170171
172+ scheduledJobs . push ( {
173+ id : 'plex-refresh-token' ,
174+ name : 'Plex Refresh Token' ,
175+ type : 'process' ,
176+ interval : 'fixed' ,
177+ cronSchedule : jobs [ 'plex-refresh-token' ] . schedule ,
178+ job : schedule . scheduleJob ( jobs [ 'plex-refresh-token' ] . schedule , ( ) => {
179+ logger . info ( 'Starting scheduled job: Plex Refresh Token' , {
180+ label : 'Jobs' ,
181+ } ) ;
182+ refreshToken . run ( ) ;
183+ } ) ,
184+ } ) ;
185+
171186 logger . info ( 'Scheduled jobs loaded' , { label : 'Jobs' } ) ;
172187} ;
Original file line number Diff line number Diff line change 1+ import PlexTvAPI from '@server/api/plextv' ;
2+ import { getRepository } from '@server/datasource' ;
3+ import { User } from '@server/entity/User' ;
4+ import logger from '@server/logger' ;
5+
6+ class RefreshToken {
7+ public async run ( ) {
8+ const userRepository = getRepository ( User ) ;
9+
10+ const users = await userRepository
11+ . createQueryBuilder ( 'user' )
12+ . addSelect ( 'user.plexToken' )
13+ . where ( "user.plexToken != ''" )
14+ . getMany ( ) ;
15+
16+ for ( const user of users ) {
17+ await this . refreshUserToken ( user ) ;
18+ }
19+ }
20+
21+ private async refreshUserToken ( user : User ) {
22+ if ( ! user . plexToken ) {
23+ logger . warn ( 'Skipping user refresh token for user without plex token' , {
24+ label : 'Plex Refresh Token' ,
25+ user : user . displayName ,
26+ } ) ;
27+ return ;
28+ }
29+
30+ const plexTvApi = new PlexTvAPI ( user . plexToken ) ;
31+ plexTvApi . pingToken ( ) ;
32+ }
33+ }
34+
35+ const refreshToken = new RefreshToken ( ) ;
36+
37+ export default refreshToken ;
Original file line number Diff line number Diff line change @@ -248,6 +248,7 @@ export type JobId =
248248 | 'plex-recently-added-scan'
249249 | 'plex-full-scan'
250250 | 'plex-watchlist-sync'
251+ | 'plex-refresh-token'
251252 | 'radarr-scan'
252253 | 'sonarr-scan'
253254 | 'download-sync'
@@ -409,6 +410,9 @@ class Settings {
409410 'plex-watchlist-sync' : {
410411 schedule : '0 */3 * * * *' ,
411412 } ,
413+ 'plex-refresh-token' : {
414+ schedule : '0 0 5 * * *' ,
415+ } ,
412416 'radarr-scan' : {
413417 schedule : '0 0 4 * * *' ,
414418 } ,
Original file line number Diff line number Diff line change @@ -53,6 +53,7 @@ const messages: { [messageName: string]: MessageDescriptor } = defineMessages({
5353 'plex-recently-added-scan' : 'Plex Recently Added Scan' ,
5454 'plex-full-scan' : 'Plex Full Library Scan' ,
5555 'plex-watchlist-sync' : 'Plex Watchlist Sync' ,
56+ 'plex-refresh-token' : 'Plex Refresh Token' ,
5657 'availability-sync' : 'Media Availability Sync' ,
5758 'radarr-scan' : 'Radarr Scan' ,
5859 'sonarr-scan' : 'Sonarr Scan' ,
Original file line number Diff line number Diff line change 768768 "components.Settings.SettingsJobsCache.nextexecution" : " Next Execution" ,
769769 "components.Settings.SettingsJobsCache.plex-full-scan" : " Plex Full Library Scan" ,
770770 "components.Settings.SettingsJobsCache.plex-recently-added-scan" : " Plex Recently Added Scan" ,
771+ "components.Settings.SettingsJobsCache.plex-refresh-token" : " Plex Refresh Token" ,
771772 "components.Settings.SettingsJobsCache.plex-watchlist-sync" : " Plex Watchlist Sync" ,
772773 "components.Settings.SettingsJobsCache.process" : " Process" ,
773774 "components.Settings.SettingsJobsCache.radarr-scan" : " Radarr Scan" ,
You can’t perform that action at this time.
0 commit comments