Доступ к готовым решениям

Переход в группу "Пользователь"

300.00 ₽
Одноразовый платёж
Быстрый переход в группу "Пользователи", без надобности написания постов и ожидания.

Покупка дает возможность:
Быть полноправным участником форума
Нормальное копирование кода
Создавать темы
Скачивать файлы
Доступ к архиву Pawno-Info

Telegram Bot | Бот знакомств на aiogram

Oleg Polikhronidi

Умник
Привет, меня тут вдруг внезапно разблокировали на форуме (очень неожиданно для меня, я думал пиро никогда не разблокирует меня). Первым делом я хочу поделиться скриптом бота для знакомств, возможно кому-то поможет и кто-то в дальнейшем будет его развивать. Этого кода нет на других форумах и прочего, это не паблик скрипт, а по большей части самописный скрипт 1х1 с ботом знакомств (я боюсь оставлять ссылку на бота, вдруг меня забанят опять на пару лет).

Используемые библиотеки: aiogram. Я крайне не рекомендую писать ботов на pyTelegramBotApi.
Для начала отправимся к отцу Telegram-ботов Bot Father: t.me/BotFather.
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!

На момент публикации этой темы, токен не будет работать, а сам бот будет удалён.
Можете не пытаться подключиться к нему.

После того как мы получили API Token для бота, делаем следующее:


  1. Жмём Win + R
  2. В поле ввода пишем cmd (или cmd.exe)
  3. Откроется командная строка, туда пишем:
pip install aiogram
Если у Вас нет Python, устанавливаем его. Не могу оставить ссылки на установщик, поскольку могу быть забанен.
Ограничиваю себя в использовании ссылок в этой теме, по-скольку уже был забанен за такое. Ищите сами как установить Python.

Например, на все мои боты я использую ОС Ubuntu 20.04. Если используете тоже, пишем в консоль следующее:
Код:
sudo apt-get update
sudo apt-get upgrade -y
sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get install screen -y
sudo apt-get install python3.9 -y
sudo apt-get install python3-pip -y
sudo apt-get install python3.9-dev -y
sudo apt-get install python3.9-distutils -y
python3.9 -m pip install pip --upgrade
Мы установили Python на ОС Ubuntu 20.04, отлично! Двигаемся дальше.

Модули и библиотеку aiogram устанавливаем следующим сообщением в консоль:
Код:
python3.9 -m pip install aiogram
Сервер готов. Возвращаемся к коду.
Мы используем локальную базу данных. Для начала, подключаем модули.
Python:
import random
import logging
from db import BotDB
from aiogram.dispatcher import FSMContext
from aiogram import Bot, Dispatcher, executor, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher.filters.state import State, StatesGroup
После того как указали модули, нам необходимо настроить бота.
Python:
bot = Bot(token="token_bot")
dp = Dispatcher(bot, storage=MemoryStorage())
logging.basicConfig(level=logging.INFO)
BotDB = BotDB('database.db')
Там, где указано token_bot вставляем значение от BotFather.
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!


Отлично, мы настроили базовую конфигурацию бота. Переходим далее.
Я не буду объяснять каждый фрагмент кода, а сразу кину сюда всю остальную часть.
Всё что я посчитал нужным к объяснению - объяснил прямо в коде. Что не понятно - спрашивайте в теме.

Заготовленные ответы для пользователей и клавиатура.
Python:
main_text = '1. Смотреть анкеты\n2. Моя анкета\n3. Удалить анкету'
profile_text = '1. Заполнить анкету заново\n2. Изменить текст анкеты\n3. Изменить фото\n4. Вернутся назад'

def show_profile(name, age, city, text):
    return f'{name}\n{age}\n{city}\n{text}'

def get_random_anketa(list_of_anketi):
    anketa = list_of_anketi[random.randint(0, len(list_of_anketi) - 1)]
    a = anketa
    return [show_profile(a[2], a[3], a[4], a[5]), BotDB.get_photo_id(a[1])]
Подключаем классы состояний для навигации.
Python:
class Wait(StatesGroup):
    choosing_gender = State()
    choosing_interest = State()
    name = State()
    age = State()
    city = State()
    text = State()
    photo = State()
    menu_answer = State()
    my_anketa_answer = State()
    change_text = State()
    change_photo = State()
    delete_confirm = State()
    anketa_reaction = State()
Весь код ниже - процесс регистрации профиля. Занесение его в базу данных.
В случае если анкета есть - показываем анкету. В случае если анкеты нет - предлагаем создать.
Python:
@dp.message_handler(commands="start", state = "*")
async def anketa_start(message: types.Message):
    if(not BotDB.user_exists(message.from_user.id)):
        BotDB.add_user(message.from_user.id)

    if(BotDB.anketa_exists(message.from_user.id)):

        anketa = BotDB.get_anketa(message.from_user.id)
        a = anketa[0]
        caption = show_profile(a[2], a[3], a[4], a[5])
        await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), chat_id = message.from_user.id, caption = caption)

        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["1", "2", "3"]
        keyboard.add(*buttons)

        await message.answer(main_text, reply_markup = keyboard)
        await Wait.menu_answer.set()

    else:

        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["Парень", "Девушка"]
        keyboard.add(*buttons)

        await message.answer("Заполним анкету!\nДля начала выберите свой пол",
         reply_markup=keyboard)
        await Wait.choosing_gender.set()

@dp.message_handler(state = Wait.choosing_gender)
async def choose_gender(message: types.Message, state: FSMContext):
    if message.text not in ["Парень", "Девушка"]:
        await message.answer("Выберите вариант из кнопок ниже")
        return
    await state.update_data(gender = message.text.lower())

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    buttons = ["Парни", "Девушки"]
    keyboard.add(*buttons)
    await message.answer("Кто тебя интересует?", reply_markup = keyboard)
    await Wait.choosing_interest.set()

@dp.message_handler(state = Wait.choosing_interest)
async def choose_interest(message: types.Message, state: FSMContext):
    if message.text == "Парни" or message.text == "Девушки":
        await state.update_data(interest = message.text.lower())
        await message.answer("Введите своё имя", reply_markup=types.ReplyKeyboardRemove())
        await Wait.name.set()
    else:
        await message.answer("Выберите вариант из кнопок ниже")
        return

@dp.message_handler(state = Wait.name)
async def name(message: types.Message, state: FSMContext):
    if len(message.text) > 30:
        await message.answer("Слишком длинное имя")
        return
    await state.update_data(name = message.text)                   
    await message.answer("Сколько вам лет?")
    await Wait.age.set()

@dp.message_handler(state = Wait.age)
async def age(message: types.Message, state: FSMContext):
    try:
        if 10 > int(message.text) or int(message.text) > 100:
            await message.answer("Какой-то странный возраст")
            return
    except(TypeError, ValueError):
        await message.answer("Какой-то странный возраст")
        return
    await state.update_data(age = message.text)
    await message.answer("Напишите свой город")
    await Wait.city.set()

@dp.message_handler(state = Wait.city)
async def city(message: types.Message, state: FSMContext):
    if len(message.text) > 30:
        await message.answer("Слишком длинный город")
        return

    await state.update_data(city = message.text)

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    keyboard.add("Оставить пустым")

    await message.answer("Введите описание анкеты до 200 символов. Можно пропустить.", reply_markup = keyboard)
    await Wait.text.set()

@dp.message_handler(state = Wait.text)
async def text(message: types.Message, state: FSMContext):
    if message.text == "Оставить пустым":
        await state.update_data(text = '')
    else:
        if len(message.text) > 200:
            await message.answer("Описание должно быть длинной до 200 символов")
            return
        await state.update_data(text = message.text)
    
    await message.answer("Загрузите своё фото", reply_markup=types.ReplyKeyboardRemove())
    await Wait.photo.set()
Здесь мы преобразовываем значение словаря в (d). В основном так же взаимодействуем с анкетами.
Python:
@dp.message_handler(state = Wait.photo, content_types = ["photo"])
async def download_photo(message: types.Message, state: FSMContext):
    await message.photo[-1].download(destination_file=f"photos/{message.from_user.id}.jpg")
    data = await state.get_data()
    d = list(data.values())
    print(d)

    BotDB.add_anketa(message.from_user.id, d[0], d[1], d[2], d[3], d[4], d[5])
    caption = show_profile(d[2], d[3], d[4], d[5])
    await message.answer("Так выглядит твоя анкета: ")
    await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    buttons = ["1", "2", "3"]
    keyboard.add(*buttons)

    await message.answer(main_text, reply_markup = keyboard)
    await Wait.menu_answer.set()

@dp.message_handler(state = Wait.menu_answer)
async def menu_answer(message: types.Message, state: FSMContext):
    if message.text == "1":
        anketa = BotDB.get_anketa(message.from_user.id)
        a = anketa[0]
        caption = show_profile(a[2], a[3], a[4], a[5])       

        list_of_anketi = BotDB.find_anketi(message.from_user.id, a[7], a[4], a[3])

        try:
            get_random_anketa(list_of_anketi)
        except ValueError:
            await message.answer("Никого не могу найти. Возможно, твой город некорректный / не популярный.")

            await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)
            
            keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
            buttons = ["1", "2", "3", "4"]
            keyboard.add(*buttons)

            await message.answer(profile_text, reply_markup = keyboard)
            await Wait.my_anketa_answer.set()

        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["Лайк", "Скип", "Вернутся назад"]
        keyboard.add(*buttons)
        anketa = get_random_anketa(list_of_anketi)
        caption = anketa[0]
        photo_id = anketa[1]

        await state.update_data(liked_id = photo_id)
        await bot.send_photo(photo = open(f"photos/{photo_id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id, reply_markup = keyboard)
        await Wait.anketa_reaction.set()
        
    elif message.text == "2":

        anketa = BotDB.get_anketa(message.from_user.id)
        a = anketa[0]
        caption = show_profile(a[2], a[3], a[4], a[5])
        await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)
        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["1", "2", "3", "4"]
        keyboard.add(*buttons)
        await message.answer(profile_text, reply_markup = keyboard)
        await Wait.my_anketa_answer.set()

    elif message.text == "3":
        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["Да", "Нет"]
        keyboard.add(*buttons)
        await message.answer("Вы точно хотите удалить свою анкету?", reply_markup = keyboard)
        await Wait.delete_confirm.set()

    else:
        await message.answer("Выберите вариант из кнопок ниже")
        return

@dp.message_handler(state = Wait.anketa_reaction)
async def anketa_reaction(message: types.Message, state: FSMContext):
    if message.text == "Лайк":
        
        data = await state.get_data()
        d = list(data.values())

        anketa = BotDB.get_anketa(message.from_user.id)
        a = anketa[0]
        caption = show_profile(a[2], a[3], a[4], a[5])

        list_of_anketi = BotDB.find_anketi(message.from_user.id, data["interest"], data["city"], data["age"])

        liked_id = data["liked_id"]

        await bot.send_message(text = "Вы понравились этому человеку: ", chat_id = liked_id)
        await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), chat_id = liked_id, caption = caption)
        await bot.send_message(text = f"Начинай общатся, если понравлися(лась) - @{message.from_user.username}", chat_id = liked_id)

        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["Лайк", "Скип", "Вернутся назад"]
        keyboard.add(*buttons)

        anketa = get_random_anketa(list_of_anketi)
        caption = anketa[0]
        photo_id = anketa[1]
        
        await bot.send_photo(photo = open(f"photos/{photo_id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)
        await Wait.anketa_reaction.set()

    elif message.text == "Скип":

        data = await state.get_data()
        list_of_anketi = BotDB.find_anketi(message.from_user.id, data["interest"], data["city"], data["age"])

        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["Лайк", "Скип", "Вернутся назад"]
        keyboard.add(*buttons)

        caption = get_random_anketa(list_of_anketi)[0]
        photo_id = get_random_anketa(list_of_anketi)[1]
        await bot.send_photo(photo = open(f"photos/{photo_id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)

        await Wait.anketa_reaction.set()

    elif message.text == "Вернутся назад":
        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["1", "2", "3"]
        keyboard.add(*buttons)

        await message.answer(main_text, reply_markup = keyboard)
        await Wait.menu_answer.set()
    else:
        await message.answer("Выберите вариант из кнопок")
        return

@dp.message_handler(state = Wait.delete_confirm)
async def delete_confirm(message: types.Message, state: FSMContext):
    if message.text == "Да":
        BotDB.delete_anketa(message.from_user.id)
        BotDB.delete_user(message.from_user.id)
        await message.answer("Ваша анкета удалена!\nВы можете вернутся сюда в любое время по команде /start", reply_markup = types.ReplyKeyboardRemove())       
    elif message.text == "Нет":
        anketa = BotDB.get_anketa(message.from_user.id)
        a = anketa[0]
        caption = show_profile(a[2], a[3], a[4], a[5])

        await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)
        
        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["1", "2", "3", "4"]
        keyboard.add(*buttons)

        await message.answer(profile_text, reply_markup = keyboard)
        await Wait.my_anketa_answer.set()
    else:
        await message.answer("Выберите вариант из кнопок ниже")
        return
Код для пересоздания анкеты. Тут мы её пересоздаем.
Python:
@dp.message_handler(state = Wait.my_anketa_answer)
async def my_anketa_answer(message: types.Message, state: FSMContext):
    if message.text == "1":
        BotDB.delete_anketa(message.from_user.id)

        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["Парень", "Девушка"]
        keyboard.add(*buttons)

        await message.answer("Для начала выберите свой пол",
         reply_markup=keyboard)
        await Wait.choosing_gender.set()
# вводим новый текст
    elif message.text == "2":
        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        keyboard.add("Оставить пустым")
        await message.answer("Введите новый текст анкеты", reply_markup=keyboard)
        await Wait.change_text.set()

    elif message.text == "3":
        await message.answer("Загрузите новое фото", reply_markup = types.ReplyKeyboardRemove())
        await Wait.change_photo.set()

    elif message.text == "4":
        anketa = BotDB.get_anketa(message.from_user.id)
        a = anketa[0]
        caption = show_profile(a[2], a[3], a[4], a[5])

        await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)
        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["1", "2", "3"]
        keyboard.add(*buttons)

        await message.answer(main_text, reply_markup = keyboard)
        await Wait.menu_answer.set()
    else:
        await message.answer("Выберите вариант из кнопок ниже")
        return

@dp.message_handler(state = Wait.change_text)
async def change_text(message: types.Message, state: FSMContext):
    if message.text == "Оставить пустым":
            BotDB.update_text(message.from_user.id, '')

            anketa = BotDB.get_anketa(message.from_user.id)
            a = anketa[0]
            caption = show_profile(a[2], a[3], a[4], a[5])   

            await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)
            
            keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
            buttons = ["1", "2", "3", "4"]
            keyboard.add(*buttons)

            await message.answer(profile_text, reply_markup = keyboard)
            await Wait.my_anketa_answer.set()
    else:
        if len(message.text) > 200:
            await message.answer("Описание должно быть длинной до 200 символов")
            return
        BotDB.update_text(message.from_user.id, message.text)

        anketa = BotDB.get_anketa(message.from_user.id)
        a = anketa[0]
        caption = show_profile(a[2], a[3], a[4], a[5])   

        await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)

        keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
        buttons = ["1", "2", "3"]
        keyboard.add(*buttons)

        await message.answer(main_text, reply_markup = keyboard)
        await Wait.menu_answer.set()

@dp.message_handler(state = Wait.change_photo, content_types = ["photo"])
async def change_photo(message: types.Message, state: FSMContext):
    await message.photo[-1].download(destination_file=f"photos/{message.from_user.id}.jpg")

    anketa = BotDB.get_anketa(message.from_user.id)
    a = anketa[0]
    caption = show_profile(a[2], a[3], a[4], a[5])   

    await message.answer("Вот ваша анкета: ")
    await bot.send_photo(photo = open(f"photos/{message.from_user.id}.jpg", "rb"), caption = caption, chat_id = message.from_user.id)

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    buttons = ["1", "2", "3"]
    keyboard.add(*buttons)

    await message.answer(main_text, reply_markup = keyboard)
    await Wait.menu_answer.set()

if __name__ == "__main__":
    executor.start_polling(dp, skip_updates=True)
Почему мы используем skip_updates=True в конце? Что это значит?
Параметр skip_updates=True позволяет пропустить накопившиеся входящие сообщения, если они нам не важны.

Далее создаём базу данных. Я не мастер объяснять SQL-запросы, к сожалению.
Код ниже - запросы к базе, они и не нуждаются в представлениях и описаниях. Используем sqlite3.
SQL:
import sqlite3

class BotDB:
    # название базы напишите сюда
    def __init__(self, db_file):
        self.conn = sqlite3.connect(db_file)
        self.cursor = self.conn.cursor()

    def user_exists(self, user_id):
        result = self.cursor.execute("SELECT `id` FROM `users` WHERE `user_id` = ?", (user_id,))
        return bool(len(result.fetchall()))

    def anketa_exists(self, user_id):
        result = self.cursor.execute("SELECT COUNT (*) FROM `anketi` WHERE `users_id` = ?", (self.get_user_id(user_id),))
        result = result.fetchone()[0]

        if result == 0:
            return False
        elif result == 1:
            return True
        else:
            return None

    def get_user_id(self, user_id):
        result = self.cursor.execute("SELECT `id` FROM `users` WHERE `user_id` = ?", (user_id,))
        return result.fetchone()[0]

    def get_photo_id(self, users_id):
        result = self.cursor.execute("SELECT `user_id` FROM `users` WHERE `id` = ?", (users_id,))
        return result.fetchone()[0]

    def add_user(self, user_id):
        self.cursor.execute("INSERT INTO `users` (`user_id`) VALUES (?)", (user_id,))
        return self.conn.commit()

    def add_anketa(self, user_id, gender, interest, name, age, city, text):
        self.cursor.execute("INSERT INTO `anketi` (`users_id`, `name`, `age`, `city`, `text`, `gender`, `interest`) VALUES\
            (?, ?, ?, ?, ?, ?, ?)", (self.get_user_id(user_id), name, age, city.title(), text, gender, interest))
        return self.conn.commit()

    def update_text(self, user_id, new_text):
        self.cursor.execute("UPDATE `anketi` SET `text` = ? WHERE `users_id` = ?", (new_text, self.get_user_id(user_id)))
        return self.conn.commit()

    def get_anketa(self, user_id):
        result = self.cursor.execute("SELECT * FROM `anketi` WHERE `users_id` = ?", (self.get_user_id(user_id),))
        return result.fetchall()

    def delete_anketa(self, user_id):
        self.cursor.execute("DELETE FROM `anketi` WHERE `users_id` = ?", (self.get_user_id(user_id),))
        return self.conn.commit()

    def delete_user(self, user_id):
        self.cursor.execute("DELETE FROM `users` WHERE `id` = ?", (self.get_user_id(user_id),))
        return self.conn.commit()

    def find_anketi(self, user_id, interest, city, age):
        gender: str = ""
        if interest == "парни":
            gender = "парень"
        if interest == "девушки":
            gender = "девушка"

        result = self.cursor.execute("SELECT * FROM `anketi` WHERE `users_id` != ? AND `gender` = ? AND `city` = ? AND `age` BETWEEN ? AND ?", (self.get_user_id(user_id), gender, city.title(), int(age) - 1, int(age) + 1))

        return result.fetchall()

    def close(self):
        self.connection.close()
Ура! Бот готов. Что у нас получилось? Смотрим скриншоты.
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!


Бот работает. Все данные о пользователях хранятся в database.bd
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!

Фотографии пользователей хранятся в папке photos.


Для тех, кто хочет сразу же скачать бота и запустить, архив прикреплён. Качайте и пользуйтесь.
Пароль от прикреплённого архива: pawno-info.ru
 

Вложения

Последнее редактирование модератором:
Сверху Снизу