mirror of
https://github.com/NoCrypt/migu.git
synced 2026-04-19 07:32:05 +00:00
feat: dns over http
fix: repeating badge color fix: w2g url
This commit is contained in:
parent
2d3013e226
commit
4da3254493
7 changed files with 170 additions and 174 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Miru",
|
||||
"version": "3.10.5",
|
||||
"version": "3.10.6",
|
||||
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
|
||||
"description": "Stream anime torrents, real-time with no waiting for downloads.",
|
||||
"main": "src/index.js",
|
||||
|
|
|
|||
|
|
@ -108,6 +108,13 @@ ipcMain.on('devtools', () => {
|
|||
webtorrentWindow.webContents.openDevTools()
|
||||
})
|
||||
|
||||
ipcMain.on('doh', (event, dns) => {
|
||||
app.configureHostResolver({
|
||||
secureDnsMode: 'secure',
|
||||
secureDnsServers: [dns]
|
||||
})
|
||||
})
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
webtorrentWindow = new BrowserWindow({
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
PLANNING: 'rgb(247,154,99)',
|
||||
COMPLETED: 'rgb(123,213,85)',
|
||||
PAUSED: 'rgb(250,122,122)',
|
||||
REPEAT: '#3baeea',
|
||||
REPEATING: '#3baeea',
|
||||
DROPPED: 'rgb(232,93,117)'
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -15,10 +15,13 @@
|
|||
missingFont: true,
|
||||
maxConns: 20,
|
||||
subtitleLanguage: 'eng',
|
||||
audioLanguage: 'jpn'
|
||||
audioLanguage: 'jpn',
|
||||
enableDoH: false,
|
||||
doHURL: 'https://cloudflare-dns.com/dns-query'
|
||||
}
|
||||
localStorage.removeItem('relations') // TODO: remove
|
||||
export const set = { ...defaults, ...(JSON.parse(localStorage.getItem('settings')) || {}) }
|
||||
if (set.enableDoH) window.IPC.emit('doh', set.doHURL)
|
||||
if (!set.rssFeeds) { // TODO: remove ;-;
|
||||
if (set.rssFeed) {
|
||||
set.rssFeeds = [['New Releases', set.rssFeed]]
|
||||
|
|
@ -363,6 +366,24 @@
|
|||
<input type='checkbox' id='rss-autoplay' bind:checked={settings.rssAutoplay} />
|
||||
<label for='rss-autoplay'>Auto-Play Torrents</label>
|
||||
</div>
|
||||
<div
|
||||
class='custom-switch mb-10 pl-10 font-size-16 w-300'
|
||||
data-toggle='tooltip'
|
||||
data-placement='bottom'
|
||||
data-title='Enables DNS Over HTTPS, useful if your ISP blocks certain domains'>
|
||||
<input type='checkbox' id='rss-dohtoggle' bind:checked={settings.enableDoH} />
|
||||
<label for='rss-dohtoggle'>Enable DoH</label>
|
||||
</div>
|
||||
<div
|
||||
class='input-group input-group-lg form-control-lg mb-10 w-500'
|
||||
data-toggle='tooltip'
|
||||
data-placement='bottom'
|
||||
data-title='Path To Folder Which To Use To Store Torrent Files'>
|
||||
<div class='input-group-prepend'>
|
||||
<span class='input-group-text w-150 justify-content-center'>DoH URL</span>
|
||||
</div>
|
||||
<input type='text' class='form-control' bind:value={settings.doHURL} placeholder={defaults.doHURL} />
|
||||
</div>
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
export let peers
|
||||
export let invite
|
||||
export let cleanup
|
||||
export let peers
|
||||
export let invite
|
||||
export let cleanup
|
||||
</script>
|
||||
|
||||
<div class='d-flex flex-column py-20 root container card'>
|
||||
|
|
@ -19,7 +19,7 @@ export let cleanup
|
|||
{/if}
|
||||
<h4 class='my-0 pl-20 mr-auto'>{peer.user?.name || 'Anonymous'}</h4>
|
||||
{#if peer.user?.name}
|
||||
<span class='material-icons pointer text-primary' on:click={() => window.IPC.emit('open', 'https://anilist.co/user/' + peer.user?.name)}> open_in_new </span>
|
||||
<span class='material-icons pointer text-primary' on:pointerdown={() => window.IPC.emit('open', 'https://anilist.co/user/' + peer.user?.name)}> open_in_new </span>
|
||||
{/if}
|
||||
<!-- {#if state === 'host'}
|
||||
<span class='material-icons ml-15 pointer text-danger' on:click={() => peer.peer.pc.close()}> logout </span>
|
||||
|
|
|
|||
|
|
@ -1,168 +1,168 @@
|
|||
<script context='module'>
|
||||
import { writable } from 'svelte/store'
|
||||
import { alID } from '@/modules/anilist.js'
|
||||
import { add, client } from '@/modules/torrent.js'
|
||||
import { generateRandomHexCode } from '@/modules/util.js'
|
||||
import { addToast } from '@/lib/Toasts.svelte'
|
||||
import { page } from '@/App.svelte'
|
||||
import 'browser-event-target-emitter'
|
||||
import { writable } from 'svelte/store'
|
||||
import { alID } from '@/modules/anilist.js'
|
||||
import { add, client } from '@/modules/torrent.js'
|
||||
import { generateRandomHexCode } from '@/modules/util.js'
|
||||
import { addToast } from '@/lib/Toasts.svelte'
|
||||
import { page } from '@/App.svelte'
|
||||
import 'browser-event-target-emitter'
|
||||
|
||||
import P2PCF from 'p2pcf'
|
||||
import P2PCF from 'p2pcf'
|
||||
|
||||
export const w2gEmitter = new EventTarget()
|
||||
export const w2gEmitter = new EventTarget()
|
||||
|
||||
const decode = TextDecoder.prototype.decode.bind(new TextDecoder('utf-8'))
|
||||
const encode = TextEncoder.prototype.encode.bind(new TextEncoder())
|
||||
const decode = TextDecoder.prototype.decode.bind(new TextDecoder('utf-8'))
|
||||
const encode = TextEncoder.prototype.encode.bind(new TextEncoder())
|
||||
|
||||
const peers = writable({})
|
||||
const peers = writable({})
|
||||
|
||||
export const state = writable(false)
|
||||
export const state = writable(false)
|
||||
|
||||
let p2pcf = null
|
||||
let p2pcf = null
|
||||
|
||||
function joinLobby (code = generateRandomHexCode(16)) {
|
||||
if (p2pcf) cleanup()
|
||||
p2pcf = new P2PCF(generateRandomHexCode(16), code)
|
||||
p2pcf.on('peerconnect', async peer => {
|
||||
console.log(peer.id)
|
||||
console.log('connect')
|
||||
const user = (await alID)?.data?.Viewer || {}
|
||||
peer.send(
|
||||
JSON.stringify({
|
||||
type: 'init',
|
||||
id: user.id || generateRandomHexCode(16),
|
||||
user
|
||||
})
|
||||
)
|
||||
})
|
||||
p2pcf.on('peerclose', peer => {
|
||||
peers.update(object => {
|
||||
function joinLobby (code = generateRandomHexCode(16)) {
|
||||
if (p2pcf) cleanup()
|
||||
p2pcf = new P2PCF(generateRandomHexCode(16), code)
|
||||
p2pcf.on('peerconnect', async peer => {
|
||||
console.log(peer.id)
|
||||
console.log('close', object[peer.id])
|
||||
delete object[peer.id]
|
||||
return object
|
||||
})
|
||||
})
|
||||
p2pcf.on('msg', (peer, data) => {
|
||||
data = typeof data === 'string' ? JSON.parse(data) : JSON.parse(decode(data))
|
||||
console.log(data)
|
||||
switch (data.type) {
|
||||
case 'init':
|
||||
console.log('init', data.user)
|
||||
peers.update(object => {
|
||||
object[peer.id] = {
|
||||
peer,
|
||||
user: data.user
|
||||
}
|
||||
return object
|
||||
console.log('connect')
|
||||
const user = (await alID)?.data?.Viewer || {}
|
||||
peer.send(
|
||||
JSON.stringify({
|
||||
type: 'init',
|
||||
id: user.id || generateRandomHexCode(16),
|
||||
user
|
||||
})
|
||||
break
|
||||
case 'player': {
|
||||
if (setPlayerState(data)) w2gEmitter.emit('playerupdate', data)
|
||||
break
|
||||
}
|
||||
case 'torrent': {
|
||||
if (data.hash !== playerState.hash) {
|
||||
playerState.hash = data.hash
|
||||
add(data.magnet)
|
||||
)
|
||||
})
|
||||
p2pcf.on('peerclose', peer => {
|
||||
peers.update(object => {
|
||||
console.log(peer.id)
|
||||
console.log('close', object[peer.id])
|
||||
delete object[peer.id]
|
||||
return object
|
||||
})
|
||||
})
|
||||
p2pcf.on('msg', (peer, data) => {
|
||||
data = typeof data === 'string' ? JSON.parse(data) : JSON.parse(decode(data))
|
||||
console.log(data)
|
||||
switch (data.type) {
|
||||
case 'init':
|
||||
console.log('init', data.user)
|
||||
peers.update(object => {
|
||||
object[peer.id] = {
|
||||
peer,
|
||||
user: data.user
|
||||
}
|
||||
return object
|
||||
})
|
||||
break
|
||||
case 'player': {
|
||||
if (setPlayerState(data)) w2gEmitter.emit('playerupdate', data)
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'index': {
|
||||
if (playerState.index !== data.index) {
|
||||
playerState.index = data.index
|
||||
w2gEmitter.emit('setindex', data.index)
|
||||
case 'torrent': {
|
||||
if (data.hash !== playerState.hash) {
|
||||
playerState.hash = data.hash
|
||||
add(data.magnet)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'index': {
|
||||
if (playerState.index !== data.index) {
|
||||
playerState.index = data.index
|
||||
w2gEmitter.emit('setindex', data.index)
|
||||
}
|
||||
break
|
||||
}
|
||||
default: {
|
||||
console.error('Invalid message type', data)
|
||||
}
|
||||
break
|
||||
}
|
||||
default: {
|
||||
console.error('Invalid message type', data)
|
||||
}
|
||||
})
|
||||
p2pcf.start()
|
||||
state.set(code)
|
||||
console.log(p2pcf)
|
||||
}
|
||||
|
||||
function setPlayerState (detail) {
|
||||
let emit = false
|
||||
for (const key of ['paused', 'time']) {
|
||||
emit = emit || detail[key] !== playerState[key]
|
||||
playerState[key] = detail[key]
|
||||
}
|
||||
return emit
|
||||
}
|
||||
|
||||
w2gEmitter.on('player', ({ detail }) => {
|
||||
if (setPlayerState(detail)) emit('player', detail)
|
||||
})
|
||||
|
||||
w2gEmitter.on('index', ({ detail }) => {
|
||||
if (playerState.index !== detail.index) {
|
||||
emit('index', detail)
|
||||
playerState.index = detail.index
|
||||
}
|
||||
})
|
||||
p2pcf.start()
|
||||
state.set(code)
|
||||
console.log(p2pcf)
|
||||
}
|
||||
|
||||
function setPlayerState (detail) {
|
||||
let emit = false
|
||||
for (const key of ['paused', 'time']) {
|
||||
emit = emit || detail[key] !== playerState[key]
|
||||
playerState[key] = detail[key]
|
||||
client.on('magnet', ({ detail }) => {
|
||||
if (detail.hash !== playerState.hash) {
|
||||
playerState.hash = detail.hash
|
||||
playerState.index = 0
|
||||
emit('torrent', detail)
|
||||
}
|
||||
})
|
||||
|
||||
function emit (type, data) {
|
||||
p2pcf?.broadcast(encode(JSON.stringify({ type, ...data })))
|
||||
}
|
||||
return emit
|
||||
}
|
||||
|
||||
w2gEmitter.on('player', ({ detail }) => {
|
||||
if (setPlayerState(detail)) emit('player', detail)
|
||||
})
|
||||
|
||||
w2gEmitter.on('index', ({ detail }) => {
|
||||
if (playerState.index !== detail.index) {
|
||||
emit('index', detail)
|
||||
playerState.index = detail.index
|
||||
const playerState = {
|
||||
paused: null,
|
||||
time: null,
|
||||
hash: null,
|
||||
index: 0
|
||||
}
|
||||
})
|
||||
|
||||
client.on('magnet', ({ detail }) => {
|
||||
if (detail.hash !== playerState.hash) {
|
||||
playerState.hash = detail.hash
|
||||
playerState.index = 0
|
||||
emit('torrent', detail)
|
||||
}
|
||||
})
|
||||
|
||||
function emit (type, data) {
|
||||
p2pcf?.broadcast(encode(JSON.stringify({ type, ...data })))
|
||||
}
|
||||
|
||||
const playerState = {
|
||||
paused: null,
|
||||
time: null,
|
||||
hash: null,
|
||||
index: 0
|
||||
}
|
||||
|
||||
function checkInvite (invite) {
|
||||
if (invite) {
|
||||
const match = invite.match(inviteRx)
|
||||
if (match) {
|
||||
page.set('watchtogether')
|
||||
joinLobby(match[1])
|
||||
function checkInvite (invite) {
|
||||
if (invite) {
|
||||
const match = invite.match(inviteRx)
|
||||
if (match) {
|
||||
page.set('watchtogether')
|
||||
joinLobby(match[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const inviteRx = /([A-z0-9]{16})/i
|
||||
window.IPC.on('w2glink', checkInvite)
|
||||
const inviteRx = /([A-z0-9]{16})/i
|
||||
window.IPC.on('w2glink', checkInvite)
|
||||
|
||||
function cleanup () {
|
||||
state.set(false)
|
||||
peers.set({})
|
||||
p2pcf.destroy()
|
||||
p2pcf = null
|
||||
}
|
||||
|
||||
function invite () {
|
||||
if (p2pcf) {
|
||||
navigator.clipboard.writeText(`<miru://w2g/${p2pcf.roomId}>`)
|
||||
addToast({
|
||||
title: 'Copied to clipboard',
|
||||
text: 'Copied invite URL to clipboard',
|
||||
type: 'primary',
|
||||
duration: '5000'
|
||||
})
|
||||
function cleanup () {
|
||||
state.set(false)
|
||||
peers.set({})
|
||||
p2pcf.destroy()
|
||||
p2pcf = null
|
||||
}
|
||||
|
||||
function invite () {
|
||||
if (p2pcf) {
|
||||
navigator.clipboard.writeText(`https://miru.watch/w2g/${p2pcf.roomId}`)
|
||||
addToast({
|
||||
title: 'Copied to clipboard',
|
||||
text: 'Copied invite URL to clipboard',
|
||||
type: 'primary',
|
||||
duration: '5000'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import Lobby from './Lobby.svelte'
|
||||
import Lobby from './Lobby.svelte'
|
||||
|
||||
let joinText
|
||||
let joinText
|
||||
|
||||
$: checkInvite(joinText)
|
||||
$: checkInvite(joinText)
|
||||
</script>
|
||||
|
||||
<div class='d-flex h-full align-items-center flex-column content'>
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
const P2PT = require('p2pt')
|
||||
|
||||
class P2PWorker extends P2PT {
|
||||
constructor (...args) {
|
||||
super(...args)
|
||||
|
||||
onmessage = this.handleMessage.bind(this)
|
||||
this.start()
|
||||
}
|
||||
|
||||
dispatch (type, data) {
|
||||
postMessage({ type, data })
|
||||
}
|
||||
|
||||
handleMessage ({ data }) {
|
||||
switch (data.type) {
|
||||
case 'current': {
|
||||
break
|
||||
}
|
||||
case 'torrent': {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let client = null
|
||||
|
||||
onmessage = ({ data }) => {
|
||||
if (!client && data.type === 'settings') client = new P2PWorker(data.data)
|
||||
if (data.type === 'destroy') client?.predestroy()
|
||||
}
|
||||
Loading…
Reference in a new issue