Ejemplo n.º 1
0
async def translate(msg: Message) -> None:
    if len(msg.args) > 3:
        return

    word = utils.to_user_id(utils.remove_diacritics(msg.args[0]))
    if word == "":
        await msg.reply("Cosa devo tradurre?")
        return

    languages_list: list[int] = []
    for lang in msg.args[1:]:  # Get language ids from the command parameters
        languages_list.append(utils.get_language_id(lang))
    languages_list.append(msg.language_id)  # Add the room language
    languages_list.extend([9, 8])  # Hardcode english and italian as fallbacks

    # Get the first two unique languages
    languages = tuple(dict.fromkeys(languages_list))[:2]
    languages = cast(tuple[int, int], languages)

    results = _get_translations(word, languages)

    if results:
        if len(results) == 1:
            await msg.reply(" / ".join(sorted(list(results.values())[0])))
            return
        resultstext = ""
        for key, val in results.items():
            if resultstext != "":
                resultstext += ", "
            resultstext += f"{' / '.join(sorted(val))} ({key[0]})"
        await msg.reply(resultstext)
        return

    await msg.reply("Non trovato")
Ejemplo n.º 2
0
async def shitpost(msg: Message) -> None:
    if msg.room is None:
        return

    phrase = utils.remove_diacritics(msg.arg.strip())
    if len(phrase) > 50:
        await msg.reply("Testo troppo lungo")
        return

    text0 = ""
    text1 = ""
    text2 = ""

    if phrase == "":
        if not msg.room.is_private:
            return
        phrase = "SHITPOST"

    if not msg.room.is_private and ("x" in phrase or "X" in phrase):
        phrase = "lolno"

    for i in phrase:
        if i in LETTERS:
            if text0 != "":
                text0 += " "
                text1 += " "
                text2 += " "
            text0 += LETTERS[i][0]
            text1 += LETTERS[i][1]
            text2 += LETTERS[i][2]

    html = e.Pre(style="margin: 0; overflow-x: auto")
    html.add(text0 + e.Br() + text1 + e.Br() + text2)
    await msg.reply_htmlbox(html)
Ejemplo n.º 3
0
def _get_translations(
        word: str, languages: tuple[int,
                                    int]) -> dict[tuple[str, str], set[str]]:
    word = utils.to_user_id(utils.remove_diacritics(utils.get_alias(word)))

    results: dict[tuple[str, str], set[str]] = {}

    db = Database.open("veekun")

    with db.get_session() as session:

        tables: dict[str, tuple[type[v.TranslatableMixin],
                                type[TranslatableTableNames]]] = {
                                    "ability": (v.Abilities, v.AbilityNames),
                                    "item": (v.Items, v.ItemNames),
                                    "move": (v.Moves, v.MoveNames),
                                    "nature": (v.Natures, v.NatureNames),
                                }

        for category_name, t in tables.items():
            stmt = (select(t[0], t[1].local_language_id).select_from(
                t[0]).join(t[1]).where(
                    t[1].local_language_id.in_(languages),
                    t[1].name_normalized == word,
                ))
            # TODO: remove annotations
            row: v.TranslatableMixin
            language_id: int
            for row, language_id in session.execute(stmt):
                translation = row.get_translation(
                    f"{category_name}_names",
                    language_id=list(set(languages) - {language_id})[0],
                    fallback_english=False,
                )

                if translation is not None:
                    res = (
                        category_name,
                        utils.to_id(utils.remove_diacritics(translation)),
                    )
                    if res not in results:
                        results[res] = set()
                    results[res].add(translation)

    return results
Ejemplo n.º 4
0
async def encounters(msg: Message) -> None:
    if len(msg.args) < 1:
        return

    location_id = utils.to_id(utils.remove_diacritics(msg.args[0].lower()))

    language_id = msg.language_id
    if len(msg.args) >= 2:
        language_id = utils.get_language_id(msg.args[1], fallback=language_id)

    db = Database.open("veekun")

    with db.get_session(language_id) as session:

        stmt = (select(v.Locations).options(
            selectinload(v.Locations.location_areas).options(
                selectinload(v.LocationAreas.location_area_prose),
                selectinload(v.LocationAreas.encounters).options(
                    selectinload(v.Encounters.version).selectinload(
                        v.Versions.version_names),
                    selectinload(v.Encounters.pokemon).selectinload(
                        v.Pokemon.species).selectinload(
                            v.PokemonSpecies.pokemon_species_names),
                    selectinload(v.Encounters.encounter_slot).selectinload(
                        v.EncounterSlots.encounter_method).selectinload(
                            v.EncounterMethods.encounter_method_prose),
                    selectinload(v.Encounters.encounter_condition_value_map).
                    selectinload(v.EncounterConditionValueMap.
                                 encounter_condition_value).selectinload(
                                     v.EncounterConditionValues.
                                     encounter_condition_value_prose),
                ),
            )).filter_by(identifier=location_id))
        # TODO: remove annotation
        location: v.Locations | None = session.scalar(stmt)
        if location is None:
            await msg.reply("Location not found.")
            return

        results = Encounters()

        for area in location.location_areas:
            for encounter in area.encounters:
                results.add_encounter_slot(area, encounter)

        html = EncountersHTML(encounters_data=results)

        if not html:
            await msg.reply("No data available.")
            return

        await msg.reply_htmlbox(html.doc)
Ejemplo n.º 5
0
async def learnset(msg: Message) -> None:
    if len(msg.args) < 2:
        return

    pokemon_id = utils.to_id(utils.remove_diacritics(msg.args[0].lower()))
    version_id = utils.to_id(utils.remove_diacritics(msg.args[1].lower()))

    language_id = msg.language_id
    if len(msg.args) >= 3:
        language_id = utils.get_language_id(msg.args[2], fallback=language_id)

    db = Database.open("veekun")

    with db.get_session(language_id) as session:

        stmt = select(v.VersionGroups).filter_by(identifier=version_id)
        # TODO: remove annotation
        version_group: v.VersionGroups | None = session.scalar(stmt)

        if version_group is None:
            stmt = select(v.Versions).filter_by(identifier=version_id)
            # TODO: remove annotation
            version: v.Versions | None = session.scalar(stmt)
            if version is None:
                await msg.reply("Game version not found.")
                return
            version_group = version.version_group

        stmt = (select(v.PokemonSpecies).options(
            selectinload(v.PokemonSpecies.pokemon).selectinload(
                v.Pokemon.pokemon_moves.and_(
                    v.PokemonMoves.version_group_id == version_group.id)).
            options(
                selectinload(v.PokemonMoves.move).options(
                    selectinload(v.Moves.move_names),
                    selectinload(
                        v.Moves.machines.and_(
                            v.Machines.version_group_id ==
                            version_group.id)).selectinload(
                                v.Machines.item).selectinload(
                                    v.Items.item_names),
                ),
                selectinload(v.PokemonMoves.pokemon_move_method).selectinload(
                    v.PokemonMoveMethods.pokemon_move_method_prose),
            )).filter_by(identifier=pokemon_id))
        # TODO: remove annotation
        pokemon_species: v.PokemonSpecies | None = session.scalar(stmt)
        if pokemon_species is None:
            await msg.reply("Pokémon not found.")
            return

        results = Learnset()

        all_forms = set(pokemon_species.pokemon)

        for pokemon in pokemon_species.pokemon:
            for pokemon_move in pokemon.pokemon_moves:
                results.add_move(pokemon, pokemon_move)

        for method_data in results.methods.values():
            for move_data in method_data.moves.values():
                if move_data.forms == all_forms:
                    move_data.forms = set()
                else:
                    method_data.form_column = True

        html = LearnsetHTML(learnset_data=results)

        if not html:
            await msg.reply("No data available.")
            return

        await msg.reply_htmlbox(html.doc)
Ejemplo n.º 6
0
async def csv_to_sqlite(conn: Connection) -> None:
    latest_veekun_commit = ""
    try:
        latest_veekun_commit = (subprocess.run(
            [
                "git",
                "rev-list",
                "-1",
                "HEAD",
                "--",
                "data/veekun",
                "databases/veekun.py",
                "tasks/veekun.py",
            ],
            cwd=join(dirname(__file__), ".."),
            capture_output=True,
            check=True,
        ).stdout.decode().strip())
        db = Database.open("veekun")
        with db.get_session() as session:
            stmt = select(v.LatestCommit.commit_id)
            if session.scalar(stmt) == latest_veekun_commit:
                return  # database is already up-to-date, skip rebuild

    except (
            subprocess.SubprocessError,  # generic subprocess error
            FileNotFoundError,  # git is not available
            OperationalError,  # table does not exist
    ):
        pass  # always rebuild on error

    print("Rebuilding veekun database...")

    with open(utils.get_config_file("veekun.sqlite"),
              "wb"):  # truncate database
        pass

    db = Database.open("veekun")

    v.Base.metadata.create_all(db.engine)

    tables_classes = {
        obj.__tablename__: obj
        for name, obj in inspect.getmembers(v) if inspect.isclass(obj)
        and obj.__module__ == v.__name__ and hasattr(obj, "__tablename__")
    }

    with db.get_session() as session:
        if latest_veekun_commit:
            session.add(v.LatestCommit(commit_id=latest_veekun_commit))

        for table in v.Base.metadata.sorted_tables:
            tname = table.key
            file_name = utils.get_data_file("veekun", f"{tname}.csv")
            if isfile(file_name):
                with open(file_name, encoding="utf-8") as f:
                    csv_data = csv.DictReader(f)
                    csv_keys = csv_data.fieldnames

                    if csv_keys is not None:
                        data = [dict(i) for i in csv_data]

                        if hasattr(table.columns, "name_normalized"):
                            for row in data:
                                row["name_normalized"] = utils.to_user_id(
                                    utils.remove_diacritics(row["name"]))

                        if tname == "locations":
                            for row in data:
                                if num := re.search(r"route-(\d+)",
                                                    row["identifier"]):
                                    row["route_number"] = num[1]

                        bulk_insert_stmt = insert(tables_classes[tname])
                        session.execute(bulk_insert_stmt, data)

                        if "identifier" in csv_keys:
                            bulk_update_stmt = (update(
                                tables_classes[tname]).values(
                                    identifier=func.replace(
                                        tables_classes[tname].identifier, "-",
                                        "")).execution_options(
                                            synchronize_session=False))
                            session.execute(bulk_update_stmt)