5 changed files with 235 additions and 0 deletions
@ -0,0 +1,99 @@ |
|||||||
|
import { proxiedFetch } from "../helpers/fetch"; |
||||||
|
import { registerProvider } from "../helpers/register"; |
||||||
|
import { MWStreamQuality, MWStreamType } from "../helpers/streams"; |
||||||
|
import { MWMediaType } from "../metadata/types"; |
||||||
|
|
||||||
|
const sflixBase = "https://sflix.video"; |
||||||
|
|
||||||
|
registerProvider({ |
||||||
|
id: "sflix", |
||||||
|
displayName: "Sflix", |
||||||
|
rank: 50, |
||||||
|
type: [MWMediaType.MOVIE, MWMediaType.SERIES], |
||||||
|
async scrape({ media, episode, progress }) { |
||||||
|
let searchQuery = `${media.meta.title} `; |
||||||
|
|
||||||
|
if (media.meta.type === MWMediaType.MOVIE) |
||||||
|
searchQuery += media.meta.year ?? ""; |
||||||
|
|
||||||
|
if (media.meta.type === MWMediaType.SERIES) |
||||||
|
searchQuery += `S${String(media.meta.seasonData.number).padStart( |
||||||
|
2, |
||||||
|
"0" |
||||||
|
)}`;
|
||||||
|
|
||||||
|
const search = await proxiedFetch<any>( |
||||||
|
`/?s=${encodeURIComponent(searchQuery)}`, |
||||||
|
{ |
||||||
|
baseURL: sflixBase, |
||||||
|
} |
||||||
|
); |
||||||
|
const searchPage = new DOMParser().parseFromString(search, "text/html"); |
||||||
|
|
||||||
|
const moviePageUrl = searchPage |
||||||
|
.querySelector(".movies-list .ml-item:first-child a") |
||||||
|
?.getAttribute("href"); |
||||||
|
if (!moviePageUrl) throw new Error("Movie does not exist"); |
||||||
|
|
||||||
|
progress(25); |
||||||
|
|
||||||
|
const movie = await proxiedFetch<any>(moviePageUrl); |
||||||
|
const moviePage = new DOMParser().parseFromString(movie, "text/html"); |
||||||
|
|
||||||
|
progress(45); |
||||||
|
|
||||||
|
let outerEmbedSrc = null; |
||||||
|
if (media.meta.type === MWMediaType.MOVIE) { |
||||||
|
outerEmbedSrc = moviePage |
||||||
|
.querySelector("iframe") |
||||||
|
?.getAttribute("data-lazy-src"); |
||||||
|
} else if (media.meta.type === MWMediaType.SERIES) { |
||||||
|
const series = Array.from(moviePage.querySelectorAll(".desc p a")).map( |
||||||
|
(a) => ({ |
||||||
|
title: a.getAttribute("title"), |
||||||
|
link: a.getAttribute("href"), |
||||||
|
}) |
||||||
|
); |
||||||
|
|
||||||
|
const episodeNumber = media.meta.seasonData.episodes.find( |
||||||
|
(e) => e.id === episode |
||||||
|
)?.number; |
||||||
|
|
||||||
|
const targetSeries = series.find((s) => |
||||||
|
s.title?.endsWith(String(episodeNumber).padStart(2, "0")) |
||||||
|
); |
||||||
|
if (!targetSeries) throw new Error("Episode does not exist"); |
||||||
|
|
||||||
|
outerEmbedSrc = targetSeries.link; |
||||||
|
} |
||||||
|
if (!outerEmbedSrc) throw new Error("Outer embed source not found"); |
||||||
|
|
||||||
|
progress(65); |
||||||
|
|
||||||
|
const outerEmbed = await proxiedFetch<any>(outerEmbedSrc); |
||||||
|
const outerEmbedPage = new DOMParser().parseFromString( |
||||||
|
outerEmbed, |
||||||
|
"text/html" |
||||||
|
); |
||||||
|
|
||||||
|
const embedSrc = outerEmbedPage |
||||||
|
.querySelector("iframe") |
||||||
|
?.getAttribute("src"); |
||||||
|
if (!embedSrc) throw new Error("Embed source not found"); |
||||||
|
|
||||||
|
const embed = await proxiedFetch<string>(embedSrc); |
||||||
|
|
||||||
|
const streamUrl = embed.match(/file\s*:\s*"([^"]+\.mp4)"/)?.[1]; |
||||||
|
if (!streamUrl) throw new Error("Unable to get stream"); |
||||||
|
|
||||||
|
return { |
||||||
|
embeds: [], |
||||||
|
stream: { |
||||||
|
streamUrl, |
||||||
|
quality: MWStreamQuality.Q1080P, |
||||||
|
type: MWStreamType.MP4, |
||||||
|
captions: [], |
||||||
|
}, |
||||||
|
}; |
||||||
|
}, |
||||||
|
}); |
||||||
@ -0,0 +1,124 @@ |
|||||||
|
{ |
||||||
|
"global": { |
||||||
|
"name": "movie-web" |
||||||
|
}, |
||||||
|
"search": { |
||||||
|
"loading_series": "Fetchin' yer favorite series...", |
||||||
|
"loading_movie": "Fetchin' yer favorite movies...", |
||||||
|
"loadin'": "Loadin'...", |
||||||
|
"allResults": "That be all we 'ave, me hearty!", |
||||||
|
"noResults": "We couldn't find anythin' that matches yer search!", |
||||||
|
"allFailed": "Failed t' find media, walk the plank and try again!", |
||||||
|
"headingTitle": "Search results", |
||||||
|
"bookmarks": "Treasure Maps", |
||||||
|
"continueWatchin'": "Continue Watchin'", |
||||||
|
"title": "Wha' be ye wantin' to watch, me matey?", |
||||||
|
"placeholder": "Wha' be ye searchin' for?" |
||||||
|
}, |
||||||
|
"media": { |
||||||
|
"movie": "Movie", |
||||||
|
"series": "Series", |
||||||
|
"stopEditin'": "Stop editin'", |
||||||
|
"errors": { |
||||||
|
"genericTitle": "Shiver me timbers! It broke!", |
||||||
|
"failedMeta": "Ye can't trust the compass, failed to load meta", |
||||||
|
"mediaFailed": "We failed t' request the media ye asked fer, check yer internet connection, or Davy Jones's locker awaits ye!", |
||||||
|
"videoFailed": "Blimey! We encountered an error while playin' the video ye requested. If this keeps happening please report the issue to the <0>Discord server</0> or on <1>GitHub</1>." |
||||||
|
} |
||||||
|
}, |
||||||
|
"seasons": { |
||||||
|
"seasonAndEpisode": "S{{season}} E{{episode}}" |
||||||
|
}, |
||||||
|
"notFound": { |
||||||
|
"genericTitle": "Ahoy! I see nothin' on the horizon.", |
||||||
|
"backArrow": "Back to the port", |
||||||
|
"media": { |
||||||
|
"title": "Avast ye! Couldn't find that media", |
||||||
|
"description": "We couldn't find the media ye requested. Either it's been scuttled or ye tampered with the URL, ye scallywag!" |
||||||
|
}, |
||||||
|
"provider": { |
||||||
|
"title": "Walk the plank! This provider has been disabled", |
||||||
|
"description": "We had issues wit' the provider or 'twas too unstable t' use, so we had t' disable it. Try another one, arrr!" |
||||||
|
}, |
||||||
|
"page": { |
||||||
|
"title": "Avast ye! Couldn't find that page.", |
||||||
|
"description": "Arrr! We searched every inch o' the vessel: from the bilge to the crow's nest, from the keel to the topmast, but avast! We couldn't find the page ye be lookin' fer, me heartie." |
||||||
|
} |
||||||
|
}, |
||||||
|
"searchBar": { |
||||||
|
"movie": "Movie", |
||||||
|
"series": "Series", |
||||||
|
"Search": "Search" |
||||||
|
}, |
||||||
|
"videoPlayer": { |
||||||
|
"findingBestVideo": "Finding the best video fer ye, hoist the colors!", |
||||||
|
"noVideos": "Blistering barnacles, couldn't find any videos fer ye. Ye need a better map!", |
||||||
|
"loading": "Loading...", |
||||||
|
"backToHome": "Back to the port, mates!", |
||||||
|
"backToHomeShort": "Back", |
||||||
|
"seasonAndEpisode": "S{{season}} E{{episode}}", |
||||||
|
"timeLeft": "{{timeLeft}} left", |
||||||
|
"finishAt": "Finish at {{timeFinished}}", |
||||||
|
"buttons": { |
||||||
|
"episodes": "Episodes", |
||||||
|
"source": "Source", |
||||||
|
"captions": "Captions", |
||||||
|
"download": "Download", |
||||||
|
"settings": "Settings", |
||||||
|
"pictureInPicture": "Spyglass view", |
||||||
|
"playbackSpeed": "Set sail!" |
||||||
|
}, |
||||||
|
"popouts": { |
||||||
|
"back": "Avast ye, go back!", |
||||||
|
"sources": "Wha' provider do ye want to use?", |
||||||
|
"seasons": "Choose which season you wants to watch!", |
||||||
|
"captions": "Select a subtitle language, me hearty!", |
||||||
|
"playbackSpeed": "Change the speed of Blackbeard's ship!", |
||||||
|
"customPlaybackSpeed": "Set a custom playback speed", |
||||||
|
"captionPreferences": { |
||||||
|
"title": "Customize yer captions", |
||||||
|
"delay": "Delay", |
||||||
|
"fontSize": "Size", |
||||||
|
"opacity": "Opacity", |
||||||
|
"color": "Color" |
||||||
|
}, |
||||||
|
"episode": "E{{index}} - {{title}}", |
||||||
|
"noCaptions": "No captions, hoist the Jolly Roger!", |
||||||
|
"linkedCaptions": "Linked captions, drop anchor!", |
||||||
|
"customCaption": "Custom caption, arrr!", |
||||||
|
"uploadCustomCaption": "Upload yer own caption!", |
||||||
|
"noEmbeds": "No embeds we be found fer this source", |
||||||
|
|
||||||
|
"errors": { |
||||||
|
"loadingWentWong": "Shiver me timbers! Somethin' went wrong loadin' the episodes fer {{seasonTitle}}", |
||||||
|
"embedsError": "Blimey! Somethin' went wrong loadin' the embeds fer this thin' that ye like" |
||||||
|
}, |
||||||
|
"descriptions": { |
||||||
|
"sources": "Wha' provider do ye wants to use?", |
||||||
|
"embeds": "Choose which video to view", |
||||||
|
"seasons": "Choose which season ye wants to watch", |
||||||
|
"episode": "Pick an episode", |
||||||
|
"captions": "Choose a subtitle language", |
||||||
|
"captionPreferences": "Make subtitles look how ye wants it", |
||||||
|
"playbackSpeed": "Change the playback speed" |
||||||
|
} |
||||||
|
}, |
||||||
|
"errors": { |
||||||
|
"fatalError": "Blow me down! The video player encounted a fatal error, please report it to the <0>Discord server</0> or on <1>GitHub</1>." |
||||||
|
} |
||||||
|
}, |
||||||
|
"settings": { |
||||||
|
"title": "Settings", |
||||||
|
"language": "Language", |
||||||
|
"captionLanguage": "Caption Language" |
||||||
|
}, |
||||||
|
"v3": { |
||||||
|
"newSiteTitle": "New version now released!", |
||||||
|
"newDomain": "https://movie-web.app", |
||||||
|
"newDomainText": "movie-web will soon be movin' to a new domain: <0>https://movie-web.app</0>. Make sure to update all yer bookmarks as <1>the ole website will stop workin' on {{date}}.</1>", |
||||||
|
"tireless": "We've worked tirelessly on this new update, we hope ye will enjoy wha' we've been cookin' up fer the past months.", |
||||||
|
"leaveAnnouncement": "Take me thar!" |
||||||
|
}, |
||||||
|
"casting": { "casting": "Casting to device..." }, |
||||||
|
"errors": { "offline": "Avast! Check yer internet connection" } |
||||||
|
} |
||||||
Loading…
Reference in new issue