Проверить ссылки iptv каналов на работоспособность

Пишу для себя приложение, что то типа менеджера плейлистов iptv каналов. Возникла необходимость проверять жива ли ссылка. Опыт в данной теме у меня нулевой, потому задачу начал решать в лоб. Вернее решал я её по разному, пока не пришёл к более менее приемлемому для себя варианту. Отправляю запрос на сервер и проверяю какой тип файла сервер пытается мне всучить (само собой если ответ не пришёл, то ссылка мертва). В 90% это файл m3u8 который уже содержит ссылку на видео, но может содержать ещё ссылки на m3u8 или сервер подсовывает какую нибудь страницу. Короче программа выуживает ссылки из файлов m3u8 до тех пор пока не наткнётся на само видео. (Если нет => ссылка мертва). Работает всё это достаточно неплохо и по скорости и по точности, но один момент я никак не могу решить :(. Например есть такой канал:введите сюда описание изображения

Программа скачивает следующий файл:

введите сюда описание изображения

Берёт первую попавшуюся ссылку в этом файле, определяет, что это видео и оно вполне себе скачивается, потому ставит каналу статус "online" и якобы всё хорошо. Но на самом деле это заглушка которая показывает следующее:

введите сюда описание изображения

Да, плейлисты берутся с открытых, бесплатных источников и потому там может быть намешано всякое и платные каналы и мёртвые ссылки и всякий мусор и ..., собственно потому и захотелось написать приложение, которое бы приводило бы в порядок весь этот хаос.

Так вот вопрос: есть ли способ определить, что это не потоковое вещание, а всего навсего заглушка? И на самом деле канал для меня недоступен.

Буду рад любой помощи.


Ответы (1 шт):

Автор решения: EvgeniyZ

Вам верно подсказали в комментариях, надо анализировать трафик и смотреть что именно происходит с вашим запросом.

Сделаем простое приложение, которое отправит GET запрос на указанный вами адрес:

private static readonly HttpClient client = new();

static async Task Main(string[] args)
{
    var resp = await client.GetAsync("http://zabava-htlive.cdn.ngenix.net/hls/CH_ULTRAHDCINEMA_HLS/bw6000000/variant.m3u8");
}

и отловим его запросы, например через Fiddler, что мы там увидим?

Fiddler

Что видим? Правильно, видим, что указанный адрес перенаправил нас на заглушку:

https://zabava-block-htvod.cdn.ngenix.net/rtk_block.m3u8

Открываем ее и что мы там видим? Верно, то, что вы и указали в вопросе

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.000000,
http://zabava-block-htvod.cdn.ngenix.net/index0.ts
#EXTINF:10.000000,
http://zabava-block-htvod.cdn.ngenix.net/index1.ts
#EXTINF:10.000000,
http://zabava-block-htvod.cdn.ngenix.net/index2.ts
#EXTINF:10.000000,
http://zabava-block-htvod.cdn.ngenix.net/index3.ts
#EXT-X-ENDLIST

Почему нам сервер дает 301?

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

Запрос от браузера

Browser

Запрос от программы

Program

И тут мы сразу видим всю разницу. Давайте по порядку будем добавлять в наше приложение эти заголовки, начнем с самого базового - UserAgent:

client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51");

Пробуем. И о чудо, сервер нас пустил!

Как отловить подобное?

Ну лично я вижу два пути:

  1. Запретить автоматическое перенаправление.

     private static readonly HttpClient client = new(new HttpClientHandler() { AllowAutoRedirect = false });
    
     static async Task Main(string[] args)
     {
         var resp = await client.GetAsync("http://zabava-htlive.cdn.ngenix.net/hls/CH_ULTRAHDCINEMA_HLS/bw6000000/variant.m3u8");
         var status = resp.StatusCode;
         var isSuccess = resp.IsSuccessStatusCode;
     }
    

    Данный код выдаст нам status == HttpStatusCode.Moved, а isSuccess == false.

  2. Смотреть куда именно нас перенаправил сайт.

     private static readonly HttpClient client = new();
    
     static async Task Main(string[] args)
     {
         var uri = new Uri("http://zabava-htlive.cdn.ngenix.net/hls/CH_ULTRAHDCINEMA_HLS/bw6000000/variant.m3u8");
         var resp = await client.GetAsync(uri);
         var requestUri = resp.RequestMessage.RequestUri;
         var isSuccess = uri.Host == requestUri.Host;
     }
    

    Заглушка на сайте находится по другому пути, да и хост другой, поэтому можем смело их проверить, isSuccess будет false, если мы попали на заглушку.

→ Ссылка