subtitle parser fixes, PWA fixes & work, sw caching

This commit is contained in:
ThaUnknown 2020-09-17 00:58:43 +02:00
parent add74eccd1
commit 1a25ff1ccb
12 changed files with 199 additions and 176 deletions

View file

@ -1,16 +1,21 @@
<!DOCTYPE html>
<html>
<html lang="en" class="auto-scaling-disabled">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
<meta name="viewport" content="width=device-width">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Miru">
<meta name="description" content="Anime torrent streaming, ad free in a simple solution.">
<meta name="theme-color" content="#111417" />
<link rel="icon" href="logo.png">
<title>Miru</title>
<link rel="apple-touch-icon" href="logo.png">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
<meta name="viewport" content="width=device-width" />
<title>Miru - Torrent streaming made simple!</title>
<link href="https://cdn.jsdelivr.net/gh/halfmoonui/halfmoon@1.0.4/css/halfmoon.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/halfmoon@1.1.0/css/halfmoon-variables.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="css/misc.css" rel="stylesheet">
<link href="css/player.css" rel="stylesheet">
@ -126,7 +131,7 @@
<div class="overflow-y-hidden content-wrapper">
<section id="player">
<a href="#player" class="w-full h-full"></a>
<video id="video" class="w-full" autoPictureInPicture>
<video id="video" class="w-full" autoPictureInPicture src="">
</video>
<div class="player d-none flex-column justify-content-between w-full h-full">
<div class="h-full w-full d-flex flex-column justify-content-between" id="ptoggle">
@ -191,7 +196,7 @@
</div>
</div>
</section>
<section id="browse">
<section id="browse" class="d-flex flex-column">
<div class="text-center pt-20">
<div class="container">
<form class="input-group mb-15" action="javascript:search()">
@ -207,13 +212,13 @@
<div class="gallery browse h-full overflow-y-scroll">
</div>
</section>
<section id="releases">
<section id="releases" class="d-flex flex-column">
<div class="gallery releases h-full overflow-y-scroll">
</div>
</section>
</div>
</div>
<script src="https://cdn.jsdelivr.net/gh/halfmoonui/halfmoon@1.0.4/js/halfmoon.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/halfmoonui/halfmoon@1.1.0/js/halfmoon.min.js"></script>
<script src="js/util.js"></script>
<script src="js/animeHandler.js"></script>
<script src="js/playerHandler.js"></script>

View file

@ -6,7 +6,6 @@
--buffer: 0%;
--height: 0;
color: #b6b6b6;
font-size: 62.5%;
--nav-size: 19rem;
--ts: "";
}

View file

@ -292,10 +292,8 @@ async function nyaaRss(url) {
}
let regex = /((?:\[[^\]]*\])*)?\s*((?:[^\d\[\.](?!S\d))*)?\s*((?:S\d+[^\w\[]*E?)?[\d\-]*)\s*(.*)?/,
str = `[HorribleSubs] Black Clover - 143 [1080p].mkv`,
m,
store = {};
const regex = /((?:\[[^\]]*\])*)?\s*((?:[^\d\[\.](?!S\d))*)?\s*((?:S\d+[^\w\[]*E?)?[\d\-]*)\s*(.*)?/;
let store = {};
async function regtest() {
if ((m = regex.exec(str)) !== null) {
if (m[2].endsWith(" - ")) {
@ -312,7 +310,7 @@ async function regtest() {
}
}
async function hsRss(url) {
let frag = document.createDocumentFragment()
document.querySelector(".releases").innerHTML = ""
res = await fetch(url)
await res.text().then(async (xmlTxt) => {
try {
@ -320,7 +318,7 @@ async function hsRss(url) {
let items = doc.querySelectorAll("item")
for (let item of items) {
let i = item.querySelector.bind(item),
regexParse = regex.exec(i("title").textContent)
regexParse = regex.exec(i("title").textContent)
if (regexParse[2].endsWith(" - ")) {
regexParse[2] = regexParse[2].slice(0, -3)
}
@ -332,10 +330,11 @@ async function hsRss(url) {
let media = store[regexParse[2]]
let template = document.createElement("div")
template.classList.add("card", "m-0", "p-0")
template.innerHTML = `
if (media) {
template.innerHTML = `
<div class="row h-full">
<div class="col-4">
<img src="${media.coverImage.extraLarge}"
<img src="${media.coverImage.extraLarge || ""}"
class="cover-img w-full h-full">
</div>
<div class="col-8 h-full card-grid">
@ -357,15 +356,36 @@ async function hsRss(url) {
</div>
</div>
`
} else {
template.innerHTML = `
<div class="row h-full">
<div class="col-4">
<img src=""
class="cover-img w-full h-full">
</div>
<div class="col-8 h-full card-grid">
<div class="px-15 py-10">
<h5 class="m-0 text-capitalize font-weight-bold">${regexParse[2]} - ${regexParse[3]}</h5>
</div>
<div class="overflow-y-scroll px-15 py-10 bg-very-dark card-desc">
</div>
<div class="px-15 pb-10 pt-5">
</div>
</div>
</div>
`
}
template.onclick = function () {
selected = [store[regexParse[2]], regexParse[3]]
addTorrent(i('link').textContent)
}
frag.appendChild(template)
document.querySelector(".releases").appendChild(template)
}
} catch (e) {
console.error(e)
}
})
document.querySelector(".releases").appendChild(frag)
}
}
// setTimeout(() => {
// hsRss("http://www.horriblesubs.info/rss.php?res=1080")
// }, 4000);

View file

@ -208,7 +208,7 @@ function bpp() {
}
function bnext() {
nyaaSearch(nowPlaying[0], nowPlaying[1] + 1)
nyaaSearch(nowPlaying[0], parseInt(nowPlaying[1]) + 1)
}
// volume shit

View file

@ -1,15 +1,12 @@
let tracks = [],
parser
function parseSubs(range, stream) {
if (video.src.endsWith(".mkv")) {
console.log('set parser', range)
parser = new MatroskaSubtitles({ prevInstance: parser, offset: range.start })
parser.once('tracks', function (pTracks) {
tracks = []
video.textTracks = {}
pTracks.forEach(track => {
tracks[track.number] = video.addTextTrack('captions', track.type, track.language || track.number)
})
@ -17,11 +14,9 @@ function parseSubs(range, stream) {
video.textTracks[0].mode = "showing"
}
})
parser.once('cues', function () {
console.log('seeking ready')
})
parser.on('subtitle', function (subtitle, trackNumber) {
subConvt(subtitle, trackNumber)
})
@ -58,10 +53,10 @@ function subConvt(result, trackNumber) {
cue.line = 0.5;
} else if (Math.floor((posNum - 1) / 3) == 2) {
cue.line = 0;
cue.text = "&nbsp;\r\n"
}
if (posNum % 3 == 1) {
cue.align = "start";
cue.text = "&nbsp;\r\n"
} else if (posNum % 3 == 0) {
cue.align = "end";
}
@ -72,10 +67,10 @@ function subConvt(result, trackNumber) {
cue.line = 0.5;
} else if (posNum > 4) {
cue.line = 0;
cue.text = "&nbsp;\r\n"
}
if ((posNum - 1) % 4 == 0) {
cue.align = "start";
cue.text = "&nbsp;\r\n"
} else if ((posNum - 1) % 4 == 2) {
cue.align = "end";
}

View file

@ -1,55 +0,0 @@
self.addEventListener('activate', evt => {
return self.clients.claim()
})
self.addEventListener('fetch', evt => {
const { request } = evt
const { url, method, headers } = request
if (!url.includes(self.registration.scope + 'webtorrent/')) return null
function getConsumer(clients) {
return new Promise(rs => {
// Use race condition for whoever controls the response stream
for (const client of clients) {
const mc = new MessageChannel()
const {port1, port2} = mc
port1.onmessage = evt => {
rs([evt.data, mc])
}
client.postMessage({
url,
method,
headers: [...headers],
scope: self.registration.scope
}, [port2])
}
})
}
evt.respondWith(
clients.matchAll({ type: 'window', includeUncontrolled: true })
.then(getConsumer)
.then(([data, mc]) => {
const body = data.body === 'stream' ? new ReadableStream({
pull(controller) {
return new Promise(rs => {
mc.port1.onmessage = evt => {
evt.data
? controller.enqueue(evt.data) // evt.data is Uint8Array
: controller.close() // evt.data is null, means the stream ended
rs()
}
mc.port1.postMessage(true) // send a pull request
})
},
cancel() {
// This event is never executed
mc.port1.postMessage(false) // send a cancel request
}
}) : data.body
return new Response(body, data)
})
.catch(console.error)
)
})

View file

@ -48,15 +48,15 @@ WEBTORRENT_ANNOUNCE = announceList
var nowPlaying,
maxTorrents = 1,
subStream
function addTorrent(magnet) {
async function addTorrent(magnet) {
if (client.torrents.length >= maxTorrents) {
client.remove(client.torrents[0].infoHash)
}
halfmoon.hideModal("tsearch")
document.location.href = "#player"
video.src = ""
await sw
client.add(magnet, async function (torrent) {
video.src = ""
await sw
function onProgress() {
peers.textContent = torrent.numPeers
downSpeed.textContent = prettyBytes(torrent.downloadSpeed) + '/s'

0
app/offline.html Normal file
View file

104
app/sw.js Normal file
View file

@ -0,0 +1,104 @@
'use strict';
const CACHE_NAME = 'static-cache-v1';
const FILES_TO_CACHE = [
'offline.html',
'app.html',
'js/animeHandler.js',
'js/bundle.js',
'js/playerHandler.js',
'js/subtitleHandler.js',
'js/torrentHandler.js',
'js/util.js',
'css/misc.css',
'css/player.css',
'logo.png'
];
self.addEventListener('install', (evt) => {
evt.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(FILES_TO_CACHE);
})
);
self.skipWaiting();
});
self.addEventListener('activate', (evt) => {
evt.waitUntil(
caches.keys().then((keyList) => {
return Promise.all(keyList.map((key) => {
if (key !== CACHE_NAME) {
return caches.delete(key);
}
}));
})
);
self.clients.claim();
});
self.addEventListener('fetch', evt => {
const { request } = evt
const { url, method, headers } = request
if (!url.includes(self.registration.scope + 'webtorrent/')) return null
function getConsumer(clients) {
return new Promise(rs => {
// Use race condition for whoever controls the response stream
for (const client of clients) {
const mc = new MessageChannel()
const { port1, port2 } = mc
port1.onmessage = evt => {
rs([evt.data, mc])
}
client.postMessage({
url,
method,
headers: [...headers],
scope: self.registration.scope
}, [port2])
}
})
}
evt.respondWith(
clients.matchAll({ type: 'window', includeUncontrolled: true })
.then(getConsumer)
.then(([data, mc]) => {
const body = data.body === 'stream' ? new ReadableStream({
pull(controller) {
return new Promise(rs => {
mc.port1.onmessage = evt => {
evt.data
? controller.enqueue(evt.data) // evt.data is Uint8Array
: controller.close() // evt.data is null, means the stream ended
rs()
}
mc.port1.postMessage(true) // send a pull request
})
},
cancel() {
// This event is never executed
mc.port1.postMessage(false) // send a cancel request
}
}) : data.body
return new Response(body, data)
})
.catch(console.error)
)
})
// self.addEventListener('fetch', (evt) => {
// if (evt.request.mode !== 'navigate') {
// return;
// }
// evt.respondWith(
// fetch(evt.request)
// .catch(async () => {
// const cache = await caches.open(CACHE_NAME);
// return cache.match('offline.html');
// })
// );
// });

View file

@ -1,34 +1,36 @@
<!DOCTYPE html>
<html>
<html lang="en" class="auto-scaling-disabled">
<head>
<link rel="manifest" href="manifest.json">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Miru">
<meta name="description" content="Way too high quality anime for streaming, ad free in a simple solution.">
<meta name="theme-color" content="#25282c" />
<link rel="manifest" href="manifest.json">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Miru">
<meta name="description" content="Anime torrent streaming, ad free in a simple solution.">
<meta name="theme-color" content="#111417" />
<link rel="icon" href="logo.png">
<link rel="apple-touch-icon" href="logo.png">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
<meta name="viewport" content="width=device-width" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="apple-touch-icon" href="logo.png">
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then((reg) => {
console.log('Service worker registered.', reg);
});
});
}
</script>
<link rel="icon" href="logo.png">
<title>Miru - Torrent streaming made simple!</title>
<link href="https://cdn.jsdelivr.net/npm/halfmoon@1.1.0/css/halfmoon-variables.min.css" rel="stylesheet" />
</head>
<body>
test
<body class="with-custom-webkit-scrollbars with-custom-css-scrollbars">
<div class="page-wrapper">
<div class="content-wrapper">
test
<!--
Add your page's main content here
Examples:
1. https://www.gethalfmoon.com/docs/content-and-cards/#building-a-page
2. https://www.gethalfmoon.com/docs/grid-system/#building-a-dashboard
-->
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/halfmoon@1.1.0/js/halfmoon.min.js"></script>
</body>
</html>

View file

@ -1,5 +1,5 @@
{
"name": "Miru",
"name": "Miru - Torrent streaming made simple!",
"short_name": "Miru",
"start_url": "/app/app.html",
"display": "standalone",
@ -8,15 +8,20 @@
],
"lang": "en-US",
"orientation": "landscape",
"background_color": "#25282c",
"theme_color": "#25282c",
"background_color": "#111417",
"theme_color": "#111417",
"scope": "/app/",
"description": "Way too high quality anime for streaming, ad free in a simple solution.",
"description": "Anime torrent streaming, ad free in a simple solution.",
"icons": [
{
"src": "/logo.png",
"sizes": "768x768",
"type": "image/png"
}
]
],
"intent_filters": {
"scope_url_scheme": "https",
"scope_url_host": "miru.moe",
"scope_url_path": "/app/"
}
}

54
sw.js
View file

@ -1,53 +1 @@
'use strict';
const CACHE_NAME = 'static-cache-v1';
const FILES_TO_CACHE = [
'/offline.html',
];
self.addEventListener('install', (evt) => {
console.log('[ServiceWorker] Install');
// CODELAB: Precache static resources here.
evt.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
console.log('[ServiceWorker] Pre-caching offline page');
return cache.addAll(FILES_TO_CACHE);
})
);
self.skipWaiting();
});
self.addEventListener('activate', (evt) => {
console.log('[ServiceWorker] Activate');
// CODELAB: Remove previous cached data from disk.
evt.waitUntil(
caches.keys().then((keyList) => {
return Promise.all(keyList.map((key) => {
if (key !== CACHE_NAME) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
self.clients.claim();
});
self.addEventListener('fetch', (evt) => {
console.log('[ServiceWorker] Fetch', evt.request.url);
// CODELAB: Add fetch event handler here.
if (evt.request.mode !== 'navigate') {
// Not a page navigation, bail.
return;
}
evt.respondWith(
fetch(evt.request)
.catch(() => {
return caches.open(CACHE_NAME)
.then((cache) => {
return cache.match('offline.html');
});
})
);
});
self.addEventListener('fetch',(event)=>{});