Closed ozz2024 closed 9 months ago
@ozz2024 Hej, dzięki za zgłoszenie! Mógłbyś proszę sprawdzić kilka rzeczy:
Jeśli po sprawdzeniu tych rzeczy dalej nie działa, daj mi proszę info:
Cześć,
mam dokładnie ten sam problem, wyświetla się komunikat:
VM1671:160 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'href')
at getAllRates (
Komunikat wyświetla się po informacji, że: pobrano 100 z 1357
Próbowałem uruchomić ten skrypt kilkakrotnie, za każdym razem ten sam błąd.
A propos Twoich pytań to: 1- tak 2- tak 3 - tak 4 - nie 5 - tak
To jest dokładnie po 100 filmie (101 film) U mnie to jest "Georgie ma się dobrze".
@podwieczorekk Jeszcze potrzebuję info jakiej przeglądarki używasz. Testowałem wszystko na chromie, i o ile się nie przełącza na inne karty, to wszystko działa u mnie jak należy.
Próbowałem zarówno na Chrome jak i na Mozilli, w obu przypadkach ten sam błąd.
@podwieczorekk Spróbuj proszę tej wersji poniżej i jeśli się znowu wywali, podeśli mi to co jest w HTML i index:
function loadAllInfiniteScrollChildren(allMoviesContainer, expectedChildCount) {
function scrollToBottom() {
window.scrollTo(0, document.body.scrollHeight);
}
return new Promise((resolve, reject) => {
if (!allMoviesContainer) {
reject("Błąd skryptu: Target element not found.");
return;
}
if (!expectedChildCount) {
reject("Błąd skryptu: No children found");
return;
}
const currentChildCount = allMoviesContainer.children.length;
if (currentChildCount >= expectedChildCount) {
resolve(allMoviesContainer.children);
}
const checkAndScroll = (mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === "childList") {
scrollToBottom();
const currentChildCount = allMoviesContainer.children.length;
if (currentChildCount >= expectedChildCount) {
// All expected children are now visible, scrolling is done
observer.disconnect();
resolve(allMoviesContainer.children);
}
}
}
};
const observer = new MutationObserver(checkAndScroll);
observer.observe(allMoviesContainer, { childList: true, subtree: true });
// Initialize creating new children
scrollToBottom();
});
}
function formatDate(dateNumber) {
const dateStr = dateNumber.toString();
const year = dateStr.substring(0, 4);
const month = dateStr.substring(4, 6);
const day = dateStr.substring(6, 8);
return `${year}-${month}-${day}`;
}
async function getMovieData(movieUrl) {
const parser = new DOMParser();
const DOMContent = await fetch(movieUrl, {
method: "GET",
headers: {
Cookie: document.cookie,
},
})
.then((response) => {
if (!response.ok) {
throw new Error(`Bład skryptu podczas ściągania danych filmu`);
}
return response.text();
})
.catch((error) => {
console.log(error);
return undefined;
});
if (!DOMContent) {
return undefined;
}
const htmlDocument = parser.parseFromString(DOMContent, "text/html");
let title = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__originalTitle"
)?.textContent;
if (!title) {
title = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__title"
)?.textContent;
}
let year = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__year"
)?.textContent;
year = year.split(" - ")[0]; // handle serial dates
const movieId = htmlDocument.querySelector("[data-film-id]")?.dataset?.filmId;
return {
movieId,
movieData: {
Title: title.includes(",") ? `"${title}"` : title,
Year: year,
},
};
}
async function getRatingData(movieId, contentType) {
const movieUrl = `https://www.filmweb.pl/api/v1/logged/vote/${contentType}/${movieId}/details`;
const ratingJSON = await fetch(movieUrl, {
method: "GET",
headers: {
Cookie: document.cookie,
},
})
.then((response) => {
if (!response.ok) {
throw new Error(`Bład skryptu podczas ściągania oceny filmu`);
}
return response.json();
})
.catch((error) => {
console.log(error);
return undefined;
});
if (!ratingJSON) {
return undefined;
}
return {
WatchedDate: formatDate(ratingJSON.viewDate),
...(ratingJSON.rate >= 1 && { Rating10: ratingJSON.rate }),
};
}
async function waitForElement(baseElement, selector, timeout = 5000) {
let timeoutId;
return new Promise((resolve) => {
if (baseElement.querySelector(selector)) {
return resolve(baseElement.querySelector(selector));
}
const observer = new MutationObserver((mutations) => {
if (baseElement.querySelector(selector)) {
timeoutId && clearTimeout(timeoutId);
observer.disconnect();
resolve(baseElement.querySelector(selector));
}
});
observer.observe(baseElement, {
childList: true,
subtree: true,
});
timeoutId = setTimeout(() => {
observer.disconnect();
resolve(undefined);
}, timeout);
});
}
async function getAllRates() {
const contentType = window.location.href.split("/").pop();
const allMoviesContainer = document.querySelector(
'div[data-group="userPage"] section > div:nth-child(2)'
);
const expectedChildCount = Number(
document.querySelector(
'div[data-group="userPage"] li > a.active[data-counter]'
).dataset.counter ?? ""
);
let allMoviesElements;
try {
allMoviesElements = await loadAllInfiniteScrollChildren(
allMoviesContainer,
expectedChildCount
);
} catch (error) {
throw new Error(error);
}
const allRates = [];
for (let i = 0; i <= expectedChildCount - 1; i++) {
const movieLinkChild = await waitForElement(
allMoviesElements[i],
"a > [data-btn-center-sel=poster]"
);
const movieLink = movieLinkChild?.parentElement?.href;
try {
if (!movieLink) {
console.log("HTML: ", allMoviesElements[i]);
console.log("index: ", i);
throw Error("Nie znaleziono filmu");
}
const { movieId, movieData } = await getMovieData(movieLink);
if (!movieId || !movieData) {
continue;
}
const ratingData = await getRatingData(movieId, contentType);
allRates.push({ ...movieData, ...ratingData });
} catch (e) {
console.log(e);
return allRates;
}
console.log("pobrano " + (i + 1) + " z " + expectedChildCount);
}
return allRates;
}
function download(filename, text) {
const element = document.createElement("a");
element.setAttribute(
"href",
"data:text/plain;charset=utf-8," + encodeURIComponent(text)
);
element.setAttribute("download", filename);
element.style.display = "none";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function arrayToCsv(allRates) {
let csvRates = Object.keys(allRates[0]).join(",") + "\n";
let filesArray = [];
for (let i = 0; i < allRates.length; i++) {
// Split csv for rate count > 1800
if (i % 1799 == 0 && i > 0) {
filesArray.push(csvRates);
csvRates = Object.keys(allRates[0]).join(",") + "\n";
}
csvRates += Object.values(allRates[i]).join(",");
csvRates += "\n";
}
filesArray.push(csvRates);
return filesArray;
}
async function main() {
console.log("Rozpoczynam pobieranie, cierpliwości...");
console.log("Proszę nie zamykać, przełączać, ani minimalizować tego okna!");
let allRates = await getAllRates();
console.log("rozpoczynam ściąganie pliku csv");
let csvRates = arrayToCsv(allRates);
for (let i = 0; i < csvRates.length; i++) {
download(`Filmweb2Letterboxd_watched_${i}.csv`, csvRates[i]);
}
}
main();
Tym razem również zatrzymało się na 100, ale zamiast się wywalić pojawiła się propozycja pobrania pliku csv z tymi 100 filmami (i rzeczywiście plik posiada 100 tytułów).
Co do treści, którą miałem skopiować, to tutaj:
@podwieczorekk nie było nic w HTML, puste?
Mam ten sam problem, po stówie się wywala
@JSerwatka HTML zwraca pustego diva (z twojego zmodyfikowanego skryptu):
<div class="sc-jBqsNv hPEvkm"></div>
Error: Nie znaleziono filmu
at getAllRates (
@pgarbocz dzięki za podesłanie. Wygląda na to, że zawartość filmu nie zdążyła się wczytać. Zrobię kilka modyfikacji i spróbujemy jeszcze raz, bo nie jestem w stanie tego odtworzyć u siebie
@pgarbocz @podwieczorekk Sprawdźcie proszę tę wersję:
function loadAllInfiniteScrollChildren(allMoviesContainer, expectedChildCount) {
function scrollToBottom() {
window.scrollTo(0, document.body.scrollHeight);
}
return new Promise((resolve, reject) => {
if (!allMoviesContainer) {
reject("Błąd skryptu: Target element not found.");
return;
}
if (!expectedChildCount) {
reject("Błąd skryptu: No children found");
return;
}
const currentChildCount = allMoviesContainer.children.length;
if (currentChildCount >= expectedChildCount) {
resolve(allMoviesContainer.children);
}
const checkAndScroll = (mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === "childList") {
scrollToBottom();
const currentChildCount = allMoviesContainer.children.length;
if (currentChildCount >= expectedChildCount) {
// All expected children are now visible, scrolling is done
observer.disconnect();
resolve(allMoviesContainer);
}
}
}
};
const observer = new MutationObserver(checkAndScroll);
observer.observe(allMoviesContainer, { childList: true, subtree: true });
// Initialize creating new children
scrollToBottom();
});
}
function formatDate(dateNumber) {
const dateStr = dateNumber.toString();
const year = dateStr.substring(0, 4);
const month = dateStr.substring(4, 6);
const day = dateStr.substring(6, 8);
return `${year}-${month}-${day}`;
}
async function getMovieData(movieUrl) {
const parser = new DOMParser();
const DOMContent = await fetch(movieUrl, {
method: "GET",
headers: {
Cookie: document.cookie,
},
})
.then((response) => {
if (!response.ok) {
throw new Error(`Bład skryptu podczas ściągania danych filmu`);
}
return response.text();
})
.catch((error) => {
console.log(error);
return undefined;
});
if (!DOMContent) {
return undefined;
}
const htmlDocument = parser.parseFromString(DOMContent, "text/html");
let title = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__originalTitle"
)?.textContent;
if (!title) {
title = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__title"
)?.textContent;
}
let year = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__year"
)?.textContent;
year = year.split(" - ")[0]; // handle serial dates
const movieId = htmlDocument.querySelector("[data-film-id]")?.dataset?.filmId;
return {
movieId,
movieData: {
Title: title.includes(",") ? `"${title}"` : title,
Year: year,
},
};
}
async function getRatingData(movieId, contentType) {
const movieUrl = `https://www.filmweb.pl/api/v1/logged/vote/${contentType}/${movieId}/details`;
const ratingJSON = await fetch(movieUrl, {
method: "GET",
headers: {
Cookie: document.cookie,
},
})
.then((response) => {
if (!response.ok) {
throw new Error(`Bład skryptu podczas ściągania oceny filmu`);
}
return response.json();
})
.catch((error) => {
console.log(error);
return undefined;
});
if (!ratingJSON) {
return undefined;
}
return {
WatchedDate: formatDate(ratingJSON.viewDate),
...(ratingJSON.rate >= 1 && { Rating10: ratingJSON.rate }),
};
}
async function waitForElement(baseElement, selector, timeout = 5000) {
let timeoutId;
return new Promise((resolve) => {
if (baseElement.querySelector(selector)) {
return resolve(baseElement.querySelector(selector));
}
const observer = new MutationObserver((mutations) => {
if (baseElement.querySelector(selector)) {
timeoutId && clearTimeout(timeoutId);
observer.disconnect();
resolve(baseElement.querySelector(selector));
}
});
observer.observe(baseElement, {
childList: true,
subtree: true,
});
timeoutId = setTimeout(() => {
observer.disconnect();
resolve(undefined);
}, timeout);
});
}
async function getAllRates() {
const contentType = window.location.href.split("/").pop();
const MOVIE_GRID_SECTION_SELECTOR = 'div[data-group="userPage"] section > div:nth-child(2)'
const allMoviesContainer = document.querySelector(MOVIE_GRID_SECTION_SELECTOR);
const expectedChildCount = Number(
document.querySelector(
'div[data-group="userPage"] li > a.active[data-counter]'
).dataset.counter ?? ""
);
let allMoviesElements;
try {
allMoviesElements = await loadAllInfiniteScrollChildren(
allMoviesContainer,
expectedChildCount
);
} catch (error) {
throw new Error(error);
}
const allRates = [];
for (let i = 0; i <= expectedChildCount - 1; i++) {
const next_movie_selector = `${MOVIE_GRID_SECTION_SELECTOR} > div:nth-child(${i+1}) a > [data-btn-center-sel=poster]`
const movieLinkChild = await waitForElement(
document,
next_movie_selector
);
const movieLink = movieLinkChild?.parentElement?.href;
try {
if (!movieLink) {
console.log("HTML: ", movieLinkChild?.parentElement?.parentElement);
console.log("index: ", i);
throw Error("Nie znaleziono filmu");
}
const { movieId, movieData } = await getMovieData(movieLink);
if (!movieId || !movieData) {
continue;
}
const ratingData = await getRatingData(movieId, contentType);
allRates.push({ ...movieData, ...ratingData });
} catch (e) {
console.log(e);
return allRates;
}
console.log("pobrano " + (i + 1) + " z " + expectedChildCount);
}
return allRates;
}
function download(filename, text) {
const element = document.createElement("a");
element.setAttribute(
"href",
"data:text/plain;charset=utf-8," + encodeURIComponent(text)
);
element.setAttribute("download", filename);
element.style.display = "none";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function arrayToCsv(allRates) {
let csvRates = Object.keys(allRates[0]).join(",") + "\n";
let filesArray = [];
for (let i = 0; i < allRates.length; i++) {
// Split csv for rate count > 1800
if (i % 1799 == 0 && i > 0) {
filesArray.push(csvRates);
csvRates = Object.keys(allRates[0]).join(",") + "\n";
}
csvRates += Object.values(allRates[i]).join(",");
csvRates += "\n";
}
filesArray.push(csvRates);
return filesArray;
}
async function main() {
console.log("Rozpoczynam pobieranie, cierpliwości...");
console.log("Proszę nie zamykać, przełączać, ani minimalizować tego okna!");
let allRates = await getAllRates();
console.log("rozpoczynam ściąganie pliku csv");
let csvRates = arrayToCsv(allRates);
for (let i = 0; i < csvRates.length; i++) {
download(`Filmweb2Letterboxd_watched_${i}.csv`, csvRates[i]);
}
}
main();
U mnie nie działa, ponownie zatrzymuje się na 100. HTML mam oznczony jako "undefined". Treść błędu:
Error: Nie znaleziono filmu
at getAllRates (
Po 100 next_movie_selector zwraca
div[data-group="userPage"] section > div:nth-child(2) > div:nth-child(101) a > [data-btn-center-sel=poster]
ale już movieLinkChild jest undefined
Sprawdzałem:
Po spowolnieniu przy 100 filmie wyskakuje: "Error: Bład skryptu podczas ściągania oceny filmu" i w zakładce błędów, dostaję następujące rzeczy:
@podwieczorekk @pgarbocz dajcie znać, czy coś takiego się u Was pojawia.
Jeśli nie, to jest jeszcze jeden sposób, żeby sprawdzić co się dzieje. Jakby któryś z Was w ustawieniach prywatności na filmwebie zmienił "Moje oceny" na wszyscy i podesłał mi link do swojego konta (/user/
Próbowałem uruchomić ten skrypt na profilu publicznym jakiegokolwiek krytyka ale wtedy leci od razu błąd
Uncaught (in promise) Error: Błąd skryptu: Target element not found.
at getAllRates (
Po 100 next_movie_selector zwraca
div[data-group="userPage"] section > div:nth-child(2) > div:nth-child(101) a > [data-btn-center-sel=poster]
ale już movieLinkChild jest undefined
Możliwe, że a > [data-btn-center-sel=poster]
nie działa dla któregoś z filmów (niestety nie ma żadnego lepszego path, żeby to wyciągnąć), ale to nie tłumaczy, dlaczego dzieje się to zawsze po 100.
@pgarbocz Jakiś konkretny krytyk, żebyśmy mieli ten sam punkt odniesienia?
Myślę że się nie obrazi: https://www.filmweb.pl/user/sobol4ever#/votes/film
Z tego co widze to paginacja jest zrobiona po 100 elementów na page, więc wygląda jakby z kolejnych stron nie potrafił ładować.
@pgarbocz dobra, udało mi się odtworzyć to na innym kompie i koncie, biorę się do roboty
Ok, mam nadzieję, że tym razem pójdzie
@pgarbocz @ozz2024 @podwieczorekk Sprawdźcie proszę tę wersję:
function loadAllInfiniteScrollChildren(allMoviesContainer, expectedChildCount) {
function scrollToBottom() {
window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
}
function checkIfAllElementsLoaded() {
let allChildrenLoaded = Array.from(allMoviesContainer.children).every((child => {
if (child.classList.length == 0 || child.classList.contains("hide")) {
return true
}
return child.querySelector("[data-btn-center-sel=poster]")
}))
const currentChildCount = allMoviesContainer.children.length;
if (currentChildCount >= expectedChildCount && allChildrenLoaded) {
return true
}
return false
}
return new Promise((resolve, reject) => {
if (!allMoviesContainer) {
reject("Błąd skryptu: Target element not found.");
return;
}
if (!expectedChildCount) {
reject("Błąd skryptu: No children found");
return;
}
if (checkIfAllElementsLoaded()) {
resolve(allMoviesContainer.children);
}
const checkAndScroll = (mutationsList) => {
for (const mutation of mutationsList) {
if (checkIfAllElementsLoaded()) {
// All expected children are now visible, scrolling is done
scrollToBottom()
observer.disconnect();
resolve(allMoviesContainer.children);
} else {
scrollToBottom()
}
}
};
const observer = new MutationObserver(checkAndScroll);
observer.observe(allMoviesContainer, { childList: true, subtree: true });
// Initialize creating new children
scrollToBottom();
});
}
function formatDate(dateNumber) {
const dateStr = dateNumber?.toString();
if (!dateStr) {
return `2000-01-01`
}
const year = dateStr.substring(0, 4);
const month = dateStr.substring(4, 6);
const day = dateStr.substring(6, 8);
return `${year}-${month}-${day}`;
}
async function getMovieData(movieUrl) {
const parser = new DOMParser();
const DOMContent = await fetch(movieUrl, {
method: "GET",
headers: {
Cookie: document.cookie,
},
})
.then((response) => {
if (!response.ok) {
throw new Error(`Bład skryptu podczas ściągania danych filmu`);
}
return response.text();
})
.catch((error) => {
console.log(error);
return undefined;
});
if (!DOMContent) {
return undefined;
}
const htmlDocument = parser.parseFromString(DOMContent, "text/html");
let title = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__originalTitle"
)?.textContent;
if (!title) {
title = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__title"
)?.textContent;
}
let year = htmlDocument.querySelector(
".filmCoverSection__titleDetails > .filmCoverSection__year"
)?.textContent;
year = year.split(" - ")[0]; // handle serial dates
const movieId = htmlDocument.querySelector("[data-film-id]")?.dataset?.filmId;
return {
movieId,
movieData: {
Title: title.includes(",") ? `"${title}"` : title,
Year: year,
},
};
}
async function getRatingData(movieId, contentType) {
const movieUrl = `https://www.filmweb.pl/api/v1/logged/vote/${contentType}/${movieId}/details`;
const ratingJSON = await fetch(movieUrl, {
method: "GET",
headers: {
Cookie: document.cookie,
},
})
.then((response) => {
if (!response.ok) {
throw new Error(`Bład skryptu podczas ściągania oceny filmu`);
}
return response.json();
})
.catch((error) => {
console.log(error);
return undefined;
});
if (!ratingJSON) {
return undefined;
}
return {
WatchedDate: formatDate(ratingJSON.viewDate),
...(ratingJSON.rate >= 1 && { Rating10: ratingJSON.rate }),
};
}
async function waitForElement(baseElement, selector, timeout = 5000) {
let timeoutId;
return new Promise((resolve) => {
if (baseElement.querySelector(selector)) {
return resolve(baseElement.querySelector(selector));
}
const observer = new MutationObserver((mutations) => {
if (baseElement.querySelector(selector)) {
timeoutId && clearTimeout(timeoutId);
observer.disconnect();
resolve(baseElement.querySelector(selector));
}
});
observer.observe(baseElement, {
childList: true,
subtree: true,
});
timeoutId = setTimeout(() => {
observer.disconnect();
resolve(undefined);
}, timeout);
});
}
async function getAllRates() {
const contentType = window.location.href.split("/").pop();
const allMoviesContainer = document.querySelector('div[data-group="userPage"] section > div:nth-child(2)');
const expectedChildCount = Number(
document.querySelector(
'div[data-group="userPage"] li > a.active[data-counter]'
).dataset.counter ?? ""
);
let allMoviesElements;
try {
allMoviesElements = await loadAllInfiniteScrollChildren(
allMoviesContainer,
expectedChildCount
);
} catch (error) {
throw new Error(error);
}
const allRates = [];
for (let i = 0; i <= expectedChildCount - 1; i++) {
const movieLink = allMoviesElements[i].querySelector("a")?.href;
try {
if (!movieLink) {
console.log("HTML: ", allMoviesElements[i]);
console.log("index: ", i);
throw Error("Nie znaleziono filmu");
}
const { movieId, movieData } = await getMovieData(movieLink);
if (!movieId || !movieData) {
continue;
}
const ratingData = await getRatingData(movieId, contentType);
allRates.push({ ...movieData, ...ratingData });
} catch (e) {
console.log(e);
return allRates;
}
console.log("pobrano " + (i + 1) + " z " + expectedChildCount);
}
return allRates;
}
function download(filename, text) {
const element = document.createElement("a");
element.setAttribute(
"href",
"data:text/plain;charset=utf-8," + encodeURIComponent(text)
);
element.setAttribute("download", filename);
element.style.display = "none";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function arrayToCsv(allRates) {
let csvRates = Object.keys(allRates[0]).join(",") + "\n";
let filesArray = [];
for (let i = 0; i < allRates.length; i++) {
// Split csv for rate count > 1800
if (i % 1799 == 0 && i > 0) {
filesArray.push(csvRates);
csvRates = Object.keys(allRates[0]).join(",") + "\n";
}
csvRates += Object.values(allRates[i]).join(",");
csvRates += "\n";
}
filesArray.push(csvRates);
return filesArray;
}
async function main() {
console.log("Rozpoczynam pobieranie, cierpliwości...");
console.log("Proszę nie zamykać, przełączać, ani minimalizować tego okna!");
let allRates = await getAllRates();
console.log("rozpoczynam ściąganie pliku csv");
let csvRates = arrayToCsv(allRates);
for (let i = 0; i < csvRates.length; i++) {
download(`Filmweb2Letterboxd_watched_${i}.csv`, csvRates[i]);
}
}
main();
@JSerwatka teraz śmiga, dzięki wielkie!
Może warto do readme dodać poradę, żeby po analizie importu na letterboxd, zaznaczyć checkboxa Hide successful matches, bo wtedy można wyłapać te których nie znalazł i powprowadzać im prawidłowe nazwy. Czasem po prostu po tytule z filmweba nie potrafi odnaleźć na letterboxd.
A seriali nie polecam na razie importować, bo nie istnieją w letterboxd i mapuje do najbardziej pasujących tytułów, ale ogłosili że w tym roku dodadzą seriale.
Mi wciąż nie działa, ani n Chrome, ani na Mozilli. :(
@pgarbocz
Może warto do readme dodać poradę, żeby po analizie importu na letterboxd, zaznaczyć checkboxa Hide successful matches, bo wtedy można wyłapać te których nie znalazł i powprowadzać im prawidłowe nazwy. Czasem po prostu po tytule z filmweba nie potrafi odnaleźć na letterboxd.
Dzięki, dobry pomysł. Ja wyciągam najpierw oryginalny tytuł, bo w letterboxd szukanie po tytule polskim jest co najmniej problematyczne
A seriali nie polecam na razie importować, bo nie istnieją w letterboxd i mapuje do najbardziej pasujących tytułów, ale ogłosili że w tym roku dodadzą seriale.
Potwierdzam, że z serialami jest kompletny chaos, ale dobrze, że wreszcie to łatają
W ogóle jestem w trakcie robienia rozszerzenia do Chroma łatającego wiele problemów letterboxd, więc stay tuned
@ozz2024 Spojrzę jeszcze jutro lub pojutrze na to. Na razie robiłem takie łatanie na szybko.
Error: Nie znaleziono filmu
at getAllRates (:197:15)
at async main (:252:18)
+ pusty HTML?
Spróbowałam na komputerze stacjonarnym i wszystko dobrze działa. To musiał być problem z moim laptopem. Oba mają windows.
@ozz2024 dzięki za info, zobaczę co da się zrobić, żeby działało tak samo, niezależnie od sprzętu
Po setnym filmie wyskakuje błąd: "Uncaught (in promise) TypeError: Cannot read properties of null (reading 'href')."