//SCRIPT INFO================================================================================================== BlockOpen (*Following until 'SCRIPT CONSTANTS...' is documentation. Please see 'USER OPTIONS' in the body of the script. --------------------------------------------- AUTHORS: VVV_Easy Contact Web: http://contactbyweb.com/vvv-easy --------------------------------------------- CHANGE LOG : V 4.3.0.1 (11/15/2025) afrocuban: Script Configurator Enhancements ------------------------------------------------------------------------------- - Built from the scratch new PythonTkinter Script Conigurator: It has all the functionalities as AHK. Plus light/dark theme developed. Unlike AHK can be used as a standalone application with the same effect as when invoked in PVD. - Built from the scratch new PythonTkinter movie type search gui: It has 30 seconds now to decide wjicj type you are searching for. Plus dark theme exclusively implemented. - Added new feature in Script Configurator to enable and manage saved settings from `pvdconf.ini`: **USE SAVED PVDCONFIG** now needs to be enabled to unlock configuration options below. This allows users to apply settings that require a restart of Personal Video Database upon saving. **Use this setting carefully!** Any changes will take effect only after clicking "Save All Script Configurations" (which will restart the application). - **UPDATE DYNAMIC VALUES_ONLY**: Allows users to update only **dynamic values** like Rating, Top 250, Metascore, and Number of votes. Updates the **Awards summary** for movies released within the last two years, capturing recent wins for fresh releases. When disabled, additional configuration options become available for comprehensive updates. Now poster can be downloaded from any page - separate procedure provided for it in Script Configurator. Single Instance in Script Configurator. No more flooding with multiple instance by mistake. Redesigned whole script to now accept UPDATE DYNAMIC VALUES ONLY switch properly. Discovered that if you try to use BASE_URL_PERSON_PRE_TRUE for ~ctDirectors~, ~ctActors~, ~ctWriters~, ~ctProducers~ and ~ctComposers~ in Movie script, you will end up with PVD assigning new pid to the same person for each career job on each update, for each movie, meaning mutiple duplicates of the same person and never aggregated career. So use only BASE_URL_PERSON_PRE, but you can use BASE_URL_PERSON_PRE_TRUE for custom fields since they're not adding people to People view of PVD. Also, you can use BASE_URL_PERSON_PRE_TRUE to add person ~url~ in People Script, but you have to keep both http and https urcs in order to avoid duplicates *) //SCRIPT INFO================================================================================================== BlockClose //SCRIPT CONSTANTS============================================================================================= BlockOpen Const //Script types----------------------------------------------------------------------------------------------------------- stMovies = 0; stPeople = 1; stPoster = 2; stScreenShots = 3; stCover = 4; //Script Obligatory Infos---------------------------------------------------------------------------------------------- SCRIPT_NAME = 'IMDB_Movie_EN_Selenium_v4'; //The most complete information provider SCRIPT_DESC = 'IMDB download Movie and Series info [EN]'; SCRIPT_FILE_NAME = 'IMDB_Movie_[EN][Selenium]-v4'; SCRIPT_VERSION = '4.3.0.1'; SCRIPT_TYPE = stMovies; SCRIPT_LANG = $09; //English //$0a es-Spanish $0c fr-French $09 en-English RATING_NAME = 'IMDB'; //PVD has ~imdbrating~ for this value CODE_PAGE = 65001; //28591=ISO 8859-1 Latin 1; Western European (ISO). Use: 65001=Unicode (UTF-8) | 0=for Autodetect //Script Options------------------------------------------------------------------------------------------------------- //WARNING!!!!!! - DO NOT USE EXACT TERMS OF THE SWITCH NAMES ABOVE THIS LINE (IN THE COMMENTS FOR EXAMPLE, BECAUSE SCRIPT CONFIGURATOR WILL TRY TO READ THEM AND REPORT AN ERROR!!!!!! //Retreive Data Config USE_SAVED_PVDCONFIG = True ; //***PVDCONFIG*** - Turn this ON to unlock and change the options below (from pvdconf.ini) Settings are applied when you click "Save". Personal Video Database will automatically restart. Use carefully! //############################################ //# All options below require USE_SAVED_PVDCONFIG # //# to be enabled so the Script Configurator # //# can apply your settings correctly. # //############################################ UPDATE_DYNAMIC_VALUES_ONLY = False ; //Update only dynamic values such as: Rating, Top 250, Metascore, Number of votes. Also update the Awards summary when the movie is less than 2 years old, to capture fresh wins for recent releases. Deselect to enable the options //################################################ //# All options below require UPDATE_DYNAMIC_VALUES_ONLY# //# to be enabled so the Script Configurator # //# can apply your settings correctly. # //############################################### GET_ORIGINAL_TITLE = False ; //Parse the alternate title in your language and country from the main movie page if it exists there to replace the original title in the Title field. GET_LOCAL_TITLE = False ; //Parse the alternate title info in your language and country from the main movie page if it exists there. GET_FULL_MPAA = True; //Parse Certification provider page to retreive the MPAA info. Or Else, only the info from the main movie page will be parsed. GET_FULL_AKA = True; //Parse 'Also known as' provider page to retreive the full AKA info. Or Else, only the info from the main movie page will be downloaded. GET_FULL_CREDIT = True; //Parse the Cast or Credit (text only) provider page to retrieve the full information. Or Else, only the info from the main movie page will be downloaded. GET_FULL_CREDIT_FROM_REFERENCE = False ; //Instead from FullCredits.htm page, parse full credits for non-Series(!) from the Reference.htm page, parsing with Function ParsePage_IMDBMovieCREDIT. GET_REFERENCE = False ; //Parse Description and Taglines from the Reference page with GET_REFERENCE. PEOPLE_LIMIT = 1000; //Limit on the number of actors (cast) or credits (crew) retrieved on the Main page. PEOPLE_LIMITS = 1000; //Limit on the number of actors (cast) or credits (crew) retrieved from any page. GET_FULL_AWARDS = True; //Parse Awards provider page to retreive the info. Or Else it doesn't do anything because there's no info on the main movie page. EVENTS_LIMIT = 1000; //Limit on number of events (USA Academy Awards, Golden Globes, etc) to retrive awards. GET_SIMPLE_CONNECTIONS = True; //Parse SIMPLE connections: Edited_from, Edited_into, Featured_in, Features, Referenced_in, References, Remade_as, Remake_of, Spin_off, Spin_off_from (Spun_off_from), Spoofed_in, Spoofs, from the movieconnections page. (* //As per https://help.imdb.com/article/contribution/titles/movie-connections/GNUNL9W2FTZDGF4Y# //*) GET_COMPLEX_CONNECTIONS = True; //Parse COMPLEX connections: Followed_by, Follows provider, Version_of and Alternate-language version of, from the movieconnections page. (* //As per https://help.imdb.com/article/contribution/titles/movie-connections/GNUNL9W2FTZDGF4Y# //*) GET_FULL_CONNECTIONS = True; //To call Function ParsePage_IMDBMovieCONNECTIONS. Not used for parsing, since it is enough to choose both SIMPLE and COMPLEX connections. --> to "True". CONNECT_LIMIT = 1001; //Limit on number of connections retrieved. GET_FULL_FEATURES = True; //Parse FULL Technical Specs to retreive the original movie features (Runtime, Sound Mix, Color, Aspect Ratio, etc). GET_MINI_FEATURES = True; //Parse MINI Technical Specs to retreive the original movie features (Runtime, Sound Mix, Color, Aspect Ratio). Needed for ~MiniSoundtracks~ for example. GET_FEATURES = True; //Parse Technical Specs with GET_FEATURES to retreive the original movie features (Runtime, Sound Mix, Color, Aspect Ratio). GET_FULL_PLOT = True; //Parse full synopsis from provider page with GET_FULL_PLOT to retreive the Plot info into custom 'Plot Summary' field. GET_FULL_PLOTKEYWORDS = True; //Parse Plot Keywords provider page to retreive the Keywords (tags). Or Else, only the info from the main movie page will be downloaded. PLOTKEYWORDS_LIMIT = 200; //Limit on number of tags retrieved. Valid only when Plot Keywords provider page downloaded. GET_FULL_PLOTSUMMARY = True; //Parse FULL_PLOTSUMMARY provider page to retreive the Summaries info. Or Else, only the info from the main movie page will be downloaded. GET_FULL_PLOT_SUMMARY = True; //Parse FULL_PLOT_SUMMARY synopsis from the Plot provider page, and retrieving the Synopsis information in the Comment box. GET_FULL_PLOT__SUMMARY = True; //Parse FULL_PLOT__SUMMARY synopsis from the Plot provider page and retrieve the Synopsis information in the Custom 'IMDB Synopsis' field." GET_FULL_PLOT_SYNOPSIS = True; //Parse FULL_PLOT_SYNOPSIS from the Plot provider page and retrieve the Synopsis information in the Custom IMDB Synopsis box. GET_FULL_COMPANYCREDITS = True; //Parse FULL_COMPANYCREDITS from the CompanyCredits provider page and retrieve full Production Companies and Distributors information in the Custom IMDb fields. //Process Data Config MAX_IMAGE_HEIGHT = 12000; //Height limit of the stored posters. PRESERVE_PVD_DESCRIPTION_SETTING = True ; //Avoid double use of ~description~ and ~comment~ using only the user check fields table selection. Or Else, try getting "plot_summary". //Process Behavior Config BYPASS_SILENT = True ; //Ensure critical ShowMessage alerts are bypassing Silent PVdB setting in PVD Preferences. CHECK_WEBSITE = True ; //Add to SearchResult List the true HTTPS links ( ' Check the real link for ' + Title + ' whose page is: ' with the browser). POSTER_IN_SEARCH = True ; //Download and show movie poster thumbnails in the SearchResult List. INTERNET_TEST_ITERATIONS = 16; //Number of attempts before alerting the user that no internet connection is detected. Increase this if the provider has low speed. DOWNLOAD_MAIN_PAGE = True; //Download Main page. DOWNLOAD_RELEASE_INFO_PAGE = True; //Download ReleaseInfo (AKA) page. DOWNLOAD_FULL_CREDITS_PAGE = True; //Download FullCredits page. DOWNLOAD_PARENTAL_GUIDE_PAGE = True; //Download ParentalGuide page. DOWNLOAD_KEYWORDS_PAGE = True; //Download Keywords page. DOWNLOAD_TECHNICAL_PAGE = True; //Download Technical page. DOWNLOAD_AWARDS_PAGE = True; //Download Awards page. DOWNLOAD_CONNECTIONS_PAGE = True; //Download MovieConnections page. DOWNLOAD_PLOTSUMMARY_PAGE = True; //Download PlotSummary page. DOWNLOAD_COMPANYCREDITS_PAGE = True; //Download CompanyCredits page. DOWNLOAD_EPISODES_LIST = True; //Download Episodes List. DOWNLOAD_MORE_PAGES = False; //Download more pages: Reviews, CompanyCredits, Locations, ExternalSites and CriticReviews (for example to create new custom fields). Following pages that will maybe be added in the future: //trivia //criticreviews //ratings //soundtrack //alternateversions //videogallery //taglines DOWNLOAD_POSTERS = True; //Download posters. Uncheck to save download time If you don't need them. //DOWNLOAD_REFERENCE_PAGE = True ; //Download Reference page. LEAVE IT TO "TRUE" WHILE COMMENTED OUT, BECAUSE OF THE SCRIPT CONFIGURATOR WILL READ IT ANYWAY, AND SO THE FIELD COULD BE PARSED BY OTHER FUNCTIONS AND IMPORTED TO THE FIELD BY DEFAULT, SO YOU DON'T NEED TO MANUALLY CHECK IT IN "SET OVERWRITEOPTIONS FORS SELECTED PLUGINS" AND TO NEED TO RESTART PVD THEN!!! ALSO READ COMMENtS WHERE THE REFERENCE PAGE FUNCTION IS AND COMMENTS IN SeleniumPVDbScriptsConfig-v4.ini HOW TO ENABLE REFERENCE PAGE OPTIONS AGAIN //Script data------------------------------------------------------------------------------------------------------------ //Used Web URL BASE_URL_PRE = 'http://www.imdb.com/title/'; //The traditional BASE_URL_PREFIX used to get movie ID if the movie URL is stored, for instance 'http://www.imdb.com/title/ tt0068646/'. BASE_URL_PRE_TRUE = 'https://www.imdb.com/title/'; //True actual link to movie's ID 'httpS://www.imdb.com/title/tt0068646/' BASE_URL_PERSON_PRE = 'http://www.imdb.com/name/'; //The traditional BASE_URL to person ID 'httpS://www.imdb.com/name/nm0094036/' BASE_URL_PERSON_PRE_TRUE = 'https://www.imdb.com/name/'; //True actual link to person's ID 'httpS://www.imdb.com/name/nm0094036/' BASE_URL_SUF = '/'; //Suffix in the link after MovieID or PersonID 'http://www.imdb.com/title/tt0068646/' BASE_URL_IMAGE_PRE = 'http://ia.media-imdb.com/images/M/'; //IMDB posters format: Full image: //'https://ia.media-imdb.com/images/M/MV5BMTI2MjI4NTgyNF5BMl5BanBnXkFtZTcwOTM5NzQ5MQ@@.jpg. BASE_URL_IMAGE_PRE_TRUE = 'https://m.media-amazon.com/images/M/'; //Resized image: //'https://ia.media-imdb.com/images/M/MV5BMTI2MjI4NTgyNF5BMl5BanBnXkFtZTcwOTM5NzQ5MQ@@._V1_UY50_CR0,0,34,50_AL_.jpg //where the two last numbers are width and height (*ORIGINAL BY IVEK: BASE_URL_AKA ='https://www.imdb.com/title/%IMDB_ID/releaseinfo/?ref_=tt_ql_sm#akas'; //Also known as provider page. WEB_SPECIFIC.*) BASE_URL_AKA = 'https://www.imdb.com/title/%IMDB_ID/releaseinfo/'; //ReleaseInfo Also known as provider page. WEB_SPECIFIC. BASE_URL_CAST = 'https://www.imdb.com/title/%IMDB_ID/fullcredits'; //FullCredits Cast provider page. WEB_SPECIFIC. BASE_URL_MPAA = 'http://www.imdb.com/title/%IMDB_ID/parentalguide/'; //ParentalGuide Certification provider page WEB_SPECIFIC. BASE_URL_REFERENCE = 'https://www.imdb.com/title/%IMDB_ID/reference'; //Reference provider page. WEB_SPECIFIC. BASE_URL_PLOTKEYWORDS = 'https://www.imdb.com/title/%IMDB_ID/keywords'; //Keywords PlotKeywords provider page. WEB_SPECIFIC. BASE_URL_TECH = 'https://www.imdb.com/title/%IMDB_ID/technical'; //Technical Specifications provider page. WEB_SPECIFIC. BASE_URL_AWARDS = 'https://www.imdb.com/title/%IMDB_ID/awards/'; //Awards provider page. WEB_SPECIFIC. BASE_URL_CONNECTIONS = 'https://www.imdb.com/title/%IMDB_ID/movieconnections/'; //MovieConnections provider page. WEB_SPECIFIC. BASE_URL_PLOTSUMMARY = 'https://www.imdb.com/title/%IMDB_ID/plotsummary/'; //PlotSummary provider page. WEB_SPECIFIC. BASE_URL_REVIEWS = 'https://www.imdb.com/title/%IMDB_ID/reviews'; //Reviews provider page. WEB_SPECIFIC. BASE_URL_COMPANYCREDITS = 'https://www.imdb.com/title/%IMDB_ID/companycredits'; //CompanyCredits provider page. WEB_SPECIFIC. BASE_URL_LOCATIONS = 'https://www.imdb.com/title/%IMDB_ID/locations'; //Locations provider page. WEB_SPECIFIC. BASE_URL_EXTERNALSITES = 'https://www.imdb.com/title/%IMDB_ID/externalsites'; //ExternalSites provider page. WEB_SPECIFIC. BASE_URL_CRITICREVIEWS = 'https://www.imdb.com/title/%IMDB_ID/criticreviews'; //CriticReviews provider page. WEB_SPECIFIC. //Following search patterns aren't needed in the script but as a reminder for Pythong scripts that now do actuall searches BASE_URL_SEARCH_PROV = 'https://www.imdb.com/search/title?title=%s&title_type=feature&release_date=%y,%y&view=simple&count=10'; //Search string for '%s' title and '%y' year. WEB_SPECIFIC //'&count=10' //BASE_URL_SEARCH_PROV = 'http://www.imdb.com/find?q=%s&s=tt&view=simple'; //Ivek23 proposition //BASE_URL_SEARCH_PROV = 'http://www.imdb.com/find/?s=tt&q=%s&view=simple'; //Ivek23proposition http://www.imdb.com/find?q=Ninja + Resurrection&s=tt BASE_URL_PERSON_SEARCH_PROV = 'https://www.imdb.com/search/name?name=%s&sort=starmeter+desc&ref_=rlm'; //Search string for '%s' name. WEB_SPECIFIC //End of search patterns that aren't needed in the script but as a reminder for Python scripts that now do actuall searches MAX_SEARCHLIST_HEIGHT = 200; //Height limit of the search list posters. //Download HTTPS needed parameters BASE_URL_ROUNDABOUT = 'ROUNDABOUT'; //Used to bypass the GET PVdB function and circumvent the 'https' failure BASE_DOWNLOAD_FILE_NO_BOM = 'Tmp\downpage-UTF8_NO_BOM.htm'; //File to store the Main page in UTF-8 without BOM, making it unnecessary to use the GET PVdB function for downloading. BASE_DOWNLOAD_FILE_IMAGE_NAME = 'Tmp\downimage-BIN'; //File to store the image file in binary, making it unnecessary to use the GET PVdB function for downloading CHEAT_PREFIX_URL = 'http://httpbingo.org/response-headers?key='; //Working HTTP URL used to bypass the GET PVdB function when it returns for SearchList choice. DUMMY_HTML_FILE = 'Scripts\BE_PATIENT_PLEASE-DOWNLOADING_DATA'; //Any existing PVD file (small) that is not used. if modified, it might trigger an external file 'C:\Windows\notepad.exe' //Script movie modes.---------------------------------------------------------------------------------------------------- smSearch = 0; //Entry mode and search list mode (AddSearchResult) smNormal = 1; //This script downloads using an external program (not with GetDownloadURL), so it only makes one pass to ParsePage to retrieve all information, credits, poster, etc. Other field modes are not necessary. //Movie PVdB fields from http://www.videodb.info/help/hlp_scripting.html#fields: //Certification (AddValueField): ~mpaa~ //Credits (AddMoviePerson): ~Directors~, ~Writers~, ~Composers~, ~Photographers~, ~Actors~, ~Producer~.Same that smCast.hat smCast. //Votes (AddValueField): ~rating~, ~imdbrating~, ~orname~, ~orating~ and related custom PVdB fields ~IMDB_Votes~, ~TOP_250~, ~FilmAffinity_Votes~. //Poster (AddValueImageURL): ~poster~, ~screenshots~, ~froncover~, ~cdcover~ //Review (AddValueField): ~comment~, ~tags~ //Awards (AddAwards). smSearchList = 8; //Used in ParsePage to request downloading the HTTPS link returned by the user in the (AddSearchResult) SearchResult window. smFinished = 9; //Indicates the script has finished. smCast = 12; smReview = 13; smCredits = 14; smSoundtracks = 15; smEp0 = 16; smEp1 = 17; smEp2 = 18; smEp3 = 19; smEp4 = 20; smEp5 = 21; smEp6 = 22; smEp7 = 23; smEp8 = 24; smEp9 = 25; smEp10 = 26; smEp11 = 27; smEp12 = 28; smEp13 = 29; smEp14 = 30; smEp15 = 31; smEp16 = 32; smEp17 = 33; smEp18 = 34; smEp19 = 35; smEp20 = 36; smEp = 37; smPoster = 38; //Parse results (returned by Script))--------------------------------------------------------------------------------------- prError = 0; //An error acquired While processing data prFinished = 1; //Script has finished gathering data prList = 3; //A list of search results is available. Use with (AddSearchResult). prListImage = 2; //A list of image search results is available. Use with? prDownload = 4; //Another URL needs to be downloaded //Download methods------------------------------------------------------------------------------------------------------- dmGET = 0; dmPOST = 1; //Credits types---------------------------------------------------------------------------------------------------------- ctActors = 0; ctDirectors = 1; ctWriters = 2; ctComposers = 3; ctProducers = 4; //Image types------------------------------------------------------------------------------------------------------------ itPoster = 0; itScreenShot = 1; itFrontCover = 2; itDiscImage = 3; itPhoto = 4; //Field Overwrite Option positions in pvdconf.ini------------------------------------------------------------------------ //0=Do nothing, 1=Set If Empty, 2=Overwrite. The Length of 'IMDB_[EN][HTTPS].psf=' is 21. opPoster = 87-21; //- Base ConfigOptions[0] := Copy(PvdConfigOptions, opPoster, 1); opTitle = 23-21; //- Base ConfigOptions[1] := Copy(PvdConfigOptions, opTitle, 1); opOrigTitle = 24-21; //- Base ConfigOptions[2] := Copy(PvdConfigOptions, opOrigTitle, 1); opAKA = 25-21; //- Base [If Not (GET_FULL_AKA)] + AKA ConfigOptions[3] := Copy(PvdConfigOptions, opAKA, 1); opYear = 26-21; //- Base ConfigOptions[4] := Copy(PvdConfigOptions, opYear, 1); opGenre = 68-21; //- Base ConfigOptions[5] := Copy(PvdConfigOptions, opGenre, 1); opCategory = 70-21; //- Base ConfigOptions[6] := Copy(PvdConfigOptions, opCategory, 1); opDirector = 76-21; //- Base [If Not (FullCreditsPageDownloaded)] + CREDIT ConfigOptions[7] := Copy(PvdConfigOptions, opDirector, 1); opProducer = 79-21; //- CREDIT ConfigOptions[8] := Copy(PvdConfigOptions, opProducer, 1); opWriter = 77-21; //- Base [If Not (FullCreditsPageDownloaded)] + CREDIT ConfigOptions[9] := Copy(PvdConfigOptions, opWriter, 1); opComposer = 78-21; //- CREDIT ConfigOptions[10] := Copy(PvdConfigOptions, opComposer, 1); opActors = 75-21; //- Base [If Not (FullCreditsPageDownloaded)] + CREDIT ConfigOptions[11] := Copy(PvdConfigOptions, opActors, 1); opCountry = 69-21; //- Base ConfigOptions[12] := Copy(PvdConfigOptions, opCountry, 1); opOrigLang = 44-21; //- Base ConfigOptions[13] := Copy(PvdConfigOptions, opOrigLang, 1); opStudio = 73-21; //- Base [If Not (ReferencePageDownloaded)] + REFERENCE ConfigOptions[14] := Copy(PvdConfigOptions, opStudio, 1); opMPAA = 27-21; //- Base [If Not (GET_FULL_MPAA)] + MPAA ConfigOptions[15] := Copy(PvdConfigOptions, opMPAA, 1); opORating = 32-21; //- For FilmAffinity rating ("Additional Rating") ConfigOptions[16] := Copy(PvdConfigOptions, opORating, 1); opTags = 74-21; //- PLOTKEYWORDS + REFERENCE (If not(GET_FULL_PLOTKEYWORDS)) ("keywords" (in a comma separated list)) ConfigOptions[17] := Copy(PvdConfigOptions, opTags, 1); opRDate = 40-21; //- Base ConfigOptions[18] := Copy(PvdConfigOptions, opRDate, 1); opBudget = 41-21; //- Base ConfigOptions[19] := Copy(PvdConfigOptions, opBudget, 1); opMoney = 42-21; //- Base ConfigOptions[20] := Copy(PvdConfigOptions, opMoney, 1); opTagline = 35-21; //- Base + REFERENCE ConfigOptions[21] := Copy(PvdConfigOptions, opTagline, 1); opDescription = 36-21; //- Base + REFERENCE ConfigOptions[22] := Copy(PvdConfigOptions, opDescription, 1); opLength = 46-21; //- Base + TECHNICAL ConfigOptions[23] := Copy(PvdConfigOptions, opLength, 1); opAwards = 85-21; //- AWARDS ConfigOptions[24] := Copy(PvdConfigOptions, opAwards, 1); opConnections = 84-21; //- CONNECTIONS ConfigOptions[25] := Copy(PvdConfigOptions, opConnections, 1); opFeatures = 55-21; //- Base [If Not (GET_FULL_FEATURES) AND If GET_MINI_FEATURES] + TECHNICAL ConfigOptions[26] := Copy(PvdConfigOptions, opFeatures, 1); opEpisodes = 92-21; //- NOT FOR MOVIE SCRIPT ConfigOptions[27] := Copy(PvdConfigOptions, opEpisodes, 1); //Custom field names to use------------------------------------------------------------------------ THANKS_FIELD = 'Thanks Credits'; FOLLOWEDBY_FIELD = 'Followed By'; SILENT_FIELD = 'Silent'; IMDB_FIELD = 'IMDB'; //SCRIPT CONSTANTS============================================================================================= BlockClose //SCRIPT GLOBAL VARIABLES=======================================================================================BlockOpen Var Mode: Byte; DownloadURL: String; StoredURL: String; MediaType, MediaTypeHTML, MediaTypeBase: String; //'Movie''TV Episode' 'TV Series' PVDConfigOptions: String; MainPageDownloaded, FullCreditsPageDownloaded, ReleaseInfoPageDownloaded, ReviewsPageDownloaded, CompanyCreditsPageDownloaded, LocationsPageDownloaded, TechnicalPageDownloaded, ExternalSitesPageDownloaded, ParentalGuidePageDownloaded, AwardsPageDownloaded, PlotSummaryPageDownloaded, ReferencePageDownloaded, KeywordsPageDownloaded, MovieConnectionsPageDownloaded, CriticReviewsPageDownloaded, EpisodeListDownloaded: Boolean; //Flags for each page PosterDownloaded: Boolean; //Flag for poster could be downloaded from any page function ELI: Integer; ExtraLinks: array [smCast..smPoster] of String; //SCRIPT GLOBAL VARIABLES=======================================================================================BlockClose //USER FUNCTIONS AND PROCEDURES=================================================================================BlockOpen //(* Procedure PurgeTmpFiles(DirectoryPath: String);//BlockOpen Var ScriptPath, Arguments: String; Begin //Define the path to the VBS script using GetAppPath ScriptPath := GetAppPath + 'Scripts\purge_tmp_files.vbs'; //Call the VBS script with the dynamic directory path FileExecute('wscript.exe', '"' + ScriptPath + '" "' + DirectoryPath + '"'); LogMessage('Procedure PurgeTmpFiles - Purged all files in directory:|' + DirectoryPath); Wait (500); //Check if any .htm or .jpg files are left in the Tmp directory If FileExists(DirectoryPath + '\Tmp\*.htm') Or FileExists(DirectoryPath + '\Tmp\*.jpg') Then Begin ShowMessage('PurgeTmpFiles says: Some files in the "Tmp" folder cannot be deleted. Please try to manually delete all .htm and .jpg files that are left in order to continue and then press "OK" here.', SCRIPT_FILE_NAME); End; //If FileExists(DirectoryPath + '\Tmp\*.htm') Or FileExists(DirectoryPath + '\Tmp\*.jpg') Then Begin should end here //*) End;//BlockClose //*) //(* Function TextBetWeenFirst(_HTML: String;_ABegin, _AEnd:String): String;//BlockOpen //Returns the first extract part of a given _HTML between _ABegin and _AEnd and removes all tags from the result subString. //In order to avoid set the Pos variable in TextBetween Var _Pos: Integer; Begin _Pos := 0; Result := TextBetWeen(_HTML, _ABegin, _AEnd, False, _Pos); Exit; End;//BlockClose //*) //(* Function GetPvdConfigOptions(): TWideArray;//BlockOpen Var PvdConfigOptions: String; ConfigOptions: TWideArray; Begin LogMessage('Function GetPvdConfigOptions BEGIN======================|'); //Read the PvdConfigOptions from the INI file PvdConfigOptions := TextBetWeenFirst(FileToString(GetAppPath + 'pvdconf.ini'), SCRIPT_FILE_NAME + '.psf=', #13#10); LogMessage('Function GetPvdConfigOptions - Results PvdConfigOptions:|' + PvdConfigOptions); //Initialize the array SetLength(ConfigOptions, 28); //Adjust the length to match the number of opXXX values //Populate the array with the values of opXXX ConfigOptions[0] := Copy(PvdConfigOptions, opPoster, 1); ConfigOptions[1] := Copy(PvdConfigOptions, opTitle, 1); ConfigOptions[2] := Copy(PvdConfigOptions, opOrigTitle, 1); ConfigOptions[3] := Copy(PvdConfigOptions, opAKA, 1); ConfigOptions[4] := Copy(PvdConfigOptions, opYear, 1); ConfigOptions[5] := Copy(PvdConfigOptions, opGenre, 1); ConfigOptions[6] := Copy(PvdConfigOptions, opCategory, 1); ConfigOptions[7] := Copy(PvdConfigOptions, opDirector, 1); ConfigOptions[8] := Copy(PvdConfigOptions, opProducer, 1); ConfigOptions[9] := Copy(PvdConfigOptions, opWriter, 1); ConfigOptions[10] := Copy(PvdConfigOptions, opComposer, 1); ConfigOptions[11] := Copy(PvdConfigOptions, opActors, 1); ConfigOptions[12] := Copy(PvdConfigOptions, opCountry, 1); ConfigOptions[13] := Copy(PvdConfigOptions, opOrigLang, 1); ConfigOptions[14] := Copy(PvdConfigOptions, opStudio, 1); ConfigOptions[15] := Copy(PvdConfigOptions, opMPAA, 1); ConfigOptions[16] := Copy(PvdConfigOptions, opORating, 1); ConfigOptions[17] := Copy(PvdConfigOptions, opTags, 1); ConfigOptions[18] := Copy(PvdConfigOptions, opRDate, 1); ConfigOptions[19] := Copy(PvdConfigOptions, opBudget, 1); ConfigOptions[20] := Copy(PvdConfigOptions, opMoney, 1); ConfigOptions[21] := Copy(PvdConfigOptions, opTagline, 1); ConfigOptions[22] := Copy(PvdConfigOptions, opDescription, 1); ConfigOptions[23] := Copy(PvdConfigOptions, opLength, 1); ConfigOptions[24] := Copy(PvdConfigOptions, opAwards, 1); ConfigOptions[25] := Copy(PvdConfigOptions, opConnections, 1); ConfigOptions[26] := Copy(PvdConfigOptions, opFeatures, 1); ConfigOptions[27] := Copy(PvdConfigOptions, opEpisodes, 1); (* //Log messages LogMessage('Function GetPvdConfigOptions - opPoster:|' + ConfigOptions[0]); LogMessage('Function GetPvdConfigOptions - opTitle:|' + ConfigOptions[1]); LogMessage('Function GetPvdConfigOptions - opOrigTitle:|' + ConfigOptions[2]); LogMessage('Function GetPvdConfigOptions - opAKA:|' + ConfigOptions[3]); LogMessage('Function GetPvdConfigOptions - opYear:|' + ConfigOptions[4]); LogMessage('Function GetPvdConfigOptions - opGenre:|' + ConfigOptions[5]); LogMessage('Function GetPvdConfigOptions - opCategory:|' + ConfigOptions[6]); LogMessage('Function GetPvdConfigOptions - opDirector:|' + ConfigOptions[7]); LogMessage('Function GetPvdConfigOptions - opProducer:|' + ConfigOptions[8]); LogMessage('Function GetPvdConfigOptions - opWriter:|' + ConfigOptions[9]); LogMessage('Function GetPvdConfigOptions - opComposer:|' + ConfigOptions[10]); LogMessage('Function GetPvdConfigOptions - opActors:|' + ConfigOptions[11]); LogMessage('Function GetPvdConfigOptions - opCountry:|' + ConfigOptions[12]); LogMessage('Function GetPvdConfigOptions - opOrigLang:|' + ConfigOptions[13]); LogMessage('Function GetPvdConfigOptions - opStudio:|' + ConfigOptions[14]); LogMessage('Function GetPvdConfigOptions - opMPAA:|' + ConfigOptions[15]); LogMessage('Function GetPvdConfigOptions - opORating:|' + ConfigOptions[16]); LogMessage('Function GetPvdConfigOptions - opTags:|' + ConfigOptions[17]); LogMessage('Function GetPvdConfigOptions - opRDate:|' + ConfigOptions[18]); LogMessage('Function GetPvdConfigOptions - opBudget:|' + ConfigOptions[19]); LogMessage('Function GetPvdConfigOptions - opMoney:|' + ConfigOptions[20]); LogMessage('Function GetPvdConfigOptions - opTagline:|' + ConfigOptions[21]); LogMessage('Function GetPvdConfigOptions - opDescription:|' + ConfigOptions[22]); LogMessage('Function GetPvdConfigOptions - opLength:|' + ConfigOptions[23]); LogMessage('Function GetPvdConfigOptions - opAwards:|' + ConfigOptions[24]); LogMessage('Function GetPvdConfigOptions - opConnections:|' + ConfigOptions[25]); LogMessage('Function GetPvdConfigOptions - opFeatures:|' + ConfigOptions[26]); LogMessage('Function GetPvdConfigOptions - opEpisodes:|' + ConfigOptions[27]); //*) //Return the array Result := ConfigOptions; LogMessage('Function GetPvdConfigOptions - completed.'); End;//BlockClose //*) //OBLIGATORY CALLBACK FUNCTIONS=================================================================================BlockOpen //(* Function GetScriptVersion: String;//BlockOpen Begin Result := SCRIPT_VERSION; End;//BlockClose //*) //(* Function GetScriptName: String;//BlockOpen Begin Result := SCRIPT_FILE_NAME; End;//BlockClose //*) //(* Function GetScriptDesc: String;//BlockOpen Begin Result := SCRIPT_DESC; End;//BlockClose //*) //(* Function GetBaseURL: AnsiString;//BlockOpen Begin Result := BASE_URL_ROUNDABOUT; //Used to bypass the GET PVdB function and circumvent the 'https' failure. End;//BlockClose //*) //(* Function GetScriptLang:Cardinal;//BlockOpen Begin Result := SCRIPT_LANG; End;//BlockClose //*) //(* Function GetScriptType:Byte;//BlockOpen Begin Result := SCRIPT_TYPE; End;//BlockClose //*) //(* Function GetCurrentMode:Byte;//BlockOpen Begin Result := Mode; End;//BlockClose //*) //(* Function ProcException(Exception: String; Msg: String): AnsiString;//BlockOpen Begin LogMessage('Function ProcException invoked - Exception:|' + Exception + ', Message:|' + Msg); //Interpret log message content If Pos('NOT_FOUND', Msg) > 0 Then Result := 'NOT_FOUND' Else If Pos('FAILED', Msg) > 0 Then Result := 'FAILED' Else If Pos('SUCCESS', Msg) > 0 Then Result := 'SUCCESS' Else Result := 'UNKNOWN'; //Handle unexpected statuses End;//BlockClose //*) //(* Function NextMode(curMode:Integer): Integer;//BlockOpen Var I: Integer; Begin Result := smFinished; If curMode < Low(ExtraLinks) - 1 Then curMode := Low(ExtraLinks) - 1; For I := curMode + 1 to High(ExtraLinks) Do If ExtraLinks[I] <> '' Then Begin Result := I; Break; End; //If ExtraLinks[I] <> '' Then Begin should end here End;//BlockClose //*) //(* Function GetDownloadURL: AnsiString;//BlockOpen Var curPos: Integer; ScriptPath, MovieID: String; RequiredScripts: Array[1..12] of String; MissingList: String; i: Integer; SubsList: String; Begin LogMessage('Function GetDownloadURL BEGIN======================|'); LogMessage('Function GetDownloadURL - Global Var: Mode|' + IntToStr(Mode) + '||'); LogMessage('Function GetDownloadURL - Global Var: DownloadURL|' + DownloadURL + '||'); ScriptPath := GetAppPath + 'Scripts\'; //Call PurgeTmpFiles at the very beginning to ensure it's executed first PurgeTmpFiles(ScriptPath + 'Tmp\'); LogMessage('Function GetDownloadURL - called PurgeTmpFiles to purge files in|' + ScriptPath + 'Tmp\' + '||'); //Validation of needed external files. RequiredScripts[1] := 'PyPVDbScriptsConfig-v4.py'; RequiredScripts[2] := 'Selenium_Chrome_Base_page_v4.py'; RequiredScripts[3] := 'Selenium_Chrome_DownloadImage-v4.py'; RequiredScripts[4] := 'Selenium_Chrome_IMDB_Episode_List_page_v4.py'; RequiredScripts[5] := 'Selenium_Chrome_Movie_Additional_pages_v4.py'; RequiredScripts[6] := 'Selenium_Chrome_Movie_AM_pages_v4.py'; RequiredScripts[7] := 'Selenium_Chrome_Movie_FA_pages_v4.py'; RequiredScripts[8] := 'Selenium_Chrome_Movie_RT_pages_v4.py'; RequiredScripts[9] := 'Selenium_Chrome_People_Additional_pages_v4.py'; RequiredScripts[10] := 'Selenium_Chrome_Search-v4.py'; RequiredScripts[11] := 'Selenium_Chrome_RT_Episode_List_page_v4.py'; RequiredScripts[12] := 'Selenium_Chrome_People_Base_page_v4.py'; MissingList := ''; For i := Low(RequiredScripts) To High(RequiredScripts) Do Begin //Only check if the entry is non-empty AND the file is missing If (RequiredScripts[i] <> '') And Not FileExists(ScriptPath + RequiredScripts[i]) Then Begin MissingList := MissingList + ' ' + RequiredScripts[i] + #13#10; LogMessage('Function GetDownloadURL - Missing required script:|' + RequiredScripts[i]); End; //If (RequiredScripts[i] <> '') And Not FileExists(ScriptPath + RequiredScripts[i]) Then Begin should end here End; //For i := Low(RequiredScripts) To High(RequiredScripts) Do Begin should end here If MissingList <> '' Then Begin ShowMessage('The following required Selenium scripts are missing:|' + #13#10 + MissingList + 'Please ensure these files are available in the Scripts directory.', SCRIPT_FILE_NAME); Mode := smFinished; Result := ''; //If error, return empty string Exit; End; //If MissingList <> '' Then Begin should end here If (Mode = smSearch) Then Begin //Get stored subs if exist. SubsList := GetFieldValueXML('subs'); AddCustomFieldValueByName('Subs', SubsList); LogMessage('Function GetDownloadURL - Stored subs: ' + SubsList + '||'); //Get StoredURL if exists StoredURL := GetFieldValueXML('url'); LogMessage('Function GetDownloadURL - Stored URL is:|' + StoredURL + '||'); //Standardize the URL StoredURL := LowerCase(StoredURL); StoredURL := StringReplace(StoredURL, 'https', 'http', True, True, False); StoredURL := StringReplace(StoredURL, 'http://', 'http:', True, True, False); LogMessage('Function GetDownloadURL - Stored URL after replacing http:// is:|' + StoredURL + '||'); StoredURL := StringReplace(StoredURL, '//', '', True, True, False); LogMessage('Function GetDownloadURL - Stored URL after replacing // with / is:|' + StoredURL + '||'); StoredURL := StringReplace(StoredURL, 'http:', 'http://', True, True, False); StoredURL := StringReplace(StoredURL, 'http://imdb.com/', 'http://www.imdb.com/', True, True, False); StoredURL := StringReplace(StoredURL, 'http://httpbin.org/response-headers?key=', '', True, False, False); StoredURL := StringReplace(StoredURL, ' ', BASE_URL_SUF, True, True, False) + BASE_URL_SUF; //Asure that the URLs always ends with the BASE_URL_SUF (even at the last position). LogMessage('Function GetDownloadURL - Final Stored URL after StringReplace is:|' + StoredURL + '||'); //Get IMDB ID if exists curPos := Pos(BASE_URL_PRE, StoredURL); If 0 < curPos Then Begin //Get IMDB_ID for search LogMessage('Function GetDownloadURL - IMDB URL.'); MovieID := TextBetWeen(StoredURL, BASE_URL_PRE, BASE_URL_SUF, False, curPos); //WEB_SPECIFIC DownloadURL := BASE_URL_PRE_TRUE + MovieID + BASE_URL_SUF; //WEB_SPECIFIC LogMessage('Function GetDownloadURL - Mode=smSearch: Parse stored information DownloadURL:|' + DownloadURL + '||'); Mode := smNormal; //->Go to function ParsePage for parse the film information Result := GetAppPath + DUMMY_HTML_FILE; //Any small existing file for cheating PVdB's automatic download. LogMessage('Function GetDownloadURL END====================== with Mode=' + IntToStr(Mode) + ' (smNormal) with Result=' + Result + '||'); Exit; End Else Begin //The movie URL doesn't exist, search mode needed. Downloading search page. //ShowMessage('No IMDB URL.', SCRIPT_FILE_NAME); LogMessage('Function GetDownloadURL - No IMDB URL.'); Mode := smSearch; //->Go to function ParsePage to search the URL (in this function you can't use user functions) DownloadURL := ''; //Has not movie URL. Result := GetAppPath + DUMMY_HTML_FILE; //Any small existing file for cheating PVdB's automatic download. LogMessage('Function GetDownloadURL END====================== with Mode=' + IntToStr(Mode) + ' (smSearch) with Result=' + Result + '||'); Exit; //Go to the End; //If 0 < curPos Then Begin should end here End; //If (Mode = smSearch) Then Begin should end here //No other modes working needed in this function. //smNormal = 1; //These scripts download with an external program (not with GetDownloadURL), so they only make one pass to ParsePage to retrieve all info, credits, poster, etc. Other field modes are not necessary. //smSearchList = 8; //Used in ParsePage to request downloading the HTTPS link returned by the user in the (AddSearchResult) window. Result := GetAppPath + DUMMY_HTML_FILE; //Any existing small file for bypassing PVdB automatic download. LogMessage('Function GetDownloadURL END====================== with Mode=' + IntToStr(Mode) + ' Result=' + Result + '||'); Exit; End;//BlockClose //*) //(* Function GetRatingName: String;//BlockOpen Begin Result := RATING_NAME; End;//BlockClose //*) //(* Function GetCodePage:Cardinal;//BlockOpen Begin Result := CODE_PAGE; End;//BlockClose //*) //OBLIGATORY CALLBACK FUNCTIONS=================================================================================BlockClose //USER FUNCTIONS AND PROCEDURES=================================================================================BlockOpen //(* Function BoolToStr(B: Boolean): String;//BlockOpen Begin If B Then Result := 'True' Else Result := 'False'; End;//BlockClose //*) //(* Function WaitForPageFile(const FileName, PageLabel: String; InitialWait: Integer; StabilizeMs: Integer): String;//BlockOpen //The function waits for the exsitence of the files to be downloaded, then when found, it converts their encoding and reads them Var i, currentWait: Integer; tryResult: String; Begin Result := ''; i := 0; //Provide defaults manually If InitialWait = 0 Then InitialWait := 2000; If StabilizeMs = 0 Then StabilizeMs := 1000; currentWait := InitialWait; While Not FileExists(FileName) Do Begin LogMessage('Function WaitForPageFile - Waiting ' + IntToStr(currentWait div 1000) + 's for the presence of:|' + FileName + '||'); Wait (currentWait); //Escalate wait times case i of 0: currentWait := 5000; 1: currentWait := 5000; 2: currentWait := 5000; 3: currentWait := 5000; 4: currentWait := 15000; 5: currentWait := 5000; End; //case i of should end here Inc(i); If i = INTERNET_TEST_ITERATIONS Then Begin case MessageBox('IMDb Movie Function WaitForPageFile - Too many faulty attempts to internet connection for ' + PageLabel + '. Cancel, Retry, or Continue (Ignore)? NOTE: IF YOU PRESS IGNORE YOU WILL NOT GET DATA FROM THAT PAGE, SO CONSIDER TO RETRY OR TO CANCEL AND START DOWNLOAD AGAIN! IMDb really makes it harder and harder to get the data.', SCRIPT_FILE_NAME, 2) of 3: //Cancel Begin LogMessage('Function WaitForPageFile for ' + PageLabel + ' ended with NO INTERNET connection===============|'); Result := '#CANCELLED#'; Exit; End; //Begin 3: //Cancel should end here 4: //Retry Begin i := 0; currentWait := InitialWait; End; //Begin 4: //Retry should end here 5: //Ignore Begin LogMessage('Function WaitForPageFile - Creating dummy ' + PageLabel + ' HTML file due to Ignore selection|'); with TStringList.Create Do Begin try Add('
Dummy ' + PageLabel + ' due to user Ignore.'); SaveToFile(FileName); finally Free; End; //try-finally should end here End; //with TStringList.Create Do Begin should end here Break; End; //Begin 5: //Ignore should end here End; //case MessageBox... of should end here End; //If i = INTERNET_TEST_ITERATIONS Then Begin should end here End; //While Not FileExists(FileName) Do Begin should end here //Stabilization wait LogMessage('Function WaitForPageFile - ' + PageLabel + ' file detected, waiting extra ' + IntToStr(StabilizeMs) + 'ms to stabilize...'); Wait (StabilizeMs); //Manual error handling instead of try/except If Not FileExists(FileName) Then Begin LogMessage(ProcException('Function WaitForPageFile - FileError', 'NOT_FOUND:|' + FileName)); Exit; End; //If Not FileExists(FileName) Then Begin should end here tryResult := FileToString(FileName); //If the environment throws, replace with safe read If tryResult = '' Then Begin tryResult := '' LogMessage(ProcException('Function WaitForPageFile - FileError', 'FAILED to read ' + FileName)) End Else Begin Result := ConvertEncoding(tryResult, 65001); LogMessage(ProcException('Function WaitForPageFile - FileRead', 'SUCCESS:|' + FileName)); End; //If tryResult = '' Then Begin should end here End;//BlockClose //*) { //Maybe I will need this function in the future, and if so it has to be reworked since it doesn't execute as such at the moment //(* Function ShouldUpdateField(FieldName: String): Boolean;//BlockOpen Var MovieYear, CurrentYear: Integer; Begin If Not UPDATE_DYNAMIC_VALUES_ONLY Then Exit; //Full update: always update all fields MovieYear := StrToIntDef(GetFieldValueXML('year'), 0); CurrentYear := YearOf(CurrentDateTime); Case FieldName of //Always update 'imdbrating', 'IMDB_Rating', 'IMDBRating', 'IMDB_Votes', 'IMDB Votes', 'IMDB Votes:', 'TOP_250', 'Top 250:', 'TOP_250_Last', 'TOP_250TV', 'TOP_250TV_Last', 'Metascore': Exit(True); //Only update if movie is recent 'IMDbAwards1', 'Awards': If (CurrentYear - MovieYear) <= 2 Then Exit(True); End; //Case FieldName of should end here Exit(False); //Skip anything Else Exit(False); //Skip anything Else End;//BlockClose //*)} //{ //Needed for HTML := DownloadPagexxx(FileTitlexxx); in Function ParsePage //(* Function ReadPageFile(const PageLabel, FileSuffix: String): String;//BlockOpen Var ScriptPath, FilePath, FileName, WebText: String; Begin LogMessage('Function ReadPageFile' + PageLabel + ' BEGIN======================|'); LogMessage('Function ReadPageFile' + PageLabel + ' - Global Var: DownloadURL|'); ScriptPath := GetAppPath + 'Scripts\'; FilePath := ScriptPath + 'Tmp\'; FileName := 'downpage-UTF8_NO_BOM' + FileSuffix + '.htm'; //Check before reading If Not FileExists(FilePath + FileName) Then Begin LogMessage('Function ReadPageFile' + PageLabel + ' - File not found, skipping.'); Result := ''; Exit; End; //If Not FileExists(FilePath + FileName) Then Begin should end here LogMessage('Function ReadPageFile' + PageLabel + ' - Reading file:|' + FilePath + FileName); WebText := FileToString(FilePath + FileName); If WebText = '' Then Begin LogMessage('Function ReadPageFile' + PageLabel + ' - File read returned empty content.'); Result := ''; Exit; End; //If WebText = '' Then Begin should end here Result := ConvertEncoding(WebText, 65001); //Convert to UTF-8 LogMessage('Function ReadPageFile' + PageLabel + ' END======================|'); End;//BlockClose//} //*) //Wrappers needed for HTML := DownloadPagexxx(FileTitlexxx); in Function ParsePage //(* Function DownloadPage(URL:AnsiString): String;//BlockOpen //Returns the URL page text. If errors, it returns empty string Var i, currentWait: Integer; FileTitleFullCredits, FileTitleReleaseInfo, FileTitleReviews, FileTitleCompanyCredits, FileTitleMain, FileTitleLocations, FileTitleTechnical, FileTitleExternalSites, FileTitleParentalGuide, FileTitleAwards, FileTitlePlotSummary, FileTitleReference, FileTitleKeywords, FileTitleMovieConnections, FileTitleCriticReviews, ScriptPath, FilePath, WebText: String; EXCLUDED_FILES: String; ConfigOptions: TWideArray; markerFilePath: String; Begin LogMessage('Function DownloadPage BEGIN======================|'); LogMessage('Function DownloadPage - Global Var: DownloadURL|' + DownloadURL + '||'); LogMessage('Function DownloadPage - Local Var: URL|' + URL + '||'); //Set the script and file paths ScriptPath := GetAppPath + 'Scripts\'; LogMessage('Function DownloadPage - Local Var: ScriptPath|' + ScriptPath + '||'); FilePath := ScriptPath + 'Tmp\'; FileTitleMain := 'downpage-UTF8_NO_BOM.htm'; FileTitleReleaseInfo := 'downpage-UTF8_NO_BOM-ReleaseInfo.htm'; FileTitleFullCredits := 'downpage-UTF8_NO_BOM-FullCredits.htm'; FileTitleParentalGuide := 'downpage-UTF8_NO_BOM-ParentalGuide.htm'; FileTitleReference := 'downpage-UTF8_NO_BOM-Reference.htm'; FileTitleKeywords := 'downpage-UTF8_NO_BOM-Keywords.htm'; FileTitleTechnical := 'downpage-UTF8_NO_BOM-Technical.htm'; FileTitleAwards := 'downpage-UTF8_NO_BOM-Awards.htm'; FileTitleMovieConnections := 'downpage-UTF8_NO_BOM-MovieConnections.htm'; FileTitlePlotSummary := 'downpage-UTF8_NO_BOM-PlotSummary.htm'; FileTitleReviews := 'downpage-UTF8_NO_BOM-Reviews.htm'; FileTitleCompanyCredits := 'downpage-UTF8_NO_BOM-CompanyCredits.htm'; FileTitleLocations := 'downpage-UTF8_NO_BOM-Locations.htm'; FileTitleExternalSites := 'downpage-UTF8_NO_BOM-ExternalSites.htm'; FileTitleCriticReviews := 'downpage-UTF8_NO_BOM-CriticReviews.htm'; //Removed redundant file deletion checks, relying on PurgeTmpFiles procedure at the start. //Download the Main page //Calling GetPvdConfigOptions Function first ConfigOptions := GetPvdConfigOptions; //(* //Log the values of each opXXX LogMessage('Function DownloadPage - opPoster:|' + ConfigOptions[0]); LogMessage('Function DownloadPage - opTitle:|' + ConfigOptions[1]); LogMessage('Function DownloadPage - opOrigTitle:|' + ConfigOptions[2]); LogMessage('Function DownloadPage - opAKA:|' + ConfigOptions[3]); LogMessage('Function DownloadPage - opYear:|' + ConfigOptions[4]); LogMessage('Function DownloadPage - opGenre:|' + ConfigOptions[5]); LogMessage('Function DownloadPage - opCategory:|' + ConfigOptions[6]); LogMessage('Function DownloadPage - opDirector:|' + ConfigOptions[7]); LogMessage('Function DownloadPage - opProducer:|' + ConfigOptions[8]); LogMessage('Function DownloadPage - opWriter:|' + ConfigOptions[9]); LogMessage('Function DownloadPage - opComposer:|' + ConfigOptions[10]); LogMessage('Function DownloadPage - opActors:|' + ConfigOptions[11]); LogMessage('Function DownloadPage - opCountry:|' + ConfigOptions[12]); LogMessage('Function DownloadPage - opOrigLang:|' + ConfigOptions[13]); LogMessage('Function DownloadPage - opStudio:|' + ConfigOptions[14]); LogMessage('Function DownloadPage - opMPAA:|' + ConfigOptions[15]); LogMessage('Function DownloadPage - opORating:|' + ConfigOptions[16]); LogMessage('Function DownloadPage - opTags:|' + ConfigOptions[17]); LogMessage('Function DownloadPage - opRDate:|' + ConfigOptions[18]); LogMessage('Function DownloadPage - opBudget:|' + ConfigOptions[19]); LogMessage('Function DownloadPage - opMoney:|' + ConfigOptions[20]); LogMessage('Function DownloadPage - opTagline:|' + ConfigOptions[21]); LogMessage('Function DownloadPage - opDescription:|' + ConfigOptions[22]); LogMessage('Function DownloadPage - opLength:|' + ConfigOptions[23]); LogMessage('Function DownloadPage - opAwards:|' + ConfigOptions[24]); LogMessage('Function DownloadPage - opConnections:|' + ConfigOptions[25]); LogMessage('Function DownloadPage - opFeatures:|' + ConfigOptions[26]); LogMessage('Function DownloadPage - opEpisodes:|' + ConfigOptions[27]); //*) //Check if the main page should be downloaded based on unique ConfigOptions If (USE_SAVED_PVDCONFIG) And ( //(ConfigOptions[0] = '0') And //Poster (ConfigOptions[1] = '0') And //Title (ConfigOptions[2] = '0') And //OrigTitle (ConfigOptions[4] = '0') And //Year (ConfigOptions[5] = '0') And //Genre (ConfigOptions[6] = '0') And //Category (ConfigOptions[12] = '0') And //Country (ConfigOptions[13] = '0') And //OrigLang (ConfigOptions[18] = '0') And //RDate (ConfigOptions[19] = '0') And //Budget (ConfigOptions[20] = '0')) (* //Money //*) Then Begin LogMessage('Function DownloadPage - Skipping download for Main page as per configuration.'); MainPageDownloaded := False; End Else Begin LogMessage('Function DownloadPage - Download attempt with Selenium in file:|' + ScriptPath + BASE_DOWNLOAD_FILE_NO_BOM + ' the information of the Main page:|' + URL + '||'); LogMessage('Function DownloadPage - Executing Python script to download URL content.'); FileExecute('pythonw.exe', '"' + ScriptPath + 'Selenium_Chrome_Base_page_v4.py" "' + URL + '" "' + ScriptPath + BASE_DOWNLOAD_FILE_NO_BOM + '"'); LogMessage('Function DownloadPage - Download started with Selenium in file:|' + ScriptPath + BASE_DOWNLOAD_FILE_NO_BOM + ' the information of the Main Page:|' + URL + '||'); //(* //Wait for the Selenium download to finish for the Main Page. WebText := WaitForPageFile(ScriptPath + BASE_DOWNLOAD_FILE_NO_BOM, 'MainPage', 8000, 4000); Result := WebText; MainPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of MainPageDownloaded:|' + BoolToStr(MainPageDownloaded)); //*) End; //If (USE_SAVED_PVDCONFIG) And (...) Then Begin should end here //Prepare the EXCLUDED_FILES list for additional pages EXCLUDED_FILES := ''; If Not (UPDATE_DYNAMIC_VALUES_ONLY) Then Begin //This applies for each function up to ParsePage function //(* //Check if the ReleaseInfo page should be downloaded based on unique ConfigOptions If (USE_SAVED_PVDCONFIG) And (ConfigOptions[3] = '0') (*//Also Kown As //*) Then Begin LogMessage('Function DownloadPage - Skipping download for ReleaseInfo page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-ReleaseInfo.htm|'; ReleaseInfoPageDownloaded := False; End; //If (USE_SAVED_PVDCONFIG) And (ConfigOptions[3] = '0') (*//Also Kown As //*) Then Begin should end here //Check if the FullCredits page should be downloaded based on unique ConfigOptions LogMessage('Function DownloadPage - if it is Series there will be MediaType:|' + MediaType + '|| or...'); LogMessage('Function DownloadPage - if it is Series there will be category:|' + GetFieldValueXML('category') + '||'); If ((USE_SAVED_PVDCONFIG) And ((ConfigOptions[8] = '0') And (ConfigOptions[10] = '0'))) Or (GET_FULL_CREDIT_FROM_REFERENCE And ((Pos('Series', MediaType) = 0) And (Pos('Series', GetFieldValueXML('category')) = 0))) Then Begin LogMessage('Function DownloadPage - Skipping download for FullCredits page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-FullCredits.htm|'; FullCreditsPageDownloaded := False; End; //If ((USE_SAVED_PVDCONFIG) And ((ConfigOptions[8] = '0') And (ConfigOptions[10] = '0'))) Or (GET_FULL_CREDIT_FROM_REFERENCE And ((Pos('Series', MediaType) = 0) And (Pos('Series', GetFieldValueXML('category')) = 0))) Then Begin should end here //Check if the ParentalGuide page should be downloaded based on unique ConfigOptions If (USE_SAVED_PVDCONFIG) And (ConfigOptions[15] = '0') (* //MPAA //*) Then Begin LogMessage('Function DownloadPage - Skipping download for ParentalGuide page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-ParentalGuide.htm|'; ParentalGuidePageDownloaded := False; End; //If (USE_SAVED_PVDCONFIG) And (ConfigOptions[15] = '0') (* //MPAA //*) Then Begin should end here //*) (* //Check if the Reference page should be downloaded based on unique ConfigOptions If (USE_SAVED_PVDCONFIG) And (ConfigOptions[14] = '0') (* //Studio (because no other page to be downloaded contains full Studio info, except CompanyCredits which is still not included) //*) (*Then Begin LogMessage('Function DownloadPage - Skipping download for Reference page as per configuration.'); //*) //THIS HAS TO STAY BECAUSE OF THE SELENIUM SCRIPT!!! EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-Reference.htm|'; ReferencePageDownloaded := False; LogMessage('Function DownloadPage - Value of ReferencePageDownloaded after skipping:|' + BoolToStr(ReferencePageDownloaded)) (* End; //If (USE_SAVED_PVDCONFIG) And (ConfigOptions[14] = '0') (* //Studio (because no other page to be downloaded contains full Studio info, except CompanyCredits which is still not included) //*) (*Then Begin should end here //*) //Check if the Keywords page should be downloaded based on unique ConfigOptions If (USE_SAVED_PVDCONFIG) And (ConfigOptions[17] = '0') (* //Tags //*) Then Begin LogMessage('Function DownloadPage - Skipping download for Keywords page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-Keywords.htm|'; KeywordsPageDownloaded := False; End; //If (USE_SAVED_PVDCONFIG) And (ConfigOptions[17] = '0') (* //Tags //*) Then Begin should end here //Check if the Technical page should be downloaded based on unique ConfigOptions If (USE_SAVED_PVDCONFIG) And (ConfigOptions[26] = '0') (* //Features //*) Then Begin LogMessage('Function DownloadPage - Skipping download for Technical page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-Technical.htm|'; TechnicalPageDownloaded := False; End; //If (USE_SAVED_PVDCONFIG) And (ConfigOptions[26] = '0') (* //Features //*) Then Begin should end here //Check if the Awards page should be downloaded based on unique ConfigOptions If (USE_SAVED_PVDCONFIG) And (ConfigOptions[24] = '0') (* //Awards //*) Then Begin LogMessage('Function DownloadPage - Skipping download for Awards page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-Awards.htm|'; AwardsPageDownloaded := False; End; //If (USE_SAVED_PVDCONFIG) And (ConfigOptions[24] = '0') (* //Awards //*) Then Begin should end here //Check if the MovieConnections page should be downloaded based on unique ConfigOptions If (USE_SAVED_PVDCONFIG) And (ConfigOptions[25] = '0') (* //Connections //*) Then Begin LogMessage('Function DownloadPage - Skipping download for MovieConnections page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-MovieConnections.htm|'; MovieConnectionsPageDownloaded := False; End; //If (USE_SAVED_PVDCONFIG) And (ConfigOptions[25] = '0') (* //Connections //*) Then Begin should end here //Check if the Plot Summary page should be downloaded based on relevant options If Not (GET_FULL_PLOTSUMMARY Or GET_FULL_PLOT_SUMMARY Or GET_FULL_PLOT__SUMMARY Or GET_FULL_PLOT_SYNOPSIS) Then Begin LogMessage('Function DownloadPage - Skipping download for Plot Summary page as no relevant options are set.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-PlotSummary.htm|'; PlotSummaryPageDownloaded := False; End; //If Not (GET_FULL_PLOTSUMMARY Or GET_FULL_PLOT_SUMMARY Or GET_FULL_PLOT__SUMMARY Or GET_FULL_PLOT_SYNOPSIS) Then Begin should end here //Check if the CompanyCredits page should be downloaded based on DOWNLOAD_MORE_PAGES If (DOWNLOAD_COMPANYCREDITS_PAGE = False) Then Begin //Check redudance for future eventual separation LogMessage('Function DownloadPage - Skipping download for CompanyCredits page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-CompanyCredits.htm|'; CompanyCreditsPageDownloaded := False; End; //If (DOWNLOAD_COMPANYCREDITS_PAGE = False) Then Begin should end here //Check if the Reviews page should be downloaded based on DOWNLOAD_MORE_PAGES If (DOWNLOAD_MORE_PAGES = False) Then Begin //Check redudance for future eventual separation LogMessage('Function DownloadPage - Skipping download for Reviews page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-Reviews.htm|'; ReviewsPageDownloaded := False; End; //If (DOWNLOAD_MORE_PAGES = False) Then Begin should end here //Check if the Locations page should be downloaded based on DOWNLOAD_MORE_PAGES If (DOWNLOAD_MORE_PAGES = False) Then Begin //Check redudance for future eventual separation LogMessage('Function DownloadPage - Skipping download for Locations page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-Locations.htm|'; LocationsPageDownloaded := False; End; //If (DOWNLOAD_MORE_PAGES = False) Then Begin should end here //Check if the ExternalSites page should be downloaded based on DOWNLOAD_MORE_PAGES If (DOWNLOAD_MORE_PAGES = False) Then Begin //Check redudance for future eventual separation LogMessage('Function DownloadPage - Skipping download for ExternalSites page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-ExternalSites.htm|'; ExternalSitesPageDownloaded := False; End; //If (DOWNLOAD_MORE_PAGES = False) Then Begin should end here //Check if the CriticReviewsPageDownloaded page should be downloaded based on DOWNLOAD_MORE_PAGES If (DOWNLOAD_MORE_PAGES = False) Then Begin //Check redudance for future eventual separation LogMessage('Function DownloadPage - Skipping download for CriticReviewsPageDownloaded page as per configuration.'); EXCLUDED_FILES := EXCLUDED_FILES + 'downpage-UTF8_NO_BOM-CriticReviews.htm|'; CriticReviewsPageDownloaded := False; End; //If (DOWNLOAD_MORE_PAGES = False) Then Begin should end here //Remove trailing pipe character if present If (Length(EXCLUDED_FILES) > 0) And (EXCLUDED_FILES[Length(EXCLUDED_FILES)] = '|') Then Delete(EXCLUDED_FILES, Length(EXCLUDED_FILES), 1); //Log the final EXCLUDED_FILES for verification LogMessage('Function DownloadPage - EXCLUDED_FILES:|' + EXCLUDED_FILES + '||'); //If (DOWNLOAD_RELEASE_INFO_PAGE And DOWNLOAD_FULL_CREDITS_PAGE And DOWNLOAD_PARENTAL_GUIDE_PAGE And DOWNLOAD_KEYWORDS_PAGE And DOWNLOAD_TECHNICAL_PAGE And DOWNLOAD_AWARDS_PAGE And DOWNLOAD_CONNECTIONS_PAGE And DOWNLOAD_PLOTSUMMARY_PAGE And DOWNLOAD_COMPANYCREDITS_PAGE) Then Begin //Download the additional URL pages using the Selenium script LogMessage('Function DownloadPage - Executing Python script to download additional pages URL content.'); FileExecute('pythonw.exe', '"' + ScriptPath + 'Selenium_Chrome_Movie_Additional_pages_v4.py" "' + URL + '" "' + ScriptPath + BASE_DOWNLOAD_FILE_NO_BOM + '" "' + EXCLUDED_FILES + '"'); //Initialize currentWait for the ReleaseInfo file If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[3] = '0')) Then Begin WebText := WaitForPageFile(FilePath + FileTitleReleaseInfo, 'ReleaseInfo', 4000, 2000); ReleaseInfoPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of ReleaseInfoPageDownloaded:|' + BoolToStr(ReleaseInfoPageDownloaded)); End; //If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[3] = '0')) Then Begin should end here //Initialize currentWait for the FullCredits file If Not (((USE_SAVED_PVDCONFIG) And ((ConfigOptions[8] = '0') And (ConfigOptions[10] = '0'))) Or (GET_FULL_CREDIT_FROM_REFERENCE And ((Pos('Series', MediaType) = 0) And (Pos('Series', GetFieldValueXML('category')) = 0)))) Then Begin WebText := WaitForPageFile(FilePath + FileTitleFullCredits, 'FullCredits', 4000, 2000); FullCreditsPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of FullCreditsPageDownloaded:|' + BoolToStr(FullCreditsPageDownloaded)); End; //If Not (((USE_SAVED_PVDCONFIG) And ((ConfigOptions[8] = '0') And (ConfigOptions[10] = '0'))) Or (GET_FULL_CREDIT_FROM_REFERENCE And ((Pos('Series', MediaType) = 0) And (Pos('Series', GetFieldValueXML('category')) = 0)))) Then Begin should end here //Initialize currentWait for the ParentalGuide file If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[15] = '0')) Then Begin WebText := WaitForPageFile(FilePath + FileTitleParentalGuide, 'ParentalGuide', 4000, 2000); ParentalGuidePageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of ParentalGuidePageDownloaded:|' + BoolToStr(ParentalGuidePageDownloaded)); End; //If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[15] = '0')) Then Begin should end here //Initialize currentWait for the Keywords file If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[17] = '0')) Then Begin WebText := WaitForPageFile(FilePath + FileTitleKeywords, 'Keywords', 4000, 2000); KeywordsPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of KeywordsPageDownloaded:|' + BoolToStr(KeywordsPageDownloaded)); End; //If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[17] = '0')) Then Begin should end here //Initialize currentWait for the Technical file If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[26] = '0')) Then Begin WebText := WaitForPageFile(FilePath + FileTitleTechnical, 'Technical', 4000, 2000); TechnicalPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of TechnicalPageDownloaded:|' + BoolToStr(TechnicalPageDownloaded)); End; //If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[26] = '0')) Then Begin should end here //Initialize currentWait for the Awards file If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[24] = '0')) Then Begin WebText := WaitForPageFile(FilePath + FileTitleAwards, 'Awards', 4000, 2000); AwardsPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of AwardsPageDownloaded:|' + BoolToStr(AwardsPageDownloaded)); End; //If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[24] = '0')) Then Begin should end here //Initialize currentWait for the MovieConnections file If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[25] = '0')) Then Begin WebText := WaitForPageFile(FilePath + FileTitleMovieConnections, 'MovieConnections', 8000, 2000); MovieConnectionsPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of MovieConnectionsPageDownloaded:|' + BoolToStr(MovieConnectionsPageDownloaded)); End; //If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[25] = '0')) Then Begin should end here //Initialize currentWait for the PlotSummary file If (GET_FULL_PLOTSUMMARY Or GET_FULL_PLOT_SUMMARY Or GET_FULL_PLOT__SUMMARY Or GET_FULL_PLOT_SYNOPSIS) Then Begin WebText := WaitForPageFile(FilePath + FileTitlePlotSummary, 'PlotSummary', 4000, 2000); PlotSummaryPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of PlotSummaryPageDownloaded:|' + BoolToStr(PlotSummaryPageDownloaded)); End; //If (GET_FULL_PLOTSUMMARY Or GET_FULL_PLOT_SUMMARY Or GET_FULL_PLOT__SUMMARY Or GET_FULL_PLOT_SYNOPSIS) Then Begin should end here //Initialize currentWait for the Reviews file If (DOWNLOAD_MORE_PAGES = True) Then Begin WebText := WaitForPageFile(FilePath + FileTitleReviews, 'Reviews', 2000, 2000); ReviewsPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of ReviewsPageDownloaded: ' + BoolToStr(ReviewsPageDownloaded)); End; //If (DOWNLOAD_MORE_PAGES = True) Then Begin should end here //Initialize currentWait for the CompanyCredits file If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[14] = '0')) Then Begin WebText := WaitForPageFile(FilePath + FileTitleCompanyCredits, 'CompanyCredits', 4000, 2000); CompanyCreditsPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of CompanyCreditsPageDownloaded: ' + BoolToStr(CompanyCreditsPageDownloaded)); End; //If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[14] = '0')) Then Begin should end here //Initialize currentWait for the Locations file If (DOWNLOAD_MORE_PAGES = True) Then Begin WebText := WaitForPageFile(FilePath + FileTitleLocations, 'Locations', 4000, 2000); LocationsPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of LocationsPageDownloaded: ' + BoolToStr(LocationsPageDownloaded)); End; //If (DOWNLOAD_MORE_PAGES = True) Then Begin should end here for Locations If (DOWNLOAD_MORE_PAGES = True) Then Begin WebText := WaitForPageFile(FilePath + FileTitleExternalSites, 'ExternalSites', 4000, 2000); ExternalSitesPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of ExternalSitesPageDownloaded: ' + BoolToStr(ExternalSitesPageDownloaded)); End; //If (DOWNLOAD_MORE_PAGES = True) Then Begin should end here for ExternalSites //Initialize currentWait for the CriticReviews file If (DOWNLOAD_MORE_PAGES = True) Then Begin WebText := WaitForPageFile(FilePath + FileTitleCriticReviews, 'CriticReviews', 4000, 2000); CriticReviewsPageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of CriticReviewsPageDownloaded: ' + BoolToStr(CriticReviewsPageDownloaded)); End; //If (DOWNLOAD_MORE_PAGES = True) Then Begin should end here for CriticReviews { //Initialize currentWait for the Reference file If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[14] = '0')) Then Begin WebText := WaitForPageFile(FilePath + FileTitleReference, 'Reference', 4000, 2000); ReferencePageDownloaded := WebText <> ''; LogMessage('Function DownloadPage - Value of ReferencePageDownloaded: ' + BoolToStr(ReferencePageDownloaded)); End; //If Not (USE_SAVED_PVDCONFIG And (ConfigOptions[14] = '0')) Then Begin should end here } //*)End; //If (DOWNLOAD_RELEASE_INFO_PAGE And DOWNLOAD_FULL_CREDITS_PAGE And DOWNLOAD_PARENTAL_GUIDE_PAGE And DOWNLOAD_KEYWORDS_PAGE And DOWNLOAD_TECHNICAL_PAGE And DOWNLOAD_AWARDS_PAGE And DOWNLOAD_CONNECTIONS_PAGE And DOWNLOAD_PLOTSUMMARY_PAGE And DOWNLOAD_COMPANYCREDITS_PAGE) Then Begin should end here //(* //All files are downloaded, proceed with processing LogMessage('Function DownloadPage - All files downloaded successfully.'); //*) //Some download data checks If (Pos('404 Not Found', Result) > 0) And (Length(Result) < 20000) Then Begin //Banned IP. WEB_SPECIFIC. If BYPASS_SILENT Then ShowMessage('Function DownloadPage - The URL is not in use (404 Not Found).' + #13#10 + 'Go to the provider web to find the good page', SCRIPT_FILE_NAME); LogMessage('Function DownloadPage - 404 Not Found|'); Result := ''; //Fatal error End; //If (Pos('404 Not Found', Result) > 0) And (Length(Result) < 20000) Then Begin should end here If (Pos('404 Error - RT', Result) > 0) And (Length(Result) < 20000) Then Begin //Banned IP. WEB_SPECIFIC. If BYPASS_SILENT Then ShowMessage('Function DownloadPage - The URL is not in use (404 Error - RT).' + #13#10 + 'Go to the provider web to find the good page', SCRIPT_FILE_NAME); LogMessage('Function DownloadPage - 404 Error - RT|'); Result := ''; //Fatal error End; //If (Pos('404 Error - RT', Result) > 0) And (Length(Result) < 20000) Then Begin should end here If (Pos('Page not found', Result) > 0) And (Length(Result) < 20000) Then Begin //Banned IP. WEB_SPECIFIC. If BYPASS_SILENT Then ShowMessage('Function DownloadPage - The URL is not in use (Page not found).' + #13#10 + 'Go to the provider web to find the good page', SCRIPT_FILE_NAME); LogMessage('Function DownloadPage - Page not found|'); Result := ''; //Fatal error End; //If (Pos('Page not found', Result) > 0) And (Length(Result) < 20000) Then Begin should end here If (Pos('405 Method not allowed', Result) > 0) And (Length(Result) < 20000) Then Begin //Banned IP. WEB_SPECIFIC. If BYPASS_SILENT Then ShowMessage('Function DownloadPage - The URL has HTTP method problems (405 Method not allowed).' + #13#10 + 'Go to the provider web to find the good page', SCRIPT_FILE_NAME); LogMessage('Function DownloadPage - 405 Method not allowed|'); Result := ''; //Fatal error End; //If (Pos('405 Method not allowed', Result) > 0) And (Length(Result) < 20000) Then Begin should end here (* If (Length(Result) < 3000) Then Begin //Banned IP. WEB_SPECIFIC. If BYPASS_SILENT Then ShowMessage('Function DownloadPage - IMDb Most probably blocked loading the page with AWF' + #13#10 + 'Go to the provider web to find the good page, or try to download it again', SCRIPT_FILE_NAME); LogMessage('Function DownloadPage - Blocked by IMDb with AWF|'); Result := ''; //Fatal error End; //If (Length(Result) < 3000) Then Begin should end here //*) If (Length(Result) < 3000) And (MainPageDownloaded) Then Begin //Banned IP. WEB_SPECIFIC. case MessageBox('Function DownloadPage - IMDb Most probably blocked loading the page with AWF.' + #13#10 + 'Cancel, Retry, or Continue (Ignore)? Note: If you press Ignore, you will not get data from that page, so consider retrying or cancelling and starting the download again!' + #13#10 + #13#10 + 'IMPORTANT: If you choose Retry, you must first externally download the page and only then press Retry.', SCRIPT_FILE_NAME, 2) of 3: //Abort -> treat as Cancel Begin LogMessage('Function DownloadPage END with BLOCKED PAGE===============|'); Result := ''; //Fatal error Exit; End; //Begin 3: //Abort -> treat as Cancel should end here 4: //Retry Begin LogMessage('Function DownloadPage - Retrying download (user will handle externally)...'); //Reload externally downloaded/corrected page Result := ReadPageFile('MainPage', ''); LogMessage('Function DownloadPage - Was externally downloaded page actually parsed, or AWF page from RAM:|' +Copy(Result, 1, 4000)); End; //Begin 4: //Retry should end here 5: //Ignore Begin LogMessage('Function DownloadPage - Ignoring blocked page and continuing...'); Result := ''; //Continue without valid data End; //Begin 5: //Ignore should end here End; //case MessageBox... of should end here End; //If (Length(Result) < 3000) Then Begin If (Pos('Too many requests', Result) > 0) Then Begin //Banned IP. WEB_SPECIFIC. If BYPASS_SILENT Then ShowMessage('Function DownloadPage - The provider has banned your IP (Too many requests).' + #13#10 + 'Go to the provider web and resolve the captcha to prove you are not a robot', SCRIPT_FILE_NAME); LogMessage('Function DownloadPage - Banned IP|'); Result := ''; //Fatal error End; //If (Pos('Too many requests', Result) > 0) Then Begin should end here End Else Begin LogMessage('Function DownloadPage - All Additional Movie Pages files skipped due to UPDATE_DYNAMIC_VALUES_ONLY'); End; //If Not (UPDATE_DYNAMIC_VALUES_ONLY) Then Begin should end here LogMessage('Function DownloadPage END======================|'); Exit; End;//BlockClose //*) //(* Function DownloadImage(URL:AnsiString;OutPutFile:AnsiString): Integer;//BlockOpen //Returns 1 or 0 if the downloaded image file exists on Exit. Var i: Integer; ScriptPath: String; Begin LogMessage('Function DownloadImage BEGIN======================|'); If Not (UPDATE_DYNAMIC_VALUES_ONLY) Then Begin //This applies for each function up to ParsePage function LogMessage('Function DownloadImage -Global Var: DownloadURL|' + DownloadURL + '||'); LogMessage('Function DownloadImage - Local Var: URL|' + URL + '||'); LogMessage('Function DownloadImage - Local Var: OutPutFile|' + OutPutFile + '||'); ScriptPath := GetAppPath + 'Scripts\'; //Delete the old downloaded page file. Needed to wait for the curl download included in the PowerShell command While FileExists(OutPutFile) Do Begin FileExecute('cmd.exe', '/C del "' + OutPutFile + '"'); LogMessage('Function DownloadImage - Waiting 1s to delete:|' + OutPutFile); Wait (1000); End; //While FileExists(OutPutFile) Do Begin should end here //Download URL page LogMessage('Function DownloadImage - Download with Selenium script to file:|' + OutPutFile + ' the information of:|' + URL + '||'); FileExecute('pythonw.exe ', '"' + ScriptPath + 'Selenium_Chrome_DownloadImage-v4.py" "' + URL + '" "' + OutPutFile + '"'); //Wait for the download to finish and ensure the downloaded page exists. i := 0; //INTERNET_TEST_ITERATIONS While Not (FileExists(OutPutFile)) Do Begin LogMessage('Function DownloadImage - Waiting 2s for the presence of :|' + OutPutFile); Wait (2000); i := i + 1; If i = INTERNET_TEST_ITERATIONS Then Begin //During image downloads, the script cannot prompt the user for an internet connection because the file might not exist. LogMessage('Function DownloadImage END with NOT image downloaded===============|'); Result := 0; Exit; End; //If i = INTERNET_TEST_ITERATIONS Then Begin should end here End; //While Not (FileExists(OutPutFile)) Do Begin should end here LogMessage('Function DownloadImage - Complete page file that is now present:|' + OutPutFile); Result := 1; LogMessage('Function DownloadImage finished processing|'); Exit; End; //If Not (UPDATE_DYNAMIC_VALUES_ONLY) Then Begin should end here LogMessage('Function DownloadImage END======================|'); End;//BlockClose //*) //(* Procedure EnsurePosterDownloaded(const HTML: String);//BlockOpen Var curPos: Integer; ItemList, ItemValue, ImageFile: String; Begin LogMessage('Procedure EnsurePosterDownloaded BEGIN=====================|'); If Not DOWNLOAD_POSTERS Then Begin LogMessage('Procedure EnsurePosterDownloaded - DOWNLOAD_POSTERS is FALSE, exiting.'); Exit; End; //If Not DOWNLOAD_POSTERS Then Begin should end here If PosterDownloaded Then Begin LogMessage('Procedure EnsurePosterDownloaded - Poster already downloaded, exiting.'); Exit; End; //If PosterDownloaded Then Begin should end here //Look for og:image in HTML curPos := Pos('"og:image"', HTML); LogMessage('Procedure EnsurePosterDownloaded - curPos:|' + IntToStr(curPos)); If curPos = 0 Then Begin LogMessage('Procedure EnsurePosterDownloaded - No "og:image" found in HTML, exiting.'); Exit; End; //If curPos = 0 Then Begin should end here //Extract the image URL snippet ItemList := TextBetWeenFirst(HTML, '"og:image"', '>'); LogMessage('Procedure EnsurePosterDownloaded - ItemList snippet:|' + ItemList); //Extract the actual image path (assuming BASE_URL_IMAGE_PRE_TRUE prefix) ItemValue := TextBetWeenFirst(ItemList, BASE_URL_IMAGE_PRE_TRUE, '.'); LogMessage('Procedure EnsurePosterDownloaded - Extracted ItemValue:|' + ItemValue); If ItemValue = '' Then Begin LogMessage('Procedure EnsurePosterDownloaded - ItemValue empty, no link for the poster, so exiting.'); Exit; End; //If ItemValue = '' Then Begin should end here //Construct full URL for AllMovie (no max height suffix) ItemValue := BASE_URL_IMAGE_PRE_TRUE + ItemValue; ImageFile := GetAppPath + 'Scripts\' + BASE_DOWNLOAD_FILE_IMAGE_NAME + '-Poster.jpg'; LogMessage('Procedure EnsurePosterDownloaded - Trying download URL:|' + ItemValue + '.jpg'); // Try with max height first If DownloadImage(ItemValue + '._V1_UY' + IntToStr(MAX_IMAGE_HEIGHT) + '_.jpg', ImageFile) = 1 Then Begin AddImageURL(itPoster, ImageFile); PosterDownloaded := True; LogMessage('Procedure EnsurePosterDownloaded - Poster downloaded successfully at max height.'); End Else If DownloadImage(ItemValue + '.jpg', ImageFile) = 1 Then Begin AddImageURL(itPoster, ImageFile); PosterDownloaded := True; LogMessage('Procedure EnsurePosterDownloaded - Poster downloaded successfully at base size.'); End Else Begin LogMessage('Procedure EnsurePosterDownloaded - Poster download failed.'); End; //If DownloadImage(ItemValue + '._V1_UY' + IntToStr(MAX_IMAGE_HEIGHT) + '_.jpg', ImageFile) = 1 Then Begin should end here LogMessage('Procedure EnsurePosterDownloaded END===================|'); End;//BlockClose //*) //(* Function DownloadPageMain(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('Main', ''); End;//BlockClose //*) //(* Function DownloadPageReleaseInfo(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('ReleaseInfo', '-ReleaseInfo'); End;//BlockClose //*) //(* Function DownloadPageFullCredits(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('FullCredits', '-FullCredits'); End;//BlockClose //*) //(* Function DownloadPageParentalGuide(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('ParentalGuide', '-ParentalGuide'); End;//BlockClose //*) //(* Function DownloadPageReference(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('Reference', '-Reference'); End;//BlockClose //*) //(* Function DownloadPageKeywords(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('Keywords', '-Keywords'); End;//BlockClose //*) //(* Function DownloadPageTechnical(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('Technical', '-Technical'); End;//BlockClose //*) //(* Function DownloadPageAwards(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('Awards', '-Awards'); End;//BlockClose //*) //(* Function DownloadPageMovieConnections(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('MovieConnections', '-MovieConnections'); End;//BlockClose //*) //(* Function DownloadPagePlotSummary(URL: AnsiString): String;//BlockOpen Begin If Not (GET_FULL_PLOTSUMMARY Or GET_FULL_PLOT_SUMMARY Or GET_FULL_PLOT__SUMMARY Or GET_FULL_PLOT_SYNOPSIS Or GET_FULL_PLOT) Then Begin LogMessage('Function DownloadPagePlotSummary - Skipping download as no relevant options are set.'); Result := ''; Exit; End; //If Not (GET_FULL_PLOTSUMMARY Or GET_FULL_PLOT_SUMMARY Or GET_FULL_PLOT__SUMMARY Or GET_FULL_PLOT_SYNOPSIS Or GET_FULL_PLOT) Then Begin should end here Result := ReadPageFile('PlotSummary', '-PlotSummary'); End;//BlockClose //*) //(* Function DownloadPageReviews(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('Reviews', '-Reviews'); End;//BlockClose //*) //(* Function DownloadPageCompanyCredits(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('CompanyCredits', '-CompanyCredits'); End;//BlockClose //*) //(* Function DownloadPageLocations(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('Locations', '-Locations'); End;//BlockClose //*) //(* Function DownloadPageCriticReviews(URL: AnsiString): String;//BlockOpen Begin Result := ReadPageFile('CriticReviews', '-CriticReviews'); End;//BlockClose //*) //(* Function ConfDate1(OrigDate:String): String;//BlockOpen Var i, rNum: Integer; d, m, y: String; TabMonths, TabFullMonths:Array of String; TabDate: TWideArray; Begin TabMonths := ['Null', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; TabFullMonths := ['Null', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; rNum := ExplodeString(OrigDate, TabDate, '/'); LogMessage('Function ConfDate1 => rNum:|' + IntToStr(rNum)); If (rNum <= 1) Then Begin rNum := ExplodeString(OrigDate, TabDate, ' '); LogMessage('Function ConfDate1 => rNum:|' + IntToStr(rNum)); End; //If (rNum <= 1) Then Begin should end here If (rNum > 0) Then Begin LogMessage('Function ConfDate1 => TabDate 0:|' + TabDate[0]); LogMessage('Function ConfDate1 => TabDate 1:|' + TabDate[1]); LogMessage('Function ConfDate1 => TabDate 2:|' + TabDate[2]); If (Length(TabDate[0]) > 0) Then Begin If (Length(TabDate[0]) > 2) Then Begin m := TabDate[0]; For i := 1 to 12 Do Begin If ((m = TabMonths[i]) Or (m = TabFullMonths[i])) Then Begin m := IntToStr(i); Break; End; //If ((m = TabMonths[i]) Or (m = TabFullMonths[i])) Then Begin should end here End; //For i := 1 to 12 Do Begin should end here LogMessage('Function ConfDate1 => Months:|' + m); //d := Copy(TabDate[1], 1, Length(TabDate[1])-1); d := TabDate[1]; If Copy(TabDate[1], 1, 1) = '0' Then d := Copy(TabDate[1], 2, 1); y := TabDate[2]; End Else If (Length(TabDate[1]) > 0) Then Begin y := TabDate[2]; m := TabDate[1]; For i := 1 to 12 Do Begin If ((m = TabMonths[i]) Or (m = TabFullMonths[i])) Then Begin m := IntToStr(i); Break; End; //If ((m = TabMonths[i]) Or (m = TabFullMonths[i])) Then Begin should end here End; //For i := 1 to 12 Do Begin should end here d := TabDate[0]; If Copy(TabDate[0], 1, 1) = '0' Then d := Copy(TabDate[0], 2, 1); LogMessage('Function ConfDate1 => Year:|' + y + ' month:|' + m + ' day:|' + d); End Else Begin //End Else If (Length(TabDate[1]) > 0) Then Begin ends here y := ''; m := ''; d := ''; End; //If (Length(TabDate[0]) > 2) Then Begin ends here End Else Begin ExplodeString(OrigDate, TabDate, '/'); y := Copy(OrigDate, 7, 4); m := Copy(OrigDate, 3, 3); For i := 1 to 12 Do Begin If m = Copy(TabMonths[i], 1, 3) Then Begin m := IntToStr(i); Break; End; //If m = Copy(TabMonths[i], 1, 3) Then Begin should end here End; //For i := 1 to 12 Do Begin should end here d := Copy(OrigDate, 1, 2); If Copy(TabDate[0], 1, Length(TabDate[0])-1) = '0' Then d := Copy(TabDate[0], 2, Length(TabDate[0])-1); LogMessage('Function ConfDate1 - Year:|' + y + ' month:|' + m + ' day:|' + d); End; //If (Length(TabDate[0]) > 0) Then Begin should end here Result := d + '.' + m + '.' + y; End; //If (rNum > 0) Then Begin should end here End;//BlockClose //*) //(* Function ConfDate2(OrigDate:String): String; Var i, rNum, curPos: Integer; d, m, y: String; TabMonths, TabFullMonths: Array of String; TabDate: TWideArray; Begin TabMonths := ['Null', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; TabFullMonths := ['Null', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; //Clean up input by removing non-date content OrigDate := TextBetween(OrigDate, '', ' (', False, curPos); OrigDate := Trim(OrigDate); //Trim extra spaces rNum := ExplodeString(OrigDate, TabDate, '/'); If (rNum <= 1) Then Begin rNum := ExplodeString(OrigDate, TabDate, ' '); End; //If (rNum <= 1) Then Begin should end here //Ensure we have at least a month and year If (rNum < 2) Then Begin LogMessage('Function ConfDate2 - Invalid date format:|' + OrigDate); Exit; //Return an empty string if the date format is invalid End; //If (rNum < 2) Then Begin should end here //Initialize variables m := ''; d := '01'; //Default to the first day of the month if day is missing y := ''; //Extract month and year If (Length(TabDate[0]) > 0) Then Begin If (Length(TabDate[0]) > 2) Then Begin m := TabDate[0]; //Month is in the first position y := TabDate[1]; //Year is in the second position End Else Begin m := TabDate[0]; //Month is in the first position y := TabDate[1]; //Year is in the second position End; //If (Length(TabDate[0]) > 2) Then Begin should end here //Convert month name to numeric For i := 1 to 12 Do Begin If ((m = TabMonths[i]) Or (m = TabFullMonths[i])) Then Begin m := IntToStr(i); Break; End; //If ((m = TabMonths[i]) Or (m = TabFullMonths[i])) Then Begin should end here End; //For i := 1 to 12 Do Begin should end here If Length(m) = 1 Then m := '0' + m; //Ensure month has two digits End; //If (Length(TabDate[0]) > 0) Then Begin should end here //Validate the year If y = '' Then Begin LogMessage('Function ConfDate2 - Year missing:|' + OrigDate); Exit; End; //If y = '' Then Begin should end here //Format the date as yyyy-mm-dd Result := y + '-' + m + '-' + d; End;//BlockClose //*) //(* Function ConfDateAM(OrigDate: String): String; Var rNum, i: Integer; d, m, y: String; yy, mm, dd: Word; TabMonths, TabFullMonths: Array of String; TabDate: TWideArray; Begin TabMonths := ['Null', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; TabFullMonths := ['Null', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; OrigDate := Trim(OrigDate); Result := OrigDate; //fallback //Case 1: dd/mm/yyyy rNum := ExplodeString(OrigDate, TabDate, '/'); If rNum = 3 Then Begin d := TabDate[0]; m := TabDate[1]; y := TabDate[2]; Result := d + '.' + m + '.' + y; Exit; End; //If rNum = 3 Then Begin should end here //Case 2: MonthName Day (no year) rNum := ExplodeString(OrigDate, TabDate, ' '); If rNum = 2 Then Begin m := TabDate[0]; d := TabDate[1]; //Inject current year using DecdDate DecdDate(CurrentDateTime, yy, mm, dd); y := IntToStr(yy); //Convert month name to number For i := 1 to 12 Do Begin If (m = TabMonths[i]) Or (m = TabFullMonths[i]) Then Begin m := IntToStr(i); Break; End; //If (m = TabMonths[i]) Or (m = TabFullMonths[i]) Then Begin should end here End; //For i := 1 to 12 Do Begin should end here Result := d + '.' + m + '.' + y; Exit; End; //If rNum = 2 Then Begin should end here //Case 3: MonthName Year (no day) If rNum = 2 Then Begin m := TabDate[0]; y := TabDate[1]; d := '1'; //default to first day For i := 1 to 12 Do Begin If (m = TabMonths[i]) Or (m = TabFullMonths[i]) Then Begin m := IntToStr(i); Break; End; //If (m = TabMonths[i]) Or (m = TabFullMonths[i]) Then Begin should end here End; //For i := 1 to 12 Do Begin should end here Result := d + '.' + m + '.' + y; Exit; End; //If rNum = 2 Then Begin should end here End;//BlockClose //*) //(* Function RemoveTagsEx0(AText:String): String;//BlockOpen //Ivek23 function for get faster the script Var B, E: Integer; Begin Result := AText; B := PosFrom('<', Result, 1); E := PosFrom('>', Result, B); While (B > 0) And (B < E) Do Begin Delete(Result, B, E - B + 1); B := Pos('<', Result); E := Pos('>', Result); End; //While (B > 0) And (B < E) Do Begin should end here End;//BlockClose //*) //(* Function RemoveTagsEx(AText:String): String;//BlockOpen //Ivek23 function for get faster the PLOTKEYWORDS script Var B, E: Integer; Begin Result := AText; B := PosFrom('<', Result, 1); E := PosFrom('>', Result, B); While (B > 0) And (B < E) Do Begin Delete(Result, B, E - B + 1); B := Pos('<', Result); E := Pos('>', Result); End; //While (B > 0) And (B