Last active
October 5, 2019 07:33
Star
You must be signed in to star a gist
HomeMediaServer podcast C++Script and PascalScript functions for getting the MediaResourceLink from moonwalk server
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
void GetLink_Moonwalk(string sLink) { | |
string sHtml, sData,sLinks, sJsData, sPost, sVer, sQual, sVal, sServ, sVar, sUrlBase, sJSONParams; | |
int i, n; float f; TRegExpr RE; bool bHdsDump, bQualLog; | |
TJsonObject JSON, OPTIONS; | |
string sUserAgent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'; | |
string sHeaders = sLink+'\r\n'+ | |
'User-Agent: '+sUserAgent+'\r\n'; | |
// Для Windows XP - отключаем сжатие страниц. Ибо автоматом ответы не распаковываются. | |
if (StrToFloatDef(RegistryRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\CurrentVersion"), 0) < 6) { | |
sHeaders += 'accept-encoding: identity\r\n'; | |
} else { | |
sHeaders += 'accept-encoding: gzip, deflate, br\r\n'; | |
} | |
// Проверка установленных дополнительных параметров | |
HmsRegExMatch('--quality=(\\w+)', mpPodcastParameters, sQual); | |
bQualLog = Pos('--qualitylog' , mpPodcastParameters) > 0; | |
// Замена домена moonwalk.co и moonwalk.pw на moonwalk.cc | |
HmsRegExReplace('(.*?moonwalk.)(co|pw)(.*)', sLink, '$1cc$3', sLink); | |
sHtml = HmsDownloadURL(sLink, 'Referer: '+sHeaders); | |
if (HmsRegExMatch('<iframe[^>]+src="(http.*?)"', sHtml, sLink)) { | |
// Если внутри есть ссылка на iframe - загружаем его | |
HmsRegExReplace('(.*?moonwalk.)(co|pw)(.*)', sLink, '$1cc$3', sLink); | |
sHtml = HmsDownloadURL(sLink, 'Referer: '+sHeaders); | |
} | |
HmsRegExMatch2('(.*?//([^/]+))', sLink, sUrlBase, sServ); // Получаем UrlBase и домен | |
JSON = TJsonObject.Create(); | |
OPTIONS = TJsonObject.Create(); | |
try { | |
// Ищем значения параметров (this.options) | |
if (!HmsRegExMatch('video_balancer_options\\s*=\\s*(\\{.*?\\});', sHtml, sData)) { | |
if (HmsRegExMatch3("//.*?/(.*?)/(.*?)/[^?]+\\??(.*)", sLink, sVer, sVal, sData)) | |
sHtml = HmsDownloadURL("http://api.lostcut.net/?action=moonhtml&t="+sVer+"&i="+sVal+"&p="+HmsHttpEncode(sData), 'Referer: '+sHeaders); | |
if (!HmsRegExMatch('video_balancer_options\\s*=\\s*(\\{.*?\\});', sHtml, sData)) { | |
sVal = "Не найдены данные VideoBalancer в iframe."; | |
if (HmsRegExMatch("<div[^>]+absolute.*?</div>", sHtml, sVal, 0, PCRE_SINGLELINE)) sVal = HmsRemoveLineBreaks(HmsHtmlToText(sVal, 65001)); | |
HmsLogMessage(2, mpTitle+": "+sVal); | |
// Заглушка | |
sVal = ExtractWord(Round(Random*2)+1, "wZ5JJ1CRWdO0,IRcEgNmu9AUn,ebxWWiOq6VbO", ","); | |
sData = HmsDownloadURL("https://studio.stupeflix.com/v/"+sVal+"/", sHeaders, true); | |
HmsRegExMatch('"(http[^>"]+\\.mp4)', sData, MediaResourceLink); | |
return; | |
} | |
} | |
OPTIONS.LoadFromString(sData); | |
sUrlBase = OPTIONS.S["proto"]+OPTIONS.S["host"]; | |
sHeaders = HmsHttpDecode(OPTIONS.S["ref_url"])+'\r\n'+ | |
'User-Agent: '+sUserAgent+'\r\n'+ | |
'Origin: '+sUrlBase+'\r\n'+ | |
'Accept: application/json, text/javascript, */*; q=0.01\r\n'+ | |
'X-Requested-With: XMLHttpRequest\r\n'; | |
// Если есть субтитры и их ещё локально не сохраняли - загружаем | |
if ((OPTIONS.S["subtitles\\master_vtt"]!="") && (!FileExists(PodcastItem[mpiSubtitleLanguage]))) { | |
sData = HmsUtf8Decode(HmsDownloadURL(OPTIONS.S["subtitles\\master_vtt"], "Referer: "+sHeaders)); | |
RE = TRegExpr.Create('(\\d{2}:\\d{2}:[\\d:,.\\s->]+.*?)(?=\n\\d{2}:d{2}:|\n\\d+\n|$)', PCRE_SINGLELINE); | |
i = 1; sVal = ""; // Форматируем | |
if (RE.Search(sData)) do { sVal += Format("%d\r\n%s\r\n\r\n", [i, RE.Match]); i++; } while (RE.SearchAgain); | |
sLink = HmsSubtitlesDirectory+'\\'+PodcastItem.ItemID+'.srt'; | |
HmsStringToFile(sVal, sLink); // Сохраняем субтитры локально | |
PodcastItem[mpiSubtitleLanguage] = sLink; // Указываем новое расположение | |
} | |
string iv = "2ea2116c80fae4e90c1e2b2b765fcc45"; | |
string sKey = "9186a0bae4afec34c323aecb7754b7c848e016188eb8b5be677d54d3e70f9cbd"; | |
sData = HmsDownloadURL("http://wonky.lostcut.net/moonwalk_key.php"); | |
HmsRegExMatch('"iv":"(\\w+)"' , sData, iv ); | |
HmsRegExMatch('"key":"(\\w+)"', sData, sKey); | |
//player_skin | |
string sData4Encrypt = '{"a":4787,"b":22245,"c":false,"d":"'+OPTIONS.S['player_skin']+'","e":"'+OPTIONS.S['video_token']+'","f":"'+sUserAgent+'"}'; | |
int padding = 16 - (Length(sData4Encrypt) % 16); | |
for (i=0; i < padding; i++) sData4Encrypt += chr(padding); // PKCS7 Padding | |
sVal = HmsCryptCipherEncode("Rijndael", sData4Encrypt, HmsHexToString(sKey), HmsHexToString(iv), cmCBCx, "MIME64"); | |
sPost = "q="+HmsHttpEncode(sVal)+'&ref='+OPTIONS.S["ref"]; | |
sData = HmsSendRequest(OPTIONS.S["host"], "/vs", 'POST', 'application/x-www-form-urlencoded; Charset=UTF-8', sHeaders, sPost, 80, true); | |
if (LeftCopy(sData, 5)!='{"mp4') { | |
// Данные защиты устарели, пробуем получить новые | |
sData = HmsDownloadURL("https://github.com/WendyH/PHP-Scripts/raw/master/moon4crack.ini"); | |
HmsRegExMatch('iv\\s*=\\s*["\']?(.*?)["\']' , sData, iv, ); | |
HmsRegExMatch('key\\s*=\\s*["\']?(.*?)["\']', sData, sKey); | |
sVal = HmsCryptCipherEncode("Rijndael", sData4Encrypt, HmsHexToString(sKey), HmsHexToString(iv), cmCBCx, "MIME64"); | |
sPost = "q="+HmsHttpEncode(sVal)+'&ref='+OPTIONS.S["ref"]; | |
sData = HmsSendRequest(sServ, "/vs", 'POST', 'application/x-www-form-urlencoded; Charset=UTF-8', sHeaders, sPost, 80, true); | |
} | |
sVar = "mp4"; | |
JSON.LoadFromString(sData); | |
bool bMP4 = Pos("--mp4", mpPodcastParameters)>0; | |
if (bMP4 && (JSON.B["mp4" ])) sVar = "mp4" ; | |
else if (JSON.B["m3u8"]) sVar = "m3u8"; | |
sLink = JSON.S[sVar]; | |
if (sLink!="") sData = HmsDownloadURL(sLink, "Referer: "+sHeaders, true); | |
} finally { JSON.Free; OPTIONS.Free; } | |
TStringList QLIST = TStringList.Create(); | |
if (sVar=="m3u8") { | |
MediaResourceLink = sLink; | |
// Получение длительности видео, если она не установлена | |
// ------------------------------------------------------------------------ | |
sVal = Trim(PodcastItem.ItemOrigin[mpiTimeLength]); | |
if ((sVal=='') || (RightCopy(sVal, 6)=='00.000')) { | |
if (HmsRegExMatch('(http.*?)[\r\n$]', sData, sLink)) { | |
sHtml = HmsDownloadUrl(sLink, 'Referer: '+sHeaders, true); | |
RE = TRegExpr.Create('#EXTINF:(\\d+.\\d+)', PCRE_SINGLELINE); f=0; | |
if (RE.Search(sHtml)) do f += StrToFloatDef(RE.Match(1), 0); while (RE.SearchAgain()); | |
RE.Free; | |
if (f > 0) PodcastItem.ItemOrigin[mpiTimeLength] = HmsTimeFormat(Round(f))+'.000'; | |
} | |
} | |
// ------------------------------------------------------------------------ | |
// Если установлен ключ --quality или в настройках подкаста выставлен приоритет выбора качества | |
// ------------------------------------------------------------------------ | |
string sSelectedQual = '', sMsg, sHeight; int iMinPriority = 99, iPriority; | |
if ((sQual!='') || (mpPodcastMediaFormats!='')) { | |
// Собираем список ссылок разного качества | |
RE = TRegExpr.Create('#EXT-X-STREAM-INF:RESOLUTION=\\d+x(\\d+).*?[\r\n](http.+)$', PCRE_MULTILINE); | |
if (RE.Search(sData)) do { | |
sHeight = Format('%.5d', [StrToInt(RE.Match(1))]); | |
sLink = RE.Match(2); | |
QLIST.Values[sHeight] = sLink; | |
iPriority = HmsMediaFormatPriority(StrToInt(sHeight), mpPodcastMediaFormats); | |
if ((iPriority >= 0) && (iPriority < iMinPriority)) { | |
iMinPriority = iPriority; | |
sSelectedQual = sHeight; | |
} | |
} while (RE.SearchAgain()); | |
RE.Free; | |
} | |
// ------------------------------------------------------------------------ | |
} else if (sVar=="mp4") { | |
// Составляем список ссылок с разным качеством | |
JSON = TJsonObject.Create(); | |
try { | |
JSON.LoadFromString(sData); | |
for (i=0; i<JSON.Count; i++) { | |
sVer = JSON.Names[i]; | |
sLink = JSON.S[sVer]; | |
sHeight = Format('%.5d', [StrToIntDef(sVer, 0)]); | |
QLIST.Values[sHeight] = sLink; | |
} | |
} finally { JSON.Free(); } | |
} else { | |
HmsLogMessage(2, mpTitle+': Ошибка получения данных от сервера moonwalk.'); | |
if (DEBUG==1) { | |
if (ServiceMode) sVal = SpecialFolderPath(0x37); // Общая папака "Видео" | |
else sVal = SpecialFolderPath(0); // Рабочий стол | |
sVal = IncludeTrailingBackslash(sVal)+'Moonwalk.log'; | |
HmsStringToFile(sHeaders+'\r\nsHtml:\r\n'+sHtml+'\r\nsPost:\r\n'+sPost+'\r\nsData:\r\n'+sData, sVal); | |
HmsLogMessage(1, mpTitle+': Создан лог файл '+sVal); | |
} | |
} | |
// Если сформирован список ссылок для разного качества | |
if (QLIST.Count > 0) { | |
QLIST.Sort(); | |
if (sQual=='low' ) sSelectedQual = QLIST.Names[0]; | |
else if (sQual=='medium') sSelectedQual = QLIST.Names[Round((QLIST.Count-1) / 2)]; | |
else if (sQual=='high' ) sSelectedQual = QLIST.Names[QLIST.Count - 1]; | |
else if (HmsRegExMatch('(\\d+)', sQual, sQual)) { | |
extended minDiff = 999999; // search nearest quality | |
for (i=0; i < QLIST.Count; i++) { | |
extended diff = StrToInt(QLIST.Names[i]) - StrToInt(sQual); | |
if (Abs(diff) < minDiff) { | |
minDiff = Abs(diff); | |
sSelectedQual = QLIST.Names[i]; | |
} | |
} | |
} | |
} | |
if (sSelectedQual != '') MediaResourceLink = QLIST.Values[sSelectedQual]; | |
if (bQualLog) { | |
sMsg = 'Доступное качество: '; | |
for (i = 0; i < QLIST.Count; i++) { | |
if (i>0) sMsg += ', '; | |
sMsg += IntToStr(StrToInt(QLIST.Names[i])); // Обрезаем лидирующие нули | |
} | |
if (sSelectedQual != '') sSelectedQual = IntToStr(StrToInt(sSelectedQual)); | |
else sSelectedQual = 'Auto'; | |
sMsg += '. Выбрано: ' + sSelectedQual; | |
HmsLogMessage(1, mpTitle+'. '+sMsg); | |
} | |
QLIST.Free; | |
if (sVar=="m3u8") MediaResourceLink = " "+Trim(MediaResourceLink); | |
} // Конец функции поулчения ссылки с moonwalk.cc |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment