(***************************************************
Ant Movie Catalog importation script
www.antp.be/software/moviecatalog/
[Infos]
Authors=HappyTalk
Title=Auto.TV.Com
Description=Automated TV series import from tv.com
Site=http://www.tv.com
Language=EN
Version=1.07.01.16
Requires=3.5.0
Comments=inspired by the tvtome script by Alex Iribarren & original tv.com script by nalf75014. ||I added full automation using intelligent soundex name searching and caching|as much info as possible. It will happily grab 1,000's of entries unmonitored |if suitably named eg:|series.xxx.episode Where xxx is anything|You may change . seperator to other using options||1) Unchecks items it modifies, so run first pass using a full automation mode|then again for checked items , not found in an interactive mode.||2) Puts title grabbed from tv.com in 'TranslatedTitle' field for fast |human cross checking that correct eps were auto-grabbed.||When running script remember when it hits Results Dialog (if turned on) |to press 'save all' so it will run automated and not re-prompt you.||Code has other commented out lines I used sometimes that may be of use, |uncomment at will to aid automation. Heavily road tested.||Cheers
License=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. |
GetInfo=1
[Options]
SortEpisodePicker=0|1|1=Yes|0=No
AutoMode=1|0|0= Prompt with menu|1= Prompt for series and episode match on every search|2= Prompt for series only when changes|3= Never Prompt for series|4= Never prompt for series or episode matches
Seperator=0|0|0=. (dot)|1=- (hyphen/minus)|2= (space)|3=_ (underscore)|4=( (open bracket)
NamingStyle=1|0|0=series.episode / series.xxx.episode|1=series.episode.xxx / series.xxx.episode.xxx
MatchMethod=0|0|0=Alpha+SoundEx|1=Alpha Only|2=SoundEx Only|3=AlphaNum Only|4=AlphaNum+SoundEx
***************************************************)
program Auto_TV_Com;
uses
AutoUtils;
var
EpName, EpNumber, SeName: string;
MovieName: string;
arraySeName, CalcSeName, Prev_CalcSEname, Prev_SeAddress, Sep : String;
temp1 : String;
AutoMode, NamingStyle, MatchMethod: Integer;
arrayEpName, arrayEpAddr, arrayEpAlpha, arrayEpSoundEX : array of string;
arrayEpCnt, arrayEpSize: Integer;
function AutoMenu() : Integer;
var
Sel: string;
begin
PickTreeClear;
PickTreeAdd('1. Prompt for series and episode match on every search', '1');
PickTreeAdd('2. Prompt for series only when changes', '2');
PickTreeAdd('3. Never Prompt for series', '3');
PickTreeAdd('4. Never prompt for series or episode matches', '4');
PickTreeExec(Sel);
result := StrToInt(Sel, 0);
end;
//The letters A,E,I,O,U,Y,H,W and other characters are not coded.
function GetSepOption() : String;
begin
result := '.'; //default
Case GetOption('Seperator') of
0 : result := '.';
1 : result := '-';
2 : result := ' ';
3 : result := '_';
4 : result := '(';
end;
end;
procedure AnalyzeEpListing(Address: string);
var
Page: TStringList;
LineNr, StartPos, EndLine, MatchCnt, i, EpIX: Integer;
Line, EpTitle, EpNr, Conv_EpName: string;
begin
if (SeName <> arraySeName) then // populate array with episodes,address
begin
Page := TStringList.Create;
Address := Address + 'episode_listings.html';
Page.Text := PostPage(Address, URLEncode('season=0'));
ArrayEpCnt := 0;
LineNr := FindLine('Click here to continue to TV.com', Page, 0);
if LineNr > -1 then
begin
Line := Page.GetString(LineNr);
Page.Free;
AnalyzeResults(SeName);
Exit;
end
// fill array with all episodes
LineNr := FindLine('
', Page, LineNr);
repeat
LineNr := FindLine('', 0, ' '' then
begin
arrayEpName[ArrayEpCnt] := EpTitle;
arrayEpAddr[ArrayEpCnt] := LineTextBetween('"', 0, '">', 0, Line, False);
if AutoMode > 1 then
begin
if (MatchMethod > 2) then
begin
arrayEpAlpha[ArrayEpCnt] := ConvertAlphaNum(EpTitle); //Only Match Alpha & Num chars (To use must uncomment other occurence further on as well!)
end else
arrayEpAlpha[ArrayEpCnt] := ConvertAlpha(EpTitle); //Only match alpha chars (ignore punctuation, numbers etc)
if (MatchMethod <> 1) and (MatchMethod <> 3) then arrayEpSoundEX[ArrayEpCnt] := ConvertSoundEx(EpTitle);
end;
ArrayEpCnt := ArrayEpCnt + 1;
end;
end
LineNr := LineNr + 1;
until (LineNr > EndLine) or (ArrayEpCnt >= arrayEpSize);
Page.Free;
arraySeName := SeName; // series currently stored
end;
if ArrayEpCnt = 0 then exit; //no matches
EpIX := 0;
// pass 1: store only matches in picker
if (AutoMode > 1) then //1 => don't do computer search, user will select
begin
PickTreeClear;
PickTreeAdd('Episode matches for "' + EpName + '" (' + GetField(fieldSource) + ')', '');
MatchCnt := 0;
if (MatchMethod > 2) then
begin
Conv_EpName := ConvertAlphaNum(EpName) //Only Match Alpha & Num chars
end else
Conv_EpName := ConvertAlpha(EpName); //Only match alpha chars (ignore punctuation, numbers etc)
if (MatchMethod <> 2) then
begin
for i := 0 to ArrayEpCnt - 1 do
begin
// if pos(Conv_EpName, arrayEpAlpha[i]) <> 0 then //look for ep name within tv.com one (as tv.com may have (aka other name) )
if (Conv_EpName = arrayEpAlpha[i]) then //exact match tv.com name
begin
PickTreeAdd(arrayEpName[i] + ' (' + IntToStr(i+1) + ')', IntToStr(i));
MatchCnt := MatchCnt + 1;
EpIX := i; //store match, if only 1 match we will use this value
end;
end;
end;
if (MatchMethod <> 1) and (MatchMethod <> 3) then
begin
Conv_EpName := ConvertSoundEx(EpName); //no exact matches try soundex compare
if (MatchCnt = 0) then //no exact matches try more liberal soundex compare
for i := 0 to ArrayEpCnt - 1 do
begin
if pos(Conv_EpName, arrayEpSoundEx[i]) <> 0 then
begin
PickTreeAdd(arrayEpName[i] + ' (' + IntToStr(i+1) + ')', IntToStr(i));
MatchCnt := MatchCnt + 1;
EpIX := i;
end;
end;
if (MatchCnt = 0) then //no exact matches try more liberal soundex compare
for i := 0 to ArrayEpCnt - 1 do
begin
if SoundExIn(Conv_EpName, arrayEpSoundEx[i]) then //find words in any order
begin
PickTreeAdd(arrayEpName[i] + ' (' + IntToStr(i+1) + ')', IntToStr(i));
MatchCnt := MatchCnt + 1;
EpIX := i;
end;
end;
end;
end;
if (AutoMode < 4) then // 4 => dont prompt user
begin
if (MatchCnt > 1) then
if PickTreeExec(EpNr) then //select from matches or if cancel select from all
begin
EpIX := StrToInt(EpNr, 0);
MatchCnt := 1;
end else
MatchCnt := 0;
//pass 2: store all in picker for user choice if no matches or cancel in pass1
if (MatchCnt = 0) then
begin
PickTreeClear;
PickTreeAdd('All episodes for "' + EpName + '" (' + GetField(fieldSource) + ')', '');
for i := 0 to ArrayEpCnt - 1 do //add (count) after Ep Name so after sort still have epnum
PickTreeAdd(arrayEpName[i] + ' (' + IntToStr(i+1) + ')', IntToStr(i));
If GetOption('SortEpisodePicker') = 1 then PickTreeSort; //sort will random order if have same name eg 'episodis weird
if PickTreeExec(EpNr) then //user select from all episodes
begin
EpIX := StrToInt(EpNr, 0);
MatchCnt := 1;
end;
end;
end;
if (MatchCnt = 1) then
begin
EpName := arrayEpName[EpIX];
AnalyzeEpisodePage(arrayEpAddr[EpIX]);
end;
end;
procedure AnalyzeEpisodePage(Address: string);
var
Line, TempStr, GuestStars, EpNr, Season, EpTitle: string;
BeginPos, Tmp, StartPos: Integer;
Page: TStringList;
LineNr: Integer;
begin
Page := TStringList.Create;
Page.Text := GetPage(Address);
// URL - OK
SetField(fieldURL, Address);
// Set Trans title = Episode Name got from tv.com
if EpName <> '' then
SetField(fieldTranslatedTitle, EpName);
// First Aired + Production Code - OK
LineNr := FindLine('First Aired:', Page, 0);
if LineNr > -1 then
begin
Line := Page.GetString(LineNr);
CutAfter(Line,'');
SetField(fieldYear, copy(Line, pos(', ',Line)+2, 4));
SetField(fieldComments,'Production Code: ' + copy(Line, pos('Code: ', Line) + 6, 4))
end;
// Rating - OK
LineNr := FindLine('', Page, 0);
if LineNr > -1 then
begin
Line := Page.GetString(LineNr);
TempStr := copy(Line, pos('">', Line) + 2, 3);
SetField(fieldRating, TempStr);
end;
// Writer - OK
LineNr := FindLine('Writer:', Page, 0);
if LineNr > -1 then
begin
Line := Page.GetString(LineNr + 3);
CutAfter(Line,'>');
TempStr := copy(Line, 1, pos('',Line)-1);
HTMLRemoveTags(TempStr);
if TempStr <> '' then SetField(fieldProducer, 'Writer: ' + TempStr);
end;
// Director - OK
LineNr := FindLine('Director:', Page, 0);
if LineNr > -1 then
begin
Line := Page.GetString(LineNr + 3);
CutAfter(Line,'>');
TempStr := copy(Line, 1, pos('',Line)-1);
HTMLRemoveTags(TempStr);
SetField(fieldDirector, TempStr);
end;
// Description - OK
Line := PageTextBetween('class="f-11 f-bold">Watch Video', 2, '', -1, Page, 0, true);
if (Line = '') then
Line := PageTextBetween(' ',3,' ', -1, Page, 0, true);
if (Line <> '') then
SetField(fieldDescription, Line);
// Cast
// Guest Stars
LineNr := FindLine('Guest Star:', Page, 0);
if LineNr > -1 then
begin
Line := Page.GetString(LineNr + 3);
TempStr := Trim(Line);
HTMLRemoveTags(TempStr);
repeat
Tmp := Length(TempStr);
TempStr := StringReplace(TempStr, ' ', ' ');
until Length(TempStr) = Tmp;
TempStr := StringReplace(TempStr, ' ,', ',');
TempStr := StringReplace(TempStr, ' ', '');
GuestStars := TempStr;
end;
LineNr := FindLine('Star:', Page, 0);
if LineNr > -1 then
begin
Line := Page.GetString(LineNr + 3);
TempStr := Trim(Line);
HTMLRemoveTags(TempStr);
repeat
Tmp := Length(TempStr);
TempStr := StringReplace(TempStr, ' ', ' ');
until Length(TempStr) = Tmp;
TempStr := StringReplace(TempStr, ' ,', ',');
TempStr := StringReplace(TempStr, ' ', '');
SetField(fieldActors, TempStr + #13#10 + 'Guest stars: ' + GuestStars);
end;
SetField(fieldChecked, ''); // uncheck any items we set
Page.Free;
end;
procedure CutAfter(var Str: string; Pattern: string);
begin
Str := Copy(str, Pos(Pattern, Str) + Length(Pattern), Length(Str));
end;
function StringReplaceAll(S, Old, New: string): string;
begin
while Pos(Old, S) > 0 do
S := StringReplace(S, Old, New);
Result := S;
end;
procedure AnalyzeResults(var Search: string);
var
Page: TStringList;
LineNr, StartPos, EndLine, SeCnt: Integer;
Line, Tmp, Address, SeDesc: string;
begin
if (SeName = arraySeName) then // and (Prev_SeAddress <> '')
begin
AnalyzeEpListing(''); //Address
end else
begin
Page := TStringList.Create;
Page.Text := GetPage('http://www.tv.com/search.php?qs=' + URLEncode(Search) + '&type=11&stype=all&tag=search%3Bbutton');
LineNr := FindLine(' -1 then // if no results found quit out
begin
EndLine := FindLine(' ', Page, LineNr);
PickTreeClear;
PickTreeAdd('Series Matches for "' + Search + '" (' + GetField(fieldOriginalTitle) + ')', '');
repeat
LineNr := FindLine(' Show:', Page, LineNr); //LineNr := FindLine('', 0, Page, LineNr, False);
SeDesc := StripSpace(Line, 2, true);
if (SeDesc <> '') then // or (GetOption('OnlySeriesWithDescription') = 0)
begin
Address := LineTextBetween('"http', -4, 'summary.html?', 0, Line, False); //new
if Address <> '' then
begin
PickTreeAdd(SeDesc, Address);
SeCnt := SeCnt + 1;
end;
end;
LineNr := LineNr + 1;
end;
until (LineNr < 0) or (LineNr > EndLine) or ((AutoMode >= 3) and (SeCnt > 0));
end;
if (SeCnt > 0) then // matches found
begin
if (AutoMode <= 2) then //and (SeCnt > 1) if 1 entry or AF > 2 => use 1st entry
if not PickTreeExec(Address) then exit; // press cancel => quit proc
AnalyzeEpListing(Address);
end else
SeName := ''; //clear series name as is no good
end;
end;
begin
if CheckVersion(3,5,0) then
begin
if AutoMode = 0 then
begin
AutoMode := (GetOption('AutoMode'));
NamingStyle := (GetOption('NamingStyle'));
MatchMethod := (GetOption('MatchMethod'));
if AutoMode = 0 then AutoMode := AutoMenu();
if AutoMode = 0 then exit;
arrayEpSize := 1000; // max number of episodes to store at once, increase if required
SetArrayLength(arrayEpName, arrayEpSize);
SetArrayLength(arrayEpAddr, arrayEpSize);
SetArrayLength(arrayEpSoundEX, arrayEpSize);
SetArrayLength(arrayEpAlpha, arrayEpSize);
Sep := GetSepOption;
end;
CalcSeName := GetField(fieldOriginalTitle);
CalcSeName := nposLeft(Sep, CalcSeName, 1, false);
if CalcSeName = '' then CalcSeName := Prev_CalcSeName; // if no series name found keep last name
if (CalcSeName = '') or (CalcSeName <> Prev_CalcSeName) or (AutoMode = 1) then // or (Prev_SeName = '')
begin //only prompt new series name if changed or AF=1
SeName := CalcSeName; //computer guess at series
if (AutoMode <= 2) then // use calc name if AutoMode >= 3
if not (Input('TV.com Import', 'Series Name for ' + GetField(fieldOriginalTitle), SeName)) then exit; //SeName := '';
end;
if SeName <> '' then
begin
EpName := GetField(fieldOriginalTitle);
if (NamingStyle = 0) then EpName := nposRight(Sep, EpName, 1, true); // get string after last dot eg (Lost.1x01.Pilot = Pilot)
if (NamingStyle = 1) then EpName := nposLeft(Sep, nposRight(Sep, EpName, 2, true), 1, false); // get string after second last dot & before last eg (Lost.1x01.Pilot.01 = Pilot)
AnalyzeResults(SeName);
end;
Prev_CalcSeName := CalcSeName;
end else
ShowMessage('This script requires a newer version of Ant Movie Catalog (at least the version 3.5.0)');
exit;
end. |