mirror of
https://github.com/NoCrypt/migu.git
synced 2026-04-19 15:42:05 +00:00
Merge branch 'master' of https://github.com/RockinChaos/miru
This commit is contained in:
commit
aecfbb7083
10 changed files with 191 additions and 19 deletions
|
|
@ -269,7 +269,7 @@ export default class TorrentClient extends WebTorrent {
|
|||
}
|
||||
this.current = found
|
||||
if (data.data.external && this.player) {
|
||||
this.playerProcess = spawn(this.player, [encodeURI('' + new URL('http://localhost:' + this.server.address().port + found.streamURL))])
|
||||
this.playerProcess = spawn(this.player, ['' + new URL('http://localhost:' + this.server.address().port + found.streamURL)])
|
||||
this.playerProcess.stdout.on('data', () => {})
|
||||
const startTime = Date.now()
|
||||
this.playerProcess.once('close', () => {
|
||||
|
|
|
|||
|
|
@ -1109,9 +1109,11 @@
|
|||
<!-- eslint-disable-next-line svelte/valid-compile -->
|
||||
<div class='w-full h-full position-absolute toggle-immerse d-none' on:dblclick={toggleFullscreen} on:click|self={toggleImmerse} />
|
||||
<div class='w-full h-full position-absolute mobile-focus-target d-none' use:click={() => { page = 'player' }} />
|
||||
<span class='material-symbols-outlined ctrl h-full align-items-center justify-content-end w-150 mw-full mr-auto' use:click={rewind}> fast_rewind </span>
|
||||
<!-- eslint-disable-next-line svelte/valid-compile -->
|
||||
<span class='material-symbols-outlined ctrl h-full align-items-center justify-content-end w-150 mw-full mr-auto' on:click={rewind}> fast_rewind </span>
|
||||
<span class='material-symbols-outlined ctrl' data-name='playPause' use:click={playPause}> {ended ? 'replay' : paused ? 'play_arrow' : 'pause'} </span>
|
||||
<span class='material-symbols-outlined ctrl h-full align-items-center w-150 mw-full ml-auto' use:click={forward}> fast_forward </span>
|
||||
<!-- eslint-disable-next-line svelte/valid-compile -->
|
||||
<span class='material-symbols-outlined ctrl h-full align-items-center w-150 mw-full ml-auto' on:click={forward}> fast_forward </span>
|
||||
<div class='position-absolute bufferingDisplay' />
|
||||
{#if currentSkippable}
|
||||
<button class='skip btn text-dark position-absolute bottom-0 right-0 mr-20 mb-5 font-weight-bold z-30' use:click={skip}>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Miru",
|
||||
"version": "5.2.3",
|
||||
"version": "5.2.6",
|
||||
"private": true,
|
||||
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
|
||||
"description": "Stream anime torrents, real-time with no waiting for downloads.",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export default class Updater {
|
|||
install () {
|
||||
if (this.hasUpdate) {
|
||||
autoUpdater.quitAndInstall()
|
||||
this.hasUpdate = false
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
32
extensions/example.js
Normal file
32
extensions/example.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
export default class AbstractSource {
|
||||
name = 'Missing name'
|
||||
description = 'No description provided'
|
||||
/** @type {import('./type-definitions').Accuracy} */
|
||||
accuracy = 'Low'
|
||||
/** @type {import('./type-definitions').Config} */
|
||||
config = {}
|
||||
|
||||
/**
|
||||
* Gets results for single episode
|
||||
* @type {import('./type-definitions').SearchFunction}
|
||||
*/
|
||||
single (options) {
|
||||
throw new Error('Source doesn\'t implement single')
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets results for batch of episodes
|
||||
* @type {import('./type-definitions').SearchFunction}
|
||||
*/
|
||||
batch (options) {
|
||||
throw new Error('Source doesn\'t implement batch')
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets results for a movie
|
||||
* @type {import('./type-definitions').SearchFunction}
|
||||
*/
|
||||
movie (options) {
|
||||
throw new Error('Source doesn\'t implement movie')
|
||||
}
|
||||
}
|
||||
42
extensions/type-definitions.d.ts
vendored
Normal file
42
extensions/type-definitions.d.ts
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
export interface Result {
|
||||
title: string // torrent title
|
||||
link: string // link to .torrent file, or magnet link
|
||||
id?: number
|
||||
seeders: number
|
||||
leechers: number
|
||||
downloads: number
|
||||
hash: string // info hash
|
||||
size: number // size in bytes
|
||||
verified: boolean // if it's a verified release, e.g. it's 100% certain it's the correct episode, manually verified by the provider e.g. anidb
|
||||
date: Date // date the torrent was uploaded
|
||||
type?: 'batch' | 'best' | 'alt'
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
anilistId: number // anilist anime id
|
||||
anidbAid?: number // anidb anime id
|
||||
anidbEid?: number // anidb episode id
|
||||
titles: string[] // list of titles and alternative titles
|
||||
episode?: number
|
||||
episodeCount?: number // total episode count for the series
|
||||
resolution: '2160' | '1080' | '720' | '540' | '480' | ''
|
||||
exclusions: string[] // list of keywords to exclude from searches
|
||||
}
|
||||
|
||||
export type SearchFunction = (options: Options) => Promise<Result[]>
|
||||
|
||||
export type Config = {
|
||||
seed?: 'perma' | number // seed ratio to hit
|
||||
}
|
||||
|
||||
export type Accuracy = 'High' | 'Medium' | 'Low'
|
||||
|
||||
export class Source {
|
||||
name: string
|
||||
description: string
|
||||
accuracy: Accuracy
|
||||
config: Config
|
||||
single: SearchFunction
|
||||
batch: SearchFunction
|
||||
movie: SearchFunction
|
||||
}
|
||||
|
|
@ -789,8 +789,8 @@ packages:
|
|||
engines: {node: '>=16.0.0'}
|
||||
dependencies:
|
||||
'@ionic/utils-terminal': 2.3.5
|
||||
debug: 4.3.4
|
||||
tslib: 2.6.2
|
||||
debug: 4.3.5
|
||||
tslib: 2.6.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -855,8 +855,8 @@ packages:
|
|||
'@ionic/utils-stream': 3.1.6
|
||||
'@ionic/utils-terminal': 2.3.4
|
||||
cross-spawn: 7.0.3
|
||||
debug: 4.3.4
|
||||
tslib: 2.6.2
|
||||
debug: 4.3.5
|
||||
tslib: 2.6.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -881,12 +881,12 @@ packages:
|
|||
engines: {node: '>=16.0.0'}
|
||||
dependencies:
|
||||
'@types/slice-ansi': 4.0.0
|
||||
debug: 4.3.4
|
||||
debug: 4.3.5
|
||||
signal-exit: 3.0.7
|
||||
slice-ansi: 4.0.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
tslib: 2.6.2
|
||||
tslib: 2.6.3
|
||||
untildify: 4.0.0
|
||||
wrap-ansi: 7.0.0
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -6496,13 +6496,13 @@ packages:
|
|||
'@ionic/utils-fs': 3.1.7
|
||||
'@ionic/utils-terminal': 2.3.5
|
||||
bplist-parser: 0.3.2
|
||||
debug: 4.3.4
|
||||
debug: 4.3.5
|
||||
elementtree: 0.1.7
|
||||
ini: 3.0.1
|
||||
plist: 3.1.0
|
||||
split2: 4.2.0
|
||||
through2: 4.0.2
|
||||
tslib: 2.6.2
|
||||
tslib: 2.6.3
|
||||
yauzl: 2.10.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class='position-absolute w-350 h-400 absolute-container top-0 bottom-0 m-auto bg-dark-light rounded overflow-hidden pointer'>
|
||||
<div class='position-absolute w-350 h-400 absolute-container z-10 top-0 bottom-0 m-auto bg-dark-light rounded overflow-hidden pointer'>
|
||||
<div class='banner position-relative bg-black'>
|
||||
<img src={media.bannerImage || ' '} alt='banner' class='img-cover w-full h-full' loading='lazy' />
|
||||
{#if media.trailer?.id}
|
||||
|
|
|
|||
66
web/src/routes/extensions/+page.svelte
Normal file
66
web/src/routes/extensions/+page.svelte
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<div class='container font-size-18 pb-20'>
|
||||
<div class='content'>
|
||||
<div class='h-vh-half px-20 px-sm-0 d-flex justify-content-center flex-column'>
|
||||
<h1 class='font-weight-bold text-white title'>About Extensions</h1>
|
||||
<div class='font-size-18 text-muted'>Frequently Asked Questions about Extensions.</div>
|
||||
</div>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>What are some recommended extensions and sources?</h3>
|
||||
<p>Miru is bring-your-own-content and does not offer anything, however <kbd>anisearch</kbd> is recommended.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Is there a curated list of extensions and sources?</h3>
|
||||
<p>No. Miru is not directly associated with any extensions or sources. It's merely a client for streaming one's own media.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>How to install/uninstall extensions?</h3>
|
||||
<p>Inside <kbd>Settings > Torrent > Extensions</kbd> you can add extensions by either inputting a full URL such as <kbd>https://example.website/file.js</kbd> or if an extension is published on npm <kbd>packagename</kbd> and pressing add. This will automatically import all sources the extension provides. You can then uninstall an extension by pressing the remove button next to it.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Can you disable sources?</h3>
|
||||
<p>You can disable sources in the sources list by clicking on it's toggle.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>How to develop new extensions?</h3>
|
||||
<p>Extensions for Miru need to be written in JavaScript which are run in an isolated <a href='https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API' target='_blank'>Web Worker</a>. Make sure the data you're fetching is CORS enabled. Extension type definitions and example structures are available on <a href='https://github.com/ThaUnknown/miru/tree/master/extensions' target='_blank'>GitHub</a>.</p>
|
||||
<p>Options object, which is passed to the class's single, batch and movie functions as the first parameters has the following fields:</p>
|
||||
<ul>
|
||||
<li>anilistId: number - Anilist anime id, can be used to query data from Anilist, such as MalID, episode metadata etc</li>
|
||||
<li>anidbAid?: number - AniDB anime id, not always present, useful to query mapping API's</li>
|
||||
<li>anidbEid?: number - AniDB episode id, not always present, useful to query specific data, as AnidbEIDs map to manually maintained files</li>
|
||||
<li>titles: string[] - list of titles and alternative titles for the given anime</li>
|
||||
<li>episode?: number - episode to look for, not always present</li>
|
||||
<li>episodeCount?: number - total episode count for the series, not always present</li>
|
||||
<li>resolution: '2160' | '1080' | '720' | '540' | '480' | '' - resolution height. empty string means any</li>
|
||||
<li>exclusions: string[] - list of keywords to exclude from searches such as codecs unsuppored by the platform, etc</li>
|
||||
</ul>
|
||||
<p>Results object, array of which is returned by the functions of the class has the following fields:</p>
|
||||
<ul>
|
||||
<li>title: string - torrent title, this isn't always the file title as a torrent might include multiple files</li>
|
||||
<li>link: string - http:// link to .torrent file, or magnet:// link</li>
|
||||
<li>id?: number - unused for now</li>
|
||||
<li>seeders: number</li>
|
||||
<li>leechers: number</li>
|
||||
<li>downloads: number</li>
|
||||
<li>hash: string - info hash REQUIRED</li>
|
||||
<li>size: number - size in bytes</li>
|
||||
<li>verified: boolean - if it's a verified release, e.g. it's 100% certain it's the correct episode, manually verified by the provider e.g. anidb</li>
|
||||
<li>date: Date - date the torrent was uploaded</li>
|
||||
<li>type?: 'batch' | 'best' | 'alt' - type of the result best/alt means it's the best known release</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
a {
|
||||
--dm-link-text-color: #1890ff !important;
|
||||
--dm-link-text-color-hover: #45a3fb !important;
|
||||
}
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
padding-top: 0.75em;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
.title {
|
||||
font-size: 5rem
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,22 +1,34 @@
|
|||
<div class='container font-size-18 pb-20'>
|
||||
<div class='content'>
|
||||
<h1 class='text-white font-weight-bold'>Frequently Asked Questions</h1>
|
||||
<h3 class='text-white font-weight-bold'>Won't this kill swarm health?</h3>
|
||||
<p>Depends. On average no. The app is always seeding 1 torrent as long as it's open. Additionally the upload speed is forced to be x1.5 that of the download speed. Those 2 things combined will already make this app seed more than the average leecher which removes the torrent the moment it's downloaded.</p>
|
||||
<div class='h-vh-half row px-20 px-sm-0 d-flex justify-content-center flex-column'>
|
||||
<h1 class='font-weight-bold text-white title'>Frequently Asked Questions</h1>
|
||||
<div class='font-size-18 text-muted'>Most commonly asked questions about Miru and its usage.</div>
|
||||
</div>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>What extensions are there? How to make extensions?</h3>
|
||||
<p>You can find all information regarding extensions on the <a href='../extensions/' target='_blank'>extensions</a> page.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Can I close the miniplayer?</h3>
|
||||
<p>No. See above. The miniplayer provides feedback that something is happening in the background. Closing it would make the user feel like the app is lagging [because it's maxing out your internet in the background by torrenting] when nothing is happening.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Can I reduce the upload speed?</h3>
|
||||
<p>No. See above. This app is also meant to seed the torrents the user downloads, if you want freeleech go to some private tracker.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Does Miru stream the video or does it store it?</h3>
|
||||
<p>Miru only stores 1 torrent on your drive, unless <kbd>Persist Files</kbd> is enabled in settings. It doesn't stream the content as it also needs to seed the data it downloads to keep the swarm alive. It's important to note that it stores 1 torrent, not 1 video. A single torrent can sometimes consist of many video files, and as such take up a lot of space.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>I have an existing media library, can Miru import it?</h3>
|
||||
<p>No. Miru does not scan libraries like Plex or Jellyfin. You can however specify Miru's <kbd>Torrent Download Location</kbd> in settings, and if you pick torrents which are already in the selected folder, Miru will use them without re-download them. Make sure that <kbd>Persis Files</kbd> is enabled, or Miru will delete content that was already watched.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Is this safe?</h3>
|
||||
<p>It's recommended that you read the <a href='https://thewiki.moe/getting-started/torrenting/' target='_blank'>guide about basics of torrenting</a>.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Will this replace streaming sites?</h3>
|
||||
<p>Not really. The underlying source of video are still torrents, which aren't always seeded, so anime that's a few years old might not play back smoothly.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Can I log in with MAL?</h3>
|
||||
<p>No. You can however migrate MAL to AL, <a href='https://anilist.co/forum/thread/3393' target='_blank'>see this guide</a>.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Why is anime X not playing?</h3>
|
||||
<p>One of four reasons:</p>
|
||||
<ul>
|
||||
|
|
@ -25,29 +37,46 @@
|
|||
<li>your ISP blocks Torrenting, see <a href='https://thewiki.moe/tutorials/unblock/' target='_blank'>this tutorial</a> for a potential fix, or simply use a VPN</li>
|
||||
<li>the app couldn't find a matching torrent for the anime</li>
|
||||
</ul>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>I selected an episode to play, but Miru plays something else!</h3>
|
||||
<p>Finding desired episodes can sometimes be difficult, if Miru auto-selects an episode incorrectly you can either disable auto-play torrents in settings to select torrents yourself during episode choosing, or manually find and paste in a .torrent file URL or a magnet URL into Miru to play a desired episode manually.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Can I play my own torrents?</h3>
|
||||
<p>Yes. For the home menu you can specify a different RSS feed to check when the app looks for new releases. Additionally you can just paste/drag-drop a torrent file/magnet link anywhere when using the app, and it will try it's best to auto-detect what anime is playing.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Can I change what tracker torrents are found from?</h3>
|
||||
<p>Yes. If you find other community made extensions, you can import them in the app settings, however there is no curated list of community made extensions.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>How is this different from sequential qBit?</h3>
|
||||
<p>Unlike qBit's sequential, this will prioritise downloading torrent pieces directly needed for playback, which with the user seeking isn't always just sequential.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Won't this kill swarm health?</h3>
|
||||
<p>Depends. On average no. The app is always seeding 1 torrent as long as it's open. Additionally the upload speed is forced to be x1.5 that of the download speed. Those 2 things combined will already make this app seed more than the average leecher which removes the torrent the moment it's downloaded.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Why is it a native app, not a website?</h3>
|
||||
<p>The BitTorrent protocol requires TCP/UDP to function, that is the only reason. Browsers can't access TCP/UDP which means they can't access the global BitTorrent swarm.</p>
|
||||
<h5 class='text-white font-weight-bold'>> Can't you make this just use WebRTC?</h5>
|
||||
<p>Yes. A BitTorrent implementation which uses WebRTC exists, but it's not yet adopted by any clients, and libtorrent [the library which qBit and others use] is still working on/just added support for WebRTC, which means there's no global swarm. This will hopefully change in the future.</p>
|
||||
<hr class='my-20' />
|
||||
<h3 class='text-white font-weight-bold'>Miru crashed too many times.</h3>
|
||||
<p>This is likely because Miru updated from a very old version to a very new one. Uninstall Miru, go to <kbd>%appdata%/miru</kbd> remove all files and re-install it. If this issue persists visit the Discord for help.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
padding-top: 10rem;
|
||||
}
|
||||
a {
|
||||
--dm-link-text-color: #1890ff !important;
|
||||
--dm-link-text-color-hover: #45a3fb !important;
|
||||
}
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
padding-top: 0.75em;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
.title {
|
||||
font-size: 5rem
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue