mirror of
https://github.com/snobu/destreamer.git
synced 2026-01-21 15:32:16 +00:00
added access token refresh logic (closes #255)
This commit is contained in:
@@ -9,6 +9,10 @@ import jwtDecode from 'jwt-decode';
|
||||
import puppeteer from 'puppeteer';
|
||||
|
||||
|
||||
type Jwt = {
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export class TokenCache {
|
||||
private tokenCacheFile = '.token_cache';
|
||||
|
||||
@@ -21,24 +25,18 @@ export class TokenCache {
|
||||
|
||||
const session: Session = JSON.parse(fs.readFileSync(this.tokenCacheFile, 'utf8'));
|
||||
|
||||
type Jwt = {
|
||||
[key: string]: any
|
||||
}
|
||||
const decodedJwt: Jwt = jwtDecode(session.AccessToken);
|
||||
const [isExpiring, timeLeft] = this.isExpiring(session);
|
||||
|
||||
const now: number = Math.floor(Date.now() / 1000);
|
||||
const exp: number = decodedJwt['exp'];
|
||||
const timeLeft: number = exp - now;
|
||||
|
||||
if (timeLeft < 120) {
|
||||
if (isExpiring) {
|
||||
logger.warn('Access token has expired! \n');
|
||||
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
logger.info(`Access token still good for ${Math.floor(timeLeft / 60)} minutes.\n`.green);
|
||||
|
||||
logger.info(`Access token still good for ${Math.floor(timeLeft / 60)} minutes.\n`.green);
|
||||
|
||||
return session;
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
public Write(session: Session): void {
|
||||
@@ -50,11 +48,23 @@ export class TokenCache {
|
||||
logger.info('Fresh access token dropped into .token_cachen \n'.green);
|
||||
});
|
||||
}
|
||||
|
||||
public isExpiring(session: Session): [boolean, number] {
|
||||
const decodedJwt: Jwt = jwtDecode(session.AccessToken);
|
||||
|
||||
const timeLeft: number = decodedJwt['exp']; - Math.floor(Date.now() / 1000);
|
||||
|
||||
if (timeLeft < (5 * 60)) {
|
||||
return [true, 0];
|
||||
}
|
||||
else {
|
||||
return [false, timeLeft];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function refreshSession(url: string): Promise<Session> {
|
||||
const videoId: string = url.split('/').pop() ?? process.exit(ERROR_CODE.INVALID_VIDEO_GUID);
|
||||
|
||||
const browser: puppeteer.Browser = await puppeteer.launch({
|
||||
executablePath: getPuppeteerChromiumPath(),
|
||||
@@ -70,7 +80,7 @@ export async function refreshSession(url: string): Promise<Session> {
|
||||
const page: puppeteer.Page = (await browser.pages())[0];
|
||||
await page.goto(url, { waitUntil: 'load' });
|
||||
|
||||
await browser.waitForTarget((target: puppeteer.Target) => target.url().includes(videoId), { timeout: 30000 });
|
||||
await browser.waitForTarget((target: puppeteer.Target) => target.url().endsWith('microsoftstream.com/'), { timeout: 150000 });
|
||||
|
||||
let session: Session | null = null;
|
||||
let tries = 1;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { setProcessEvents } from './Events';
|
||||
import { logger } from './Logger';
|
||||
import { getPuppeteerChromiumPath } from './PuppeteerHelper';
|
||||
import { drawThumbnail } from './Thumbnail';
|
||||
import { TokenCache} from './TokenCache';
|
||||
import { TokenCache, refreshSession} from './TokenCache';
|
||||
import { Video, Session } from './Types';
|
||||
import { checkRequirements, parseInputFile, parseCLIinput, getUrlsFromPlaylist} from './Utils';
|
||||
import { getVideosInfo, createUniquePaths } from './VideoUtils';
|
||||
@@ -195,6 +195,12 @@ async function downloadVideo(videoGUIDs: Array<string>,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv.keepLoginCookies && tokenCache.isExpiring(session)) {
|
||||
logger.info('Trying to refresh access token...');
|
||||
session = await refreshSession('https://web.microsoftstream.com/');
|
||||
apiClient.setSession(session);
|
||||
}
|
||||
|
||||
masterParser.push(await apiClient.callUrl(video.playbackUrl).then(res => res?.data));
|
||||
masterParser.end();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user