const
 script_name='RusKino';
 language='Russian';
 version=9;
 author='Vlad';
 MinProgramBuild=5500;

 PostReferer = 'post';
 CRLF = #13#10;   

 PERSON_DIRECTOR = 1;
 PERSON_WRITER   = 2;
 PERSON_ACTOR    = 3;
 PERSON_COMPOSER = 4;

 IMAGE_PHOTO = 6;

 InvalidChars = '~!@#$%^&*()_+`-"№;%:?*<>{}''\|/[]., ';


var
	persons_count: integer;
	persons: array of string;
	imdb_codes: array of string;
	imdb_code, person_code: string;
	name, code, year, description: string;
	person, BasicURL, biography, trivia, character, birth_date, death_date, birthplace, birth_name, salary, height, original_name, person_site_url: string;
	photo_url: string;
	monthes: array [1..12] of string;
	prefixes: array [1..13] of string;
	person_height: integer;
	is_photos_present: boolean;
	DownloadPersonBiography, DownloadPersonAdditionalInfo: boolean;
	MaxPhotosCount: integer;

  SearchRes, InternalURL, BaseImageURL, ActorInfo: string;

function GetStr(str: String; s1: String; s2: String): String;
var
  I: Integer;
  J: Integer;
begin
  // Вырезает кусок строки между s1 и s2
	Result := '';
	I := Pos(LowerCase(s1), LowerCase(str));
	if I > 0 then
	begin
		J := MyPos(LowerCase(s2), LowerCase(str), I + Length(s1));
		if J > 0 then
  		Result := Copy(str, I + Length(s1), J - I - Length(s1));
	end;
end;

function ClearExtraBlankCharacters(text: string): string;
begin
	// Clear all extra blank charackters
	while (length(text) > 0) and (ord(text[1]) in [1..32]) do
		delete(text, 1, 1);
	while (length(text) > 0) and (ord(text[length(text)]) in [1..32]) do
		delete(text, length(text), 1);
	Result := text;
end;



//==================================================================================================
//  Вспомогательные функции
//==================================================================================================

 
//==================================================================================================
function Parse(var Str: string; const Separator: string): string;
 var
  Position: Integer;
 begin
  Position:=Pos(Separator, Str);
  if Position=0
   then   begin
           Result:=Str;
           Str:=''
          end
   else   begin
           Result:=Copy(Str, 1, Position-1);
           Delete(Str, 1, Position+Length(Separator)-1)
          end
 end;
              
                                                 
//==================================================================================================
function SeparateLeft(const Value, Delimiter: string): string;
 var
  Index: Integer;
 begin
  Index:=Pos(Delimiter, Value);
  if Index=0
   then   Result:=Value
   else   Result:=Copy(Value, 1, Index-1)
 end;  

    


//==================================================================================================
//  Удаление непечатных символов с разных сторон имени, HTML-декодирование, удаление "*" из имени,
//  вырезание "левых" скобок
//==================================================================================================
function CleanName(Name: string): string;
 var
  Start ,
  Finish,
  Step  : Integer;
 begin
  Start:=Pos('(', Name);
  Finish:=Pos(')', Name);
  if (Start>0) and (Finish>0)
   then   begin
           Delete(Name, Start, Finish-Start+1);
           Name:=ReplaceStr(Name, '  ', ' ', -1)
          end;

  Result:=Trim(ReplaceStr(DecodeHTML(Trim(Name)), '*', '', -1));

  Finish:=0;
  for Step:=Length(Result) downto 1
   do   if Pos(Result[Step], InvalidChars)>0
         then   Finish:=Step
         else   Break;
  if Finish<>0
   then   Delete(Result, Finish, Length(Name)-Finish+1)
 end;

                                             
//==================================================================================================
function CleanText(Text: string): string;
 begin
  Result:=ReplaceStr(Trim(Text), CRLF, '', -1);      
  Result:=ReplaceStr(Result, '<br /> ', CRLF, -1);
  Result:=ReplaceStr(Result, '<br />', CRLF, -1);
  Result:=Trim(DecodeHTML(Result))
 end;    


//==================================================================================================
procedure AnalyzeRoles(Text: string);
 var
  Temp: string;
  Kind: Integer;
 begin
  Parse(Text, '<b>');
  Kind:=GetRoleKind(Trim(Parse(Text, '</b>')));
  if Kind=-1
   then   Exit;
  Parse(Text, '<a href=');
  while Text<>''
   do   begin
         Temp:=Parse(Text, '<td width=48% valign=top align="');
         AnalyzeMovie(Temp, Kind)
        end
 end;     


//==================================================================================================
function GetRoleKind(Role: string): Integer;
 begin
  if Role='режиссер'
   then   Result:=PERSON_DIRECTOR
   else   if Role='сценарист'
           then   Result:=PERSON_WRITER
           else   if (Role='актер') or (Role='озвучка') or (Role='актриса') or (Role='озвучание')
                   then   Result:=PERSON_ACTOR
//                   else   if Role=''
  //                         then   Result:=PERSON_COMPOSER
                           else   Result:=-1
 end;

                                                     
//==================================================================================================
procedure AnalyzeMovie(Data: string; Kind: Integer);
 var
  Movie,
  Role ,
  Code ,
  Year : string;
 begin
  //  Определение, если есть, ссылки на фильм
  if Pos('/mov/', Data)>0
   then   begin
           Parse(Data, '/mov/');
           Code:=Trim(Parse(Data, '"'))
          end;

  //  Определение названия фильма
  Parse(Data, '<b>');
  Movie:=CleanName(Parse(Data, '</b>'));

  //  Определение года
  if Pos('<b class="tText" style="margin-left: 0; margin-right: 1">', Data)>0
   then   begin
           Parse(Data, '<b class="tText" style="margin-left: 0; margin-right: 1">');
           Year:=Parse(Data, '</b>');
          end;

  //  Определение роли
  if Kind=PERSON_ACTOR
   then   begin
           Parse(Data, 'роль: <b>');
           Role:=CleanText(Parse(Data, '</b>'))
          end
   else   Role:='';

  SetMovieName(Movie, Role, Kind, Code, Year)
 end;


//==================================================================================================
function SetPhoto(Photo: string): Boolean;
 begin
  Result:=Pos(Photo, ActorInfo)>0;
  if Result
   then   SetImageName('', BaseImageURL+Photo, '', IMAGE_PHOTO)
 end;
 




//==================================================================================================
//  Экспортируемые из скрипта функции
//==================================================================================================

             
//==================================================================================================
//  01. Формирование URL для поиска актёра на сайте по названию
//==================================================================================================
function GetSearchURLbyName(PersonName: string): string;
 begin
	Result:=Format('http://ruskino.ru/art/search?v=1&word=%s&tip=0', [PersonName])
 end;


//==================================================================================================
//  02. Загрузка html-документа по поисковой ссылке
//==================================================================================================
function DownloadSearchURL(URL: string): Integer;
 begin          
  SearchRes:=DownloadURLWithReferer(URL, PostReferer);
  if (SearchRes<>'-1') and (GetResponseCode=200)
   then   Result:=SelectActor
   else   Result:=-1
 end;    

                                                                                                  
//==================================================================================================
//  03. Парсинг страницы поисков с актёрами
//==================================================================================================
function SelectActor: Integer;
 var
  Actor, Code, temp, small_photo, description : string; 
 begin
	Result:=0;
	while (Pos('<tr><td class="itemTitr"', SearchRes)>0) do begin
		temp := GetStr(SearchRes, '<tr><td class="itemTitr"', '</tr>');
		Code := ParseString(temp, ' href="http://ruskino.ru/art/(\d+)', 1);
		Actor := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(temp, '<h3>', '</h3>'))));
		small_photo := GetStr(temp, ' src="', '"');
		if small_photo <> '' then
			small_photo := 'http://ruskino.ru' + small_photo;
		description := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(temp, '<div align="text">', '</div>'))));
		if (Actor<>'') and (Code<>'') then begin
			Inc(Result);
			SetSearchResult2(Actor, Code, '', '', description, small_photo);
		end;
		delete(SearchRes, 1, Pos('<tr><td class="itemTitr"', SearchRes));
	end;
 end;


//==================================================================================================
//  04. Формирование URL с информацией об актёре по коду актёра в формате сайта 
//  images_only - признак закачки только картинок
//==================================================================================================
function GetPersonURL(Code: string; Images_Only: Boolean): string;
 begin
  if Code<>''
   then   Result:='http://ruskino.ru/art/'+Code
   else   Result:=''
 end;     

procedure ExtractMovies(text: String; mode: Integer);
var
	s, title, code, year, character: String;
	i, j: Integer;
begin
	i := Pos('<td class="itemTitr"', text);
	while i>0 do begin
		i := MyPos('<td class="itemTitr"', text, i + 1);
		j := MyPos('</tr>', text, i+1);
		s := copy(text, i, j-i);
		code := ParseString(s, ' href="http://ruskino.ru/mov/(\d+)', 1);
		title := GetStr(s, ' href="http://ruskino.ru/mov/', '/a>');
		title := GetStr(title, '>', '<');
		title := ClearExtraBlankCharacters(DecodeHTML(title));
		year := GetStr(s, '"itemNameTitle2Titr">', '<');
		character := '';
		if (mode = 3) then begin
			character := GetStr(s, 'роль: ', '</');
			if character = '' then
				character := GetStr(s, ' class="rolabout">', '</');
			character := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(character)));
		end;
		if (title <> '') then
			SetMovieName(title, character, mode, code, year);
		delete(text, 1, j);
		i := Pos('<td class="itemTitr"', text);
	end;	
end;

//==================================================================================================
//  05. Получение данных по фильму по URL
//  images_only - признак закачки только картинок
//==================================================================================================
function GetInfo(URL: string; Images_Only: Boolean): string;
 var
  Temp, day, month, year, s: string;
  ActorIndex, i, j: Integer;
  sl: TStringList;
 begin
  InternalURL:=URL;
  BaseImageURL:=ReplaceStr(InternalURL, 'art', 'artist', -1);
  Person_Code:=URL;
  Parse(Person_Code, '/art/');
  person_site_url:=GetPersonSiteURL(Person_Code);

  //  Проверка на ошибки
  if URL=''
   then   begin
           Result:='-1';
           Exit;
          end;
  if Images_Only
   then   begin
           Result:='';
           Exit
          end;

  //  Скачивание главной страницы
  Result:=DownloadURL(URL);
  if (Result='-1') or (GetResponseCode<>200)
   then   Exit;
  ActorInfo:=Result;
  all := Result;
  
  Person := GetStr(all, '<h2>', '</h2>');
  Person := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(Person)));

  //  Получение биографии
  biography := GetStr(all, '<div class="itemAnnot" align="left">', '</div>');
  biography := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(biography)));
  
  //дата рождения
  sl := TStringList.Create;
  sl.Text := biography;
  temp := '';
  for i := 0 to sl.Count - 1 do begin
	if (Pos('Родился ', sl[i]) > 0) then begin
		temp := sl[i];
		s := 'Родился ';
	end
	else if (Pos('Родилась ', sl[i]) > 0) then begin
		temp := sl[i];
		s := 'Родилась ';
	end;
  end;
  day := ParseString(temp, s+'(\d+)', 1);
  month := ParseString(temp, s+'\d+ (.*?) \d+', 1);
  year := ParseString(temp, s+'.*? (\d+)', 1);
  i:=1;
  while (i<=12) and (monthes[i]<>month) do
	i:=i+1;
  if (i<=12) and (year<>'') and (day <> '') then
	birth_date:=IntToStr(i)+format('/%s/%s', [day, year])
  else if (year <> '') then
	birth_date := year;
	
  //дата смерти
  temp := '';
  for i := 0 to sl.Count - 1 do begin
	if (Pos('Ушел из жизни ', sl[i]) > 0) then begin
		temp := sl[i];
		s := 'Ушел из жизни ';
	end
	else if (Pos('Ушла из жизни ', sl[i]) > 0) then begin
		temp := sl[i];
		s := 'Ушла из жизни ';
	end;
  end;
  day := ParseString(temp, s + '(\d+)', 1);
  month := ParseString(temp, s + '\d+ (.*?) \d+г.', 1);
  year := ParseString(temp, s + '.*? (\d+)г.', 1);
  i:=1;
  while (i<=12) and (monthes[i]<>month) do
	i:=i+1;
  if (i<=12) and (year<>'') and (day <> '') then
	death_date:=IntToStr(i)+format('/%s/%s', [day, year])
  else if (year <> '') then
	death_date := year;

  
  //фильмография
  
  //актер
  i := Pos('<h2><b>актер</b></h2>', all);
  if i = 0 then
	i := Pos('<h2><b>актриса</b></h2>', all);
  if i>0 then begin
	j := MyPos('<td class="line" colspan="3">', all, i+1);
	if j = 0 then
		j := MyPos('</table>', all, i+1);
	temp := copy(all, i, j-i);
	ExtractMovies(temp, 3);
  end;
  
  //режиссер
  i := Pos('<h2><b>режиссер</b></h2>', all);
  if i>0 then begin
	j := MyPos('<td class="line" colspan="3">', all, i+1);
	if j = 0 then
		j := MyPos('</table>', all, i+1);
	temp := copy(all, i, j-i);
	ExtractMovies(temp, 1);	
  end;
  
  //сценарист
  i := Pos('<h2><b>сценарист</b></h2>', all);
  if i>0 then begin
	j := MyPos('<td class="line" colspan="3">', all, i+1);
	if j = 0 then
		j := MyPos('</table>', all, i+1);
	temp := copy(all, i, j-i);
	ExtractMovies(temp, 2);	
  end;
  
  //композитор
  i := Pos('<h2><b>композитор</b></h2>', all);
  if i>0 then begin
	j := MyPos('<td class="line" colspan="3">', all, i+1);
	if j = 0 then
		j := MyPos('</table>', all, i+1);
	temp := copy(all, i, j-i);
	ExtractMovies(temp, 4);	
  end;

 end;


//==================================================================================================
//  07. Загрузка картинок
//==================================================================================================
procedure GetImages;
 var
  Temp   ,
  Photo  : string;
  Counter: Integer;
 begin
  Counter:=1;
  //  Получение фотографии актёра
  if not SetPhoto('/sov_pv_portret.jpg')
   then   if not SetPhoto('/sov_md_portret.jpg')
           then   if not SetPhoto('/pv_portret.jpg')
                   then   if not SetPhoto('/md_portret.jpg')
                           then   Counter:=0;

  //  Получение других фотографий актёра
  Temp:=ActorInfo;
  while Temp<>''
   do   begin       
         if Counter>=MaxPhotosCount
          then   Break;
         Parse(Temp, 'photo/pv_');
         Photo:=Parse(Temp, '"');
         if Photo<>''
          then   begin
                  Inc(Counter);
                  SetImageName('', BaseImageURL+'/photo/'+Photo, '', IMAGE_PHOTO)
                 end
        end
 end;

                                                                                                
//==================================================================================================
//  08. Сохранение картинки по ее URL в выбранный файл
//==================================================================================================
function SavePhoto(URL, FileName: string): Boolean;
 var
  Stream: TFileStream;
  Temp  : string;
 begin          
  Temp:=DownloadURL(URL);
  if (Length(Temp)>0) and (Temp<>'-1') and (GetResponseCode=200)
   then   try
						Stream:=TFileStream.Create(FileName, fmCreate);
    				Stream.Write(Temp, Length(Temp));
    				Stream.Free;
						Result:=True;
	         except
	          Result:=False
	         end
   else   Result:=False
 end;


//==================================================================================================
//  Получение ссылки на страницу фильма по коду в формате сайта
//==================================================================================================
function GetMovieSiteURL(Code: string): string;
 begin
	if Code=''
   then   Result:=''
   else   Result:='http://ruskino.ru/mov/'+Code
 end;


//==================================================================================================
//  Получение ссылки на страницу актёра по коду в формате сайта
//==================================================================================================
function GetPersonSiteURL(Code: string): string;
 begin
	if Code=''
   then  Result:=''
   else  Result:='http://ruskino.ru/art/'+Code
 end;


begin

  monthes[1]:='января';
  monthes[2]:='февраля';
  monthes[3]:='марта';
  monthes[4]:='апреля';
  monthes[5]:='мая';
  monthes[6]:='июня';
  monthes[7]:='июля';
  monthes[8]:='августа';
  monthes[9]:='сентября';
  monthes[10]:='октября';
  monthes[11]:='ноября';
  monthes[12]:='декабря';

end.
