repair.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. import os, pickle, logging
  2. from data import database, config
  3. logger = logging.getLogger(__name__)
  4. def repair_main_db():
  5. everything_okay = True
  6. #region Check structure
  7. logger.info('Checking database structure')
  8. if 'type' not in database:
  9. logger.warning('Database type set to \'main\'')
  10. database['type'] = 'main'
  11. everything_okay = False
  12. if database['type'] != 'main':
  13. logger.critical('The loaded database isn\'t the right type')
  14. everything_okay = False
  15. return everything_okay
  16. #region main
  17. if 'music' not in database:
  18. logger.warning('Database missing music field')
  19. database['music'] = {}
  20. everything_okay = False
  21. if 'artists' not in database:
  22. logger.warning('Database missing artists field')
  23. database['artists'] = {}
  24. everything_okay = False
  25. if 'albums' not in database:
  26. logger.warning('Database missing albums field')
  27. database['albums'] = {}
  28. everything_okay = False
  29. if 'genres' not in database:
  30. logger.warning('Database missing genres field')
  31. database['genres'] = {}
  32. everything_okay = False
  33. #endregion
  34. #region music
  35. logger.info('Checking track structure')
  36. for track_uuid in database['music']:
  37. logger.info('Checking track %s' % track_uuid)
  38. track = database['music'][track_uuid]
  39. if 'title' not in track:
  40. logger.error('Track missing title field')
  41. track['title'] = None
  42. everything_okay = False
  43. if 'artists' not in track:
  44. logger.error('Track missing artists field')
  45. track['artists'] = []
  46. everything_okay = False
  47. if 'album' not in track:
  48. logger.error('Track missing album field')
  49. track['album'] = None
  50. everything_okay = False
  51. if 'genre' not in track:
  52. logger.error('Track missing genre field')
  53. track['genre'] = None
  54. everything_okay = False
  55. #endregion
  56. #region albums
  57. logger.info('Checking album structure')
  58. for album_uuid in database['albums']:
  59. logger.info('Checking album %s' % album_uuid)
  60. album = database['albums'][album_uuid]
  61. if 'name' not in album:
  62. logger.error('Album missing name field')
  63. album['name'] = None
  64. everything_okay = False
  65. if 'artist' not in album:
  66. logger.error('Album missing artist field')
  67. album['artist'] = None
  68. everything_okay = False
  69. #endregion
  70. #region artists
  71. logger.info('Checking artist structure')
  72. for artist_uuid in database['artists']:
  73. logger.info('Checking artist %s' % artist_uuid)
  74. artist = database['artists'][artist_uuid]
  75. if 'name' not in artist:
  76. logger.error('Artist missing name field')
  77. artist['name'] = None
  78. everything_okay = False
  79. #endregion
  80. #region genres
  81. logger.info('Checking genre structure')
  82. for genre_uuid in database['genres']:
  83. logger.info('Checking genre %s' % genre_uuid)
  84. genre = database['genres'][genre_uuid]
  85. if 'name' not in genre:
  86. logger.error('Genre missing name field')
  87. genre['name'] = None
  88. everything_okay = False
  89. #endregion
  90. #endregion
  91. #region Check tracks
  92. tracks_to_destroy = set()
  93. logger.info('Checking tracks')
  94. for uuid in database['music']:
  95. logger.info('Checking track %s' % uuid)
  96. track = database['music'][uuid]
  97. logger.info('Correcting file path')
  98. track['path'] = track['path'].replace('\\', '/')
  99. #region Check if file exists
  100. logger.info('Checking if file exists')
  101. abs_track_path = os.path.join(config['files']['audio']['path'], track['path'])
  102. if not os.path.exists(abs_track_path):
  103. logger.error('Track file not found. Queueing the track to be removed for the database')
  104. tracks_to_destroy.add(uuid)
  105. everything_okay = False
  106. continue
  107. #endregion
  108. #region Check artists
  109. logger.info('Checking artists')
  110. if 'artists' in track:
  111. if type(track['artists']) == list:
  112. logger.info('Changing data type from list to set')
  113. track['artists'] = set(track['artists'])
  114. artists_removed = 0
  115. artists_to_remove = []
  116. for artist in track['artists']:
  117. if artist not in database['artists']:
  118. artists_to_remove.append(artist)
  119. for artist in artists_to_remove:
  120. track['artists'].remove(artist)
  121. artists_removed += 1
  122. if artists_removed:
  123. logger.info('Removed %s non-existent artists' % artists_removed)
  124. everything_okay = False
  125. else:
  126. logger.error('Track missing artists field')
  127. track['artists'] = set()
  128. #endregion
  129. #region Check albums
  130. logger.info('Checking album')
  131. if 'album' in track:
  132. if track['album'] and track['album'] not in database['albums']:
  133. track['album'] = None
  134. logger.error('Track album doesn\'t exist in the database')
  135. everything_okay = False
  136. else:
  137. logger.error('Track missing album field')
  138. track['album'] = None
  139. #endregion
  140. #region Check genres
  141. if 'genre' in track:
  142. logger.info('Checking genre')
  143. if track['genre'] and track['genre'] not in database['genres']:
  144. track['genre'] = None
  145. logger.error('Track genre doesn\'t exist in the database')
  146. everything_okay = False
  147. else:
  148. logger.error('Track missing genre field')
  149. track['genre'] = None
  150. #endregion
  151. #endregion
  152. #region Destroy tracks
  153. if tracks_to_destroy:
  154. logger.info('Removing %s tracks from the database' % len(tracks_to_destroy))
  155. for track in tracks_to_destroy:
  156. del database['music'][track]
  157. logger.info('Removed %s from the database' % track)
  158. everything_okay = False
  159. else:
  160. logger.info('No tracks were removed from the database')
  161. #endregion
  162. #region Check album artists
  163. logger.info('Checking album artists')
  164. for uuid in database['albums']:
  165. if not album['artist']:
  166. continue
  167. if album['artist'] not in database['artists']:
  168. logger.error('Album %s referenced an artist that is not in the database' % uuid)
  169. album['artist'] = None
  170. #endregion
  171. if everything_okay:
  172. logger.info('Everything okay')
  173. return everything_okay
  174. def repair_sync_db(path):
  175. everything_okay = True
  176. #region load database
  177. logger.info('Loading sync database')
  178. if os.path.exists(os.path.join(path, 'sync.pkl')):
  179. with open(os.path.join(path, 'sync.pkl'), 'rb') as f:
  180. db = pickle.load(f)
  181. else:
  182. logger.critical('Failed to load sync database')
  183. return
  184. #endregion
  185. #region check strucure
  186. logger.info('Checking database structure')
  187. if not 'type' in db:
  188. logger.warning('Database type set to \'sync\'')
  189. db['type'] = 'sync'
  190. everything_okay = False
  191. if not 'music' in db:
  192. logger.info('Database missing music field')
  193. db['music'] = {}
  194. everything_okay = False
  195. if not 'templates' in db:
  196. logger.info('Database missing templates field')
  197. db['templates'] = {}
  198. everything_okay = False
  199. if not 'path' in db['templates']:
  200. db['templates']['path'] = '%(album)s by %(albumArtist)s/%(title)s by %(artists)s.%(ext)s'
  201. if not 'overwrite' in db['music']:
  202. print('Database missing \'music\' \'overwrite\'')
  203. db['music']['overwrite'] = {}
  204. everything_okay = False
  205. if not 'tracks' in db['music']:
  206. print('Database missing \'music\' \'tracks\'')
  207. db['music']['tracks'] = {}
  208. everything_okay = False
  209. if not 'blacklist' in db['music']:
  210. print('Database missing \'music\' \'blacklist\'')
  211. db['music']['blacklist'] = {}
  212. everything_okay = False
  213. if not 'artist' in db['templates']:
  214. print('Database missing \'templates\' \'artist\'')
  215. db['templates']['artist'] = {}
  216. everything_okay = False
  217. if not 'metadata' in db['music']['overwrite']:
  218. print('Database missing \'music\' \'overwrite\' \'metadata\'')
  219. db['music']['overwrite']['metadata'] = True
  220. everything_okay = False
  221. if not 'path' in db['music']['overwrite']:
  222. print('Database missing \'music\' \'overwrite\' \'path\'')
  223. db['music']['overwrite']['path'] = True
  224. everything_okay = False
  225. if not 'seperator' in db['templates']['artist']:
  226. print('Database missing \'templates\' \'artist\' \'seperator\'')
  227. db['templates']['artist']['seperator'] = {}
  228. everything_okay = False
  229. if not 'filename' in db['templates']['artist']['seperator']:
  230. print('Database missing \'templates\' \'artist\' \'seperator\' \'filename\'')
  231. db['templates']['artist']['seperator']['filename'] = ', '
  232. everything_okay = False
  233. if not 'metadata' in db['templates']['artist']['seperator']:
  234. print('Database missing \'templates\' \'artist\' \'seperator\' \'metadata\'')
  235. db['templates']['artist']['seperator']['metadata'] = ';'
  236. everything_okay = False
  237. #region check tracks
  238. # print('Checking track structure')
  239. # for uuid in db['music']['tracks']:
  240. # track = db['music']['tracks'][uuid]
  241. #endregion
  242. #endregion
  243. #region check files
  244. print('Checking files')
  245. to_remove = set()
  246. for uuid in db['music']['tracks']:
  247. sync_track = db['music']['tracks'][uuid]
  248. if not os.path.exists(os.path.join(path, sync_track['path'])):
  249. print('%s is missing it\'s sync file and will be queued for removal' % uuid)
  250. to_remove.add(uuid)
  251. everything_okay = False
  252. if not uuid in database['music']:
  253. print('%s wasn\'t found in the main database and will be queued for removal' % uuid)
  254. to_remove.add(uuid)
  255. everything_okay = False
  256. if uuid in db['music']['blacklist']:
  257. print('%s has been synced, but it\'s in the blacklist. It will be queued for removal' % uuid)
  258. to_remove.add(uuid)
  259. everything_okay = False
  260. #endregion
  261. #region remove files
  262. for uuid in to_remove:
  263. print('Removing track %s' % uuid)
  264. sync_track = db['music']['tracks'][uuid]
  265. if os.path.exists(os.path.join(path, sync_track['path'])):
  266. os.remove(os.path.join(path, sync_track['path']))
  267. del db['music']['tracks'][uuid]
  268. if to_remove:
  269. print('Removed %s tracks' % len(to_remove))
  270. #endregion
  271. if everything_okay:
  272. print('Everything okay')
  273. print('Dumping sync database')
  274. with open(os.path.join(path, 'sync.pkl'), 'wb') as f:
  275. pickle.dump(db, f)
  276. return everything_okay