test
Tags: python
Published: 2023-11-23 01:32:11

# Imports
import asyncio
import cv2
import discord
import math
import numpy as np
import random
import requests
import tensorflow as tf

# Functions

def handle_spawn_event(client: discord.Client, model: tf.keras.Sequential, pokemon_list: list, image_url: str, message: discord.Message, typo_chance: int, loop) -> None:
    pokemon_name = predict_pokemon(model, pokemon_list, image_url)
    pokemon_name = pokemon_name.lower()

    client.awaitables.append((client, message, loop, pokemon_name, typo_chance))


def process_pending_actions(client: discord.Client) -> None:
    while True:
        if len(client.awaitables) > 0:
            for awaitable in client.awaitables:
                message = awaitable[1]
                loop = awaitable[2]
                name = awaitable[3]
                typofy_rate = awaitable[4]

                if random.randint(0, 100) < typofy_rate:
                    asyncio.run_coroutine_threadsafe(
                        typofied_catch(message, name), loop)

                else:
                    asyncio.run_coroutine_threadsafe(
                        catch(message, name), loop)

                client.awaitables.remove(awaitable)


def predict_pokemon(model: tf.keras.Sequential, pokemon_list: list, image_url: str) -> str:
    image_bytes = requests.get(image_url, stream=True).content
    original_image = cv2.imdecode(np.frombuffer(image_bytes, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
    
    resized_image = cv2.resize(original_image, (200, 125))
    resized_image = resized_image / 255.0
    resized_image = np.expand_dims(resized_image, axis=0)
    
    predictions = model.predict(resized_image)
    index = np.argmax(predictions, axis=1).tolist()[0]
    
    predicted_name = pokemon_list[index]
    print(predictions[0][index])
    return predicted_name


def get_neighboring_keys(key: str) -> str:
    neighboring_keys = []

    if key.strip() == "":
        neighboring_keys = ["z", "x", "c", "v", "b", "n", "m"]
    else:
        keyboard_rows = ' qwertyuiop[]\\', ' asdfghjkl;\' ', ' zxcvbnm,./ '
        indexes = []

        for row_idx, row in enumerate(keyboard_rows):
            if key in row:
                key_idx = row.find(key)
                indexes.append((row_idx, key_idx))

        row_index, key_index = indexes[0]

        if row_index:
            rows = keyboard_rows[row_index-1: row_index+2]
        else:
            rows = keyboard_rows[0: 2]

        for row in rows:
            for i in [-1, 0, 1]:
                if len(row) > key_index + i and row[key_index + i] != key and key_index + i >= 0:
                    neighboring_keys.append(row[key_index + i])

    return neighboring_keys


def introduce_typo(pokemon_name: str) -> str:
    typo_count = math.ceil(len(pokemon_name) * 12 / 100)
    prev_typo_position = None
    prev_typo_char = None

    characters = list(pokemon_name)

    iterations = 0
    while iterations < typo_count:
        iterations += 1

        typo_position = random.randint(0, len(characters) - 1)
        char_to_typo = characters[typo_position]

        if typo_position == 0:
            continue

        if typo_position == prev_typo_position:
            continue

        if char_to_typo == " " and prev_typo_char == " ":
            continue

        prev_typo_position = typo_position
        prev_typo_char = char_to_typo

        neighboring_chars = get_neighboring_keys(char_to_typo)
        typo_char = random.choice(neighboring_chars)

        characters[typo_position] = typo_char

    typo_name = "".join(characters)

    return typo_name


async def typofied_catch(message: discord.Message, pokemon_name: str) -> None:
    typo_name = introduce_typo(pokemon_name)
    catch_message = f"<@716390085896962058> c {typo_name}"

    try:
        msg = await message.channel.send(catch_message)
        catch_message = f"<@716390085896962058> c {pokemon_name}"

        await asyncio.sleep(1.2)
        await msg.edit(content=catch_message)
        await message.channel.trigger_typing()
    except discord.errors.HTTPException:
        print("[?] Can't keep up! Reduce the number of catching channels.")
        await asyncio.sleep(4)
        await message.channel.send(catch_message)
    
async def catch(message: discord.Message, name: str) -> None:
    catch_message = f"<@716390085896962058> c {name}"

    try:
        await message.channel.send(catch_message)
        await asyncio.sleep(0.2)
        await message.channel.trigger_typing()
    except discord.errors.HTTPException:
        print("[?] Can't keep up! Reduce the number of catching channels.")
        await asyncio.sleep(4)
        await message.channel.send(catch_message)