def fileName(self): bt = None if not self.titleId in Titles.keys(): if not Title.getBaseId(self.titleId) in Titles.keys(): Print.info('could not find title key for ' + str(self.titleId) + ' or ' + str(Title.getBaseId(self.titleId))) return None bt = Titles.get(Title.getBaseId(self.titleId)) t = Title() t.loadCsv(self.titleId + '0000000000000000|0000000000000000|' + bt.name) else: t = Titles.get(self.titleId) if not t: Print.error('could not find title id ' + str(self.titleId)) return None try: if not t.baseId in Titles.keys(): Print.info('could not find baseId for ' + self.path) return None except BaseException as e: print('exception: could not find title id ' + str(self.titleId) + ' ' + str(e)) return None bt = Titles.get(t.baseId) if t.isDLC: format = Config.paths.getTitleDLC(not self.hasValidTicket) elif t.isDemo: if t.idExt != 0: format = Config.paths.getTitleDemoUpdate( not self.hasValidTicket) else: format = Config.paths.getTitleDemo(not self.hasValidTicket) elif t.idExt != 0: format = Config.paths.getTitleUpdate(not self.hasValidTicket) else: format = Config.paths.getTitleBase(not self.hasValidTicket) format = format.replace('{id}', self.cleanFilename(t.id)) format = format.replace('{region}', self.cleanFilename(t.getRegion() or '')) format = format.replace('{name}', self.cleanFilename(t.getName() or '')) format = format.replace('{version}', str(self.getVersion() or 0)) format = format.replace('{baseId}', self.cleanFilename(bt.id)) baseName = self.cleanFilename(bt.getName() or '') result = format.replace('{baseName}', baseName) while (len(os.path.basename(result).encode('utf-8')) > 240 and len(baseName) > 3): baseName = baseName[:-1] result = format.replace('{baseName}', baseName) return result
def scanLatestTitleUpdates(): global versionHistory initTitles() initFiles() now = datetime.datetime.now() today = now.strftime("%Y-%m-%d") try: with open('titledb/versions.json', 'r') as f: for titleId, vers in json.loads(f.read()).items(): for ver, date in vers.items(): setVersionHistory(titleId, ver, date) except BaseException: pass if not hasCdn: return for k, i in cdn.hacVersionList().items(): id = str(k).upper() version = str(i) if not Titles.contains(id): if len(id) != 16: Print.info('invalid title id: ' + id) continue t = Titles.get(id) if t.isUpdate: setVersionHistory(Title.getBaseId(id), version, today) else: setVersionHistory(id, version, today) if str(t.version) != str(version): Print.info('new version detected for %s[%s] v%s' % (t.name or '', t.id or ('0' * 16), str(version))) t.setVersion(version, True) Titles.save() try: with open('titledb/versions.json', 'w') as outfile: json.dump(versionHistory, outfile, indent=4, sort_keys=True) except BaseException as e: Print.info(str(e))
def fileName(self, forceNsp=False): bt = None if self.titleId not in Titles.keys(): if not Title.getBaseId(self.titleId) in Titles.keys(): Print.error('could not find base title for ' + str(self.titleId) + ' or ' + str(Title.getBaseId(self.titleId))) return None bt = Titles.get(Title.getBaseId(self.titleId)) t = Title.Title() if bt.name is not None: t.loadCsv(self.titleId + '0000000000000000|0000000000000000|' + bt.name) else: t.setId(self.titleId) else: t = Titles.get(self.titleId) if not t: Print.error('could not find title id ' + str(self.titleId)) return None try: if t.baseId not in Titles.keys(): Print.info('could not find baseId for ' + self.path) return None except BaseException as e: Print.error('exception: could not find title id ' + str(self.titleId) + ' ' + str(e)) return None bt = Titles.get(t.baseId) isNsx = not self.hasValidTicket and not forceNsp try: if t.isDLC: format = Config.paths.getTitleDLC(isNsx, self.path) elif t.isDemo: if t.idExt != 0: format = Config.paths.getTitleDemoUpdate(isNsx, self.path) else: format = Config.paths.getTitleDemo(isNsx, self.path) elif t.idExt != 0: if bt and bt.isDemo: format = Config.paths.getTitleDemoUpdate(isNsx, self.path) else: format = Config.paths.getTitleUpdate(isNsx, self.path) else: format = Config.paths.getTitleBase(isNsx, self.path) except BaseException as e: Print.error('calc path exception: ' + str(e)) return None if not format: return None newName = self.cleanFilename(t.getName() or '') format = format.replace('{id}', self.cleanFilename(t.id)) format = format.replace( '{region}', self.cleanFilename(t.getRegion() or bt.getRegion())) format = format.replace('{name}', newName) format = format.replace('{version}', str(self.getVersion() or 0)) format = format.replace('{baseId}', self.cleanFilename(bt.id)) if '{cr}' in format: format = format.replace('{cr}', str(self.getCr())) if '{icr}' in format: format = format.replace('{icr}', str(self.getCr(True))) bn = os.path.basename(self.path) if (not newName or len(newName) == 0) and not bn.upper().startswith(t.id.upper()): Print.error('could not get new name for ' + bn) return os.path.join(os.path.dirname(format), os.path.basename(self.path)) baseName = self.cleanFilename(bt.getName() or '') if not baseName or len(baseName) == 0: baseName = os.path.basename(self.path) result = format.replace('{baseName}', baseName) while (len(os.path.basename(result).encode('utf-8')) > 240 and len(baseName) > 3): baseName = baseName[:-1] result = format.replace('{baseName}', baseName) return os.path.abspath(result)
def move(self, forceNsp=False): if not self.path: Print.error('no path set') return False if os.path.abspath(self.path).startswith( os.path.abspath(Config.paths.nspOut) ) and not self.path.endswith('.nsz') and not self.path.endswith( '.xcz') and Config.compression.auto: nszFile = nut.compress(self.path, Config.compression.level, os.path.abspath(Config.paths.nspOut)) if nszFile: nsp = Fs.Nsp(nszFile, None) nsp.hasValidTicket = True nsp.move(forceNsp=True) Nsps.files[nsp.path] = nsp Nsps.save() newPath = self.fileName(forceNsp=forceNsp) if not newPath: Print.error('could not get filename for ' + self.path) return False if os.path.abspath(newPath).lower().replace( '\\', '/') == os.path.abspath(self.path).lower().replace('\\', '/'): return False if os.path.isfile(newPath): Print.info('\nduplicate title: ') Print.info(os.path.abspath(self.path)) Print.info(os.path.abspath(newPath)) Print.info('\n') return False if not self.verifyNcaHeaders(): Print.error('verification failed: could not move title for ' + str(self.titleId) + ' or ' + str(Title.getBaseId(self.titleId))) return False try: Print.info(self.path + ' -> ' + newPath) if not Config.dryRun: os.makedirs(os.path.dirname(newPath), exist_ok=True) #newPath = self.fileName(forceNsp = forceNsp) if not Config.dryRun: if self.isOpen(): self.close() shutil.move(self.path, newPath) if self.path in Nsps.files: del Nsps.files[self.path] Nsps.files[newPath] = self self.path = newPath except BaseException as e: Print.error('failed to rename file! %s -> %s : %s' % (self.path, newPath, e)) if not Config.dryRun: self.moveDupe() return True