moved socket event pause/resume to api/system/

This commit is contained in:
arabcoders 2025-08-29 19:00:26 +03:00
parent 20cfc00640
commit e2b4a8caa3
9 changed files with 85 additions and 79 deletions

View file

@ -1,11 +1,13 @@
import asyncio import asyncio
import logging import logging
import time
from aiohttp import web from aiohttp import web
from aiohttp.web import Request, Response from aiohttp.web import Request, Response
from aiohttp.web_runner import GracefulExit from aiohttp.web_runner import GracefulExit
from app.library.config import Config from app.library.config import Config
from app.library.DownloadQueue import DownloadQueue
from app.library.encoder import Encoder from app.library.encoder import Encoder
from app.library.Events import EventBus, Events from app.library.Events import EventBus, Events
from app.library.router import route from app.library.router import route
@ -13,10 +15,80 @@ from app.library.router import route
LOG: logging.Logger = logging.getLogger(__name__) LOG: logging.Logger = logging.getLogger(__name__)
@route("POST", "api/system/pause", "system.pause")
async def downloads_pause(queue: DownloadQueue, encoder: Encoder, notify: EventBus) -> Response:
"""
Pause non-active downloads.
Args:
request (Request): The request object.
queue (DownloadQueue): The download queue instance.
encoder (Encoder): The encoder instance.
notify (EventBus): The event bus instance.
Returns:
Response: The response object.
"""
if queue.is_paused():
return web.json_response(
{"message": "Non-active downloads are already paused."},
status=web.HTTPNotAcceptable.status_code,
dumps=encoder.encode,
)
queue.pause()
msg = "Non-active downloads have been paused."
await notify.emit(
Events.PAUSED,
data={"paused": True, "at": time.time()},
title="Downloads Paused",
message=msg,
)
return web.json_response(data={"message": msg}, status=web.HTTPOk.status_code, dumps=encoder.encode)
@route("POST", "api/system/resume", "system.resume")
async def downloads_resume(queue: DownloadQueue, encoder: Encoder, notify: EventBus) -> Response:
"""
Resume non-active downloads.
Args:
request (Request): The request object.
queue (DownloadQueue): The download queue instance.
encoder (Encoder): The encoder instance.
notify (EventBus): The event bus instance.
Returns:
Response: The response object.
"""
if not queue.is_paused():
return web.json_response(
{"message": "Non-active downloads are not paused."},
status=web.HTTPNotAcceptable.status_code,
dumps=encoder.encode,
)
queue.resume()
msg = "Resumed all downloads."
await notify.emit(
Events.RESUMED,
data={"paused": False, "at": time.time()},
title="Downloads Resumed",
message=msg,
)
return web.json_response(data={"message": msg}, status=web.HTTPOk.status_code, dumps=encoder.encode)
@route("POST", "api/system/shutdown", "system.shutdown") @route("POST", "api/system/shutdown", "system.shutdown")
async def shutdown_system(request: Request, config: Config, encoder: Encoder, notify: EventBus) -> Response: async def shutdown_system(request: Request, config: Config, encoder: Encoder, notify: EventBus) -> Response:
""" """
Get the presets. Initiate application shutdown.
Args: Args:
request (Request): The request object. request (Request): The request object.

View file

@ -1,38 +1,13 @@
import logging import logging
import time
from app.library.DownloadQueue import DownloadQueue from app.library.DownloadQueue import DownloadQueue
from app.library.Events import EventBus, Events from app.library.Events import EventBus, Events
from app.library.ItemDTO import Item from app.library.ItemDTO import Item
from app.library.router import RouteType, route from app.library.router import RouteType, route
from app.library.Utils import archive_add, archive_read, get_archive_id
from app.library.YTDLPOpts import YTDLPOpts
LOG: logging.Logger = logging.getLogger(__name__) LOG: logging.Logger = logging.getLogger(__name__)
@route(RouteType.SOCKET, "pause", "pause_downloads")
async def pause(notify: EventBus, queue: DownloadQueue):
queue.pause()
await notify.emit(
Events.PAUSED,
data={"paused": True, "at": time.time()},
title="Downloads Paused",
message="Non-active downloads have been paused.",
)
@route(RouteType.SOCKET, "resume", "resume_downloads")
async def resume(notify: EventBus, queue: DownloadQueue):
queue.resume()
await notify.emit(
Events.RESUMED,
data={"paused": False, "at": time.time()},
title="Downloads Resumed",
message="Resumed all downloads.",
)
@route(RouteType.SOCKET, "add_url", "add_url") @route(RouteType.SOCKET, "add_url", "add_url")
async def add_url(queue: DownloadQueue, notify: EventBus, sid: str, data: dict): async def add_url(queue: DownloadQueue, notify: EventBus, sid: str, data: dict):
data = data if isinstance(data, dict) else {} data = data if isinstance(data, dict) else {}
@ -74,40 +49,6 @@ async def item_delete(queue: DownloadQueue, notify: EventBus, sid: str, data: di
await queue.clear([id], remove_file=bool(data.get("remove_file", False))) await queue.clear([id], remove_file=bool(data.get("remove_file", False)))
@route(RouteType.SOCKET, "archive_item", "archive_item")
async def archive_item(data: dict):
if not isinstance(data, dict) or "url" not in data:
return
params: YTDLPOpts = YTDLPOpts.get_instance()
if "preset" in data and isinstance(data["preset"], str):
params.preset(name=data["preset"])
if "cli" in data and isinstance(data["cli"], str) and len(data["cli"]) > 1:
params.add_cli(data["cli"], from_user=True)
params = params.get_all()
if not (file := params.get("download_archive")):
return
idDict = get_archive_id(url=data["url"])
if not idDict.get("archive_id"):
LOG.warning(f"URL '{data['url']}' does not have an archive ID.")
return
archive_id: str = idDict.get("archive_id")
if len(archive_read(file, [archive_id])) > 0:
LOG.info(f"URL '{data['url']}' already archived.")
return
archive_add(file, [archive_id])
LOG.info(f"Archiving url '{data['url']}' with id '{archive_id}'.")
@route(RouteType.SOCKET, "item_start", "item_start") @route(RouteType.SOCKET, "item_start", "item_start")
async def item_start(queue: DownloadQueue, notify: EventBus, sid: str, data: list | str) -> None: async def item_start(queue: DownloadQueue, notify: EventBus, sid: str, data: list | str) -> None:
if not data: if not data:

View file

@ -81,7 +81,7 @@ onMounted(async (): Promise<void> => {
try { try {
isLoading.value = true isLoading.value = true
const response = await request(url, { credentials: 'include' }) const response = await request(url)
const body = await response.text() const body = await response.text()
try { try {

View file

@ -611,9 +611,6 @@ const deleteSelectedItems = () => {
continue continue
} }
const item = stateStore.get('history', item_id, {} as StoreItem) as StoreItem const item = stateStore.get('history', item_id, {} as StoreItem) as StoreItem
if ('finished' === item.status) {
socket.emit('archive_item', item)
}
socket.emit('item_delete', { socket.emit('item_delete', {
id: item._id, id: item._id,
remove_file: config.app.remove_files, remove_file: config.app.remove_files,
@ -737,10 +734,7 @@ const addArchiveDialog = (item: StoreItem) => {
const archiveItem = async (item: StoreItem, opts = {}) => { const archiveItem = async (item: StoreItem, opts = {}) => {
try { try {
const req = await request(`/api/history/${item._id}/archive`, { const req = await request(`/api/history/${item._id}/archive`, { method: 'POST' })
credentials: 'include',
method: 'POST',
})
const data = await req.json() const data = await req.json()
dialog_confirm.value.visible = false dialog_confirm.value.visible = false
if (!req.ok) { if (!req.ok) {
@ -832,8 +826,7 @@ const downloadSelected = async () => {
try { try {
const response = await request('/api/file/download', { const response = await request('/api/file/download', {
method: 'POST', method: 'POST',
credentials: 'include', body: JSON.stringify(files_list)
body: JSON.stringify(files_list),
}) })
const json = await response.json() const json = await response.json()
if (!response.ok) { if (!response.ok) {
@ -871,7 +864,7 @@ const removeFromArchiveDialog = (item: StoreItem) => {
const removeFromArchive = async (item: StoreItem, opts?: { re_add?: boolean, remove_history?: boolean }) => { const removeFromArchive = async (item: StoreItem, opts?: { re_add?: boolean, remove_history?: boolean }) => {
console.log('Removing from archive:', item, opts) console.log('Removing from archive:', item, opts)
try { try {
const req = await request(`/api/history/${item._id}/archive`, { credentials: 'include', method: 'DELETE' }) const req = await request(`/api/history/${item._id}/archive`, { method: 'DELETE' })
const data = await req.json() const data = await req.json()
if (!req.ok) { if (!req.ok) {
toast.error(data.error) toast.error(data.error)

View file

@ -50,7 +50,7 @@ onMounted(async () => {
try { try {
isLoading.value = true isLoading.value = true
const imgRequest = await request(url, { credentials: 'include' }) const imgRequest = await request(url)
if (200 !== imgRequest.status) { if (200 !== imgRequest.status) {
return return
} }

View file

@ -351,7 +351,6 @@ const addDownload = async () => {
try { try {
addInProgress.value = true addInProgress.value = true
const response = await request('/api/history', { const response = await request('/api/history', {
credentials: 'include',
method: 'POST', method: 'POST',
body: JSON.stringify(request_data), body: JSON.stringify(request_data),
}) })

View file

@ -510,7 +510,7 @@ const convert_url = async (url: string): Promise<string> => {
try { try {
convertInProgress.value = true convertInProgress.value = true
const resp = await request('/api/yt-dlp/url/info?' + params.toString(), { credentials: 'include' }) const resp = await request('/api/yt-dlp/url/info?' + params.toString())
const body = await resp.json() const body = await resp.json()
const channel_id = ag(body, 'channel_id', null) const channel_id = ag(body, 'channel_id', null)
console.log('convert_url', { url, channel_id, body }) console.log('convert_url', { url, channel_id, body })

View file

@ -170,7 +170,7 @@ const filters = reactive({
const reload = async (): Promise<void> => { const reload = async (): Promise<void> => {
try { try {
isLoading.value = true isLoading.value = true
const resp = await request('/api/yt-dlp/options', { credentials: 'include' }) const resp = await request('/api/yt-dlp/options')
if (!resp.ok) { if (!resp.ok) {
return return
} }

View file

@ -29,8 +29,7 @@
<span class="icon"><i class="fas fa-pause" /></span> <span class="icon"><i class="fas fa-pause" /></span>
<span v-if="!isMobile">Pause</span> <span v-if="!isMobile">Pause</span>
</button> </button>
<button class="button is-danger" @click="socket.emit('resume', {})" v-else <button class="button is-danger" @click="resumeDownload" v-else v-tooltip.bottom="'Resume downloading.'">
v-tooltip.bottom="'Resume downloading.'">
<span class="icon"><i class="fas fa-play" /></span> <span class="icon"><i class="fas fa-play" /></span>
<span v-if="!isMobile">Resume</span> <span v-if="!isMobile">Resume</span>
</button> </button>
@ -174,6 +173,8 @@ watch(() => stateStore.queue, () => {
}, { deep: true }) }, { deep: true })
const resumeDownload = async () => await request('/api/system/resume', { method: 'POST' })
const pauseDownload = () => { const pauseDownload = () => {
dialog_confirm.value.visible = true dialog_confirm.value.visible = true
dialog_confirm.value.html_message = ` dialog_confirm.value.html_message = `
@ -188,8 +189,8 @@ const pauseDownload = () => {
<li>If you are in middle of adding a playlist/channel, it will break and stop adding more items.</li> <li>If you are in middle of adding a playlist/channel, it will break and stop adding more items.</li>
</ul> </ul>
</span>` </span>`
dialog_confirm.value.confirm = () => { dialog_confirm.value.confirm = async () => {
socket.emit('pause', {}) await request('/api/system/pause', { method: 'POST' })
dialog_confirm.value.visible = false dialog_confirm.value.visible = false
} }
} }