1 changed files with 162 additions and 0 deletions
@ -0,0 +1,162 @@ |
|||||||
|
import { MWEmbedType } from "../helpers/embed"; |
||||||
|
import { proxiedFetch } from "../helpers/fetch"; |
||||||
|
import { registerProvider } from "../helpers/register"; |
||||||
|
import { MWMediaType } from "../metadata/types"; |
||||||
|
|
||||||
|
const gomoviesBase = "https://gomovies.sx"; |
||||||
|
|
||||||
|
registerProvider({ |
||||||
|
id: "gomovies", |
||||||
|
displayName: "GOmovies", |
||||||
|
rank: 300, |
||||||
|
type: [MWMediaType.MOVIE, MWMediaType.SERIES], |
||||||
|
|
||||||
|
async scrape({ media, episode }) { |
||||||
|
const search = await proxiedFetch<any>("/ajax/search", { |
||||||
|
baseURL: gomoviesBase, |
||||||
|
method: "POST", |
||||||
|
body: JSON.stringify({ |
||||||
|
keyword: media.meta.title, |
||||||
|
}), |
||||||
|
headers: { |
||||||
|
"X-Requested-With": "XMLHttpRequest", |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
const searchPage = new DOMParser().parseFromString(search, "text/html"); |
||||||
|
const mediaElements = searchPage.querySelectorAll("a.nav-item"); |
||||||
|
|
||||||
|
const mediaData = Array.from(mediaElements).map((movieEl) => { |
||||||
|
const name = movieEl?.querySelector("h3.film-name")?.textContent; |
||||||
|
const year = movieEl?.querySelector( |
||||||
|
"div.film-infor span:first-of-type" |
||||||
|
)?.textContent; |
||||||
|
const path = movieEl.getAttribute("href"); |
||||||
|
return { name, year, path }; |
||||||
|
}); |
||||||
|
|
||||||
|
const targetMedia = mediaData.find( |
||||||
|
(m) => |
||||||
|
m.name === media.meta.title && |
||||||
|
(media.meta.type === MWMediaType.MOVIE |
||||||
|
? m.year === media.meta.year |
||||||
|
: true) |
||||||
|
); |
||||||
|
if (!targetMedia?.path) throw new Error("Media not found"); |
||||||
|
|
||||||
|
// Example movie path: /movie/watch-{slug}-{id}
|
||||||
|
// Example series path: /tv/watch-{slug}-{id}
|
||||||
|
let mediaId = targetMedia.path.split("-").pop()?.replace("/", ""); |
||||||
|
|
||||||
|
let sources = null; |
||||||
|
if (media.meta.type === MWMediaType.SERIES) { |
||||||
|
const seasons = await proxiedFetch<any>( |
||||||
|
`/ajax/v2/tv/seasons/${mediaId}`, |
||||||
|
{ |
||||||
|
baseURL: gomoviesBase, |
||||||
|
headers: { |
||||||
|
"X-Requested-With": "XMLHttpRequest", |
||||||
|
}, |
||||||
|
} |
||||||
|
); |
||||||
|
|
||||||
|
const seasonsEl = new DOMParser() |
||||||
|
.parseFromString(seasons, "text/html") |
||||||
|
.querySelectorAll(".ss-item"); |
||||||
|
|
||||||
|
const seasonsData = [...seasonsEl].map((season) => ({ |
||||||
|
number: season.innerHTML.replace("Season ", ""), |
||||||
|
dataId: season.getAttribute("data-id"), |
||||||
|
})); |
||||||
|
|
||||||
|
const seasonNumber = media.meta.seasonData.number; |
||||||
|
const targetSeason = seasonsData.find( |
||||||
|
(season) => +season.number === seasonNumber |
||||||
|
); |
||||||
|
if (!targetSeason) throw new Error("Season not found"); |
||||||
|
|
||||||
|
const episodes = await proxiedFetch<any>( |
||||||
|
`/ajax/v2/season/episodes/${targetSeason.dataId}`, |
||||||
|
{ |
||||||
|
baseURL: gomoviesBase, |
||||||
|
headers: { |
||||||
|
"X-Requested-With": "XMLHttpRequest", |
||||||
|
}, |
||||||
|
} |
||||||
|
); |
||||||
|
|
||||||
|
const episodesEl = new DOMParser() |
||||||
|
.parseFromString(episodes, "text/html") |
||||||
|
.querySelectorAll(".eps-item"); |
||||||
|
|
||||||
|
const episodesData = Array.from(episodesEl).map((ep) => ({ |
||||||
|
dataId: ep.getAttribute("data-id"), |
||||||
|
number: ep |
||||||
|
.querySelector("strong") |
||||||
|
?.textContent?.replace("Eps", "") |
||||||
|
.replace(":", "") |
||||||
|
.trim(), |
||||||
|
})); |
||||||
|
|
||||||
|
const episodeNumber = media.meta.seasonData.episodes.find( |
||||||
|
(e) => e.id === episode |
||||||
|
)?.number; |
||||||
|
|
||||||
|
const targetEpisode = episodesData.find((ep) => |
||||||
|
ep.number ? +ep.number : ep.number === episodeNumber |
||||||
|
); |
||||||
|
|
||||||
|
if (!targetEpisode?.dataId) throw new Error("Episode not found"); |
||||||
|
|
||||||
|
mediaId = targetEpisode.dataId; |
||||||
|
|
||||||
|
sources = await proxiedFetch<any>(`/ajax/v2/episode/servers/${mediaId}`, { |
||||||
|
baseURL: gomoviesBase, |
||||||
|
headers: { |
||||||
|
"X-Requested-With": "XMLHttpRequest", |
||||||
|
}, |
||||||
|
}); |
||||||
|
} else { |
||||||
|
sources = await proxiedFetch<any>(`/ajax/movie/episodes/${mediaId}`, { |
||||||
|
baseURL: gomoviesBase, |
||||||
|
headers: { |
||||||
|
"X-Requested-With": "XMLHttpRequest", |
||||||
|
}, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
const upcloud = new DOMParser() |
||||||
|
.parseFromString(sources, "text/html") |
||||||
|
.querySelector('a[title*="upcloud" i]'); |
||||||
|
|
||||||
|
const upcloudDataId = |
||||||
|
upcloud?.getAttribute("data-id") ?? upcloud?.getAttribute("data-linkid"); |
||||||
|
|
||||||
|
if (!upcloudDataId) throw new Error("Upcloud source not available"); |
||||||
|
|
||||||
|
const upcloudSource = await proxiedFetch<{ |
||||||
|
type: "iframe" | string; |
||||||
|
link: string; |
||||||
|
sources: []; |
||||||
|
title: string; |
||||||
|
tracks: []; |
||||||
|
}>(`/ajax/sources/${upcloudDataId}`, { |
||||||
|
baseURL: gomoviesBase, |
||||||
|
headers: { |
||||||
|
"X-Requested-With": "XMLHttpRequest", |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
if (!upcloudSource.link || upcloudSource.type !== "iframe") |
||||||
|
throw new Error("No upcloud stream found"); |
||||||
|
|
||||||
|
return { |
||||||
|
embeds: [ |
||||||
|
{ |
||||||
|
type: MWEmbedType.UPCLOUD, |
||||||
|
url: upcloudSource.link, |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
}, |
||||||
|
}); |
||||||
Loading…
Reference in new issue