-
-
Save georgybu/2d4ac646f90e16b7ab02f7f011341705 to your computer and use it in GitHub Desktop.
Decrypt m3u8 files from play.boomstream.com/player.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FileSaver.min.js | |
(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Depricated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(b,c,d){var e=new XMLHttpRequest;e.open("GET",b),e.responseType="blob",e.onload=function(){a(e.response,c,d)},e.onerror=function(){console.error("could not download file")},e.send()}function d(a){var b=new XMLHttpRequest;return b.open("HEAD",a,!1),b.send(),200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=f.saveAs||"object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(a,b,d,e){if(e=e||open("","_blank"),e&&(e.document.title=e.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(f.HTMLElement)||f.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"object"==typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),e?e.location.href=a:location=a,e=null},j.readAsDataURL(a)}else{var k=f.URL||f.webkitURL,l=k.createObjectURL(a);e?e.location=l:location.href=l,e=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}};f.saveAs=a.saveAs=a,"undefined"!=typeof module&&(module.exports=a)}); | |
function buf2hex(buffer) { | |
return Array.from(new Uint8Array(buffer)).map(x => ('00' + x.toString(16)).slice(-2)).join(''); | |
} | |
function stringToArrayBuffer(str) { | |
return new Uint8Array(Array.from(str).map(x => x.charCodeAt(0))).buffer; | |
} | |
function encrypt(input, key) { | |
let c = []; | |
while (key.length < input.length) { | |
key += key; | |
} | |
for (let i = 0; i < input.length; i++) { | |
let value1 = input.charCodeAt(i); | |
let value2 = key.charCodeAt(i); | |
let xorValue = value1 ^ value2; | |
let xorValueAsHexString = xorValue.toString(16); | |
if (xorValueAsHexString.length < 2) { | |
xorValueAsHexString = '0' + xorValueAsHexString; | |
} | |
c.push(xorValueAsHexString); | |
} | |
return c.join(''); | |
} | |
function decrypt(input, key) { | |
let c = []; | |
while (key.length < input.length) { | |
key += key; | |
} | |
for (let i = 0; i < input.length; i += 2) { | |
let hexValueString = input.substring(i, i + 2); | |
let value1 = parseInt(hexValueString, 16); | |
let value2 = key.charCodeAt(i / 2); | |
let xorValue = value1 ^ value2; | |
c.push(String.fromCharCode(xorValue)) | |
} | |
return c.join(''); | |
} | |
function pProcess(string) { | |
const READY_REGEX = /(?:#EXT-X-MEDIA-READY: *(\w+))\r?\n?/; | |
let result = READY_REGEX.exec(string); | |
let data = decrypt(result[1], 'bla_bla_bla'); | |
let ready = stringToArrayBuffer(data); | |
let iv = '0x' + buf2hex(ready.slice(20, 36)); | |
let key = window.boomstreamConfig.bases.api + '/process/' + encrypt(data.slice(0, 20) + window.boomstreamConfig.mediaData.token, 'bla_bla_bla'); | |
return string.replace('[KEY]', key).replace('[IV]', iv); | |
} | |
fetch(window.boomstreamConfig.mediaData.links.hls) | |
.then(res => res.text()) | |
.then(playlist => playlist.match(/(https:\/\/m\d{1,2}\.boomstream\.com.+)/g)[0]) | |
.then(fetch) | |
.then(res => res.text()) | |
.then(text => | |
saveAs(new Blob([window.boomstreamConfig.encrypt ? pProcess(text) : text], { type: 'text/plain;charset=utf-8;' }), `${window.boomstreamConfig.mediaData.title}.m3u8`) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment