mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-15 01:15:05 +00:00
Merge branch 'feature/AddWebapiDiskspace' into dev
This commit is contained in:
commit
4dc131bc7d
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