IMDB script Awards

If you made a script you can offer it to the others here, or ask help to improve it. You can also report here bugs & problems with existing scripts.
Post Reply
DarKHawK
Posts: 11
Joined: 2003-10-17 01:19:36

IMDB script Awards

Post by DarKHawK »

Hi,

The awards part of the IMDB script seems to be a hit and miss. Sometimes it work sometimes it doesn't. Trivia is working fine, that means RapidAPI is working since both rely on it to work.

Something I'm missing?

Thanks.
Dorohedoro
Posts: 52
Joined: 2016-12-13 00:45:45

Re: IMDB script Awards

Post by Dorohedoro »

Some movies doesn't have any awards.
DarKHawK
Posts: 11
Joined: 2003-10-17 01:19:36

Re: IMDB script Awards

Post by DarKHawK »

True.

But those that does have awards, sometimes the script gets the awards and sometimes it doesn't
MrObama2022
Posts: 64
Joined: 2022-02-02 00:03:55

Re: IMDB script Awards

Post by MrObama2022 »

That's because iMDB changed html only in some pages (100% different html), so iMDB parser must be rewritten to support both version (old and one) and that's a huge work with a lot of testing ...
antp
Site Admin
Posts: 9687
Joined: 2002-05-30 10:13:07
Location: Brussels
Contact:

Re: IMDB script Awards

Post by antp »

I suppose the easiest way to do it would be to first detect if it is the old page or new page before starting to extract info from it, and then run the old (unmodified code) in he first case, or call a new separate function in the second case.
That way you don't have to worry on how to handle the old pages.
MrObama2022
Posts: 64
Joined: 2022-02-02 00:03:55

Re: IMDB script Awards

Post by MrObama2022 »

That's right, the hard work is write all the code for all the super-detailed fields (and that's because who use iMDB script want Awards, Trivia, actor names, rating, etc. etc.).
Dorohedoro
Posts: 52
Joined: 2016-12-13 00:45:45

Re: IMDB script Awards

Post by Dorohedoro »

MrObama2022 wrote: 2025-06-13 18:35:54 That's right, the hard work is write all the code for all the super-detailed fields (and that's because who use iMDB script want Awards, Trivia, actor names, rating, etc. etc.).
In my opinion IA may be capable of assisting you with the tedious process.
MrObama2022
Posts: 64
Joined: 2022-02-02 00:03:55

Re: IMDB script Awards

Post by MrObama2022 »

This is also my opinion ... Let me try with Lovable.dev, I've a premium account ...
MrObama2022
Posts: 64
Joined: 2022-02-02 00:03:55

Re: IMDB script Awards

Post by MrObama2022 »

IA sucks ... tried Gemini and Perplexity too, no way, old school is the way
antp
Site Admin
Posts: 9687
Joined: 2002-05-30 10:13:07
Location: Brussels
Contact:

Re: IMDB script Awards

Post by antp »

For this kind of very specific task, using a non-standard language, the IA is probably not so efficient indeed :/
Dorohedoro
Posts: 52
Joined: 2016-12-13 00:45:45

Re: IMDB script Awards

Post by Dorohedoro »

antp wrote: 2025-06-14 06:31:09 For this kind of very specific task, using a non-standard language, the IA is probably not so efficient indeed :/
For the massive task you guys have ahead maybe the IA is a bit dumb right now, but it helped me with the code to extract only number of votes without the rating, gave me a working code in the first try.

Sometimes the result depends a lot on the prompt.
fulvio53s03
Posts: 771
Joined: 2007-04-28 05:46:43
Location: Italy

Re: IMDB script Awards

Post by fulvio53s03 »

Dorohedoro wrote: 2025-06-14 06:44:48 Sometimes the result depends a lot on the prompt.
Could you show us something about the prompt you nominated? Which AI did you turn to?
it could be very useful for all of us.
Thank you. :grinking:
Dorohedoro
Posts: 52
Joined: 2016-12-13 00:45:45

Re: IMDB script Awards

Post by Dorohedoro »

fulvio53s03 wrote: 2025-06-14 10:50:24
Dorohedoro wrote: 2025-06-14 06:44:48 Sometimes the result depends a lot on the prompt.
Could you show us something about the prompt you nominated? Which AI did you turn to?
it could be very useful for all of us.
Thank you. :grinking:
Disclaimer: I'm not telling that chatgpt or any ia will do all the work, the ia should only help with some tasks.

In my case It was simple (and I don't have any coding experience), this code extracts both ratings and amount of votes from imdb:

Code: Select all

Value := 'User Rating: ' + GetField(fieldRating) + ' out of 10  (with ' + Value + ')';
And I told chatgpt:

Value := GetField(fieldRating) + ' ' + Value + ''; that code works extracting both rating and number of votes from this page: https://www.imdb.com/title/tt0114885/reference, what I should delete from the code to erase the rating and just get the amount of votes?

This was the chatgpt response:

Ah, I see! Let’s tweak that line to erase the rating while keeping only the number of votes from the string returned by GetField(fieldRating).

Given your current line:

pascal
Copiar
Editar
Value := GetField(fieldRating) + ' ' + Value + '';
This simply concatenates the full rating string (e.g., "6 (12.909)") with a space and then Value. But you only want the number in parentheses (i.e., "12.909").

🔎 Step-by-Step Fix:
1️⃣ Currently:

pascal
Copiar
Editar
Value := GetField(fieldRating) + ' ' + Value;
✅ Extracts everything, including both rating and votes.

2️⃣ To remove the rating but keep the votes (the part inside the parentheses), you can extract only the text inside the parentheses.

Replace:

pascal
Copiar
Editar
Value := GetField(fieldRating) + ' ' + Value;
With:

pascal
Copiar
Editar
Value := Copy(GetField(fieldRating), Pos('(', GetField(fieldRating)) + 1, Pos(')', GetField(fieldRating)) - Pos('(', GetField(fieldRating)) - 1) + ' ' + Value;
🔥 Explanation:
Copy(...) extracts text between ( and ).

The rest of the line concatenates that extracted value with a space and then Value.

📝 Example:
GetField(fieldRating) → "6 (12.909)"

Extracted → "12.909"

Value → "<whatever was in Value before>"

Result → "12.909 <whatever was in Value before>"

This should work, please let me know if you'd like to refine that even more! 🚀
fulvio53s03
Posts: 771
Joined: 2007-04-28 05:46:43
Location: Italy

Re: IMDB script Awards

Post by fulvio53s03 »

Dorohedoro wrote: 2025-06-14 15:56:02 Disclaimer: I'm not telling that chatgpt or any ia will do all the work, the ia should only help with some tasks.
This should work, please let me know if you'd like to refine that even more! 🚀
Thank you, it's clear. Maybe i'll try (but I would prefere to use a script.) :innocent:
antp
Site Admin
Posts: 9687
Joined: 2002-05-30 10:13:07
Location: Brussels
Contact:

Re: IMDB script Awards

Post by antp »

If you provide all existing scripts + the technical info about script from the help file of the program, it may be more efficient and correct :)
Also an IA like Claude or Gemini would be better than ChatGPT.
Dorohedoro
Posts: 52
Joined: 2016-12-13 00:45:45

Re: IMDB script Awards

Post by Dorohedoro »

antp wrote: 2025-06-15 06:23:12 If you provide all existing scripts + the technical info about script from the help file of the program, it may be more efficient and correct :)
Also an IA like Claude or Gemini would be better than ChatGPT.
I did this script with Deepseek, it succerfully extracts the picture, the year (well it seems not this one, but in another try yesterday it gave me the year and also the aspect ratio) and the description (with a minor error and it's taking wrongfully the long description), I think this could give you guys some clues:

Code: Select all

program IMDB;

uses
//  Debug,
  StringUtils1, StringUtils7552;

const
  PopularTitleSearchURL =  'https://www.imdb.com/find?s=tt&q=';
  FullTitleSearchURL = 'https://www.imdb.com/find?s=tt&exact=true&q=';
  EpisodeTitleSearchURL = 'https://www.imdb.com/find?s=ep&q=';

var
  MovieName: string;
  MovieURL: string;
  MovieNumber: string;
  MovieYear: string;
  UpdateFile: TStringList;

function ConvertToASCII(AText: string): string;
begin
  Result := UTF8Decode(AText);
  if Result = '' then
    Result := AText; // in case of a UTF8 decoding error
  if GetOption('ConvertToASCII') = 1 then
    Result := Cp1252ToASCII(Result);
end;

function AKACountry: string;
begin
  case AnsiLowerCase(fulltrim(GetParam('UserCountry'))) of
  'andorra': result := 'AD';
  'united arab emirates': result := 'AE';
  'afghanistan': result := 'AF';
  'antigua and barbuda': result := 'AG';
  'anguilla': result := 'AI';
  'albania': result := 'AL';
  'armenia': result := 'AM';
  'angola': result := 'AO';
  'antarctica': result := 'AQ';
  'argentina': result := 'AR';
  'american samoa': result := 'AS';
  'austria': result := 'AT';
  'australia': result := 'AU';
  'aruba': result := 'AW';
  'åland islands': result := 'AX';
  'azerbaijan': result := 'AZ';
  'bosnia and herzegovina': result := 'BA';
  'barbados': result := 'BB';
  'bangladesh': result := 'BD';
  'belgium': result := 'BE';
  'burkina faso': result := 'BF';
  'bulgaria': result := 'BG';
  'bahrain': result := 'BH';
  'burundi': result := 'BI';
  'benin': result := 'BJ';
  'saint barthélemy': result := 'BL';
  'bermuda': result := 'BM';
  'brunei darussalam': result := 'BN';
  'bolivia (plurinational state of)': result := 'BO';
  'bonaire, sint eustatius and saba': result := 'BQ';
  'brazil': result := 'BR';
  'bahamas': result := 'BS';
  'bhutan': result := 'BT';
  'bouvet island': result := 'BV';
  'botswana': result := 'BW';
  'belarus': result := 'BY';
  'belize': result := 'BZ';
  'canada': result := 'CA';
  'cocos (keeling) islands': result := 'CC';
  'congo, democratic republic of the': result := 'CD';
  'central african republic': result := 'CF';
  'congo': result := 'CG';
  'switzerland': result := 'CH';
  'côte d''ivoire': result := 'CI';
  'cook islands': result := 'CK';
  'chile': result := 'CL';
  'cameroon': result := 'CM';
  'china': result := 'CN';
  'colombia': result := 'CO';
  'costa rica': result := 'CR';
  'cuba': result := 'CU';
  'cabo verde': result := 'CV';
  'curaçao': result := 'CW';
  'christmas island': result := 'CX';
  'cyprus': result := 'CY';
  'czechia': result := 'CZ';
  'germany': result := 'DE';
  'djibouti': result := 'DJ';
  'denmark': result := 'DK';
  'dominica': result := 'DM';
  'dominican republic': result := 'DO';
  'algeria': result := 'DZ';
  'ecuador': result := 'EC';
  'estonia': result := 'EE';
  'egypt': result := 'EG';
  'western sahara': result := 'EH';
  'eritrea': result := 'ER';
  'spain': result := 'ES';
  'ethiopia': result := 'ET';
  'finland': result := 'FI';
  'fiji': result := 'FJ';
  'falkland islands (malvinas)': result := 'FK';
  'micronesia (federated states of)': result := 'FM';
  'faroe islands': result := 'FO';
  'france': result := 'FR';
  'gabon': result := 'GA';
  'united kingdom of great britain and northern ireland': result := 'GB';
  'grenada': result := 'GD';
  'georgia': result := 'GE';
  'french guiana': result := 'GF';
  'guernsey': result := 'GG';
  'ghana': result := 'GH';
  'gibraltar': result := 'GI';
  'greenland': result := 'GL';
  'gambia': result := 'GM';
  'guinea': result := 'GN';
  'guadeloupe': result := 'GP';
  'equatorial guinea': result := 'GQ';
  'greece': result := 'GR';
  'south georgia and the south sandwich islands': result := 'GS';
  'guatemala': result := 'GT';
  'guam': result := 'GU';
  'guinea-bissau': result := 'GW';
  'guyana': result := 'GY';
  'hong kong': result := 'HK';
  'heard island and mcdonald islands': result := 'HM';
  'honduras': result := 'HN';
  'croatia': result := 'HR';
  'haiti': result := 'HT';
  'hungary': result := 'HU';
  'indonesia': result := 'ID';
  'ireland': result := 'IE';
  'israel': result := 'IL';
  'isle of man': result := 'IM';
  'india': result := 'IN';
  'british indian ocean territory': result := 'IO';
  'iraq': result := 'IQ';
  'iran (islamic republic of)': result := 'IR';
  'iceland': result := 'IS';
  'italy': result := 'IT';
  'jersey': result := 'JE';
  'jamaica': result := 'JM';
  'jordan': result := 'JO';
  'japan': result := 'JP';
  'kenya': result := 'KE';
  'kyrgyzstan': result := 'KG';
  'cambodia': result := 'KH';
  'kiribati': result := 'KI';
  'comoros': result := 'KM';
  'saint kitts and nevis': result := 'KN';
  'korea (democratic people''s republic of)': result := 'KP';
  'korea, republic of': result := 'KR';
  'kuwait': result := 'KW';
  'cayman islands': result := 'KY';
  'kazakhstan': result := 'KZ';
  'lao people''s democratic republic': result := 'LA';
  'lebanon': result := 'LB';
  'saint lucia': result := 'LC';
  'liechtenstein': result := 'LI';
  'sri lanka': result := 'LK';
  'liberia': result := 'LR';
  'lesotho': result := 'LS';
  'lithuania': result := 'LT';
  'luxembourg': result := 'LU';
  'latvia': result := 'LV';
  'libya': result := 'LY';
  'morocco': result := 'MA';
  'monaco': result := 'MC';
  'moldova, republic of': result := 'MD';
  'montenegro': result := 'ME';
  'saint martin (french part)': result := 'MF';
  'madagascar': result := 'MG';
  'marshall islands': result := 'MH';
  'north macedonia': result := 'MK';
  'mali': result := 'ML';
  'myanmar': result := 'MM';
  'mongolia': result := 'MN';
  'macao': result := 'MO';
  'northern mariana islands': result := 'MP';
  'martinique': result := 'MQ';
  'mauritania': result := 'MR';
  'montserrat': result := 'MS';
  'malta': result := 'MT';
  'mauritius': result := 'MU';
  'maldives': result := 'MV';
  'malawi': result := 'MW';
  'mexico': result := 'MX';
  'malaysia': result := 'MY';
  'mozambique': result := 'MZ';
  'namibia': result := 'NA';
  'new caledonia': result := 'NC';
  'niger': result := 'NE';
  'norfolk island': result := 'NF';
  'nigeria': result := 'NG';
  'nicaragua': result := 'NI';
  'netherlands, kingdom of the': result := 'NL';
  'norway': result := 'NO';
  'nepal': result := 'NP';
  'nauru': result := 'NR';
  'niue': result := 'NU';
  'new zealand': result := 'NZ';
  'oman': result := 'OM';
  'panama': result := 'PA';
  'peru': result := 'PE';
  'french polynesia': result := 'PF';
  'papua new guinea': result := 'PG';
  'philippines': result := 'PH';
  'pakistan': result := 'PK';
  'poland': result := 'PL';
  'saint pierre and miquelon': result := 'PM';
  'pitcairn': result := 'PN';
  'puerto rico': result := 'PR';
  'palestine, state of': result := 'PS';
  'portugal': result := 'PT';
  'palau': result := 'PW';
  'paraguay': result := 'PY';
  'qatar': result := 'QA';
  'réunion': result := 'RE';
  'romania': result := 'RO';
  'serbia': result := 'RS';
  'russian federation': result := 'RU';
  'rwanda': result := 'RW';
  'saudi arabia': result := 'SA';
  'solomon islands': result := 'SB';
  'seychelles': result := 'SC';
  'sudan': result := 'SD';
  'sweden': result := 'SE';
  'singapore': result := 'SG';
  'saint helena, ascension and tristan da cunha': result := 'SH';
  'slovenia': result := 'SI';
  'svalbard and jan mayen': result := 'SJ';
  'slovakia': result := 'SK';
  'sierra leone': result := 'SL';
  'san marino': result := 'SM';
  'senegal': result := 'SN';
  'somalia': result := 'SO';
  'suriname': result := 'SR';
  'south sudan': result := 'SS';
  'sao tome and principe': result := 'ST';
  'el salvador': result := 'SV';
  'sint maarten (dutch part)': result := 'SX';
  'syrian arab republic': result := 'SY';
  'eswatini': result := 'SZ';
  'turks and caicos islands': result := 'TC';
  'chad': result := 'TD';
  'french southern territories': result := 'TF';
  'togo': result := 'TG';
  'thailand': result := 'TH';
  'tajikistan': result := 'TJ';
  'tokelau': result := 'TK';
  'timor-leste': result := 'TL';
  'turkmenistan': result := 'TM';
  'tunisia': result := 'TN';
  'tonga': result := 'TO';
  'türkiye': result := 'TR';
  'trinidad and tobago': result := 'TT';
  'tuvalu': result := 'TV';
  'taiwan, province of china[note 1]': result := 'TW';
  'tanzania, united republic of': result := 'TZ';
  'ukraine': result := 'UA';
  'uganda': result := 'UG';
  'united states minor outlying islands': result := 'UM';
  'united states': result := 'US';
  'uruguay': result := 'UY';
  'uzbekistan': result := 'UZ';
  'holy see': result := 'VA';
  'saint vincent and the grenadines': result := 'VC';
  'venezuela (bolivarian republic of)': result := 'VE';
  'virgin islands (british)': result := 'VG';
  'virgin islands (u.s.)': result := 'VI';
  'viet nam': result := 'VN';
  'vanuatu': result := 'VU';
  'wallis and futuna': result := 'WF';
  'samoa': result := 'WS';
  'yemen': result := 'YE';
  'mayotte': result := 'YT';
  'south africa': result := 'ZA';
  'zambia': result := 'ZM';
  'zimbabwe': result := 'ZW';
  else
  begin
    ShowMessage('Invalid country (' + GetParam('UserCountry') + '), set default one (United States of America). Please use a valid country written in english as it is on IMDb, e.g. one of these: United States, Canada, Mexico, Brazil, Argentina, Australia, India, Italy, Spain, Portugal, France, Germany, Netherlands, United Kingdom, Ireland, Finland, Norway, Sweden, Switzerland, ....');
    SetParam('UserCountry', 'United States of America');
    result := 'US';
  end;
  end;
end;

// ***** analyzes IMDB's results page that asks to select a movie from a list *****

procedure AnalyzeResultsPage(Address: string);
var
  PageText: string;
  Value: string;
begin
  PageText := ConvertToASCII(GetPage(Address));
  if pos('<title>Find - IMDb', PageText) = 0 then
    begin
      AnalyzeMoviePage(PageText)
    end else
    begin
      if Pos('<b>No Matches.</b>', PageText) > 0 then
        begin
          if GetOption('BatchMode') = 0 then
            ShowMessage('No movie found for this search.');
          Exit;
        end;
      if GetOption('BatchMode') = 0 then
      begin
        PickTreeClear;
        Value := TextBetween(PageText, '>Titles</h3>', '</section>');
        if Value <> '' then
        begin
          PickTreeAdd('Titles search results', '');
          AddMovieTitles(Value);
        end;
        if PickTreeExec(Address) then
          AnalyzeResultsPage(Address);
      end
      else
        if (MovieYear <> '') then
        begin
          Value := GetUrl(PageText, '(' + MovieYear + ')', '');
          if Value = '' then
          begin
            Value := GetUrl(PageText, '(' + IntToStr(StrToInt(MovieYear, 0) - 1) + ')', '');
            if Value = '' then
              Value := GetUrl(PageText, '(' + IntToStr(StrToInt(MovieYear, 0) + 1) + ')', '');
          end;
          if Value <> '' then
            AnalyzeResultsPage('https://www.imdb.com' + Value);
        end
        else
        begin
          Value := GetUrl(PageText, 'find-title-result', '');
          if Value <> '' then
            AnalyzeResultsPage('https://www.imdb.com' + Value);
        end;
    end;
end;

// ***** adds the movie titles found on IMDB's results page *****

function AddMovieTitles(List: string): Boolean;
var
  Value: string;
  Address: string;
begin
  Result := False;
  Value := TextBetween(List, '<td class="result_text">', '</td>');
  if Value = '' then
  begin
    Value := TextBetween(List, '<div class="ipc-metadata-list-summary-item__c">', '</div></div>');
  end;
  List := RemainingText;
  while Value <> '' do
  begin
    Address := TextBetween(Value, '<a href="/title/tt', '/');
    if Address = '' then
    begin
      Address := TextBetween(Value, '<a class="ipc-metadata-list-summary-item__t" tabindex="0" aria-disabled="false" href="/title/tt', '/');
    end;
    Address := Address + '/reference';
    if Pos('for="_blank">', Value) > 0 then
    begin
      Value := StringReplace(Value, 'for="_blank">', '> (');
      Value := StringReplace(Value, '</label>', ')');
    end
    Value := RegExprSetReplace('\>(\d+)\<\/span\>', Value, '> ($1) </span>', True);
    HTMLRemoveTags(Value);
    HTMLDecode(Value);
    PickTreeAdd(Value, 'https://www.imdb.com/title/tt' + Address);
    Result := True;
    Value := TextBetween(List, '<td class="result_text">', '</td>');
    if value = '' then
    begin
      Value := TextBetween(List, '<div class="ipc-metadata-list-summary-item__c">', '</div></div>');
    end;
     List := RemainingText;
  end;
end;


// ***** decode rapidApi charset ****

function decodeRapidApiCharsetToCP1252(str: string): string;
begin
  // Romanian chars fix
  str := StringReplace(str, (chr(195) + chr(136) + chr(194)), chr(200));

  // UTF-8 fix
  str := StringReplace(str, (chr(195) + chr(130) + chr(194)), chr(194));
  str := StringReplace(str, (chr(195) + chr(131) + chr(194)), chr(195));
  str := StringReplace(str, (chr(195) + chr(132) + chr(194)), chr(196));
  str := StringReplace(str, (chr(195) + chr(133) + chr(194)), chr(197));

  result := UTF8Decode(str);
  if (result = '') then
    result := str;
end;


// ***** retrieve alternative titles from RapidAPI *****

procedure retrieveTitlesFromRapidAPI;
var
  JsonResponse, Headers, Delimiter, Lang, Country, CountryTitle, CountryTitleLowercase: string;
  WorldwideTitles, TranslatedTitles, CountryTitles: string;
begin
  Delimiter := ' || ';
  Headers := 'X-RapidAPI-Key=' + GetParam('RapidAPIKey') + Chr(13) + Chr(10) + 'X-RapidAPI-Host=imdb8.p.rapidapi.com';
  WorldwideTitles := Delimiter;
  TranslatedTitles := Delimiter;
  CountryTitles := Delimiter;
  JsonResponse := GetPage5('https://imdb8.p.rapidapi.com/title/get-versions?tconst=tt' + MovieNumber, '', '', '', Headers);
  // if rapidapi fails, retry again
  if (JsonResponse = '') then
    JsonResponse := GetPage5('https://imdb8.p.rapidapi.com/title/get-versions?tconst=tt' + MovieNumber, '', '', '', Headers);
  JsonResponse := decodeRapidApiCharsetToCP1252(JsonResponse);
  // remove unneeded json (first part)
  Delete(JsonResponse, 1, pos('"alternateTitles":[', JsonResponse));
  if (pos('"region":"', JsonResponse) = 0) then
    ShowMessage('RapidApi failed twice, please retry. If still fails, check your API Key, your monthly limit usage and your routing to imdb8.p.rapidapi.com')
  else
  while (pos('"region":"', JsonResponse) > 0) do
  begin
    Lang := copy(JsonResponse, 0, pos('"region":"', JsonResponse));
    Lang := fulltrim(textbetween(Lang, '"language":"','"')); // note: "language" could be not defined for some regions
    Country := fulltrim(textbetween(JsonResponse, '"region":"','"'));
    CountryTitle := fulltrim(textbetween(JsonResponse, '"title":"','"'));
    CountryTitleLowercase := AnsiLowerCase(CountryTitle);
    Delete(JsonResponse, 1, (pos('}', JsonResponse) + 1)); // remove this entry
    if ((Lang = 'ar') OR (Lang = 'bg') OR (Lang = 'yue') OR (Lang = 'hi') OR (Lang = 'ja') OR (Lang = 'cmn') OR (Lang = 'ru') OR (Country = 'VN')) then
      CountryTitle := ''
    else
    if ((Country = 'BY') OR (Country = 'BG') OR (Country = 'EG') OR (Country = 'GR') OR (Country = 'HK') OR (Country = 'KZ') OR (Country = 'JP') OR (Country = 'RU') OR (Country = 'SA') OR (Country = 'RS') OR (Country = 'KR') OR (Country = 'TW') OR (Country = 'TH') OR (Country = 'UA') OR (Country = 'AE')) then
      if ((pos('Ð', CountryTitle) > 0) OR (pos(chr(194), CountryTitle) > 0) OR (pos(chr(195), CountryTitle) > 0) OR (pos(chr(196), CountryTitle) > 0) OR (pos(chr(197), CountryTitle) > 0) OR (pos(chr(206), CountryTitle) > 0) OR (pos(chr(208), CountryTitle) > 0) OR (pos(chr(190), CountryTitle) > 0) OR (pos(chr(180), CountryTitle) > 0) OR (pos(chr(228), CountryTitle) > 0) OR (pos(chr(229), CountryTitle) > 0) OR (pos(chr(230), CountryTitle) > 0) OR (pos(chr(231), CountryTitle) > 0) OR (pos(chr(232), CountryTitle) > 0)) then
        CountryTitle := '';
    if (CountryTitle <> '') then
    begin
      if (Country = AKACountry()) then
      begin
        if (pos(Delimiter + CountryTitle + Delimiter, CountryTitles) = 0) then
          CountryTitles := CountryTitles + CountryTitle + Delimiter;
        WorldwideTitles := StringReplace(WorldwideTitles, Delimiter + CountryTitle + Delimiter, Delimiter);
        TranslatedTitles := StringReplace(TranslatedTitles, Delimiter + CountryTitle + Delimiter, Delimiter);
      end
      else if ((CountryTitleLowercase <> AnsiLowerCase(GetField(fieldOriginalTitle))) AND (pos(Delimiter + CountryTitleLowercase + Delimiter, AnsiLowerCase(CountryTitles)) = 0) AND (pos(Delimiter + CountryTitleLowercase + Delimiter, AnsiLowerCase(WorldwideTitles)) = 0)) then
      begin
        if ((Country = 'XWW') OR (Country = 'US') OR (Country = '')) then
        begin
          WorldwideTitles := WorldwideTitles + CountryTitle + Delimiter;
          TranslatedTitles := StringReplace(TranslatedTitles, Delimiter + CountryTitle + Delimiter, Delimiter);
        end
        else if (pos(Delimiter + CountryTitle + Delimiter, TranslatedTitles) = 0) then
          TranslatedTitles := TranslatedTitles + CountryTitle + Delimiter;
      end;
    end;
  end;

  // all titles
  if (GetOption('TranslatedTitle') = 4) then
  begin
    if ((Length(WorldwideTitles) <= Length(Delimiter)) AND (Length(CountryTitles) <= Length(Delimiter))) then
    begin
      // if no country titles or worldwide titles are available, I set as first translated title the original one.
      TranslatedTitles := Delimiter + GetField(fieldOriginalTitle) + TranslatedTitles;
    end
    else
    begin
      if (Length(WorldwideTitles) > Length(Delimiter)) then
        TranslatedTitles := copy(WorldwideTitles, 1, Length(WorldwideTitles) - Length(Delimiter)) + TranslatedTitles;
      if (Length(CountryTitles) > Length(Delimiter)) then
        TranslatedTitles := copy(CountryTitles, 1, Length(CountryTitles) - Length(Delimiter)) + TranslatedTitles;
    end;
    if (Length(TranslatedTitles) > Length(Delimiter)) then
      setField(fieldTranslatedTitle, copy(TranslatedTitles, Length(Delimiter) + 1, (Length(TranslatedTitles) - Length(Delimiter) - Length(Delimiter))))
    else if (GetField(fieldTranslatedTitle) = '') then
      setField(fieldTranslatedTitle, GetField(fieldOriginalTitle));
  end
  else
  begin
  // only one title
    if (Length(CountryTitles) > Length(Delimiter)) then
      setField(fieldTranslatedTitle, textBetween(CountryTitles, Delimiter, Delimiter))
    else if (Length(WorldwideTitles) > Length(Delimiter)) then
      setField(fieldTranslatedTitle, textBetween(WorldwideTitles, Delimiter, Delimiter));
  end;
end;


// ***** retrieve (un)spoilt content from json from RapidAPI *****

function retrieveTriviaPartFromRapidAPI(JsonResponse, tagFrom, tagTo: string): string;
var JsonContent, Txt, TriviaType: string;
begin
  JsonContent := textBetween(JsonResponse, tagFrom, tagTo);
  if (JsonContent = '') then
    JsonContent := TextAfter(JsonResponse, tagFrom);

  Result := '';
  while (pos('"text":', JsonContent) > 0) do
  begin
    JsonContent := textAfter(JsonContent, '"text":');
    Txt := textBetween(JsonContent, '"', '"');
    JsonContent := textAfter(JsonContent, Txt);
    TriviaType := textBetween(JsonContent, '"', '}');
    TriviaType := textBetween(TriviaType, '"type": "', '"');
    JsonContent := textAfter(JsonContent, '}');
    Result := Result + '- ';
    if (TriviaType <> '') then
      Result := Result + '[' + StringReplace(TriviaType, '-', ' ') + '] ';
    Result := Result + Txt + Chr(13) + Chr(10);
  end;
end;


// ***** retrieve trivia from RapidAPI *****

function retrieveTriviaFromRapidAPI(): string;
var
  JsonResponse, Headers: string;
  Trivia, Spoiler, AposReplace: string;
begin
  AposReplace := 'fj57hg785gh4jg7gh48g45g'; // any unique string ...
  Trivia := '';
  Spoiler := '';
  Headers := 'X-RapidAPI-Key=' + GetParam('RapidAPIKey') + Chr(13) + Chr(10) + 'X-RapidAPI-Host=imdb8.p.rapidapi.com';
  JsonResponse := GetPage5('https://imdb8.p.rapidapi.com/title/get-trivia?tconst=tt' + MovieNumber, '', '', '', Headers);
  // if rapidapi fails, retry again
  if (JsonResponse = '') then
    JsonResponse := GetPage5('https://imdb8.p.rapidapi.com/title/get-trivia?tconst=tt' + MovieNumber, '', '', '', Headers);
  JsonResponse := decodeRapidApiCharsetToCP1252(JsonResponse);
  JsonResponse := StringReplace(JsonResponse, '\"', AposReplace);

  // remove unneeded json (first part)
  Trivia := retrieveTriviaPartFromRapidAPI(JsonResponse, '"unspoilt":', '"spoilt":');
  Spoiler := retrieveTriviaPartFromRapidAPI(JsonResponse, '"spoilt":', '"unspoilt":');
  Trivia := StringReplace(Trivia, AposReplace, '"');
  Spoiler := StringReplace(Spoiler, AposReplace, '"');

  Result := Chr(13) + Chr(10) + Trivia;
  if (Spoiler <> '') then
    Result := Result + Chr(13) + Chr(10) + 'SPOILERS:' + Chr(13) + Chr(10) + Spoiler;
end;


// ***** analyzes the page containing movie information *****

procedure AnalyzeMoviePage(PageText: string);
var
  Value, Value1, Value2, FullValue, LastValue, originalTitle: string;
  p, Count, updated: Integer;
begin
  // Fixed movie ID extraction
  MovieNumber := TextBetween(PageText, '<meta property="pageId" content="tt', '"');
  if MovieNumber = '' then
    MovieNumber := TextBetween(PageText, '<link rel="canonical" href="https://www.imdb.com/title/tt', '/');
  if MovieNumber = '' then
    MovieNumber := TextBetween(PageText, '<link rel="canonical" href="http://www.imdb.com/title/tt', '/');

  if MovieNumber = '' then
  begin
    ShowMessage('Could not extract movie ID');
    Exit;
  end;

  MovieURL := 'https://www.imdb.com/title/tt' + MovieNumber;

  // URL
  if CanSetField(fieldURL) then
    SetField(fieldURL, MovieURL);

  // Fixed original title extraction
  originalTitle := TextBetween(PageText, '"originalTitleText":{"text":"', '"');
  if originalTitle ='' then originalTitle := TextBefore(PageText, '(original title)', '</h3>');
  if originalTitle ='' then originalTitle := TextBetween(PageText, '<h3 itemprop="name">', '<span class="titlereference-title-year">');

  // Extract year from title
  Value := '';
  p := Pos('(', originalTitle);
  if p > 0 then
  begin
    Value := Copy(originalTitle, p + 1, 4);
    if (StrToInt(Value, 0) > 1900) and (StrToInt(Value, 0) < 2100) then
    begin
      MovieYear := Value;
      originalTitle := Copy(originalTitle, 1, p - 1);
    end;
  end;

  HTMLRemoveTags(originalTitle);
  HTMLDecode(originalTitle);
  originalTitle := RemoveSpaces(originalTitle, true);
  if (originalTitle <> '') and CanSetField(fieldOriginalTitle) then
    SetField(fieldOriginalTitle, FullTrim(originalTitle));

  if CanSetField(fieldYear) and (MovieYear <> '') then
    SetField(fieldYear, MovieYear);

  // Fixed picture extraction
  if CanSetPicture then
  begin
    Value := TextBetween(PageText, '<meta property="og:image" content="', '"');
    if Value <> '' then
    begin
      GetPicture(Value);
    end;
  end;

  // Fixed director extraction
  if CanSetField(fieldDirector) then
  begin
    Value := TextBetween(PageText, '>Directors</a></li>', '</ul>');
    if Value = '' then
      Value := TextBetween(PageText, '>Director</a></li>', '</ul>');

    FullValue := '';
    Value2 := TextBetween(Value, '<a href="/name/', '</a>');
    while Value2 <> '' do
    begin
      Value := RemainingText;
      Value2 := TextAfter(Value2, '>');
      if FullValue <> '' then
        FullValue := FullValue + ', ';
      FullValue := FullValue + Value2;
      Value2 := TextBetween(Value, '<a href="/name/', '</a>');
    end;
    HTMLDecode(FullValue);
    FullValue := RemoveSpaces(FullValue, true);
    SetField(fieldDirector, FullValue);
  end;

  // Fixed actors extraction
  if CanSetField(fieldActors) then
  begin
    if GetOption('AllActors') = 0 then
    begin
      FullValue := TextBetween(PageText, '<div data-testid="title-cast-item"', '</div>');
      HTMLRemoveTags(FullValue);
      HTMLDecode(FullValue);
      FullValue := RemoveSpaces(FullValue, true);
    end
    else
    begin
      FullValue := '';
      Value := FullTrim(TextBetween(PageText, '<section data-testid="title-cast"', '</section>'));
      if Value <> '' then
      begin
        Count := 0;
        p := StrToInt(GetParam('MaxActors'), 10);
        case GetOption('ActorsLayout') of
          0, 1:
            while Pos('<div data-testid="title-cast-item"', Value) > 0 do
            begin
              Value2 := TextBetween(Value, '<div data-testid="title-cast-item"', '</div>');
              Value := RemainingText;
              if FullValue <> '' then
                FullValue := FullValue + #13#10;
              Value2 := FullTrim(TextBetween(Value2, '>', '<'));
              HTMLRemoveTags(Value2);
              Value2 := RemoveSpaces(Value2, true);
              if Value2 <> '' then
              begin
                FullValue := FullValue + Value2;
                Count := Count + 1;
              end;
              if (Count = p) and (GetOption('AllActors') = 2) then
              begin
                Break;
              end;
            end;
          2, 3, 4:
            while Pos('<div data-testid="title-cast-item"', Value) > 0 do
            begin
              Value2 := TextBetween(Value, '<div data-testid="title-cast-item"', '</div>');
              Value := RemainingText;
              if FullValue <> '' then
                FullValue := FullValue + #13#10;
              Value2 := FullTrim(TextBetween(Value2, '>', '<'));
              HTMLRemoveTags(Value2);
              Value2 := RemoveSpaces(Value2, true);
              if Value2 <> '' then
              begin
                FullValue := FullValue + Value2;
                Value2 := FullTrim(TextBetween(RemainingText, '<span data-testid="title-cast-item__characters"', '</span>'));
                HTMLRemoveTags(Value2);
                Value2 := RemoveSpaces(Value2, true);
                if Value2 <> '' then
                begin
                  if GetOption('ActorsLayout') = 4 then
                  begin
                    FullValue := FullValue + ' ... ' + Value2;
                  end
                  else
                  begin
                    FullValue := FullValue + ' (as ' + Value2 + ')';
                  end;
                end;
                Count := Count + 1;
                if (Count = p) and (GetOption('AllActors') = 2) then
                begin
                  Break;
                end;
              end;
            end;
        end;
        HTMLRemoveTags(FullValue);
        HTMLDecode(FullValue);
        case GetOption('ActorsLayout') of
          0, 2:
            begin
              FullValue := StringReplace(FullValue, #13#10, ', ');
            end;
        end;
      end;
    end;
    SetField(fieldActors, FullValue);
  end;

  // Fixed composer extraction
  if CanSetField(fieldComposer) then
  begin
    Value := TextBetween(PageText, '>Composer</a></li>', '</ul>');
    FullValue := '';
    Value2 := TextBetween(Value, '<a href="/name/', '</a>');
    while Value2 <> '' do
    begin
      Value := RemainingText;
      Value2 := TextAfter(Value2, '>');
      if FullValue <> '' then
        FullValue := FullValue + ', ';
      FullValue := FullValue + Value2;
      Value2 := TextBetween(Value, '<a href="/name/', '</a>');
    end;
    HTMLDecode(FullValue);
    FullValue := RemoveSpaces(FullValue, true);
    SetField(fieldComposer, FullValue);
  end;

  //Country
  if CanSetField(fieldCountry) then
  begin
    SetField(fieldCountry, ImportList(PageText, GetOption('MultipleValuesCountry'), '<td class="ipl-zebra-list__label">Country</td>'));
  end;
  //Category
  if CanSetField(fieldCategory) then
  begin
    SetField(fieldCategory, ImportList(PageText, GetOption('MultipleValuesCategory'), '<td class="ipl-zebra-list__label">Genres</td>'));
  end;
  // Language
  if CanSetField(fieldLanguages) then
  begin
    SetField(fieldLanguages, ImportList(PageText, GetOption('MultipleValuesLanguages'), '<td class="ipl-zebra-list__label">Language</td>'));
  end;
  // Audio Format
  if CanSetField(fieldAudioFormat) then
  begin
    SetField(fieldAudioFormat, ImportList(PageText, GetOption('MultipleValuesAudioFormat'), '<td class="ipl-zebra-list__label">Sound Mix</td>'));
  end;
  // Aspect Ratio
  begin
    Value := '';
    Value := TextBetween(PageText, '<td class="ipl-zebra-list__label">Aspect Ratio</td>', '</li>');
    HTMLRemoveTags(Value);
    HTMLDecode(Value);
    Value := RemoveSpaces(Value, true);
    if (CanSetField(fieldVideoFormat)) and (GetOption('AspectRatio') = 1) then
      SetField(fieldVideoFormat, Value);
    if (CanSetField(fieldResolution)) and (GetOption('AspectRatio') = 2) then
      SetField(fieldResolution, Value);
  end;
  // Description
  if CanSetField(fieldDescription) then
  begin
    Value := TextBetween(PageText, '<div data-testid="plot"', '</div>');
    if Value = '' then
      Value := TextBetween(PageText, '<div class="ipc-html-content-inner-div"', '</div>');

    if Value = '' then
      Value := TextBetween(PageText, '<span data-testid="plot-l"', '</span>');

    HTMLRemoveTags(Value);
    HTMLDecode(Value);
    Value := RemoveSpaces(Value, true);
    SetField(fieldDescription, Value);
  end;
  // Length
  if CanSetField(fieldLength) then
  begin
    Value := TextBetween(PageText, '<li role="presentation" data-testid="title-techspec_runtime"', '</li>');
    Value := TextBetween(Value, '>', '<');
    Value := TextBefore(Value, ' min', '');
    HTMLRemoveTags(Value);
    Value := RemoveSpaces(Value, true);
    if Value <> '' then
    begin
      SetField(fieldLength, Value);
    end;
  end;

  // Producer
  if CanSetField(fieldProducer) then
  begin
    Value := TextBetween(PageText, '>Producers</a></li>', '</ul>');
    FullValue := '';
    Value2 := TextBetween(Value, '<a href="/name/', '</a>');
    while Value2 <> '' do
    begin
      Value := RemainingText;
      Value2 := TextAfter(Value2, '>');
      if FullValue <> '' then
        FullValue := FullValue + ', ';
      HTMLRemoveTags(Value2);
      FullValue := FullValue + RemoveSpaces(Value2, true);
      Value2 := TextBetween(Value, '<a href="/name/', '</a>');
    end;
    HTMLDecode(FullValue);
    SetField(fieldProducer, FullValue);
  end;

  // Writer
  if CanSetField(fieldWriter) then
  begin
    Value := TextBetween(PageText, '>Writers</a></li>', '</ul>');
    FullValue := '';
    Value2 := TextBetween(Value, '<a href="/name/', '</a>');
    while Value2 <> '' do
    begin
      Value := RemainingText;
      Value2 := TextAfter(Value2, '>');
      if FullValue <> '' then
        FullValue := FullValue + ', ';
      HTMLRemoveTags(Value2);
      FullValue := FullValue + RemoveSpaces(Value2, true);
      Value2 := TextBetween(Value, '<a href="/name/', '</a>');
    end;
    HTMLDecode(FullValue);
    SetField(fieldWriter, FullValue);
  end;

  // AKA Name
  if CanSetField(fieldTranslatedTitle) then
  begin
    updated := 0;
    case GetOption('TranslatedTitle') of
      1:
        begin
          if (originalTitle <> '') and (originalTitle <> GetField(fieldOriginalTitle)) then
          begin
            SetField(fieldTranslatedTitle, originalTitle);
            updated := 1;
          end;
        end;
      2:
        begin
          Count := 0;
          LastValue := '';
          FullValue := ConvertToASCII(GetPage(MovieURL+'/releaseinfo/#akas'));
          FullValue := TextBetween(FullValue, '<div data-testid="sub-section-akas"', '</div></ul></div>');
          PickTreeClear;
          PickTreeAdd('Select the translated title', '');
          while Fullvalue <> '' do
          begin
            Value2 := TextBetween(FullValue, '<span class="ipc-metadata-list-item__label" aria-disabled="false">', '</span>');  //country
            Value := TextBetween(FullValue, '<span class="ipc-metadata-list-item__list-content-item" aria-disabled="false">', '</span>');   //title
            HTMLDecode(Value2);
            HTMLDecode(Value);
            if (Pos(AKACountry(), Value2) > 0) and (Value <> originalTitle) then
            begin
              LastValue := Value;
              Count := Count + 1;
              if (Count = 1) and (GetOption('BatchMode') > 0) then
              begin
                Break;
              end
              PickTreeAdd(Value, Value);
            end;
            FullValue := TextAfter(FullValue, '</ul>');
          end;
          if Count = 1 then
          begin
            SetField(fieldTranslatedTitle, LastValue);
            updated := 1;
          end else
          if Count > 1 then
          begin
            if PickTreeExec(Value) then
            begin
              SetField(fieldTranslatedTitle, Value);
              updated := 1;
            end;
          end;
        end;
      3:
        begin
          if (originalTitle <> '') and (originalTitle <> GetField(fieldOriginalTitle)) then
          begin
            SetField(fieldTranslatedTitle, FullTrim(originalTitle));
            updated := 1;
          end;
        end;
      4:
        if (GetParam('RapidAPIKey') = '') then
          ShowMessage('If you set TranslatedTitle option to 4 then you must set also a valid RapidAPIKey in parameters');
    end;
    if (updated = 0) and (GetOption('TranslatedTitle') > 0) and (GetParam('RapidAPIKey') <> '') then
      retrieveTitlesFromRapidAPI();
  end;

  // Comments
  if CanSetField(fieldComments) then
  begin
    case GetOption('CommentType') of
      0, 1:
        begin
          Value2 := '';
          p := 0;
          FullValue := ConvertToASCII(GetPage(MovieURL+'/reviews'));
          FullValue := TextAfter(FullValue, '<section class="ipc-page-section ipc-page-section--base ipc-page-section--sp-pageMargin">');
          while FullValue <> '' do
          begin
            Value := TextBetween(FullValue, '<article','</article>');
            if Value = '' then
            begin
              Break;
            end;
            Value1 := TextBetween(Value, '<div class="ipc-html-content-inner-div" role="presentation">','</div>');
            Value1 := StringReplace(Value1, #13#10, ' ');
            Value1 := StringReplace(Value1, '<br/><br/>', #13#10);
            Value1 := StringReplace(Value1, '<br/>', #13#10);
            HtmlRemoveTags(Value1);
            Value1 := FullTrim(Value1);
            if Value1 = '' then
            begin
              FullValue := TextAfter(FullValue, '</article>');
              Continue;
            end;
            if GetOption('CommentType') = 1 then
            begin
              p := p + 1;
              Value2 := Value2 + inttostr(p) + '. ';
            end;
            Value2 := Value2 + TextBetween(Value, '<h3 class="ipc-title__text">','</h3>');
            Value2 := Value2 + ' (by ' + TextAfter (TextBetween(Value, 'data-testid="author-link"','</a>'),'>');
            Value2 := Value2 + #32 + 'on ' + TextBetween(Value, '<li role="presentation" class="ipc-inline-list__item review-date">', '</li>') + ')' ;
            Value2 := Value2 + #13#10 + #13#10 + Value1;
            if (GetOption('CommentType') = 0) or (p = 10) then
            begin
              Break;
            end;
            FullValue := TextAfter(FullValue, '</article>');
            if FullValue <> '' then
            begin
              Value2 := Value2 +  #13#10 + #13#10;
            end;
          end;
          HTMLRemoveTags(Value2);
          HTMLDecode(Value2);
          SetField(fieldComments, Value2);
        end;
      2:
        begin
          SetField(fieldComments, '');
        end;
    end;
  end;
  // TagLine
  if GetOption('GetTagline') > 0 then
  begin
    Value := TextBetween(PageText, '<div data-testid="storyline-taglines"', '</div>');
    HTMLRemoveTags(Value);
    HTMLDecode(Value);
    if Value <> '' then
    begin
      if StrGet(Value, 1) <> '"' then
        Value := '"' + Value + '"';
      case GetOption('GetTagline') of
        1:
          begin
            if GetField(fieldDescription) <> '' then
              Value := Value + #13#10 + #13#10 + GetField(fieldDescription);
            SetField(fieldDescription, Value);
          end;
        2:
          begin
            if GetField(fieldComments) <> '' then
              Value := Value + #13#10 + #13#10 + GetField(fieldComments);
            SetField(fieldComments, Value);
          end;
      end;
    end;
  end;
  // Trivia
  if GetOption('Trivia') > 0 then
  begin
    case GetOption('Trivia') of
      1,2:
        begin
          sleep(50);
          Value := MovieUrl;
          FullValue := ConvertToASCII(GetPage(Value+'/trivia'));
          Value := TextBetween(FullValue, '<div class="ipc-html-content-inner-div"', '</div>');
          if Value <> '' then
          begin
            Value := StringReplace(Value, #13#10, '');
            while Pos('  ', Value) > 0 do
              Value := StringReplace(Value, '  ', '');
            HTMLRemoveTags(Value);
            HTMLDecode(Value);
          end;
        end;
      3,4:
        if (GetParam('RapidAPIKey') <> '') then
          Value := retrieveTriviaFromRapidAPI()
        else
          Value := '';
    end;
    if Value <> '' then
    begin
      case GetOption('Trivia') of
        1,3:
          begin
            if GetField(fieldDescription) <> '' then
              Value := GetField(fieldDescription) + #13#10 + #13#10 + 'IMDB TRIVIA: ' + Trim(Value)
            else
              Value :=  'IMDB TRIVIA: ' + Value;
            SetField(fieldDescription, Value);
          end;
        2,4:
          begin
            if GetField(fieldComments) <> '' then
              Value := GetField(fieldComments) + #13#10 + #13#10 + 'IMDB TRIVIA: ' + Trim(Value)
            else
              Value :=  'IMDB TRIVIA: ' + Value;
            SetField(fieldComments, Value);
          end;
      end;
    end;
  end;
  // Awards
  if (GetOption('Awards') > 0) then
  begin
    ImportAwards();
  end;
  // Rating
  if CanSetField(fieldRating) then
  begin
    Value := TextBetween(PageText, '<span data-testid="ratingValue"', '</span>');
    if Value = '' then
      Value := TextBetween(PageText, '<div data-testid="hero-rating-bar__aggregate-rating__score"', '</div>');
    if Value <> '' then
      if (GetOption('RoundRating') = 1) then
        SetField(fieldRating, IntToStr(Round(StrToFloat(Value))))
      else
        SetField(fieldRating, Value);
  end;
  if GetOption('UserRatings') > 0 then
    begin
    Value := TextBetween(PageText, 'data-testid="ratingCount"', '</div>');
    Value := TextAfter(Value, '>');
    Value := TextBefore(Value, '<', '');
      if Value <> '' then
        Value := Copy(GetField(fieldRating), Pos('(', GetField(fieldRating)) + 1, Pos(')', GetField(fieldRating)) - Pos('(', GetField(fieldRating)) - 1) + '' + Value;
      if (GetOption('UserRatings') = 1) and (Value <> '') and (CanSetField(fieldsubtitles)) then
        SetField(fieldsubtitles, Value);
      if (GetOption('UserRatings') = 2) and (Value <> '') then
        SetField(fieldComments, GetField(fieldComments) + #13#10 + #13#10 + Value);
    end;
  // Classification
  if CanSetField(fieldCertification) then
  begin
    Value := TextBetween(PageText, '<li data-testid="storyline-certificate"', '</li>');
    Value := TextBetween(Value, '>', '<');
    if Value <> '' then
      SetField(fieldCertification, Value);
  end;
  // MPAA rating
  if (GetOption('MPAA') > 0) then
  begin
     Value := TextBetween(PageText, '<li role="presentation" data-testid="title-details-certificates"', '</li>');
     Value := TextBetween(Value, '>', '<');
     if Value <> '' then
     begin
      if GetOption('MPAA') = 1 then
        SetField(fieldMediaType, Value)
      else
        SetField(fieldComments, GetField(fieldComments) + #13#10 + #13#10 + 'Rated ' + Value);
     end;
  end;
end;

// ***** Imports lists like Genre, Country, etc. depending of the selected option *****

function ImportList(PageText: string; MultipleValues: Integer; StartTag: string): string;
var
  Value, Value2: string;
begin
  if MultipleValues = 0 then
  begin
    Value := TextBetween(PageText, StartTag, '</a>');
    Value2 := TextAfter(Value, '<li class="ipl-inline-list__item">');
  end
  else if MultipleValues = 3 then
  begin
    Exit;
  end
  else
  begin
    Value := TextBetween(PageText, StartTag, '</ul>');
    Value2 := TextBefore(Value, 'See more &raquo;</a>', '');
    if Value2 = '' then
      Value2 := Value;
    Value2 := TextAfter(Value2, '">');
    Value2 := StringReplace(Value2, '<li class="ipl-inline-list__item">', ' / ');
  end;
  HTMLRemoveTags(Value2);
  HTMLDecode(Value2);
  Value2 := RemoveSpaces(Value2, true);
  if Pos('/ ', Value2) = 1 then
  begin
    Delete(Value2, 1, 2);
  end;
  if MultipleValues = 1 then
  begin
    Value2 := StringReplace(Value2, ' / ', ', ');
  end;
  Result := Value2;
end;

// ***** functions to import the different pictures kinds, depending of the option selected by user *****

//Import small picture from IMDB movie main page
function ImportSmallPicture(PageText: string): Boolean;
var
  Value: string;
begin
  Result := False;
  Value := TextBetween(PageText, 'alt="Poster"', '/>');
  if (Value <> '') then
  begin
    Value := TextBetween(Value, 'src="', '"');
    if Value <> '' then
    begin
      GetPicture(Value);
      Result := True;
    end;
  end;
end;

//Import large image, building link from the small image of the movie page
function ImportLargePicture(PageText: string): Boolean;
var
  Value: string;
begin
  Result := False;
  Value := TextBetween(PageText, 'alt="Poster"', '/>');
  if (Value <> '') then
  begin
    Value := TextBetween(Value, 'src="', '"');
    if Value <> '' then
    begin
      Value := TextBefore(Value, '._', '') + '._V1_SY' + GetParam('LargePictureHeight') + '_AL_.jpg';
      GetPicture(Value);
      Result := True;
    end;
  end;
end;

//Image not available, import "No Poster Available" icon
function ImportPictureNotAvailable(PageText: string): Boolean;
var
  Value: string;
begin
  Result := False;
  Value := TextBetween(PageText, '<div class="photo">', '</div>');
  if (Value <> '') and (Pos('"Poster Not Submitted"', Value) > 0) then
  begin
    Value := TextBetween(Value, 'src="', '"');
    if Value <> '' then
    begin
      GetPicture(Value);
      Result := True;
    end;
  end;
end;

//Image from DVD Details Page
function ImportDvdDetailsPicture: Boolean;
var
  Value, PageText: string;
begin
  Result := False;
  PageText := ConvertToASCII(GetPage(MovieUrl+'/dvd'));
  Value := TextBefore(PageText, '.jpg alt="', '<table class="dvd_section" cellpadding="10"><tr>');
  if Value <> '' then
  begin
    Value := TextBetween(Value, '<a href="', '">');
    if Value <> '' then
      Result := ImportFromAmazonRedirect('https://www.imdb.com' + Value);
  end;
end;

//Image from Merchandising Links (/sales) Page
function ImportMerchandisingPicture: Boolean;
var
  Value, PageText: string;
begin
  Result := False;
  PageText := ConvertToASCII(GetPage(MovieUrl+'/sales'));
  Value := TextBefore(PageText, '.jpg" width=', '<td class=w_rowtable_colcover><a href="');
  if Value <> '' then
  begin
    Value := TextBefore(Value, '"><img', '');
    if Value <> '' then
      Result := ImportFromAmazonRedirect('https://www.imdb.com' + Value);
  end;
end;

function ImportFromAmazonRedirect(Url: string): Boolean;
var
  Value, PageText: string;
begin
  Result := False;
  PageText := ConvertToASCII(GetPage(Url));
  Value := TextBetween(PageText, '<td id="prodImageCell"', '" id="prodImage"');
  Value := StringReplace(TextAfter(Value, ' src="'), '_AA240', '');
  if Value <> '' then
  begin
    GetPicture(Value);
    Result := True;
  end;
end;

// ***** Gets summaries for the movie, based on the plot outline given in parameter (that contains the URL to more summaries) *****

function ImportSummary(PlotText: string): string;
var
  Address, Value, PageText, Longest: string;
begin
  Address := TextBetween(PlotText, '<a class="tn15more inline" href="', '" ');
  if (Address = '') or (GetOption('DescriptionSelection') = 0) then
  begin
    Result := FullTrim(TextBefore(PlotText, '<a class="tn15more inline"', ''));
    if Result = '' then
      Result := FullTrim(PlotText);
    HTMLRemoveTags(Result);
    HTMLDecode(Result);
  end else
  begin
    PageText := ConvertToASCII(GetPage('https://www.imdb.com' + Address));
    PickListClear;
    Longest := '';
    PageText := TextBetween(PageText, '<ul class="ipl-zebra-list" id="plot-summaries-content">', '</ul>');
    Value := TextBetween(PageText, '<p>', '</p>');
    PageText := RemainingText;
    while Value <> '' do
    begin
      Value := FullTrim(StringReplace(Value, #13#10, ' '));
      Value := StringReplace(Value, '<br>', #13#10);
      HTMLRemoveTags(Value);
      HTMLDecode(Value);
      while Pos('  ', Value) > 0 do
        Value := StringReplace(Value, '  ', ' ');
      if Length(Value) > Length(Longest) then
        Longest := Value;
      PickListAdd(FullTrim(Value));
      Value := TextBetween(PageText, '<p>', '</p>');
      PageText := RemainingText;
    end;
    if (GetOption('BatchMode') > 0) or (GetOption('DescriptionSelection') = 2) then
      Result := Longest
    else
    begin
      if not PickListExec('Select a description for "' + GetField(fieldOriginalTitle) + '"', Result) then
        Result := '';
    end;
  end;
end;

// Import awards
procedure ImportAwards;
var
  IndexPage: TStringList;
  PageText, FullValue, Block, Value, Row, OldOutcome, TmpOutcome, Outcome, Details, AwardShow, PageText1: string;
  AwardShowYear, AwardYear, Result, Award, Category: string;
begin
  sleep(50);

// pageText: all the page
// Block: a single AwardShow with one or more Awards
// Row: single Award
// all these variables are reduced after main data are extracted

  PageText := ConvertToASCII(GetPage(MovieUrl+'/awards'));
  Block := TextBetween(PageText, '<h3 class="ipc-title__text"><span id="', '</section>');
  while (Block <> '') do
  begin
    // entire AwardShow
    PageText := RemainingText;

    AwardShow := TextBetween(Block, '>', '</span>');
    HTMLRemoveTags(AwardShow);
    HTMLDecode(AwardShow);
    AwardShow := FullTrim(AwardShow);
    AwardShow := StringReplace(AwardShow, #13, '');
    AwardShow := StringReplace(AwardShow, #10, '');
    // note: #13#10 is added now because AwardShow Year is missing
    FullValue := FullValue + #32 + AwardShow;
    AwardShowYear := '';
    OldOutcome := '';

    while (pos('<div class="ipc-metadata-list-summary-item__tc">', Block) > 0) do
    begin
      // single Award of main AwardShow
      Row := TextBetween(Block, '<div class="ipc-metadata-list-summary-item__tc">', '</div>');
      Block := RemainingText;

      Outcome := TextBetween(Row, '>', '<');
      Row := RemainingText;
      Award:= TextBetween(Row, '>', '<');

      Row := RemainingText;
      If Award <> '' then
        Award := StringReplace(Award, '<br />', #32);

      Category := '<' + TextBetween(Row, 'awardCategoryName', '<');
      Row := '<' + RemainingText;

      Details := '<' + TextBetween(Row, 'role="presentation"', '</a>');
      Row := '<' + RemainingText;

      HTMLRemoveTags(Outcome);
      HTMLDecode(Outcome);
      HTMLRemoveTags(Award);
      HTMLDecode(Award);
      HTMLRemoveTags(Category);
      HTMLDecode(Category);
      HTMLRemoveTags(Details);
      HTMLDecode(Details);
      if Details <> '' then
      begin
        Details := ':' + #32 + Details;
      end;
      Row := StringReplace(Row, '<', ' <');
      HTMLRemoveTags(Row);
      HTMLDecode(Row);
      Row := FullTrim(Row);
      while (pos('  ', Row) > 0) do
      begin
        Row := StringReplace(Row, '  ', ' ');
      end;
      if Row <> '' then
      begin
        Details := Details + '. ' + Row;
      end;

      if OldOutcome <> Outcome then
      begin
        TmpOutcome := Outcome;
        If Outcome <> '' then
        begin
          // note: for backward compatibility there is only a year and that is AwardShow Year
          // After April 2023, iMDB set Year for every award so I retrieve it here (if any) and add to AwardShow only, removing from single Award
          AwardYear := copy(Outcome, 1, 4);
          if ((IntToStr(StrToInt(AwardYear, 0)) = AwardYear) AND (copy(Outcome, 5, 1) = ' ') then
          begin
            Outcome := copy(Outcome, 5, (length(Outcome) - 4));
            if (AwardShowYear = '') then
            begin
              AwardShowYear := AwardYear;
              FullValue := FullValue + #32 + AwardShowYear + #13#10;
            end;
          end
          else if (AwardShowYear = '') then
          begin
            FullValue := FullValue + #13#10;
            AwardShowYear := ' ';  // no AwardShowYear at all
          end;
          if OldOutcome <> '' then
          begin
            FullValue := FullValue + #13#10;
          end;
          FullValue := FullValue + #32 + #32 + FullTrim(Outcome) + #13#10;
        end;
        OldOutcome := TmpOutcome;
      end;

      FullValue := FullValue + #32 + #32 + #32;
      If Category <> '' then
        FullValue := FullValue + Category + #32;

      If Award <> '' then
      begin
        Award := StringReplace(Award, #13, '');
        Award := StringReplace(Award, #10, '');
        Award := FullTrim(Award);
        Award := StringReplace(Award, '  ', '');
        FullValue := FullValue + Award;
      end;

      If Details <> '' then
      begin
        Award := StringReplace(Details, #13, '');
        Award := StringReplace(Details, #10, '');
        Award := FullTrim(Details);

        FullValue := FullValue + Details;
      end;
      FullValue := FullValue + #13#10;
    end;

    FullValue := FullValue + #13#10;
    Block := TextBetween(PageText, '<h3 class="ipc-title__text"><span id="', '</section>');
  end;

  if FullValue <> '' then
    case GetOption('Awards') of
      1:
        begin
          if GetField(fieldDescription) <> '' then
            Value := GetField(fieldDescription) + #13#10 + #13#10 + 'AWARDS: ' + #13#10 + FullValue
          else
            Value := 'AWARDS: ' + FullValue;
          SetField(fieldDescription, Value);
        end;
      2:
        begin
          if GetField(fieldComments) <> '' then
            Value := GetField(fieldComments) + #13#10 + #13#10 + 'AWARDS: ' + #13#10 + FullValue
          else
            Value := 'AWARDS: ' + FullValue;
          SetField(fieldComments, Value);
        end;
  end;
end;

// ***** beginning of the program *****

begin
  // Check StringUtils1 version and update if < version 7
  if StringUtils1_Version < 7 then
    begin
      if ShowWarning('Old version of file "Stringutils1.pas" detected: v'+IntToStr(StringUtils1_Version)+#13#10+'The script requires at least version 7.'+#13#10+'Download and install latest version now ?') = True then
        begin
          UpdateFile := TStringList.Create;
          UpdateFile.Text := GetPage('http://update.antp.be/amc/scripts/StringUtils1.pas');
          UpdateFile.SaveToFile(dirScripts + 'StringUtils1.pas');
          UpdateFile.Free;
          ShowInformation('StringUtils1 has been updated. Please restart IMDB script now. Thank you.');
          Exit;
        end
      else
        begin
          ShowInformation('You can download latest version of "StringUtils1.pas" using script "update scripts" or via http://update.antp.be/amc/scripts');
          Exit;
        end;
    end;
  // Check for current AMC version
  if CheckVersion(4,2,3) then
  begin
    // bug with default values it seems ?
    if GetParam('MaxActors') = '' then
    begin
      SetParam('MaxActors', '10');
    end;
    if GetParam('UserCountry') = '' then
    begin
      SetParam('UserCountry', 'United States');
    end;
    if GetParam('LargePictureHeight') = '' then
    begin
      SetParam('LargePictureHeight', '720');
    end;
    MovieYear := GetField(fieldYear);
    MovieName := '';
    if GetOption('BatchMode') = 2 then
    begin
      MovieName := GetField(fieldURL);
      if Pos('imdb.com', MovieName) = 0 then
        MovieName := '';
    end;
    if MovieName = '' then
      MovieName := GetField(fieldOriginalTitle);
    if MovieName = '' then
      MovieName := GetField(fieldTranslatedTitle);
    if GetOption('BatchMode') = 0 then
    begin
      if not Input('IMDB Import', 'Enter the title or the IMDB URL of the movie:', MovieName) then
        Exit;
    end
    else
      Sleep(500);
    if MovieName <> '' then
    begin
      if Pos('imdb.com', MovieName) > 0 then
      begin
        MovieName := StringReplace(MovieName, '//imdb.com', '//www.imdb.com');
        MovieName := StringReplace(MovieName, 'http://', 'https://');
        AnalyzeResultsPage(MovieName)
      end else
      if RegExprSetExec('tt[0-9]+', moviename) then
        AnalyzeResultsPage('https://www.imdb.com/title/' + MovieName + '/reference')
      else
      begin
        if CheckVersion(4,2,2) then
          MovieName := StringReplace(MovieName, '&', 'and')
        else
          MovieName := UTF8Encode(StringReplace(MovieName, '&', 'and'));
        if (GetOption('BatchMode') > 0) or (GetOption('PopularSearches') = 1) then
          AnalyzeResultsPage(PopularTitleSearchURL + UrlEncode(MovieName))
        else
          AnalyzeResultsPage(FullTitleSearchURL + UrlEncode(MovieName));
      end;
    end;
  end
  else
  begin
     ShowInformation('This script requires a newer version of Ant Movie Catalog, at least the version 4.2.3')
  end;
end.
Post Reply