const
 script_name='RusKino';
 language='Russian';
 version=14;
 author='Vlad';
	MinProgramBuild=5500;
 
 PostReferer = 'post';

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

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


var
	DownloadMovieBigCover, DownloadMovieShortCast, DownloadMovieFullCast, 
	DownloadMovieBigDescription, DownloadMovieComments, 
	DownloadMovieStudios,	DownloadMovieAwards, DownloadMovieEarnings, 
	DownloadMovieAdditionalInfo, DownloadMovieSeasonsList, DownloadMovieTechnicalInfo: boolean;
	MaxShotsCount, MaxPostersCount: integer;
	
 duration: Integer;
 imdb_rating, rating: Double;
 title, year, country, description, imdb_code, movie_code, movie_site_url,
 original_title, mpaa, mpaa_rating,
 InternalURL, BaseImageURL, MovieInfo: string;   //  результаты поиска фильмов
 resolution, barcode, aspect_ratio, features, media_format, video_codec: string;
 ShotsPage, ShotName, PostersPage: String;
	AlreadyAddedPeople: TStringList;



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;

                   
//==================================================================================================
//  Добавление крупных скриншотов с отдельной страницы
//==================================================================================================
procedure GetLargeScreenShots(Temp: string; MaxImgCnt, ImgMode: Integer;);
 var
  ImgName,
  Desc   : string;
  Counter: Integer;
 begin
	Counter:=0;
	while (Pos(ShotName, Temp)>0) and (Counter < MaxImgCnt) do begin
        ImgName := GetStr(Temp, ShotName, '"');
        if ImgName<>'' then begin
           Inc(Counter);
           SetImageName('', BaseImageURL+'/kadr/'+ImgName+'.jpg', '', ImgMode)
        end;
		delete(Temp, 1, Pos(ShotName, Temp));
	end;
 end;


//==================================================================================================
//  Добавление мелких скриншотов с главной страницы фильма
//==================================================================================================
procedure GetSmallScreenShots;
 var
  Temp   ,
  ImgName: string;
  Counter: Integer;
 begin
  Counter:=0;
  Temp:=MovieInfo;
  while (Pos('/kadr/', Temp)>0) and (Counter < MaxShotsCount) do begin
	ImgName := GetStr(Temp, '/kadr/', '"');
		if ImgName<>'' then begin
            Inc(Counter);
            SetImageName('', BaseImageURL+'/kadr/'+ImgName, '', IMAGE_SCREENSHOT)
        end;
	end;
 end;

//==================================================================================================
//  01-а. Получение название фильма по штрих-коду
//==================================================================================================
function GetMovieNameByUPC(barcode: string): string;
var
	url, s2, s3, res: string;
	i, j: integer;
begin
	res:='';
	url:=format('http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&SubscriptionId=0J0N83PT9M72BYH98YR2&Operation=ItemSearch&Keywords=%s&SearchIndex=Video&ResponseGroup=Request,Images,Tracks,ItemAttributes', [barcode]);
	url:=ReplaceStr(url, ' ', '+', -1);
	all:=DownloadURL(url);
	//search image by title
	i:=pos('<Item>', all);
	while (i>0) and (res='') do begin
		j:=MyPos('</Item>', all, i+1);
		if j>0 then begin
			s2:=copy(all, i, j-i);
			s3:=ParseString(s2, '<Title>(.*?) \(.*\)</Title>', 1);
			if s3='' then
				s3:=ParseString(s2, '<Title>(.*?)</Title>', 1);
			if s3<>'' then
				res:=s3;
		end;
		i:=MyPos('<Item>', all, i+1);
	end;
	result:=res;
end;


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


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

//==================================================================================================
//  03. Парсинг страницы поисков с фильмами 
//==================================================================================================
function SelectMovie: Integer;
 var
	Movie, Code, small_cover, description, year, actors, tempCode, s : string;
	i, j : Integer;
 begin
  Result:=0;
  tempCode := GetStr(all, '<!-- код поиска -->', '<script');
  while Pos('<td class="itemTitr"', tempCode) > 0 do begin
	j := MyPos('</tr>', tempCode, Pos('<td class="itemTitr"', tempCode) + 1);
    s := GetStr(tempCode, '<td class="itemTitr"', '</tr>');
	small_cover := GetStr(s, ' src="', '"');
	if (Pos('noposter', small_cover)>0) then
		small_cover := '';
	year := ClearExtraBlankCharacters(RemoveTags(GetStr(s, '<div class="year">', '</div>')));
	Movie := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(s, '<h3>', '</h3>'))));
	Code := ParseString(s, '<a href="http://ruskino.ru/mov/(\d+)', 1);
	actors := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(s, 'Актеры:', '</'))));
	description := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(s, 'align="justify">', '<a '))));
	if (Movie <> '') and (Code <> '') then begin
		SetSearchResult2(Movie, Code, Year, actors, description, small_cover);
		Inc(Result);
	end;
	delete(tempCode, 1, j);
  end;
 end;


//==================================================================================================
//  04. Формирование URL с информацией о фильме по коду фильма в формате сайта
//==================================================================================================
function GetMovieURL(code: string; images_only: boolean): string;
 begin
  if Code<>''
   then   Result:='http://ruskino.ru/mov/'+Code
   else   Result:=''
 end;

function GetMovieSiteURL(code: string): string;
 begin
  if Code<>''
   then   Result:='http://ruskino.ru/mov/'+Code
   else   Result:=''
 end;

//==================================================================================================
//
//==================================================================================================
function GetPersonSiteURL(Code: string): string;
 begin
  if Code<>''
   then   Result:='http://ruskino.ru/art/'+Code
   else   Result:=''
 end;

procedure ExtractActors(text: String; mode: Integer);
var
	s, s2, small_photo, name, code, character: String;
	i, j, k, local_mode: Integer;
begin
	while (Pos('<tr><td class="itemTitr"', text)>0) do begin
		s := GetStr(text, '<tr><td class="itemTitr"', '</tr>');
		local_mode := mode;
		small_photo := GetStr(s, ' src="http://ruskino.ru/artist/', '"');
		if (Pos('noportret', small_photo)>0) then
			small_photo := '';
		if (small_photo <> '') then
			small_photo := 'http://ruskino.ru/artist/' + ReplaceStr(small_photo, 'tn_portret', 'pv_portret', -1);
		code := ParseString(s, '<a href="http://ruskino.ru/art/(\d+)', 1);
		name := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(s, '<div class="artRol">', '</div>'))));
		k := Pos('(', name);
		if k>0 then
			delete(name, k, length(name)-k+1);
		if (Pos('*', name) = 1) then
			delete(name, 1, 1);
		if (mode = 3) then begin
			character := GetStr(s, 'роль: <b>', '</b>');
			if character = '' then begin
				s2 := GetStr(s, '<span class="rolabout"', '</span>');
				k := Pos('<br', s2);
				if k>0 then
					delete(s2, k, length(s2)-k+1);
				if s2 <> '' then
					character := RemoveTags('<' + s2);
			end;
			character := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(character)));
		end
		else
			character := '';
		if (mode = 0) and (Pos('режиссер', s)>0) then begin
			local_mode := 1;
			if (name <> '') then
				AlreadyAddedPeople.Add(name);
		end;
		if (mode = 0) and (Pos('сценарист', s)>0) then begin
			local_mode := 2;
			if (name <> '') then
				AlreadyAddedPeople.Add(name);
		end;
		if (mode = 0) and (Pos('композитор', s)>0) then
			local_mode := 4;
		if (local_mode > 0) and (name <> '') then begin
			SetPersonName(name, character, local_mode, code, small_photo);
		end;
		delete(text, 1, Pos('<tr><td class="itemTitr"', text));
	end;
	if (mode = 3) and (Pos('В эпизодических ролях: ', text)>0) then begin
		i := Pos('<a href="http://ruskino.ru/art/', text);
		while (i>0) do begin
			j := MyPos('</a>', text, i+1);
			s := copy(text, i, j-i);
			code := ParseString(s, '<a href="http://ruskino.ru/art/(\d+)', 1);
			name := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(s)));
			if (name <> '') and (name <> '[...]') then
				SetPersonName(name, '', mode, code);
			delete(text, 1, j);
			i := Pos('<a href="http://ruskino.ru/art/', text);
		end;
	end;
end;

procedure ExtractPeopleSmall(temp: String; mode: Integer);
var
	i, k: Integer;
	name: String;
begin
	temp := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(temp)));
	while (temp <> '') do begin
		i := Pos(', ', temp);
		if i>0 then begin
			name := copy(temp, 1, i-1);
		end
		else begin
			name := temp;
			i := length(temp);
		end;
		k := Pos('(', name);
		if k>0 then
			delete(name, k, length(name)-k+1);
		if (name <> '') and (AlreadyAddedPeople.IndexOf(name) < 0) then
			SetPersonName(name, '', mode, '');
		delete(temp, 1, i+1);
	end;
end;

//==================================================================================================
//  Получение данных по фильму по URL
//  images_only - признак закачки только картинок
//==================================================================================================
function GetInfo(URL: string; Images_Only: boolean): string;
const
	StudioWordsToReplace=['Первого', 'канала'];
	StudioWordsReplaced=['Первый', 'канал'];
 var
  Temp, Name, Value, Actors, ActorName, ActorInfo, ActorLink, s: string;
  Step, i, j, k: Integer;
 begin
  InternalURL:=URL;
  BaseImageURL:=ReplaceStr(InternalURL, 'mov', 'film', -1);

  //  Проверка на ошибки
  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;  
  MovieInfo:=Result;
  
  //------------------------------------------------------------------------------------------------
  //  Парсинг основной информации
  //------------------------------------------------------------------------------------------------
  all:=Result;
  
  AlreadyAddedPeople := TStringList.Create;
  
  //загрузка кадров
  ShotsPage := InternalURL+'/photo';
  if (MaxShotsCount > 0) then begin 
	if (Pos(ShotsPage, all)>0) then begin
		AddRequestForHTMLPageContent(ShotsPage, False);
		ShotName := '/photo/';
	end
	else begin
		ShotsPage := InternalURL+'/gallery';
		if (Pos(ShotsPage, all)>0) then begin
			AddRequestForHTMLPageContent(ShotsPage, False);
			ShotName := '/gallery/';
		end;
	end;
  end;
  
  //загрузка постеров
  PostersPage := InternalURL+'/poster';
  if (Pos(PostersPage, all)>0) and (MaxPostersCount > 0) then begin
	AddRequestForHTMLPageContent(PostersPage, False);
  end;  

  //  Возврат кода фильма в формате сайта
  movie_code:=ParseString(URL, '(\d+)$', 1);
  movie_site_url := GetMovieSiteURL(movie_code);
  title := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(all, '<h2>', '</h2>'))));
  original_title := '';

  //описание
  description := GetStr(all, '<div class="itemAnnot" align="justify">', '</td>');
  description := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(description)));
  
  //год
  temp := GetStr(all, '<td class="itemTitr" align="right">'#10'Год', '</tr>');
  year := ParseString(temp, '(\d+)', 1);
 
  //  Добавление страны по флагу
  if Pos('razdel=sov', Result)=0 then   SetCountry('Россия')
  else   SetCountry('СССР');
  
  //актеры
  i := Pos('<h2>актеры и роли</h2>', all);
  if i>0 then begin
	j := MyPos('<td class="line" colspan="2">', all, i+1);
	if j=0 then
		j := MyPos('</table>', all, i+1);
	temp := copy(all, i, j-i);
	ExtractActors(temp, 3);
  end;
  
  //творческая группа
  temp := GetStr(all, '<h2>творческая группа</h2>', '</table>');
  if temp <> '' then
	ExtractActors(temp, 0);

  //режиссер
  temp := GetStr(all, 'Режиссер</td>', '</tr>');
  ExtractPeopleSmall(temp, 1);
  //сценаристы
  temp := GetStr(all, 'Сценарий</td>', '</tr>');
  ExtractPeopleSmall(temp, 2);
  //композитор
  temp := GetStr(all, 'Композитор</td>', '</tr>');
  ExtractPeopleSmall(temp, 4);
  
  //студии
  temp := GetStr(all, 'Производство</td>', '</tr>');
  temp := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(temp)));
  i := Pos('"', temp);
  if (i = 0) and (temp <> '') then
	SetStudio(temp);
  while (i>0) do begin
	j := MyPos('"', temp, i+1);
	s := copy(temp, i+1, j-i-1);
	for k := 0 to Length(StudioWordsToReplace) do
		s := ReplaceStr(s, StudioWordsToReplace[k], StudioWordsReplaced[k], -1);
	if s<>'' then
		SetStudio(s);
	delete(temp, 1, j);
	i := Pos('"', temp);
  end;
  
  //рейтинг сайта
  temp := ClearExtraBlankCharacters(RemoveTags(GetStr(all, '<div class="rating">', '</div>')));
  i:=pos('.', temp);
  if i>0 then
	temp[i]:=DecimalSeparator;
	try
		rating:=StrToFloat(temp);
	except
	end;
	
  AlreadyAddedPeople.Free;

 end;


//==================================================================================================
//  Загрузка картинок
//==================================================================================================
procedure GetImages;
 var
  Temp: string;
 begin                                   
  //  Получение постера для фильма
  if Pos(BaseImageURL+'/md_poster.jpg', MovieInfo)>0
   then   //  Найдена большая обложка, загружаем её
          SetImageName('', BaseImageURL+'/md_poster.jpg', '', IMAGE_FRONT_COVER)
   else   if Pos(BaseImageURL+'/pv_poster.jpg', MovieInfo)>0
           then   //  Найдена только малая обложка, загружаем её
                  SetImageName('', BaseImageURL+'/pv_poster.jpg', '', IMAGE_FRONT_COVER);

  //  Получение кадров из фильма
  Temp := GetHTMLPageContentFromRequest(ShotsPage);
  if (Temp <> '') and (temp <> '-1') then
	GetLargeScreenshots(Temp, MaxShotsCount, IMAGE_SCREENSHOT)
  else
	GetSmallScreenShots;

  //постеры
  Temp := GetHTMLPageContentFromRequest(PostersPage);
  if (Temp <> '') and (temp <> '-1') then begin
	ShotName := '/poster/';
	GetLargeScreenshots(Temp, MaxPostersCount, IMAGE_POSTER);
  end;
	
 end;


//==================================================================================================
//  Сохранение картинки по ее URL в выбранный файл
//==================================================================================================
function SaveFrontCover(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;


begin
end.
