//This version of script is for use with PVD versions 0.9.9.16 and above!!! (* * Original code for 0.1.2.0 by Gazonkfoo * 0.1.2.1 Modded 12/20/2013 by Aimhere - add option to exclude back cover images per a flag in constants section * 0.1.2.2 Modded 02/18/2015 by pra15 - due to ADE website changes (see forum) * 0.1.2.3 Modded 06/27/2015 by pra15 - due to ADE search results changes (see forum) * 0.1.2.4 Modded 07/05/2015 by Aimhere - slight change in ADE search results page HTML * 0.1.2.5 Modded 07/08/2015 by pra15 - change method to find URL in search results * 0.1.2.6 Modded 08/09/2015 by Aimhere - script was no longer finding Tagline/Description, Customer Rating * 0.1.2.7 Modded 08/09/2015 by Aimhere - script was not finding Genre/Studio/Duration/Release Date, list of actors had extra/bad entries, director name was messed up, infinite loop if Producer was present, Release Date not saved * 0.1.2.8 Modded 02/22/2017 by Aimhere - was not finding Year, Tagline, Description due to ADE website changes; duration was not being calculated correctly; duration was not being saved to correct XML field * 0.1.2.9 Modded 02/22/2017 by Ivek23 - due to ADE website URL changes (see forum) * 0.1.3.0 Modded 12/31/2017 by Aimhere - more ADE website HTML changes * 0.2.0.0 Modded 10/15/2023 by NetworkShark - Rewritten for use with curl [HTTPS workaround] and adaptation to new website * 0.2.1.0 Modded 10/16/2023 by NetworkShark - Bugfixing folder temp. * 0.2.2.0 Modded 10/16/2023 by NetworkShark - Added the limit at search pages. * 0.2.3.0 Modded 10/18/2023 by NetworkShark & Ivek - Bugfixing + Create tmp folder only if necessary * 0.2.4.0 Modded 10/19/2023 by NetworkShark & Ivek - Bugfixing * 0.2.5.0 Modded 10/20/2023 by Ivek & NetworkShark - Bugfixing + Set Genre to Adult * 0.2.5.1 Modded 10/21/2023 by NetworkShark & Ivek - Bugfixing * 0.2.6.0 Modded 10/22/2023 by NetworkShark - Rewrote the function for extracting director data and removed code from other functions previously used * 0.2.7.0 Modded 10/25/2023 by Ivek23 - Bugfixing & Adding functions * 0.2.7.1 Modded 10/25/2023 by NetworkShark & Ivek - Bugfixing * 0.2.7.2 Modded 10/25/2023 by NetworkShark & Ivek - Bugfixing: actor url generate duplicates on people views * 0.2.7.3 Modded 10/26/2024 by NetworkShark - Bugfixing: handled if search movie return no results * 0.2.8.0 Modded 10/26/2024 by NetworkShark - Added function to bypass Age Confermation on GetLogin * 0.2.9.0 Modded 11/XX/2024 by NetworkShark - Added function to remove old files *) //Some useful constants const //Script types stMovies = 0; stPeople = 1; stPoster = 2; //Script modes smSearch = 0; smNormal = 1; smPoster = 2; smDummy = 3; //Parse results prError = 0; prFinished = 1; prList = 2; prListImage = 3; prDownload = 4; //Credits types ctActors = 0; ctDirectors = 1; ctWriters = 2; ctComposers = 3; ctProducers = 4; //Image types imPoster = 0; imScreenshoot = 1; imFrontCover = 2; imDiscImage = 3; imPhoto = 4; //Script data //This version of script is for use with PVD versions 0.9.9.16 and above!!! SCRIPT_VERSION = '0.2.9.0'; SCRIPT_NAME = '[EN][HTTPS]adultempire.com'; SCRIPT_DESC = '[EN] Get movie information from adultempire.com'; SCRIPT_LANG = $09; //English SCRIPT_TYPE = stMovies; BASE_URL = 'http://www.adultempire.com'; BASE_URL_HTTPS = 'https://www.adultempire.com'; RATING_NAME = 'ADE'; BASE_SEARCH = BASE_URL + '/allsearch/search'; SEARCH_STR = BASE_SEARCH + '?pageSize=48&q=%s&view=list'; MAX_SEARCH_PAGES = 10; CODE_PAGE = 0; //65001 UTF-8 - Use 0 for Autodetect USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0'; INTERNET_TEST_ITERATIONS = 20; //Attempts before to alert user that not internet connection detected. Increase if the provider has low speed. INTERNET_WAIT_TIMING = 500; BASE_DOWNLOAD = 'tmp\'; FILE_INDEX_DOWNLOAD = 'adultempire_single_index.list'; MAX_OLD_DOWNLOAD_DIFF = 5; // in minutes //Global variables var Mode: Byte; idxSearchPage: Integer; DummyUrl, LastUrl, SearchResultIndex, MovieID: String; function minutesDiff(timeA, timeB: String): Integer; var separator: String; hourA, hourB, minA, minB, secA, secB: Integer; tmpDate: TWIDEARRAY; begin // LogMessage('minutesDiff: timeA: ' + timeA + ', timeB: ' + timeB); separator := ':'; ExplodeString(timeA, tmpDate, separator); hourA := StrToInt(tmpDate[0]); minA := StrToInt(tmpDate[1]); secA := StrToInt(tmpDate[2]); // LogMessage('minutesDiff: hourA: ' + IntToStr(hourA) + ', minA: ' + IntToStr(minA) + ', secA: ' + IntToStr(secA)); ExplodeString(timeB, tmpDate, separator); hourB := StrToInt(tmpDate[0]); minB := StrToInt(tmpDate[1]); secB := StrToInt(tmpDate[2]); // LogMessage('minutesDiff: hourB: ' + IntToStr(hourB) + ', minB: ' + IntToStr(minB) + ', secB: ' + IntToStr(secB)); Result := Integer(((hourA - hourB) * 3600 + (minA - minB) * 60 + (secA - secB)) / 60); end; function compareDates(dateA, dateB: String): Boolean; var separator: String; yearA, yearB, monthA, monthB, dayA, dayB: Integer; tmpDate: TWIDEARRAY; begin separator := '-'; ExplodeString(dateA, tmpDate, separator); yearA := StrToInt(tmpDate[0]); monthA := StrToInt(tmpDate[1]); dayA := StrToInt(tmpDate[2]); ExplodeString(dateB, tmpDate, separator); yearB := StrToInt(tmpDate[0]); monthB := StrToInt(tmpDate[1]); dayB := StrToInt(tmpDate[2]); Result := (yearA = yearB) And (monthA = monthB) And (dayA = dayB); end; procedure CleanTmp(); var rowCount, colCount, rowIdx, filesNotDeleted, diff: Integer; indexFilePath, listFiles, curDate, curTime, newListFiles: String; rows, cols: TWIDEARRAY; begin LogMessage('Called CleanTmp'); indexFilePath := GetAppPath() + BASE_DOWNLOAD + FILE_INDEX_DOWNLOAD; if (FileExists(indexFilePath)) then begin newListFiles := ''; filesNotDeleted := 0; curDate := DateToStr(CurrentDateTime()); curTime := TimeToStr(CurrentDateTime()); // LogMessage('CleanTmp: DateTime: ' + curDate + ' ' + curTime); listFiles := FileToString(indexFilePath); // LogMessage('CleanTmp: listFiles: ' + #13#10 + listFiles); if (Length(listFiles) > 0) then begin rowCount := ExplodeString(listFiles, rows, #13#10); // LogMessage('CleanTmp: rowCount: '+ IntToStr(rowCount)); if (rowCount > 0) then begin for rowIdx := 0 To rowCount-1 do begin colCount := ExplodeString(rows[rowIdx], cols, '|'); // LogMessage('CleanTmp: rowIdx: '+ IntToStr(rowIdx)); if (colCount > 2) then begin if (FileExists(cols[2])) then begin diff := minutesDiff(curTime, cols[1]); if ((Not compareDates(curDate, cols[0])) Or (diff > MAX_OLD_DOWNLOAD_DIFF)) then begin LogMessage('CleanTmp: remove: '+ cols[2]); FileExecute('cmd', ' /C del /Q /F ' + cols[2]); end else begin LogMessage('CleanTmp: skip time (' + IntToStr(diff) + '): '+ cols[2]); newListFiles := newListFiles + rows[rowIdx] + #13#10; filesNotDeleted := filesNotDeleted + 1; end; end else begin LogMessage('CleanTmp: skip NOT exists: '+ cols[2]); end; end; end; end; end; if (filesNotDeleted > 0) then begin LogMessage('CleanTmp: filesNotDeleted: '+ IntToStr(filesNotDeleted)); StringToFile(IndexFilePath, newListFiles, false, true); end else begin LogMessage('CleanTmp: remove: '+ indexFilePath); FileExecute('cmd', ' /C del /Q /F ' + indexFilePath); StringToFile(IndexFilePath, '', false, true); end; end else begin StringToFile(IndexFilePath, '', false, true); end; LogMessage('Exited CleanTmp'); end; // HTTPS Functions function EscapeUriToFileName(URL: AnsiString):String; var outputFilePath: String; begin outputFilePath := StringReplace(URL, 'https://', '', True, True, False); outputFilePath := StringReplace(outputFilePath, 'http://', '', True, True, False); outputFilePath := StringReplace(outputFilePath, '/', '_', True, True, False); outputFilePath := StringReplace(outputFilePath, ':', '_', True, True, False); outputFilePath := StringReplace(outputFilePath, '?', '_', True, True, False); outputFilePath := StringReplace(outputFilePath, '+', '_', True, True, False); outputFilePath := StringReplace(outputFilePath, '&', '_', True, True, False); outputFilePath := StringReplace(outputFilePath, '=', '_', True, True, False); while Pos('__', outputFilePath)>0 do begin outputFilePath := StringReplace(outputFilePath, '__', '_', True, True, False); end; Result := outputFilePath; end; function DownloadItem(URL:AnsiString; OutputPath: String; Async, registerDownload: Boolean):Integer; var i: integer; CredentialPath, IndexFilePath: String; begin if (not FileExists(GetAppPath() + BASE_DOWNLOAD + 'not-delete.me')) then begin FileExecute('cmd', ' /C if not exist ' + BASE_DOWNLOAD + ' mkdir ' + BASE_DOWNLOAD); wait (500); StringToFile(GetAppPath() + BASE_DOWNLOAD + 'not-delete.me', 'Questo file serve solo a verificare l''esistenza della folder.' + #13#10 + 'Nel caso mancasse verrĂ  ricreato automaticamente', false, false); end; IndexFilePath := GetAppPath() + BASE_DOWNLOAD + FILE_INDEX_DOWNLOAD; CredentialPath := GetAppPath() + BASE_DOWNLOAD + 'AdultDVDEmpire_cred.txt'; if (Length(Trim(URL))>1) then begin if (Pos(' ', URL) > 0) then begin URL := StringReplace(URL, ' ', '%20', True, True, False); end; if not(FileExists(OutputPath)) then begin URL := StringReplace(URL, 'http://', 'https://', True, True, False); FileExecute('cmd', '/Q /C start /min curl -s -L -k -b "' + CredentialPath + '" -c "' + CredentialPath + '" -A "' + USER_AGENT + '" "' + URL + '" -o "' + OutputPath + '"'); if (not Async) then begin while not(FileExists(OutputPath)) do begin wait (INTERNET_WAIT_TIMING); i:=i+1; If i=INTERNET_TEST_ITERATIONS then begin //In the images download the scritp can not ask to the user for internet conexion because perhaps the file doesnt exist. LogMessage(' FAIL TO DOWNLOAD ITEM: ' + URL); // LogMessage('cmd /Q /C start /min curl -s -L -k -b "' + CredentialPath + '" -c "' + CredentialPath + '" -A "' + USER_AGENT + '" "' + URL + '" -o "' + OutputPath + '"'); Result := 0; exit; end; end; end; Result := 1; if (registerDownload) then begin StringToFile(IndexFilePath, DateToStr(CurrentDateTime()) + '|' + TimeToStr(CurrentDateTime()) + '|' + OutputPath + #13#10, FileExists(indexFilePath), true); end; end else begin Result := 2; // File Exist! end; end else Result := 0; end; function DownloadPage(URL:AnsiString; IsDummyFile:Boolean; Async: Boolean):String; var outputFilePath: String; ret: Integer; begin outputFilePath := GetAppPath() + BASE_DOWNLOAD + EscapeUriToFileName(URL); if (Pos('htm', outputFilePath) <= 0) then outputFilePath := outputFilePath + '.html'; if (IsDummyFile) then begin outputFilePath := outputFilePath + '.dummy'; StringToFile(outputFilePath, URL, False, False); Result := outputFilePath; end else begin ret := DownloadItem(URL, outputFilePath, Async, true); if (ret > 0) then begin Result := outputFilePath; if ((not Async) and (ret = 1)) then begin wait (1500); end; end else begin Result := ''; end; end; end; function DownloadImage(URL:AnsiString):String; var outputFilePath: String; begin LogMessage('DownloadImage: ' + URL); outputFilePath := GetAppPath() + BASE_DOWNLOAD + EscapeUriToFileName(URL); if DownloadItem(URL, outputFilePath, true, true) > 0 then begin Result := outputFilePath; end else begin Result := ''; end; end; procedure BypassAgeConfirmation(); var URL, outputFilePath, CredentialPath: String; begin LogMessage('Called BypassAgeConfirmation'); CredentialPath := GetAppPath() + BASE_DOWNLOAD + 'AdultDVDEmpire_cred.txt'; URL := 'https://www.adultempire.com/Account/AgeConfirmation?ageConfirmationClicked=true'; outputFilePath := GetAppPath() + BASE_DOWNLOAD + 'bypassAgeConfirmation.json'; DownloadItem(URL, outputFilePath, false, false); FileExecute('cmd', ' /C if exist ' + outputFilePath + ' del /Q /F ' + outputFilePath); LogMessage('BypassAgeConfirmation Complete!'); end; // PVD Required Functions procedure GetLoginInfo(out URL : AnsiString; out Params : AnsiString); begin CleanTmp; BypassAgeConfirmation; end; function GetScriptVersion: String; begin Result := SCRIPT_VERSION; end; function GetScriptName: String; begin Result := SCRIPT_NAME; end; function GetScriptDesc: String; begin Result := SCRIPT_DESC; end; function GetBaseURL: AnsiString; begin LogMessage('Called GetBaseURL'); Result := ''; end; function GetScriptLang: Cardinal; begin Result := SCRIPT_LANG; end; function GetScriptType: Byte; begin LogMessage('Called GetScriptType'); Result := SCRIPT_TYPE; end; function GetCurrentMode: Byte; begin LogMessage('Called GetCurrentMode'); Result := Mode; if (Result = smSearch) then begin LogMessage('GetCurrentMode: Search'); end else if (Result = smNormal) then begin LogMessage('GetCurrentMode: Normal'); end else if (Result = smPoster) then begin LogMessage('GetCurrentMode: Poster'); end else if (Result = smDummy) then begin LogMessage('GetCurrentMode: Dummy'); end else begin LogMessage('GetCurrentMode: ' + IntToStr(Mode)); end; end; function GetCodePage: Cardinal; begin LogMessage('Called GetCodePage'); Result := CODE_PAGE; end; function ProcException(Exception: String; Msg: String): AnsiString; begin LogMessage('EXCEPTION!'); LogMessage('message: ' + Msg); Result := ''; end; function GetDownloadURL: AnsiString; var urlNum, idx: Integer; field, searchStr, url, tmp: String; urls: TWIDEARRAY; begin LogMessage('Called GetDownloadURL - Mode: ' + IntToStr(Mode)); if (Mode = smSearch) then begin url := ''; searchStr := StringReplace(BASE_URL, 'http://', '', true, true, true); field := GetFieldValueXML('url'); if (Length(field) > 0) then begin urlNum := ExplodeString(field, urls, ' '); if (urlNum > 1) then begin for idx := 0 To urlNum do begin tmp := Trim(StringReplace(urls[idx], 'https', 'http', true, true, true)); if (Pos(searchStr, tmp) > 0) then begin url := tmp; LastUrl := url; Mode := smNormal; break; end; end; end else if (urlNum > 0) then url := Trim(StringReplace(field, 'https', 'http', true, true, true)); LastUrl := url; Mode := smNormal; begin end; end; if (Length(url) <= 0) then url := StringReplace(SEARCH_STR, '%s', StringReplace(GetFieldValueXML('title'), ' ', '%20', true, false, true), true, false, true); Result := DownloadPage(url, false, false); end else if (Mode = smNormal) then begin if (Length(DummyUrl) > 0) then begin LastUrl := DummyUrl; Result := DownloadPage(DummyUrl, false, false); end else begin Result := ''; end; end else begin LogMessage('Unknown Mode: ' + IntToStr(Mode)); end; LogMessage(' * DownloadURL: ' +#13#10+ url +'||'+' * Mode: '+ IntToStr(Mode)); end; function GetTitleSearchResult(HTML: string): AnsiString; var curPos, endPos: Integer; tmp: String; begin tmp := 'Label="Title"' curPos := Pos(tmp, HTML) + Length(tmp); curPos := PosFrom('>', HTML, curPos) + 1; endPos := PosFrom(' Length(tmp)) and (endPos > 0)) then begin Result := Trim(HTMLToText(Copy(HTML, curPos, endPos - curPos))); end else begin Result := '' end; end; function GetYearSearchResult(HTML: string): AnsiString; var curPos, endPos: Integer; tmp: String; begin tmp := '(' curPos := Pos(tmp, HTML) + Length(tmp); if (curPos > Length(tmp)) then begin endPos := PosFrom(') 0) then begin Result := tmp; end else begin Result := '-0'; end; end else begin Result := '-0'; end; end; function GetUrlSearchResult(HTML: string): AnsiString; var curPos, endPos: Integer; tmp: String; begin tmp := ' Length(tmp)) then begin endPos := PosFrom(' 0) then begin Result := tmp; end else begin Result := '-0'; end; end else begin Result := '-0'; end; //LogMessage(' * GetStudioSearchResult: ' +#13#10+ Result); end; function GetCoverSearchResult(HTML: string): AnsiString; var curPos, endPos: Integer; tmp: String; begin tmp := 'data-src="' curPos := Pos(tmp, HTML) + Length(tmp); endPos := PosFrom('"', HTML, curPos); Result := Trim(Copy(HTML, curPos, endPos - curPos)); end; function GetNextPage(HTML: string): AnsiString; var curPos, endPos: Integer; tmp, searchStr: String; begin LogMessage('Called GetNextPage'); searchStr := '