def getclasstagtitle(classes, tags): """Return a title desciribing a class/tag search""" all_classes = list(tf2api.getallclasses().keys()) classes_text = ', '.join(sorted(classes, key=all_classes.index)) tags_text = ', '.join(sorted(tags)).title() if len(classes) == 1 and len(tags) == 1: title = f'{classes_text} {tags_text}' elif classes and tags: title = f'{classes_text} × {tags_text}' elif classes: title = classes_text elif tags: title = tags_text return title
async def search(request, **kwargs): user = asyncio.ensure_future(getcurrentuser(request)) slug = kwargs.get('slug') is_json = kwargs.get('is_json', '') query = slug.replace('-', ' ') if slug else request.args.get('q') if not query: if is_json: return {'error': 'No query provided.'} return redirect('/') elif query == 'random': index = await store.srandmember('items:indexes') return redirect('/{}{}'.format(index, is_json)) itemnames = await store.hgetall('items:names') if query in itemnames: return redirect('/{}'.format(itemnames[query])) t0 = time.time() classes = set() tags = set() priceviz = False if query == 'all': items = store.Hashes( [getitemkey(k.decode()) for k in await store.sort('items')]) results = [tf2search.getsearchresult(items=items)] else: sources = ('backpack.tf', 'trade.tf') pricesource = request.cookies.get('price_source') if pricesource not in sources: pricesource = sources[0] items = { item['index']: item async for item in store.Hashes([ getitemkey(143), # Earbuds getitemkey(5021), # Key getitemkey(5002), # Refined getitemkey(5001), # Reclaimed getitemkey(5000), # Scrap getitemkey(0) # Weapon ]) } results = tf2search.visualizeprice(query, items, pricesource) input_ = tf2search.parseinput(query) classes = input_['classes'] tags = input_['tags'] if results is not None: if len(results) != 0: priceviz = True if not is_json: items = [] for item in results[0]['items']: items.extend([item['item']] * item['count']) results[0]['items'] = items elif classes or tags: results = await getresults(classes, tags) else: itemsdict = await store.SearchHashSet( 'items', getitemkey, ('index', 'name', 'image', 'classes', 'tags', 'marketprice'), int) itemsets = await store.get('items:sets') bundles = await store.get('items:bundles') results = tf2search.search(query, itemsdict, itemnames, itemsets, bundles, pricesource) for result in results: result['items'] = store.Hashes( [h.key for h in result['items']]) t1 = time.time() count = sum(len(result['items']) for result in results) all_classes = list(tf2api.getallclasses().keys()) classes_text = getlistastext(sorted(classes, key=all_classes.index)) tags_text = getlistastext(sorted(tags)) if query == 'all': description = f'A list of all {count:,} items in TF2.' elif classes and tags: description = ( f'A list of the {count:,} {tags_text} items for {classes_text}' ' in TF2.' ) elif classes: description = ( f'A list of the {count:,} items for {classes_text} in TF2.' ) elif tags: description = f'A list of the {count:,} {tags_text} items in TF2.' elif priceviz: from_, equals, to = results[0]['title'].partition(' = ') to = getlistastext(to.split(' + ')) description = (f'{from_} is the same as {to} in TF2.' if equals else f'A list of {from_} items in TF2.') elif results and ':' in results[0]['title']: title = results[0]['title'].replace(':', '') description = f'{count:,} {title} items in TF2.' else: description = f'Search results for "{query}" items in TF2.' qualities = defaultdict(set) user = await user if user: for item in user.get('backpack', {}).get('items', []): qualities[item['defindex']].add(item['quality']) if is_json: for result in results: result['items'] = [item async for item in result['items']] return tojson(results) else: return await render('search.html', query=query, description=description, results=results, qualities=qualities, count=count, time=round(t1 - t0, 3))
async def search(**kwargs): user = asyncio.ensure_future(getcurrentuser(request)) slug = kwargs.get('slug') is_json = kwargs.get('is_json', '') query = slug.replace('-', ' ') if slug else request.query.q if not query: if is_json: return {'error': 'No query provided.'} return redirect('/') elif query == 'random': index = await store.srandmember('items:indexes') return redirect('/{}{}'.format(index, is_json)) itemnames = await store.hgetall('items:names') if query in itemnames: return redirect('/{}'.format(itemnames[query])) t0 = time.time() classes = set() tags = set() priceviz = False if query == 'all': items = store.Hashes( [getitemkey(k.decode()) for k in await store.sort('items')]) results = [tf2search.getsearchresult(items=items)] else: sources = ('backpack.tf', 'trade.tf') pricesource = request.get_cookie('price_source') if pricesource not in sources: pricesource = sources[0] items = { item['index']: item async for item in store.Hashes([ getitemkey(143), # Earbuds getitemkey(5021), # Key getitemkey(5002), # Refined getitemkey(5001), # Reclaimed getitemkey(5000), # Scrap getitemkey(0) # Weapon ]) } results = tf2search.visualizeprice(query, items, pricesource) input_ = tf2search.parseinput(query) classes = input_['classes'] tags = input_['tags'] if results is not None: if len(results) != 0: priceviz = True if not is_json: items = [] for item in results[0]['items']: items.extend([item['item']] * item['count']) results[0]['items'] = items elif classes or tags: results = await getresults(classes, tags) else: itemsdict = await store.SearchHashSet( 'items', getitemkey, ('index', 'name', 'image', 'classes', 'tags', 'marketprice'), int) itemsets = await store.get('items:sets') bundles = await store.get('items:bundles') results = tf2search.search(query, itemsdict, itemnames, itemsets, bundles, pricesource) for result in results: result['items'] = store.Hashes( [h.key for h in result['items']]) t1 = time.time() count = sum(len(result['items']) for result in results) all_classes = list(tf2api.getallclasses().keys()) classes_text = getlistastext(sorted(classes, key=all_classes.index)) tags_text = getlistastext(sorted(tags)) if query == 'all': description = f'A list of all {count:,} items in TF2.' elif classes and tags: description = ( f'A list of the {count:,} {tags_text} items for {classes_text}' ' in TF2.') elif classes: description = ( f'A list of the {count:,} items for {classes_text} in TF2.') elif tags: description = f'A list of the {count:,} {tags_text} items in TF2.' elif priceviz: from_, equals, to = results[0]['title'].partition(' = ') to = getlistastext(to.split(' + ')) description = (f'{from_} is the same as {to} in TF2.' if equals else f'A list of {from_} items in TF2.') elif results and ':' in results[0]['title']: title = results[0]['title'].replace(':', '') description = f'{count:,} {title} items in TF2.' else: description = f'Search results for "{query}" items in TF2.' qualities = defaultdict(set) user = await user if user: for item in user.get('backpack', {}).get('items', []): qualities[item['defindex']].add(item['quality']) if is_json: for result in results: result['items'] = [item async for item in result['items']] return tojson(results) else: return await render('search.html', query=query, description=description, results=results, qualities=qualities, count=count, time=round(t1 - t0, 3))
def _parseblueprints(blueprints, itemsbyname): """Parse a dictionary of blueprint descriptions""" url = '/images/items/' localrepl = {'Any Class Token': 'class_token.png', 'Any Slot Token': 'slot_token.png', 'Any Token': 'token.png'} repl = {"Any Santa's Little Accomplice Weapon": "Santa's Little Accomplice Bundle", 'Any Primary Weapon': 'Rocket Launcher', 'Any Secondary Weapon': 'Pistol', 'Any Melee Weapon': 'Fire Axe', 'Any Spy Watch': 'Invis Watch', 'Any Hat': 'Modest Pile of Hat', 'Any Burned Item': 'Burned Banana Peel', 'Any Cursed Object': 'Voodoo-Cursed Object'} polyweps = ("The Gas Jockey's Gear", "The Saharan Spy", "The Tank Buster", "The Croc-o-Style Kit", "The Special Delivery") for class_ in tf2api.getallclasses(): repl['Any {} Weapon'.format(class_)] = '{} Starter Pack'.format(class_) for name in polyweps: repl['Any {} Weapon'.format(name)] = name for i in ('Victory', 'Moonman', 'Brainiac'): pack = "Dr. Grordbort's {} Pack".format(i) repl["Any {} Weapon".format(pack)] = pack blueprintsdict = defaultdict(list) for b in blueprints: required = blueprints[b][0] results = blueprints[b][1] for name in results: if name in itemsbyname: index = itemsbyname[name]['defindex'] chance = int(round(100.0 / len(results))) blueprintlist = [] for i in OrderedDict.fromkeys(required): blueprintdict = {} if i in localrepl: image = url + localrepl[i] elif i in repl: image = itemsbyname[repl[i]]['image_url'] elif i in itemsbyname: item = itemsbyname[i] image = item['image_url'] blueprintdict['index'] = item['defindex'] else: image = '/images/items/whatsthis.png' blueprintdict['name'] = i blueprintdict['image'] = image blueprintdict['count'] = required.count(i) blueprintlist.append(blueprintdict) blueprintsdict[index].append({'chance': chance, 'required': blueprintlist}) return blueprintsdict
def _getclass(word): """Parse a word and return TF2 class or alias if it matches one""" word = word.capitalize() for name, aliases in tf2api.getallclasses().items(): if word == name or word in aliases: return name
async def main(flush): store = await create_redis(('localhost', 6379), commands_factory=Redis) tf2info = await tf2search.gettf2info(config.apikey, config.backpackkey, config.tradekey, config.blueprintsfile) if flush: await store.delete('items') await store.delete_all('items:*') await store.delete_all('item:*') suggestions = [[], [], []] sitemap = Sitemap() sitemap.add(config.homepage) all_classes = [class_.lower() for class_ in tf2api.getallclasses()] all_tags = list(tf2api.getalltags()) all_qualities = [quality.replace("'", '').lower() for quality in tf2api.getallqualities().values()] keywords = all_classes + all_tags + all_qualities for keyword in keywords: sitemap.add(f'{config.homepage}/search/{keyword}') for class_tag in all_classes + all_tags: for quality in all_qualities: sitemap.add(f'{config.homepage}/search/{quality}-{class_tag}') for class_ in all_classes: for tag in all_tags: sitemap.add(f'{config.homepage}/search/{class_}-{tag}') for quality in all_qualities: sitemap.add( f'{config.homepage}/search/{quality}-{class_}-{tag}' ) for index in tf2info.items: pipe = store.pipeline() itemdict = tf2search.createitemdict(index, tf2info) name = itemdict['name'] pipe.hmset_dict(getitemkey(index), itemdict) pipe.sadd('items', index) classes = itemdict['classes'] tags = itemdict['tags'] if index == tf2info.itemsbyname[name]['defindex']: slug = slugify(name) pipe.hmset_dict('items:slugs', {slug: index}) if tf2search.isvalidresult(itemdict, False): if not classes: pipe.sadd(getclasskey(), index) if len(classes) > 1: pipe.sadd(getclasskey(multi=True), index) if not tags: pipe.sadd(gettagkey(), index) for class_ in classes: pipe.sadd(getclasskey(class_), index) for tag in tags: pipe.sadd(gettagkey(tag), index) if tf2search.isvalidresult(itemdict): pipe.sadd('items:indexes', index) pipe.hmset_dict('items:names', {name: index}) path = f'{config.homepage}/{slug}' suggestions[0].append(name) suggestions[1].append('{} - {}'.format( ', '.join(itemdict['classes']), ', '.join(itemdict['tags']))) suggestions[2].append(path) sitemap.add(path) await pipe.execute() await store.delete('items:new') for index in tf2info.newstoreprices: await store.sadd('items:new', index) bundles = {str(k): v for k, v in tf2info.bundles.items()} data = {'items:sets': tf2info.itemsets, 'items:bundles': bundles, 'items:suggestions': suggestions, 'items:lastupdated': time.time(), 'sitemap': sitemap.toxml()} await store.mset_dict(data)
async def main(flush): store = await create_redis(('localhost', 6379), commands_factory=Redis) tf2info = tf2search.gettf2info(config.apikey, config.backpackkey, config.tradekey, config.blueprintsfile) if flush: await store.delete('items') await store.delete_all('items:*') await store.delete_all('item:*') suggestions = [[], [], []] sitemap = Sitemap() sitemap.add(config.homepage) all_classes = [class_.lower() for class_ in tf2api.getallclasses()] all_tags = list(tf2api.getalltags()) all_qualities = [quality.replace("'", '').lower() for quality in tf2api.getallqualities().values()] keywords = all_classes + all_tags + all_qualities for keyword in keywords: sitemap.add(f'{config.homepage}/search/{keyword}') for class_tag in all_classes + all_tags: for quality in all_qualities: sitemap.add(f'{config.homepage}/search/{quality}-{class_tag}') for class_ in all_classes: for tag in all_tags: sitemap.add(f'{config.homepage}/search/{class_}-{tag}') for quality in all_qualities: sitemap.add( f'{config.homepage}/search/{quality}-{class_}-{tag}' ) for index in tf2info.items: pipe = store.pipeline() itemdict = tf2search.createitemdict(index, tf2info) name = itemdict['name'] pipe.hmset_dict(getitemkey(index), itemdict) pipe.sadd('items', index) classes = itemdict['classes'] tags = itemdict['tags'] if index == tf2info.itemsbyname[name]['defindex']: slug = slugify(name) pipe.hmset_dict('items:slugs', {slug: index}) if tf2search.isvalidresult(itemdict, False): if not classes: pipe.sadd(getclasskey(), index) if len(classes) > 1: pipe.sadd(getclasskey(multi=True), index) if not tags: pipe.sadd(gettagkey(), index) for class_ in classes: pipe.sadd(getclasskey(class_), index) for tag in tags: pipe.sadd(gettagkey(tag), index) if tf2search.isvalidresult(itemdict): pipe.sadd('items:indexes', index) pipe.hmset_dict('items:names', {name: index}) path = f'{config.homepage}/{slug}' suggestions[0].append(name) suggestions[1].append('{} - {}'.format( ', '.join(itemdict['classes']), ', '.join(itemdict['tags']))) suggestions[2].append(path) sitemap.add(path) await pipe.execute() await store.delete('items:new') for index in tf2info.newstoreprices: await store.sadd('items:new', index) bundles = {str(k): v for k, v in tf2info.bundles.items()} data = {'items:sets': tf2info.itemsets, 'items:bundles': bundles, 'items:suggestions': suggestions, 'items:lastupdated': time.time(), 'sitemap': sitemap.toxml()} await store.mset_dict(data)