├── texts ├── __init__.py └── main.py ├── states ├── __init__.py └── states.py ├── dbs ├── __init__.py ├── models │ ├── __init__.py │ ├── p_methods.json │ ├── __pycache__ │ │ ├── users.cpython-38.pyc │ │ ├── __init__.cpython-38.pyc │ │ └── settings.cpython-38.pyc │ ├── user.json │ ├── users.py │ └── settings.py └── main.py ├── handlers ├── admin.py ├── __init__.py ├── private.py └── private_inline.py ├── .env ├── buttons ├── __init__.py ├── reply.py └── inline.py ├── custom ├── __init__.py ├── get_amount.py └── schedule_jobs.py ├── loader.py ├── main.py ├── requirements.txt └── README.md /texts/__init__.py: -------------------------------------------------------------------------------- 1 | from .main import get_lang -------------------------------------------------------------------------------- /states/__init__.py: -------------------------------------------------------------------------------- 1 | from .states import Navigation -------------------------------------------------------------------------------- /dbs/__init__.py: -------------------------------------------------------------------------------- 1 | from .main import Mongodb as DataBase -------------------------------------------------------------------------------- /handlers/admin.py: -------------------------------------------------------------------------------- 1 | from loader import bot, dp 2 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | BOT_TOKEN=TOKEN 2 | DEV_ADMIN=TELEGRAM_USER_ID 3 | -------------------------------------------------------------------------------- /dbs/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .users import User 2 | from .settings import Settings -------------------------------------------------------------------------------- /buttons/__init__.py: -------------------------------------------------------------------------------- 1 | from .reply import get_keyboard, get_array 2 | from .inline import get_inline_keyboard -------------------------------------------------------------------------------- /handlers/__init__.py: -------------------------------------------------------------------------------- 1 | from .admin import dp 2 | from .private import dp 3 | from .private_inline import dp 4 | -------------------------------------------------------------------------------- /custom/__init__.py: -------------------------------------------------------------------------------- 1 | from .get_amount import get_amount 2 | from .schedule_jobs import schedule_jobs 3 | from .freepik_cookies import cookies -------------------------------------------------------------------------------- /dbs/models/p_methods.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "click", 3 | "title": "Click Uzbekistan", 4 | "currency": [ 5 | "sum" 6 | ] 7 | } -------------------------------------------------------------------------------- /dbs/models/__pycache__/users.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/islombay/python-tgbot-premium-subscription/HEAD/dbs/models/__pycache__/users.cpython-38.pyc -------------------------------------------------------------------------------- /dbs/models/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/islombay/python-tgbot-premium-subscription/HEAD/dbs/models/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /dbs/models/__pycache__/settings.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/islombay/python-tgbot-premium-subscription/HEAD/dbs/models/__pycache__/settings.cpython-38.pyc -------------------------------------------------------------------------------- /custom/get_amount.py: -------------------------------------------------------------------------------- 1 | from loader import db 2 | 3 | 4 | async def get_amount(provider, currency, coins_amount): 5 | pricing = (await db.get_pricing_for_provider(provider))[currency] 6 | return pricing[coins_amount] 7 | -------------------------------------------------------------------------------- /dbs/models/user.json: -------------------------------------------------------------------------------- 1 | { 2 | "user_id": "telegrams id", 3 | "locale": "user's language", 4 | "status": "vip, ban, user", 5 | "expire_date": "Datetime.now()", 6 | "check_id": "None | or digit", 7 | "coins": 0 8 | } 9 | -------------------------------------------------------------------------------- /states/states.py: -------------------------------------------------------------------------------- 1 | from aiogram.dispatcher.filters.state import State, StatesGroup 2 | 3 | 4 | class Navigation(StatesGroup): 5 | menu = State() 6 | settings = State() 7 | balance = State() 8 | premium = State() 9 | -------------------------------------------------------------------------------- /dbs/models/users.py: -------------------------------------------------------------------------------- 1 | class User: 2 | def __init__(self, document: dict): 3 | if document: 4 | self.doc = document 5 | for key, value in document.items(): 6 | setattr(self, key, value) 7 | 8 | def __str__(self): 9 | text = "" 10 | for key, value in self.doc.items(): 11 | text += f"{str(key)}={str(value)}, " 12 | 13 | return f"User({text})" 14 | -------------------------------------------------------------------------------- /dbs/models/settings.py: -------------------------------------------------------------------------------- 1 | class Settings: 2 | def __init__(self, document: dict): 3 | if document: 4 | self.doc = document 5 | for key, value in document.items(): 6 | setattr(self, key, value) 7 | 8 | def __str__(self): 9 | text = "" 10 | for key, value in self.doc.items(): 11 | text += f"{str(key)}={str(value)}, " 12 | 13 | return f"Settings({text})" 14 | -------------------------------------------------------------------------------- /loader.py: -------------------------------------------------------------------------------- 1 | import os 2 | from dotenv import load_dotenv 3 | 4 | from aiogram import Bot, Dispatcher 5 | from aiogram.contrib.fsm_storage.mongo import MongoStorage 6 | 7 | from dbs import DataBase 8 | 9 | load_dotenv() 10 | 11 | db = DataBase("test_db") 12 | 13 | storage = MongoStorage(host='localhost', port=27017, db_name='db_name') 14 | 15 | bot = Bot(os.getenv("BOT_TOKEN"), parse_mode="html") 16 | dp = Dispatcher(bot, storage=storage) 17 | 18 | dev_admin = os.getenv("DEV_ADMIN") 19 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from aiogram import executor, Bot, Dispatcher 2 | from loader import dev_admin 3 | 4 | from custom import schedule_jobs 5 | 6 | 7 | async def startup_function(dp): 8 | await dp.bot.send_message(dev_admin, "Bot started") 9 | 10 | 11 | async def shutdown_function(dp: Dispatcher): 12 | await dp.storage.close() 13 | await dp.storage.wait_closed() 14 | await dp.bot.close() 15 | 16 | if __name__ == "__main__": 17 | from handlers import dp 18 | 19 | schedule_jobs() 20 | 21 | executor.start_polling(dp, on_startup=startup_function, on_shutdown=shutdown_function) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiogram==2.25.1 2 | aiohttp==3.8.4 3 | aiosignal==1.3.1 4 | APScheduler==3.10.1 5 | async-timeout==4.0.2 6 | attrs==22.2.0 7 | Babel==2.9.1 8 | backports.zoneinfo==0.2.1 9 | certifi==2022.12.7 10 | charset-normalizer==3.1.0 11 | dnspython==2.3.0 12 | frozenlist==1.3.3 13 | gino==1.0.1 14 | idna==3.4 15 | magic-filter==1.0.9 16 | motor==3.1.1 17 | multidict==6.0.4 18 | pymongo==4.3.3 19 | python-dateutil==2.8.2 20 | python-dotenv==1.0.0 21 | pytz==2022.7.1 22 | pytz-deprecation-shim==0.1.0.post0 23 | six==1.16.0 24 | SQLAlchemy==1.3.24 25 | tzdata==2022.7 26 | tzlocal==4.3 27 | yarl==1.8.2 28 | -------------------------------------------------------------------------------- /custom/schedule_jobs.py: -------------------------------------------------------------------------------- 1 | from apscheduler.schedulers.asyncio import AsyncIOScheduler 2 | 3 | from loader import db 4 | import datetime 5 | 6 | scheduler = AsyncIOScheduler() 7 | 8 | 9 | def schedule_jobs(): 10 | scheduler.add_job(chekc_expire_date, "interval", days=5) 11 | scheduler.start() 12 | 13 | 14 | async def chekc_expire_date(): 15 | users = await db.get_users() 16 | for user in users: 17 | status = user.status 18 | if status == "premium": 19 | exp = (user.expire_date).timestamp() 20 | now = datetime.datetime.now().timestamp() 21 | 22 | difference = now - exp 23 | if difference > 0: 24 | await db.get_premium_back(user.user_id) 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Telegram bot with premium subscription 2 | 3 | **Notice:** Premium is not official telegram messanger's premium subscription 4 | 5 | ## What is this bot about 6 | 7 | This is a test bot with some functionality in buying coins using telegram methods of payment. Database (mongodb) exists. 8 | 9 |
10 |
11 | 12 | ## Quick start 13 | 14 | First of all, download all modules that you need to run the bot. Use the command below: 15 | 16 | ``` 17 | pip install requirements 18 | ``` 19 | 20 | Next, create your own telegram bot using [BotFather](https://telegram.me/botFather) (hope everyone knows how to do that). Once you get a bot token, change the value for `BOT_TOKEN` in `.env` file using your own one. 21 | Do not forget to set your telegram accounts id for `DEV_ADMIN` in the same file. This is needed for notifing you when bot is started. 22 | 23 | ### Database - MongoDB 24 | 25 | Install it 26 | 27 | ### **Run the bot** 28 | 29 | Following command starts the bot: 30 | 31 | ``` 32 | python3 main.py 33 | ``` 34 | -------------------------------------------------------------------------------- /buttons/reply.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | from aiogram.types import ReplyKeyboardMarkup as kmarkup,\ 3 | KeyboardButton as btn 4 | 5 | from loader import db 6 | 7 | tfb = { 8 | "uz": { 9 | "balance": "Balans", "premium":"💎Premium", 10 | "settings": "⚙Sozlamalar", "language": "🚩Til", 11 | "menu_back": "◀Menyu" 12 | }, 13 | "ru": { 14 | "balance": "Баланс", "premium": "💎Premium", 15 | "settings": "⚙Настройки", "language": "🚩Язык", 16 | "menu_back": "◀Меню" 17 | }, 18 | "en": { 19 | "balance": "Balance", "premium": "💎Premium", 20 | "settings": "⚙Settings", "language": "🚩Language", 21 | "menu_back": "◀Menu" 22 | }, 23 | } 24 | 25 | 26 | markup = { 27 | "uz": { 28 | "start_message": kmarkup(resize_keyboard=True).add( 29 | btn(tfb['uz']['balance']), btn(tfb['uz']['premium']) 30 | ).add(btn(tfb['uz']['settings'])), 31 | 32 | "settings_message": kmarkup(resize_keyboard=True).add( 33 | btn(tfb['uz']['language']) 34 | ).add(btn(tfb['uz']['menu_back'])) 35 | }, 36 | "ru": { 37 | "start_message": kmarkup(resize_keyboard=True).add( 38 | btn(tfb['ru']['balance']), btn(tfb['ru']['premium']) 39 | ).add(btn(tfb['ru']['settings'])), 40 | 41 | "settings_message": kmarkup(resize_keyboard=True).add( 42 | btn(tfb['ru']['language']) 43 | ).add(btn(tfb['ru']['menu_back'])) 44 | }, 45 | "en": { 46 | "start_message": kmarkup(resize_keyboard=True).add( 47 | btn(tfb['en']['balance']), btn(tfb['en']['premium']) 48 | ).add(btn(tfb['en']['settings'])), 49 | 50 | "settings_message": kmarkup(resize_keyboard=True).add( 51 | btn(tfb['en']['language']) 52 | ).add(btn(tfb['en']['menu_back'])) 53 | } 54 | } 55 | 56 | 57 | async def get_keyboard(keyboards_text): 58 | user = types.User.get_current() 59 | user_locale = await db.get_user_locale(user.id) 60 | 61 | return markup[user_locale][keyboards_text] 62 | 63 | 64 | def get_array(text): 65 | return [i[text] for i in tfb.values()] -------------------------------------------------------------------------------- /handlers/private.py: -------------------------------------------------------------------------------- 1 | from loader import dp, db 2 | 3 | from aiogram.types import Message, ContentType 4 | from aiogram.dispatcher.filters import Text 5 | from aiogram.dispatcher.storage import FSMContext 6 | 7 | from texts import get_lang as _ 8 | from buttons import * 9 | from states import Navigation 10 | 11 | 12 | @dp.message_handler(commands='start', state="*") 13 | async def start_func(msg: Message, state: FSMContext): 14 | await db.add_user(msg.from_user.id) 15 | await msg.answer(await _("start_message"), 16 | reply_markup=(await get_keyboard("start_message"))) 17 | 18 | await Navigation.menu.set() 19 | 20 | 21 | # Settings button 22 | @dp.message_handler(Text(get_array("settings")), state=Navigation.menu) 23 | async def settings_func(msg: Message, state: FSMContext): 24 | await msg.answer(await _("settings_message"), 25 | reply_markup=(await get_keyboard("settings_message"))) 26 | 27 | await Navigation.settings.set() 28 | await state.update_data(last_action="menu") 29 | 30 | 31 | @dp.message_handler(Text(get_array("language")), state=Navigation.settings) 32 | async def change_language(msg: Message): 33 | await msg.answer(await _("change_language"), 34 | reply_markup=(await get_inline_keyboard("change_language_message"))) 35 | # ------------------------------------------------------------- 36 | 37 | 38 | # Premium button 39 | @dp.message_handler(Text(get_array("premium")), state=Navigation.menu) 40 | async def premium_func(msg: Message, state: FSMContext): 41 | markup = None if (await db.is_premium_user(msg.from_user.id)) else await get_inline_keyboard("buy_premium") 42 | await msg.answer(await _("premium_message", 1), reply_markup=markup) 43 | # ------------------------------------------------------------- 44 | 45 | 46 | # Balance button 47 | @dp.message_handler(Text(get_array("balance")), state=Navigation.menu) 48 | async def balance_func(msg: Message, state: FSMContext): 49 | await msg.answer(await _("balance_message", 1), reply_markup=(await get_inline_keyboard("buy_coins"))) 50 | 51 | 52 | # ------------------------------------------------------------- 53 | 54 | # Payment message 55 | @dp.message_handler(content_types=ContentType.SUCCESSFUL_PAYMENT, state="*") 56 | async def successful_payment_done(msg: Message, state: FSMContext): 57 | data = await state.get_data() 58 | await db.add_check_id(msg.from_user.id, data['pre_checkout_id'], data['coins_amount']) 59 | 60 | from_dev_information = {"coins_amount": data['coins_amount'], "provider": data['provider']} 61 | await db.add_successful_payment(msg.successful_payment, data['pre_checkout_id'], from_dev_information) 62 | await db.add_coins(msg.from_user.id, data['coins_amount']) 63 | await msg.answer(await _("thanks_for_payment")) 64 | 65 | 66 | # Back Button everywhere 67 | @dp.message_handler(Text(get_array("menu_back")), state=[Navigation.settings, Navigation.balance]) 68 | async def back_func(msg: Message, state: FSMContext): 69 | last_action = (await state.get_data())['last_action'] 70 | if last_action == "menu": 71 | await start_func(msg, state) -------------------------------------------------------------------------------- /handlers/private_inline.py: -------------------------------------------------------------------------------- 1 | from loader import bot, dp, db 2 | 3 | from aiogram.types import CallbackQuery, LabeledPrice, PreCheckoutQuery 4 | from aiogram.dispatcher.storage import FSMContext 5 | 6 | from texts import get_lang as _ 7 | from buttons import * 8 | from states import Navigation 9 | from custom import get_amount 10 | 11 | from .private import start_func, premium_func 12 | 13 | 14 | @dp.callback_query_handler(text_startswith="lang_", state="*") 15 | async def change_language_call(call: CallbackQuery, state: FSMContext): 16 | chosen_language = str(call.data).replace("lang_", "") 17 | await db.change_user_locale(call.from_user.id, chosen_language) 18 | 19 | await call.answer(await _("language_changed"), show_alert=True) 20 | await start_func(call.message, state) 21 | 22 | 23 | @dp.callback_query_handler(text="buy_coins", state="*") 24 | async def buy_coins_call(call: CallbackQuery, state: FSMContext): 25 | await call.message.answer( 26 | await _("buy_coins_call"), 27 | reply_markup=(await get_inline_keyboard("payment_methods", 1)) 28 | ) 29 | 30 | 31 | @dp.callback_query_handler(text_startswith="pvia_", state='*') 32 | async def choose_amount_of_money_to_buy(call: CallbackQuery, state: FSMContext): 33 | provider = call.data.replace("pvia_", "") 34 | await call.message.edit_text(await _("how_many_coins")) 35 | await call.message.edit_reply_markup(await get_inline_keyboard(f"pay_via_{provider}", 1)) 36 | 37 | await state.update_data(provider=provider) 38 | 39 | 40 | @dp.callback_query_handler(text_startswith="bcoins_", state="*") 41 | async def send_invoice_to_pay(call: CallbackQuery, state: FSMContext): 42 | dt = (call.data.replace("bcoins_", "")).split("_") 43 | data = await state.get_data() 44 | 45 | coins_amount = dt[0] 46 | currency = dt[1] 47 | total_amount = await get_amount(data['provider'], currency, coins_amount) 48 | providerToken = await db.get_provider_token(data['provider'], test=True) 49 | labaled_price = await _("invoice_prices_labaled_price_label") 50 | 51 | await state.update_data(currency=currency, total_amount=total_amount, 52 | coins_amount=coins_amount) 53 | 54 | await call.message.delete() 55 | await bot.send_invoice(call.from_user.id, 56 | title=(await _(f"invoice_title")), 57 | description=(await _("invoice_description")), 58 | payload=call.from_user.id, 59 | provider_token=providerToken, 60 | currency=currency.upper(), 61 | prices=[LabeledPrice(labaled_price, int(total_amount))], 62 | start_parameter="start", 63 | protect_content=True 64 | ) 65 | 66 | 67 | @dp.pre_checkout_query_handler(state="*") 68 | async def process_of_pre_checkout_query(query: PreCheckoutQuery, state: FSMContext): 69 | await bot.answer_pre_checkout_query(query.id, ok=True) 70 | await db.add_precheckout(query) 71 | await state.update_data(pre_checkout_id=query.id) 72 | 73 | 74 | @dp.callback_query_handler(text="buy_premium", state="*") 75 | async def buy_premium_for_coins(call: CallbackQuery, state: FSMContext): 76 | coins_amount = await db.get_user_coins(call.from_user.id) 77 | coins_for_premium = await db.get_coins_for_premium() 78 | user_status = await db.get_user_status(call.from_user.id) 79 | 80 | isEnough = (coins_amount - coins_for_premium) >= 0 81 | if user_status != "premium": 82 | if isEnough: 83 | await db.buy_premium_for_coins(call.from_user.id) 84 | await call.answer("👍🏻", show_alert=True) 85 | await premium_func(call.message, state) 86 | else: 87 | await call.answer(await _("not_enough_funds"), show_alert=True) 88 | else: 89 | await call.answer(await _("already_a_premium"), show_alert=True) 90 | 91 | -------------------------------------------------------------------------------- /buttons/inline.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | from aiogram.types import InlineKeyboardMarkup as kmarkup,\ 3 | InlineKeyboardButton as btn 4 | 5 | from loader import db 6 | 7 | tfb = { 8 | "uz": { 9 | }, 10 | "ru": { 11 | }, 12 | "en": { 13 | }, 14 | } 15 | 16 | # INLINE 17 | markup = { 18 | "uz": { 19 | "change_language_message": kmarkup().add(btn("🇺🇿O'zbek", callback_data="lang_uz")) 20 | .add(btn("🇷🇺Русский", callback_data="lang_ru")) 21 | .add(btn("🏴󠁧󠁢󠁥󠁮󠁧󠁿English", callback_data="lang_en")), 22 | 23 | "buy_premium": kmarkup().add( 24 | btn("💎 Premium sotib olish", callback_data="buy_premium") 25 | ), 26 | 27 | "buy_coins": kmarkup().add( 28 | btn("Tanga sotib olish", callback_data="buy_coins") 29 | ) 30 | }, 31 | "ru": { 32 | "change_language_message": kmarkup().add(btn("🇺🇿O'zbek", callback_data="lang_uz")) 33 | .add(btn("🇷🇺Русский", callback_data="lang_ru")) 34 | .add(btn("🏴󠁧󠁢󠁥󠁮󠁧󠁿English", callback_data="lang_en")), 35 | 36 | "buy_premium": kmarkup().add( 37 | btn("Купить 💎 Premium", callback_data="buy_premium") 38 | ), 39 | 40 | "buy_coins": kmarkup().add( 41 | btn("Купить монеты", callback_data="buy_coins") 42 | ) 43 | }, 44 | "en": { 45 | "change_language_message": kmarkup().add(btn("🇺🇿O'zbek", callback_data="lang_uz")) 46 | .add(btn("🇷🇺Русский", callback_data="lang_ru")) 47 | .add(btn("🏴󠁧󠁢󠁥󠁮󠁧󠁿English", callback_data="lang_en")), 48 | 49 | "buy_premium": kmarkup().add( 50 | btn("Buy 💎 Premium", callback_data="buy_premium") 51 | ), 52 | 53 | "buy_coins": kmarkup().add( 54 | btn("Buy Coins", callback_data="buy_coins") 55 | ) 56 | } 57 | } 58 | 59 | markup_f = { 60 | "uz": { 61 | 62 | }, 63 | "ru": { 64 | 65 | }, 66 | "en": { 67 | 68 | } 69 | } 70 | 71 | 72 | async def format_price(value, currency): 73 | if currency == "uzs" or currency == "rub": 74 | index = 0 75 | new_value = "" 76 | # 1 000 000,00 77 | isComma = True 78 | for e in str(value)[::-1]: 79 | # print(new_value, index, e) 80 | index += 1 81 | new_value += e 82 | if index == 2 and isComma: 83 | new_value += ',' 84 | isComma = False 85 | index = 0 86 | 87 | if index == 3 and not isComma: 88 | new_value += " " 89 | index = 0 90 | # print(new_value, index, e) 91 | 92 | return new_value[::-1] 93 | return value 94 | 95 | 96 | async def get_inline_keyboard_formattable(txt, user, locale): 97 | if txt == "payment_methods": 98 | methods_list = await db.get_payment_methods() 99 | k = kmarkup() 100 | for method in methods_list: 101 | k.add(btn(method['title'], callback_data=f"pvia_{method['name']}")) 102 | 103 | return k 104 | 105 | elif "pay_via_" in txt: 106 | provider = txt.replace("pay_via_","") 107 | pricing = await db.get_pricing_for_provider(provider) 108 | currency_names = {"uzs": "so'm", "usd": "dollars", "rub": "рубль"} 109 | k = kmarkup() 110 | for currency in pricing: 111 | for key, value in pricing[currency].items(): 112 | k.add(btn(f"{key} = {await format_price(value, currency)} {currency_names[currency]}", callback_data=f"bcoins_{key}_{currency}")) 113 | 114 | return k 115 | 116 | 117 | async def get_inline_keyboard(keyboards_text, is_format: [bool, int] =False): 118 | user = types.User.get_current() 119 | user_locale = await db.get_user_locale(user.id) 120 | 121 | if not is_format: 122 | return markup[user_locale][keyboards_text] 123 | return await get_inline_keyboard_formattable(keyboards_text, user, user_locale) -------------------------------------------------------------------------------- /texts/main.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | from loader import db 3 | import datetime as dt 4 | 5 | 6 | lang = { 7 | "uz": { 8 | "start_message": "Assalamu Alaykum", 9 | "settings_message": "⚙Sozlamalar", 10 | "change_language": "🚩Tilni tanlang", 11 | "language_changed": "Til o'zgartilindi", 12 | "buy_coins_call": "To'lov usulini tanlang", 13 | "how_many_coins": "Qancha tanga sotib olmoqchisiz?", 14 | 15 | "invoice_title": "Tangalar uchun to'lov", 16 | "invoice_description": "Tangalar sotib olish uchun pastdagi tugmani bosib, karta raqamingizni kiriting va to'lovni amalga oshiring.\n\n" + \ 17 | "Barcha pul o'tqazmalar xavfsiz. Telegram tomonlama amalga oshiriladi", 18 | "invoice_prices_labaled_price_label": "Tangalar", 19 | "expire_date": "Tugash sanasi:", 20 | "not_enough_funds": "Tangalar yetarli emas", 21 | "already_a_premium": "Siz premium foydalanuvchisiz.", 22 | "thanks_for_payment": "Ushbu botdan foydalanyotganingiz uchun rahmat.\nShu tangalar orqali 💎 Premium sotib olishingiz mumkin" 23 | }, 24 | "ru": { 25 | "start_message": "Здравствуйте", 26 | "settings_message": "⚙Настройки", 27 | "change_language": "🚩Выберите язык", 28 | "language_changed": "Язык изменен", 29 | "buy_coins_call": "Выберите метод оплаты", 30 | "how_many_coins": "Сколько монет вы хотите купить?", 31 | "invoice_title": "Оплата за монеты", 32 | "invoice_description": "Чтобы купить монет нажмите на кнопку ниже, введиты данные карты и совершите оплату\n\n" + \ 33 | "Все транзакции безопасны. Они осуществляются с помощью телеграм", 34 | "invoice_prices_labaled_price_label": "Монеты", 35 | "expire_date": "Истечение:", 36 | "not_enough_funds": "Монет не достаточно", 37 | "already_a_premium": "Вы являетесь Premium ползователем", 38 | "thanks_for_payment": "Спасибо что пользуетесь этим ботом.\nТеперь вы можете купить 💎 Premium используя эти монеты" 39 | }, 40 | "en": { 41 | "start_message": "Welcome", 42 | "settings_message": "⚙Settings", 43 | "change_language": "🚩Choose the language", 44 | "language_changed": "The language has been changed", 45 | "buy_coins_call": "Choose payment method", 46 | "how_many_coins": "How many coins would you like to purchase?", 47 | "invoice_title": "Payment for coins", 48 | "invoice_description": "To buy coins press on the button below, enter you credir card information and make a payment\n\n" + \ 49 | "All transactions are safe. They are made by Telegram.", 50 | "invoice_prices_labaled_price_label": "Coins", 51 | "expire_date": "Expire date:", 52 | "not_enough_funds": "Coins are not enough", 53 | "already_a_premium": "You are already a premium user", 54 | "thanks_for_payment": "Thank you for using us.\nNow you can buy 💎 Premium using this coins" 55 | } 56 | } 57 | 58 | lang_formattable = { 59 | "uz": { 60 | "premium_message": "📊 Sizning statusingiz: {}\n\n{} tanga evaziga 💎 Premium ga aylaning", 61 | "balance_message": "🪙 Balans: {} tanga\nTanga sotib olishni unutmang" 62 | }, 63 | "ru": { 64 | "premium_message": "📊 Ваш статус: {}\n\nПолучите 💎 Premium за {} монет", 65 | "balance_message": "🪙 Баланс: {} coins\nНе забывайте покупать монеты" 66 | }, 67 | "en": { 68 | "premium_message": "📊 Your status: {}\n\nBecome 💎 Premium for {} coins", 69 | "balance_message": "🪙 Balance: {} coins\nDo not forget to buy coins" 70 | } 71 | } 72 | 73 | 74 | async def get_formattable_lang(text, locale, user: types.User): 75 | respond = lang_formattable[locale][text] 76 | if text == "premium_message": 77 | user_status = await db.get_user_status(user.id) 78 | if user_status == "premium": 79 | exp = await db.get_expire_date(user.id) 80 | exp = dt.datetime.strptime(str(exp), "%Y-%m-%d %H:%M:%S.%f") 81 | exp = exp.strftime("%d/%m/%Y") 82 | user_status += f"\n{lang[locale]['expire_date']}: {exp}" 83 | respond = respond.format( 84 | user_status, await db.get_coins_for_premium() 85 | ) 86 | elif text == "balance_message": 87 | respond = respond.format( 88 | await db.get_user_coins(user.id) 89 | ) 90 | 91 | return respond 92 | 93 | 94 | async def get_lang(text, formattable: [bool, int] = False): 95 | user = types.User.get_current() 96 | user_locale = await db.get_user_locale(user.id) 97 | 98 | if not bool(formattable): 99 | return lang[user_locale][text] 100 | return await get_formattable_lang(text, user_locale, user) 101 | 102 | -------------------------------------------------------------------------------- /dbs/main.py: -------------------------------------------------------------------------------- 1 | from .models import User, Settings 2 | 3 | from motor.motor_asyncio import AsyncIOMotorClient 4 | from datetime import datetime 5 | from dateutil.relativedelta import relativedelta 6 | 7 | 8 | # MongoDB 9 | class Mongodb: 10 | def __init__(self, dbName, host=None, port=None): 11 | self.host = host if host else "localhost" 12 | self.port = port if port else 27017 13 | self.dbName = dbName 14 | 15 | self.client = AsyncIOMotorClient(host, port) 16 | 17 | self.db = self.client[self.dbName] 18 | self.users = self.db.users 19 | self.settings = self.db.settings 20 | self.payment_methods = self.db.payment_methods 21 | self.pre_checkout = self.db.pre_checkouts 22 | self.successful_payments = self.db.successful_payments 23 | 24 | async def _get_user(self, user_id): 25 | document = await self.users.find_one({"user_id": user_id}) 26 | if document: 27 | return User(document) 28 | return document 29 | 30 | async def _user_exists(self, user_id): 31 | result = await self._get_user(user_id) 32 | return bool(result) 33 | 34 | async def add_user(self, user_id, locale="en", status="user", expire_date=None, check_id=None): 35 | _user_exists = await self._user_exists(user_id) 36 | if not _user_exists: 37 | document = { 38 | "user_id": int(user_id), 39 | "locale": locale, 40 | "status": status, 41 | "expire_date": expire_date if expire_date else datetime.now(), 42 | "check_id": [], 43 | "coins": 0 44 | } 45 | result = await self.users.insert_one(document) 46 | return bool(result.inserted_id) 47 | return False 48 | 49 | async def get_user(self, user_id): 50 | document = await self.users.find_one({"user_id": user_id}) 51 | if document: 52 | return User(document) 53 | return document 54 | 55 | async def get_users(self): 56 | docs_list = [] 57 | async for doc in self.users.find(): 58 | docs_list.append(User(doc)) 59 | 60 | return docs_list 61 | 62 | async def get_user_locale(self, user_id): 63 | _exist = await self._user_exists(user_id) 64 | if _exist: 65 | user = await self.get_user(user_id) 66 | return user.locale 67 | else: 68 | await self.add_user(user_id) 69 | await self.get_user_locale(user_id) 70 | raise Exception 71 | 72 | async def change_user_locale(self, user_id, locale): 73 | _exist = await self._user_exists(user_id) 74 | if _exist: 75 | _user_locale = await self.get_user_locale(user_id) 76 | if _user_locale != locale: 77 | await self.users.update_one({"user_id": user_id}, {"$set": {"locale": locale}}) 78 | 79 | async def get_user_status(self, user_id): 80 | _exist = await self._user_exists(user_id) 81 | if _exist: 82 | user = await self.get_user(user_id) 83 | return user.status 84 | return None 85 | 86 | async def is_premium_user(self, user_id): 87 | cstatus = await self.get_user_status(user_id) 88 | if cstatus: 89 | return cstatus == "premium" 90 | return None 91 | 92 | async def get_user_coins(self, user_id): 93 | user = await self.get_user(user_id) 94 | if user: 95 | return user.coins 96 | return None 97 | 98 | async def get_coins_for_premium(self): 99 | result = Settings(await self.settings.find_one({"coins_for_premium": {"$gt": 0}})) 100 | return result.coins_for_premium 101 | 102 | async def get_payment_methods(self): 103 | documents = self.payment_methods.find() 104 | all = await documents.to_list(length=50) 105 | return all 106 | 107 | async def get_payment_method_currency(self, name): 108 | document = await self.payment_methods.find_one({"name": name}) 109 | return document.currencies 110 | 111 | async def get_pricing_for_provider(self, provider): 112 | coins_cost = await self.payment_methods.find_one({"name":provider}) 113 | pricing = coins_cost['cost'] 114 | return pricing 115 | 116 | async def get_provider_token(self, provider_name, test=False): 117 | document = await self.payment_methods.find_one({"name": provider_name}) 118 | if test: 119 | return document['token_test'] 120 | return document['token_live'] 121 | 122 | async def add_precheckout(self, tg_msg): 123 | new_msg = tg_msg 124 | new_msg['date_of_query'] = (datetime.now()).isoformat() 125 | await self.pre_checkout.insert_one(dict(new_msg)) 126 | 127 | async def add_coins(self, user_id, amount): 128 | user = await self.get_user(user_id) 129 | await self.users.update_one({"user_id": user_id}, {"$set": {"coins": (int(user.coins) + int(amount))}}) 130 | 131 | async def add_check_id(self, user_id, pre_checkout_id, coins_amount): 132 | user = await self.get_user(user_id) 133 | now = (datetime.now()).isoformat() 134 | 135 | new_list = user.check_id 136 | new_list.append({"pre_check_id": pre_checkout_id, 137 | "date_of_add": now, 138 | "coins_amount": coins_amount}) 139 | 140 | await self.users.update_one({"user_id": user_id}, {"$set": {"check_id": new_list}}) 141 | 142 | async def add_successful_payment(self, tg_msg, query_id, from_dev): 143 | new_msg = tg_msg 144 | new_msg['pre_checkout_id'] = query_id 145 | new_msg['date_of_it'] = (datetime.now()).isoformat() 146 | new_msg['from_dev'] = from_dev 147 | await self.successful_payments.insert_one(dict(new_msg)) 148 | 149 | async def buy_premium_for_coins(self, user_id): 150 | user = await self.get_user(user_id) 151 | coins_amount = user.coins 152 | needed = await self.get_coins_for_premium() 153 | expire_date = datetime.now() + relativedelta(months=1) 154 | await self.users.update_one({"user_id": user_id}, {"$set": { 155 | "coins": int(coins_amount) - int(needed), 156 | "status": "premium", 157 | "expire_date": expire_date}}) 158 | 159 | async def get_expire_date(self, user_id): 160 | user = await self.get_user(user_id) 161 | if user: 162 | return user.expire_date 163 | 164 | async def get_premium_back(self, user_id): 165 | user = await self.get_user(user_id) 166 | if user: 167 | await self.users.update_one({"user_id": user_id}, 168 | {"$set": { 169 | "status": "user" 170 | }}) 171 | 172 | 173 | async def main(): 174 | 175 | db_mongo = Mongodb(dbName="test_db") 176 | await db_mongo.add_check_id(10, "34322353") 177 | 178 | if __name__ == "__main__": 179 | import asyncio 180 | loop = asyncio.get_event_loop() 181 | loop.run_until_complete(main()) --------------------------------------------------------------------------------