1 Commits

Author SHA1 Message Date
8man 2c8f6cb32f Update modflix.json 2025-02-16 12:11:18 +05:30
4 changed files with 87 additions and 495 deletions
-219
View File
@@ -1,219 +0,0 @@
const fs = require('fs');
const axios = require('axios');
const FILE_PATH = 'modflix.json';
const updatedProviders = []; // Track updated providers for Discord notification
const DEFAULT_HEADERS = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36',
Accept:
'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
Connection: 'keep-alive',
'Upgrade-Insecure-Requests': '1'
};
// Read the modflix.json file
function readModflixJson() {
try {
const data = fs.readFileSync(FILE_PATH, 'utf8');
return JSON.parse(data);
} catch (error) {
console.error(`Error reading ${FILE_PATH}:`, error);
process.exit(1);
}
}
// Extract domain (origin) from URL without trailing slash
function getDomain(url) {
try {
const urlObj = new URL(url);
return urlObj.origin;
} catch (error) {
console.error(`Error parsing URL ${url}:`, error);
return url;
}
}
// Check if original URL has a trailing slash in path
function hasTrailingSlash(url) {
return url.endsWith('/') && !url.endsWith('://');
}
function getFinalUrl(response, originalUrl) {
return (
response?.request?.res?.responseUrl ||
response?.request?._redirectable?._currentUrl ||
response?.config?.url ||
originalUrl
);
}
function normalizeOrigin(url) {
try {
return new URL(url).origin;
} catch {
return url;
}
}
async function requestUrl(method, url) {
return axios({
method,
url,
maxRedirects: 5,
timeout: 10000,
validateStatus: status => true,
headers: DEFAULT_HEADERS
});
}
function logVerboseResult(url, response, finalUrl) {
const status = response?.status ?? 'unknown';
const locationHeader = response?.headers?.location;
console.log(
`${url} -> status=${status} final=${finalUrl}` +
(locationHeader ? ` location=${locationHeader}` : '')
);
}
function shouldUpdateFromFinalUrl(originalUrl, finalUrl) {
const originalDomain = getDomain(originalUrl);
const finalDomain = getDomain(finalUrl);
return finalDomain && finalDomain !== originalDomain;
}
// Check URL and return new URL if domain redirected or resolved elsewhere
async function checkUrl(url) {
try {
const response = await requestUrl('get', url);
const finalUrl = getFinalUrl(response, url);
logVerboseResult(url, response, finalUrl);
if (shouldUpdateFromFinalUrl(url, finalUrl)) {
const updatedUrl = normalizeOrigin(finalUrl) + (hasTrailingSlash(url) ? '/' : '');
console.log(`🔄 ${url} resolved to ${finalUrl}`);
console.log(`Will update to: ${updatedUrl} (preserved trailing slash: ${hasTrailingSlash(url)})`);
return updatedUrl;
}
if (response.status === 200) {
console.log(`${url} is valid (200 OK)`);
return null;
}
if (response.status >= 300 && response.status < 400) {
const newLocation = response.headers.location;
if (newLocation) {
let fullRedirectUrl = newLocation;
if (!newLocation.startsWith('http')) {
const baseUrl = new URL(url);
fullRedirectUrl = new URL(newLocation, baseUrl.origin).toString();
}
if (shouldUpdateFromFinalUrl(url, fullRedirectUrl)) {
const newDomain = normalizeOrigin(fullRedirectUrl);
const needsTrailingSlash = hasTrailingSlash(url);
const finalUrlForUpdate = newDomain + (needsTrailingSlash ? '/' : '');
console.log(`🔄 ${url} redirects to ${fullRedirectUrl}`);
console.log(
`Will update to: ${finalUrlForUpdate} (preserved trailing slash: ${needsTrailingSlash})`
);
return finalUrlForUpdate;
}
}
}
console.log(`⚠️ ${url} returned status ${response.status}`);
} catch (error) {
if (error.response) {
const finalUrl = getFinalUrl(error.response, url);
logVerboseResult(url, error.response, finalUrl);
// If the request resolves to a different origin even with a non-2xx status,
// use that as an update signal. This keeps existing behavior intact while
// allowing sites that block HEAD/GET with 403 but still resolve elsewhere.
if (shouldUpdateFromFinalUrl(url, finalUrl)) {
const updatedUrl = normalizeOrigin(finalUrl) + (hasTrailingSlash(url) ? '/' : '');
console.log(`🔄 ${url} resolved to ${finalUrl}`);
console.log(
`Will update to: ${updatedUrl} (preserved trailing slash: ${hasTrailingSlash(url)})`
);
return updatedUrl;
}
console.log(`⚠️ ${url} returned status ${error.response.status}`);
} else if (error.code === 'ECONNABORTED') {
console.log(`${url} request timed out`);
} else if (error.code === 'ENOTFOUND') {
console.log(`${url} domain not found`);
} else {
console.log(`❌ Error checking ${url}: ${error.message}`);
}
}
// Return null if no change or error
return null;
}
// Main function
async function main() {
const providers = readModflixJson();
let hasChanges = false;
// Process each provider
for (const [key, provider] of Object.entries(providers)) {
const url = provider.url;
console.log(`Checking ${provider.name} (${url})...`);
try {
const newUrl = await checkUrl(url);
if (newUrl && newUrl !== url) {
// Store the old URL before updating
const oldUrl = provider.url;
// Update the provider URL
provider.url = newUrl;
hasChanges = true;
console.log(`Updated ${provider.name} URL from ${oldUrl} to ${newUrl}`);
// Track updated provider for Discord notification
updatedProviders.push({
name: provider.name,
oldUrl: oldUrl,
newUrl: newUrl
});
}
} catch (error) {
console.log(`❌ Error processing ${url}: ${error.message}`);
}
}
// Write changes back to file if needed
if (hasChanges) {
// Use a space-efficient JSON format but with proper formatting
const jsonString = JSON.stringify(providers, null, 2);
fs.writeFileSync(FILE_PATH, jsonString);
console.log(`✅ Updated ${FILE_PATH} with new URLs`);
// Output updated providers for Discord notification in a clean format
if (updatedProviders.length > 0) {
console.log("\n### UPDATED_PROVIDERS_START ###");
for (const provider of updatedProviders) {
// Format: name|oldUrl|newUrl (pipe-delimited for easy parsing)
console.log(`${provider.name}|${provider.oldUrl}|${provider.newUrl}`);
}
console.log("### UPDATED_PROVIDERS_END ###");
}
} else {
console.log(`️ No changes needed for ${FILE_PATH}`);
}
}
// Execute main function with error handling
main().catch(error => {
console.error('Unhandled error:', error);
process.exit(1);
});
-136
View File
@@ -1,136 +0,0 @@
name: Check Provider URLs
on:
schedule:
- cron: '0 0 * * *' # Run daily at midnight UTC
workflow_dispatch: # Allow manual triggering
# Set explicit permissions for the GITHUB_TOKEN
permissions:
contents: write
jobs:
check-urls:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install axios
- name: Run URL checker
id: url_checker
shell: bash
run: |
set -o pipefail
# Run the URL checker and show output in the job logs while also saving it
node .github/scripts/url-checker.js 2>&1 | tee checker_output.log
# Check if there are updated providers
if grep -q "### UPDATED_PROVIDERS_START ###" checker_output.log; then
echo "CHANGES_DETECTED=true" >> "$GITHUB_ENV"
# Extract only the updated provider lines between the markers
sed -n '/### UPDATED_PROVIDERS_START ###/,/### UPDATED_PROVIDERS_END ###/p' checker_output.log | \
grep -v "###" > updated_providers.txt
else
echo "CHANGES_DETECTED=false" >> "$GITHUB_ENV"
fi
echo "--- checker_output.log ---"
cat checker_output.log
echo "--- end checker_output.log ---"
- name: Commit changes if any
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"
git add modflix.json
# Check if there are changes using git status
if [[ $(git status --porcelain modflix.json) ]]; then
echo "Found changes in modflix.json, committing..."
git commit -m "Update provider URLs [skip ci]"
git push
echo "CHANGES_MADE=true" >> $GITHUB_ENV
else
echo "No changes detected in modflix.json"
echo "CHANGES_MADE=false" >> $GITHUB_ENV
fi
- name: Send Discord notification
if: env.CHANGES_MADE == 'true' && env.CHANGES_DETECTED == 'true'
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
run: |
if [ -z "$DISCORD_WEBHOOK" ]; then
echo "Error: DISCORD_WEBHOOK secret is not set. Skipping notification."
exit 0
fi
# Count updated providers
PROVIDER_COUNT=$(wc -l < updated_providers.txt)
# Create discord-message.json file with proper formatting
cat > discord-message.json << EOF
{
"embeds": [
{
"title": "🔄 Provider URLs Updated ($PROVIDER_COUNT)",
"color": 3066993,
"fields": [
EOF
# Process each updated provider
while IFS='|' read -r name oldUrl newUrl; do
# continue if line is empty
[[ -z "$name" ]] && continue
# Escape any double quotes in the values
name=$(echo "$name" | sed 's/"/\\"/g')
oldUrl=$(echo "$oldUrl" | sed 's/"/\\"/g')
newUrl=$(echo "$newUrl" | sed 's/"/\\"/g')
# Add the provider as a field with clickable links using <URL> syntax
cat >> discord-message.json << EOF
{
"name": "${name}",
"value": "**Old:** <${oldUrl}>\\n**New:** <${newUrl}>",
"inline": false
},
EOF
done < updated_providers.txt
# Remove the trailing comma from the last field
sed -i '$ s/,$//' discord-message.json
# Complete the JSON structure
cat >> discord-message.json << EOF
],
"footer": {
"text": "Updated on $(date +"%Y-%m-%d %H:%M:%S UTC")"
}
}
]
}
EOF
# Send the webhook
curl -s -X POST \
-H "Content-Type: application/json" \
-d @discord-message.json \
"$DISCORD_WEBHOOK"
# Check if the webhook was sent successfully
if [ $? -eq 0 ]; then
echo "Discord notification sent successfully!"
else
echo "Failed to send Discord notification."
fi
+3
View File
@@ -0,0 +1,3 @@
{
"nfmirror":"hd=on; lang=hin; SE81149450=81220014; SE81707950=81726576; SE81285617=81285624; SE80995578=81480005; 81726031=26%3A10557; SE81586657=81586786; 81586786=30%3A3460; SE81061734=81592026; SE81237994=81237996; 81237996=3623%3A3985; SE81122198=81171277; 81171277=1668%3A4082; 81592026=853%3A2978; t_hash_t=fd1f9cd4008673d113bb0d37ffdfd651%3A%3Afe5f4ed63a7f250563a619616112193c%3A%3A1728207435%3A%3Ani; t_hash=1395f97b15c2e39c2f4dda9ee22b8a4c%3A%3A1728207467%3A%3Ani; recentplay=81602831-SE81061734-SE81122198-SE81237994-SE81586657-81726031-SE80995578-SE81285617-81282732-SE81707950-70213514-235527-SE81149450"
}
+21 -77
View File
@@ -1,19 +1,19 @@
{ {
"Moviesmod": { "Moviesmod": {
"name": "Moviesmod", "name": "Moviesmod",
"url": "https://moviesmod.farm" "url": "https://moviesmod.how"
}, },
"Animeflix": { "Animeflix": {
"name": "Animeflix", "name": "Animeflix",
"url": "https://ww3.animeflix.ltd" "url": "https://animeflix.lol"
}, },
"Topmovies": { "Topmovies": {
"name": "Topmovies", "name": "Topmovies",
"url": "https://moviesleech.bar" "url": "https://topmovies.fyi"
}, },
"UhdMovies": { "UhdMovies": {
"name": "UhdMovies", "name": "UhdMovies",
"url": "https://uhdmovies.food" "url": "https://uhdmovies.fyi"
}, },
"filepress": { "filepress": {
"name": "filepress", "name": "filepress",
@@ -21,23 +21,23 @@
}, },
"Vega": { "Vega": {
"name": "vegamovies", "name": "vegamovies",
"url": "https://vegamovies.mq" "url": "https://vegamovies.rs"
}, },
"lux": { "lux": {
"name":"luxmovies", "name":"luxmovies",
"url": "https://rogmovies.work" "url":"https://rogmovies.cfd"
}, },
"drive":{ "drive":{
"name":"moviesDrive", "name":"moviesDrive",
"url": "https://new3.moviesdrives.my/" "url":"https://moviesdrive.pro/"
}, },
"multi":{ "multi":{
"name":"multimovies", "name":"multimovies",
"url": "https://multimovies.fyi" "url":"https://multimovies.life"
}, },
"w4u":{ "w4u":{
"name":"world4ufree", "name":"world4ufree",
"url": "https://world4ufree.cl" "url":"https://world4ufree.durban"
}, },
"extra":{ "extra":{
"name":"extraMovies", "name":"extraMovies",
@@ -45,15 +45,15 @@
}, },
"hdhub":{ "hdhub":{
"name":"hdhub4u", "name":"hdhub4u",
"url": "https://new1.hdhub4u.cl" "url":"https://hdhub4u.soy"
}, },
"kat":{ "kat":{
"name": "katmovieshd", "name": "katmovieshd",
"url": "https://new1.katmoviehd.cymru" "url":"https://katmoviehd.wales"
}, },
"dc":{ "dc":{
"name":"dramacool", "name":"dramacool",
"url": "https://dramacool.org.ro" "url":"https://embasic.pro"
}, },
"dooflix":{ "dooflix":{
"name":"dooflix", "name":"dooflix",
@@ -77,23 +77,23 @@
}, },
"consumet":{ "consumet":{
"name":"consumet", "name":"consumet",
"url": "https://consumet.zendax.tech" "url":"https://consumet.8man.me"
}, },
"nfMirror":{ "nfMirror":{
"name":"nfMirror", "name":"nfMirror",
"url": "https://net22.cc" "url":"https://iosmirror.cc"
}, },
"primewire":{ "primewire":{
"name":"primewire", "name":"primewire",
"url": "https://primewire.si" "url":"https://www.primewire.li"
}, },
"rive":{ "rive":{
"name":"rive", "name":"rive",
"url": "https://www.rivestream.app" "url":"https://rivestream.live"
}, },
"kissKh":{ "kissKh":{
"name":"kissKh", "name":"kissKh",
"url": "https://kisskh.do" "url":"https://kisskh.co"
}, },
"vadapav":{ "vadapav":{
"name":"vadapav", "name":"vadapav",
@@ -101,7 +101,7 @@
}, },
"cinemaLuxe":{ "cinemaLuxe":{
"name":"cinemaLuxe", "name":"cinemaLuxe",
"url": "https://cinemalux.cyou" "url":"https://cinemaluxe.work"
}, },
"showbox":{ "showbox":{
"name":"showbox", "name":"showbox",
@@ -113,7 +113,7 @@
}, },
"moviesapi":{ "moviesapi":{
"name":"moviesapi", "name":"moviesapi",
"url": "https://moviesapi.to" "url":"https://moviesapi.club"
}, },
"ridomovies":{ "ridomovies":{
"name":"ridomovies", "name":"ridomovies",
@@ -121,70 +121,14 @@
}, },
"protonMovies":{ "protonMovies":{
"name":"protonMovies", "name":"protonMovies",
"url": "https://m.protonmovies.space" "url":"https://m.protonmovies.top"
}, },
"dramafull":{ "dramafull":{
"name":"dramafull", "name":"dramafull",
"url": "https://dramafull.cc" "url":"https://dramafull.net"
}, },
"nfCookie":{ "nfCookie":{
"name":"nf cookie verify", "name":"nf cookie verify",
"url":"https://userverify.netmirror.app" "url":"https://userverify.netmirror.app"
},
"embedsu": {
"name": "embedsu",
"url": "https://moviemaze.cc"
},
"filmyfly": {
"name": "flimyfly",
"url": "https://new2.filmyfiy.org"
},
"4khdhub": {
"name": "4khdhub",
"url": "https://4khdhub.one"
},
"moviezwap": {
"name": "moviezwap",
"url": "https://www.moviezwap.onl/"
},
"9xflix": {
"name": "9xflix",
"url": "https://soft-water-2a42.flixoflixx.workers.dev"
},
"movieBox": {
"name": "MovieBox",
"url": "https://api6.aoneroom.com"
},
"cinevood": {
"name": "Cinevood",
"url": "https://kmmovies.space"
},
"kmmovies": {
"name": "kmmovies",
"url": "https://kmmovies.space"
},
"zeefliz": {
"name": "zeefliz",
"url": "https://zeefliz.beer"
},
"katmoviefix": {
"name": "katmoviefix",
"url": "https://katmoviefix.rest"
},
"movies4u": {
"name": "movies4u",
"url": "https://movies4u.as"
},
"joya9tv": {
"name": "joya9tv1",
"url": "https://joya9tv1.com"
},
"skymovieshd": {
"name": "skyMovesHd",
"url": "https://skymovieshd.spot"
},
"1cinevood": {
"name": "cinewood",
"url": "https://1cinevood.in"
} }
} }