mirror of
https://github.com/robweber/xbmcbackup.git
synced 2024-11-14 20:35:48 +01:00
moved scheduler to resources/lib and created non-complex entry point
This commit is contained in:
parent
b1f6d36d73
commit
04bac77690
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<addon id="script.xbmcbackup"
|
<addon id="script.xbmcbackup"
|
||||||
name="Backup" version="1.6.1~beta2" provider-name="robweber">
|
name="Backup" version="1.6.1~beta3" provider-name="robweber">
|
||||||
<requires>
|
<requires>
|
||||||
<import addon="xbmc.python" version="3.0.0"/>
|
<import addon="xbmc.python" version="3.0.0"/>
|
||||||
<import addon="script.module.dateutil" version="2.8.0" />
|
<import addon="script.module.dateutil" version="2.8.0" />
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<extension point="xbmc.python.script" library="default.py">
|
<extension point="xbmc.python.script" library="default.py">
|
||||||
<provides>executable</provides>
|
<provides>executable</provides>
|
||||||
</extension>
|
</extension>
|
||||||
<extension point="xbmc.service" library="scheduler.py" />
|
<extension point="xbmc.service" library="service.py" />
|
||||||
<extension point="xbmc.addon.metadata">
|
<extension point="xbmc.addon.metadata">
|
||||||
<summary lang="ar_SA">إنسخ إحتياطياً قاعده بيانات إكس بى إم سى وملفات اﻹعدادات فى حاله وقوع إنهيار مع إمكانيه اﻹسترجاع</summary>
|
<summary lang="ar_SA">إنسخ إحتياطياً قاعده بيانات إكس بى إم سى وملفات اﻹعدادات فى حاله وقوع إنهيار مع إمكانيه اﻹسترجاع</summary>
|
||||||
<summary lang="be_BY">Backup and restore your Kodi database and configuration files in the event of a crash or file corruption.</summary>
|
<summary lang="be_BY">Backup and restore your Kodi database and configuration files in the event of a crash or file corruption.</summary>
|
||||||
|
@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|||||||
- display every file transfered in progress bar, not just directory
|
- display every file transfered in progress bar, not just directory
|
||||||
- base progress bar percent on transfer size, not total files
|
- base progress bar percent on transfer size, not total files
|
||||||
- changed getSettings where needed to getSettingBool and getSettingInt
|
- changed getSettings where needed to getSettingBool and getSettingInt
|
||||||
|
- use service.py to start scheduler, moving scheduler to resources/lib/scheduler.py Kodi doesn't cache files in the root directory
|
||||||
|
|
||||||
## [Version 1.6.0](https://github.com/robweber/xbmcbackup/compare/krypton-1.5.2...robweber:matrix-1.6.0) - 2019-11-26
|
## [Version 1.6.0](https://github.com/robweber/xbmcbackup/compare/krypton-1.5.2...robweber:matrix-1.6.0) - 2019-11-26
|
||||||
|
|
||||||
|
@ -1,200 +1,197 @@
|
|||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcvfs
|
import xbmcvfs
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
import resources.lib.utils as utils
|
from . import utils as utils
|
||||||
from resources.lib.croniter import croniter
|
from resources.lib.croniter import croniter
|
||||||
from resources.lib.backup import XbmcBackup
|
from resources.lib.backup import XbmcBackup
|
||||||
|
|
||||||
UPGRADE_INT = 2 # to keep track of any upgrade notifications
|
UPGRADE_INT = 2 # to keep track of any upgrade notifications
|
||||||
|
|
||||||
|
|
||||||
class BackupScheduler:
|
class BackupScheduler:
|
||||||
monitor = None
|
monitor = None
|
||||||
enabled = "false"
|
enabled = "false"
|
||||||
next_run = 0
|
next_run = 0
|
||||||
next_run_path = None
|
next_run_path = None
|
||||||
restore_point = None
|
restore_point = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.monitor = UpdateMonitor(update_method=self.settingsChanged)
|
self.monitor = UpdateMonitor(update_method=self.settingsChanged)
|
||||||
self.enabled = utils.getSettingBool("enable_scheduler")
|
self.enabled = utils.getSettingBool("enable_scheduler")
|
||||||
self.next_run_path = xbmc.translatePath(utils.data_dir()) + 'next_run.txt'
|
self.next_run_path = xbmc.translatePath(utils.data_dir()) + 'next_run.txt'
|
||||||
|
|
||||||
if(self.enabled):
|
if(self.enabled):
|
||||||
|
|
||||||
# sleep for 2 minutes so Kodi can start and time can update correctly
|
# sleep for 2 minutes so Kodi can start and time can update correctly
|
||||||
xbmc.Monitor().waitForAbort(120)
|
xbmc.Monitor().waitForAbort(120)
|
||||||
|
|
||||||
nr = 0
|
nr = 0
|
||||||
if(xbmcvfs.exists(self.next_run_path)):
|
if(xbmcvfs.exists(self.next_run_path)):
|
||||||
|
|
||||||
fh = xbmcvfs.File(self.next_run_path)
|
fh = xbmcvfs.File(self.next_run_path)
|
||||||
try:
|
try:
|
||||||
# check if we saved a run time from the last run
|
# check if we saved a run time from the last run
|
||||||
nr = float(fh.read())
|
nr = float(fh.read())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
nr = 0
|
nr = 0
|
||||||
|
|
||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
# if we missed and the user wants to play catch-up
|
# if we missed and the user wants to play catch-up
|
||||||
if(0 < nr <= time.time() and utils.getSettingBool('schedule_miss')):
|
if(0 < nr <= time.time() and utils.getSettingBool('schedule_miss')):
|
||||||
utils.log("scheduled backup was missed, doing it now...")
|
utils.log("scheduled backup was missed, doing it now...")
|
||||||
progress_mode = utils.getSettingInt('progress_mode')
|
progress_mode = utils.getSettingInt('progress_mode')
|
||||||
|
|
||||||
if(progress_mode == 0):
|
if(progress_mode == 0):
|
||||||
progress_mode = 1 # Kodi just started, don't block it with a foreground progress bar
|
progress_mode = 1 # Kodi just started, don't block it with a foreground progress bar
|
||||||
|
|
||||||
self.doScheduledBackup(progress_mode)
|
self.doScheduledBackup(progress_mode)
|
||||||
|
|
||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
# scheduler was turned on, find next run time
|
# scheduler was turned on, find next run time
|
||||||
utils.log("scheduler enabled, finding next run time")
|
utils.log("scheduler enabled, finding next run time")
|
||||||
self.findNextRun(time.time())
|
self.findNextRun(time.time())
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
|
||||||
# display upgrade messages if they exist
|
# display upgrade messages if they exist
|
||||||
if(utils.getSettingInt('upgrade_notes') < UPGRADE_INT):
|
if(utils.getSettingInt('upgrade_notes') < UPGRADE_INT):
|
||||||
xbmcgui.Dialog().ok(utils.getString(30010), utils.getString(30132))
|
xbmcgui.Dialog().ok(utils.getString(30010), utils.getString(30132))
|
||||||
utils.setSetting('upgrade_notes', str(UPGRADE_INT))
|
utils.setSetting('upgrade_notes', str(UPGRADE_INT))
|
||||||
|
|
||||||
# check if a backup should be resumed
|
# check if a backup should be resumed
|
||||||
resumeRestore = self._resumeCheck()
|
resumeRestore = self._resumeCheck()
|
||||||
|
|
||||||
if(resumeRestore):
|
if(resumeRestore):
|
||||||
restore = XbmcBackup()
|
restore = XbmcBackup()
|
||||||
restore.selectRestore(self.restore_point)
|
restore.selectRestore(self.restore_point)
|
||||||
# skip the advanced settings check
|
# skip the advanced settings check
|
||||||
restore.skipAdvanced()
|
restore.skipAdvanced()
|
||||||
restore.restore()
|
restore.restore()
|
||||||
|
|
||||||
while(not self.monitor.abortRequested()):
|
while(not self.monitor.abortRequested()):
|
||||||
|
|
||||||
if(self.enabled):
|
if(self.enabled):
|
||||||
# scheduler is still on
|
# scheduler is still on
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
|
||||||
if(self.next_run <= now):
|
if(self.next_run <= now):
|
||||||
progress_mode = utils.getSettingInt('progress_mode')
|
progress_mode = utils.getSettingInt('progress_mode')
|
||||||
self.doScheduledBackup(progress_mode)
|
self.doScheduledBackup(progress_mode)
|
||||||
|
|
||||||
# check if we should shut the computer down
|
# check if we should shut the computer down
|
||||||
if(utils.getSettingBool("cron_shutdown")):
|
if(utils.getSettingBool("cron_shutdown")):
|
||||||
# wait 10 seconds to make sure all backup processes and files are completed
|
# wait 10 seconds to make sure all backup processes and files are completed
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
xbmc.executebuiltin('ShutDown()')
|
xbmc.executebuiltin('ShutDown()')
|
||||||
else:
|
else:
|
||||||
# find the next run time like normal
|
# find the next run time like normal
|
||||||
self.findNextRun(now)
|
self.findNextRun(now)
|
||||||
|
|
||||||
xbmc.sleep(500)
|
xbmc.sleep(500)
|
||||||
|
|
||||||
# delete monitor to free up memory
|
# delete monitor to free up memory
|
||||||
del self.monitor
|
del self.monitor
|
||||||
|
|
||||||
def doScheduledBackup(self, progress_mode):
|
def doScheduledBackup(self, progress_mode):
|
||||||
if(progress_mode != 2):
|
if(progress_mode != 2):
|
||||||
utils.showNotification(utils.getString(30053))
|
utils.showNotification(utils.getString(30053))
|
||||||
|
|
||||||
backup = XbmcBackup()
|
backup = XbmcBackup()
|
||||||
|
|
||||||
if(backup.remoteConfigured()):
|
if(backup.remoteConfigured()):
|
||||||
|
|
||||||
if(utils.getSettingInt('progress_mode') in [0, 1]):
|
if(utils.getSettingInt('progress_mode') in [0, 1]):
|
||||||
backup.backup(True)
|
backup.backup(True)
|
||||||
else:
|
else:
|
||||||
backup.backup(False)
|
backup.backup(False)
|
||||||
|
|
||||||
# check if this is a "one-off"
|
# check if this is a "one-off"
|
||||||
if(utils.getSettingInt("schedule_interval") == 0):
|
if(utils.getSettingInt("schedule_interval") == 0):
|
||||||
# disable the scheduler after this run
|
# disable the scheduler after this run
|
||||||
self.enabled = False
|
self.enabled = False
|
||||||
utils.setSetting('enable_scheduler', 'false')
|
utils.setSetting('enable_scheduler', 'false')
|
||||||
else:
|
else:
|
||||||
utils.showNotification(utils.getString(30045))
|
utils.showNotification(utils.getString(30045))
|
||||||
|
|
||||||
def findNextRun(self, now):
|
def findNextRun(self, now):
|
||||||
progress_mode = utils.getSettingInt('progress_mode')
|
progress_mode = utils.getSettingInt('progress_mode')
|
||||||
|
|
||||||
# find the cron expression and get the next run time
|
# find the cron expression and get the next run time
|
||||||
cron_exp = self.parseSchedule()
|
cron_exp = self.parseSchedule()
|
||||||
|
|
||||||
cron_ob = croniter(cron_exp, datetime.fromtimestamp(now))
|
cron_ob = croniter(cron_exp, datetime.fromtimestamp(now))
|
||||||
new_run_time = cron_ob.get_next(float)
|
new_run_time = cron_ob.get_next(float)
|
||||||
|
|
||||||
if(new_run_time != self.next_run):
|
if(new_run_time != self.next_run):
|
||||||
self.next_run = new_run_time
|
self.next_run = new_run_time
|
||||||
utils.log("scheduler will run again on " + utils.getRegionalTimestamp(datetime.fromtimestamp(self.next_run), ['dateshort', 'time']))
|
utils.log("scheduler will run again on " + utils.getRegionalTimestamp(datetime.fromtimestamp(self.next_run), ['dateshort', 'time']))
|
||||||
|
|
||||||
# write the next time to a file
|
# write the next time to a file
|
||||||
fh = xbmcvfs.File(self.next_run_path, 'w')
|
fh = xbmcvfs.File(self.next_run_path, 'w')
|
||||||
fh.write(str(self.next_run))
|
fh.write(str(self.next_run))
|
||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
# only show when not in silent mode
|
# only show when not in silent mode
|
||||||
if(progress_mode != 2):
|
if(progress_mode != 2):
|
||||||
utils.showNotification(utils.getString(30081) + " " + utils.getRegionalTimestamp(datetime.fromtimestamp(self.next_run), ['dateshort', 'time']))
|
utils.showNotification(utils.getString(30081) + " " + utils.getRegionalTimestamp(datetime.fromtimestamp(self.next_run), ['dateshort', 'time']))
|
||||||
|
|
||||||
def settingsChanged(self):
|
def settingsChanged(self):
|
||||||
current_enabled = utils.getSettingBool("enable_scheduler")
|
current_enabled = utils.getSettingBool("enable_scheduler")
|
||||||
|
|
||||||
if(current_enabled and not self.enabled):
|
if(current_enabled and not self.enabled):
|
||||||
# scheduler was just turned on
|
# scheduler was just turned on
|
||||||
self.enabled = current_enabled
|
self.enabled = current_enabled
|
||||||
self.setup()
|
self.setup()
|
||||||
elif (not current_enabled and self.enabled):
|
elif (not current_enabled and self.enabled):
|
||||||
# schedule was turn off
|
# schedule was turn off
|
||||||
self.enabled = current_enabled
|
self.enabled = current_enabled
|
||||||
|
|
||||||
if(self.enabled):
|
if(self.enabled):
|
||||||
# always recheck the next run time after an update
|
# always recheck the next run time after an update
|
||||||
self.findNextRun(time.time())
|
self.findNextRun(time.time())
|
||||||
|
|
||||||
def parseSchedule(self):
|
def parseSchedule(self):
|
||||||
schedule_type = utils.getSettingInt("schedule_interval")
|
schedule_type = utils.getSettingInt("schedule_interval")
|
||||||
cron_exp = utils.getSetting("cron_schedule")
|
cron_exp = utils.getSetting("cron_schedule")
|
||||||
|
|
||||||
hour_of_day = utils.getSetting("schedule_time")
|
hour_of_day = utils.getSetting("schedule_time")
|
||||||
hour_of_day = int(hour_of_day[0:2])
|
hour_of_day = int(hour_of_day[0:2])
|
||||||
if(schedule_type == 0 or schedule_type == 1):
|
if(schedule_type == 0 or schedule_type == 1):
|
||||||
# every day
|
# every day
|
||||||
cron_exp = "0 " + str(hour_of_day) + " * * *"
|
cron_exp = "0 " + str(hour_of_day) + " * * *"
|
||||||
elif(schedule_type == 2):
|
elif(schedule_type == 2):
|
||||||
# once a week
|
# once a week
|
||||||
day_of_week = utils.getSetting("day_of_week")
|
day_of_week = utils.getSetting("day_of_week")
|
||||||
cron_exp = "0 " + str(hour_of_day) + " * * " + day_of_week
|
cron_exp = "0 " + str(hour_of_day) + " * * " + day_of_week
|
||||||
elif(schedule_type == 3):
|
elif(schedule_type == 3):
|
||||||
# first day of month
|
# first day of month
|
||||||
cron_exp = "0 " + str(hour_of_day) + " 1 * *"
|
cron_exp = "0 " + str(hour_of_day) + " 1 * *"
|
||||||
|
|
||||||
return cron_exp
|
return cron_exp
|
||||||
|
|
||||||
def _resumeCheck(self):
|
def _resumeCheck(self):
|
||||||
shouldContinue = False
|
shouldContinue = False
|
||||||
if(xbmcvfs.exists(xbmc.translatePath(utils.data_dir() + "resume.txt"))):
|
if(xbmcvfs.exists(xbmc.translatePath(utils.data_dir() + "resume.txt"))):
|
||||||
rFile = xbmcvfs.File(xbmc.translatePath(utils.data_dir() + "resume.txt"), 'r')
|
rFile = xbmcvfs.File(xbmc.translatePath(utils.data_dir() + "resume.txt"), 'r')
|
||||||
self.restore_point = rFile.read()
|
self.restore_point = rFile.read()
|
||||||
rFile.close()
|
rFile.close()
|
||||||
xbmcvfs.delete(xbmc.translatePath(utils.data_dir() + "resume.txt"))
|
xbmcvfs.delete(xbmc.translatePath(utils.data_dir() + "resume.txt"))
|
||||||
shouldContinue = xbmcgui.Dialog().yesno(utils.getString(30042), utils.getString(30043), utils.getString(30044))
|
shouldContinue = xbmcgui.Dialog().yesno(utils.getString(30042), utils.getString(30043), utils.getString(30044))
|
||||||
|
|
||||||
return shouldContinue
|
return shouldContinue
|
||||||
|
|
||||||
|
|
||||||
class UpdateMonitor(xbmc.Monitor):
|
class UpdateMonitor(xbmc.Monitor):
|
||||||
update_method = None
|
update_method = None
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
xbmc.Monitor.__init__(self)
|
xbmc.Monitor.__init__(self)
|
||||||
self.update_method = kwargs['update_method']
|
self.update_method = kwargs['update_method']
|
||||||
|
|
||||||
def onSettingsChanged(self):
|
def onSettingsChanged(self):
|
||||||
self.update_method()
|
self.update_method()
|
||||||
|
|
||||||
|
|
||||||
BackupScheduler().start()
|
|
4
service.py
Normal file
4
service.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from resources.lib.scheduler import BackupScheduler
|
||||||
|
|
||||||
|
# start the backup scheduler
|
||||||
|
BackupScheduler().start()
|
Loading…
Reference in New Issue
Block a user