feat: aniskip API

This commit is contained in:
ThaUnknown 2023-01-16 17:15:06 +01:00
parent d9c9d6849f
commit 2b12bd690e
4 changed files with 61 additions and 1 deletions

View file

@ -1,6 +1,6 @@
{
"name": "Miru",
"version": "3.6.0",
"version": "3.7.0",
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
"description": "Stream anime torrents, real-time with no waiting for downloads.",
"main": "src/index.js",

View file

@ -8,6 +8,7 @@
import Subtitles from '@/modules/subtitles.js'
import { toTS, videoRx, fastPrettyBytes, throttle } from '@/modules/util.js'
import { addToast } from '../Toasts.svelte'
import { getChaptersAniSkip } from '@/modules/anime.js'
import { w2gEmitter } from '../WatchTogether/WatchTogether.svelte'
import Keybinds, { loadWithDefaults, condition } from 'svelte-keybinds'
@ -636,6 +637,11 @@
client.on('chapters', ({ detail }) => {
chapters = detail
})
async function findChapters () {
if (!chapters.length) {
chapters = await getChaptersAniSkip(current, safeduration)
}
}
let hoverChapter = null
let currentSkippable = null
@ -911,6 +917,7 @@
on:loadedmetadata={hideBuffering}
on:ended={tryPlayNext}
on:loadedmetadata={initThumbnails}
on:loadedmetadata={findChapters}
on:loadedmetadata={autoPlay}
on:loadedmetadata={checkAudio}
on:leavepictureinpicture={() => (pip = false)} />

View file

@ -190,6 +190,7 @@ export async function alRequest (opts) {
const userId = (await alID)?.data?.Viewer.id
const queryObjects = /* js */`
id,
idMal,
title {
romaji,
english,

View file

@ -71,6 +71,58 @@ export async function traceAnime (image) { // WAIT lookup logic
}
}
const parts = ['A', 'B', 'C', 'D', 'E']
export async function getChaptersAniSkip (file, duration) {
const res = await fetch(`https://api.aniskip.com/v2/skip-times/${file.media.media.idMal}/${file.media.episode}/?episodeLength=${duration}&types=op&types=ed&types=recap`)
const { found, results } = await res.json()
if (!found) return []
const chapters = results.map(result => {
return {
start: result.interval.startTime * 1000,
end: result.interval.endTime * 1000,
text: result.skipType.toUpperCase()
}
})
const ed = chapters.find(({ text }) => text === 'ED')
const recap = chapters.find(({ text }) => text === 'RECAP')
if (recap) recap.text = 'Recap'
chapters.sort((a, b) => a - b)
if ((chapters[0].start | 0) !== 0) {
chapters.unshift({ start: 0, end: chapters[0].start, text: 'Intro' })
}
let part = 0
if (ed) {
if ((ed.end | 0) + 5000 - duration * 1000 < 0) {
chapters.push({ start: ed.end, end: duration * 1000, text: 'Preview' })
}
} else if ((chapters[chapters.length - 1].end | 0) + 5000 - duration * 1000 < 0) {
chapters.push({
start: chapters[chapters.length - 1].end,
end: duration * 1000,
text: 'Part ' + parts[part++]
})
}
for (let i = 0, len = chapters.length - 2; i <= len; ++i) {
const current = chapters[i]
const next = chapters[i + 1]
if ((current.end | 0) !== (next.start | 0)) {
chapters.push({
start: current.end,
end: next.start,
text: 'Part ' + parts[part++]
})
}
}
chapters.sort((a, b) => a - b)
return chapters
}
export function getMediaMaxEp (media, playable) {
if (playable) {
return media.nextAiringEpisode?.episode - 1 || media.airingSchedule?.nodes?.[0]?.episode - 1 || media.episodes