예제 #1
0
def add_new_account(user_id):
    """Add new points accounts to database.

    Args:
        user_id (int): The ID of the user

    Returns:
        None: If account wasn't created previously
        bool: True if account was restored, False if account is already added
    """
    account_status = check_account(user_id)
    if account_status:
        return False
    if account_status is None:
        database.modify_data(
            "pointsDB",
            'INSERT INTO points_accounts VALUES (?, ?, 0, "", 0)',
            user_id,
            DEFAULT_BALANCE,
        )
        return None
    database.modify_data(
        "pointsDB",
        "UPDATE points_accounts SET is_deleted = 0 WHERE user_id = ?",
        user_id,
    )
    return True
예제 #2
0
def remove_bot_config():
    """Delete bot from database.

    This function handles bot removal from database and that's it.
    (Did you expect to see rocket launch codes here?)
    """
    bots_db_status = check_bots_database()
    if not bots_db_status:
        print("\nThere are no bots in database. "
              "Aborting removing process...\n")
        time.sleep(0.5)
        return
    if bots_db_status == 1:
        print("\nThere is one bot in database.\n"
              "Are you sure you want to remove last bot there? (y/N)")
        while True:
            confirmation = get_user_input().lower()
            if confirmation in ["", "n", "y"]:
                break
            print("You have chosen something wrong, please try again\n")
    if confirmation == "y":
        if not (bot_name := is_bot_in_database()):
            return
        database.modify_data("confDB", "DELETE FROM tokens WHERE bot_name = ?",
                             bot_name)
        print(
            f'\nBot "{bot_name}" has been found and deleted from the database!\n'
        )
예제 #3
0
def manage_r_words_tables(word, table, delete_mode=False):
    """Manage russian roulette word base.

    Args:
        word (str): Word to add or remove
        table (str): Table to modify
        delete_mode (bool): Trigger for delete mode
        If set to True, words will be deleted from table,
        otherwise - words will be added

    Returns:
        str: Function completion message or warning
    """
    requested_word = database.get_data(
        "wordsDB", True,
        f"SELECT * FROM roulette_{table}_words WHERE words = ?", word)
    if not delete_mode:
        if not requested_word:
            database.modify_data(
                "wordsDB", f"INSERT INTO roulette_{table}_words VALUES (?)",
                word)
            return f'Хей, я успешно добавил слово "{word}" себе в базу!'
        return "Данное слово уже есть в базе данных, попробуйте добавить другое"
    if requested_word:
        database.modify_data(
            "wordsDB", f"DELETE FROM roulette_{table}_words WHERE words = ?",
            word)
        return f'Хей, я успешно удалил слово "{word}" из своей базы!'
    return "Ой, я не смог найти это слово. Убедитесь в правильности написания!"
예제 #4
0
def add_bot_config():
    """Add bot configuration into the database.

    This function require bot's name and token to add this to the database.
    If initial setup was completed, also redirects to main menu of setup only
    """
    current_status = get_curr_setup_status()
    bot_name = get_user_input("\nEnter name of your Discord bot: ")
    if not current_status:
        print("\nEnter your Discord bot token\n"
              "(If you don't know where to get it, "
              f"go to this page - {WIKI_LINK})")
    else:
        if database.get_data("confDB", True,
                             "SELECT * FROM tokens WHERE bot_name = ?",
                             bot_name):
            print("A bot with the same name is already in the database!"
                  "\nCancel adding ...\n")
        print("\nEnter your Discord bot token")
    while True:
        bot_token = get_user_input()
        if len(bot_token) == 59:
            break
        print("\nIt looks like your token is wrong.\n"
              "It must be 59 characters long "
              f"(Yours is {len(bot_token)} characters long)")
    database.modify_data("confDB", "INSERT INTO tokens VALUES (?, ?)",
                         bot_name, bot_token)
    print(f'\nGreat, I added bot "{bot_name}" to the database!')
    if current_status:
        print("")
    time.sleep(0.5)
예제 #5
0
    async def __reset_ship(self, ctx, notif=True):
        """Reset latest ship results to start over.

        This function resets results of shipping to allow user execute
        new ship function

        Args:
            ctx (commands.context.Context): Context object to execute functions
            notif (bool): Controls sending message about resetting results
        """
        database.modify_data(
            "mainDB",
            "UPDATE variables SET ship_date = ?, ship_text_short = ?, "
            "ship_text_full = ?, ship_activated = ?",
            "",
            "",
            "",
            0,
        )
        if notif:
            await ctx.reply(
                "Результаты шиппинга сброшены! "
                "*(Вы разлучили, возможно, великолепную парочку!)*",
                delete_after=self.delete_time,
            )
            await asyncio.sleep(self.delete_time)
            await ctx.message.delete()
예제 #6
0
    def __manage_rsp_state(lock_state=False):
        """Lock or Unlock RSP game in database.

        This function locks/unlocks RSP game in database, so that only one game can be
        executed at a time.
        """
        database.modify_data("mainDB",
                             "UPDATE variables SET rsp_game_active = ?",
                             1 if lock_state else 0)
예제 #7
0
    async def __remove_admin(self, ctx, user_id):
        """Remove user's ID from admin list.

        This function handles removal of user's ID from admin list.

        **Noteworthy:** Since this list is very important for the bot's operation,
        several checks have been added here: if the list consists of one ID,
        it cancels the deletion, if the admin wants to delete himself,
        he is asked to confirm the action

        Args:
            ctx (commands.context.Context): Context object to execute functions
            user_id (str): User's ID to remove from admins
        """
        if int(user_id) == ctx.author.id and users.is_user_admin(user_id):
            if (len(
                    database.get_data(
                        "mainDB", False,
                        "SELECT admins_id FROM admin_list")) == 1):
                await ctx.reply("Вы единственный админ бота. "
                                "Управление ботом будет затруднено, "
                                "если список админов будет пуст, "
                                "поэтому я отменяю удаление")
            else:
                ask_msg = await ctx.reply("Вы уверены что хотите убрать себя?"
                                          " (Да/Нет)")
                try:
                    wait_msg = await self.client.wait_for("message",
                                                          timeout=15)
                except asyncio.TimeoutError:
                    await ask_msg.edit(
                        content="Похоже вы не решились с выбором. "
                        "Я отменил удаление вас из списка")
                else:
                    if wait_msg.content.lower() in ["да", "ок", "давай"]:
                        database.modify_data(
                            "mainDB",
                            "DELETE FROM admin_list WHERE admins_id = ?",
                            user_id,
                        )
                        await ask_msg.edit(content="Я удалил вас из админов :("
                                           )
                    elif wait_msg.content.lower() in ["не", "нет", "неа"]:
                        await ask_msg.edit(content="Удаление было отменено")
                    else:
                        await ask_msg.edit(content="Вы ответили как-то иначе, "
                                           "удаление было отменено")
        else:
            if not users.is_user_admin(user_id):
                await ctx.reply("Данный пользователь не является админом")
            else:
                database.modify_data(
                    "mainDB", "DELETE FROM admin_list WHERE admins_id = ?",
                    user_id)
                await ctx.reply("Я успешно удалил такого админа")
예제 #8
0
def message_words_to_db(words):
    """Add content of regular messages to database.

    This function takes array of words from message and adds them
    to special table for Markov chains

    Args:
        words (list): Array of words from message contents
    """
    for word in words:
        database.modify_data("wordsDB", "INSERT INTO markov_words VALUES (?)",
                             word)
예제 #9
0
    def __change_game_status(ctx, game_status):
        """Change game status value in DB.

        Args:
            ctx (commands.context.Context): Context object to execute functions
            game_status (int): New game status value
        """
        database.modify_data(
            "pointsDB",
            "UPDATE points_accounts SET active_roulette = ? WHERE user_id = ?",
            game_status,
            ctx.author.id,
        )
예제 #10
0
def clear_words_table():
    """Clear words tables in database.

    This function handles deleting all data
    of selected words tables in the database

    Because of possible SQL injection, loop for tables list
    was removed
    """
    database.modify_data(
        "wordsDB",
        "DELETE FROM main_words_base; DELETE FROM roulette_lose_words; "
        "DELETE FROM roulette_win_words; DELETE FROM roulette_zero_words",
    )
예제 #11
0
    async def __add_admin(self, ctx, user_id):
        """Add user's ID to admin list.

        This function handles addition of user's ID to admin list.

        Args:
            ctx (commands.context.Context): Context object to execute functions
            user_id (str): User's ID to add as an admin
        """
        if users.is_user_admin(user_id):
            await ctx.reply("Данный пользователь уже админ")
            return
        database.modify_data("mainDB", "INSERT INTO admin_list VALUES (?)",
                             user_id)
        await ctx.reply("Я успешно добавил такого админа")
예제 #12
0
def select_bot_config():
    """Select main bot to run.

    This function allows user to select the desired bot to run
    when main script starts up
    """
    list_of_bots = database.get_data("confDB", False,
                                     "SELECT bot_name FROM tokens")
    curr_selected_bot = database.get_data(
        "mainDB", True, "SELECT current_selected_bot FROM variables")
    bots_count = 0
    if not list_of_bots:
        print(
            "\nIt looks like there are no bots in my list, try adding a new one\n"
        )
    elif len(list_of_bots) == 1:
        print("\nSince you haven't added any more bots, "
              f'your only active bot is "{list_of_bots[curr_selected_bot]}"\n')
    else:
        print("\nAt the moment, the selected bot is "
              f'"{list_of_bots[curr_selected_bot]}"')
        print("Here are all the added bots:")
        for bot_name in list_of_bots:
            bots_count += 1
            print(f"{bots_count}. {bot_name}")
        print("0. Exit")
        while True:
            select_bot = get_user_input("\nEnter the number of option:")
            if select_bot == "0":
                print("\nExiting to main menu\n")
                break
            try:
                index_of_bot = int(select_bot) - 1
                selected_bot = list_of_bots[index_of_bot]
                if index_of_bot in range(len(list_of_bots)):
                    print("\nGreat choice! "
                          f'Selecting "{selected_bot}" as default...\n')
                    database.modify_data(
                        "mainDB",
                        "UPDATE variables SET current_selected_bot = ?",
                        index_of_bot,
                    )
                    break
                print("Invalid number of option. Please, try again")
            except ValueError:
                print("\nIt looks like you entered not a number. "
                      "Please, try again")
    time.sleep(0.5)
예제 #13
0
    async def __remove_ignored(self, ctx, user_id):
        """Remove user's ID from ignore list.

        This function handles removal of user's ID from ignore list

        Args:
            ctx (commands.context.Context): Context object to execute functions
            user_id (str): User's ID to unban
        """
        if not users.is_user_blocked(user_id):
            await ctx.reply("Данный юзер уже разблокирован")
        else:
            database.modify_data(
                "mainDB", "DELETE FROM block_list WHERE blocked_id = ?",
                user_id)
            await ctx.reply("Я успешно разблокировал этого юзера")
예제 #14
0
def change_bot_name(bot_name):
    """Handle name changing of bot.

    Args:
        bot_name (str): Current name of bot
    """
    new_bot_name = get_user_input("\nEnter new bot's name:")
    bot_info = database.get_data("confDB", False,
                                 "SELECT * FROM tokens WHERE bot_name = ?",
                                 bot_name)
    database.modify_data(
        "confDB",
        "UPDATE tokens SET bot_name = ?, bot_token = ?",
        new_bot_name,
        bot_info[1],
    )
    print(f'\nGreat, I changed name from "{bot_name}" to "{new_bot_name}"\n')
예제 #15
0
    async def __add_ignored(self, ctx, user_id):
        """Add user's ID to blacklist.

        This function handles addition of user's ID to ignore list

        Args:
            ctx (commands.context.Context): Context object to execute functions
            user_id (str): User's ID to ban
        """
        if users.is_user_admin(user_id):
            await ctx.reply("Я не могу заблокировать админа...")
        else:
            if users.is_user_blocked(user_id):
                await ctx.reply("Данный пользователь уже заблокирован")
            else:
                database.modify_data("mainDB",
                                     "INSERT INTO block_list VALUES (?)",
                                     user_id)
                await ctx.reply("Я успешно заблокировал этого юзера")
예제 #16
0
def change_setup_status():
    """Edit current setup status.

    This function changes setup status to 0, when it needs to be reset
    or set to 1, when initial setup was completed
    """
    current_status = get_curr_setup_status()
    database.modify_data(
        "mainDB",
        "UPDATE variables SET is_setup_completed = ?",
        1 if not current_status else 0,
    )
    if current_status:
        database.reset_bot_tables()
        print("\nThe bot's settings have been reset. "
              "Restart the script for initial setup")
        sys.exit()
    print("The initial setup of the bot has been completed. "
          'To enable bot, run "python main.py"')
    sys.exit()
예제 #17
0
def delete_account(user_id):
    """Remove active points account from database.

    Args:
        user_id (int): The ID of the user

    Returns:
        bool: True if account was deleted, False if account was already deleted
    """
    account_status = check_account(user_id)
    if not account_status:
        return False
    database.modify_data(
        "pointsDB",
        "UPDATE points_accounts SET points_balance = ?, "
        "is_deleted = 1 WHERE user_id = ?",
        ZERO_BALANCE,
        user_id,
    )
    return True
예제 #18
0
def add_points(user_id, points, skip_check=False):
    """Add points to user points account.

    Args:
        user_id (int): The ID of the user
        points (int): The amount of points to add
        skip_check (bool): Skip checking if check was already done
    """
    if not skip_check:
        account_status = check_account(user_id)
        if not account_status:
            return False
    database.modify_data(
        "pointsDB",
        "UPDATE points_accounts "
        "SET points_balance = points_balance + ? WHERE user_id = ?",
        points,
        user_id,
    )
    return True
예제 #19
0
def add_member_to_db(member_id):
    """Add member to database.

    Used for adding members on startup or when member is getting
    on the server

    Args:
        member_id (int): ID of member to add
    """
    return database.modify_data("mainDB", "INSERT INTO users VALUES (?)",
                                member_id)
예제 #20
0
def add_bot_to_db(bot_id):
    """Add bot to database.

    Used for adding bots on startup or when member is getting
    on the server (For some ignore purposes)

    Args:
        bot_id (int): ID of bot to add
    """
    return database.modify_data("mainDB", "INSERT INTO bots VALUES (?)",
                                bot_id)
예제 #21
0
    async def __manage_ship_ignore(self, ctx, user_id, mode):
        """Manage ignore list of shipping users.

        This function helps users to opt out of shipping or
        opt in.

        Args:
            ctx (commands.context.Context): Context object to execute functions
            user_id (int): ID of user to ignore/add
            mode (str): Mode of operation with ignore list
        """
        user_state = database.get_data(
            "mainDB", True, "SELECT * FROM ignored_users WHERE users_id = ?",
            user_id)
        if mode == "выйти":
            if user_state is None:
                database.modify_data("mainDB",
                                     "INSERT INTO ignored_users VALUES (?)",
                                     user_id)
                database.modify_data("mainDB",
                                     "DELETE FROM users WHERE users_id = ?",
                                     user_id)
                await ctx.reply(
                    "Вы были убраны из списка участников шиппинга!",
                    delete_after=self.delete_time,
                )
                await asyncio.sleep(self.delete_time)
                await ctx.message.delete()
                return
            await ctx.reply("Вы не учавствуете в шиппинге!",
                            delete_after=self.delete_time)
            await asyncio.sleep(self.delete_time)
            await ctx.message.delete()
            return
        if user_state is not None:
            database.modify_data(
                "mainDB", "DELETE FROM ignored_users WHERE users_id = ?",
                user_id)
            database.modify_data("mainDB", "INSERT INTO users VALUES (?)",
                                 user_id)
            await ctx.reply(
                "Вы были добавлены в список участников шиппинга!",
                delete_after=self.delete_time,
            )
            await asyncio.sleep(self.delete_time)
            await ctx.message.delete()
            return
        await ctx.reply("Вы уже учавствуете в шиппинге!",
                        delete_after=self.delete_time)
        await asyncio.sleep(self.delete_time)
        await ctx.message.delete()
예제 #22
0
def change_bot_token(bot_name):
    """Handle token changing of bot.

    Args:
        bot_name (str): Name of bot to modify
    """
    print("\nEnter new bot's token:")
    while True:
        new_bot_token = get_user_input()
        if len(new_bot_token) == 59:
            break
        print("\nIt looks like your token is wrong.\n"
              "It must be 59 characters long "
              f"(Yours is {len(new_bot_token)} characters long)")
    database.modify_data(
        "confDB",
        "UPDATE tokens SET bot_name = ?, bot_token = ?",
        bot_name,
        new_bot_token,
    )
    print(f'\nGreat, I changed token of "{bot_name}" to a new one!\n')
예제 #23
0
async def on_ready():
    """Execute necessary functions.

    This function executes certain actions on bot's load, such as:
        - Resetting DB table and delay of randomly generated Markov message
        - Loading commands
        - Updating table with users
        - Changing bot's status and avatar
        - Setting up new bot's uptime
    """
    database.clear_tables()
    markov_utils.markov_delay_handler("clear")
    await client.change_presence(status=discord.Status.dnd)
    avatar_data = avatar_changer.get_avatar_bytes()
    if avatar_data["avatar_bytes"]:
        await client.user.edit(avatar=avatar_data["avatar_bytes"])
    await general_scripts.load_commands(client)
    await general_scripts.update_member_list(client)
    database.modify_data("mainDB", "UPDATE variables SET bot_uptime = ?",
                         int(time.time()))
    print(f"Successfully logged in as {client.user}!")
예제 #24
0
def get_avatar_bytes(avatar_cooldown=None):
    """Get bytes from avatar picture.

    This function has built-in check for
    avatar change cooldown

    Args:
        avatar_cooldown (Union[int, None]): Cooldown for setting new avatar

    Returns:
        Union[int, list[bytes, int]]:
        Current cooldown time or bytes of PNG w/ new cooldown time
    """
    if not avatar_cooldown:
        avatar_cooldown = database.get_data(
            "mainDB",
            True,
            "SELECT avatar_cooldown FROM variables",
        )
    curr_time = int(time.time())
    curr_cooldown = avatar_cooldown - curr_time
    if curr_cooldown > 0:
        return {
            "avatar_cooldown": avatar_cooldown,
            "curr_cooldown": int(curr_cooldown),
            "avatar_bytes": None,
        }
    new_avatar_cooldown = curr_time + avatar_cooldown
    database.modify_data("mainDB", "UPDATE variables SET avatar_cooldown = ?",
                         new_avatar_cooldown)
    avatar_path = (f"{pathlib.Path().absolute()}/src/avatars/"
                   f"Avatar_{random.randint(1, 16)}.png")
    with open(avatar_path, "rb") as f:
        avatar_bytes = f.read()
    f.close()
    return {
        "avatar_cooldown": new_avatar_cooldown,
        "curr_cooldown": None,
        "avatar_bytes": avatar_bytes,
    }
예제 #25
0
def import_word_file(db_name, table, path):
    """Download word base by link and import it.

    This function downloads .txt file and imports it to database
    If link is incorrect, aborts importing

    Args:
        db_name (str): Name of database to edit data
        table (str): Name of table in DB
        path (str): Path to local file of word base

    Returns:
        bool: True if word base was imported successfully, False otherwise
    """
    words_download_status = download_words_file(path)
    if not words_download_status:
        return False
    words_array = files.import_data(path)
    for element in words_array:
        database.modify_data(db_name, f"INSERT INTO {table} VALUES (?)",
                             element)
    return True
예제 #26
0
def markov_delay_handler(mode):
    """Handle needed delay operation for Markov chains.

    This function manages delay of autogenerated message and
    updates current message counter

    Here are modes, such as:
    - Update: Updates current message counter (+1)
    - Clear: Updates delay of autogenerated message
    (Random integer from 20 to 45)
    - Get: Return delay and message counter

    If wrong mode provided or it isn't a 'get' mode, returns None

    Args:
        mode (str): Mode of delay handler

    Returns:
        Union[list, None]: List of current delay and message counter.
        If wrong mode/'update' or 'clear' mode were provided, returns None
    """
    current_delay = database.get_data("mainDB", True,
                                      "SELECT markov_delay FROM variables")
    msg_counter = database.get_data("mainDB", True,
                                    "SELECT msg_counter FROM variables")
    if mode == "update":
        database.modify_data("mainDB", "UPDATE variables SET msg_counter = ?",
                             msg_counter + 1)
    elif mode == "clear":
        database.modify_data(
            "mainDB",
            "UPDATE variables SET markov_delay = ?, msg_counter = ?",
            random.randint(60, 120),
            1,
        )
    elif mode == "get":
        return [current_delay, msg_counter]
    return None
예제 #27
0
def subtract_points(user_id, points, skip_check=False):
    """Subtract points from user points account.

    Args:
        user_id (int): The ID of the user
        points (int): The amount of points to subtract
        skip_check (bool): Skip checking if check was already done
    """
    if not skip_check:
        account_status = check_account(user_id)
        if not account_status:
            return False
    account_balance = get_account_balance(user_id)
    if account_balance == 0 or account_balance < points:
        return False
    database.modify_data(
        "pointsDB",
        "UPDATE points_accounts "
        "SET points_balance = points_balance - ? WHERE user_id = ?",
        points,
        user_id,
    )
    return True
예제 #28
0
def daily_points_manager(user_id):
    """Manage daily points rewarding.

    Args:
        user_id (int): The ID of the user

    Returns:
        int: The amount of bouns points
        bool: False if points accounts does not exist
        None: If user alredy got daily points
    """
    account_status = check_account(user_id)
    if not account_status:
        return False
    current_date = dt.datetime.now().date()
    next_date = (dt.datetime.now() + dt.timedelta(days=1)).date()
    daily_points_date = database.get_data(
        "pointsDB",
        True,
        "SELECT daily_points_date FROM points_accounts WHERE user_id = ?",
        user_id,
    )
    if (not daily_points_date or current_date >= dt.datetime.strptime(
            daily_points_date, "%Y-%m-%d").date()):
        random_points = random.randrange(100, 2000, 100)
        add_points(user_id, random_points, skip_check=True)
        database.modify_data(
            "pointsDB",
            "UPDATE points_accounts SET daily_points_date = ? "
            "WHERE user_id = ?",
            next_date,
            user_id,
        )
        return random_points
    if current_date < dt.datetime.strptime(daily_points_date,
                                           "%Y-%m-%d").date():
        return None
예제 #29
0
def rem_member_from_db(member_id):
    """Remove member from database.

    Used for removing members from database in certain cases
    (Ignoring in shipping and etc.)

    **Noteworthy:** This makes sense until the bot reboots. In future there are plans
    for adding ignore list for shipping and other commands

    Args:
        member_id (int): ID of member to remove
    """
    return database.modify_data("mainDB",
                                "DELETE FROM users WHERE users_id = ?",
                                member_id)
예제 #30
0
async def lock_shipping():
    """Change variables of shipping in DB."""
    database.modify_data(
        "mainDB",
        "UPDATE variables SET ship_in_active = ?, ship_activated = ?", 1, 1)
    return