This commit is contained in:
yumoqing 2025-08-23 12:10:48 +08:00
parent 7ba58a135c
commit 5630669c17
12 changed files with 271 additions and 0 deletions

View File

@ -0,0 +1,57 @@
# DownloadMgr
a web ui for aria2
## Dependent
* [apppublic](https://git.opencomputing.cn/yumoqing/apppublic)
* [sqlor](https://git.opencomputing.cn/yumoqing/sqlor)
* [ahserver](https://git.opencomputing.cn/yumoqing/ahserver)
* [appbase](https://git.opencomputing.cn/yumoqing/appbase)
* [rbac](https://git.opencomputing.cn/yumoqing/rbac)
* [uapi](https://git.opencomputing.cn/yumoqing/uapi)
* [bricks](https://git.opencomputing.cn/yumoqing/bricks)
also depentent on
* [xls2ddl](https://git.opencomputing.cn/yumoqing/xls2ddl)
use it to translates database definintion excel file to database ddl sql file
and translate table information to CRUD UI for bricks.
## Install
```
pip install git+https://git.opencomputing.cn/yumoqing/downloadmgr
```
## Usage
in your web app
```
from downloadmgr.init import load_downloadmgr
# call the load_downloadmgr() before the web server start listening
```
## examples:
```
from ahserver.webapp import webapp
from ahserver.serverenv import ServerEnv
from appbase.init import load_appbase
from rbac.init import load_rbac
from downloadmgr.init import load_downloadmgr
def get_module_dbanme(modulename):
return 'mydb' # assume all modules use same database 'mydb'
def init():
env = ServerEnv()
env.get_module_dbname = get_module_dbname
load_appbase()
load_rbac()
load_downloadmgr()
if __name__ == '__main__':
webapp(init)
```
## database table
downloadmgr use a table named "download", it record the user download infomation

Binary file not shown.

0
downloadmgr/__init__.py Normal file
View File

106
downloadmgr/download.py Normal file
View File

@ -0,0 +1,106 @@
import time
import json
from appPublic.dictObject import DictObject
from sqlor.dbpools import DBPools
from ahserver.serverenv import ServerEnv, get_serverenv
class DownloadMgr:
def __init__(self,request):
self.request = request
self.env = request['run_ns']
self.uapi = self.env.UAPI(request, **self.env)
self.uappid = 'downloader'
async def save_finished_task(self, taskid):
db = DBPools()
userid = await self.env.get_user()
dbname = self.env.get_module_dbname('downloadmgr')
async with db.sqlorContext(dbname) as sor:
ns = {
"id": taskid,
"finish_time": time.time(),
}
await sor.U('download', ns)
async def save_task(self, taskid):
db = DBPools()
userid = await self.env.get_user()
dbname = self.env.get_module_dbname('downloadmgr')
async with db.sqlorContext(dbname) as sor:
ns = {
"id": taskid,
"userid": userid,
"start_time": time.time()
}
await sor.C('download', ns)
async def get_user_tasks(self):
db = DBPools()
userid = await self.env.get_user()
dbname = self.env.get_module_dbname('downloadmgr')
async with db.sqlorContext(dbname) as sor:
sql = """select * from download
where userid=${userid}$
and finish_time is NULL"""
ns = {
'userid': userid
}
recs = await sor.sqlExe(sql, ns)
return recs
return []
async def uapicall(self, apiname, ns):
userid = await self.env.get_user()
x = self.uapi.call(self.uappname,
apiname,
userid,
ns)
d = json.loads(x.decode('utf-8')
return DictObject(**d)
async download(self, url):
try:
d = await self.uapicall('addUrl', {'url':url})
await self.save_task(d.result)
return d.result
except Exception as e:
self.env.exception(f'{url=},{e}\n{format_exc()}')
raise e
async def delete_file(self, filename):
pass
async remove_task(self, taskid):
await self.uapicall('remove-task', {'taskid':taskid})
return True
async def file_downloaded(self, filename):
pass
async def check_download_finished(self, status):
s = status
if s.totalLength == s.completedLength:
await self.save_finished_task(s.gid)
await self.file_downloaded(s.info.name)
await self.remove_task(s.gid)
await self.delete_file(s.info.name)
async def get_task_status(self, tid):
d = await self.uapicall('get_task_status', {'taskid':tid})
await self.check_downlaod_finished(d.result)
rzt = d.result
rzt.filename = rzt.info.name
return rzt
async get_tasks_status(self):
recs = await self.get_user_tasks(userid)
urls = [r.id for r in recs]
try:
d = await self.uapicall('get_task_status', {'taskid':tid})
await self.check_downlaod_finished(d.result)
return d.result
except Exception as e:
self.env.exception(f'{e=}\n{format_exc()}')
raise e

6
downloadmgr/init.py Normal file
View File

@ -0,0 +1,6 @@
from downloadmgr.download import DownloadMgr
from ahserver.serverenv import ServerEnv
def load_downloadmgr():
env = ServerEnv()
env.DownloadMgr = DownloadMgr

BIN
models/download.xlsx Normal file

Binary file not shown.

4
pyproject.toml Normal file
View File

@ -0,0 +1,4 @@
[build-system]
requires = ["setuptools>=61", "wheel"]
build-backend = "setuptools.build_meta"

16
setup.cfg Normal file
View File

@ -0,0 +1,16 @@
[metadata]
name=downloadmgr
version = 0.0.1
description = a web ui for aria2
author = "yu moqing"
author_email = "yumoqing@gmail.com"
readme = "README.md"
license = "MIT"
[options]
packages = find:
requires_python = ">=3.8"
install_requires =
apppublic
sqlor
ahserver

View File

@ -0,0 +1,26 @@
{
"widgettype":"Form",
"options":{
"width":"100%",
"height":"100%",
"fields":[
{
"name":"url",
"label":"下载地址",
"uitype":"text",
"required":true
}
]
},
"binds":[
{
"wid":"self",
"event":"submit",
"actiontype":"urlwidget",
"target":"self",
"options":{
"url":"{{entire_url('./download_url.dspy')}}"
}
}
]
}

View File

@ -0,0 +1,8 @@
#
dmgr = DownloadMgr(request)
try:
x = await dmgr.download(params_kw.url)
return UiMessage(title='download', message=f'download submited')
except Exception as e:
exception(f'{params_kw.url} download failed,{e=}\n{format_exc()}')
return UiError(title='download error', message=f'{params_kw.url} download failed,{e=}')

View File

@ -0,0 +1,22 @@
{
"widgettype":"DynamicColumn",
"options":{
"width":"100%",
"height":"100%"
},
"subwidgets":[
{% set dmgr = DownloadMgr(request) %}
{for task in dmgr.get_user_tasks() %}
{
"widgettype":"urlwidget",
"options":{
"params":{
"taskid":"{{task.id}}"
},
"url":"{{entire_url('task_info.ui')}}"
}
}
{% if not loop.last %},{% endif %}
{% endfor %}
]
}

26
wwwroot/task_info.ui Normal file
View File

@ -0,0 +1,26 @@
{% set dmgr=DownloadMgr(request) %}
{% set status=dmgr.get_task_status(params_kw.taskid) %}
{
"widgettype":"VBox",
"options":{
"cwidth":16,
"cheight":14,
"css":"card"
},
"subwidgets":[
{
"widgettype":"Title3",
"options:{
"text":"{{status.filename}}",
"wrap":true,
"halign":"left"
}
},
{
"widgettype":"Text",
"options":{
"text":"{{status.completedLength}}/{{status.totalLength}}"
}
}
]
}