css content type + doctype html + repeat + branch
This commit is contained in:
parent
5d54f08c2b
commit
14aedca8b4
@ -223,7 +223,8 @@ class MusicAppFactory(AppFactory):
|
|||||||
@routes.get('/main.css')
|
@routes.get('/main.css')
|
||||||
async def maincss(_request: web.Request) -> web.Response:
|
async def maincss(_request: web.Request) -> web.Response:
|
||||||
return web.Response(
|
return web.Response(
|
||||||
text=await self.file('main.css')
|
text=await self.file('main.css'),
|
||||||
|
content_type='text/css'
|
||||||
)
|
)
|
||||||
|
|
||||||
@routes.post('/api/')
|
@routes.post('/api/')
|
||||||
|
@ -144,6 +144,53 @@ async def default(ctx: Context, args: list[str]) -> None:
|
|||||||
await ctx.reply(f'effects set to `{effects}`')
|
await ctx.reply(f'effects set to `{effects}`')
|
||||||
|
|
||||||
|
|
||||||
|
@at('commands', 'repeat')
|
||||||
|
async def repeat(ctx: Context, args: list[str]):
|
||||||
|
match args:
|
||||||
|
case []:
|
||||||
|
n = 1
|
||||||
|
case [n_] if n_.isdecimal():
|
||||||
|
n = int(n_)
|
||||||
|
case _:
|
||||||
|
raise Explicit('misformatted')
|
||||||
|
assert_admin(ctx.member)
|
||||||
|
queue = await queue_for(ctx, create=False, force_play=False)
|
||||||
|
if not queue.queue:
|
||||||
|
raise Explicit('empty queue')
|
||||||
|
if n > 99:
|
||||||
|
raise Explicit('too long')
|
||||||
|
audio = queue.queue[0]
|
||||||
|
for _ in range(n):
|
||||||
|
queue.queue.insert(1, audio.copy())
|
||||||
|
|
||||||
|
|
||||||
|
@at('commands', 'branch')
|
||||||
|
async def branch(ctx: Context, args: list[str]):
|
||||||
|
match args:
|
||||||
|
case ['-', effects]:
|
||||||
|
pass
|
||||||
|
case ['+', preset]:
|
||||||
|
effects = effects_for_preset(preset)
|
||||||
|
case ['none']:
|
||||||
|
effects = ''
|
||||||
|
case []:
|
||||||
|
effects = None
|
||||||
|
case _:
|
||||||
|
raise Explicit('misformatted')
|
||||||
|
assert_admin(ctx.member)
|
||||||
|
queue = await queue_for(ctx, create=False, force_play=False)
|
||||||
|
if not queue.queue:
|
||||||
|
raise Explicit('empty queue')
|
||||||
|
audio = queue.queue[0].branch()
|
||||||
|
if effects is not None:
|
||||||
|
seconds = audio.source_seconds()
|
||||||
|
audio.options = options_for_effects(effects or None)
|
||||||
|
audio.set_seconds(seconds)
|
||||||
|
else:
|
||||||
|
audio.set_source()
|
||||||
|
queue.queue.insert(1, audio)
|
||||||
|
|
||||||
|
|
||||||
@at('commands', '//')
|
@at('commands', '//')
|
||||||
@at('commands', 'queue')
|
@at('commands', 'queue')
|
||||||
async def queue_(ctx: Context, args: list[str]) -> None:
|
async def queue_(ctx: Context, args: list[str]) -> None:
|
||||||
|
@ -45,7 +45,7 @@ class QueueAudio(discord.AudioSource):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls, guild: discord.Guild):
|
async def create(cls, guild: discord.Guild):
|
||||||
return cls(guild, await QueueAudio.respawned(guild))
|
return cls(guild, await cls.respawned(guild))
|
||||||
|
|
||||||
async def save(self, delay: bool):
|
async def save(self, delay: bool):
|
||||||
hybernated = []
|
hybernated = []
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import functools
|
||||||
import random
|
import random
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from v6d2ctx.context import Benchmark
|
from v6d2ctx.context import Explicit
|
||||||
|
|
||||||
from v6d3music.core.ffmpegnormalaudio import FFmpegNormalAudio
|
from v6d3music.core.ffmpegnormalaudio import FFmpegNormalAudio
|
||||||
from v6d3music.core.real_url import real_url
|
from v6d3music.core.real_url import real_url
|
||||||
@ -12,6 +13,9 @@ from v6d3music.utils.sparq import sparq
|
|||||||
from v6d3music.utils.tor_prefix import tor_prefix
|
from v6d3music.utils.tor_prefix import tor_prefix
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ('YTAudio',)
|
||||||
|
|
||||||
|
|
||||||
class YTAudio(discord.AudioSource):
|
class YTAudio(discord.AudioSource):
|
||||||
source: FFmpegNormalAudio
|
source: FFmpegNormalAudio
|
||||||
|
|
||||||
@ -24,6 +28,9 @@ class YTAudio(discord.AudioSource):
|
|||||||
rby: discord.Member,
|
rby: discord.Member,
|
||||||
already_read: int,
|
already_read: int,
|
||||||
tor: bool,
|
tor: bool,
|
||||||
|
/,
|
||||||
|
*,
|
||||||
|
stop_at: int | None = None
|
||||||
):
|
):
|
||||||
self.url = url
|
self.url = url
|
||||||
self.origin = origin
|
self.origin = origin
|
||||||
@ -36,6 +43,7 @@ class YTAudio(discord.AudioSource):
|
|||||||
# self.set_source()
|
# self.set_source()
|
||||||
self._durations: dict[str, str] = {}
|
self._durations: dict[str, str] = {}
|
||||||
self.loop = asyncio.get_running_loop()
|
self.loop = asyncio.get_running_loop()
|
||||||
|
self.stop_at: int | None = stop_at
|
||||||
|
|
||||||
def set_source_if_necessary(self):
|
def set_source_if_necessary(self):
|
||||||
if not hasattr(self, 'source'):
|
if not hasattr(self, 'source'):
|
||||||
@ -117,6 +125,8 @@ class YTAudio(discord.AudioSource):
|
|||||||
def read(self) -> bytes:
|
def read(self) -> bytes:
|
||||||
if self.regenerating:
|
if self.regenerating:
|
||||||
return FILL
|
return FILL
|
||||||
|
if self.stop_at is not None and self.already_read >= self.stop_at - 1:
|
||||||
|
return b''
|
||||||
self.already_read += 1
|
self.already_read += 1
|
||||||
ret: bytes = self.source.read()
|
ret: bytes = self.source.read()
|
||||||
if not ret and not self.source.droppable():
|
if not ret and not self.source.droppable():
|
||||||
@ -156,6 +166,7 @@ class YTAudio(discord.AudioSource):
|
|||||||
'rby': self.rby.id,
|
'rby': self.rby.id,
|
||||||
'already_read': self.already_read,
|
'already_read': self.already_read,
|
||||||
'tor': self.tor,
|
'tor': self.tor,
|
||||||
|
'stop_at': self.stop_at,
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -167,7 +178,8 @@ class YTAudio(discord.AudioSource):
|
|||||||
respawn['options'],
|
respawn['options'],
|
||||||
guild.get_member(respawn['rby']) or await guild.fetch_member(respawn['rby']),
|
guild.get_member(respawn['rby']) or await guild.fetch_member(respawn['rby']),
|
||||||
respawn['already_read'],
|
respawn['already_read'],
|
||||||
respawn.get('tor', False)
|
respawn.get('tor', False),
|
||||||
|
stop_at=respawn.get('stop_at', None),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def regenerate(self):
|
async def regenerate(self):
|
||||||
@ -189,3 +201,29 @@ class YTAudio(discord.AudioSource):
|
|||||||
'description': self.description,
|
'description': self.description,
|
||||||
'canbeskipped': self.can_be_skipped_by(member),
|
'canbeskipped': self.can_be_skipped_by(member),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def copy(self) -> 'YTAudio':
|
||||||
|
return YTAudio(
|
||||||
|
self.url,
|
||||||
|
self.origin,
|
||||||
|
self.description,
|
||||||
|
self.options,
|
||||||
|
self.rby,
|
||||||
|
0,
|
||||||
|
self.tor,
|
||||||
|
)
|
||||||
|
|
||||||
|
def branch(self) -> 'YTAudio':
|
||||||
|
if self.stop_at is not None:
|
||||||
|
raise Explicit('already branched')
|
||||||
|
self.stop_at = stop_at = self.already_read + 50
|
||||||
|
audio = YTAudio(
|
||||||
|
self.url,
|
||||||
|
self.origin,
|
||||||
|
self.description,
|
||||||
|
self.options,
|
||||||
|
self.rby,
|
||||||
|
stop_at,
|
||||||
|
self.tor,
|
||||||
|
)
|
||||||
|
return audio
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
<link rel="stylesheet" href="/main.css" />
|
<link rel="stylesheet" href="/main.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
<script>
|
<script>
|
||||||
@ -6,3 +10,4 @@
|
|||||||
root.append(await pageHome());
|
root.append(await pageHome());
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
</body>
|
||||||
|
@ -1,5 +1,23 @@
|
|||||||
html, body {
|
html,
|
||||||
|
body,
|
||||||
|
input {
|
||||||
color: white;
|
color: white;
|
||||||
background: black;
|
background: black;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #555;
|
||||||
|
}
|
||||||
|
@ -147,38 +147,40 @@ const aQueue = async () => {
|
|||||||
const sleep = (s) => {
|
const sleep = (s) => {
|
||||||
return new Promise((resolve) => setTimeout(resolve, 1000 * s));
|
return new Promise((resolve) => setTimeout(resolve, 1000 * s));
|
||||||
};
|
};
|
||||||
const aUpdateAudioSchedule = async (timecode, audio, i, current_i) => {
|
const audioWidget = (audio) => {
|
||||||
while (i == current_i()) {
|
|
||||||
timecode.innerText = audio.ts();
|
|
||||||
await sleep(0.5);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const audioWidget = (audio, i, current_i) => {
|
|
||||||
const description = baseEl("span", audio.description);
|
const description = baseEl("span", audio.description);
|
||||||
const timecode = baseEl("span", audio.timecode);
|
const timecode = baseEl("span", audio.timecode);
|
||||||
const duration = baseEl("span", audio.duration);
|
const duration = baseEl("span", audio.duration);
|
||||||
aUpdateAudioSchedule(timecode, audio, i, current_i);
|
audio.tce = timecode;
|
||||||
return baseEl("div", "audio", " ", timecode, "/", duration, " ", description);
|
return baseEl("div", "audio", " ", timecode, "/", duration, " ", description);
|
||||||
};
|
};
|
||||||
const aUpdateQueueOnce = async (queue, el, i, current_i) => {
|
const aUpdateQueueOnce = async (queue, el) => {
|
||||||
console.log(queue);
|
|
||||||
console.log(JSON.stringify(queue));
|
|
||||||
el.innerHTML = "";
|
el.innerHTML = "";
|
||||||
if (queue !== null) {
|
if (queue !== null) {
|
||||||
for (const audio of queue.queuejson) {
|
for (const audio of queue.queuejson) {
|
||||||
el.append(audioWidget(audio, i, current_i));
|
el.append(audioWidget(audio));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const aUpdateQueueSetup = async (el) => {
|
const aUpdateQueueSetup = async (el) => {
|
||||||
let i = 0;
|
let queue = await aQueue();
|
||||||
await aUpdateQueueOnce(await aQueue(), el, i, () => i);
|
await aUpdateQueueOnce(queue, el);
|
||||||
(async () => {
|
(async () => {
|
||||||
while (true) {
|
while (true) {
|
||||||
const queue = await aQueue();
|
|
||||||
i += 1;
|
|
||||||
await aUpdateQueueOnce(queue, el, i, () => i);
|
|
||||||
await sleep(2);
|
await sleep(2);
|
||||||
|
const newQueue = await aQueue();
|
||||||
|
await aUpdateQueueOnce(newQueue, el);
|
||||||
|
queue = newQueue;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
(async () => {
|
||||||
|
while (true) {
|
||||||
|
await sleep(.25);
|
||||||
|
if (queue !== null) {
|
||||||
|
for (const audio of queue.queuejson) {
|
||||||
|
audio.tce.innerText = audio.ts();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user