Advertisement
kenmills69

Untitled

May 10th, 2021
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.26 KB | None | 0 0
  1.  
  2. import datetime
  3.  
  4. import json as jsoninterface
  5.  
  6. import sqlite3
  7.  
  8. import xml.etree.ElementTree as ET
  9.  
  10. import mysql.connector
  11.  
  12. import xbmc
  13.  
  14. import xbmcaddon
  15.  
  16. import xbmcgui
  17.  
  18. import xbmcvfs
  19.  
  20.  
  21. # database versions to scan for
  22. MIN_VIDEODB_VERSION = 35
  23. MAX_VIDEODB_VERSION = 119 # i.e. Leia, aka Kodi 18
  24.  
  25.  
  26. ACTION_PREVIOUS_MENU = 10
  27. ACTION_SELECT_ITEM = 7
  28. ACTION_NAV_BACK = 92
  29. ACTION_MOUSE_LEFT_CLICK = 100
  30. flag = 0
  31. WINDOW = xbmcgui.Window(10000)
  32.  
  33.  
  34. class MyClass(xbmcgui.WindowXMLDialog):
  35. def __init__( self, *args, **kwargs ): pass
  36.  
  37. def onInit( self ):
  38. self.container = self.getControl(6)
  39. self.container2 = self.getControl(8)
  40. self.container3 = self.getControl(10)
  41. self.listitems = []
  42. self.excludesitems = []
  43. self.addonsettings = []
  44.  
  45. # List paths from sources.xml
  46. if not specificpath and not replacepath:
  47. self.display_list = display_list
  48. for i in range(len(self.display_list)):
  49. self.listitems.append('[COLOR yellow]'+ self.display_list[i] + '[/COLOR]')
  50. if no_sources:
  51. self.listitems.append('[COLOR red][B]No sources are in use[/B][/COLOR]')
  52. self.listitems.append('[COLOR red][B]All streaming paths will be removed[/B][/COLOR]')
  53. if excluding:
  54. self.listitems.append('')
  55. self.listitems.append('[COLOR red][B]Paths from excludes.xml will be kept[/B][/COLOR]')
  56. if replacepath:
  57. self.listitems.append('[COLOR yellow]Replacing a path[/COLOR]')
  58. self.listitems.append('[COLOR yellow]in your database[/COLOR]')
  59. self.listitems.append('[COLOR yellow]Confirm details below[/COLOR]')
  60. if specificpath:
  61. self.listitems.append('[COLOR yellow]Removing a path[/COLOR]')
  62. self.listitems.append('[COLOR yellow]in your database[/COLOR]')
  63. self.listitems.append('[COLOR yellow]Confirm details below[/COLOR]')
  64. self.container.addItems(self.listitems)
  65. # List paths in excludes.xml (if it exists)
  66. self.excludes_list = excludes_list
  67.  
  68. if excluding:
  69. for i in range(len(self.excludes_list)):
  70. self.excludesitems.append('[COLOR yellow]' + self.excludes_list[i]+ '[/COLOR]')
  71. else:
  72. self.excludesitems.append("Not Present")
  73. self.container2.addItems(self.excludesitems)
  74.  
  75. # List the relevant addon settings
  76.  
  77. if is_pvr and (not specificpath and not replacepath):
  78. self.addonsettings.append('Keep PVR information')
  79. if bookmarks and (not specificpath and not replacepath):
  80. self.addonsettings.append('Keep bookmark information')
  81. if autoclean:
  82. self.addonsettings.append('Auto call Clean Library')
  83. if promptdelete:
  84. self.addonsettings.append('Show summary window (This window !!)')
  85. if autobackup == 'true' and not is_mysql:
  86. self.addonsettings.append('Auto backing up local database')
  87. if no_sources or specificpath or replacepath:
  88. self.addonsettings.append('[COLOR red]Not[/COLOR] using info from sources.xml')
  89. if specificpath:
  90. self.addonsettings.append('[COLOR red]Cleaning a specific path[/COLOR]')
  91. if replacepath:
  92. self.addonsettings.append('[COLOR red]Replacing a path[/COLOR]')
  93. if enable_logging:
  94. self.addonsettings.append('Writing a logfile to Kodi TEMP directory')
  95. if debugging:
  96. debug_string = 'Debugging [COLOR red]enabled[/COLOR]'
  97. else:
  98. debug_string = 'Debugging [COLOR green]disabled[/COLOR]'
  99. self.addonsettings.append(debug_string)
  100. self.addonsettings.append('') #blank line
  101. # Display the name of the database we are connected to
  102. self.addonsettings.append('Database is - [COLOR green][B]%s[/B][/COLOR]' % our_dbname)
  103. cursor.execute(our_select)
  104. data_list = cursor.fetchall()
  105. data_list_size = len(data_list)
  106. if replacepath:
  107. self.addonsettings.append('[COLOR red][B]There are %d paths to be changed[/B][/COLOR]' % data_list_size)
  108. else:
  109. self.addonsettings.append('[COLOR red][B]There are %d entries to be removed[/B][/COLOR]' % data_list_size)
  110.  
  111. self.container3.addItems(self.addonsettings)
  112. # Show warning about backup if using MySQL
  113. if is_mysql:
  114. self.getControl(20).setLabel('WARNING - MySQL database [COLOR red][B]not[/B][/COLOR] backed up automatically, please do this [B]manually[/B]')
  115. if specificpath:
  116. self.getControl(20).setLabel('WARNING - Removing specific path [COLOR yellow]%s[/COLOR] ' % specific_path_to_remove)
  117. if replacepath:
  118. self.getControl(20).setLabel('WARNING - Renaming specific path from [COLOR yellow]%s[/COLOR] ' % old_path)
  119. self.getControl(21).setLabel('TO [COLOR yellow]%s[/COLOR] ' % new_path)
  120.  
  121. def onAction(self, action):
  122. global flag
  123. dbglog('Got an action %s' % action.getId())
  124. if ( action == ACTION_PREVIOUS_MENU ) or ( action == ACTION_NAV_BACK ):
  125. self.close()
  126. if (action == ACTION_SELECT_ITEM) or ( action == ACTION_MOUSE_LEFT_CLICK ):
  127. try:
  128. btn = self.getFocus()
  129. btn_id = btn.getId()
  130.  
  131. except:
  132. btn_id = None
  133. if btn_id == 1:
  134. dbglog('you pressed abort')
  135. flag = 0
  136. self.close()
  137. elif btn_id == 2:
  138. dbglog('you pressed clean')
  139. flag = 1
  140. self.close()
  141.  
  142. # Set some variables ###
  143.  
  144. addon = xbmcaddon.Addon()
  145. addonname = addon.getAddonInfo('name')
  146. addonversion = addon.getAddonInfo('version')
  147. addonpath = addon.getAddonInfo('path')
  148.  
  149. advanced_file = xbmc.translatePath('special://profile/advancedsettings.xml')
  150. sources_file = xbmc.translatePath('special://profile/sources.xml')
  151. excludes_file = xbmc.translatePath('special://profile/addon_data/script.database.cleaner/excludes.xml')
  152. db_path = xbmc.translatePath('special://database')
  153. userdata_path = xbmc.translatePath('special://userdata')
  154. bp_logfile_path = xbmc.translatePath('special://temp/bp-debuglog.log')
  155. type_of_log =''
  156. is_pvr = addon.getSetting('pvr')
  157. autoclean = addon.getSetting('autoclean')
  158. bookmarks = addon.getSetting('bookmark')
  159. promptdelete = addon.getSetting('promptdelete')
  160. source_file_path = addon.getSetting('sourcefilepath')
  161. debugging = addon.getSetting('debugging')
  162. no_sources = addon.getSetting('usesources')
  163. autobackup = addon.getSetting('autobackup')
  164. specificpath = addon.getSetting('specificpath')
  165. backup_filename = addon.getSetting('backupname')
  166. forcedbname = addon.getSetting('overridedb')
  167. replacepath = addon.getSetting('replacepath')
  168. enable_logging = addon.getSetting('logtolog')
  169. if enable_logging == 'true':
  170. enable_logging = True
  171. type_of_log = addon.getSetting('typeoflog')
  172. else:
  173. enable_logging = False
  174. if replacepath == 'true':
  175. replacepath = True
  176. else:
  177. replacepath = False
  178. old_path = addon.getSetting('oldpath')
  179. new_path = addon.getSetting('newpath')
  180. if forcedbname == 'true':
  181. forcedbname = True
  182. else:
  183. forcedbname = False
  184. forcedname = addon.getSetting('forceddbname')
  185. if specificpath == 'true':
  186. specificpath = True
  187. else:
  188. specificpath = False
  189. specific_path_to_remove = addon.getSetting('spcpathstr')
  190. display_list = []
  191. excludes_list = []
  192. renamepath_list = []
  193. excluding = False
  194. found = False
  195. is_mysql = False
  196. remote_file = False
  197. cleaning = False
  198. path_name = ''
  199. the_path = ''
  200. success = 0
  201. our_source_list = ''
  202. if debugging == 'true':
  203. debugging = True
  204. else:
  205. debugging = False
  206.  
  207.  
  208. def log(txt):
  209.  
  210. if isinstance(txt, str):
  211. txt = txt
  212. message = u'%s: %s' % (addonname, txt)
  213. xbmc.log(msg=message.encode('utf-8'), level=xbmc.LOGDEBUG)
  214.  
  215. def dbglog(txt):
  216. if debugging:
  217. log(txt)
  218.  
  219. def exit_on_error():
  220. WINDOW.setProperty('database-cleaner-running', 'false')
  221. exit(1)
  222.  
  223. def cleaner_log_file(our_select, cleaning):
  224. cleaner_log = xbmc.translatePath('special://temp/database-cleaner.log')
  225. old_cleaner_log = xbmc.translatePath('special://temp/database-cleaner.old.log')
  226. old_log_contents =''
  227. do_progress = False
  228. if not enable_logging:
  229. return
  230. if type_of_log == '0':
  231. dbglog('Writing to new log file')
  232. if cleaning:
  233. if xbmcvfs.exists(cleaner_log):
  234. dbglog('database-cleaner.log exists - renaming to old.log')
  235. xbmcvfs.delete(old_cleaner_log)
  236. xbmcvfs.copy(cleaner_log, old_cleaner_log)
  237. xbmcvfs.delete(cleaner_log)
  238. else:
  239. xbmcvfs.delete(cleaner_log)
  240. else:
  241. dbglog('Appending to existing log file')
  242. if cleaning:
  243. if xbmcvfs.exists(cleaner_log):
  244. dbglog('database-cleaner.log exists - backing up to old.log')
  245. xbmcvfs.delete(old_cleaner_log)
  246. xbmcvfs.copy(cleaner_log, old_cleaner_log)
  247. old_log= xbmcvfs.File(cleaner_log)
  248. old_log_contents=old_log.read()
  249. old_log.close()
  250.  
  251. now = datetime.datetime.now()
  252. logfile=xbmcvfs.File(cleaner_log, 'w')
  253. if old_log_contents:
  254. logfile.write(old_log_contents)
  255. date_long_format = xbmc.getRegion('datelong')
  256. time_format = xbmc.getRegion('time')
  257. date_long_format = date_long_format + ' '+time_format
  258. logfile_header = 'Video Database Cleaner V' + addonversion+ ' - Running at ' +now.strftime(date_long_format) + '\n\n'
  259. logfile.write(logfile_header)
  260. cursor.execute(our_select)
  261. counting = 0
  262. my_data = cursor.fetchall()
  263. listsize = len(my_data)
  264. dbglog("Listsize is %d" % listsize)
  265. logfile.write('There are %d paths in the database that meet your criteria\n\n' % listsize)
  266. if listsize > 600:
  267. do_progress = True
  268. dialog = xbmcgui.DialogProgressBG()
  269. dbglog('Creating progress dialog for logfile')
  270. dialog.create('Getting required data. Please wait')
  271. dialog.update(1)
  272.  
  273. if not cleaning and not replacepath:
  274. logfile.write('The following file paths would be removed from your database')
  275. logfile.write('\n\n')
  276. elif cleaning and not replacepath:
  277. logfile.write('The following paths were removed from the database')
  278. logfile.write('\n\n')
  279. elif not cleaning and replacepath:
  280. logfile.write('The following paths will be changed in your database')
  281. logfile.write('\n\n')
  282. else:
  283. logfile.write('The following paths were changed in your database')
  284. logfile.write('\n\n')
  285. if not specificpath and not replacepath:
  286. for strPath in my_data:
  287. counting +=1
  288. mystring = u''.join(strPath) + '\n'
  289. outdata = mystring.encode('utf-8')
  290. if do_progress:
  291. dialog.update(percent = int((counting / float(listsize)) * 100))
  292. if cleaning:
  293. dbglog('Removing %s' % strPath)
  294. logfile.write(outdata)
  295. elif specificpath and not replacepath:
  296. dbglog('Removing specific path %s' % specific_path_to_remove)
  297. for strPath in my_data:
  298. counting +=1
  299. mystring = u''.join(strPath) + '\n'
  300. outdata = mystring.encode('utf-8')
  301. if do_progress:
  302. dialog.update(percent = int((counting / float(listsize)) * 100))
  303. if cleaning:
  304. dbglog('Removing unwanted path %s' % strPath)
  305. logfile.write(outdata)
  306. else:
  307. for strPath in my_data:
  308. counting +=1
  309. mystring = u''.join(strPath) + '\n'
  310. outdata = mystring.encode('utf-8')
  311. if do_progress:
  312. dialog.update(percent = int((counting / float(listsize)) * 100))
  313. if cleaning:
  314. dbglog('Changing path %s' % strPath)
  315. logfile.write(outdata)
  316. our_data = cursor
  317. if counting == 0: # nothing to remove
  318. logfile.write('No paths have been found to remove\n')
  319. if do_progress:
  320. dialog.close()
  321. logfile.write('\n\n')
  322. logfile.close()
  323.  
  324. #### Start Here !! ####
  325.  
  326. dbglog('script version %s started' % addonversion)
  327. #if WINDOW.getProperty('database-cleaner-running') == 'true':
  328. #log('Video Database Cleaner already running')
  329. #exit(0)
  330. #else:
  331. #WINDOW.setProperty('database-cleaner-running', 'true')
  332.  
  333. xbmcgui.Dialog().notification(addonname, 'Starting Up', xbmcgui.NOTIFICATION_INFO, 2000)
  334. xbmc.sleep(2000)
  335.  
  336. if xbmcvfs.exists(advanced_file):
  337. dbglog('Found advancedsettings.xml')
  338. found = True
  339.  
  340. if found:
  341. msg = advanced_file.encode('utf-8')
  342. dbglog('looking in advancedsettings for videodatabase info')
  343. try:
  344. advancedsettings = ET.parse(advanced_file)
  345. except ET.ParseError:
  346. dbglog('Error parsing advancedsettings.xml file')
  347. xbmcgui.Dialog().ok(addonname, 'Error parsing advancedsettings.xml file[CR] Possibly a mal-formed comment or missing closing tag - script aborted')
  348. exit_on_error()
  349. root = advancedsettings.getroot()
  350. try:
  351. for videodb in root.findall('videodatabase'):
  352. try:
  353. our_host = videodb.find('host').text
  354. except:
  355. log('Unable to find MySQL host address')
  356. try:
  357. our_username = videodb.find('user').text
  358. except:
  359. log('Unable to determine MySQL username')
  360. try:
  361. our_password = videodb.find('pass').text
  362. except:
  363. log('Unable to determine MySQL password')
  364. try:
  365. our_port = videodb.find('port').text
  366. except:
  367. log('Unable to find MySQL port')
  368. try:
  369. our_dbname = videodb.find('name').text
  370. except:
  371. our_dbname = 'MyVideos'
  372. dbglog('MySQL details - %s, %s, %s, %s' % (our_host, our_port, our_username, our_dbname))
  373. is_mysql = True
  374. except Exception as e:
  375. e =str(e)
  376. dbglog ('Error parsing advancedsettings file - %s' % e)
  377. is_mysql = False
  378.  
  379. if not is_mysql:
  380. our_dbname = 'MyVideos'
  381.  
  382. for num in range(MAX_VIDEODB_VERSION, MIN_VIDEODB_VERSION, -1):
  383. testname = our_dbname + str(num)
  384. our_test = db_path + testname + '.db'
  385.  
  386. dbglog('Checking for local database %s' % testname)
  387. if xbmcvfs.exists(our_test):
  388. break
  389. if num != MIN_VIDEODB_VERSION:
  390. our_dbname = testname
  391.  
  392. if our_dbname == 'MyVideos':
  393. dbglog('No video database found - assuming MySQL database')
  394. dbglog('Database name is %s' % our_dbname)
  395.  
  396. if is_pvr == 'true':
  397. is_pvr = True
  398. else:
  399. is_pvr = False
  400.  
  401. if autoclean == 'true':
  402. autoclean = True
  403. else:
  404. autoclean = False
  405. if bookmarks == 'true':
  406. bookmarks = True
  407. else:
  408. bookmarks = False
  409. if promptdelete == 'true':
  410. promptdelete = True
  411. else:
  412. promptdelete = False
  413. if no_sources == 'true':
  414. no_sources = False
  415. else:
  416. no_sources = True
  417.  
  418. dbglog('Settings for file cleaning are as follows')
  419. if is_pvr:
  420. dbglog('keeping PVR files')
  421. if bookmarks:
  422. dbglog('Keeping bookmarks')
  423. if autoclean:
  424. dbglog('autocleaning afterwards')
  425. if promptdelete:
  426. dbglog('Prompting before deletion')
  427. if no_sources:
  428. dbglog('Not using sources.xml')
  429.  
  430. if source_file_path != '':
  431. sources_file = source_file_path
  432. remote_file = True
  433. dbglog('Remote sources.xml file path identified')
  434. if xbmcvfs.exists(sources_file) and not remote_file:
  435. try:
  436. source_file = sources_file
  437. tree = ET.parse(source_file)
  438. root = tree.getroot()
  439. dbglog('Got local sources.xml file')
  440. except:
  441. dbglog('Error parsing local sources.xml file')
  442. xbmcgui.Dialog().ok(addonname, 'Error parsing local sources.xml file - script aborted')
  443. exit_on_error()
  444. elif xbmcvfs.exists(sources_file):
  445. try:
  446. f = xbmcvfs.File(sources_file)
  447. source_file = f.read()
  448. f.close()
  449. root = ET.fromstring(source_file)
  450. dbglog('Got remote sources.xml')
  451. except:
  452. dbglog('Error parsing remote sources.xml')
  453. xbmcgui.Dialog().ok(addonname, 'Error parsing remote sources.xml file - script aborted')
  454. exit_on_error()
  455. else:
  456. xbmcgui.Dialog().notification(addonname,
  457. 'Warning - no sources.xml file found - defaulting to cleaning streaming paths only',xbmcgui.NOTIFICATION_INFO,3000)
  458. dbglog('No local sources.xml, no remote sources file set in settings')
  459. xbmc.sleep(3000)
  460. no_sources = True
  461. my_command = ''
  462. first_time = True
  463. if forcedbname:
  464. log('Forcing video db version to %s' % forcedname)
  465.  
  466. # Open database connection
  467.  
  468. if is_mysql and not forcedbname:
  469. if our_dbname == '': # no db name in advancedsettings
  470. our_dbname = 'MyVideos'
  471. for num in range(MAX_VIDEODB_VERSION, MIN_VIDEODB_VERSION, -1):
  472. testname = our_dbname + str(num)
  473. try:
  474. dbglog('Attempting MySQL connection to %s' % testname)
  475. db = mysql.connector.connect(user=our_username,
  476. database=testname, password=our_password,
  477. host=our_host)
  478. if db.is_connected():
  479. our_dbname = testname
  480. dbglog('Connected to MySQL database %s' % our_dbname)
  481. break
  482. except:
  483. pass
  484. else: # already got db name from ad settings
  485. for num in range(MAX_VIDEODB_VERSION, MIN_VIDEODB_VERSION, -1):
  486. testname = our_dbname + str(num)
  487. try:
  488. dbglog('Attempting MySQL connection to %s' % testname)
  489. db = mysql.connector.connect(user=our_username, database=testname, password=our_password, host=our_host, port=our_port)
  490. if db.is_connected():
  491. our_dbname = testname
  492. dbglog('Connected to MySQL database %s' % our_dbname)
  493. break
  494. except:
  495. pass
  496. if not db.is_connected():
  497. xbmcgui.Dialog().ok(addonname, "Couldn't connect to MySQL database", s)
  498. log("Error - couldn't connect to MySQL database - %s " % s)
  499. exit_on_error()
  500. elif is_mysql and forcedbname:
  501. try:
  502. db = mysql.connector.connect(user=our_username, database=forcedname, password=our_password, host=our_host, port=our_port)
  503. if db.is_connected():
  504. our_dbname = forcedname
  505. dbglog('Connected to forced MySQL database %s' % forcedname)
  506. except:
  507. log('Error connecting to forced database - %s' % forcedname)
  508. exit_on_error()
  509. elif not is_mysql and not forcedbname:
  510. try:
  511. my_db_connector = db_path + our_dbname + '.db'
  512. db = sqlite3.connect(my_db_connector)
  513. except Exception as e:
  514. s = str(e)
  515. xbmcgui.Dialog().ok(addonname, 'Error connecting to SQLite database', s)
  516. log('Error connecting to SQLite database - %s' % s)
  517. exit_on_error()
  518. else:
  519. testpath = db_path + forcedname + '.db'
  520. if not xbmcvfs.exists(testpath):
  521. log('Forced version of database does not exist')
  522. xbmcgui.Dialog().ok(addonname,'Error - Forced version of database ( %s ) not found. Script will now exit' % forcedname)
  523. exit_on_error()
  524. try:
  525. my_db_connector = db_path + forcedname + '.db'
  526. db = sqlite3.connect(my_db_connector)
  527. dbglog('Connected to forced video database')
  528. except:
  529. xbmcgui.Dialog().ok(addonname,'Error - Unable to connect to forced database %s. Script will now exit' % forcedname)
  530. log('Unable to connect to forced database s%' % forcedname)
  531. exit_on_error()
  532.  
  533. cursor = db.cursor()
  534.  
  535. if xbmcvfs.exists(excludes_file):
  536. excludes_list =[]
  537. excluding = True
  538. exclude_command = ''
  539. try:
  540. tree = ET.parse(excludes_file)
  541. er = tree.getroot()
  542. for excludes in er.findall('exclude'):
  543. to_exclude = excludes.text
  544. excludes_list.append(to_exclude)
  545. dbglog('Excluding plugin path - %s' % to_exclude)
  546. exclude_command = exclude_command + " AND strPath NOT LIKE '" + to_exclude + "%'"
  547. log('Parsed excludes.xml')
  548. except:
  549. log('Error parsing excludes.xml')
  550. xbmcgui.Dialog().ok(addonname, 'Error parsing excludes.xml file - script aborted')
  551. exit_on_error()
  552.  
  553. if not no_sources:
  554. # start reading sources.xml and build SQL statements to exclude these sources from any cleaning
  555. try:
  556. display_list =[]
  557. for video in root.findall('video'):
  558. dbglog('Contents of sources.xml file')
  559.  
  560. for sources in video.findall('source'):
  561. for path_name in sources.findall('name'):
  562. the_path_name = path_name.text
  563. for paths in sources.findall('path'):
  564. the_path = paths.text.replace("'","''")
  565. display_list.append(the_path)
  566. dbglog('%s - %s' % (the_path_name, the_path))
  567. if first_time:
  568. first_time = False
  569. my_command = "strPath NOT LIKE '" + the_path + "%'"
  570. our_source_list = 'Keeping files in ' + the_path
  571. else:
  572. my_command = my_command + " AND strPath NOT LIKE '" + the_path + "%'"
  573. our_source_list = our_source_list + ', ' + the_path
  574. if path_name == '':
  575. no_sources = True
  576. dbglog('******* WARNING *******')
  577. dbglog('local sources.xml specified in settings')
  578. dbglog('But no sources found in sources.xml file')
  579. dbglog('Defaulting to alternate method for cleaning')
  580. except:
  581. log('Error parsing sources.xml file')
  582. xbmcgui.Dialog().ok(addonname, 'Error parsing sources.xml file - script aborted')
  583. exit_on_error()
  584.  
  585. if is_pvr:
  586. my_command = my_command + " AND strPath NOT LIKE 'pvr://%'"
  587. our_source_list = our_source_list + 'Keeping PVR info '
  588. if excluding:
  589. my_command = my_command + exclude_command
  590. our_source_list = our_source_list + 'Keeping items from excludes.xml '
  591. if bookmarks:
  592. my_command = my_command + ' AND idFile NOT IN (SELECT idFile FROM bookmark)'
  593. our_source_list = our_source_list + 'Keeping bookmarked files '
  594.  
  595. # construct the full SQL query
  596.  
  597. sql = \
  598. """DELETE FROM files WHERE idPath IN(SELECT idPath FROM path where (""" + my_command + """));"""
  599. if no_sources:
  600. my_command = ''
  601. our_source_list = 'NO SOURCES FOUND - REMOVING rtmp(e), plugin and http info '
  602. dbglog('Not using sources.xml')
  603. if is_pvr:
  604. my_command = my_command + "strPath NOT LIKE 'pvr://%'"
  605. our_source_list = our_source_list + 'Keeping PVR info '
  606. if bookmarks:
  607. if my_command:
  608. my_command = my_command + ' AND idFile NOT IN (SELECT idFile FROM bookmark)'
  609. else:
  610. my_command = my_command + ' idFile NOT IN (SELECT idFile FROM bookmark)'
  611. our_source_list = our_source_list + 'Keeping bookmarked files '
  612. if excluding:
  613. if my_command:
  614. my_command = my_command + exclude_command
  615. else:
  616. my_command = my_command + exclude_command.replace('AND','',1)
  617. our_source_list = our_source_list + 'Keeping items from excludes.xml '
  618.  
  619. # Build SQL query
  620.  
  621. if not no_sources: # this is SQL for no sources
  622. sql = """DELETE FROM files WHERE idPath IN ( SELECT idPath FROM path WHERE ((""" + my_command + """)));"""
  623. # sql2="""DELETE FROM path WHERE idPath IN (SELECT * FROM( SELECT idPath FROM path WHERE ((strPath LIKE 'rtmp://%' OR strPath Like 'rtmpe:%' OR strPath LIKE 'plugin:%' OR strPath LIKE 'http://%') AND (""" + my_command +"""))) as pathsub);"""
  624. else:
  625. sql = """DELETE FROM files WHERE idPath IN (SELECT idPath FROM path WHERE ((strPath LIKE 'rtmp://%' OR strPath LIKE 'rtmpe:%' OR strPath LIKE 'plugin:%' OR strPath LIKE 'http://%' OR strPath LIKE 'https://%') AND (""" + my_command + """)));"""
  626. # sql2= """DELETE FROM path WHERE idPath IN (SELECT * FROM( SELECT idPath FROM path WHERE (strPath LIKE 'rtmp://%' OR strPath Like 'rtmpe:%' OR strPath LIKE 'plugin:%' OR strPath LIKE 'http://%') as pathsub);"""
  627. if my_command == "":
  628. sql=sql.replace('((strPath','(strPath').replace(' AND ()))',')')
  629. dbglog('SQL command is %s' % sql)
  630. if not specificpath and not replacepath:
  631. dbglog (our_source_list)
  632. our_select = sql.replace('DELETE FROM files','SELECT strPath FROM path',1)
  633. if bookmarks: # have to delete from paths table rather than files as there is a conflicting trigger on the files table
  634. our_select = sql.replace('DELETE FROM files', 'SELECT strPath FROM path WHERE idPath in (SELECT idPath FROM files', 1)
  635. our_select = our_select.replace('bookmark)', 'bookmark))',1)
  636. sql = sql.replace('DELETE FROM files','DELETE FROM path',1)
  637. dbglog('Select Command is %s' % our_select)
  638. elif not replacepath and specificpath: # cleaning a specific path
  639. if specific_path_to_remove != '':
  640. sql = """delete from path where idPath in(select * from (SELECT idPath FROM path WHERE (strPath LIKE '""" + specific_path_to_remove +"""%')) as temptable)"""
  641. our_select = "SELECT strPath FROM path WHERE idPath IN (SELECT idPath FROM path WHERE (strPath LIKE'" + specific_path_to_remove + "%'))"
  642. dbglog('Select Command is %s' % our_select)
  643. else:
  644. xbmcgui.Dialog().ok(addonname,'Error - Specific path selected but no path defined. Script aborted')
  645. dbglog("Error - Specific path selected with no path defined")
  646. exit_on_error()
  647. else: # must be replacing a path at this point
  648. if old_path != '' and new_path != '':
  649. our_select = "SELECT strPath from path WHERE strPath Like '" + old_path + "%'"
  650. else:
  651. xbmcgui.Dialog().ok(addonname,'Error - Replace path selected but one or more paths are not defined. Script aborted')
  652. dbglog('Error - Missing path for replacement')
  653. exit_on_error()
  654. xbmc.sleep(500)
  655.  
  656. if promptdelete:
  657. cleaner_log_file(our_select, False)
  658. mydisplay = MyClass('cleaner-window.xml', addonpath, 'Default', '1080i')
  659. mydisplay.doModal()
  660. del mydisplay
  661. if flag == 1:
  662. i = True
  663. else:
  664. i = False
  665.  
  666. else:
  667. i = True
  668. if i:
  669. if autobackup == 'true' and not is_mysql:
  670. backup_path = xbmc.translatePath('special://database/backups/'
  671. )
  672.  
  673. if not xbmcvfs.exists(backup_path):
  674. dbglog('Creating backup path %s' % backup_path)
  675. xbmcvfs.mkdir(backup_path)
  676. now = datetime.datetime.now()
  677. if forcedbname:
  678. our_dbname = forcedname
  679. current_db = db_path + our_dbname + '.db'
  680. if backup_filename == '':
  681. backup_filename = our_dbname
  682. backup_db = backup_path + backup_filename + '_' \
  683. + now.strftime('%Y-%m-%d_%H%M') + '.db'
  684. backup_filename = backup_filename + '_' \
  685. + now.strftime('%Y-%m-%d_%H%M')
  686. success = xbmcvfs.copy(current_db, backup_db)
  687. if success == 1:
  688. success = 'successful'
  689. else:
  690. success = 'failed'
  691. dbglog('auto backup database %s.db to %s.db - result was %s'
  692. % (our_dbname, backup_filename, success))
  693. cleaner_log_file(our_select, True)
  694. if not replacepath:
  695. try:
  696.  
  697. # Execute the SQL command
  698. dbglog('Executing SQL command - %s' % sql)
  699. cursor.execute(sql)
  700. # cursor.execute(sql2)
  701. # Commit the changes in the database
  702.  
  703. db.commit()
  704.  
  705. except Exception as e:
  706.  
  707. # Rollback in case there is any error
  708.  
  709. db.rollback()
  710. dbglog('Error in db commit. Transaction rolled back')
  711. dbglog('******************************************************************************')
  712. dbglog('** SQL ERROR ** SQL ERROR ** SQL ERROR ** SQL ERROR ** SQL ERROR **')
  713. dbglog('** %s ' % e)
  714. dbglog('******************************************************************************')
  715.  
  716. else:
  717. dbglog('Changing Paths - generating SQL statements')
  718. our_select = "SELECT strPath from path WHERE strPath Like '" + old_path + "%'"
  719. cursor.execute(our_select)
  720. tempcount=0
  721. listsize = len(cursor.fetchall())
  722. dialog = xbmcgui.DialogProgressBG()
  723. dbglog('Creating progress dialog')
  724. dialog.create('Replacing paths in database. Please wait')
  725. dialog.update(1)
  726. dbglog('Cursor size is %d' % listsize)
  727. cursor.execute(our_select)
  728. renamepath_list = []
  729. for strPath in cursor: # build a list of paths to change
  730. renamepath_list.append( ''.join(strPath))
  731.  
  732. for i in range(len(renamepath_list)):
  733. tempcount += 1
  734. our_old_path = renamepath_list[i]
  735. our_new_path = our_old_path.replace(old_path, new_path,1)
  736. sql = 'UPDATE path SET strPath ="' + our_new_path + '" WHERE strPath LIKE "' +our_old_path + '"'
  737. dialog.update(percent = int((tempcount / float(listsize)) * 100))
  738. dbglog('Percentage done %d' % int((tempcount / float(listsize)) * 100))
  739. dbglog('SQL - %s' % sql)
  740. try:
  741. cursor.execute(sql)
  742. db.commit()
  743. except Exception as e:
  744. e = str(e)
  745. db.rollback()
  746. dbglog('Error in db commit %s. Transaction rolled back' % e)
  747.  
  748. # disconnect from server
  749. # xbmc.executebuiltin( "Dialog.Close(busydialog)" )
  750. xbmc.sleep(1000)
  751. dbglog('Closing progress dialog')
  752. dialog.close()
  753. db.close()
  754. dbglog("Database connection closed")
  755. # Make sure replacing or changing a path is a one-shot deal
  756.  
  757. if replacepath or specificpath:
  758. addon.setSetting('specificpath', 'false')
  759. addon.setSetting('replacepath', 'false')
  760.  
  761.  
  762. if autoclean:
  763. xbmcgui.Dialog().notification(addonname,
  764. 'Running cleanup', xbmcgui.NOTIFICATION_INFO,
  765. 2000)
  766. xbmc.sleep(2000)
  767.  
  768. json_query = \
  769. xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "VideoLibrary.Clean","id": 1 }'
  770. )
  771. json_query = str(json_query, errors='ignore')
  772. json_query = jsoninterface.loads(json_query)
  773. if json_query.has_key('result'):
  774. dbglog('Clean library sucessfully called')
  775. else:
  776. xbmcgui.Dialog().ok(addonname,
  777. 'Script finished. You should run clean library for best results'
  778. )
  779. dbglog('Script finished')
  780.  
  781. else:
  782. xbmcgui.Dialog().notification(addonname, 'Script aborted - No changes made', xbmcgui.NOTIFICATION_INFO, 3000)
  783. dbglog('script aborted by user - no changes made')
  784. WINDOW.setProperty('database-cleaner-running', 'false')
  785. exit(1)
  786. WINDOW.setProperty('database-cleaner-running', 'false')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement