Skip to content

Commit

Permalink
Merge pull request #154 from himanshu8443/feature
Browse files Browse the repository at this point in the history
update v2.5.5
  • Loading branch information
Zenda-Cross authored Nov 21, 2024
2 parents d1b1b85 + 76fd884 commit 0e576b0
Show file tree
Hide file tree
Showing 13 changed files with 329 additions and 163 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ android {
applicationId "com.vega"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 78
versionName "2.5.4"
versionCode 80
versionName "2.5.5"
}
signingConfigs {
release {
Expand Down
4 changes: 2 additions & 2 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
]
],
"slug": "vega",
"version": "2.5.4",
"version": "2.5.5",
"sdkVersion": "51.0.0",
"android": {
"minSdkVersion": 24,
"package": "com.vega",
"versionCode": 78
"versionCode": 80
},
"platforms": ["ios", "android"]
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vega",
"version": "2.5.4",
"version": "2.5.5",
"private": true,
"scripts": {
"android": "react-native run-android",
Expand Down
6 changes: 4 additions & 2 deletions src/components/SeasonList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ const SeasonList = ({
fontWeight: 'bold',
}}
labelField={'title'}
valueField={LinkList[0]?.episodesLink ? 'episodesLink' : 'directLinks'}
valueField={
LinkList[0]?.episodesLink ? 'episodesLink' : 'directLinks'
}
onChange={item => {
setActiveSeason(item);
MmmkvCache.setMap(`ActiveSeason${metaTitle + providerValue}`, item);
Expand All @@ -220,7 +222,7 @@ const SeasonList = ({
style={{
overflow: 'hidden',
borderWidth: 1,
borderColor: 'gray',
borderColor: '#2f302f',
paddingHorizontal: 12,
borderRadius: 8,
backgroundColor: 'black',
Expand Down
24 changes: 12 additions & 12 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ export const providersList: ProvidersList[] = [
type: 'global',
flag: '🌏',
},
// {
// name: 'MultiMovies',
// value: 'multi',
// type: 'global',
// flag: '🌏',
// },
{
name: 'MultiMovies',
value: 'multi',
type: 'global',
flag: '🌏',
},
{
name: 'World4uFree',
value: 'world4u',
Expand Down Expand Up @@ -91,12 +91,12 @@ export const providersList: ProvidersList[] = [
type: 'global',
flag: '🌏',
},
{
name: 'MoviesApi',
value: 'moviesApi',
type: 'english',
flag: '🇬🇧',
},
// {
// name: 'MoviesApi',
// value: 'moviesApi',
// type: 'english',
// flag: '🇬🇧',
// },
{
name: 'FlixHQ',
value: 'flixhq',
Expand Down
13 changes: 9 additions & 4 deletions src/lib/providers/multi/multiPosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const multiGetPostsSearch = async function (
): Promise<Post[]> {
const baseUrl = await getBaseUrl('multi');
// console.log(baseUrl);
const url = `${baseUrl}/page/${page}/?s=${searchQuery}`;
const url = `${baseUrl}/?s=${searchQuery}`;
console.log('multiUrl', url);

return posts(url, signal);
Expand All @@ -42,7 +42,9 @@ async function posts(url: string, signal: AbortSignal): Promise<Post[]> {
.map((i, element) => {
const title = $(element).find('.poster').find('img').attr('alt');
const link = $(element).find('.poster').find('a').attr('href');
const image = $(element).find('.poster').find('img').attr('src');
const image =
$(element).find('.poster').find('img').attr('data-src') ||
$(element).find('.poster').find('img').attr('src');
if (title && link && image) {
catalog.push({
title: title,
Expand All @@ -54,8 +56,11 @@ async function posts(url: string, signal: AbortSignal): Promise<Post[]> {
$('.result-item').map((i, element) => {
const title = $(element).find('.thumbnail').find('img').attr('alt');
const link = $(element).find('.thumbnail').find('a').attr('href');
const image = $(element).find('.thumbnail').find('img').attr('src');
if (title && link && image) {
const image =
$(element).find('.thumbnail').find('img').attr('data-src') ||
$(element).find('.thumbnail').find('img').attr('src') ||
'';
if (title && link) {
catalog.push({
title: title,
link: link,
Expand Down
204 changes: 173 additions & 31 deletions src/lib/providers/netflixMirror/nfGetCookie.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,192 @@
import axios from 'axios';
import {getBaseUrl} from '../getBaseUrl';
import * as cheerio from 'cheerio';
import {MmmkvCache} from '../../Mmkv';
import {ToastAndroid} from 'react-native';

export async function nfGetCookie() {
try {
const baseUrl = await getBaseUrl('nfMirror');
const res = await axios.get(baseUrl + '/home', {withCredentials: false});
const $ = cheerio.load(res.data);
// console.log('nf cookie html', res.data);
const addhash = $('body').attr('data-addhash');
console.log('nf addhash', addhash);
export class NetMirrorCookieFetcher {
private static readonly COOKIE_CACHE_KEY = 'nfCookie';
private static readonly COOKIE_TIME_KEY = 'nfCookieTime';
private static readonly COOKIE_EXPIRY_MS = 79200000; // 22 hours
private static readonly VERIFY_TIMEOUT_MS = 25000;
private static readonly MAX_RETRY_ATTEMPTS = 50;

/**
* Fetches a cookie with intelligent caching and error handling
* @returns Promise resolving to the cookie string
*/
static async fetchCookie(): Promise<string> {
try {
const addRes = await fetch(
baseUrl + '/v.php?hash=' + addhash + '&t=' + Math.random(),
{
credentials: 'omit',
},
// Check cached cookie first
const cachedCookie = this.getCachedCookie();
if (cachedCookie) {
return cachedCookie;
}

// Show waiting toast
ToastAndroid.show(
'Getting cookie, please wait 20 sec...',
ToastAndroid.SHORT,
);

// Fetch new cookie with retry mechanism
return await this.fetchFreshCookie();
} catch (err) {
console.log('nf addhash error ', err);
console.error('NetMirror cookie fetch failed:', err);
return '';
}
}

/**
* Retrieves cached cookie if still valid
* @returns Cached cookie or null if expired
*/
private static getCachedCookie(): string | null {
const nfCookieTime = MmmkvCache.getString(this.COOKIE_TIME_KEY);
if (nfCookieTime) {
const timeDiff = new Date().getTime() - parseInt(nfCookieTime);
if (timeDiff < this.COOKIE_EXPIRY_MS) {
const nfCookie = MmmkvCache.getString(this.COOKIE_CACHE_KEY);
console.log('NetMirror cookie retrieved from cache');
return nfCookie || null;
}
}
return null;
}

/**
* Fetches a fresh cookie with multiple verification steps
* @returns Promise resolving to the new cookie
*/
private static async fetchFreshCookie(): Promise<string> {
const baseUrl = await getBaseUrl('nfMirror');

// Fetch initial page to get addhash
const res = await axios.get(`${baseUrl}/home`, {withCredentials: false});
const $ = cheerio.load(res.data);
const addhash = $('body').attr('data-addhash');

if (!addhash) {
throw new Error('Unable to extract addhash');
}

// Preliminary verification
await this.performPreliminaryVerification(addhash);

// Cookie verification with retry logic
const cookie = await this.verifyCookie(baseUrl, addhash);

// Cache the new cookie
this.cacheCookie(cookie);
ToastAndroid.show('Cookie saved for 24 hours', ToastAndroid.SHORT);

return cookie;
}

/**
* Performs preliminary verification request
* @param addhash Verification hash
*/
private static async performPreliminaryVerification(
addhash: string,
): Promise<void> {
try {
const addRes = await fetch(
'https://userverify.netmirror.app/verify?vhf=' +
addhash +
'&t=' +
Math.random(),
{
credentials: 'omit',
},
await fetch(
`https://userverify.netmirror.app/verify?dp1=${addhash}&a=y&t=${Math.random()}`,
{credentials: 'omit'},
);
} catch (err) {
console.log('nf addhash error ', err);
console.warn('Preliminary verification failed:', err);
}
const form = new FormData();
form.append('verify', addhash);
const res2 = await fetch(baseUrl + '/verify2.php', {
}

/**
* Verifies and retrieves the cookie with retry mechanism
* @param baseUrl Base URL for verification
* @param addhash Verification hash
* @returns Promise resolving to the cookie string
*/
private static async verifyCookie(
baseUrl: string,
addhash: string,
): Promise<string> {
for (let attempt = 1; attempt <= this.MAX_RETRY_ATTEMPTS; attempt++) {
const form = new FormData();
form.append('verify', addhash);

const verificationPromise = new Promise<string>((resolve, reject) => {
const timeoutId = setTimeout(() => {
reject(new Error('Cookie verification timed out'));
}, this.VERIFY_TIMEOUT_MS);

this.performCookieVerification(baseUrl, form)
.then(cookie => {
clearTimeout(timeoutId);
resolve(cookie);
})
.catch(err => {
clearTimeout(timeoutId);
reject(err);
});
});

try {
return await verificationPromise;
} catch (err) {
console.warn(`Cookie verification attempt ${attempt} failed:`, err);
if (attempt === this.MAX_RETRY_ATTEMPTS) {
throw err;
}
// Optional: add a small delay between retries
await new Promise(resolve => setTimeout(resolve, 1000));
}
}

throw new Error('Failed to retrieve cookie after multiple attempts');
}

/**
* Performs the actual cookie verification request
* @param baseUrl Base URL for verification
* @param form FormData for verification
* @returns Promise resolving to the cookie string
*/
private static async performCookieVerification(
baseUrl: string,
form: FormData,
): Promise<string> {
const res2 = await fetch(`${baseUrl}/verify2.php`, {
method: 'POST',
body: form,
credentials: 'omit',
});

const res2Json = await res2.json();
console.log('NetMirror verification response:', res2Json);

if (res2Json.statusup !== 'All Done') {
throw new Error('Verification not complete');
}

const cookie2 = res2.headers.get('set-cookie');
console.log('nfCookie2', cookie2);
return cookie2?.split(';')[0] + ';' || '';
} catch (err) {
console.error('nf cookie error: ', err);
return '';
if (!cookie2) {
throw new Error('No cookie found in response');
}

return `${cookie2.split(';')[0]};`;
}

/**
* Caches the retrieved cookie
* @param cookie Cookie string to cache
*/
private static cacheCookie(cookie: string): void {
MmmkvCache.setString(this.COOKIE_CACHE_KEY, cookie);
MmmkvCache.setString(this.COOKIE_TIME_KEY, new Date().getTime().toString());
}
}

// Usage
export async function nfGetCookie(): Promise<string> {
return NetMirrorCookieFetcher.fetchCookie();
}
8 changes: 7 additions & 1 deletion src/lib/providers/vega/getInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ export const vegaGetInfo = async (link: string): Promise<Info> => {
try {
const url = link;
console.log('url', url);
const response = await axios.get(url, {headers});
const baseUrl = url.split('/').slice(0, 3).join('/');
const response = await axios.get(url, {
headers: {
...headers,
Referer: baseUrl,
},
});
const $ = cheerio.load(response.data);
const infoContainer = $('.entry-content');
const heading = infoContainer?.find('h3');
Expand Down
18 changes: 14 additions & 4 deletions src/lib/providers/vega/getPosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const vegaGetPosts = async (
console.log('vegaGetPosts baseUrl:', providerValue, baseUrl);
const url = `${baseUrl}/${filter}/page/${page}/`;
console.log('vegaGetPosts url:', url);
return posts(url, signal);
return posts(baseUrl, url, signal);
};

export const vegaGetPostsSearch = async (
Expand All @@ -30,12 +30,22 @@ export const vegaGetPostsSearch = async (
const url = `${baseUrl}/page/${page}/?s=${searchQuery}`;
console.log('vegaGetPosts url:', url);

return posts(url, signal);
return posts(baseUrl, url, signal);
};

async function posts(url: string, signal: AbortSignal): Promise<Post[]> {
async function posts(
baseUrl: string,
url: string,
signal: AbortSignal,
): Promise<Post[]> {
try {
const urlRes = await axios.get(url, {headers, signal});
const urlRes = await axios.get(url, {
headers: {
...headers,
Referer: baseUrl,
},
signal,
});
const $ = cheerio.load(urlRes.data);
const posts: Post[] = [];
$('.blog-items')
Expand Down
Loading

0 comments on commit 0e576b0

Please sign in to comment.