Esempio n. 1
0
File: Api.py Progetto: carlchina/nut
def getTitleImage(request, response):
    if len(request.bits) < 3:
        return Server.Response404(request, response)

    id = request.bits[2]
    try:
        width = int(request.bits[3])
    except:
        return Server.Response404(request, response)

    if width < 32 or width > 1024:
        return Server.Response404(request, response)

    if not Titles.contains(id):
        return Server.Response404(request, response)

    path = Titles.get(id).iconFile(width) or Titles.get(id).frontBoxArtFile(
        width)

    if not path:
        return Server.Response404(request, response)

    response.setMime(path)
    response.headers['Cache-Control'] = 'max-age=31536000'

    if os.path.isfile(path):
        with open(path, 'rb') as f:
            response.write(f.read())

    return Server.Response500(request, response)
Esempio n. 2
0
    def isUpdateAvailable(self):
        title = self.title()

        if self.titleId and title.version != None and self.version < title.version and str(
                title.version) != '0':
            return {
                'id': title.id,
                'baseId': title.baseId,
                'currentVersion': self.version,
                'newVersion': title.version
            }

        if not title.isUpdate and not title.isDLC and Titles.contains(
                title.updateId):
            updateFile = self.getUpdateFile()

            if updateFile:
                return updateFile.isUpdateAvailable()

            updateTitle = Titles.get(title.updateId)

            if updateTitle.version and str(updateTitle.version) != '0':
                return {
                    'id': updateTitle.id,
                    'baseId': title.baseId,
                    'currentVersion': None,
                    'newVersion': updateTitle.version
                }

        return None
Esempio n. 3
0
File: Api.py Progetto: carlchina/nut
def getScreenshotImage(request, response):
    if len(request.bits) < 3:
        return Server.Response404(request, response)

    id = request.bits[2]

    try:
        i = int(request.bits[3])
    except:
        return Server.Response404(request, response)

    if not Titles.contains(id):
        return Server.Response404(request, response)

    path = Titles.get(id).screenshotFile(i)

    if not path:
        return Server.Response404(request, response)

    response.setMime(path)
    response.headers['Cache-Control'] = 'max-age=31536000'

    if os.path.isfile(path):
        with open(path, 'rb') as f:
            response.write(f.read())

    return Server.Response500(request, response)
Esempio n. 4
0
File: nut.py Progetto: carlchina/nut
def scanLatestTitleUpdates():
    initTitles()
    initFiles()

    for k, i in CDNSP.get_versionUpdates().items():
        id = str(k).upper()
        version = str(i)

        if not Titles.contains(id):
            if len(id) != 16:
                Print.info('invalid title id: ' + id)
                continue
            continue
            t = Title()
            t.setId(id)
            Titles.set(id, t)
            Print.info('Found new title id: ' + str(id))

        t = Titles.get(id)
        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()
Esempio n. 5
0
File: nut.py Progetto: carlchina/nut
def downloadThread(i):
    Print.info('starting thread ' + str(i))
    global status
    while Config.isRunning:
        try:
            id = Titles.queue.shift()
            if id and Titles.contains(id):
                activeDownloads[i] = 1
                t = Titles.get(id)
                path = CDNSP.download_game(t.id.lower(), t.lastestVersion(),
                                           t.key, True, '', True)

                if os.path.isfile(path):
                    nsp = Fs.Nsp(path, None)
                    nsp.move()
                    Nsps.files[nsp.path] = nsp
                    Nsps.save()
                    status.add()
                activeDownloads[i] = 0
            else:
                time.sleep(1)
        except KeyboardInterrupt:
            pass
        except BaseException as e:
            Print.error(str(e))
    activeDownloads[i] = 0
    Print.info('ending thread ' + str(i))
Esempio n. 6
0
def updateVersions(force = True):
	initTitles()
	initFiles()

	i = 0
	for k,t in Titles.items():
		if force or t.version == None:
			if (t.isDLC or t.isUpdate or Config.download.base) and (not t.isDLC or Config.download.DLC) and (not t.isDemo or Config.download.demo) and (not t.isUpdate or Config.download.update) and (t.key or Config.download.sansTitleKey) and (len(titleWhitelist) == 0 or t.id in titleWhitelist) and t.id not in titleBlacklist:
				v = t.lastestVersion(True)
				Print.info("%s[%s] v = %s" % (str(t.name), str(t.id), str(v)) )
			
				i = i + 1
				if i % 20 == 0:
					Titles.save()
			
	for t in list(Titles.data().values()):
		if not t.isUpdate and not t.isDLC and t.updateId and t.updateId and not Titles.contains(t.updateId):
			u = Title()
			u.setId(t.updateId)
			
			if u.lastestVersion():
				Titles.set(t.updateId, u)
				
				Print.info("%s[%s] FOUND" % (str(t.name), str(u.id)) )
				
				i = i + 1
				if i % 20 == 0:
					Titles.save()
					
	Titles.save()
Esempio n. 7
0
def download(id):
	bits = id.split(',')

	version = None
	key = None

	if len(bits) == 1:
		id = bits[0].upper()
	elif len(bits) == 2:
		id = bits[0].upper()
		key = bits[1].strip()
	elif len(bits) == 3:
		id = bits[0].upper()
		key = bits[1].strip()
		version = bits[2].strip()
	else:
		Print.info('invalid args: ' + download)
		return False

	if key == '':
		key = None

	if version == '':
		version = None

	if len(id) != 16:
		raise IOError('Invalid title id format')

	if Titles.contains(id):
		title = Titles.get(id)

		CDNSP.download_game(title.id.lower(), version or title.lastestVersion(), key or title.key, True, '', True)
	else:
		CDNSP.download_game(id.lower(), version or Title.getCdnVersion(id.lower()), key, True, '', True)
	return True
Esempio n. 8
0
def get_name(titleId):
	titleId = titleId.upper()

	if Titles.contains(titleId):
			try:
				t = Titles.get(titleId)
				return (re.sub(r'[/\\:*?!"|???]+', "", unidecode.unidecode(t.name.strip())))[:70]
			except:
				pass
	return 'Unknown Title'
Esempio n. 9
0
def get_name(titleId):
    titleId = titleId.upper()
    lines = titlekey_list
    if Titles.contains(titleId):
        try:
            t = Titles.get(titleId)
            return re.sub(r'[/\\:*?!"|™©®]+', "",
                          unidecode.unidecode(t.name.strip()))
        except:
            pass
    return 'Unknown Title'
Esempio n. 10
0
    def unlock(self):
        #if not self.isOpen():
        #	self.open('r+b')

        if not Titles.contains(self.titleId):
            raise IOError('No title key found in database!')

        self.ticket().setTitleKeyBlock(int(Titles.get(self.titleId).key, 16))
        Print.info('setting title key to ' + Titles.get(self.titleId).key)
        self.ticket().flush()
        self.close()
        self.hasValidTicket = True
        self.move()
Esempio n. 11
0
File: Api.py Progetto: carlchina/nut
def getFiles(request, response):
    r = {}
    for path, nsp in Nsps.files.items():
        if Titles.contains(nsp.titleId):
            title = Titles.get(nsp.titleId)
            if not title.baseId in r:
                r[title.baseId] = {'base': [], 'dlc': [], 'update': []}
            if title.isDLC:
                r[title.baseId]['dlc'].append(nsp.dict())
            elif title.isUpdate:
                r[title.baseId]['update'].append(nsp.dict())
            else:
                r[title.baseId]['base'].append(nsp.dict())
    response.write(json.dumps(r))
Esempio n. 12
0
File: nut.py Progetto: carlchina/nut
def scanDLC(id, showErr=True, dlcStatus=None):
    id = id.upper()
    title = Titles.get(id)
    baseDlc = Title.baseDlcId(id)
    for i in range(0x1FF):
        scanId = format(baseDlc + i, 'X').zfill(16)
        if Titles.contains(scanId):
            continue
        ver = CDNSP.get_version(scanId.lower())
        if ver != None:
            t = Title()
            t.setId(scanId)
            Titles.set(scanId, t)
            Titles.save()
            Print.info('Found new DLC ' + str(title.name) + ' : ' + scanId)
        elif showErr:
            Print.info('nothing found at ' + scanId + ', ' + str(ver))
        if dlcStatus:
            dlcStatus.add()
Esempio n. 13
0
File: nut.py Progetto: carlchina/nut
def scanBaseThread(baseStatus):
    while Config.isRunning:
        try:
            id = getRandomTitleId()

            if Titles.contains(id):
                continue

            ver = CDNSP.get_version(id.lower())

            if ver != None:
                Print.info('Found new base ' + id)
                t = Title()
                t.setId(id)
                Titles.set(id, t)
                Titles.save()

            baseStatus.add()
        except BaseException as e:
            print('exception: ' + str(e))
Esempio n. 14
0
def getNsuIds(titleIds, type='title', region='US', shop_id=4):
    j = ids(titleIds, type, region, shop_id)
    lst = {}
    try:
        for i in j['id_pairs']:
            titleId = i['title_id'].upper()
            nsuId = int(['id'])
            lst[titleId] = nsuId

            if Titles.contains(titleId):
                Titles.get(titleId).nsuId = nsuId
            else:
                title = Title.Title()
                title.setId(titleId)
                title.nsuId = nsuId
                Titles.set(titleId, title)

    except BaseException as e:
        pass
    return lst
Esempio n. 15
0
def getAddOns(titleId, shop_id=3):
    url = 'https://superfly.hac.%s.d4c.nintendo.net/v1/a/%s/dv' % (
        Config.cdn.environment, titleId)
    j = makeJsonRequest('GET', url, {}, '%d/a/%s/dv.json' % (shop_id, titleId))
    lst = []

    if not j:
        return lst

    for i in j:
        id = i['title_id'].upper()

        if not Titles.contains(id):
            Print.info('New DLC found: ' + id)

        title = Titles.get(id, None, None)
        title.setVersion(int(i['version']))

        lst.append(id)

    return lst
Esempio n. 16
0
File: Api.py Progetto: carlchina/nut
def getBannerImage(request, response):
    if len(request.bits) < 3:
        return Server.Response404(request, response)

    id = request.bits[2]

    if not Titles.contains(id):
        return Server.Response404(request, response)

    path = Titles.get(id).bannerFile()

    if not path:
        return Server.Response404(request, response)

    response.setMime(path)
    response.headers['Cache-Control'] = 'max-age=31536000'

    if os.path.isfile(path):
        with open(path, 'rb') as f:
            response.write(f.read())

    return Server.Response500(request, response)
Esempio n. 17
0
    def removeTitleRights(self):
        if not Titles.contains(self.titleId):
            raise IOError('No title key found in database! ' + self.titleId)

        ticket = self.ticket()
        masterKeyRev = ticket.getMasterKeyRevision()
        titleKeyDec = Keys.decryptTitleKey(
            ticket.getTitleKeyBlock().to_bytes(16, byteorder='big'),
            Keys.getMasterKeyIndex(masterKeyRev))
        rightsId = ticket.getRightsId()

        Print.info('rightsId =\t' + hex(rightsId))
        Print.info('titleKeyDec =\t' + str(hx(titleKeyDec)))
        Print.info('masterKeyRev =\t' + hex(masterKeyRev))

        for nca in self:
            if type(nca) == Nca:
                if nca.header.getCryptoType2() != masterKeyRev:
                    pass
                    raise IOError('Mismatched masterKeyRevs!')

        ticket.setRightsId(0)

        for nca in self:
            if type(nca) == Nca:
                if nca.header.getRightsId() == 0:
                    continue

                Print.info('writing masterKeyRev for %s, %d' %
                           (str(nca._path), masterKeyRev))
                crypto = aes128.AESECB(
                    Keys.keyAreaKey(Keys.getMasterKeyIndex(masterKeyRev),
                                    nca.header.keyIndex))

                encKeyBlock = crypto.encrypt(titleKeyDec * 4)
                nca.header.setRightsId(0)
                nca.header.setKeyBlock(encKeyBlock)
                Hex.dump(encKeyBlock)
Esempio n. 18
0
def getAddOns(titleId):
    url = 'https://superfly.hac.%s.d4c.nintendo.net/v1/a/%s/dv' % (
        Config.cdn.environment, titleId)
    j = makeJsonRequest('GET', url)
    lst = []

    if not j:
        return lst

    for i in j:
        id = i['title_id'].upper()

        if Titles.contains(id):
            Titles.get(id).setVersion(int(i['version']))
        else:
            Print.info('New DLC found: ' + id)
            title = Title.Title()
            title.setId(id)
            title.setVersion(int(i['version']))
            Titles.set(id, title)

        lst.append(id)

    return lst
Esempio n. 19
0
File: nut.py Progetto: ScuttleSE/nut
				key = bits[1].strip()
				version = bits[2].strip()
			else:
				print('invalid args: ' + download)
				continue

			if key == '':
				key = None

			if version == '':
				version = None

			if len(id) != 16:
				raise IOError('Invalid title id format')

			if Titles.contains(id):
				title = Titles.get(id)

				CDNSP.download_game(title.id.lower(), version or title.lastestVersion(), key or title.key, True, '', True)
			else:
				CDNSP.download_game(id.lower(), version or Title.getCdnVersion(id.lower()), key, True, '', True)
	
	if args.scan:
		initTitles()
		initFiles()
		scan()
		
	if args.refresh:
		refresh()
	
	if args.organize:
Esempio n. 20
0
 def getName(self):
     baseId = getBaseId(self.id)
     if self.isUpdate and Titles.contains(baseId):
         return Titles.get(baseId).name
     return self.name or ''
Esempio n. 21
0
def scrapeTitles(region='US', shop_id=4):
    Print.info('Scraping %s' % region)
    pageSize = 50
    offset = 0
    total = 1
    c = 0
    while offset < total:
        url = 'https://bugyo.hac.%s.eshop.nintendo.net/shogun/v1/titles?shop_id=%d&lang=%s&country=%s&sort=new&limit=%d&offset=%d' % (
            Config.cdn.environment, shop_id, countryLanguage(region), region,
            pageSize, offset)
        #print(url)
        j = makeJsonRequest(
            'GET', url, {}, '%d/%s/%s/titles/index/%d-%d.json' %
            (shop_id, countryLanguage(region), region, pageSize, offset))

        if not j:
            break

        total = int(j['total'])

        try:
            for i in j['contents']:
                title = Titles.getNsuid(i['id'])
                n = getTitleByNsuid(i['id'], region)

                if title:

                    for x in cdn.Superfly.getAddOns(title.id):
                        getNsuIds(x, 'aoc', region)

                    title.parseShogunJson(n)

                    rt = Title.Title()
                    rt.setId(title.id)
                    rt.setRegion(region)
                    rt.parseShogunJson(n)
                    Titles.set(title.id, rt, region)

                    scrapeDlc(i['id'], region)
                else:
                    try:
                        if n and len(n["applications"]) > 0:
                            titleId = n["applications"][0]["id"].upper()

                            for x in cdn.Superfly.getAddOns(titleId):
                                getNsuIds(x, 'aoc', region)

                            if titleId:
                                if Titles.contains(titleId):
                                    title = Titles.get(titleId)
                                    title.setId(titleId)
                                    title.parseShogunJson(n)
                                    #print('existing title found!')
                                else:
                                    title = Title.Title()
                                    title.setId(titleId)
                                    title.parseShogunJson(n)
                                    Titles.set(titleId, title)
                                    print('added new title %s %s' %
                                          (title.id, title.name))

                                rt = Title.Title()
                                rt.setId(titleId)
                                rt.setRegion(region)
                                rt.parseShogunJson(n)
                                Titles.set(titleId, rt, region)

                                scrapeDlc(i['id'], region)
                            else:
                                print('Could not get title json!')
                        else:
                            #print('no title id found in json!')
                            pass
                    except Exception as e:
                        #print(str(e))
                        pass

        except Exception as e:
            print(str(e))
            raise
            break

        offset = offset + len(j['contents'])

        #c = c + 1
        #if c % 100 == 0:
        #	Print.info('.')
        #	Titles.save()
    Titles.save()
Esempio n. 22
0
    def setMasterKeyRev(self, newMasterKeyRev):
        if not Titles.contains(self.titleId):
            raise IOError('No title key found in database! ' + self.titleId)

        ticket = self.ticket()
        masterKeyRev = ticket.getMasterKeyRevision()
        titleKey = ticket.getTitleKeyBlock()
        newTitleKey = Keys.changeTitleKeyMasterKey(
            titleKey.to_bytes(16, byteorder='big'),
            Keys.getMasterKeyIndex(masterKeyRev),
            Keys.getMasterKeyIndex(newMasterKeyRev))
        rightsId = ticket.getRightsId()

        if rightsId != 0:
            raise IOError('please remove titlerights first')

        if (newMasterKeyRev == None
                and rightsId == 0) or masterKeyRev == newMasterKeyRev:
            Print.info('Nothing to do')
            return

        Print.info('rightsId =\t' + hex(rightsId))
        Print.info('titleKey =\t' +
                   str(hx(titleKey.to_bytes(16, byteorder='big'))))
        Print.info('newTitleKey =\t' + str(hx(newTitleKey)))
        Print.info('masterKeyRev =\t' + hex(masterKeyRev))

        for nca in self:
            if type(nca) == Nca:
                if nca.header.getCryptoType2() != masterKeyRev:
                    pass
                    raise IOError('Mismatched masterKeyRevs!')

        ticket.setMasterKeyRevision(newMasterKeyRev)
        ticket.setRightsId((ticket.getRightsId()
                            & 0xFFFFFFFFFFFFFFFF0000000000000000) +
                           newMasterKeyRev)
        ticket.setTitleKeyBlock(int.from_bytes(newTitleKey, 'big'))

        for nca in self:
            if type(nca) == Nca:
                if nca.header.getCryptoType2() != newMasterKeyRev:
                    Print.info('writing masterKeyRev for %s, %d -> %s' %
                               (str(nca._path), nca.header.getCryptoType2(),
                                str(newMasterKeyRev)))

                    encKeyBlock = nca.header.getKeyBlock()

                    if sum(encKeyBlock) != 0:
                        key = Keys.keyAreaKey(
                            Keys.getMasterKeyIndex(masterKeyRev),
                            nca.header.keyIndex)
                        Print.info('decrypting with %s (%d, %d)' %
                                   (str(hx(key)),
                                    Keys.getMasterKeyIndex(masterKeyRev),
                                    nca.header.keyIndex))
                        crypto = aes128.AESECB(key)
                        decKeyBlock = crypto.decrypt(encKeyBlock)

                        key = Keys.keyAreaKey(
                            Keys.getMasterKeyIndex(newMasterKeyRev),
                            nca.header.keyIndex)
                        Print.info('encrypting with %s (%d, %d)' %
                                   (str(hx(key)),
                                    Keys.getMasterKeyIndex(newMasterKeyRev),
                                    nca.header.keyIndex))
                        crypto = aes128.AESECB(key)

                        reEncKeyBlock = crypto.encrypt(decKeyBlock)
                        nca.header.setKeyBlock(reEncKeyBlock)

                    if newMasterKeyRev >= 3:
                        nca.header.setCryptoType(2)
                        nca.header.setCryptoType2(newMasterKeyRev)
                    else:
                        nca.header.setCryptoType(newMasterKeyRev)
                        nca.header.setCryptoType2(0)
Esempio n. 23
0
 def isUnlockable(self):
     return (not self.hasValidTicket) and self.titleId and Titles.contains(
         self.titleId) and Titles.get(self.titleId).key
Esempio n. 24
0
def scrapeDlc(baseNsuid, region='US', shop_id=3):

    pageSize = 50
    offset = 0
    total = 1
    while offset < total:
        url = 'https://bugyo.hac.%s.eshop.nintendo.net/shogun/v1/titles/%d/aocs?shop_id=%d&lang=%s&country=%s' % (
            Config.cdn.environment, baseNsuid, shop_id,
            countryLanguage(region), region)
        #print(url)
        #exit(0)
        j = makeJsonRequest(
            'GET', url, {}, '%d/%s/%s/titles/aocs/%d.json' %
            (shop_id, countryLanguage(region), region, baseNsuid))

        if not j:
            break

        total = int(j['total'])

        if total == 0:
            break

        try:
            for i in j['contents']:
                title = Titles.getNsuid(i['id'])
                n = getDlcByNsuid(i['id'])

                if title:
                    title.parseShogunJson(n, region)

                    rt = Title.Title()
                    rt.setId(title.id)
                    rt.setRegion(region)
                    rt.parseShogunJson(n)
                    Titles.set(title.id, rt, region)

                else:
                    try:
                        if n and len(n["applications"]) > 0:
                            titleId = n["applications"][0]["id"].upper()
                            if titleId:
                                if Titles.contains(titleId):
                                    title = Titles.get(titleId)
                                    title.setId(titleId)
                                    title.parseShogunJson(n, region)
                                    #print('existing title found!')
                                else:
                                    title = Title.Title()
                                    title.setId(titleId)
                                    title.parseShogunJson(n, region)
                                    Titles.set(titleId, title)
                                    print('added new DLC %s %s' %
                                          (title.id, title.name))

                                rt = Title.Title()
                                rt.setId(titleId)
                                rt.setRegion(region)
                                rt.parseShogunJson(n, region)
                                Titles.set(titleId, rt, region)
                            else:
                                print('Could not get title json!')
                        else:
                            #print('no title id found in json!')
                            pass
                    except Exception as e:
                        #print(str(e))
                        pass

        except Exception as e:
            print(str(e))
            raise
            break

        offset = offset + len(j['contents'])
Esempio n. 25
0
 def getName(self):
     baseId = getBaseId(self.id)
     if hasattr(self,
                'isUpdate') and self.isUpdate and Titles.contains(baseId):
         return (Titles.get(baseId).name or '').replace('\n', ' ')
     return (self.name or '').replace('\n', ' ')
Esempio n. 26
0
 def getBaseName(self):
     baseId = getBaseId(self.id)
     if Titles.contains(baseId):
         return (Titles.get(baseId).name or '').replace('\n', ' ')
     return ''
Esempio n. 27
0
File: nut.py Progetto: carlchina/nut
						Hex.dump(buf)
						j.seek(0x28)
						#j.writeInt64(0)
						Print.info('min: ' + str(j.readInt64()))
				#f.flush()
				#f.close()
				'''

        if args.scrape_shogun:
            scrapeShogun()

        if args.scrape_title:
            initTitles()
            initFiles()

            if not Titles.contains(args.scrape_title):
                Print.error('Could not find title ' + args.scrape_title)
            else:
                Titles.get(args.scrape_title).scrape(False)
                Titles.save()
                #Print.info(repr(Titles.get(args.scrape_title).__dict__))
                pprint.pprint(Titles.get(args.scrape_title).__dict__)

        if args.scrape or args.scrape_delta:
            initTitles()
            initFiles()

            threads = []
            for i in range(scrapeThreads):
                t = threading.Thread(target=scrapeThread,
                                     args=[i, args.scrape_delta])