177 lines
6.0 KiB
JavaScript
177 lines
6.0 KiB
JavaScript
(function () {
|
||
'use strict';
|
||
|
||
var FLAG = 'lampa_p365x_parser_started';
|
||
if (window[FLAG]) return;
|
||
window[FLAG] = true;
|
||
|
||
var BASE = 'https://m.porno365x.space';
|
||
var STATE = { items: [], page: 1, loading: false };
|
||
|
||
function $(sel, root) { return (root || document).querySelector(sel); }
|
||
function el(tag, cls, txt) {
|
||
var n = document.createElement(tag);
|
||
if (cls) n.className = cls;
|
||
if (txt != null) n.textContent = txt;
|
||
return n;
|
||
}
|
||
|
||
function extractCards(html) {
|
||
var out = [];
|
||
var re = /<li id="(\d+)"[\s\S]*?<a class="image" href="([^"]+)"[\s\S]*?<img src="([^"]+)"[\s\S]*?<p>([^<]+)<\/p>[\s\S]*?<span class="duration">([^<]*)<\/span>/g;
|
||
var m;
|
||
while ((m = re.exec(html))) {
|
||
out.push({
|
||
id: m[1],
|
||
url: m[2].startsWith('http') ? m[2] : BASE + m[2],
|
||
poster: m[3],
|
||
title: m[4].trim(),
|
||
duration: (m[5] || '').trim()
|
||
});
|
||
}
|
||
return out;
|
||
}
|
||
|
||
function extractMp4(movieHtml) {
|
||
var all = [];
|
||
var re = /file\s*:\s*"([^"]+\.mp4[^"]*)"/g;
|
||
var m;
|
||
while ((m = re.exec(movieHtml))) all.push(m[1]);
|
||
if (!all.length) {
|
||
var v = movieHtml.match(/<video[^>]+src="([^"]+\.mp4[^"]*)"/i);
|
||
if (v) all.push(v[1]);
|
||
}
|
||
// prefer highest quality by filename suffix _1080p/_720p ...
|
||
all.sort(function (a, b) {
|
||
function q(x) {
|
||
var mm = x.match(/_(\d{3,4})p\.mp4/i);
|
||
return mm ? Number(mm[1]) : 0;
|
||
}
|
||
return q(b) - q(a);
|
||
});
|
||
return all[0] || '';
|
||
}
|
||
|
||
async function request(url) {
|
||
var r = await fetch(url, { credentials: 'omit' });
|
||
if (!r.ok) throw new Error('HTTP ' + r.status);
|
||
return await r.text();
|
||
}
|
||
|
||
async function fetchList(page) {
|
||
var url = page > 1 ? (BASE + '/page/' + page + '/') : (BASE + '/');
|
||
var html = await request(url);
|
||
return extractCards(html);
|
||
}
|
||
|
||
async function fetchStream(movieUrl) {
|
||
var html = await request(movieUrl);
|
||
return extractMp4(html);
|
||
}
|
||
|
||
function createUi() {
|
||
if ($('#p365x-root')) return;
|
||
|
||
var css = el('style');
|
||
css.textContent = '' +
|
||
'#p365x-fab{position:fixed;right:24px;bottom:24px;z-index:99999;background:#e91e63;color:#fff;border:none;border-radius:999px;padding:10px 14px;font-weight:700;}' +
|
||
'#p365x-root{position:fixed;inset:0;z-index:99998;background:#111;color:#fff;display:none;}' +
|
||
'#p365x-head{padding:12px 16px;display:flex;gap:10px;align-items:center;border-bottom:1px solid #333;}' +
|
||
'#p365x-list{padding:10px;display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px;overflow:auto;height:calc(100% - 64px);}' +
|
||
'.p365x-card{background:#1b1b1b;border:1px solid #333;border-radius:8px;overflow:hidden;cursor:pointer;}' +
|
||
'.p365x-card img{width:100%;height:130px;object-fit:cover;display:block;}' +
|
||
'.p365x-meta{padding:8px;font-size:13px;}' +
|
||
'#p365x-player{position:fixed;inset:0;z-index:100000;background:#000;display:none;}' +
|
||
'#p365x-player video{width:100%;height:100%;}' +
|
||
'#p365x-close-player{position:absolute;top:10px;right:10px;z-index:2;}';
|
||
document.head.appendChild(css);
|
||
|
||
var fab = el('button');
|
||
fab.id = 'p365x-fab';
|
||
fab.textContent = 'P365';
|
||
|
||
var root = el('div');
|
||
root.id = 'p365x-root';
|
||
root.innerHTML = '<div id="p365x-head"><button id="p365x-close">Закрыть</button><button id="p365x-more">Ещё</button><span id="p365x-status"></span></div><div id="p365x-list"></div>';
|
||
|
||
var player = el('div');
|
||
player.id = 'p365x-player';
|
||
player.innerHTML = '<button id="p365x-close-player">Закрыть</button><video id="p365x-video" controls autoplay playsinline></video>';
|
||
|
||
document.body.appendChild(fab);
|
||
document.body.appendChild(root);
|
||
document.body.appendChild(player);
|
||
|
||
fab.addEventListener('click', function () {
|
||
root.style.display = 'block';
|
||
if (!STATE.items.length) loadNextPage();
|
||
});
|
||
$('#p365x-close').addEventListener('click', function () { root.style.display = 'none'; });
|
||
$('#p365x-more').addEventListener('click', loadNextPage);
|
||
$('#p365x-close-player').addEventListener('click', function () {
|
||
player.style.display = 'none';
|
||
var v = $('#p365x-video');
|
||
v.pause();
|
||
v.removeAttribute('src');
|
||
v.load();
|
||
});
|
||
}
|
||
|
||
function setStatus(t) { var s = $('#p365x-status'); if (s) s.textContent = t || ''; }
|
||
|
||
function renderItems() {
|
||
var list = $('#p365x-list');
|
||
if (!list) return;
|
||
list.innerHTML = '';
|
||
STATE.items.forEach(function (item) {
|
||
var c = el('div', 'p365x-card');
|
||
c.innerHTML = '<img src="' + item.poster + '" alt=""><div class="p365x-meta"><div>' + item.title + '</div><div style="opacity:.7">' + item.duration + '</div></div>';
|
||
c.addEventListener('click', async function () {
|
||
try {
|
||
setStatus('Загрузка видео...');
|
||
var src = await fetchStream(item.url);
|
||
if (!src) throw new Error('Поток не найден');
|
||
var p = $('#p365x-player');
|
||
var v = $('#p365x-video');
|
||
v.src = src;
|
||
p.style.display = 'block';
|
||
setStatus('');
|
||
} catch (e) {
|
||
setStatus('Ошибка: ' + e.message);
|
||
}
|
||
});
|
||
list.appendChild(c);
|
||
});
|
||
}
|
||
|
||
async function loadNextPage() {
|
||
if (STATE.loading) return;
|
||
STATE.loading = true;
|
||
try {
|
||
setStatus('Загрузка страницы ' + STATE.page + '...');
|
||
var items = await fetchList(STATE.page);
|
||
STATE.items = STATE.items.concat(items);
|
||
STATE.page += 1;
|
||
renderItems();
|
||
setStatus('Найдено: ' + STATE.items.length);
|
||
} catch (e) {
|
||
setStatus('Не удалось загрузить. Возможен CORS/блокировка: ' + e.message);
|
||
} finally {
|
||
STATE.loading = false;
|
||
}
|
||
}
|
||
|
||
function start() {
|
||
createUi();
|
||
}
|
||
|
||
if (window.appready) start();
|
||
else if (window.Lampa && Lampa.Listener) {
|
||
Lampa.Listener.follow('app', function (e) {
|
||
if (e.type === 'ready') start();
|
||
});
|
||
} else {
|
||
window.addEventListener('load', start);
|
||
}
|
||
})();
|