Closed funplayertv closed 5 years ago
@funplayertv dzięki zajmę się tym niebawem
Próbowałem poniższych zapytań. Wszystko się rozbija o CORS „Access-Control-Allow-Origin”
$.ajax({ dataType: "json", method: "GET", url: "https://apivod.tvp.pl/tv/video/42549669/", password: "vod", username: "api", success: function(){ console.log('JUPI') } })
$.ajax({ dataType: "json", method: "GET", url: "https://apivod.tvp.pl/tv/video/42549669/", beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic " + btoa("api:vod")); }, success: function(){ console.log('JUPI') } });
$.ajax({ dataType: "json", method: "GET", url: "https://apivod.tvp.pl/tv/video/42549812/", headers: { "Authorization": "Basic " + btoa("api:vod") }, success: function(){ console.log('JUPI') } })
$.ajax({ dataType: "jsonp", url: "https://apivod.tvp.pl/tv/video/42549669/", jsonpCallback: function(json){ console.log(json) } })
tutaj patrzyłes ?
https://stackoverflow.com/questions/1652178/basic-authentication-with-xmlhttprequest i https://stackoverflow.com/questions/45533002/basic-authentication-with-header-javascript-xmlhttprequest
edit. zastanawia mnie tez, dlaczego w takim razie w org. miniskryptach to funkcjonuje... ale wiadomo recznie trzeba wpisac dane.
To nie kwestia tego, że nie mogę się zautoryzować. To się udaje. Nie można pociągnąć jsona z innej domeny, chyba że konfiguracja serwera to umożliwia, a przynajmniej jeszcze nie znalazłem na to sposobu.
a jakas manipulacja nagłowkami? bez tworzenia proxy itd. ?
Jakimś cudem w naszym skrypcie, w wersji 4.9 to działa. https://greasyfork.org/en/scripts/6049-skrypt-umo%C5%BCliwiaj%C4%85cy-pobieranie-materia%C5%82%C3%B3w-ze-znanych-serwis%C3%B3w-vod/code?version=627360
Problem chyba jest w tym, że nowy przycisk ładuje się bezpośrednio w ramce (?) a nie na stronie materiału. Wcześniej ten przycisk po prostu pojawiał się na wszystkich stronach, vod.* nawet w widoku kategorii.
Ciekawym rozwiązaniem mogłoby być ustawienie jakiejś funkcji "nasłuchowej" (sorry za złe nazewnictwo). Czyli Skrypt Tampermonkey mógłby sprawdzać czy jakaś zmienna globalna JSON_FAILED zmieniła wartość na TRUE i wtedy wywoływać funkcję pobierania z parenta (czyli okna nadrzędnego)?
Domena apivod.tvp.pl nie pozwala na zaciągnięcie tego jsona z innych domen. Szczegóły tutaj: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy. Nie widzę ładnego sposobu by to zrobić.
Musiałbyś postawić serwer, który by wysyłał request do "apivod.tvp.pl" i odbierał te dane twoim skryptem ;) Daje 100% gwarancji, że to zadziała. Problemem jest to, że musiałbyś utrzymywać serwer
Spójrz: Serwer lokalnie uruchomiłem ale na vps i tym podobnych też działa
alternatywnie, o ile jest taka możliwość, autoryzować, i wyswietlić nowa zakłądkę z jsonem ale bezpośrednio pod adresem danej lokalizacji, czyli tak jakby po porstu wyswietlic nowa zakłądkę i/albo juz z autoryzacja zeby nie trzeba było wpisywac, albo po porstu wymagac autoryzacji
Z poziomu przeglądarki tego się raczej nie zrobi, bo z tego co wiem, to przeglądarka nie pozwala wysłać requesta i wywala komunikat CORS
Edit: Chyba, że skrypt może ingerować w przeglądarkę i wyłączyć blokadę.
Stara wersja (4.9) wyciąga ID materiału jako: 42383664 Nowa jako: 42549669
I dzięki temu działa.
skąd ta różnica? przecież materiał: https://vod.tvp.pl/video/wiadomosci,17052019-1200,42549669 ma ID 42549669;
nie widze nigdzie id 42383664
Ramka jest z numerkiem 42383664:
<iframe id="tvplayer" src="/sess/tvplayer.php?object_id=42383664&autoplay=true&nextprev=1&vastTransformer=1.13.1"
I z tej ramki spróbuję wyciągnąć object_id. Może zacny poprawi/ulepszy żeby nie sypało błędami w razie problemów.
ale to nic nie da, zauważ, ze nawet jak pobierzez ID 42383664 za pomoca https://www.tvp.pl/shared/cdn/tokenizer_v2.php?object_id=42383664 otrzymasz jsona, ALEEEEE do plikow video max "totalBitrate":820000, a z apomoca api - juz normalna jakosc :)
Nie rozumiem? Wersja 4.9 wyciąga te wiadomości w 9100000, takiej samej jak jakiś inny pseudo-serial.
zgadza się, juz miałem edytowac, moj bład, faktycznie, gdy sie pobierze ten ID z iframe o ktorym mowisz, nawet za pomoca https://www.tvp.pl/shared/cdn/tokenizer_v2.php?object_id=42383664 to działa, poprawnie
Heh, tylko oni nie wyświetlają tej ramki jak adblock jest włączony, więc ciężko jest wyciągnąć ten numerek od razu.
Mam taki pomysł:
Mogę się tym zająć, tylko że ja piszę tym brzydkim, niespójnym Javascriptem więc będzie do poprawy. @zacny napisz proszę czy sam chcesz to zrobić, żeby nie powtarzać tego samego.
Obczaję to co mówicie. @aleks365. Czy to co zrobiłeś da się jakimś prostym skryptem php zrobić? Jeżeli tak to można coś nawet darmowego skonfigurować (najwyżej będzie się zamulać). Obczaję też czemu jest różnica w ID. Ja na wersji 4,9 w ogóle nie miałem przycisków, nawet jak się adbloki wyłączyło. Ostatecznie jak nic nie wymyślę, to zrobię rozwiązanie takie, że dam linka do tego api o tak: api To działa przecież :)
@HerMajestyDrMona widzę tylko jedną ramkę. Brak podanego przez Ciebie ID...a nie doczytałem, że adblocka trzeba wyłączyć.
@zacny, a materiał się odtwarza w ogóle? Jakieś reklamy lecą itd.? Edit: no tak, ten anty adblock nieszczęsny...
@zacny Pewnie, że się da ;) Łap:
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://apivod.tvp.pl/tv/video/42549669/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Authorization: Basic YXBpOnZvZA==",
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
U mnie to wygląda tak. Co bym nie zrobił to mam wyłączyć blokadę.
@aleks365 Dziękuję i proszę jeszcze o słowo wyjaśnienia jak mam tego skryptu użyć. Mam go po prostu odpalić? Odpaliłem sobie tutaj:
https://voddownloader.000webhostapp.com/apitvp.php
i mam taką odpowiedź od serwera:
{"success":0,"error":500,"message":"Undefined class constant 'ERROR_CODE_GEO_BLOCK_MSG'","version":"v2","data":[]}
Jakaś inna wersja php? Z PHP to prawie wcale nie miałem do czynienia więc nie znam nawet podstaw podstaw.
@zacny, nie używasz przypadkiem PiHole, albo jakiegoś innego filtrującego DNSa? W moim przypadku właśnie trzeba było PiHole pauzować.
@HerMajestyDrMona no mam PiHole... eh zawsze o tym zapominam.
@HerMajestyDrMona Faktycznie jest ramka, ale nie działa na firefoxie u mnie, na chromu już mu lepiej. Dobra zrobię taką zmianę, że będzie wykrywało tę ramkę jeżeli jest. Choć używanie tego serwisu bez blokowania reklam to jest jakiś masochizm.
@aleks365 Dziękuję i proszę jeszcze o słowo wyjaśnienia jak mam tego skryptu użyć. Mam go po prostu odpalić? Odpaliłem sobie tutaj: https://voddownloader.000webhostapp.com/apitvp.php i mam taką odpowiedź od serwera:
{"success":0,"error":500,"message":"Undefined class constant 'ERROR_CODE_GEO_BLOCK_MSG'","version":"v2","data":[]}
Jakaś inna wersja php? Z PHP to prawie wcale nie miałem do czynienia więc nie znam nawet podstaw podstaw.
Ja mam wersje php 7.2.9 do tego musisz mieć zainstalowany moduł php-curl... Zobacz czy serwer na których masz skrypt obsługuję curl, ale obawiam się, że mają to wyłączone bo to darmowy hosting
Edit: Jak chcesz to mogę wrzucić skrypt na któryś z moim serwerów żebyś mógł używać
@zacny @HerMajestyDrMona no własnie, wyjasniło sie dlaczego na firefoxie u mnie tej ramki tez nie ma, ale ten sam problem mam, mimo ze mam wyłączonego ublocka to i tak jest dupa, a nie uzywam PiHole ani nic z tych rzeczy... mysle ze wiecej bedzie takich ludzi, wiec fajnie bybyło wymyslic jakas taka metode ktora byłaby odporna na te sytuacje.... bo osobiscie domyslna moja przeglądarka jest lisek, nie wyobrazam sobie tez własnie zyc z nim bez ublocka
A co z tym apivod? Różni się czymś? Nie działa przy jakichś materiałach?
Ewentualnie można zrobić 3 failbacki:
Lub zamienić punkt 3 i 2 pozycjami.
@HerMajestyDrMona Obecna wersja zawiera obejście problemu. Wyświetlam linka do tego jsona i można sobie go kliknąć. Brzydkie wiem, ale na razie tylko tyle wymyśliłem. Pomysł z:
<iframe id="tvplayer" src="/sess/tvplayer.php?object_id=42383664&autoplay=true&nextprev=1&vastTransformer=1.13.1"
Nie bardzo można zrealizować. Nie można zjeść ciastka i mieć ciastka. Albo będzie dobrze dla przypadków gdzie ludzie mają poblokowane adbloki albo dla tych masochistów, który tego nie zrobili. Można to zaobserwować na obecnej wersji jeżeli zmienimy:
'#tvplayer, div.playerContainer'
na
'#tvplayer'
Jak są reklamy to tam jest wolna amerykanka i pełno ramek. Skrypt jest z uwagi na inne serwisy ustawiony tak, by uruchamiał się w każdej z ramek pasujących do dopuszczanych urli.
Więc w razie większej ilości przycisków jeden zakrywa drugi.
Jedyna nadzieja na normalne działanie jaką ja widzę to jest przygotowanie skryptu według pomysłu kolegi @aleks365
Czyli js strzela do skryptu php albo innego na serwerze z id materiału, a on dla niego loguje się i ściąga jsona z api oraz przesyła dalej.
Jeżeli są inne racjonalne pomysły to chętnie przygarnę.
Nie bardzo można zrealizować. Nie można zjeść ciastka i mieć ciastka. Albo będzie dobrze dla przypadków gdzie ludzie mają poblokowane adbloki albo dla tych masochistów, który tego nie zrobili.
Ale w czym dokładnie problem? Ten przycisk mógłby się wyświetlać w identyczny sposób jak teraz, tylko po kliknięciu, zmienić zachowanie funkcji po:
if(data.status == 'OK' && data.formats !== undefined){
dodać:
else { //Sprawdzenie czy Ramka istnieje //Powtórzenie funkcji tym razem używając ID z ramki }
Być może gdzieś wcześniej da się sprawdzić czy Json jest OK i zmienić "url" jeszcze wcześniej? W najnowszej wersji pod:
if(exception.name = 'API_ERROR'){
A w przypadku braku ramki dopiero pokazać linka apivod? W ten sposób istnieje większa szansa że ktoś pobierze co potrzebuje, niżeli ręczne przeszukiwanie.
Dodatkowo, można też ustawić skrypt z Tampermonkeya żeby aktywował się na stronie "apivod.tvp.pl" I wyświetlał potwierdzenie czy wyodrębnić linki w przyjaznej formie (albo w ogóle nie musiałby się pytać). Potem traktował innerHTML jako JSON i pokazywał wszystko w przyjaznej formie. Tak na Ipli stara wersja skryptu działała, Json w nowej karcie i pobieranie informacji o materiałach + sortowanie.
Wiadomo, byłaby to lekko brzydsza metoda, ale użyteczność zwiększyłaby się bardzo.
@zacny Po przeanalizowaniu api tvp zauważyłem, że linki wideo są przypisane do IP itp dlatego jakby mój skrypt php wysyłał request do https://apivod.tvp.pl/tv/video/ To linki przechwycone przez Twój skrypt by nie działały u użytkownika.
Napisałem prosty skrypt w nodejs do którego przekazujemy ID wideo i on sprawdza czy materiał kryje się pod innym ID czy pod takim samym
Przykład: Tego wideo nie da się pobrać skryptem, ponieważ w api ma on inne ID https://vod.tvp.pl/video/teleexpress,19052019-1700,42549812 Przesyłam ID tego wideo do mojego skryptu i w odpowiedzi dostaje poprawne ID
Otrzymane ID przesyłamy do: https://www.tvp.pl/shared/cdn/tokenizer_v2.php?object_id=42405307 I otrzymujemy wszystko co niezbędne do dalszych akcji skryptu.
W sytuacji gdy wideo ma takie samo ID na stronie jak w api w odpowiedzi dostane to samo ID
Najlepszą wygodą dla użytkownika byłoby kliknąć i mieć wideo które go interesuje dlatego warto przyjrzeć się mojej propozycji
Skrypt można zrobić oczywiście również w php i rezultat otrzymamy taki sam
Zewnętrzne VPSy mogą być banowane przez VODy, a w ekstremalnych warunkach zgłaszane za "ataki". Trzeba by wprowadzić limity na IP (np.
if (!apcu_exists(){ apcu_store("Limit-".$_SERVER["REMOTE_ADDR"]),"blablabla", 5);//Dalszy kod }
Do tego kwestia telemetrii. Nie posądzając że ktoś zbierałby jakieś informacje o odwiedzinach, itd. to i tak połączenia do serwerów 3cich mogą być negatywnie odbierane przez użytkowników.
Dobrze byłoby pozostać przy wersji gdzie wszystko odbywa się lokalnie.
Testowałem taki scenariusz i do żadnych blokach nie doszło Przez 25 minut wysyłałem 100 zapytań do api w ciągu 2-3 sekund z jednego hosta i wszystko działa dalej także testy zaliczone. Co do zbieraniu informacji to @zacny miałby dostęp przez ssh/sftp do skryptu ale jak tam uważasz w takim razie moja rola w tym momencie się kończy skoro skrypt ma lokalnie uzyskać poprawne id wideo. Pozdrawiam i życzę rozwiązania problemu jak najszybciej
Problem jest praktycznie rozwiązany w wersji 5.3.3. Pozostaje wyciągnąć linki z JSONa otworzonego w nowej karcie.
Btw. nie sugeruję że ktoś miałby zbierać jakieś dane, ale o poczucie prywatności przez użytkowników. Równie dobrze można by cały skrypt przerobić na PHP z jakimś interpreterem JS i postawić jako zewnętrzną stronkę.
@zacny Po przeanalizowaniu api tvp zauważyłem, że linki wideo są przypisane do IP itp dlatego jakby mój skrypt php wysyłał request do https://apivod.tvp.pl/tv/video/ To linki przechwycone przez Twój skrypt by nie działały u użytkownika.
Napisałem prosty skrypt w nodejs do którego przekazujemy ID wideo i on sprawdza czy materiał kryje się pod innym ID czy pod takim samym
Przykład: Tego wideo nie da się pobrać skryptem, ponieważ w api ma on inne ID https://vod.tvp.pl/video/teleexpress,19052019-1700,42549812 Przesyłam ID tego wideo do mojego skryptu i w odpowiedzi dostaje poprawne ID
Otrzymane ID przesyłamy do: https://www.tvp.pl/shared/cdn/tokenizer_v2.php?object_id=42405307 I otrzymujemy wszystko co niezbędne do dalszych akcji skryptu.
W sytuacji gdy wideo ma takie samo ID na stronie jak w api w odpowiedzi dostane to samo ID
Najlepszą wygodą dla użytkownika byłoby kliknąć i mieć wideo które go interesuje dlatego warto przyjrzeć się mojej propozycji
Skrypt można zrobić oczywiście również w php i rezultat otrzymamy taki sam
bardzo ciekawa opcja i rozwiązanie wg mnie. chyba ze faktycznie da sie zrobić tak, jak pisał @HerMajestyDrMona ze skoro juz skrypt wyświetli jsona, to tak jakby go ponownie przeszukac i wyciagnac linki z juz otworoznego jsona na karcie nowej... zamiast klikac recznie.
edit. a jescze tak przyszło mi do głowy... czy skrypt mogłby np. symulowac (dla konkretnego serwisu VOD) w tym przypadku tego tvp, jako jakis osobny moduł... wejscie na strone jako Chrome? stosujac jakies maskowanie aby jednak to iframe było widoczne w kazdej przeglądarce? wtedy (zakładam o ile jest taka mozliwosc) ten json i tak moznaby go wyłapać... i to lokalnie u danego usera...
Zrobiłem nową gałąź: dev. Można sprawdzić czy nowe rozwiązanie działa. Za pierwszym razem api chce autoryzacji niestety. Uprościłem sobie robotę i założyłem, że zawsze strzelamy do api po dane, a nie gdy do tokenizera się nie uda. Nie wiem czy to nie błąd.
Wygląda na to że działa tak testując na szybko, jedynie parę razy zdarzało się że pojawiał się błąd json error jakby pod video, ale nie mogę zte produkować tego jzeby powiedzieć co i jak... Ale fakt faktem rozumiem metoda z ramka udana?
PS api @ vod w linku nie uda? Coby nie wpisywać?
Nie każdy zagląda na gita i skąd użytkownik skryptu ma znać login i hasło do api? Skoro to już jest w taki dziwny sposób zrobione to lepiej zmienić
urlTemplates: ['https://apivod.tvp.pl/tv/video/$idn'],
Na:
urlTemplates: ['https://api:vod@apivod.tvp.pl/tv/video/$idn'],
I
VideoGrabber.grabVideoDataFromJson = function(vod, templateIndex, w){ w = (w === undefined) ? window.open(): w; var url = getUrl(vod, templateIndex); return DomTamper.createIframe(url, w); };
Zamienić na:
VideoGrabber.grabVideoDataFromJson = function(vod, templateIndex, w){ var url = getUrl(vod, templateIndex); w = (w === undefined) ? window.open(url): w; return DomTamper.createIframe(url, w); };
Dzięki temu użytkownik nie musi autoryzować się do api. Chociaż to i tak nie jest zadowalające rozwiązanie ale lepsze niż aktualne
@aleks365 - działa, ale u mnie np. standardowo lisek ostrzega o próbie zalogowania (mimo, ze samo zalogowanie juz nastapiło) to i tak wywala sie popup, co gorsza po kliknieciu ok, wyswietla się json czysty (a przed kliknieciem ok, wyswietlało sie formatowanie skryptu
Wiem dlatego takie rozwiązanie nie jest według mnie aceptowalne. W docelowej wersji widzę to tak. Użytkownik dostaje na twarz komunikat, że trzeba się ręcznie zalogować z użyciem danych jakie mu wyświetlimy i że ma sobie zapamiętać hasło jak nie chce tego robić więcej, oraz jak nie chce widzieć więcej tego kumunikatu to ma sobie kliknąć link który doda ustawienie do store przeglądarki. Komunikat będzie widoczny przez x sekund z odliczaniem i samoczynnie zniknie, po czym następować będzie próba autoryzacji. Proste prawda :)
Wiem dlatego takie rozwiązanie nie jest według mnie aceptowalne.
ok, a gdyby zrobić to tak jak Ty zrobiłes @zacny , ale wczesniej wyswietlić stronę z informacją na zasadzie: "kliknij tutaj aby otrzymać linki (po pojawieniu sie okna z autoryzcjia wpisz: xxxx ", kliaksz, jestes poinformowany co wpisac, wyswietla Ci sie Json sformatownay i wsio hula. na około bo na około no ale coż...
Do iframe nie można wrzucać autoryzacji w url bo chrome blokuje i inni też mogą zacząć, poza tym dochodziłoby wykrywanie jeszcze kto ma jaką przeglądarkę.
dlatego mówie, poprzedzić Twoja implementację 'nową stroną' a na niej 'button' + komunikat na zasadzie: "Materiał wymaga dodatkowej interakcji, kliknij tutaj i autoryzuj sie danymi: xxx xxx, aby uzsykac linki"
uzytkownik klika, pojawia sie okienko standardowe z autoryzacjia, autoryzuje, i pojawia sie nowa/albo odświeżona karta (jak sie da) ze sformatowanym jsonem przez skrypt.
Czy waszym zdaniem przed tym całym procesem powinna być też próba dostania się do plików przez tokenizer? Nie mam poności czy apivod posiada wszystko co tokenizer, więc moim zdaniem - tak.
zdrowy rozsądek podpowiada mi intuicyjnie, że tak - powinno być wszystko, ale biorąc pod uwagę, ze zazwyczaj nic nie jest zero jedynkowe to dla swietego spokoju ja osobiscie bym sprawdzał i tu i tu, bo moze byc tak ze czesc materiałow starszych np. (chociaz szukam i nie moge takiego znaleźć) przez api dostepna nie bedzie....
p.s. co do tego błedu o ktorym pisałem wczesniej:
@aleks365 firefox za każdym razem przy url z autoryzacją, pokazuje komunikat typu prompt. W iframe już nie, ale za to chrome blokuje. Opery nie sprawdzałem. Firefox nie odpala skryptu tampermonkey na urlach z jsonem dopóki nie wyłączy się json viewera, a ten jest domyślnie włączony.
zostawie tutaj, bo bedzie czytelniej, a więc...
dobrze bybyło dodać/naprawić obsługę materiałow, które sa dostepne przez API, dla przykładu: https://vod.tvp.pl/video/wiadomosci,17052019-1200,42549669 tutaj json sie nie pobierze standardową metodą czyli https://www.tvp.pl/shared/cdn/tokenizer_v2.php?object_id= otrzymamy
zeby to naprawić i zeby mozna było pobrac odpowiedni plik json trzeba skorzystac z linku (dokładnie wczesniejszy skrypt z miniskrypt tak działał/działa) https://apivod.tvp.pl/tv/video/42549669/ tutaj po podaniu autoryzacji api/vod otrzymamy odpowiedni plik json.
tak jak zauwayzłem i napisałem na forum, wyglad ana to ze inne materiąły sa tez dostepne przez te metode, natomiast niekotre zdaja się byc dostepne tlyko przez te metode API.
tzreba by sprawdzać najpierw czy działa przez tokenizer a jak nie sprawdzać przez apivod dopiero w zaleznosci od tego co sie wydarzy wysweitlac link :)
źródło na forum: https://greasyfork.org/pl/forum/discussion/57515/x
edit. dodam jescze na przykłądu pewną rzecz....
mamy sobie materiały:
i teraz, dla numerka 2... skrypt reaguje i wyświetla guzik umozliwiajacy pobranie, ale niestety nie bedzie działać przez sytuacje opsiana powyzej.
dla numerka 1, skrypt nie wyswietla zadnego guzika, ale jak ręcznie wpiszemy: https://www.tvp.pl/shared/cdn/tokenizer_v2.php?object_id=42405307 to otrzymujemy poprawny json