changes in db
This commit is contained in:
@@ -135,9 +135,8 @@ def _int_setting(data: dict[str, Any], current: dict[str, Any], key: str, defaul
|
||||
return max(minimum, int(default))
|
||||
|
||||
|
||||
def _default_settings(user_id: int, profile_id: int) -> dict[str, Any]:
|
||||
def _default_settings(profile_id: int) -> dict[str, Any]:
|
||||
return {
|
||||
'user_id': user_id,
|
||||
'profile_id': profile_id,
|
||||
'enabled': 0,
|
||||
'max_active_downloads': 5,
|
||||
@@ -162,18 +161,16 @@ def _default_settings(user_id: int, profile_id: int) -> dict[str, Any]:
|
||||
|
||||
|
||||
def get_settings(profile_id: int, user_id: int | None = None) -> dict[str, Any]:
|
||||
user_id = user_id or default_user_id()
|
||||
with connect() as conn:
|
||||
row = conn.execute(
|
||||
'SELECT * FROM smart_queue_settings WHERE user_id=? AND profile_id=?',
|
||||
(user_id, profile_id),
|
||||
'SELECT * FROM smart_queue_settings WHERE profile_id=?',
|
||||
(profile_id,),
|
||||
).fetchone()
|
||||
settings = dict(row or _default_settings(user_id, profile_id))
|
||||
settings = dict(row or _default_settings(profile_id))
|
||||
return settings
|
||||
|
||||
|
||||
def save_settings(profile_id: int, data: dict[str, Any], user_id: int | None = None) -> dict[str, Any]:
|
||||
user_id = user_id or default_user_id()
|
||||
current = get_settings(profile_id, user_id)
|
||||
settings = {
|
||||
'enabled': 1 if data.get('enabled', current.get('enabled')) else 0,
|
||||
@@ -214,9 +211,9 @@ def save_settings(profile_id: int, data: dict[str, Any], user_id: int | None = N
|
||||
now = utcnow()
|
||||
with connect() as conn:
|
||||
conn.execute(
|
||||
'''INSERT INTO smart_queue_settings(user_id,profile_id,enabled,max_active_downloads,stalled_seconds,min_speed_bytes,min_seeds,min_peers,ignore_seed_peer,ignore_speed,manage_stopped,cooldown_minutes,stop_batch_size,start_grace_seconds,protect_active_below_cap,auto_stop_idle,refill_enabled,refill_interval_minutes,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
ON CONFLICT(user_id, profile_id) DO UPDATE SET
|
||||
'''INSERT INTO smart_queue_settings(profile_id,enabled,max_active_downloads,stalled_seconds,min_speed_bytes,min_seeds,min_peers,ignore_seed_peer,ignore_speed,manage_stopped,cooldown_minutes,stop_batch_size,start_grace_seconds,protect_active_below_cap,auto_stop_idle,refill_enabled,refill_interval_minutes,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
ON CONFLICT(profile_id) DO UPDATE SET
|
||||
enabled=excluded.enabled,
|
||||
max_active_downloads=excluded.max_active_downloads,
|
||||
stalled_seconds=excluded.stalled_seconds,
|
||||
@@ -234,80 +231,74 @@ def save_settings(profile_id: int, data: dict[str, Any], user_id: int | None = N
|
||||
refill_enabled=excluded.refill_enabled,
|
||||
refill_interval_minutes=excluded.refill_interval_minutes,
|
||||
updated_at=excluded.updated_at''',
|
||||
(user_id, profile_id, settings['enabled'], settings['max_active_downloads'], settings['stalled_seconds'], settings['min_speed_bytes'], settings['min_seeds'], settings['min_peers'], settings['ignore_seed_peer'], settings['ignore_speed'], settings['manage_stopped'], settings['cooldown_minutes'], settings['stop_batch_size'], settings['start_grace_seconds'], settings['protect_active_below_cap'], settings['auto_stop_idle'], settings['refill_enabled'], settings['refill_interval_minutes'], now),
|
||||
(profile_id, settings['enabled'], settings['max_active_downloads'], settings['stalled_seconds'], settings['min_speed_bytes'], settings['min_seeds'], settings['min_peers'], settings['ignore_seed_peer'], settings['ignore_speed'], settings['manage_stopped'], settings['cooldown_minutes'], settings['stop_batch_size'], settings['start_grace_seconds'], settings['protect_active_below_cap'], settings['auto_stop_idle'], settings['refill_enabled'], settings['refill_interval_minutes'], now),
|
||||
)
|
||||
return get_settings(profile_id, user_id)
|
||||
|
||||
|
||||
def list_exclusions(profile_id: int, user_id: int | None = None) -> list[dict[str, Any]]:
|
||||
user_id = user_id or default_user_id()
|
||||
with connect() as conn:
|
||||
return conn.execute(
|
||||
'SELECT * FROM smart_queue_exclusions WHERE user_id=? AND profile_id=? ORDER BY created_at DESC',
|
||||
(user_id, profile_id),
|
||||
'SELECT * FROM smart_queue_exclusions WHERE profile_id=? ORDER BY created_at DESC',
|
||||
(profile_id,),
|
||||
).fetchall()
|
||||
|
||||
|
||||
def set_exclusion(profile_id: int, torrent_hash: str, excluded: bool, reason: str = '', user_id: int | None = None) -> None:
|
||||
user_id = user_id or default_user_id()
|
||||
now = utcnow()
|
||||
with connect() as conn:
|
||||
if excluded:
|
||||
conn.execute(
|
||||
'INSERT OR REPLACE INTO smart_queue_exclusions(user_id,profile_id,torrent_hash,reason,created_at) VALUES(?,?,?,?,?)',
|
||||
(user_id, profile_id, torrent_hash, reason, now),
|
||||
'INSERT OR REPLACE INTO smart_queue_exclusions(profile_id,torrent_hash,reason,created_at) VALUES(?,?,?,?)',
|
||||
(profile_id, torrent_hash, reason, now),
|
||||
)
|
||||
else:
|
||||
conn.execute(
|
||||
'DELETE FROM smart_queue_exclusions WHERE user_id=? AND profile_id=? AND torrent_hash=?',
|
||||
(user_id, profile_id, torrent_hash),
|
||||
'DELETE FROM smart_queue_exclusions WHERE profile_id=? AND torrent_hash=?',
|
||||
(profile_id, torrent_hash),
|
||||
)
|
||||
|
||||
|
||||
|
||||
def add_history(profile_id: int, event: str, paused: list[str] | None = None, resumed: list[str] | None = None, checked: int = 0, details: dict[str, Any] | None = None, user_id: int | None = None) -> None:
|
||||
user_id = user_id or default_user_id()
|
||||
paused = paused or []
|
||||
resumed = resumed or []
|
||||
details = details or {}
|
||||
with connect() as conn:
|
||||
conn.execute(
|
||||
'INSERT INTO smart_queue_history(user_id,profile_id,event,paused_count,resumed_count,checked_count,details_json,created_at) VALUES(?,?,?,?,?,?,?,?)',
|
||||
(user_id, profile_id, event, len(paused), len(resumed), int(checked or 0), json.dumps({**details, 'paused': paused, 'resumed': resumed}), utcnow()),
|
||||
'INSERT INTO smart_queue_history(profile_id,event,paused_count,resumed_count,checked_count,details_json,created_at) VALUES(?,?,?,?,?,?,?)',
|
||||
(profile_id, event, len(paused), len(resumed), int(checked or 0), json.dumps({**details, 'paused': paused, 'resumed': resumed}), utcnow()),
|
||||
)
|
||||
|
||||
def list_history(profile_id: int, user_id: int | None = None, limit: int = 30) -> list[dict[str, Any]]:
|
||||
user_id = user_id or default_user_id()
|
||||
with connect() as conn:
|
||||
return conn.execute(
|
||||
'SELECT * FROM smart_queue_history WHERE user_id=? AND profile_id=? ORDER BY created_at DESC LIMIT ?',
|
||||
(user_id, profile_id, max(1, min(int(limit or 30), 100))),
|
||||
'SELECT * FROM smart_queue_history WHERE profile_id=? ORDER BY created_at DESC LIMIT ?',
|
||||
(profile_id, max(1, min(int(limit or 30), 100))),
|
||||
).fetchall()
|
||||
|
||||
|
||||
def clear_history(profile_id: int, user_id: int | None = None) -> int:
|
||||
"""Delete Smart Queue history rows for the current profile and return the removed count."""
|
||||
# Note: Manual cleanup only removes audit history; settings, exclusions and pending queue state stay untouched.
|
||||
user_id = user_id or default_user_id()
|
||||
with connect() as conn:
|
||||
row = conn.execute(
|
||||
'SELECT COUNT(*) AS count FROM smart_queue_history WHERE user_id=? AND profile_id=?',
|
||||
(user_id, profile_id),
|
||||
'SELECT COUNT(*) AS count FROM smart_queue_history WHERE profile_id=?',
|
||||
(profile_id,),
|
||||
).fetchone()
|
||||
count = int((row or {}).get('count') or 0)
|
||||
conn.execute(
|
||||
'DELETE FROM smart_queue_history WHERE user_id=? AND profile_id=?',
|
||||
(user_id, profile_id),
|
||||
'DELETE FROM smart_queue_history WHERE profile_id=?',
|
||||
(profile_id,),
|
||||
)
|
||||
return count
|
||||
|
||||
|
||||
def count_history(profile_id: int, user_id: int | None = None) -> int:
|
||||
user_id = user_id or default_user_id()
|
||||
with connect() as conn:
|
||||
row = conn.execute(
|
||||
'SELECT COUNT(*) AS count FROM smart_queue_history WHERE user_id=? AND profile_id=?',
|
||||
(user_id, profile_id),
|
||||
'SELECT COUNT(*) AS count FROM smart_queue_history WHERE profile_id=?',
|
||||
(profile_id,),
|
||||
).fetchone()
|
||||
return int((row or {}).get('count') or 0)
|
||||
|
||||
@@ -315,11 +306,10 @@ def count_history(profile_id: int, user_id: int | None = None) -> int:
|
||||
def _latest_history_event(profile_id: int, user_id: int | None = None) -> str:
|
||||
"""Return the newest Smart Queue history event for duplicate suppression."""
|
||||
# Note: Disabled Smart Queue should leave one waiting marker, not a poller-generated log stream.
|
||||
user_id = user_id or default_user_id()
|
||||
with connect() as conn:
|
||||
row = conn.execute(
|
||||
'SELECT event FROM smart_queue_history WHERE user_id=? AND profile_id=? ORDER BY created_at DESC LIMIT 1',
|
||||
(user_id, profile_id),
|
||||
'SELECT event FROM smart_queue_history WHERE profile_id=? ORDER BY created_at DESC LIMIT 1',
|
||||
(profile_id,),
|
||||
).fetchone()
|
||||
return str((row or {}).get('event') or '')
|
||||
|
||||
@@ -338,8 +328,8 @@ def _record_disabled_waiting_once(profile_id: int, user_id: int, details: dict[s
|
||||
return True
|
||||
|
||||
|
||||
def _excluded_hashes(profile_id: int, user_id: int) -> set[str]:
|
||||
return {r['torrent_hash'] for r in list_exclusions(profile_id, user_id)}
|
||||
def _excluded_hashes(profile_id: int, user_id: int | None = None) -> set[str]:
|
||||
return {r['torrent_hash'] for r in list_exclusions(profile_id)}
|
||||
|
||||
|
||||
|
||||
@@ -891,7 +881,7 @@ def _refill_mode(settings: dict[str, Any]) -> str:
|
||||
def _mark_refill_run(profile_id: int, user_id: int) -> None:
|
||||
# Note: Custom refill interval is measured from the last lightweight refill attempt.
|
||||
with connect() as conn:
|
||||
conn.execute('UPDATE smart_queue_settings SET last_refill_at=?, updated_at=? WHERE user_id=? AND profile_id=?', (utcnow(), utcnow(), user_id, profile_id))
|
||||
conn.execute('UPDATE smart_queue_settings SET last_refill_at=?, updated_at=? WHERE profile_id=?', (utcnow(), utcnow(), profile_id))
|
||||
|
||||
|
||||
def _refill_underfilled_queue(profile: dict, settings: dict[str, Any], profile_id: int, user_id: int) -> dict[str, Any]:
|
||||
@@ -1090,13 +1080,13 @@ def _refill_underfilled_queue(profile: dict, settings: dict[str, Any], profile_i
|
||||
def mark_run(profile_id: int, user_id: int | None = None) -> None:
|
||||
user_id = user_id or default_user_id()
|
||||
with connect() as conn:
|
||||
conn.execute('UPDATE smart_queue_settings SET last_run_at=?, updated_at=? WHERE user_id=? AND profile_id=?', (utcnow(), utcnow(), user_id, profile_id))
|
||||
conn.execute('UPDATE smart_queue_settings SET last_run_at=?, updated_at=? WHERE profile_id=?', (utcnow(), utcnow(), profile_id))
|
||||
|
||||
def _disable_when_idle(profile_id: int, user_id: int, torrents: list[dict[str, Any]], details: dict[str, Any]) -> dict[str, Any]:
|
||||
# Note: Auto-stop is intentionally profile-scoped and only flips the Smart Queue enabled flag; saved thresholds remain intact.
|
||||
now = utcnow()
|
||||
with connect() as conn:
|
||||
conn.execute('UPDATE smart_queue_settings SET enabled=0, last_run_at=?, updated_at=? WHERE user_id=? AND profile_id=?', (now, now, user_id, profile_id))
|
||||
conn.execute('UPDATE smart_queue_settings SET enabled=0, last_run_at=?, updated_at=? WHERE profile_id=?', (now, now, profile_id))
|
||||
add_history(profile_id, 'auto_stopped_idle', [], [], len(torrents), details, user_id)
|
||||
settings = get_settings(profile_id, user_id)
|
||||
return {'ok': True, 'enabled': False, 'auto_stopped_idle': True, 'paused': [], 'resumed': [], 'stopped': [], 'started': [], 'checked': len(torrents), 'settings': settings, 'message': 'Smart Queue stopped because there is no active or waiting work.'}
|
||||
|
||||
Reference in New Issue
Block a user