mirror of
https://github.com/NoCrypt/migu.git
synced 2026-08-14 19:37:41 +00:00
fix: S2 text being removed from titles, player failing on no media, improve resolveFileMedia speed
This commit is contained in:
parent
26a1741aae
commit
8969d293e4
6 changed files with 133 additions and 135 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Miru",
|
||||
"version": "2.2.3",
|
||||
"version": "2.2.4",
|
||||
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
|
||||
"main": "src/index.js",
|
||||
"homepage": "https://github.com/ThaUnknown/miru#readme",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<link href='/lib/halfmoon.css' rel='stylesheet'>
|
||||
<link href="/lib/Material-Icons.css" rel="stylesheet">
|
||||
|
||||
<script defer type="module" src="/src/main.js"></script>
|
||||
<script defer type="module" src="/src/main.js" async></script>
|
||||
</head>
|
||||
|
||||
<body class="dark-mode with-custom-webkit-scrollbars with-custom-css-scrollbars">
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@
|
|||
exclusions.push('AC3', 'AC-3')
|
||||
}
|
||||
video.remove()
|
||||
console.log(exclusions)
|
||||
|
||||
async function getRSSEntries ({ media, episode, mode }) {
|
||||
// mode cuts down on the amt of queries made
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
export let media = null
|
||||
let fileMedia = null
|
||||
let hadImage = false
|
||||
export function updateMedia(fileMed) {
|
||||
export function updateMedia (fileMed) {
|
||||
if (!fileMedia) {
|
||||
setDiscordRPC(fileMed)
|
||||
}
|
||||
|
|
@ -20,34 +20,34 @@
|
|||
const metadata =
|
||||
fileMedia.episodeThumbnail || fileMedia.mediaCover
|
||||
? new MediaMetadata({
|
||||
title: name,
|
||||
artwork: [
|
||||
{
|
||||
src: fileMedia.episodeThumbnail || fileMedia.mediaCover,
|
||||
sizes: '256x256',
|
||||
type: 'image/jpg'
|
||||
}
|
||||
]
|
||||
})
|
||||
title: name,
|
||||
artwork: [
|
||||
{
|
||||
src: fileMedia.episodeThumbnail || fileMedia.mediaCover,
|
||||
sizes: '256x256',
|
||||
type: 'image/jpg'
|
||||
}
|
||||
]
|
||||
})
|
||||
: new MediaMetadata({ title: name })
|
||||
if (fileMedia.parseObject?.release_group) metadata.artist = fileMedia.parseObject.release_group
|
||||
navigator.mediaSession.metadata = metadata
|
||||
}
|
||||
function setDiscordRPC(fileMedia) {
|
||||
function setDiscordRPC (fileMedia) {
|
||||
if (fileMedia) {
|
||||
window.IPC.emit('discord', {
|
||||
activity: {
|
||||
details: fileMedia.media.title.userPreferred,
|
||||
state: 'Watching Episode' + (!fileMedia.media.episodes ? ` ${fileMedia.episodeNumber}` : ''),
|
||||
details: fileMedia.media?.title.userPreferred || fileMedia.parseObject.anime_title,
|
||||
state: 'Watching Episode ' + ((!fileMedia.media?.episodes && fileMedia.episodeNumber) || ''),
|
||||
timestamps: {
|
||||
start: Date.now()
|
||||
},
|
||||
party: {
|
||||
size: (fileMedia.episodeNumber && fileMedia.media.episodes && [fileMedia.episodeNumber, fileMedia.media.episodes]) || undefined
|
||||
size: (fileMedia.episodeNumber && fileMedia.media?.episodes && [fileMedia.episodeNumber, fileMedia.media.episodes]) || undefined
|
||||
},
|
||||
assets: {
|
||||
large_text: fileMedia.media.title.userPreferred,
|
||||
large_image: fileMedia.media.coverImage.extraLarge,
|
||||
large_text: fileMedia.media?.title.userPreferred,
|
||||
large_image: fileMedia.media?.coverImage.extraLarge,
|
||||
small_image: 'logo',
|
||||
small_text: 'https://github.com/ThaUnknown/miru'
|
||||
},
|
||||
|
|
@ -74,11 +74,11 @@
|
|||
paused = detail.paused
|
||||
})
|
||||
|
||||
function updatew2g() {
|
||||
function updatew2g () {
|
||||
w2gEmitter.emit('player', { time: Math.floor(currentTime), paused })
|
||||
}
|
||||
|
||||
async function mediaChange(current, image) {
|
||||
async function mediaChange (current, image) {
|
||||
if (current && 'mediaSession' in navigator) {
|
||||
if (!media || (!hadImage && image)) {
|
||||
// filename is already mapped so this *should* be fine
|
||||
|
|
@ -92,8 +92,8 @@
|
|||
|
||||
export let miniplayer = false
|
||||
export let page
|
||||
$: updateFiles(files)
|
||||
export let files = []
|
||||
$: updateFiles(files)
|
||||
let src = null
|
||||
let video = null
|
||||
let container = null
|
||||
|
|
@ -111,16 +111,16 @@
|
|||
let bufferTimeout = null
|
||||
let subHeaders = null
|
||||
let pip = false
|
||||
let presentationRequest = null
|
||||
const presentationRequest = null
|
||||
let presentationConnection = null
|
||||
let canCast = false
|
||||
const canCast = false
|
||||
let isFullscreen = false
|
||||
let ended = false
|
||||
let volume = localStorage.getItem('volume') || 1
|
||||
let playbackRate = 1
|
||||
$: localStorage.setItem('volume', volume || 0)
|
||||
|
||||
function checkAudio() {
|
||||
function checkAudio () {
|
||||
if ('audioTracks' in HTMLVideoElement.prototype && !video.audioTracks.length) {
|
||||
addToast({
|
||||
text: "This torrent's audio codec is not supported, try a different release by disabling Autoplay Torrents in RSS settings.",
|
||||
|
|
@ -129,12 +129,12 @@
|
|||
})
|
||||
}
|
||||
}
|
||||
function getFPS() {
|
||||
function getFPS () {
|
||||
video.fps = new Promise(resolve => {
|
||||
let lastmeta = null
|
||||
let count = 0
|
||||
|
||||
function handleFrames(now, metadata) {
|
||||
function handleFrames (now, metadata) {
|
||||
if (count) {
|
||||
// resolve on 2nd frame, 1st frame might be a cut-off
|
||||
if (lastmeta) {
|
||||
|
|
@ -169,7 +169,7 @@
|
|||
}
|
||||
|
||||
// plays one frame
|
||||
function playFrame() {
|
||||
function playFrame () {
|
||||
let wasPaused = false
|
||||
video.requestVideoFrameCallback(() => {
|
||||
if (wasPaused) paused = true
|
||||
|
|
@ -193,16 +193,16 @@
|
|||
// })
|
||||
// }
|
||||
|
||||
//document.fullscreenElement isn't reactive
|
||||
// document.fullscreenElement isn't reactive
|
||||
document.addEventListener('fullscreenchange', () => {
|
||||
isFullscreen = !!document.fullscreenElement
|
||||
})
|
||||
|
||||
function handleHeaders() {
|
||||
function handleHeaders () {
|
||||
subHeaders = subs?.headers
|
||||
}
|
||||
|
||||
function updateFiles(files) {
|
||||
function updateFiles (files) {
|
||||
if (files && files.length) {
|
||||
videos = files.filter(file => videoRx.test(file.name))
|
||||
if (videos?.length) {
|
||||
|
|
@ -222,7 +222,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function handleCurrent(file) {
|
||||
async function handleCurrent (file) {
|
||||
if (file) {
|
||||
if (thumbnailData.video?.src) URL.revokeObjectURL(video?.src)
|
||||
Object.assign(thumbnailData, {
|
||||
|
|
@ -243,7 +243,7 @@
|
|||
|
||||
let hasNext = false
|
||||
let hasLast = false
|
||||
function checkAvail(current) {
|
||||
function checkAvail (current) {
|
||||
if ((media?.nextAiringEpisode?.episode - 1 || media?.episodes) > fileMedia?.episodeNumber) {
|
||||
hasNext = true
|
||||
} else if (videos.indexOf(current) !== videos.length - 1) {
|
||||
|
|
@ -260,11 +260,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
function initSubs() {
|
||||
function initSubs () {
|
||||
if (subs) subs.destroy()
|
||||
subs = new Subtitles(video, files, current, handleHeaders)
|
||||
}
|
||||
function cycleSubtitles() {
|
||||
function cycleSubtitles () {
|
||||
if (current && subs?.headers) {
|
||||
const tracks = subs.headers.filter(header => header)
|
||||
const index = tracks.indexOf(subs.headers[subs.current]) + 1
|
||||
|
|
@ -274,33 +274,33 @@
|
|||
|
||||
let subDelay = 0
|
||||
$: updateDelay(subDelay)
|
||||
function updateDelay(delay) {
|
||||
function updateDelay (delay) {
|
||||
if (subs?.renderer) subs.renderer.timeOffset = delay
|
||||
}
|
||||
|
||||
let currentTime = 0
|
||||
$: progress = currentTime / duration
|
||||
$: targetTime = (!paused && currentTime) || targetTime
|
||||
function handleMouseDown({ target }) {
|
||||
function handleMouseDown ({ target }) {
|
||||
wasPaused = paused
|
||||
paused = true
|
||||
targetTime = target.value * duration
|
||||
}
|
||||
function handleMouseUp() {
|
||||
function handleMouseUp () {
|
||||
paused = wasPaused
|
||||
currentTime = targetTime
|
||||
}
|
||||
function handleProgress({ target }) {
|
||||
function handleProgress ({ target }) {
|
||||
targetTime = target.value * duration
|
||||
}
|
||||
|
||||
function autoPlay() {
|
||||
function autoPlay () {
|
||||
if (!miniplayer) video.play()
|
||||
}
|
||||
function playPause() {
|
||||
function playPause () {
|
||||
paused = !paused
|
||||
}
|
||||
function toggleMute() {
|
||||
function toggleMute () {
|
||||
muted = !muted
|
||||
}
|
||||
let visibilityPaused = true
|
||||
|
|
@ -314,10 +314,10 @@
|
|||
}
|
||||
}
|
||||
})
|
||||
function tryPlayNext() {
|
||||
function tryPlayNext () {
|
||||
if (set.playerAutoplay) playNext()
|
||||
}
|
||||
function playNext() {
|
||||
function playNext () {
|
||||
if (hasNext) {
|
||||
const index = videos.indexOf(current)
|
||||
if (index + 2 < videos.length) {
|
||||
|
|
@ -327,7 +327,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
function playLast() {
|
||||
function playLast () {
|
||||
if (hasLast) {
|
||||
const index = videos.indexOf(current)
|
||||
if (index > 1) {
|
||||
|
|
@ -337,10 +337,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
function toggleFullscreen() {
|
||||
function toggleFullscreen () {
|
||||
document.fullscreenElement ? document.exitFullscreen() : container.requestFullscreen()
|
||||
}
|
||||
function seek(time) {
|
||||
function seek (time) {
|
||||
if (time === 85 && currentTime < 10) {
|
||||
targetTime = currentTime = 90
|
||||
} else if (time === 85 && duration - currentTime < 90) {
|
||||
|
|
@ -349,13 +349,13 @@
|
|||
targetTime = currentTime += time
|
||||
}
|
||||
}
|
||||
function forward() {
|
||||
function forward () {
|
||||
seek(2)
|
||||
}
|
||||
function rewind() {
|
||||
function rewind () {
|
||||
seek(-2)
|
||||
}
|
||||
function selectAudio(id) {
|
||||
function selectAudio (id) {
|
||||
if (id !== undefined) {
|
||||
for (const track of video.audioTracks) {
|
||||
track.enabled = track.id === id
|
||||
|
|
@ -363,7 +363,7 @@
|
|||
seek(-0.5) // stupid fix because video freezes up when chaging tracks
|
||||
}
|
||||
}
|
||||
function toggleCast() {
|
||||
function toggleCast () {
|
||||
if (video.readyState) {
|
||||
if (presentationConnection) {
|
||||
presentationConnection?.terminate()
|
||||
|
|
@ -372,7 +372,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
function togglePopout() {
|
||||
function togglePopout () {
|
||||
if (video.readyState) {
|
||||
if (!subs?.renderer) {
|
||||
if (video !== document.pictureInPictureElement) {
|
||||
|
|
@ -414,7 +414,7 @@
|
|||
}
|
||||
}
|
||||
let showKeybinds = false
|
||||
async function handleKeydown({ key }) {
|
||||
async function handleKeydown ({ key }) {
|
||||
if (!miniplayer) {
|
||||
switch (key) {
|
||||
case 'r':
|
||||
|
|
@ -481,7 +481,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function getBurnIn(noSubs) {
|
||||
function getBurnIn (noSubs) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const context = canvas.getContext('2d')
|
||||
let loop = null
|
||||
|
|
@ -502,7 +502,7 @@
|
|||
return { stream: canvas.captureStream(), destroy }
|
||||
}
|
||||
|
||||
function initCast(event) {
|
||||
function initCast (event) {
|
||||
// these quality settings are likely to make cast overheat, oh noes!
|
||||
let peer = new Peer({
|
||||
polite: true,
|
||||
|
|
@ -559,12 +559,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
function immersePlayer() {
|
||||
function immersePlayer () {
|
||||
immersed = true
|
||||
immerseTimeout = undefined
|
||||
}
|
||||
|
||||
function resetImmerse() {
|
||||
function resetImmerse () {
|
||||
if (immerseTimeout) {
|
||||
clearTimeout(immerseTimeout)
|
||||
} else {
|
||||
|
|
@ -573,7 +573,7 @@
|
|||
immerseTimeout = setTimeout(immersePlayer, 8 * 1000)
|
||||
}
|
||||
|
||||
function hideBuffering() {
|
||||
function hideBuffering () {
|
||||
if (bufferTimeout) {
|
||||
clearTimeout(bufferTimeout)
|
||||
bufferTimeout = null
|
||||
|
|
@ -581,7 +581,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function showBuffering() {
|
||||
function showBuffering () {
|
||||
bufferTimeout = setTimeout(() => {
|
||||
buffering = true
|
||||
resetImmerse()
|
||||
|
|
@ -604,7 +604,7 @@
|
|||
}
|
||||
let stats = null
|
||||
let requestCallback = null
|
||||
function toggleStats() {
|
||||
function toggleStats () {
|
||||
if ('requestVideoFrameCallback' in HTMLVideoElement.prototype) {
|
||||
if (requestCallback) {
|
||||
stats = null
|
||||
|
|
@ -618,7 +618,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
async function handleStats(now, metadata) {
|
||||
async function handleStats (now, metadata) {
|
||||
if (stats) {
|
||||
stats = {
|
||||
fps: await video.fps,
|
||||
|
|
@ -633,8 +633,8 @@
|
|||
setTimeout(() => video.requestVideoFrameCallback(handleStats), 200)
|
||||
}
|
||||
}
|
||||
function getBufferHealth(time) {
|
||||
for (let index = video.buffered.length; index--; ) {
|
||||
function getBufferHealth (time) {
|
||||
for (let index = video.buffered.length; index--;) {
|
||||
if (time < video.buffered.end(index) && time > video.buffered.start(index)) {
|
||||
return parseInt(video.buffered.end(index) - time)
|
||||
}
|
||||
|
|
@ -652,13 +652,13 @@
|
|||
let hover = null
|
||||
let hoverTime = 0
|
||||
let hoverOffset = 0
|
||||
function handleHover({ offsetX, target }) {
|
||||
function handleHover ({ offsetX, target }) {
|
||||
hoverOffset = offsetX / target.clientWidth
|
||||
hoverTime = duration * hoverOffset
|
||||
hover.style.setProperty('left', hoverOffset * 100 + '%')
|
||||
thumbnail = thumbnailData.thumbnails[Math.floor(hoverTime / thumbnailData.interval)] || ' '
|
||||
}
|
||||
function createThumbnail(vid = video) {
|
||||
function createThumbnail (vid = video) {
|
||||
if (vid?.readyState >= 2) {
|
||||
const index = Math.floor(vid.currentTime / thumbnailData.interval)
|
||||
if (!thumbnailData.thumbnails[index]) {
|
||||
|
|
@ -669,7 +669,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
function initThumbnails() {
|
||||
function initThumbnails () {
|
||||
const height = 200 / (videoWidth / videoHeight)
|
||||
if (!isNaN(height)) {
|
||||
thumbnailData.interval = duration / 300 < 5 ? 5 : duration / 300
|
||||
|
|
@ -677,7 +677,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function finishThumbnails() {
|
||||
function finishThumbnails () {
|
||||
const t0 = performance.now()
|
||||
const video = document.createElement('video')
|
||||
let index = 0
|
||||
|
|
@ -715,7 +715,7 @@
|
|||
let innerWidth, innerHeight, videoWidth, videoHeight
|
||||
let menubarOffset = 0
|
||||
// $: calcMenubarOffset(innerWidth, innerHeight, videoWidth, videoHeight)
|
||||
function calcMenubarOffset(innerWidth, innerHeight, videoWidth, videoHeight) {
|
||||
function calcMenubarOffset (innerWidth, innerHeight, videoWidth, videoHeight) {
|
||||
// outerheight resize and innerheight resize is mutual, additionally update on metadata and app state change
|
||||
if (videoWidth && videoHeight) {
|
||||
// so windows is very dumb, and calculates windowed mode as if it was window XP, with the old bars, but not when maximised
|
||||
|
|
@ -734,13 +734,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
function toggleDropdown({ target }) {
|
||||
function toggleDropdown ({ target }) {
|
||||
target.classList.toggle('active')
|
||||
target.closest('.dropdown').classList.toggle('show')
|
||||
}
|
||||
|
||||
let completed = false
|
||||
function checkCompletion() {
|
||||
function checkCompletion () {
|
||||
if (!completed && duration && video?.readyState && duration - 180 < currentTime) {
|
||||
if (fileMedia?.media?.episodes || fileMedia?.media?.nextAiringEpisode?.episode) {
|
||||
if (fileMedia.media.episodes || fileMedia.media.nextAiringEpisode?.episode > fileMedia.episodeNumber) {
|
||||
|
|
@ -752,7 +752,7 @@
|
|||
}
|
||||
const torrent = {}
|
||||
client.on('stats', updateStats)
|
||||
function updateStats({ detail }) {
|
||||
function updateStats ({ detail }) {
|
||||
torrent.peers = detail.numPeers || 0
|
||||
torrent.up = detail.uploadSpeed || 0
|
||||
torrent.down = detail.downloadSpeed || 0
|
||||
|
|
@ -763,13 +763,13 @@
|
|||
ctx = bufferCanvas.getContext('2d')
|
||||
clearCanvas()
|
||||
})
|
||||
function clearCanvas() {
|
||||
function clearCanvas () {
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)'
|
||||
ctx.fillRect(0, 0, bufferCanvas.width, 1)
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.4)'
|
||||
}
|
||||
let imageData = null
|
||||
function handlePieces({ detail }) {
|
||||
function handlePieces ({ detail }) {
|
||||
if (detail.constructor === Array) {
|
||||
if (imageData) {
|
||||
for (let i = 0; i < detail.length; ++i) {
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@ query ($page: Int, $perPage: Int, $sort: [MediaSort], $type: MediaType, $search:
|
|||
}
|
||||
options.body = JSON.stringify({
|
||||
query: query.replace(/\s/g, ''),
|
||||
variables: variables
|
||||
variables
|
||||
})
|
||||
|
||||
return await handleRequest(options)
|
||||
|
|
|
|||
|
|
@ -91,47 +91,51 @@ const postfix = {
|
|||
}
|
||||
|
||||
async function resolveTitle (name) {
|
||||
if (!(name in relations)) {
|
||||
const method = { name, method: 'SearchName', perPage: 1, status: ['RELEASING', 'FINISHED'], sort: 'SEARCH_MATCH' }
|
||||
const method = { name, method: 'SearchName', perPage: 1, status: ['RELEASING', 'FINISHED'], sort: 'SEARCH_MATCH' }
|
||||
|
||||
// inefficient but readable
|
||||
// inefficient but readable
|
||||
|
||||
let media = null
|
||||
// change S2 into Season 2 or 2nd Season
|
||||
const match = method.name.match(/ S(\d)$/)
|
||||
const oldname = method.name
|
||||
try {
|
||||
let media = null
|
||||
// change S2 into Season 2 or 2nd Season
|
||||
const match = method.name.match(/ S(\d)$/)
|
||||
const oldname = method.name
|
||||
try {
|
||||
if (match) {
|
||||
method.name = method.name.replace(/ S(\d)$/, ` ${match[1]}${postfix[match[1]] || 'th'} Season`)
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
if (!media) {
|
||||
method.name = oldname.replace(/ S(\d)$/, ` Season ${match[1]}`)
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
}
|
||||
} else {
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
}
|
||||
|
||||
// remove (TV)
|
||||
if (!media) {
|
||||
const match = method.name.match(/\(TV\)/)
|
||||
if (match) {
|
||||
method.name = method.name.replace(/ S(\d)$/, ` ${match[1]}${postfix[match[1]] || 'th'} Season`)
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
if (!media) {
|
||||
method.name = oldname.replace(/ S(\d)$/, ` Season ${match[1]}`)
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
}
|
||||
} else {
|
||||
method.name = name.replace('(TV)', '').replace('-', '')
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
}
|
||||
|
||||
// remove (TV)
|
||||
if (!media) {
|
||||
const match = method.name.match(/\(TV\)/)
|
||||
if (match) {
|
||||
method.name = name.replace('(TV)', '').replace('-', '')
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
}
|
||||
}
|
||||
// remove 2020
|
||||
if (!media) {
|
||||
const match = method.name.match(/ (19[5-9]\d|20\d{2})/)
|
||||
if (match) {
|
||||
method.name = method.name.replace(/ (19[5-9]\d|20\d{2})/, '')
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
}
|
||||
// remove 2020
|
||||
if (!media) {
|
||||
const match = method.name.match(/ (19[5-9]\d|20\d{2})/)
|
||||
if (match) {
|
||||
method.name = method.name.replace(/ (19[5-9]\d|20\d{2})/, '')
|
||||
media = (await alRequest(method)).data.Page.media[0]
|
||||
}
|
||||
}
|
||||
} catch (e) { }
|
||||
}
|
||||
} catch (e) { }
|
||||
|
||||
if (media?.id) relations[name] = media.id
|
||||
}
|
||||
if (media) relations[name] = media
|
||||
}
|
||||
|
||||
function getParseObjTitle (obj) {
|
||||
let title = obj.anime_title
|
||||
if (obj.anime_season) title += ' S' + obj.anime_season
|
||||
return title
|
||||
}
|
||||
|
||||
export async function resolveFileMedia (opts) {
|
||||
|
|
@ -140,28 +144,23 @@ export async function resolveFileMedia (opts) {
|
|||
? opts.fileName.map(name => anitomyscript(name))
|
||||
: [anitomyscript(opts.fileName)]
|
||||
const parseObjs = await Promise.all(parsePromises)
|
||||
await PromiseBatch(resolveTitle, [...new Set(parseObjs.map(obj => obj.anime_title).filter(title => !(title in relations)))], 10)
|
||||
const assoc = {}
|
||||
for (let ids = [...new Set(parseObjs.map(obj => relations[obj.anime_title]))]; ids.length; ids = ids.slice(50)) {
|
||||
for await (const media of (await alRequest({ method: 'SearchIDS', id: ids.slice(0, 50), perPage: 50 }))?.data?.Page.media || []) {
|
||||
assoc[media.id] = media
|
||||
}
|
||||
}
|
||||
// batches promises in 10 at a time, because of CF burst protection, which still sometimes gets triggered :/
|
||||
await PromiseBatch(resolveTitle, [...new Set(parseObjs.map(obj => getParseObjTitle(obj)))].filter(title => !(title in relations)), 10)
|
||||
const fileMedias = []
|
||||
for (const praseObj of parseObjs) {
|
||||
for (const parseObj of parseObjs) {
|
||||
let failed = false
|
||||
let episode
|
||||
let media = assoc[relations[praseObj.anime_title]]
|
||||
let media = relations[getParseObjTitle(parseObj)]
|
||||
// resolve episode, if movie, dont.
|
||||
const maxep = media?.nextAiringEpisode?.episode || media?.episodes
|
||||
if ((media?.format !== 'MOVIE' || maxep) && praseObj.episode_number) {
|
||||
if (praseObj.episode_number.constructor === Array) {
|
||||
if ((media?.format !== 'MOVIE' || maxep) && parseObj.episode_number) {
|
||||
if (parseObj.episode_number.constructor === Array) {
|
||||
// is an episode range
|
||||
if (parseInt(praseObj.episode_number[0]) === 1) {
|
||||
if (parseInt(parseObj.episode_number[0]) === 1) {
|
||||
// if it starts with #1 and overflows then it includes more than 1 season in a batch, cant fix this cleanly, name is parsed per file basis so this shouldnt be an issue
|
||||
episode = `${praseObj.episode_number[0]} ~ ${praseObj.episode_number[1]}`
|
||||
episode = `${parseObj.episode_number[0]} ~ ${parseObj.episode_number[1]}`
|
||||
} else {
|
||||
if (maxep && parseInt(praseObj.episode_number[1]) > maxep) {
|
||||
if (maxep && parseInt(parseObj.episode_number[1]) > maxep) {
|
||||
// get root media to start at S1, instead of S2 or some OVA due to parsing errors
|
||||
// this is most likely safe, if it was relative episodes then it would likely use an accurate title for the season
|
||||
// if they didnt use an accurate title then its likely an absolute numbering scheme
|
||||
|
|
@ -170,43 +169,43 @@ export async function resolveFileMedia (opts) {
|
|||
const root = prequel && (await resolveSeason({ media: (await alRequest({ method: 'SearchIDSingle', id: prequel.id })).data.Media, force: true })).media
|
||||
|
||||
// if highest value is bigger than episode count or latest streamed episode +1 for safety, parseint to math.floor a number like 12.5 - specials - in 1 go
|
||||
const result = await resolveSeason({ media: root || media, episode: praseObj.episode_number[1] })
|
||||
const result = await resolveSeason({ media: root || media, episode: parseObj.episode_number[1] })
|
||||
media = result.rootMedia
|
||||
const diff = praseObj.episode_number[1] - result.episode
|
||||
episode = `${praseObj.episode_number[0] - diff} ~ ${result.episode}`
|
||||
const diff = parseObj.episode_number[1] - result.episode
|
||||
episode = `${parseObj.episode_number[0] - diff} ~ ${result.episode}`
|
||||
failed = result.failed
|
||||
} else {
|
||||
// cant find ep count or range seems fine
|
||||
episode = `${Number(praseObj.episode_number[0])} ~ ${Number(praseObj.episode_number[1])}`
|
||||
episode = `${Number(parseObj.episode_number[0])} ~ ${Number(parseObj.episode_number[1])}`
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (maxep && parseInt(praseObj.episode_number) > maxep) {
|
||||
if (maxep && parseInt(parseObj.episode_number) > maxep) {
|
||||
// see big comment above
|
||||
const prequel = findEdge(media, 'PREQUEL')?.node || ((media.format === 'OVA' || media.format === 'ONA') && findEdge(media, 'PARENT')?.node)
|
||||
const root = prequel && (await resolveSeason({ media: (await alRequest({ method: 'SearchIDSingle', id: prequel.id })).data.Media, force: true })).media
|
||||
|
||||
// value bigger than episode count
|
||||
const result = await resolveSeason({ media: root || media, episode: parseInt(praseObj.episode_number) })
|
||||
const result = await resolveSeason({ media: root || media, episode: parseInt(parseObj.episode_number) })
|
||||
media = result.rootMedia
|
||||
episode = result.episode
|
||||
failed = result.failed
|
||||
} else {
|
||||
// cant find ep count or episode seems fine
|
||||
episode = Number(praseObj.episode_number)
|
||||
episode = Number(parseObj.episode_number)
|
||||
}
|
||||
}
|
||||
}
|
||||
const streamingEpisode = media?.streamingEpisodes.filter(episode => episodeRx.exec(episode.title) && Number(episodeRx.exec(episode.title)[1]) === Number(praseObj.episode_number))[0]
|
||||
const streamingEpisode = media?.streamingEpisodes.filter(episode => episodeRx.exec(episode.title) && Number(episodeRx.exec(episode.title)[1]) === Number(parseObj.episode_number))[0]
|
||||
fileMedias.push({
|
||||
mediaTitle: media?.title.userPreferred,
|
||||
episodeNumber: episode,
|
||||
mediaTitle: media?.title.userPreferred || parseObj.anime_title,
|
||||
episodeNumber: episode || parseObj.episode_number,
|
||||
episodeTitle: streamingEpisode && episodeRx.exec(streamingEpisode.title)[2],
|
||||
episodeThumbnail: streamingEpisode?.thumbnail,
|
||||
mediaCover: media?.coverImage.medium,
|
||||
name: 'Miru',
|
||||
parseObject: praseObj,
|
||||
media: media,
|
||||
parseObject: parseObj,
|
||||
media,
|
||||
failed
|
||||
})
|
||||
}
|
||||
|
|
@ -268,4 +267,4 @@ export async function resolveSeason (opts) {
|
|||
return resolveSeason({ media, episode, increment, offset, rootMedia, force })
|
||||
}
|
||||
|
||||
export const relations = {}
|
||||
const relations = {}
|
||||
|
|
|
|||
Loading…
Reference in a new issue