mirror of
https://github.com/snobu/destreamer.git
synced 2026-02-26 16:28:24 +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';
|
import puppeteer from 'puppeteer';
|
||||||
|
|
||||||
|
|
||||||
|
type Jwt = {
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
export class TokenCache {
|
export class TokenCache {
|
||||||
private tokenCacheFile = '.token_cache';
|
private tokenCacheFile = '.token_cache';
|
||||||
|
|
||||||
@@ -21,24 +25,18 @@ export class TokenCache {
|
|||||||
|
|
||||||
const session: Session = JSON.parse(fs.readFileSync(this.tokenCacheFile, 'utf8'));
|
const session: Session = JSON.parse(fs.readFileSync(this.tokenCacheFile, 'utf8'));
|
||||||
|
|
||||||
type Jwt = {
|
const [isExpiring, timeLeft] = this.isExpiring(session);
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
const decodedJwt: Jwt = jwtDecode(session.AccessToken);
|
|
||||||
|
|
||||||
const now: number = Math.floor(Date.now() / 1000);
|
if (isExpiring) {
|
||||||
const exp: number = decodedJwt['exp'];
|
|
||||||
const timeLeft: number = exp - now;
|
|
||||||
|
|
||||||
if (timeLeft < 120) {
|
|
||||||
logger.warn('Access token has expired! \n');
|
logger.warn('Access token has expired! \n');
|
||||||
|
|
||||||
return null;
|
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 {
|
public Write(session: Session): void {
|
||||||
@@ -50,11 +48,23 @@ export class TokenCache {
|
|||||||
logger.info('Fresh access token dropped into .token_cachen \n'.green);
|
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> {
|
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({
|
const browser: puppeteer.Browser = await puppeteer.launch({
|
||||||
executablePath: getPuppeteerChromiumPath(),
|
executablePath: getPuppeteerChromiumPath(),
|
||||||
@@ -70,7 +80,7 @@ export async function refreshSession(url: string): Promise<Session> {
|
|||||||
const page: puppeteer.Page = (await browser.pages())[0];
|
const page: puppeteer.Page = (await browser.pages())[0];
|
||||||
await page.goto(url, { waitUntil: 'load' });
|
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 session: Session | null = null;
|
||||||
let tries = 1;
|
let tries = 1;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { setProcessEvents } from './Events';
|
|||||||
import { logger } from './Logger';
|
import { logger } from './Logger';
|
||||||
import { getPuppeteerChromiumPath } from './PuppeteerHelper';
|
import { getPuppeteerChromiumPath } from './PuppeteerHelper';
|
||||||
import { drawThumbnail } from './Thumbnail';
|
import { drawThumbnail } from './Thumbnail';
|
||||||
import { TokenCache} from './TokenCache';
|
import { TokenCache, refreshSession} from './TokenCache';
|
||||||
import { Video, Session } from './Types';
|
import { Video, Session } from './Types';
|
||||||
import { checkRequirements, parseInputFile, parseCLIinput, getUrlsFromPlaylist} from './Utils';
|
import { checkRequirements, parseInputFile, parseCLIinput, getUrlsFromPlaylist} from './Utils';
|
||||||
import { getVideosInfo, createUniquePaths } from './VideoUtils';
|
import { getVideosInfo, createUniquePaths } from './VideoUtils';
|
||||||
@@ -195,6 +195,12 @@ async function downloadVideo(videoGUIDs: Array<string>,
|
|||||||
continue;
|
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.push(await apiClient.callUrl(video.playbackUrl).then(res => res?.data));
|
||||||
masterParser.end();
|
masterParser.end();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user