Fuente M440, modo sin conexión (servidor sin internet y app sin servidor), cola del dispositivo en Colas y arreglo del reescalado de tiras altas
- M440 (m440.in, español): búsqueda, populares, actualizados paginados, ficha, capítulos, descargas y seguimiento. La lista de capítulos viene cifrada: la clave se saca de un script ofuscado del sitio ejecutándolo en un proceso aislado con permisos mínimos (m440-key.mjs) y se renueva sola. - Servidor sin internet (connectivity.js): se detecta en segundos; las fuentes fallan al instante, la portada muestra lo descargado en el servidor con buscador, portadas locales de respaldo, descargas y comprobaciones en pausa y reanudación automática al volver la conexión. - App sin conexión con el servidor: el service worker usa la copia guardada si el servidor no contesta en 3 s, las peticiones comprueban si el servidor sigue vivo en vez de quedarse colgadas, aviso arriba e inicio con lo guardado en el dispositivo; al volver, se reconecta sola y envía el progreso pendiente. - Colas: sección «En este dispositivo» con el guardado en curso en directo y cancelación (sin dejar capítulos a medias); también visible sin servidor. - Imágenes: el proxy y el guardado en el dispositivo reintentan con tiempo límite cuando el CDN de la fuente falla. - Reescalado HD: las páginas que superan 16383 px al reescalar (tiras de webtoon) se reducen al límite de WebP en vez de hacer fallar el capítulo. - Entidades HTML con nombre en las sinopsis; pestañas de fuentes cortas en móvil; portadas rotas con icono de respaldo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// Extrae la clave con la que M440 cifra su lista de capítulos. La clave está repartida en trozos dentro de
|
||||
// un script ofuscado (js/ads2.js) que llama a CryptoJS.AES.decrypt(datos, clave, …). En vez de
|
||||
// desofuscarlo, se ejecuta en un contexto vm vacío con un CryptoJS falso que solo anota la clave.
|
||||
//
|
||||
// Se lanza como proceso aparte con el modelo de permisos de Node (sin acceso a archivos salvo este, sin
|
||||
// procesos hijo ni workers) y con tiempo límite. Dentro del vm no se pasa ningún objeto del proceso
|
||||
// (todo se define con código dentro del contexto) y la generación de código desde strings está
|
||||
// desactivada, así que el script no puede alcanzar process ni require.
|
||||
// Entrada: el script por stdin. Salida: {"key": "..."} por stdout.
|
||||
import vm from 'node:vm'
|
||||
|
||||
let src = ''
|
||||
process.stdin.setEncoding('utf8')
|
||||
for await (const chunk of process.stdin) {
|
||||
src += chunk
|
||||
if (src.length > 2e6) process.exit(2)
|
||||
}
|
||||
|
||||
const ctx = vm.createContext({}, { codeGeneration: { strings: false, wasm: false } })
|
||||
vm.runInContext(`
|
||||
var __key = null;
|
||||
var window = globalThis, self = globalThis;
|
||||
var UsaPoncho = '{"ct":"AAAA","iv":"00","s":"00"}';
|
||||
function mk() {
|
||||
return new Proxy(function () {}, {
|
||||
get: function (t, k) {
|
||||
if (k === Symbol.toPrimitive) return function () { return '' };
|
||||
if (k === 'toString') return function () { return '[]' };
|
||||
return mk();
|
||||
},
|
||||
apply: function () { return mk() },
|
||||
construct: function () { return mk() },
|
||||
});
|
||||
}
|
||||
var document = mk(), $ = mk(), jQuery = $, localStorage = mk(), sessionStorage = mk();
|
||||
var navigator = { userAgent: 'Mozilla/5.0', language: 'es' }, location = { href: 'https://m440.in/', hostname: 'm440.in' };
|
||||
var setTimeout = function () {}, setInterval = function () {}, clearTimeout = function () {}, clearInterval = function () {};
|
||||
var console = { log: function () {}, warn: function () {}, error: function () {}, info: function () {}, debug: function () {}, trace: function () {}, table: function () {}, exception: function () {} };
|
||||
var id = function (s) { return s };
|
||||
var CryptoJS = {
|
||||
AES: {
|
||||
decrypt: function (c, k) { if (__key === null) __key = String(k); return { toString: function () { return '"[]"' } } },
|
||||
encrypt: mk(),
|
||||
},
|
||||
enc: { Utf8: { parse: id, stringify: id }, Hex: { parse: id, stringify: id }, Base64: { parse: id, stringify: id } },
|
||||
lib: { CipherParams: { create: id }, WordArray: { create: id } },
|
||||
format: { OpenSSL: {} },
|
||||
};
|
||||
`, ctx)
|
||||
try {
|
||||
vm.runInContext(src, ctx, { timeout: 5000 })
|
||||
} catch {}
|
||||
const key = vm.runInContext('typeof __key === "string" ? __key : ""', ctx)
|
||||
process.stdout.write(JSON.stringify({ key: typeof key === 'string' ? key.slice(0, 200) : '' }))
|
||||
process.exit(0)
|
||||
Reference in New Issue
Block a user