Files
openclaw/integrations/lampa/p365x-plugin.js
2026-03-03 01:48:51 +03:00

177 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(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);
}
})();