Where if you have a scanner, you could scan all your film's, and the database could tell you if you have any missing. (from the media labels)
I share a house with a few people, so this would come in useful.
Not sure how hard it would be?


Code: Select all
// GETINFO SCRIPTING
// UPC BASED IMDB (US) import - click "Editor" tab to change options
{
To change the options, go to the "GetOption"
and "CanSetField" functions
}
(***************************************************
* Movie importation script for: *
* IMDB (US), http://us.imdb.com *
* *
* (c) 2002-2005 Antoine Potten *
* software@antp.be *
* *
* Based on the script made for version 3.x by *
* Antoine Potten, Danny Falkov, Kai Blankenhorn, *
* lboregard, Ork, Trekkie, Youri Heijnen *
* *
* For use with Ant Movie Catalog 3.4.3 *
* www.antp.be/software/moviecatalog *
* *
* This program is free software; you can *
* redistribute it and/or modify it under the *
* terms of the GNU General Public License as *
* published by the Free Software Foundation; *
* either version 2 of the License, or (at your *
* option) any later version. *
***************************************************)
program IMDB;
// ***** Here you can change the options of the script *****
function GetOption(OptName: string): Integer;
begin
case OptName of
'ImageKind': Result := 2;
{
0=No image
1=IMDB small image, from the main movie page
2=IMDB large image if found easily, else small image
3=First search for Amazon large image, then IMDB large one, then IMDB small image if other failed
4=First search for Amazon large image, then directly take IMDB small image if the first one failed
5=IMDB large image if found easily, else search for Amazon large image, then take IMDB small image if others failed
}
'BatchMode': Result := 0;
{
0=Normal working mode, prompts user when needed
1=Does not display any window, takes the first movie found
}
'PopularSearches': Result := 1;
{
0=Do not use the popular searches page, directly show full search results
1=Show popular searches first, I'll click on "Find more" if needed
}
'ActorsLayout': Result := 0;
{
0=Only actor names, separated by commas
1=Only actor names, separated by linebreaks
2=Actors names with character names between parenthesis separated by commas
3=Actors names with character names between parenthesis separated by linebreaks
4=Actor names like on IMDB page, with "...." and separated by linebreaks
}
'MultipleValuesCountry': Result := 0;
{
0=Only take first value for Country
1=Take full list, separated by commas
2=Take full list, separated by slashes
}
'MultipleValuesCategory': Result := 0;
{
0=Only take first value for Category
1=Take full list, separated by commas
2=Take full list, separated by slashes
}
'MultipleValuesLanguages': Result := 0;
{
0=Only take first value for Languages
1=Take full list, separated by commas
2=Take full list, separated by slashes
}
'DescriptionSelection': Result := 2;
{
0=Take the short summary, from main page (faster)
1=Show a list of available summaries
2=Take the longest summary
}
'GetTagline': Result := 0;
{
0=Do not get tagline
1=Put it in Description field, before the summary
2=Put it in the Comment field, before the comments
}
end;
end;
// Here you can specify which fields can be modified.
// Simply remove a field from the list if it cannot be modified
function CanSetField(fieldID: Integer): Boolean;
begin
case fieldID of
fieldNumber,
fieldMedia,
fieldMediaType,
fieldSource,
fieldDate,
fieldBorrower,
fieldRating,
fieldOriginalTitle,
fieldTranslatedTitle,
fieldDirector,
fieldProducer,
fieldCountry,
fieldCategory,
fieldYear,
fieldLength,
fieldActors,
fieldURL,
fieldDescription,
fieldComments,
fieldVideoFormat,
fieldVideoBitrate,
fieldAudioFormat,
fieldAudioBitrate,
fieldResolution,
fieldFrameRate,
fieldLanguages,
fieldSubtitles,
fieldSize,
fieldDisks: Result := True;
else
Result := False;
end;
end;
var
MovieName: string;
MovieURL: string;
MovieNumber: string;
MovieUPC: string; //UPC ADD IN
var
RemainingText: string;
{
when calling... this variable contains...
TextBefore the text after SearchText
TextBetween the text after AfterText
}
// ***** Like the Pos function, but returns the last occurence instead of the first one *****
/// UPC ADD INS
function FindLine(Pattern: string; List: TStringList; StartAt: Integer): Integer;
var
i: Integer;
begin
Result := -1;
if StartAt < 0 then
StartAt := 0;
for i := StartAt to List.Count-1 do
if Pos(Pattern, List.GetString(i)) <> 0 then
begin
Result := i;
Break;
end;
end;
function AnalyzeUPCPage(Address : string): string;
var
Page : TStringList;
LineNr, BeginPos, EndPos : Integer;
Line, Value : string;
begin
Page := TStringList.Create;
Page.Text := GetPage(Address);
LineNr := FindLine('Description', Page, 0);
Line := Page.GetString(LineNr);
if LineNr > -1 then
begin
BeginPos := LineNr;
if BeginPos > -1 then
BeginPos := BeginPos + 29;
EndPos := pos('</td></tr>', Line);
//if EndPos = 0 then
// EndPos := pos('(', Line);
Value := copy(Line, BeginPos -2, EndPos - BeginPos +2);
HTMLDecode(Value);
Result := Value;
end;
Page.Free;
end;
function GetMovieTitleFromUPC(UPC : string): string;
begin
Result := AnalyzeUPCPage('http://www.upcdatabase.com/item.pl?upc=' + UPC);
end;
function LastPos(ASearch: string; AText: string): Integer;
var
CurPos, PrevPos: Integer;
begin
PrevPos := 0;
CurPos := Pos(ASearch, AText);
while CurPos > 0 do
begin
if PrevPos = 0 then
PrevPos := CurPos
else
PrevPos := PrevPos + CurPos + Length(ASearch) - 1;
Delete(AText, 1, CurPos + Length(ASearch) - 1);
CurPos := Pos(ASearch, AText);
end;
Result := PrevPos;
end;
// *****
{ Returns the text before SearchText, but not before BeginLimit (if it is not empty),
It takes the last occurence of BeginLimit found before the position of SearchText }
function TextBefore(WholeText: string; SearchText: string; BeginLimit: string): string;
var
FoundPos, PrevPos: Integer;
WorkText: string;
begin
Result := '';
FoundPos := Pos(SearchText, WholeText);
if FoundPos = 0 then
Exit;
WorkText := Copy(WholeText, 1, FoundPos - 1);
RemainingText := Copy(WholeText, FoundPos + Length(SearchText), Length(WholeText));
if BeginLimit <> '' then
begin
FoundPos := LastPos(BeginLimit, WorkText);
if FoundPos = 0 then
Exit
else
FoundPos := FoundPos + Length(BeginLimit);
end
else
FoundPos := 1;
Result := Copy(WorkText, FoundPos, Length(WorkText));
end;
// ***** Returns the text after SearchText *****
function TextAfter(WholeText: string; SearchText: string): string;
var
FoundPos: Integer;
begin
Result := '';
FoundPos := Pos(SearchText, WholeText);
if FoundPos = 0 then
Exit;
Result := Copy(WholeText, FoundPos + Length(SearchText), Length(WholeText));
end;
// *****
{ Returns the text between BeforeText and AfterText (without these two strings),
It takes the first AfterText occurence found after the position of BeforeText }
function TextBetween(WholeText: string; BeforeText: string; AfterText: string): string;
var
FoundPos: Integer;
WorkText: string;
begin
Result := '';
FoundPos := Pos(BeforeText, WholeText);
if FoundPos = 0 then
Exit;
WorkText := Copy(WholeText, FoundPos + Length(BeforeText), Length(WholeText));
FoundPos := Pos(AfterText, WorkText);
if FoundPos = 0 then
Exit;
Result := Copy(WorkText, 1, FoundPos - 1);
RemainingText := Copy(WorkText, FoundPos + Length(AfterText), Length(WorkText));
end;
// ***** analyzes the results page that asks to select a movie from a list *****
procedure AnalyzeResultsPage(Address: string);
var
PageText: string;
Value: string;
begin
PageText := GetPage(Address);
if pos('<title>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;
PickTreeClear;
repeat
Value := TextBefore(PageText, '<ol>', '<b>');
if Value <> '' then
begin
HTMLRemoveTags(Value);
HTMLDecode(Value);
PickTreeAdd(Value, '');
end;
Value := TextBetween(PageText, '<ol>', '</ol>');
PageText := RemainingText;
until not AddMovieTitles(Value);
Value := TextBefore(PageText, '"><b>more titles</b></a>', '<a href="');
if Value <> '' then
PickTreeMoreLink('http://us.imdb.com' + Value);
if PickTreeExec(Address) then
AnalyzeResultsPage(Address);
end;
end;
// ***** adds the titles contained in <ol>'s items *****
function AddMovieTitles(List: string): Boolean;
var
Value: string;
Address: string;
begin
Result := False;
Value := TextBetween(List, '<li>', '</li>');
List := RemainingText;
while Value <> '' do
begin
Address := 'http://us.imdb.com' + TextBetween(Value, '<a href="', '">');
HTMLRemoveTags(Value);
HTMLDecode(Value);
PickTreeAdd(Value, Address);
Result := True;
Value := TextBetween(List, '<li>', '</li>');
List := RemainingText;
end;
end;
// ***** analyzes the page containing movie information *****
procedure AnalyzeMoviePage(PageText: string);
var
Value, Value2, Value3, FullValue: string;
begin
MovieNumber := TextBefore(PageText, '"><option>Your Vote', '<select name="');
MovieURL := 'http://us.imdb.com/title/tt' + MovieNumber;
// URL
if CanSetField(fieldURL) then
SetField(fieldURL, MovieURL);
// Original Title & Year
if CanSetField(fieldOriginalTitle) or CanSetField(fieldYear) then
begin
Value := TextBetween(PageText, '<title>', '</title>');
Value2 := TextBefore(Value, ' (', '');
Value := RemainingText;
HTMLDecode(Value2);
if CanSetField(fieldOriginalTitle) then
SetField(fieldOriginalTitle, Value2);
if Pos('/', Value) > 0 then
Value2 := TextBefore(Value, '/', '')
else
Value2 := TextBefore(Value, ')', '');
if CanSetField(fieldYear) then
SetField(fieldYear, Value2);
end;
// Rating
if CanSetField(fieldRating) then
begin
Value := TextBetween(PageText, '/rating-stars/', '/rating-vote/');
Value2 := TextBetween(Value, '<b>', '.');
if StrToInt(Copy(RemainingText, 1, 1), 0) >= 5 then
Value2 := IntToStr(StrToInt(Value2, 0) + 1);
SetField(fieldRating, Value2);
end;
// Picture
case GetOption('ImageKind') of
1: ImportSmallPicture(PageText);
2: if not ImportLargePicture('http://us.imdb.com/gallery/ss/' + MovieNumber) then
ImportSmallPicture(PageText);
3: if not ImportAmazonPicture(PageText) then
if not ImportLargePicture('http://us.imdb.com/gallery/ss/' + MovieNumber) then
ImportSmallPicture(PageText);
4: if not ImportAmazonPicture(PageText) then
ImportSmallPicture(PageText);
5: if not ImportLargePicture('http://us.imdb.com/gallery/ss/' + MovieNumber) then
if not ImportAmazonPicture(PageText) then
ImportSmallPicture(PageText);
end;
// Director
if CanSetField(fieldDirector) then
begin
Value := TextBetween(PageText, '<b class="blackcatheader">Directed by</b>', '</a>');
Value := TextAfter(Value, '">');
HTMLDecode(Value);
SetField(fieldDirector, Value);
end;
// Actors
if CanSetField(fieldActors) then
begin
Value := TextBetween(PageText, 'ast overview', '</div>');
if Value = '' then
Value := TextBetween(PageText, 'redited cast', '</div>');
if Value <> '' then
begin
Value := TextAfter(Value, '</tr> ');
FullValue := '';
case GetOption('ActorsLayout') of
0, 1:
while Pos('<tr>', Value) > 0 do
begin
Value2 := TextBetween(Value, '<tr>', '</tr>');
Value := RemainingText;
if Pos('<a href="fullcredits">(more)</a>', Value2) > 0 then
Break;
if FullValue <> '' then
FullValue := FullValue + ', ';
FullValue := FullValue + TextBefore(Value2, '</td>', '');
end;
2, 3:
while Pos('<tr>', Value) > 0 do
begin
Value2 := TextBetween(Value, '<tr>', '</tr>');
Value := RemainingText;
if Pos('<a href="fullcredits">(more)</a>', Value2) > 0 then
Break;
if FullValue <> '' then
FullValue := FullValue + ', ';
FullValue := FullValue + TextBefore(Value2, '</td>', '');
Value2 := TextBetween(RemainingText, '<td valign="top">', '</td>');
if Value2 <> '' then
FullValue := FullValue + ' (' + Value2 + ')';
end;
4:
begin
FullValue := TextBefore(Value, '</tr><tr><td colspan="2">', '');
if FullValue = '' then
FullValue := Value;
FullValue := StringReplace(FullValue, '</tr>', #13#10);
end;
end;
HTMLRemoveTags(FullValue);
HTMLDecode(FullValue);
case GetOption('ActorsLayout') of
1, 3:
FullValue := StringReplace(FullValue, ', ', #13#10);
end;
SetField(fieldActors, FullValue);
end;
end;
//Country
if CanSetField(fieldCountry) then
begin
SetField(fieldCountry, ImportList(PageText, GetOption('MultipleValuesCountry'), '/Countries/'));
end;
//Category
if CanSetField(fieldCategory) then
begin
SetField(fieldCategory, ImportList(PageText, GetOption('MultipleValuesCategory'), '/Genres/'));
end;
// Language
if CanSetField(fieldLanguages) then
begin
SetField(fieldLanguages, ImportList(PageText, GetOption('MultipleValuesLanguages'), '/Languages/'));
end;
//Description
if CanSetField(fieldDescription) then
begin
Value := TextBetween(PageText, '<b class="ch">Plot Outline:</b>', '<br><br>');
if Value = '' then
Value := TextBetween(PageText, '<b class="ch">Plot Summary:</b>', '<br><br>');
if Value <> '' then
SetField(fieldDescription, ImportSummary(Value));
end;
// Comments
if CanSetField(fieldComments) then
begin
Value := TextAfter(PageText, '/comments">');
if Value <> '' then
begin
Value := TextBetween(Value, '<p>', '</p>');
Value := StringReplace(Value, #13#10, ' ');
Value := StringReplace(Value, '<br>', #13#10);
HTMLRemoveTags(Value);
HTMLDecode(Value);
Value := Trim(Value);
while Pos(' ', Value) > 0 do
Value := StringReplace(Value, ' ', ' ');
while Pos(#13#10, Value) = 1 do
Delete(Value, 1, 2);
SetField(fieldComments, Value);
end;
end;
// Length
if CanSetField(fieldLength) then
begin
Value := TextBetween(PageText, '<b class="ch">Runtime:</b>' + #13#10, ' ');
if Value <> '' then
begin
if Pos(':', Value) > 0 then
SetField(fieldLength, TextAfter(Value, ':'))
else
SetField(fieldLength, Value);
end;
end;
// TagLine
if GetOption('GetTagline') > 0 then
begin
Value := TextBetween(PageText, 'Tagline:</b>', #13);
if Pos('<a', Value) > 0 then
Value := TextBefore(Value, '<a', '');
HTMLRemoveTags(Value);
HTMLDecode(Value);
Value := Trim(Value);
if Value <> '' then
begin
Value := '"' + Value + '"';
case GetOption('GetTagline') of
1:
if CanSetField(fieldDescription) then
SetField(fieldDescription, Value + #13#10 + GetField(fieldDescription));
2:
if CanSetField(fieldComments) then
SetField(fieldComments, Value + #13#10 + GetField(fieldComments));
end;
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, '">');
end
else
begin
Value := TextBetween(PageText, StartTag, #13#10);
Value2 := TextBefore(Value, ' <a href="/rg', '');
if Value2 <> '' then
Value := Value2;
Value2 := TextAfter(Value, '">');
HTMLRemoveTags(Value2);
if MultipleValues = 1 then
Value2 := StringReplace(Value2, ' / ', ', ');
end;
HTMLDecode(Value2);
Result := Value2;
end;
// ***** functions to import the different pictures kinds, depending of the option selected by user *****
function ImportSmallPicture(PageText: string): Boolean;
var
Value: string;
begin
Result := False;
Value := TextBetween(PageText, '<img border="0" alt="cover" src="', '"');
if Value <> '' then
begin
GetPicture(Value, False);
Result := True;
end;
end;
function ImportLargePicture(Address: string): Boolean;
var
Value, Value2: string;
begin
Result := True;
Value := GetPage(Address);
if SearchForLargePicture(Value, 'Onesheet_text', False) then
Exit;
if SearchForLargePicture(Value, 'Onesheet', False) then
Exit;
if SearchForLargePicture(Value, 'poster', False) then
Exit;
if SearchForLargePicture(Value, 'usposter', False) then
Exit;
if SearchForLargePicture(Value, 'text', True) then
Exit;
if SearchForLargePicture(Value, 'pos01', True) then
Exit;
if SearchForLargePicture(Value, 'KeyArt', True) then
Exit;
Address := TextBetween(Value, 'There are ' + #13#10 + '<a href="', '">');
if Address <> '' then
Result := ImportLargePicture('http://us.imdb.com' + Address)
else
Result := False;
end;
function SearchForLargePicture(PageText: string; Name: string; PartialName: Boolean): Boolean;
var
Value: string;
begin
Result := False;
if PartialName then
begin
Value := TextBefore(PageText, Name + '.jpg', '/');
if Value = '' then
Exit
else
Name := Value + Name;
end;
Value := TextBefore(PageText, 'th-' + Name + '.jpg', 'src="');
if Value <> '' then
begin
GetPicture(Value + Name + '.jpg', False);
Result := True;
end;
end;
function ImportAmazonPicture(PageText: string): Boolean;
var
Value, Value2: string;
begin
Result := False;
Value := TextBefore(PageText, '" title="DVD available', '<a href="');
if Value = '' then
Exit;
PageText := GetPage('http://us.imdb.com' + Value);
if Pos('unable to find exact matches', PageText) > 0 then
Exit;
if Pos('You may also be interested in these items...', PageText) > 0 then
PageText := TextBefore(PageText, 'You may also be interested in these items...', '');
Value := TextBefore(PageText, 'TZZZZZZZ.jpg', '<img src="');
if Value = '' then
Value := TextBefore(PageText, 'THUMBZZZ.jpg', '<img src="');
if Value <> '' then
begin
GetPicture(Value + 'LZZZZZZZ.jpg', False);
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, Value2, PageText, Longest: string;
begin
Address := TextBetween(PlotText, '<a href="/rg/title-tease/plotsummary', '">(more)</a>');
if (Address = '') or (GetOption('DescriptionSelection') = 0) then
begin
Result := Trim(TextBefore(PlotText, '<a href="/rg', ''));
if Result = '' then
Result := Trim(PlotText);
HTMLRemoveTags(Result);
HTMLDecode(Result);
end
else
begin
PageText := GetPage('http://us.imdb.com/rg/title-tease/plotsummary' + Address);
PickListClear;
Longest := '';
Value := TextBetween(PageText, '<p class="plotpar">', '</p>');
PageText := RemainingText;
while Value <> '' do
begin
Value := 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(Trim(Value));
Value := TextBetween(PageText, '<p class="plotpar">', '</p>');
PageText := RemainingText;
end;
if (GetOption('BatchMode') = 1) or (GetOption('DescriptionSelection') = 2) then
Result := Longest
else
begin
if not PickListExec('Select a description for "' + GetField(fieldOriginalTitle) + '"', Result) then
Result := '';
end;
end;
end;
// ***** beginning of the program *****
begin
if CheckVersion(3,4,3) then
begin
//MovieName := GetField(fieldOriginalTitle);
//if MovieName = '' then
// MovieName := GetField(fieldTranslatedTitle);
if GetOption('BatchMode') = 0 then
begin
if not Input('UPC Import', 'Enter the UPC of the movie:', MovieUPC) then
Exit;
MovieName := GetMovieTitleFromUPC(MovieUPC);
//ShowMessage('Detected Movie Title : ' + MovieName);
if (MovieName = '') or (MovieName = '(unknown)') then
Input('UPC Import', 'Upc Unknown : Please Type the Title.', MovieName);
end;
if MovieName <> '' then
begin
if Pos('imdb.com', MovieName) > 0 then
AnalyzeResultsPage(MovieName)
else
begin
MovieName := StringReplace(MovieName, '&', 'and');
if (GetOption('BatchMode') = 1) or (GetOption('PopularSearches') = 1) then
AnalyzeResultsPage('http://us.imdb.com/find?tt=1;q=' + UrlEncode(MovieName))
else
AnalyzeResultsPage('http://us.imdb.com/find?more=tt;q=' + UrlEncode(MovieName));
end;
DisplayResults;
end;
end
else
ShowMessage('This script requires a newer version of Ant Movie Catalog (at least the version 3.4.3)');
end.