├── 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())
--------------------------------------------------------------------------------