minor change in th epage loading
created function that fetchs title and hlsUrl from the Microsoft api after beeing authenticated with the token fetched from the page
This commit is contained in:
parent
1b6ff66dee
commit
ec407d1e9b
1 changed files with 59 additions and 32 deletions
|
@ -5,10 +5,16 @@ import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { BrowserTests } from './BrowserTests';
|
import { BrowserTests } from './BrowserTests';
|
||||||
import yargs = require('yargs');
|
import yargs = require('yargs');
|
||||||
import sanitize = require('sanitize-filename')
|
import sanitize = require('sanitize-filename');
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exitCode 25 = cannot split videoID from videUrl
|
||||||
|
* exitCode 27 = no hlsUrl in the api
|
||||||
|
* exitCode 88 = error extracting cookies
|
||||||
|
*/
|
||||||
|
|
||||||
// Type in your username here (the one you use to
|
|
||||||
// login to Microsoft Stream).
|
|
||||||
const args: string[] = process.argv.slice(2); // TODO: Remove this
|
const args: string[] = process.argv.slice(2); // TODO: Remove this
|
||||||
|
|
||||||
const argv = yargs.options({
|
const argv = yargs.options({
|
||||||
|
@ -69,7 +75,7 @@ function sanityChecks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Removed check on the first argoumenti not being null or
|
/* Removed check on the first argoumenti not being null or
|
||||||
longer than 10 since we have yargs now */
|
longer than 10 since we use yargs now */
|
||||||
}
|
}
|
||||||
|
|
||||||
async function rentVideoForLater(videoUrls: string[], username: string, outputDirectory: string) {
|
async function rentVideoForLater(videoUrls: string[], username: string, outputDirectory: string) {
|
||||||
|
@ -84,7 +90,7 @@ async function rentVideoForLater(videoUrls: string[], username: string, outputDi
|
||||||
|
|
||||||
// This breaks on slow connections, needs more reliable logic
|
// This breaks on slow connections, needs more reliable logic
|
||||||
//const oidcUrl = "https://login.microsoftonline.com/common/oauth2/authorize?client_id=cf53fce8-def6-4aeb-8d30-b158e7b1cf83&response_mode=form_post&response_type=code+id_token&scope=openid+profile&state=OpenIdConnect.AuthenticationProperties%3d1VtrsKV5QUHtzn8cDWL4wJmacu-VHH_DfpPxMQBhnfbar-_e8X016GGJDPfqfvcyUK3F3vBoiFwUpahR2ANfrzHE469vcw7Mk86wcAqBGXCvAUmv59MDU_OZFHpSL360oVRBo84GfVXAKYdhCjhPtelRHLHEM_ADiARXeMdVTAO3SaTiVQMhw3c9vLWuXqrKKevpI7E5esCQy5V_dhr2Q7kKrlW3gHX0232b8UWAnSDpc-94&nonce=636832485747560726.NzMyOWIyYWQtM2I3NC00MmIyLTg1NTMtODBkNDIwZTI1YjAxNDJiN2JkNDMtMmU5Ni00OTc3LWFkYTQtNTNlNmUwZmM1NTVl&nonceKey=OpenIdConnect.nonce.F1tPks6em0M%2fWMwvatuGWfFM9Gj83LwRKLvbx9rYs5M%3d&site_id=500453&redirect_uri=https%3a%2f%2fmsit.microsoftstream.com%2f&post_logout_redirect_uri=https%3a%2f%2fproducts.office.com%2fmicrosoft-stream&msafed=0";
|
//const oidcUrl = "https://login.microsoftonline.com/common/oauth2/authorize?client_id=cf53fce8-def6-4aeb-8d30-b158e7b1cf83&response_mode=form_post&response_type=code+id_token&scope=openid+profile&state=OpenIdConnect.AuthenticationProperties%3d1VtrsKV5QUHtzn8cDWL4wJmacu-VHH_DfpPxMQBhnfbar-_e8X016GGJDPfqfvcyUK3F3vBoiFwUpahR2ANfrzHE469vcw7Mk86wcAqBGXCvAUmv59MDU_OZFHpSL360oVRBo84GfVXAKYdhCjhPtelRHLHEM_ADiARXeMdVTAO3SaTiVQMhw3c9vLWuXqrKKevpI7E5esCQy5V_dhr2Q7kKrlW3gHX0232b8UWAnSDpc-94&nonce=636832485747560726.NzMyOWIyYWQtM2I3NC00MmIyLTg1NTMtODBkNDIwZTI1YjAxNDJiN2JkNDMtMmU5Ni00OTc3LWFkYTQtNTNlNmUwZmM1NTVl&nonceKey=OpenIdConnect.nonce.F1tPks6em0M%2fWMwvatuGWfFM9Gj83LwRKLvbx9rYs5M%3d&site_id=500453&redirect_uri=https%3a%2f%2fmsit.microsoftstream.com%2f&post_logout_redirect_uri=https%3a%2f%2fproducts.office.com%2fmicrosoft-stream&msafed=0";
|
||||||
await page.goto(videoUrls[0], { waitUntil: 'networkidle2' });
|
await page.goto(videoUrls[0], { waitUntil: "networkidle2" });
|
||||||
await page.waitForSelector('input[type="email"]');
|
await page.waitForSelector('input[type="email"]');
|
||||||
await page.keyboard.type(username);
|
await page.keyboard.type(username);
|
||||||
await page.click('input[type="submit"]');
|
await page.click('input[type="submit"]');
|
||||||
|
@ -95,7 +101,11 @@ async function rentVideoForLater(videoUrls: string[], username: string, outputDi
|
||||||
console.log('Sorry, i mean "you".');
|
console.log('Sorry, i mean "you".');
|
||||||
|
|
||||||
for (let videoUrl of videoUrls) {
|
for (let videoUrl of videoUrls) {
|
||||||
await page.goto(videoUrl, { waitUntil: 'networkidle2' });
|
let videoID = videoUrl.split('/').pop() ?? (console.error("Couldn't split the videoID, wrong url"), process.exit(25))
|
||||||
|
|
||||||
|
// changed waitUntil value to load (page completly loaded)
|
||||||
|
await page.goto(videoUrl, { waitUntil: 'load' });
|
||||||
|
|
||||||
await sleep(2000);
|
await sleep(2000);
|
||||||
// try this instead of hardcoding sleep
|
// try this instead of hardcoding sleep
|
||||||
// https://github.com/GoogleChrome/puppeteer/issues/3649
|
// https://github.com/GoogleChrome/puppeteer/issues/3649
|
||||||
|
@ -104,39 +114,20 @@ async function rentVideoForLater(videoUrls: string[], username: string, outputDi
|
||||||
console.log('Got cookie. Consuming cookie...');
|
console.log('Got cookie. Consuming cookie...');
|
||||||
|
|
||||||
await sleep(4000);
|
await sleep(4000);
|
||||||
console.log('Looking up AMS stream locator...');
|
console.log("Accessing API...");
|
||||||
|
|
||||||
let document: any;
|
let sessionInfo: any;
|
||||||
const amsUrl = await page.evaluate(
|
var accesToken = await page.evaluate(
|
||||||
// maybe there should be some check in case the url fetch fails
|
|
||||||
() => {
|
() => {
|
||||||
return document?.querySelector(".azuremediaplayer")?.player?.cache_?.src;
|
return sessionInfo.AccessToken;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// console.log(`Video url is: ${amsUrl}`);
|
console.log("Fetching title and HLS URL...")
|
||||||
console.log('Fetching title...');
|
var [title, hlsUrl] = await getVideoInfo(videoID, accesToken)
|
||||||
|
|
||||||
let title = await page.evaluate(
|
title = (sanitize(title) == "") ? `Video${videoUrls.indexOf(videoUrl)}` : sanitize(title)
|
||||||
// Using optional chaining to return handle null case, generating default name
|
|
||||||
() => {
|
|
||||||
return document?.querySelector(".title")?.textContent?.trim() ??
|
|
||||||
`Video${videoUrls.indexOf(videoUrl)}`;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Implemented sanitize-filename as suggested in issue #11
|
|
||||||
title = sanitize(title)
|
|
||||||
|
|
||||||
if (title == "")
|
|
||||||
title = `Video${videoUrls.indexOf(videoUrl)}`
|
|
||||||
|
|
||||||
//console.log(`Video title is: ${title}`);
|
|
||||||
|
|
||||||
console.log('Constructing HLS URL...');
|
|
||||||
const hlsUrl = amsUrl.substring(0, amsUrl.lastIndexOf('/')) + '/manifest(format=m3u8-aapl)';
|
|
||||||
|
|
||||||
// If the simulate flag is true skip the download
|
|
||||||
if (!argv.simulate) {
|
if (!argv.simulate) {
|
||||||
console.log('Spawning youtube-dl with cookie and HLS URL...');
|
console.log('Spawning youtube-dl with cookie and HLS URL...');
|
||||||
let format = ''
|
let format = ''
|
||||||
|
@ -186,6 +177,42 @@ async function exfiltrateCookie(page: puppeteer.Page) {
|
||||||
return `Authorization=${authzCookie.value}; Signature=${sigCookie.value}`;
|
return `Authorization=${authzCookie.value}; Signature=${sigCookie.value}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function getVideoInfo(videoID: string, accesToken: string) {
|
||||||
|
let title: string;
|
||||||
|
let hlsUrl: string;
|
||||||
|
|
||||||
|
let content = axios.get(
|
||||||
|
`https://euwe-1.api.microsoftstream.com/api/videos/${videoID}?$expand=creator,tokens,status,liveEvent,extensions&api-version=1.3-private`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer " + accesToken
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function (response) {
|
||||||
|
return response.data
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
title = await content.then(data => {
|
||||||
|
return data["name"];
|
||||||
|
})
|
||||||
|
|
||||||
|
hlsUrl = await content.then(data => {
|
||||||
|
for (const item of data["playbackUrls"]) {
|
||||||
|
if (item["mimeType"] == "application/vnd.apple.mpegurl")
|
||||||
|
return item["playbackUrl"]
|
||||||
|
}
|
||||||
|
console.error("Error fetching hlsUrl")
|
||||||
|
process.exit(27)
|
||||||
|
})
|
||||||
|
|
||||||
|
return [title, hlsUrl];
|
||||||
|
}
|
||||||
|
|
||||||
// We should probably use Mocha or something
|
// We should probably use Mocha or something
|
||||||
if (args[0] === 'test')
|
if (args[0] === 'test')
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue