Как я научил родителей качать турецкие сериалы одним щелчком

от автора

Добрый день!
У многих из нас есть родители, которые не очень дружат с техникой, и дружить приходится за них. Моя семья в полном составе смотрит сериал "Великолепный век", серии которого выходят раз в неделю. Вроде не так часто, но субботу за субботой слышать «Иди проверь, нет ли серии», искать раздачу, запускать торрент и так далее стало утомительно, и я решил переложить это на цифровые плечи четвертого .NetFramework-а.
Что нам понадобится:
Visual Studio 2010 или выше
— Консольный торрент-клиент Aria2c.

Осторожно, местами присутствует индусский код! Я предупреждал.

Задача передо мной стояла такая: приложение запускается, скачивает торрент и скармливает его консольному торрент-клиенту, который закачивают серию на флешку (флешку вставляют в телевизор).

Для начала нам нужно понять, какую серию мы хотим скачать. Сериал выходит в Турции по средам, у нас с переводом в субботу-воскресение. На днях вышла 96 серия. Сейчас по календарю идет 18 неделя. Значит, к номеру текущей недели надо прибавить 78, если программу запускают в будний день, и 79, если в выходные.
Выглядеть это будет так:

        DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;         DateTime date1 = DateTime.Now;         Calendar cal = dfi.Calendar;         var week = cal.GetWeekOfYear(date1, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);         var day = (int)cal.GetDayOfWeek(date1) == 0 ? 6 : (int)cal.GetDayOfWeek(date1) - 1; //В США недели начинаются с воскресения, поэтому метод GetDayOfWeek возвращает 0 для воскресения, расставим  дни в привычном порядке. GetWeekOfYear же возвращаем правильное значание, так как применена локаль         var epnumber = week + 79 - ((day < 5) ? 1 : 0); 

Теперь, когда нам известен номер серии, можем идти на треккер.
Сперва нужно авторизоваться, для этого создаем POST-запрос на страничку login.php, и передаем ему пару логин-пароль.

byte[] buffer = Encoding.ASCII.GetBytes("login_username=ВАШ_ЛОГИН&login_password=ВАШ_ПАРОЛЬ&login=%C2%F5%EE%E4");         HttpWebRequest WebReq = (HttpWebRequest)WebRequest.Create("http://login.rutracker.org/forum/login.php");//Строка для Post-запроса         var cc = new CookieContainer();         WebReq.CookieContainer = cc;//включаем куки         WebReq.Method = "POST";         WebReq.ContentType = "application/x-www-form-urlencoded";         WebReq.ContentLength = buffer.Length;         HttpWebResponse WebResp;          try         {             Stream PostData = WebReq.GetRequestStream();             PostData.Write(buffer, 0, buffer.Length);             PostData.Close();             WebResp = (HttpWebResponse)WebReq.GetResponse();         }         catch (Exception e)         {             MessageBox.Show("Ошибка сети", " ", MessageBoxButtons.OK, MessageBoxIcon.Error);             return;         } 

Сервер в ответ плюнул в нас кукой авторизации, которая хранится у нас в cc. Теперь с этой кукой можно сделать запрос на поиск серии:

        var url = @"http://rutracker.org/forum/tracker.php?nm=%D0%92%D0%B5%D0%BB%D0%B8%D0%BA%D0%BE%D0%BB%D0%B5%D0%BF%D0%BD%D1%8B%D0%B9%20%D0%B2%D0%B5%D0%BA%20sub%20"+epnumber;  WebReq = (HttpWebRequest)WebRequest.Create(url);         WebReq.CookieContainer = cc;         WebReq.Method = "GET";         WebReq.ContentType = "application/x-www-form-urlencoded";         WebResp = (HttpWebResponse)WebReq.GetResponse();          string result;         Encoding responseEncoding = Encoding.GetEncoding(WebResp.CharacterSet);         try         {             using (StreamReader sr = new StreamReader(WebResp.GetResponseStream(), responseEncoding))             {                 result = sr.ReadToEnd();             }         }         catch (Exception e)         {             MessageBox.Show("Ошибка сети", "Заголовок сообщения", MessageBoxButtons.OK, MessageBoxIcon.Error);             return;         } 

Страницу поиска парсим на наличие ссылок на торрент файлы вида dl.rutracker.org/forum/dl.php?12345:

 string pattern = @"http://dl.rutracker.org/forum/dl.php\?t=\d+";         Regex regex = new Regex(pattern);         Match match = regex.Match(result);         if (match.Length == 0)         {              MessageBox.Show("Новая серия еще не вышла!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);             return;         }         else            AutoClosingMessageBox.Show("Новая серия вышла! Начинаем закачку.", "Caption", 3000); 

Торрент-файл найден, сохраняем его на жесткий диск:

 try         {             WebReq = (HttpWebRequest)WebRequest.Create(match.ToString());             WebReq.CookieContainer = cc;             WebReq.AllowAutoRedirect = false;             WebReq.Method = "POST";             WebReq.Referer = url;             WebReq.ContentType = "application/x-www-form-urlencoded";              /*Пишем его в файл*/             Stream ReceiveStream = WebReq.GetResponse().GetResponseStream();             string filename = @"C:\123.torrent";             byte[] buffer1 = new byte[1024];             FileStream outFile = new FileStream(filename, FileMode.Create);             int bytesRead;             while ((bytesRead = ReceiveStream.Read(buffer1, 0, buffer.Length)) != 0)                 outFile.Write(buffer1, 0, bytesRead);             outFile.Close();             ReceiveStream.Close();                       }         catch (Exception e)         {             MessageBox.Show("Ошибка при скачке торрент-файла!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);             return;         } 

Теперь проверяем, не забыли ли незадачливые родственники вставить флешку, и достаточно ли на ней места:

string letter = "";         foreach (DriveInfo i in System.IO.DriveInfo.GetDrives())         {               try             {                 if (i.DriveType.ToString() == "Removable" && i.ToString() != "A:\\")                 {                     if (i.TotalFreeSpace < 3000000000)                     {                         MessageBox.Show("На флешке мало место, нужно 3гб!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);                         return;                     }                      letter = String.Copy(i.ToString());                     break;                 }                 //Console.WriteLine(i.DriveType);              }             catch (Exception E)             {                 return;             }         }         if (letter == "")         {             MessageBox.Show("Вставь флешку!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);             return;         } 

Наконец, все готово к скачке, можно приступать!

 string par = @"--seed-time=0 -d " + letter + " --select-file="+(epnumber-3)+ @" ""C:\123.torrent"" "; //--seed-time=0 - выход сразу после загрузки, не сидируя. Нужно для сигнализации о завершения загрузки, да простят меня личи. //-d - указывает в качестве папки загрузки найденную ранее свободную флешку //--select-file - номер файла, нужного для скачки. В раздаче три серии пропущены, поэтому уменьшаем индекс на 3.          Process P = Process.Start(@"C:\aria2-1.17.0-win-32bit-build1\aria2-1.17.0-win-32bit-build1\aria2c.exe", par);         P.WaitForExit();         int result1 = P.ExitCode;         Console.WriteLine(result1);         if (result1 == 0)         {             MessageBox.Show("Фильм скачан! Можно вытаскивать флешку!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);         }         else         {             MessageBox.Show("Неизвестная ошибка!", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);         } 

Все, сериал скачан и ждет просмотра.
Полный текст скрипта на http://pastebin.com/8L03vkJg.
Берегите ваших родителей.

P.S. Да, понятно, что на Per/PHP/Python/… можно уменьшить количество строчек в несколько раз. Код написан с целью самообразования.

ссылка на оригинал статьи http://habrahabr.ru/post/178493/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *