def find_card(lrrbot, search, includehidden=False, game=CARD_GAME_MTG): cards = lrrbot.metadata.tables["cards"] card_multiverse = lrrbot.metadata.tables["card_multiverse"] card_collector = lrrbot.metadata.tables["card_collector"] if isinstance(search, int): query = (sqlalchemy.select([cards.c.name, cards.c.text]).select_from( card_multiverse.join( cards, cards.c.id == card_multiverse.c.cardid)).where( card_multiverse.c.id == search)) if not includehidden: query = query.where(cards.c.hidden == False) if game is not None: query = query.where(cards.c.game == game) with lrrbot.engine.begin() as conn: return conn.execute(query).fetchall() if isinstance(search, tuple): query = (sqlalchemy.select([cards.c.name, cards.c.text]).select_from( card_collector.join( cards, cards.c.id == card_collector.c.cardid)).where( (card_collector.c.setid == search[0].lower()) & (card_collector.c.collector == search[1]))) if not includehidden: query = query.where(cards.c.hidden == False) if game is not None: query = query.where(cards.c.game == game) with lrrbot.engine.begin() as conn: return conn.execute(query).fetchall() cleansearch = clean_text(search) with lrrbot.engine.begin() as conn: query = (sqlalchemy.select( [cards.c.name, cards.c.text]).where(cards.c.filteredname == cleansearch)) if not includehidden: query = query.where(cards.c.hidden == False) if game is not None: query = query.where(cards.c.game == game) rows = conn.execute(query).fetchall() if rows: return rows searchwords = search.split() searchwords = [clean_text(i) for i in searchwords] searchlike = "%" + "%".join( common.postgres.escape_like(i) for i in searchwords) + "%" query = (sqlalchemy.select([cards.c.name, cards.c.text]).where( cards.c.filteredname.like(searchlike))) if not includehidden: query = query.where(cards.c.hidden == False) if game is not None: query = query.where(cards.c.game == game) return conn.execute(query).fetchall()
def find_card(lrrbot, search, includehidden=False, game=CARD_GAME_MTG): cards = lrrbot.metadata.tables["cards"] card_multiverse = lrrbot.metadata.tables["card_multiverse"] card_collector = lrrbot.metadata.tables["card_collector"] if isinstance(search, int): query = (sqlalchemy.select([cards.c.name, cards.c.text]) .select_from(card_multiverse.join(cards, cards.c.id == card_multiverse.c.cardid)) .where(card_multiverse.c.id == search)) if not includehidden: query = query.where(cards.c.hidden == False) if game is not None: query = query.where(cards.c.game == game) with lrrbot.engine.begin() as conn: return conn.execute(query).fetchall() if isinstance(search, tuple): query = (sqlalchemy.select([cards.c.name, cards.c.text]) .select_from(card_collector.join(cards, cards.c.id == card_collector.c.cardid)) .where((card_collector.c.setid == search[0].lower()) & (card_collector.c.collector == search[1]))) if not includehidden: query = query.where(cards.c.hidden == False) if game is not None: query = query.where(cards.c.game == game) with lrrbot.engine.begin() as conn: return conn.execute(query).fetchall() cleansearch = clean_text(search) with lrrbot.engine.begin() as conn: query = (sqlalchemy.select([cards.c.name, cards.c.text]) .where(cards.c.filteredname == cleansearch)) if not includehidden: query = query.where(cards.c.hidden == False) if game is not None: query = query.where(cards.c.game == game) rows = conn.execute(query).fetchall() if rows: return rows searchwords = search.split() searchwords = [clean_text(i) for i in searchwords] searchlike = "%" + "%".join(common.postgres.escape_like(i) for i in searchwords) + "%" query = (sqlalchemy.select([cards.c.name, cards.c.text]) .where(cards.c.filteredname.like(searchlike))) if not includehidden: query = query.where(cards.c.hidden == False) if game is not None: query = query.where(cards.c.game == game) return conn.execute(query).fetchall()
def process_card(card, expansion, houses, include_reminder=False): # sanitise card name filtered = clean_text(card.get('internalname', card["card_title"])) if not re_check.match(filtered): print("Still some junk left in name %s (%s)" % (card.get( 'internalname', card["card_title"]), json.dumps(filtered))) print(json.dumps(card)) sys.exit(1) def build_description(): yield card['card_title'] yield ' [' if card.get('is_anomaly'): yield "Anomaly" elif card['house'] in houses: yield houses[card['house']]['name'] else: yield card['house'] if card.get('amber'): yield '\u2014' yield str(card['amber']) yield '<A>' yield '] | ' yield card['card_type'] if card.get('traits'): yield ' \u2014 ' yield card['traits'] if card['card_type'] == "Creature": yield ' [' yield str(card['power']) if card.get('armor'): yield '/' yield str(card['armor']) yield ']' if card.get('card_text'): yield ' | ' yield process_text(card['card_text'], include_reminder) desc = ''.join(build_description()) desc = re_multiplespaces.sub(' ', desc).strip() desc = utils.trim_length(desc) numbers = card['card_number'] if card.get('card_number') else [] if not isinstance(numbers, list): numbers = [numbers] numbers = [(expansion['code'].lower(), str(i)) for i in numbers] hidden = 'internalname' in card return filtered, card['card_title'], desc, numbers, hidden
def process_card(card, expansion, houses, include_reminder=False): # sanitise card name filtered = clean_text(card.get('internalname', card["card_title"])) if not re_check.match(filtered): print("Still some junk left in name %s (%s)" % (card.get('internalname', card["card_title"]), json.dumps(filtered))) print(json.dumps(card)) sys.exit(1) def build_description(): yield card['card_title'] yield ' [' if card['house'] in houses: yield houses[card['house']]['name'] else: yield card['house'] if card.get('amber'): yield '\u2014' yield str(card['amber']) yield '<A>' yield '] | ' yield card['card_type'] if card.get('traits'): yield ' \u2014 ' yield card['traits'] if card.get('power') or card.get('armor') or card['card_type'] == "Creature": yield ' [' yield str(card['power']) if card.get('armor'): yield '/' yield str(card['armor']) yield ']' if card.get('card_text'): yield ' | ' yield process_text(card['card_text'], include_reminder) desc = ''.join(build_description()) desc = re_multiplespaces.sub(' ', desc).strip() desc = utils.trim_length(desc) numbers = card['card_number'] if card.get('card_number') else [] if not isinstance(numbers, list): numbers = [numbers] numbers = [(expansion['code'].lower(), str(i)) for i in numbers] hidden = 'internalname' in card return filtered, card['card_title'], desc, numbers, hidden
def process_single_card(card, expansion, include_reminder=False): # sanitise card name filtered = clean_text(card.get('internalname', card["name"])) if not re_check.match(filtered): print("Still some junk left in name %s (%s)" % (card.get('internalname', card["name"]), json.dumps(filtered))) print(json.dumps(card)) sys.exit(1) def build_description(): yield card['name'] if 'manaCost' in card: yield ' [' yield re_mana.sub(r"\1", card['manaCost']) yield ']' if card.get('layout') == 'flip': if card['name'] == card['names'][0]: yield ' (flip: ' yield card['names'][1] yield ')' else: yield ' (unflip: ' yield card['names'][0] yield ')' elif card.get('layout') == 'transform': if card['name'] == card['names'][0]: yield ' (back: ' yield card['names'][1] yield ')' else: yield ' (front: ' yield card['names'][0] yield ')' elif card.get('layout') == 'meld': card_a, melded_card, card_b = card['names'] if card['name'] in (card_a, card_b): # mtgjson is inconsistent as to which of these is which # check if "melds with cardname" is in the card text if card['name'] == card_a: other_card = card_b else: other_card = card_a if '(Melds with %s.)' % other_card in card['text']: yield ' (melds with: ' yield other_card yield '; into: ' yield melded_card yield ')' else: # The names of what this melds with and into are in the rules text pass elif card['name'] == melded_card: yield ' (melds from: ' yield card_a yield '; ' yield card_b yield ')' yield ' | ' yield card.get('type', '?Type missing?') if 'power' in card or 'toughness' in card: yield ' [' yield card.get('power', '?') yield '/' yield card.get('toughness', '?') yield ']' if 'loyalty' in card: yield ' [' yield str(card['loyalty']) yield ']' if 'hand' in card or 'life' in card: yield ' [hand: ' if 'hand' in card: yield card['hand'] else: yield "?" yield ', life: ' if 'life' in card: yield card['life'] else: yield "?" yield ']' if 'text' in card: yield ' | ' yield process_text(card['text'], include_reminder) desc = ''.join(build_description()) desc = re_multiplespaces.sub(' ', desc).strip() desc = utils.trim_length(desc) if card.get('layout') == 'flip' and card['name'] != card['names'][0]: multiverseids = numbers = [] else: if card.get('layout') == 'transform': if card['name'] == card['names'][0]: if card.get('number') and 'a' not in card[ 'number'] and 'b' not in card['number']: card['number'] = [card['number'], card['number'] + 'a'] else: if card.get('number') and 'a' not in card[ 'number'] and 'b' not in card['number']: card['number'] = card['number'] + 'b' card['foreignData'] = [ ] # mtgjson doesn't seem to have accurate foreign multiverse ids for back faces multiverseids = [card['multiverseId'] ] if card.get('multiverseId') else [] # disabling adding foreign multiverse ids unless we decide we want them for some reason # they add a lot of time to the running of this script #for lang in card.get('foreignData', []): # if lang.get('multiverseId'): # multiverseids.append(lang['multiverseId']) numbers = card['number'] if card.get('number') else [] if not isinstance(numbers, list): numbers = [numbers] hidden = 'internalname' in card # if a card has multiple variants, make "number" entries for the variants # to match what sort of thing we'd be seeing on scryfall if len(multiverseids) > 1 and len(numbers) == 1: orig_number = numbers[0] for i in range(len(multiverseids)): numbers.append(orig_number + chr(ord('a') + i)) numbers = [(expansion['code'].lower(), i) for i in numbers] return filtered, card['name'], desc, multiverseids, numbers, hidden
async def cardviewer_announce(session): if not flask.request.is_json: return flask.jsonify(message="Request not JSON"), 400 req = flask.request.get_json() log.debug("Received cardviewer: %r", req) cards = server.db.metadata.tables['cards'] card_multiverse = server.db.metadata.tables['card_multiverse'] try: game = CARD_GAME_CODE_MAPPING[req.get('game', 'mtg')] except KeyError: return flask.jsonify(message="Unrecognised game code"), 400 query = sqlalchemy.select([cards.c.id, cards.c.name, cards.c.text]).where(cards.c.game == game) if 'multiverseid' in req: query = query.select_from(cards.join(card_multiverse)).where( card_multiverse.c.id == req['multiverseid']) elif 'name' in req: name = card.to_query(req['name']) exact = card.clean_text(req['name']) hidden = False if 'variant' in req: name += escape_like("_" + req['variant']) exact += "_" + req['variant'] hidden = True exact_query = sqlalchemy.exists().where(cards.c.filteredname == exact) if not hidden: exact_query = exact_query.where(~cards.c.hidden) query = query.where((exact_query & (cards.c.filteredname == exact)) | (~exact_query & cards.c.filteredname.ilike(name))) if not hidden: query = query.where(~cards.c.hidden) elif 'host' in req or 'augment' in req: name = "" if 'augment' in req: name += card.to_query(req['augment']) + escape_like("_aug") if 'host' in req: name += ("_" if name != "" else "") + card.to_query( req['host']) + escape_like("_host") query = query.where(cards.c.filteredname.ilike(name)) else: return flask.jsonify(message=""), 400 with server.db.engine.begin() as conn: cards = conn.execute(query).fetchall() if len(cards) == 0: return flask.jsonify(message="No such card"), 400 elif len(cards) > 1: return flask.jsonify(message="Matched multiple cards"), 400 card_id, name, text = cards[0] await common.rpc.bot.cardviewer.announce(card_id) return flask.jsonify( name=name, text=text, )
def process_single_card(card, expansion, include_reminder=False): # sanitise card name filtered = clean_text(card.get('internalname', card["name"])) if not re_check.match(filtered): print("Still some junk left in name %s (%s)" % (card.get('internalname', card["name"]), json.dumps(filtered))) print(json.dumps(card)) sys.exit(1) def build_description(): yield card['name'] if 'manaCost' in card: yield ' [' yield re_mana.sub(r"\1", card['manaCost']) yield ']' if card.get('layout') == 'flip': if card['name'] == card['names'][0]: yield ' (flip: ' yield card['names'][1] yield ')' else: yield ' (unflip: ' yield card['names'][0] yield ')' elif card.get('layout') == 'transform': if card['name'] == card['names'][0]: yield ' (back: ' yield card['names'][1] yield ')' else: yield ' (front: ' yield card['names'][0] yield ')' elif card.get('layout') == 'meld': card_a, melded_card, card_b = card['names'] if card['name'] in (card_a, card_b): # mtgjson is inconsistent as to which of these is which # check if "melds with cardname" is in the card text if card['name'] == card_a: other_card = card_b else: other_card = card_a if '(Melds with %s.)' % other_card in card['text']: yield ' (melds with: ' yield other_card yield '; into: ' yield melded_card yield ')' else: # The names of what this melds with and into are in the rules text pass elif card['name'] == melded_card: yield ' (melds from: ' yield card_a yield '; ' yield card_b yield ')' yield ' | ' yield card.get('type', '?Type missing?') if 'power' in card or 'toughness' in card: yield ' [' yield card.get('power', '?') yield '/' yield card.get('toughness', '?') yield ']' if 'loyalty' in card: yield ' [' yield str(card['loyalty']) yield ']' if 'hand' in card or 'life' in card: yield ' [hand: ' if 'hand' in card: yield card['hand'] else: yield "?" yield ', life: ' if 'life' in card: yield card['life'] else: yield "?" yield ']' if 'text' in card: yield ' | ' yield process_text(card['text'], include_reminder) desc = ''.join(build_description()) desc = re_multiplespaces.sub(' ', desc).strip() desc = utils.trim_length(desc) if card.get('layout') == 'flip' and card['name'] != card['names'][0]: multiverseids = numbers = [] else: if card.get('layout') == 'transform': if card['name'] == card['names'][0]: if card.get('number') and 'a' not in card['number'] and 'b' not in card['number']: card['number'] = [card['number'], card['number'] + 'a'] else: if card.get('number') and 'a' not in card['number'] and 'b' not in card['number']: card['number'] = card['number'] + 'b' card['foreignData'] = [] # mtgjson doesn't seem to have accurate foreign multiverse ids for back faces multiverseids = [card['multiverseId']] if card.get('multiverseId') else [] # disabling adding foreign multiverse ids unless we decide we want them for some reason # they add a lot of time to the running of this script #for lang in card.get('foreignData', []): # if lang.get('multiverseId'): # multiverseids.append(lang['multiverseId']) numbers = card['number'] if card.get('number') else [] if not isinstance(numbers, list): numbers = [numbers] hidden = 'internalname' in card # if a card has multiple variants, make "number" entries for the variants # to match what sort of thing we'd be seeing on scryfall if len(multiverseids) > 1 and len(numbers) == 1: orig_number = numbers[0] for i in range(len(multiverseids)): numbers.append(orig_number + chr(ord('a') + i)) numbers = [(expansion['code'].lower(), i) for i in numbers] return filtered, card['name'], desc, multiverseids, numbers, hidden
async def cardviewer_announce(session): if not flask.request.is_json: return flask.jsonify(message="Request not JSON"), 400 req = flask.request.get_json() log.debug("Received cardviewer: %r", req) cards = server.db.metadata.tables['cards'] card_multiverse = server.db.metadata.tables['card_multiverse'] try: game = CARD_GAME_CODE_MAPPING[req.get('game', 'mtg')] except KeyError: return flask.jsonify(message="Unrecognised game code"), 400 query = sqlalchemy.select([cards.c.id, cards.c.name, cards.c.text]).where(cards.c.game == game) if 'multiverseid' in req: query = query.select_from(cards.join(card_multiverse)).where(card_multiverse.c.id == req['multiverseid']) elif 'name' in req: name = card.to_query(req['name']) exact = card.clean_text(req['name']) hidden = False if 'variant' in req: name += escape_like("_" + req['variant']) exact += "_" + req['variant'] hidden = True exact_query = sqlalchemy.exists().where(cards.c.filteredname == exact) if not hidden: exact_query = exact_query.where(~cards.c.hidden) query = query.where( (exact_query & (cards.c.filteredname == exact)) | (~exact_query & cards.c.filteredname.ilike(name))) if not hidden: query = query.where(~cards.c.hidden) elif 'host' in req or 'augment' in req: name = "" if 'augment' in req: name += card.to_query(req['augment']) + escape_like("_aug") if 'host' in req: name += ("_" if name != "" else "") + card.to_query(req['host']) + escape_like("_host") query = query.where(cards.c.filteredname.ilike(name)) else: return flask.jsonify(message=""), 400 with server.db.engine.begin() as conn: cards = conn.execute(query).fetchall() if len(cards) == 0: return flask.jsonify(message="No such card"), 400 elif len(cards) > 1: return flask.jsonify(message="Matched multiple cards"), 400 card_id, name, text = cards[0] await common.rpc.bot.cardviewer.announce(card_id) return flask.jsonify( name=name, text=text, )