mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-18 08:43:37 +00:00
Change optionally add disk free space in response to three Web API endpoints.
Change increase API version number to 15. Add actually use mount points to get disk free space. Add optional "freespace" parameter to endpoints: sg.getrootdirs, sg.addrootdir, sg.deleterootdir Change update help of affected endpoints. Fix explicitly save rootdirs after adding or deleting via Web API.
This commit is contained in:
parent
40badef803
commit
e239b81a18
4 changed files with 93 additions and 45 deletions
|
@ -9,6 +9,12 @@
|
|||
* Change codebase cleanups
|
||||
* Change improve perf by using generators with `any`
|
||||
* Change deprecate processEpisode used by nzbToMedia to advise how to configure API instead
|
||||
* Change optionally add disk free space in response to three Web API endpoints
|
||||
* Change increase API version number to 15
|
||||
* Add actually use mount points to get disk free space
|
||||
* Add optional "freespace" parameter to endpoints: sg.getrootdirs, sg.addrootdir, sg.deleterootdir
|
||||
* Change update help of affected endpoints
|
||||
* Fix explicitly save rootdirs after adding or deleting via Web API
|
||||
|
||||
|
||||
[develop changelog]
|
||||
|
|
|
@ -70,11 +70,11 @@ addList("Command", "Help", "?cmd=help", "sg.functions-list", "","", "default");
|
|||
addOption("sg.functions-list", "$k", "&subject=$k", "", "", "#echo ('sb', 'sg')['sg' in $k]#")
|
||||
#end for
|
||||
addList("Command", "SickBeard.AddRootDir", "?cmd=sb.addrootdir", "sb.addrootdir");
|
||||
addList("Command", "SickGear.AddRootDir", "?cmd=sg.addrootdir", "sb.addrootdir");
|
||||
addList("Command", "SickGear.AddRootDir", "?cmd=sg.addrootdir", "sg.addrootdir");
|
||||
addOption("Command", "SickBeard.CheckScheduler", "?cmd=sb.checkscheduler");
|
||||
addOption("Command", "SickGear.CheckScheduler", "?cmd=sg.checkscheduler");
|
||||
addList("Command", "SickBeard.DeleteRootDir", "?cmd=sb.deleterootdir", "sb.deleterootdir");
|
||||
addList("Command", "SickGear.DeleteRootDir", "?cmd=sg.deleterootdir", "sb.deleterootdir");
|
||||
addList("Command", "SickGear.DeleteRootDir", "?cmd=sg.deleterootdir", "sg.deleterootdir");
|
||||
addOption("Command", "SickBeard.ForceSearch", "?cmd=sb.forcesearch");
|
||||
addList("Command", "SickGear.ForceSearch", "?cmd=sg.forcesearch", "sg.forcesearch");
|
||||
addOption("Command", "SickGear.SearchQueue", "?cmd=sg.searchqueue");
|
||||
|
@ -88,7 +88,7 @@ addList("Command", "SickGear.GetIndexers", "?cmd=sg.getindexers", "listindexers"
|
|||
addList("Command", "SickGear.GetIndexerIcon", "?cmd=sg.getindexericon", "getindexericon");
|
||||
addList("Command", "SickGear.GetNetworkIcon", "?cmd=sg.getnetworkicon", "getnetworkicon");
|
||||
addOption("Command", "SickBeard.GetRootDirs", "?cmd=sb.getrootdirs");
|
||||
addOption("Command", "SickGear.GetRootDirs", "?cmd=sg.getrootdirs");
|
||||
addList("Command", "SickGear.GetRootDirs", "?cmd=sg.getrootdirs", "sg.addfreespace");
|
||||
addList("Command", "SickBeard.PauseBacklog", "?cmd=sb.pausebacklog", "sb.pausebacklog");
|
||||
addList("Command", "SickGear.PauseBacklog", "?cmd=sg.pausebacklog", "sb.pausebacklog");
|
||||
addOption("Command", "SickBeard.Ping", "?cmd=sb.ping");
|
||||
|
@ -621,10 +621,26 @@ addOption("sb.addrootdir-opt", "Optional Param", "", 1);
|
|||
addOption("sb.addrootdir-opt", "Default", "&default=1");
|
||||
addOption("sb.addrootdir-opt", "Not Default", "&default=0");
|
||||
|
||||
addOption("sb.deleterootdir", "C:\\Temp", "&location=C:\\Temp", "", 1);
|
||||
addList("sg.addrootdir", "C:\\Temp", "&location=C:\\Temp", "sg.addrootdir-opt");
|
||||
addList("sg.addrootdir", "/usr/bin", "&location=/usr/bin/", "sg.addrootdir-opt");
|
||||
addList("sg.addrootdir", "S:\\Invalid_Location", "&location=S:\\Invalid_Location", "sg.addrootdir-opt");
|
||||
|
||||
addList("sg.addrootdir-opt", "Optional Param", "", "sg.addfreespace");
|
||||
addList("sg.addrootdir-opt", "Default", "&default=1", "sg.addfreespace");
|
||||
addList("sg.addrootdir-opt", "Not Default", "&default=0", "sg.addfreespace");
|
||||
|
||||
addOption("sb.deleterootdir", "C:\\Temp", "&location=C:\\Temp", 1);
|
||||
addOption("sb.deleterootdir", "/usr/bin", "&location=/usr/bin/");
|
||||
addOption("sb.deleterootdir", "S:\\Invalid_Location", "&location=S:\\Invalid_Location");
|
||||
|
||||
addList("sg.deleterootdir", "C:\\Temp", "&location=C:\\Temp", "sg.addfreespace");
|
||||
addList("sg.deleterootdir", "/usr/bin", "&location=/usr/bin/", "sg.addfreespace");
|
||||
addList("sg.deleterootdir", "S:\\Invalid_Location", "&location=S:\\Invalid_Location", "sg.addfreespace");
|
||||
|
||||
addOption("sg.addfreespace", "Optional Param", "", 1)
|
||||
addOption("sg.addfreespace", "incl Freespace", "&freespace=1")
|
||||
addOption("sg.addfreespace", "excl Freespace", "&freespace=0")
|
||||
|
||||
#for $cur_show_obj in $sortedShowList:
|
||||
addList("show.pause", "$cur_show_obj.name", "&indexerid=$cur_show_obj.prodid", "show.pause-opt");
|
||||
#end for
|
||||
|
|
|
@ -34,7 +34,7 @@ import sickgear
|
|||
from . import db, logger, notifiers
|
||||
from .common import cpu_presets, mediaExtensions, Overview, Quality, statusStrings, subtitleExtensions, \
|
||||
ARCHIVED, DOWNLOADED, FAILED, IGNORED, SKIPPED, SNATCHED_ANY, SUBTITLED, UNAIRED, UNKNOWN, WANTED
|
||||
from .sgdatetime import SGDatetime
|
||||
from .sgdatetime import SGDatetime
|
||||
from lib.tvinfo_base.exceptions import *
|
||||
from exceptions_helper import ex, MultipleShowObjectsException
|
||||
|
||||
|
@ -1031,7 +1031,7 @@ def clear_cache(force=False):
|
|||
"""
|
||||
# clean out cache directory, remove everything > 12 hours old
|
||||
dirty = None
|
||||
del_time = SGDatetime.timestamp_near(td=datetime.timedelta(hours=12))
|
||||
del_time = SGDatetime.timestamp_near(td=datetime.timedelta(hours=12))
|
||||
direntry_args = dict(follow_symlinks=False)
|
||||
for direntry in scantree(sickgear.CACHE_DIR, ['images|rss|zoneinfo'], follow_symlinks=True):
|
||||
if direntry.is_file(**direntry_args) and (force or del_time > direntry.stat(**direntry_args).st_mtime):
|
||||
|
@ -1342,7 +1342,7 @@ def delete_not_changed_in(paths, days=30, minutes=0):
|
|||
:param minutes: Purge files not modified in this number of minutes (default: 0 minutes)
|
||||
:return: tuple; number of files that qualify for deletion, number of qualifying files that failed to be deleted
|
||||
"""
|
||||
del_time = SGDatetime.timestamp_near(td=datetime.timedelta(days=days, minutes=minutes))
|
||||
del_time = SGDatetime.timestamp_near(td=datetime.timedelta(days=days, minutes=minutes))
|
||||
errors = 0
|
||||
qualified = 0
|
||||
for cur_path in (paths, [paths])[not isinstance(paths, list)]:
|
||||
|
@ -1367,7 +1367,7 @@ def set_file_timestamp(filename, min_age=3, new_time=None):
|
|||
:param new_time:
|
||||
:type new_time: None or int
|
||||
"""
|
||||
min_time = SGDatetime.timestamp_near(td=datetime.timedelta(days=min_age))
|
||||
min_time = SGDatetime.timestamp_near(td=datetime.timedelta(days=min_age))
|
||||
try:
|
||||
if os.path.isfile(filename) and os.path.getmtime(filename) < min_time:
|
||||
os.utime(filename, new_time)
|
||||
|
@ -1412,6 +1412,19 @@ def is_link(filepath):
|
|||
return os.path.islink(filepath)
|
||||
|
||||
|
||||
def find_mount_point(path):
|
||||
# type: (AnyStr) -> AnyStr
|
||||
"""
|
||||
returns the mount point for the given path
|
||||
:param path: path to find the mount point
|
||||
:return: mount point for path
|
||||
"""
|
||||
path = os.path.realpath(os.path.abspath(path))
|
||||
while not os.path.ismount(path):
|
||||
path = os.path.dirname(path)
|
||||
return path
|
||||
|
||||
|
||||
def df():
|
||||
"""
|
||||
Return disk free space at known parent locations
|
||||
|
@ -1424,17 +1437,9 @@ def df():
|
|||
if sickgear.ROOT_DIRS and sickgear.DISPLAY_FREESPACE:
|
||||
targets = []
|
||||
for path in sickgear.ROOT_DIRS.split('|')[1:]:
|
||||
location_parts = os.path.splitdrive(path)
|
||||
target = location_parts[0]
|
||||
if 'win32' == sys.platform:
|
||||
if not re.match('(?i)[a-z]:(?:\\\\)?$', target):
|
||||
# simple drive letter not found, fallback to full path
|
||||
target = path
|
||||
min_output = False
|
||||
elif sys.platform.startswith(('linux', 'darwin', 'sunos5')) or 'bsd' in sys.platform:
|
||||
target = path
|
||||
min_output = False
|
||||
target = find_mount_point(path)
|
||||
if target and target not in targets:
|
||||
min_output = False
|
||||
targets += [target]
|
||||
free = freespace(path)
|
||||
if None is not free:
|
||||
|
|
|
@ -43,7 +43,7 @@ from . import classes, db, helpers, history, image_cache, logger, network_timezo
|
|||
from .common import ARCHIVED, DOWNLOADED, FAILED, IGNORED, SKIPPED, SNATCHED, SNATCHED_ANY, SNATCHED_BEST, \
|
||||
SNATCHED_PROPER, UNAIRED, UNKNOWN, WANTED, Quality, qualityPresetStrings, statusStrings
|
||||
from .name_parser.parser import NameParser
|
||||
from .helpers import starify
|
||||
from .helpers import df, find_mount_point, starify
|
||||
from .indexers import indexer_api, indexer_config
|
||||
from .indexers.indexer_config import *
|
||||
from lib.tvinfo_base.exceptions import *
|
||||
|
@ -150,7 +150,7 @@ else:
|
|||
|
||||
class Api(webserve.BaseHandler):
|
||||
""" api class that returns json results """
|
||||
version = 14 # use an int since float-point is unpredictable
|
||||
version = 15 # use an int since float-point is unpredictable
|
||||
|
||||
def check_xsrf_cookie(self):
|
||||
pass
|
||||
|
@ -801,38 +801,45 @@ def _getQualityMap():
|
|||
return quality_map_inversed
|
||||
|
||||
|
||||
def _getRootDirs():
|
||||
if "" == sickgear.ROOT_DIRS:
|
||||
return {}
|
||||
def _get_root_dirs(get_freespace=False):
|
||||
# type: (bool) -> List[Dict]
|
||||
"""
|
||||
|
||||
:param get_freespace: include disk free space info in response
|
||||
"""
|
||||
dir_list = []
|
||||
if not sickgear.ROOT_DIRS:
|
||||
return dir_list
|
||||
|
||||
rootDir = {}
|
||||
root_dirs = sickgear.ROOT_DIRS.split('|')
|
||||
default_index = int(sickgear.ROOT_DIRS.split('|')[0])
|
||||
|
||||
rootDir["default_index"] = int(sickgear.ROOT_DIRS.split('|')[0])
|
||||
# remove default_index value from list (this fixes the offset)
|
||||
root_dirs.pop(0)
|
||||
default_index = int(root_dirs.pop(0))
|
||||
|
||||
if len(root_dirs) < default_index:
|
||||
return {}
|
||||
return dir_list
|
||||
|
||||
# clean up the list - replace %xx escapes by their single-character equivalent
|
||||
root_dirs = [unquote_plus(x) for x in root_dirs]
|
||||
|
||||
default_dir = root_dirs[default_index]
|
||||
|
||||
dir_list = []
|
||||
for root_dir in root_dirs:
|
||||
valid = 1
|
||||
if root_dirs and get_freespace:
|
||||
diskfree, _ = df()
|
||||
|
||||
for cur_root_dir in root_dirs:
|
||||
try:
|
||||
os.listdir(root_dir)
|
||||
os.listdir(cur_root_dir)
|
||||
valid = 1
|
||||
except (BaseException, Exception):
|
||||
valid = 0
|
||||
default = 0
|
||||
if root_dir is default_dir:
|
||||
default = 1
|
||||
|
||||
dir_list.append({'valid': valid, 'location': root_dir, 'default': default})
|
||||
new_entry = {'valid': valid, 'location': cur_root_dir, 'default': int(cur_root_dir is default_dir)}
|
||||
|
||||
if get_freespace:
|
||||
# noinspection PyUnboundLocalVariable
|
||||
new_entry.update({'free_space': next((space for disk, space in diskfree or []
|
||||
if disk == find_mount_point(cur_root_dir)), '')})
|
||||
|
||||
dir_list.append(new_entry)
|
||||
|
||||
return dir_list
|
||||
|
||||
|
@ -1975,7 +1982,8 @@ class CMD_SickGearAddRootDir(ApiCall):
|
|||
_help = {"desc": "add a user configured parent directory",
|
||||
"requiredParameters": {"location": {"desc": "the full path to root (parent) directory"}
|
||||
},
|
||||
"optionalParameters": {"default": {"desc": "make the location passed the default root (parent) directory"}
|
||||
"optionalParameters": {"default": {"desc": "make the location passed the default root (parent) directory"},
|
||||
"freespace": {"desc": "include free space of paths in response"}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1984,6 +1992,7 @@ class CMD_SickGearAddRootDir(ApiCall):
|
|||
self.location, args = self.check_params(args, kwargs, "location", None, True, "string", [])
|
||||
# optional
|
||||
self.default, args = self.check_params(args, kwargs, "default", 0, False, "bool", [])
|
||||
self.freespace, args = self.check_params(args, kwargs, "freespace", 0, False, "bool", [])
|
||||
# super, missing, help
|
||||
ApiCall.__init__(self, handler, args, kwargs)
|
||||
|
||||
|
@ -2026,7 +2035,9 @@ class CMD_SickGearAddRootDir(ApiCall):
|
|||
root_dirs_new = '|'.join([text_type(x) for x in root_dirs_new])
|
||||
|
||||
sickgear.ROOT_DIRS = root_dirs_new
|
||||
return _responds(RESULT_SUCCESS, _getRootDirs(), msg="Root directories updated")
|
||||
sickgear.save_config()
|
||||
return _responds(RESULT_SUCCESS, _get_root_dirs(not self.sickbeard_call and self.freespace),
|
||||
msg="Root directories updated")
|
||||
|
||||
|
||||
class CMD_SickBeardAddRootDir(CMD_SickGearAddRootDir):
|
||||
|
@ -2084,20 +2095,24 @@ class CMD_SickBeardCheckScheduler(CMD_SickGearCheckScheduler):
|
|||
|
||||
class CMD_SickGearDeleteRootDir(ApiCall):
|
||||
_help = {"desc": "delete a user configured parent directory",
|
||||
"requiredParameters": {"location": {"desc": "the full path to root (parent) directory"}}
|
||||
"requiredParameters": {"location": {"desc": "the full path to root (parent) directory"}},
|
||||
"optionalParameters": {"freespace": {"desc": "include free space of paths in response"}
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, handler, args, kwargs):
|
||||
# required
|
||||
self.location, args = self.check_params(args, kwargs, "location", None, True, "string", [])
|
||||
# optional
|
||||
self.freespace, args = self.check_params(args, kwargs, "freespace", 0, False, "bool", [])
|
||||
# super, missing, help
|
||||
ApiCall.__init__(self, handler, args, kwargs)
|
||||
|
||||
def run(self):
|
||||
""" delete a user configured parent directory """
|
||||
if sickgear.ROOT_DIRS == "":
|
||||
return _responds(RESULT_FAILURE, _getRootDirs(), msg="No root directories detected")
|
||||
return _responds(RESULT_FAILURE, _get_root_dirs(not self.sickbeard_call and self.freespace),
|
||||
msg="No root directories detected")
|
||||
|
||||
newIndex = 0
|
||||
root_dirs_new = []
|
||||
|
@ -2124,8 +2139,10 @@ class CMD_SickGearDeleteRootDir(ApiCall):
|
|||
root_dirs_new = "|".join([text_type(x) for x in root_dirs_new])
|
||||
|
||||
sickgear.ROOT_DIRS = root_dirs_new
|
||||
sickgear.save_config()
|
||||
# what if the root dir was not found?
|
||||
return _responds(RESULT_SUCCESS, _getRootDirs(), msg="Root directory deleted")
|
||||
return _responds(RESULT_SUCCESS, _get_root_dirs(not self.sickbeard_call and self.freespace),
|
||||
msg="Root directory deleted")
|
||||
|
||||
|
||||
class CMD_SickBeardDeleteRootDir(CMD_SickGearDeleteRootDir):
|
||||
|
@ -2374,18 +2391,22 @@ class CMD_SickGearGetqualityStrings(ApiCall):
|
|||
|
||||
|
||||
class CMD_SickGearGetRootDirs(ApiCall):
|
||||
_help = {"desc": "get list of user configured parent directories"}
|
||||
_help = {"desc": "get list of user configured parent directories",
|
||||
"optionalParameters": {"freespace": {"desc": "include free space of paths in response"}
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, handler, args, kwargs):
|
||||
# required
|
||||
# optional
|
||||
self.freespace, args = self.check_params(args, kwargs, "freespace", 0, False, "bool", [])
|
||||
# super, missing, help
|
||||
ApiCall.__init__(self, handler, args, kwargs)
|
||||
|
||||
def run(self):
|
||||
""" get list of user configured parent directories """
|
||||
|
||||
return _responds(RESULT_SUCCESS, _getRootDirs())
|
||||
return _responds(RESULT_SUCCESS, _get_root_dirs(not self.sickbeard_call and self.freespace))
|
||||
|
||||
|
||||
class CMD_SickBeardGetRootDirs(CMD_SickGearGetRootDirs):
|
||||
|
|
Loading…
Reference in a new issue