@samitouri / QOSami-HFS / commits / 12d60a37

show active downloads/uploads in command "status"

Massimo Melina committed Apr 16, 2026 at 14:23 UTC 12d60a37af6ba31621982773a20a19926f35d038
2 files changed +21 -12
src/api.monitor.ts
+17 -11
@@ -72,20 +72,10 @@ export default {
72
73 function fromCtx(ctx?: Koa.Context) {
74 if (!ctx) return
75 - const s = ctx.state // short alias
75 return {
76 user: getCurrentUsername(ctx),
77 agent: shortenAgent(ctx.get('user-agent')),
79 - archive: s.archive,
80 - ...s.browsing ? { op: 'browsing', path: safeDecodeURIComponent(s.browsing) }
81 - : s.uploadPath ? { op: 'upload', path: safeDecodeURIComponent(s.uploadPath) }
82 - : {
83 - op: !s.considerAsGui && (ctx.state.archive || ctx.state.vfsNode) ? 'download' : undefined,
84 - path: safeDecodeURIComponent(ctx.originalUrl),
85 - },
86 - opProgress: _.isNumber(s.opProgress) ? _.round(s.opProgress, 3) : undefined,
87 - opTotal: s.opTotal,
88 - opOffset: s.opOffset,
78 + ...inferOperation(ctx)
79 }
80 }
81 },
@@ -117,6 +107,22 @@ function ignore(conn: Connection) {
107 return false //conn.socket && isLocalHost(conn)
108 }
109
110 +export function inferOperation(ctx: Koa.Context) {
111 + const s = ctx.state // short alias
112 + return {
113 + archive: s.archive,
114 + ...s.browsing ? { op: 'browsing', path: safeDecodeURIComponent(s.browsing) }
115 + : s.uploadPath ? { op: 'upload', path: safeDecodeURIComponent(s.uploadPath) }
116 + : {
117 + op: !s.considerAsGui && (ctx.state.archive || ctx.state.vfsNode) ? 'download' : undefined,
118 + path: safeDecodeURIComponent(ctx.originalUrl),
119 + },
120 + opProgress: _.isNumber(s.opProgress) ? _.round(s.opProgress, 3) : undefined,
121 + opTotal: s.opTotal,
122 + opOffset: s.opOffset,
123 + }
124 +}
125 +
126 function getConnAddress(conn: Connection, overrideIp?: string) {
127 return {
128 ip: overrideIp ?? conn.ip,
src/commands.ts
+4 -1
@@ -13,7 +13,8 @@ import { getInactivePlugins, mapPlugins, startPlugin, stopPlugin } from './plugi
13 import { purgeFileAttr } from './fileAttr'
14 import { downloadPlugin } from './github'
15 import { Dict, formatBytes, formatSpeed, formatTimestamp, makeMatcher } from './cross'
16 -import apiMonitor from './api.monitor'
16 +import apiMonitor, { inferOperation } from './api.monitor'
17 +import { getConnections } from './connections'
18 import { argv } from './argv'
19 import { getServerStatus } from './listen'
20
@@ -197,6 +198,8 @@ const commands = {
198 console.log(_.map(ports, (x, k) =>
199 `${k.toUpperCase()} ${x.configuredPort < 0 ? "disabled" : x.listening ? `on port ${x.port}` : (x.error || "not working")}`
200 ).join(" – "))
201 + const operations = _.countBy(getConnections(), x => x.ctx && inferOperation(x.ctx).op)
202 + console.log(`Active downloads ↑ ${operations.download || 0} – uploads ↓ ${operations.upload || 0}`)
203 const conn = (await apiMonitor.get_connection_stats().next()).value
204 if (conn) {
205 const {sent_got: sg} = conn