diff --git a/dist/Joya9tv/catalog.js b/dist/Joya9tv/catalog.js new file mode 100644 index 0000000..367d39a --- /dev/null +++ b/dist/Joya9tv/catalog.js @@ -0,0 +1 @@ +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.catalog=void 0,exports.catalog=[{title:"Latest",filter:""},{title:"Bangali-Movies",filter:"genre/bengali-movies/"}]; \ No newline at end of file diff --git a/dist/Joya9tv/episodes.js b/dist/Joya9tv/episodes.js new file mode 100644 index 0000000..161fba0 --- /dev/null +++ b/dist/Joya9tv/episodes.js @@ -0,0 +1 @@ +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getEpisodes=void 0;const getEpisodes=function({url:url,providerContext:providerContext}){const{axios:axios,cheerio:cheerio,commonHeaders:headers}=providerContext;return axios.get(url,{headers:headers}).then(res=>{const $=cheerio.load(res.data),container=$("ul:has(p.font-bold:contains('Episode'))").first(),episodes=[];return container.find("p.font-bold").each((_,element)=>{const el=$(element);let title=el.text().trim();if(!title)return;let currentElement=el.parent();for(;currentElement.next().length&&!currentElement.next().find("p.font-bold").length;)currentElement=currentElement.next(),currentElement.find("a[href]").each((_,a)=>{var _a;const href=null===(_a=$(a).attr("href"))||void 0===_a?void 0:_a.trim();href&&(href.includes("hubcloud.one")||href.includes("gdflix.dev"))&&episodes.push({title:title.replace(/ Links$/i,""),link:href})})}),episodes}).catch(err=>[])};exports.getEpisodes=getEpisodes; \ No newline at end of file diff --git a/dist/Joya9tv/meta.js b/dist/Joya9tv/meta.js new file mode 100644 index 0000000..fb43146 --- /dev/null +++ b/dist/Joya9tv/meta.js @@ -0,0 +1 @@ +"use strict";var __awaiter=this&&this.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator.throw(value))}catch(e){reject(e)}}function step(result){var value;result.done?resolve(result.value):(value=result.value,value instanceof P?value:new P(function(resolve){resolve(value)})).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.getMeta=void 0;const headers={Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Cache-Control":"no-store","Accept-Language":"en-US,en;q=0.9",DNT:"1","sec-ch-ua":'"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"',"sec-ch-ua-mobile":"?0","sec-ch-ua-platform":'"Windows"',"Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1",Cookie:"xla=s4t; _ga=GA1.1.1081149560.1756378968; _ga_BLZGKYN5PF=GS2.1.s1756378968$o1$g1$t1756378984$j44$l0$h0","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"},getMeta=function(_a){return __awaiter(this,arguments,void 0,function*({link:link,providerContext:providerContext}){var _b;const{cheerio:cheerio}=providerContext,url=link,baseUrl=url.split("/").slice(0,3).join("/"),emptyResult={title:"",synopsis:"",image:"",imdbId:"",type:"movie",linkList:[]};try{const response=yield fetch(url,{headers:Object.assign(Object.assign({},headers),{Referer:baseUrl})}),data=yield response.text(),$=cheerio.load(data),infoContainer=$(".content.right").first(),result={title:"",synopsis:"",image:"",imdbId:"",type:"movie",linkList:[]};/S\d+|Season \d+|TV Series\/Shows/i.test(infoContainer.find("h1").text()+$(".sgeneros").text())?result.type="series":result.type="movie";const rawTitle=$("h1").first().text().trim();let finalTitle=rawTitle.replace(/ Download.*|\[Episode \d+ Added\]/g,"").trim();finalTitle=finalTitle.split(/\(2025\)| S\d+/i)[0].trim()||"Unknown Title",result.title=finalTitle;const imdbMatch=null===(_b=infoContainer.html())||void 0===_b?void 0:_b.match(/tt\d+/);result.imdbId=imdbMatch?imdbMatch[0]:"";let image=infoContainer.find(".poster img[src]").first().attr("src")||"";image.startsWith("//")&&(image="https:"+image),(image.includes("no-thumbnail")||image.includes("placeholder"))&&(image=""),result.image=image,result.synopsis=$("#info .wp-content").text().trim()||"";const links=[];return $("#download .links_table table tbody").find("tr").each((index,element)=>{var _a;const row=$(element),quality=row.find("strong.quality").text().trim(),size=row.find("td:nth-child(4)").text().trim(),directLinkAnchor=row.find("td a").first(),directLink=directLinkAnchor.attr("href"),linkTitle=directLinkAnchor.text().trim();if(quality&&directLink){const directLinks=[{title:linkTitle||"Download Link",link:directLink,type:result.type}],seasonMatch=null===(_a=rawTitle.match(/S(\d+)/))||void 0===_a?void 0:_a[1];let fullTitle=`${result.title}`;seasonMatch&&(fullTitle+=` Season ${seasonMatch}`),fullTitle+=` - ${quality}`,size&&(fullTitle+=` (${size})`),links.push({title:fullTitle,quality:quality.replace(/[^0-9p]/g,""),episodesLink:directLink,directLinks:directLinks})}}),result.linkList=links,result}catch(err){return emptyResult}})};exports.getMeta=getMeta; \ No newline at end of file diff --git a/dist/Joya9tv/posts.js b/dist/Joya9tv/posts.js new file mode 100644 index 0000000..574270e --- /dev/null +++ b/dist/Joya9tv/posts.js @@ -0,0 +1 @@ +"use strict";var __awaiter=this&&this.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator.throw(value))}catch(e){reject(e)}}function step(result){var value;result.done?resolve(result.value):(value=result.value,value instanceof P?value:new P(function(resolve){resolve(value)})).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.getPosts=getPosts,exports.getSearchPosts=getSearchPosts;const defaultHeaders={Referer:"https://www.google.com","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Accept-Language":"en-US,en;q=0.9",Pragma:"no-cache","Cache-Control":"no-cache"};function getPosts(_a){return __awaiter(this,arguments,void 0,function*({filter:filter,page:page=1,signal:signal,providerContext:providerContext}){return fetchPosts({filter:filter,page:page,query:"",signal:signal,providerContext:providerContext})})}function getSearchPosts(_a){return __awaiter(this,arguments,void 0,function*({searchQuery:searchQuery,page:page=1,signal:signal,providerContext:providerContext}){return fetchPosts({filter:"",page:page,query:searchQuery,signal:signal,providerContext:providerContext})})}function fetchPosts(_a){return __awaiter(this,arguments,void 0,function*({filter:filter,query:query,page:page=1,signal:signal,providerContext:providerContext}){try{const baseUrl=yield providerContext.getBaseUrl("joya9tv");let url;if(query&&query.trim()&&"what are you looking for?"!==query.trim().toLowerCase()){const params=new URLSearchParams;params.append("s",query.trim()),page>1&¶ms.append("paged",page.toString()),url=`${baseUrl}/?${params.toString()}`}else url=filter?filter.startsWith("/")?`${baseUrl}${filter.replace(/\/$/,"")}${page>1?`/page/${page}`:""}`:`${baseUrl}/${filter}${page>1?`/page/${page}`:""}`:`${baseUrl}${page>1?`/page/${page}`:""}`;const{cheerio:cheerio}=providerContext,res=yield fetch(url,{headers:defaultHeaders,signal:signal}),data=yield res.text(),$=cheerio.load(data||""),resolveUrl=href=>(null==href?void 0:href.startsWith("http"))?href:new URL(href,baseUrl).href,seen=new Set,catalog=[];return $("article.item.movies").each((_,el)=>{const card=$(el);let link=card.find("div.data h3 a").attr("href")||"";if(!link)return;if(link=resolveUrl(link),seen.has(link))return;let title=card.find("div.data h3 a").text().trim();if(!title)return;let img=card.find("div.poster img").attr("src")||"";const image=img?resolveUrl(img):"";seen.add(link),catalog.push({title:title,link:link,image:image})}),$(".result-item article").each((_,el)=>{const card=$(el);let link=card.find("a").attr("href")||"";if(!link)return;if(link=resolveUrl(link),seen.has(link))return;let title=card.find("a").attr("title")||card.find("img").attr("alt")||"";if(title=title.trim(),!title)return;let img=card.find("img").attr("src")||"";const image=img?resolveUrl(img):"";seen.add(link),catalog.push({title:title,link:link,image:image})}),catalog.slice(0,100)}catch(err){return[]}})} \ No newline at end of file diff --git a/dist/Joya9tv/stream.js b/dist/Joya9tv/stream.js new file mode 100644 index 0000000..a7723b9 --- /dev/null +++ b/dist/Joya9tv/stream.js @@ -0,0 +1 @@ +"use strict";var __awaiter=this&&this.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator.throw(value))}catch(e){reject(e)}}function step(result){var value;result.done?resolve(result.value):(value=result.value,value instanceof P?value:new P(function(resolve){resolve(value)})).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.getStream=getStream;const headers={accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","accept-language":"en-US,en;q=0.9,en-IN;q=0.8","cache-control":"no-cache",pragma:"no-cache",priority:"u=0, i","sec-ch-ua":'"Chromium";v="140", "Not=A?Brand";v="24", "Microsoft Edge";v="140"',"sec-ch-ua-mobile":"?0","sec-ch-ua-platform":'"Windows"',"sec-fetch-dest":"document","sec-fetch-mode":"navigate","sec-fetch-site":"none","sec-fetch-user":"?1","upgrade-insecure-requests":"1"};function getStream(_a){return __awaiter(this,arguments,void 0,function*({link:link,type:type,signal:signal,providerContext:providerContext}){var _b,_c,_d,_e;const{axios:axios,cheerio:cheerio,extractors:extractors}=providerContext,{hubcloudExtracter:hubcloudExtracter}=extractors;try{const streamLinks=[];if("movie"===type){const dotlinkRes=yield fetch(`${link}`,{headers:headers}),dotlinkText=yield dotlinkRes.text();link=(dotlinkText.match(/{const $=cheerio.load(res.data),container=$(".entry-content, .entry-inner");$(".unili-content, .code-block-1").remove();const episodes=[];return container.find("h4, h3").each((_,element)=>{const el=$(element);let title=el.text().replace(/[-:]/g,"").trim();title&&el.next("p").find("a[href*='vcloud.lol']").each((_,a)=>{var _a;const href=null===(_a=$(a).attr("href"))||void 0===_a?void 0:_a.trim();href&&episodes.push({title:title,link:href})})}),episodes}).catch(err=>[])};exports.getEpisodes=getEpisodes; \ No newline at end of file diff --git a/dist/skyMovieHD/meta.js b/dist/skyMovieHD/meta.js new file mode 100644 index 0000000..b2fb77e --- /dev/null +++ b/dist/skyMovieHD/meta.js @@ -0,0 +1 @@ +"use strict";var __awaiter=this&&this.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator.throw(value))}catch(e){reject(e)}}function step(result){var value;result.done?resolve(result.value):(value=result.value,value instanceof P?value:new P(function(resolve){resolve(value)})).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.getMeta=void 0,exports.fetchEpisodesFromSelectedLink=fetchEpisodesFromSelectedLink;const headers={Referer:"https://google.com","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"};function fetchEpisodesFromSelectedLink(url,providerContext){return __awaiter(this,void 0,void 0,function*(){const{axios:axios,cheerio:cheerio}=providerContext,res=yield axios.get(url,{headers:headers}),$=cheerio.load(res.data),episodes=[];return $("h4").each((_,h4El)=>{const epTitle=$(h4El).text().trim();if(!epTitle)return;const directLinks=[];$(h4El).nextUntil("h4, hr").find("a[href]").each((_,linkEl)=>{let href=($(linkEl).attr("href")||"").trim();if(!href)return;href.startsWith("http")||(href=new URL(href,url).href);const btnText=$(linkEl).text().trim()||"Watch Episode";directLinks.push({link:href,title:btnText,quality:"AUTO",type:"episode"})}),directLinks.length>0&&episodes.push({title:epTitle,directLinks:directLinks})}),episodes})}const getMeta=function(_a){return __awaiter(this,arguments,void 0,function*({link:link,providerContext:providerContext}){var _b,_c;const{axios:axios,cheerio:cheerio}=providerContext;link.startsWith("http")||(link=new URL(link,"https://vgmlinks.click").href);try{const res=yield axios.get(link,{headers:headers}),$=cheerio.load(res.data),content=$(".entry-content, .post-inner").length?$(".entry-content, .post-inner"):$("body"),title=$("h1.entry-title").first().text().trim()||(null===(_b=$("meta[property='og:title']").attr("content"))||void 0===_b?void 0:_b.trim())||"Unknown",pageText=content.text(),type=/Season\s*\d+/i.test(pageText)||/Episode\s*\d+/i.test(pageText)?"series":"movie";let image=$(".poster img").attr("src")||$("meta[property='og:image']").attr("content")||$("meta[name='twitter:image']").attr("content")||"";image&&!image.startsWith("http")&&(image=new URL(image,link).href);let synopsis="";$(".entry-content p").each((_,el)=>{const txt=$(el).text().trim();if(txt.length>40&&!txt.toLowerCase().includes("download"))return synopsis=txt,!1});const imdbLink=$("a[href*='imdb.com']").attr("href")||"",imdbId=imdbLink?"tt"+((null===(_c=imdbLink.split("/tt")[1])||void 0===_c?void 0:_c.split("/")[0])||""):"",tags=[];$(".entry-content p strong").each((_,el)=>{const txt=$(el).text().trim();txt.match(/drama|biography|action|thriller|romance|adventure|animation/i)&&tags.push(txt)});const extra={};$("p").each((_,el)=>{var _a,_b,_c,_d,_e,_f;const html=$(el).html()||"";html.includes("Series Name")&&(extra.name=null===(_a=$(el).text().split(":")[1])||void 0===_a?void 0:_a.trim()),html.includes("Language")&&(extra.language=null===(_b=$(el).text().split(":")[1])||void 0===_b?void 0:_b.trim()),html.includes("Released Year")&&(extra.year=null===(_c=$(el).text().split(":")[1])||void 0===_c?void 0:_c.trim()),html.includes("Quality")&&(extra.quality=null===(_d=$(el).text().split(":")[1])||void 0===_d?void 0:_d.trim()),html.includes("Episode Size")&&(extra.size=null===(_e=$(el).text().split(":")[1])||void 0===_e?void 0:_e.trim()),html.includes("Format")&&(extra.format=null===(_f=$(el).text().split(":")[1])||void 0===_f?void 0:_f.trim())});const links=[],episodeList=[],isInformationalHeading=text=>{const lowerText=text.toLowerCase();return lowerText.includes("series info")||lowerText.includes("series name")||lowerText.includes("language")||lowerText.includes("released year")||lowerText.includes("episode size")||lowerText.includes("format")||lowerText.includes("imdb rating")||lowerText.includes("winding up")||lowerText.length<5&&!/\d/.test(lowerText)};return"series"===type?content.find("h3").each((_,h3)=>{var _a;const h3Text=$(h3).text().trim();if(isInformationalHeading(h3Text))return;const qualityMatch=(null===(_a=h3Text.match(/\d+p/))||void 0===_a?void 0:_a[0])||"AUTO",vcloudLink=$(h3).nextUntil("h3, hr").find("a").filter((_,a)=>/v-cloud|mega|gdrive|download/i.test($(a).text())).first(),href=vcloudLink.attr("href");if(href){const btnText=vcloudLink.text().trim()||"Link";if(btnText.toLowerCase().includes("imdb rating")||btnText.toLowerCase().includes("winding up"))return;links.push({title:h3Text,quality:qualityMatch,episodesLink:href})}}):content.find("h3, h5").each((_,heading)=>{var _a;const headingText=$(heading).text().trim();if(isInformationalHeading(headingText))return;const qualityMatch=(null===(_a=headingText.match(/\d+p/))||void 0===_a?void 0:_a[0])||"AUTO",linkEl=$(heading).nextUntil("h3, h5, hr").find("a[href]").first(),href=linkEl.attr("href");if(href){let finalHref=href.trim();finalHref.startsWith("http")||(finalHref=new URL(finalHref,link).href);const btnText=linkEl.text().trim()||"Download Link";if(btnText.toLowerCase().includes("imdb rating")||btnText.toLowerCase().includes("winding up"))return;links.push({title:headingText,quality:qualityMatch,episodesLink:"",directLinks:[{title:btnText,link:finalHref,type:"movie"}]})}}),{title:title,synopsis:synopsis,image:image,imdbId:imdbId,type:type,tags:tags,cast:[],rating:$(".entry-meta .entry-date").text().trim()||"",linkList:links,extraInfo:extra,episodeList:episodeList}}catch(err){return{title:"",synopsis:"",image:"",imdbId:"",type:"movie",tags:[],cast:[],rating:"",linkList:[],extraInfo:{},episodeList:[]}}})};exports.getMeta=getMeta; \ No newline at end of file diff --git a/dist/skyMovieHD/posts.js b/dist/skyMovieHD/posts.js new file mode 100644 index 0000000..62cccf7 --- /dev/null +++ b/dist/skyMovieHD/posts.js @@ -0,0 +1 @@ +"use strict";var __awaiter=this&&this.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator.throw(value))}catch(e){reject(e)}}function step(result){var value;result.done?resolve(result.value):(value=result.value,value instanceof P?value:new P(function(resolve){resolve(value)})).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.getPosts=getPosts,exports.getSearchPosts=getSearchPosts;const defaultHeaders={Referer:"https://www.google.com","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Accept-Language":"en-US,en;q=0.9",Pragma:"no-cache","Cache-Control":"no-cache"};function getPosts(_a){return __awaiter(this,arguments,void 0,function*({filter:filter,page:page=1,signal:signal,providerContext:providerContext}){return fetchPosts({filter:filter,page:page,query:"",signal:signal,providerContext:providerContext})})}function getSearchPosts(_a){return __awaiter(this,arguments,void 0,function*({searchQuery:searchQuery,page:page=1,signal:signal,providerContext:providerContext}){return fetchPosts({filter:"",page:page,query:searchQuery,signal:signal,providerContext:providerContext})})}function fetchPosts(_a){return __awaiter(this,arguments,void 0,function*({filter:filter,query:query,page:page=1,signal:signal,providerContext:providerContext}){try{const baseUrl="https://skymovieshd.tattoo";let url;if(query&&query.trim()&&"what are you looking for?"!==query.trim().toLowerCase()){const params=new URLSearchParams;params.append("s",query.trim()),page>1&¶ms.append("paged",page.toString()),url=`${baseUrl}/?${params.toString()}`}else url=filter?filter.startsWith("/")?`${baseUrl}${filter.replace(/\/$/,"")}${page>1?`/page/${page}`:""}`:`${baseUrl}/${filter}${page>1?`/page/${page}`:""}`:`${baseUrl}${page>1?`/page/${page}`:""}`;const{axios:axios,cheerio:cheerio}=providerContext,res=yield axios.get(url,{headers:defaultHeaders,signal:signal}),$=cheerio.load(res.data||""),resolveUrl=href=>(null==href?void 0:href.startsWith("http"))?href:new URL(href,baseUrl).href,seen=new Set,catalog=[];return $("article.latestpost").each((_,el)=>{const card=$(el);let link=card.find("header.entry-header h2.entry-title a, header.entry-header h1.entry-title a").attr("href")||"";if(!link)return;if(link=resolveUrl(link),seen.has(link))return;let title=card.find("header.entry-header h2.entry-title a, header.entry-header h1.entry-title a").text().replace(/^Download\s*/i,"").trim();if(!title)return;let img=card.find("a#featured-thumbnail img").attr("data-src")||card.find("a#featured-thumbnail img").attr("src")||"";const image=img?resolveUrl(img):"";seen.add(link),catalog.push({title:title,link:link,image:image})}),catalog.slice(0,100)}catch(err){return[]}})} \ No newline at end of file diff --git a/dist/skyMovieHD/stream.js b/dist/skyMovieHD/stream.js new file mode 100644 index 0000000..7893de1 --- /dev/null +++ b/dist/skyMovieHD/stream.js @@ -0,0 +1 @@ +"use strict";var __awaiter=this&&this.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator.throw(value))}catch(e){reject(e)}}function step(result){var value;result.done?resolve(result.value):(value=result.value,value instanceof P?value:new P(function(resolve){resolve(value)})).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.getStream=getStream;const headers={Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Cache-Control":"no-store","Accept-Language":"en-US,en;q=0.9",DNT:"1","sec-ch-ua":'"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"',"sec-ch-ua-mobile":"?0","sec-ch-ua-platform":'"Windows"',"Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1",Cookie:"xla=s4t; _ga=GA1.1.1081149560.1756378968; _ga_BLZGKYN5PF=GS2.1.s1756378968$o1$g1$t1756378984$j44$l0$h0","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"};function getStream(_a){return __awaiter(this,arguments,void 0,function*({link:link,type:type,signal:signal,providerContext:providerContext}){const{axios:axios,cheerio:cheerio,extractors:extractors}=providerContext,{hubcloudExtracter:hubcloudExtracter}=extractors;try{return yield hubcloudExtracter(link,signal)}catch(error){return error.message.includes("Aborted"),[]}})} \ No newline at end of file diff --git a/providers/Joya9tv/catalog.ts b/providers/Joya9tv/catalog.ts new file mode 100644 index 0000000..18644b1 --- /dev/null +++ b/providers/Joya9tv/catalog.ts @@ -0,0 +1,10 @@ +export const catalog = [ + { + title: "Latest", + filter: "", // baseUrl se latest page fetch hoga + }, + { + title: "Bangali-Movies", + filter: "genre/bengali-movies/", + }, +]; diff --git a/providers/Joya9tv/episodes.ts b/providers/Joya9tv/episodes.ts new file mode 100644 index 0000000..634a442 --- /dev/null +++ b/providers/Joya9tv/episodes.ts @@ -0,0 +1,58 @@ +import { EpisodeLink, ProviderContext } from "../types"; + +export const getEpisodes = function ({ + url, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + const { axios, cheerio, commonHeaders: headers } = providerContext; + console.log("getEpisodeLinks", url); + + return axios + .get(url, { headers }) + .then((res) => { + const $ = cheerio.load(res.data); + // Target the container that holds the episode links (based on the provided sample) + const container = $("ul:has(p.font-bold:contains('Episode'))").first(); + + const episodes: EpisodeLink[] = []; + + // Find all bold episode link headings (e.g., 'Episode 38 Links 480p') + container.find("p.font-bold").each((_, element) => { + const el = $(element); + let title = el.text().trim(); // e.g., "Episode 38 Links 480p" + if (!title) return; + + // Use a selector for the direct links that follow this title (in the next siblings) + // The episode links are in
  • elements directly following the

    + let currentElement = el.parent(); // Get the parent

  • of the

    + + // Loop through the siblings until the next

    (the start of the next episode) + while (currentElement.next().length && !currentElement.next().find("p.font-bold").length) { + currentElement = currentElement.next(); + // Find all anchor tags (links) in the current

  • sibling + currentElement.find("a[href]").each((_, a) => { + const anchor = $(a); + const href = anchor.attr("href")?.trim(); + + // Only include links for hubcloud and gdflix as requested + if (href && (href.includes("hubcloud.one") || href.includes("gdflix.dev"))) { + // Clean up the title to be just "Episode X 480p" + episodes.push({ + title: title.replace(/ Links$/i, ''), + link: href + }); + } + }); + } + }); + + return episodes; + }) + .catch((err) => { + console.log("getEpisodeLinks error:", err); + return []; + }); +}; \ No newline at end of file diff --git a/providers/Joya9tv/meta.ts b/providers/Joya9tv/meta.ts new file mode 100644 index 0000000..49c1e6f --- /dev/null +++ b/providers/Joya9tv/meta.ts @@ -0,0 +1,160 @@ +import { Info, Link, ProviderContext } from "../types"; + +// Headers +const headers = { + Accept: + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + "Cache-Control": "no-store", + "Accept-Language": "en-US,en;q=0.9", + DNT: "1", + "sec-ch-ua": + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"Windows"', + "Sec-Fetch-Dest": "document", + "Sec-Fetch-Mode": "navigate", + "Sec-Fetch-Site": "none", + "Sec-Fetch-User": "?1", + Cookie: + "xla=s4t; _ga=GA1.1.1081149560.1756378968; _ga_BLZGKYN5PF=GS2.1.s1756378968$o1$g1$t1756378984$j44$l0$h0", + "Upgrade-Insecure-Requests": "1", + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0", +}; + +export const getMeta = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + const { cheerio } = providerContext; + const url = link; + const baseUrl = url.split("/").slice(0, 3).join("/"); + + const emptyResult: Info = { + title: "", + synopsis: "", + image: "", + imdbId: "", + type: "movie", + linkList: [], + }; + + try { + const response = await fetch(url, { + headers: { ...headers, Referer: baseUrl }, + }); + + const data = await response.text(); + const $ = cheerio.load(data); + // Use the main container from the new HTML structure + const infoContainer = $(".content.right").first(); + + const result: Info = { + title: "", + synopsis: "", + image: "", + imdbId: "", + type: "movie", + linkList: [], + }; + + // --- Type determination (Based on content, the HTML is for a Series) --- + // Check for 'S' or 'Season' in the main heading + if ( + /S\d+|Season \d+|TV Series\/Shows/i.test( + infoContainer.find("h1").text() + $(".sgeneros").text() + ) + ) { + result.type = "series"; + } else { + result.type = "movie"; + } + + // --- Title --- + const rawTitle = $("h1").first().text().trim(); + + // Clean up title (remove 'Download', site name, quality/episode tags) + let finalTitle = rawTitle + .replace(/ Download.*|\[Episode \d+ Added\]/g, "") + .trim(); + + // Extract base title before S19, (2025), etc. + finalTitle = + finalTitle.split(/\(2025\)| S\d+/i)[0].trim() || "Unknown Title"; + result.title = finalTitle; + + // --- IMDb ID --- + // The new HTML doesn't explicitly show an IMDb ID, so we'll rely on a more generic search. + const imdbMatch = infoContainer.html()?.match(/tt\d+/); + result.imdbId = imdbMatch ? imdbMatch[0] : ""; + + // --- Image --- + let image = + infoContainer.find(".poster img[src]").first().attr("src") || ""; + if (image.startsWith("//")) image = "https:" + image; + + // Check for "no-thumbnail" or "placeholder" in the filename + if (image.includes("no-thumbnail") || image.includes("placeholder")) + image = ""; + result.image = image; + + // --- Synopsis --- + // The synopsis is directly in the
    inside #info + result.synopsis = $("#info .wp-content").text().trim() || ""; + + // --- LinkList extraction (Updated for the structure in #download) --- + const links: Link[] = []; + const downloadTable = $("#download .links_table table tbody"); + + // The entire season/series batch links are in the table + downloadTable.find("tr").each((index, element) => { + const row = $(element); + const quality = row.find("strong.quality").text().trim(); + + // Get the size from the fourth
    in the row + const size = row.find("td:nth-child(4)").text().trim(); + + const directLinkAnchor = row.find("td a").first(); + const directLink = directLinkAnchor.attr("href"); + const linkTitle = directLinkAnchor.text().trim(); + + if (quality && directLink) { + // FIX: Assert the type to satisfy the Link interface's literal type requirement + const assertedType = result.type as "movie" | "series"; + + // Assuming the table links are for the entire batch/season + const directLinks = [ + { + title: linkTitle || "Download Link", + link: directLink, + type: assertedType, // Use the asserted type + }, + ]; + + // Combine title, quality, and size for the LinkList entry + const seasonMatch = rawTitle.match(/S(\d+)/)?.[1]; + let fullTitle = `${result.title}`; + if (seasonMatch) fullTitle += ` Season ${seasonMatch}`; + fullTitle += ` - ${quality}`; + if (size) fullTitle += ` (${size})`; // ADDED: Append size to the link title + + links.push({ + title: fullTitle, + quality: quality.replace(/[^0-9p]/g, ""), // Clean to just 480p, 720p, 1080p + // The direct link is to a page that lists all episodes, so it acts as the episodesLink + episodesLink: directLink, + directLinks, + }); + } + }); + + result.linkList = links; + return result; + } catch (err) { + console.log("getMeta error:", err); + return emptyResult; + } +}; diff --git a/providers/Joya9tv/posts.ts b/providers/Joya9tv/posts.ts new file mode 100644 index 0000000..b82d989 --- /dev/null +++ b/providers/Joya9tv/posts.ts @@ -0,0 +1,148 @@ +import { Post, ProviderContext } from "../types"; + +const defaultHeaders = { + Referer: "https://www.google.com", + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " + + "(KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36", + Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Accept-Language": "en-US,en;q=0.9", + Pragma: "no-cache", + "Cache-Control": "no-cache", +}; + +// --- Normal catalog posts --- +export async function getPosts({ + filter, + page = 1, + signal, + providerContext, +}: { + filter?: string; + page?: number; + signal?: AbortSignal; + providerContext: ProviderContext; +}): Promise { + return fetchPosts({ filter, page, query: "", signal, providerContext }); +} + +// --- Search posts --- +export async function getSearchPosts({ + searchQuery, + page = 1, + signal, + providerContext, +}: { + searchQuery: string; + page?: number; + signal?: AbortSignal; + providerContext: ProviderContext; +}): Promise { + return fetchPosts({ + filter: "", + page, + query: searchQuery, + signal, + providerContext, + }); +} + +// --- Core fetch function --- +async function fetchPosts({ + filter, + query, + page = 1, + signal, + providerContext, +}: { + filter?: string; + query?: string; + page?: number; + signal?: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const baseUrl = await providerContext.getBaseUrl("joya9tv"); + let url: string; + + if ( + query && + query.trim() && + query.trim().toLowerCase() !== "what are you looking for?" + ) { + const params = new URLSearchParams(); + params.append("s", query.trim()); + if (page > 1) params.append("paged", page.toString()); + url = `${baseUrl}/?${params.toString()}`; + } else if (filter) { + url = filter.startsWith("/") + ? `${baseUrl}${filter.replace(/\/$/, "")}${ + page > 1 ? `/page/${page}` : "" + }` + : `${baseUrl}/${filter}${page > 1 ? `/page/${page}` : ""}`; + } else { + url = `${baseUrl}${page > 1 ? `/page/${page}` : ""}`; + } + + const { cheerio } = providerContext; + const res = await fetch(url, { headers: defaultHeaders, signal }); + const data = await res.text(); + const $ = cheerio.load(data || ""); + + const resolveUrl = (href: string) => + href?.startsWith("http") ? href : new URL(href, baseUrl).href; + + const seen = new Set(); + const catalog: Post[] = []; + + // ✅ Case 1: Normal catalog listing + $("article.item.movies").each((_, el) => { + const card = $(el); + + let link = card.find("div.data h3 a").attr("href") || ""; + if (!link) return; + link = resolveUrl(link); + if (seen.has(link)) return; + + let title = card.find("div.data h3 a").text().trim(); + if (!title) return; + + let img = card.find("div.poster img").attr("src") || ""; + const image = img ? resolveUrl(img) : ""; + + seen.add(link); + catalog.push({ title, link, image }); + }); + + // ✅ Case 2: Search results + $(".result-item article").each((_, el) => { + const card = $(el); + + let link = card.find("a").attr("href") || ""; + if (!link) return; + link = resolveUrl(link); + if (seen.has(link)) return; + + let title = + card.find("a").attr("title") || card.find("img").attr("alt") || ""; + title = title.trim(); + if (!title) return; + + let img = card.find("img").attr("src") || ""; + const image = img ? resolveUrl(img) : ""; + + seen.add(link); + catalog.push({ title, link, image }); + }); + + console.log(`fetchPosts: Fetched ${catalog.length} posts from ${url}`); + + return catalog.slice(0, 100); + } catch (err) { + console.error( + "fetchPosts error:", + err instanceof Error ? err.message : String(err) + ); + return []; + } +} diff --git a/providers/Joya9tv/stream.ts b/providers/Joya9tv/stream.ts new file mode 100644 index 0000000..146e91d --- /dev/null +++ b/providers/Joya9tv/stream.ts @@ -0,0 +1,114 @@ +import { ProviderContext, Stream } from "../types"; + +const headers = { + accept: + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + "accept-language": "en-US,en;q=0.9,en-IN;q=0.8", + "cache-control": "no-cache", + pragma: "no-cache", + priority: "u=0, i", + "sec-ch-ua": + '"Chromium";v="140", "Not=A?Brand";v="24", "Microsoft Edge";v="140"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"Windows"', + "sec-fetch-dest": "document", + "sec-fetch-mode": "navigate", + "sec-fetch-site": "none", + "sec-fetch-user": "?1", + "upgrade-insecure-requests": "1", +}; + +export async function getStream({ + link, + type, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}) { + const { axios, cheerio, extractors } = providerContext; + const { hubcloudExtracter } = extractors; + try { + const streamLinks: Stream[] = []; + console.log("dotlink", link); + if (type === "movie") { + // vlink + const dotlinkRes = await fetch(`${link}`, { headers }); + const dotlinkText = await dotlinkRes.text(); + // console.log('dotlinkText', dotlinkText); + const vlink = dotlinkText.match(/ { + const { axios, cheerio, commonHeaders: headers } = providerContext; + console.log("getEpisodeLinks", url); + + return axios + .get(url, { headers }) + .then((res) => { + const $ = cheerio.load(res.data); + const container = $(".entry-content, .entry-inner"); + + // Remove unnecessary elements + $(".unili-content, .code-block-1").remove(); + + const episodes: EpisodeLink[] = []; + + container.find("h4, h3").each((_, element) => { + const el = $(element); + let title = el.text().replace(/[-:]/g, "").trim(); + if (!title) return; + + // Saare V-Cloud links fetch + el.next("p") + .find("a[href*='vcloud.lol']") + .each((_, a) => { + const anchor = $(a); + const href = anchor.attr("href")?.trim(); + if (href) { + episodes.push({ title, link: href }); + } + }); + }); + + return episodes; + }) + .catch((err) => { + console.log("getEpisodeLinks error:", err); + return []; + }); +}; diff --git a/providers/skyMovieHD/meta.ts b/providers/skyMovieHD/meta.ts new file mode 100644 index 0000000..35b22e6 --- /dev/null +++ b/providers/skyMovieHD/meta.ts @@ -0,0 +1,268 @@ +import { Info, Link, ProviderContext } from "../types"; + +interface DirectLink { + link: string; + title: string; + quality: string; + type: "movie" | "episode"; +} + +interface Episode { + title: string; + directLinks: DirectLink[]; +} + +const headers = { + Referer: "https://google.com", + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", +}; + +export async function fetchEpisodesFromSelectedLink( + url: string, + providerContext: ProviderContext +): Promise { + const { axios, cheerio } = providerContext; + const res = await axios.get(url, { headers }); + const $ = cheerio.load(res.data); + + const episodes: Episode[] = []; + + $("h4").each((_, h4El) => { + const epTitle = $(h4El).text().trim(); + if (!epTitle) return; + + const directLinks: DirectLink[] = []; + + $(h4El) + .nextUntil("h4, hr") + .find("a[href]") + .each((_, linkEl) => { + let href = ($(linkEl).attr("href") || "").trim(); + if (!href) return; + if (!href.startsWith("http")) href = new URL(href, url).href; + + const btnText = $(linkEl).text().trim() || "Watch Episode"; + directLinks.push({ + link: href, + title: btnText, + quality: "AUTO", + type: "episode", + }); + }); + + if (directLinks.length > 0) { + episodes.push({ + title: epTitle, + directLinks, + }); + } + }); + + return episodes; +} + +// --- Main getMeta function +export const getMeta = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise< + Info & { extraInfo: Record; episodeList: Episode[] } +> { + const { axios, cheerio } = providerContext; + if (!link.startsWith("http")) + link = new URL(link, "https://vgmlinks.click").href; + + try { + const res = await axios.get(link, { headers }); + const $ = cheerio.load(res.data); + const content = $(".entry-content, .post-inner").length + ? $(".entry-content, .post-inner") + : $("body"); + + const title = + $("h1.entry-title").first().text().trim() || + $("meta[property='og:title']").attr("content")?.trim() || + "Unknown"; // --- Type Detect --- + + const pageText = content.text(); + const type = + /Season\s*\d+/i.test(pageText) || /Episode\s*\d+/i.test(pageText) + ? "series" + : "movie"; + + let image = + $(".poster img").attr("src") || + $("meta[property='og:image']").attr("content") || + $("meta[name='twitter:image']").attr("content") || + ""; + if (image && !image.startsWith("http")) image = new URL(image, link).href; + + let synopsis = ""; + $(".entry-content p").each((_, el) => { + const txt = $(el).text().trim(); + if (txt.length > 40 && !txt.toLowerCase().includes("download")) { + synopsis = txt; + return false; + } + }); + + const imdbLink = $("a[href*='imdb.com']").attr("href") || ""; + const imdbId = imdbLink + ? "tt" + (imdbLink.split("/tt")[1]?.split("/")[0] || "") + : ""; + + const tags: string[] = []; + $(".entry-content p strong").each((_, el) => { + const txt = $(el).text().trim(); + if ( + txt.match( + /drama|biography|action|thriller|romance|adventure|animation/i + ) + ) + tags.push(txt); + }); + + const extra: Record = {}; + $("p").each((_, el) => { + const html = $(el).html() || ""; + if (html.includes("Series Name")) + extra.name = $(el).text().split(":")[1]?.trim(); + if (html.includes("Language")) + extra.language = $(el).text().split(":")[1]?.trim(); + if (html.includes("Released Year")) + extra.year = $(el).text().split(":")[1]?.trim(); + if (html.includes("Quality")) + extra.quality = $(el).text().split(":")[1]?.trim(); + if (html.includes("Episode Size")) + extra.size = $(el).text().split(":")[1]?.trim(); + if (html.includes("Format")) + extra.format = $(el).text().split(":")[1]?.trim(); + }); + + const links: Link[] = []; + const episodeList: Episode[] = []; + + const isInformationalHeading = (text: string) => { + const lowerText = text.toLowerCase(); + return ( + lowerText.includes("series info") || + lowerText.includes("series name") || + lowerText.includes("language") || + lowerText.includes("released year") || + lowerText.includes("episode size") || + lowerText.includes("format") || + lowerText.includes("imdb rating") || + lowerText.includes("winding up") || + (lowerText.length < 5 && !/\d/.test(lowerText)) + ); + }; // --- Download Links Extraction --- + + if (type === "series") { + // Series case: h3 text as title + episode link button (V-Cloud) + content.find("h3").each((_, h3) => { + const h3Text = $(h3).text().trim(); + + if (isInformationalHeading(h3Text)) return; + + const qualityMatch = h3Text.match(/\d+p/)?.[0] || "AUTO"; + + const vcloudLink = $(h3) + .nextUntil("h3, hr") + .find("a") + .filter((_, a) => /v-cloud|mega|gdrive|download/i.test($(a).text())) + .first(); + + const href = vcloudLink.attr("href"); + if (href) { + // Hide unwanted texts + const btnText = vcloudLink.text().trim() || "Link"; + if ( + btnText.toLowerCase().includes("imdb rating") || + btnText.toLowerCase().includes("winding up") + ) + return; + + links.push({ + title: h3Text, + quality: qualityMatch, + episodesLink: href, + }); + } + }); + } else { + // Movie case: h5/h3 text as title + direct download link + content.find("h3, h5").each((_, heading) => { + const headingText = $(heading).text().trim(); + + if (isInformationalHeading(headingText)) return; + + const qualityMatch = headingText.match(/\d+p/)?.[0] || "AUTO"; + const linkEl = $(heading) + .nextUntil("h3, h5, hr") + .find("a[href]") + .first(); + + const href = linkEl.attr("href"); + if (href) { + let finalHref = href.trim(); + if (!finalHref.startsWith("http")) + finalHref = new URL(finalHref, link).href; + + const btnText = linkEl.text().trim() || "Download Link"; // Hide unwanted texts + + if ( + btnText.toLowerCase().includes("imdb rating") || + btnText.toLowerCase().includes("winding up") + ) + return; + + links.push({ + title: headingText, + quality: qualityMatch, + episodesLink: "", + directLinks: [ + { + title: btnText, + link: finalHref, + type: "movie", + }, + ], + }); + } + }); + } + + return { + title, + synopsis, + image, + imdbId, + type: type as "movie" | "series", + tags, + cast: [], + rating: $(".entry-meta .entry-date").text().trim() || "", + linkList: links, + extraInfo: extra, + episodeList, + }; + } catch (err) { + console.error("getMeta error:", err); + return { + title: "", + synopsis: "", + image: "", + imdbId: "", + type: "movie", + tags: [], + cast: [], + rating: "", + linkList: [], + extraInfo: {}, + episodeList: [], + }; + } +}; diff --git a/providers/skyMovieHD/posts.ts b/providers/skyMovieHD/posts.ts new file mode 100644 index 0000000..0e3daed --- /dev/null +++ b/providers/skyMovieHD/posts.ts @@ -0,0 +1,118 @@ +import { Post, ProviderContext } from "../types"; + +const defaultHeaders = { + Referer: "https://www.google.com", + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " + + "(KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36", + Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Accept-Language": "en-US,en;q=0.9", + Pragma: "no-cache", + "Cache-Control": "no-cache", +}; + +// --- Normal catalog posts --- +export async function getPosts({ + filter, + page = 1, + signal, + providerContext, +}: { + filter?: string; + page?: number; + signal?: AbortSignal; + providerContext: ProviderContext; +}): Promise { + return fetchPosts({ filter, page, query: "", signal, providerContext }); +} + +// --- Search posts --- +export async function getSearchPosts({ + searchQuery, + page = 1, + signal, + providerContext, +}: { + searchQuery: string; + page?: number; + signal?: AbortSignal; + providerContext: ProviderContext; +}): Promise { + return fetchPosts({ filter: "", page, query: searchQuery, signal, providerContext }); +} + +// --- Core fetch function --- +async function fetchPosts({ + filter, + query, + page = 1, + signal, + providerContext, +}: { + filter?: string; + query?: string; + page?: number; + signal?: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const baseUrl = "https://skymovieshd.tattoo"; + let url: string; + + if (query && query.trim() && query.trim().toLowerCase() !== "what are you looking for?") { + const params = new URLSearchParams(); + params.append("s", query.trim()); + if (page > 1) params.append("paged", page.toString()); + url = `${baseUrl}/?${params.toString()}`; + } else if (filter) { + url = filter.startsWith("/") + ? `${baseUrl}${filter.replace(/\/$/, "")}${page > 1 ? `/page/${page}` : ""}` + : `${baseUrl}/${filter}${page > 1 ? `/page/${page}` : ""}`; + } else { + url = `${baseUrl}${page > 1 ? `/page/${page}` : ""}`; + } + + const { axios, cheerio } = providerContext; + const res = await axios.get(url, { headers: defaultHeaders, signal }); + const $ = cheerio.load(res.data || ""); + + const resolveUrl = (href: string) => + href?.startsWith("http") ? href : new URL(href, baseUrl).href; + + const seen = new Set(); + const catalog: Post[] = []; + + // ✅ Scrape posts + $("article.latestpost").each((_, el) => { + const card = $(el); + + // Link + let link = card.find("header.entry-header h2.entry-title a, header.entry-header h1.entry-title a").attr("href") || ""; + if (!link) return; + link = resolveUrl(link); + if (seen.has(link)) return; + + // Title: remove "Download" + let title = card.find("header.entry-header h2.entry-title a, header.entry-header h1.entry-title a") + .text() + .replace(/^Download\s*/i, "") + .trim(); + if (!title) return; + + // Image + let img = + card.find("a#featured-thumbnail img").attr("data-src") || + card.find("a#featured-thumbnail img").attr("src") || + ""; + const image = img ? resolveUrl(img) : ""; + + seen.add(link); + catalog.push({ title, link, image }); + }); + + return catalog.slice(0, 100); + } catch (err) { + console.error("fetchPosts error:", err instanceof Error ? err.message : String(err)); + return []; + } +} diff --git a/providers/skyMovieHD/stream.ts b/providers/skyMovieHD/stream.ts new file mode 100644 index 0000000..f366890 --- /dev/null +++ b/providers/skyMovieHD/stream.ts @@ -0,0 +1,49 @@ +import { ProviderContext, Stream } from "../types"; + +const headers = { + Accept: + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + "Cache-Control": "no-store", + "Accept-Language": "en-US,en;q=0.9", + DNT: "1", + "sec-ch-ua": + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"Windows"', + "Sec-Fetch-Dest": "document", + "Sec-Fetch-Mode": "navigate", + "Sec-Fetch-Site": "none", + "Sec-Fetch-User": "?1", + Cookie: + "xla=s4t; _ga=GA1.1.1081149560.1756378968; _ga_BLZGKYN5PF=GS2.1.s1756378968$o1$g1$t1756378984$j44$l0$h0", + "Upgrade-Insecure-Requests": "1", + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0", +}; + +export async function getStream({ + link, + type, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}) { + const { axios, cheerio, extractors } = providerContext; + const { hubcloudExtracter } = extractors; + try { + const streamLinks: Stream[] = []; + console.log("dotlink", link); + + return await hubcloudExtracter(link, signal); + } catch (error: any) { + console.log("getStream error: ", error); + if (error.message.includes("Aborted")) { + } else { + } + return []; + } +}