Large refactor
This commit is contained in:
parent
fe5f531c8d
commit
69d63ca1ce
229
bwtbot.py
229
bwtbot.py
@ -1,214 +1,37 @@
|
|||||||
# -*- coding: utf-8 -*-
|
import logging
|
||||||
|
from os import getpid
|
||||||
|
|
||||||
from os import getpid, system
|
from convopyro import Conversation
|
||||||
from subprocess import call
|
|
||||||
from pyrogram import filters
|
|
||||||
from pyrogram.client import Client
|
|
||||||
from pyrogram.sync import idle
|
|
||||||
from pyrogram.types import (
|
|
||||||
ForceReply,
|
|
||||||
BotCommand,
|
|
||||||
BotCommandScopeChat,
|
|
||||||
Message,
|
|
||||||
ReplyKeyboardRemove,
|
|
||||||
)
|
|
||||||
from pyrogram.enums.chat_action import ChatAction
|
|
||||||
from convopyro import Conversation, listen_message
|
|
||||||
from functions import *
|
|
||||||
from modules.colors import *
|
|
||||||
from modules.bwt import *
|
|
||||||
|
|
||||||
config = jsonLoad("config.json")
|
from modules.app import PyroClient
|
||||||
|
|
||||||
owner_id = config["owner_id"]
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
app = Client(
|
format="%(name)s.%(funcName)s | %(levelname)s | %(message)s",
|
||||||
config["bot_name"],
|
datefmt="[%X]",
|
||||||
api_id=config["api_id"],
|
|
||||||
api_hash=config["api_hash"],
|
|
||||||
bot_token=config["bot_token"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Conversation(app)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import uvloop
|
||||||
|
|
||||||
|
uvloop.install()
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(
|
def main():
|
||||||
~filters.scheduled
|
client = PyroClient()
|
||||||
& filters.command(["setcard", "задать карту"], prefixes=["/", ""])
|
Conversation(client)
|
||||||
)
|
|
||||||
async def setcard(_: Client, msg: Message):
|
|
||||||
await msg.reply_text(
|
|
||||||
string("send_number"),
|
|
||||||
reply_markup=ForceReply(placeholder=string("enter_number")),
|
|
||||||
)
|
|
||||||
answer = await listen_message(_, msg.chat.id, timeout=None)
|
|
||||||
if answer is None:
|
|
||||||
return
|
|
||||||
elif answer.text.strip() in ["/cancel", "cancel", "/відміна", "відміна"]:
|
|
||||||
await msg.reply_text(string("cancel"), reply_markup=ReplyKeyboardRemove())
|
|
||||||
return
|
|
||||||
userSet(answer.from_user.id, "card", answer.text)
|
|
||||||
appendLog(f"User {str(msg.from_user.id)} set card id to {answer.text}")
|
|
||||||
await msg.reply_text(
|
|
||||||
string("card_linked").format(answer.text), reply_markup=ReplyKeyboardRemove()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(
|
|
||||||
~filters.scheduled
|
|
||||||
& filters.command(["resetcard", "забути картку"], prefixes=["/", ""])
|
|
||||||
)
|
|
||||||
async def resetcard(_: Client, msg: Message):
|
|
||||||
if "card" in jsonLoad("data/database.json")[str(msg.from_user.id)]:
|
|
||||||
userReset(msg.from_user.id, "card")
|
|
||||||
await msg.reply_text(string("card_unlinked"))
|
|
||||||
appendLog(f"User {str(msg.from_user.id)} reseted his card")
|
|
||||||
else:
|
|
||||||
await msg.reply_text(string("card_not_linked").format(string("get_number")))
|
|
||||||
appendLog(f"User {str(msg.from_user.id)} tried to reset non-existent card")
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(
|
|
||||||
~filters.scheduled & filters.command(["balance", "баланс"], prefixes=["/", ""])
|
|
||||||
)
|
|
||||||
async def balance(_: Client, msg: Message):
|
|
||||||
try:
|
try:
|
||||||
if "card" in jsonLoad("data/database.json")[str(msg.from_user.id)]:
|
client.run()
|
||||||
await app.send_chat_action(chat_id=msg.chat.id, action=ChatAction.TYPING)
|
except KeyboardInterrupt:
|
||||||
water_left = await getWaterLeft(
|
logger.warning(f"Forcefully shutting down with PID {getpid()}...")
|
||||||
userGet(msg.from_user.id, "card"), msg.from_user.id, app
|
finally:
|
||||||
)
|
exit()
|
||||||
if water_left == "":
|
|
||||||
await msg.reply_text(
|
|
||||||
string("error_new").format(
|
|
||||||
f'https://bwtaqua.com.ua/card-topup/?id={userGet(msg.from_user.id, "card")}'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# raise EmptyCardException("Card information is empty")
|
|
||||||
elif water_left == "Failure":
|
|
||||||
await msg.reply_text(
|
|
||||||
string("error_occured").format(string("get_number"))
|
|
||||||
)
|
|
||||||
appendLog(
|
|
||||||
f"User {str(msg.from_user.id)} could not get left water amount"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await msg.reply_text(string("card_balance").format(water_left))
|
|
||||||
appendLog(
|
|
||||||
f"User {str(msg.from_user.id)} has {water_left} liters remaining"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await msg.reply_text(string("card_not_linked").format(string("get_number")))
|
|
||||||
appendLog(
|
|
||||||
f"User {str(msg.from_user.id)} tried to get balance without card set"
|
|
||||||
)
|
|
||||||
except Exception as exp:
|
|
||||||
if msg.from_user.id != config["owner_id"]:
|
|
||||||
await msg.reply_text(string("error_occured").format(string("get_number")))
|
|
||||||
await app.send_message(
|
|
||||||
owner_id,
|
|
||||||
f"Error occured by {str(msg.from_user.id)}:\nException: `{exp}`\nTraceback: `{format_exc()}`",
|
|
||||||
)
|
|
||||||
appendLog(f"User {str(msg.from_user.id)} could not get left water amount")
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(
|
if __name__ == "__main__":
|
||||||
~filters.scheduled
|
main()
|
||||||
& filters.command(["topup", "refill", "поповнити"], prefixes=["/", ""])
|
|
||||||
)
|
|
||||||
async def topup_cmd(_: Client, msg: Message):
|
|
||||||
try:
|
|
||||||
if "card" in jsonLoad("data/database.json")[str(msg.from_user.id)]:
|
|
||||||
await app.send_chat_action(chat_id=msg.chat.id, action=ChatAction.TYPING)
|
|
||||||
await msg.reply_text(
|
|
||||||
string("top_up").format(str(userGet(msg.from_user.id, "card")))
|
|
||||||
)
|
|
||||||
appendLog(f"User {str(msg.from_user.id)} requested top up")
|
|
||||||
else:
|
|
||||||
await msg.reply_text(string("card_not_linked").format(string("get_number")))
|
|
||||||
appendLog(
|
|
||||||
f"User {str(msg.from_user.id)} tried to request top up without card set"
|
|
||||||
)
|
|
||||||
except Exception as exp:
|
|
||||||
await msg.reply_text(str(exp))
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(
|
|
||||||
~filters.scheduled
|
|
||||||
& filters.command(["start", "help", "допомога"], prefixes=["/", ""])
|
|
||||||
)
|
|
||||||
async def help(_: Client, msg: Message):
|
|
||||||
await msg.reply_text(string("welcome").format(string("get_number")))
|
|
||||||
if msg.from_user.language_code in jsonLoad("strings.json"):
|
|
||||||
userSet(msg.from_user.id, "locale", msg.from_user.language_code)
|
|
||||||
else:
|
|
||||||
userSet(msg.from_user.id, "locale", "en")
|
|
||||||
|
|
||||||
|
|
||||||
pid = getpid()
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(
|
|
||||||
~filters.scheduled & filters.command(["kill", "die", "shutdown"], prefixes="/")
|
|
||||||
)
|
|
||||||
async def kill(_: Client, msg: Message):
|
|
||||||
if msg.from_user.id == owner_id:
|
|
||||||
await msg.reply_text(f"Shutting down bot with pid **{pid}**")
|
|
||||||
system(f"kill -9 {pid}")
|
|
||||||
|
|
||||||
|
|
||||||
print(f"{nowtime()} {WHITE}Starting with PID {YELLOW}{pid}{RESET}")
|
|
||||||
|
|
||||||
app.start() # type: ignore
|
|
||||||
app.send_message(owner_id, f"Starting bot with pid **{pid}**") # type: ignore
|
|
||||||
|
|
||||||
app.set_bot_commands(
|
|
||||||
[
|
|
||||||
BotCommand("help", "Меню допомоги"),
|
|
||||||
BotCommand("balance", "Баланс картки"),
|
|
||||||
BotCommand("topup", "Поповнити картку"),
|
|
||||||
BotCommand("setcard", "Прив'язати картку"),
|
|
||||||
BotCommand("resetcard", "Відв'язати картку"),
|
|
||||||
],
|
|
||||||
language_code="uk",
|
|
||||||
) # type: ignore
|
|
||||||
|
|
||||||
app.set_bot_commands(
|
|
||||||
[
|
|
||||||
BotCommand("help", "Меню допомоги"),
|
|
||||||
BotCommand("balance", "Баланс картки"),
|
|
||||||
BotCommand("topup", "Поповнити картку"),
|
|
||||||
BotCommand("setcard", "Прив'язати картку"),
|
|
||||||
BotCommand("resetcard", "Відв'язати картку"),
|
|
||||||
],
|
|
||||||
language_code="ru",
|
|
||||||
) # type: ignore
|
|
||||||
|
|
||||||
app.set_bot_commands(
|
|
||||||
[
|
|
||||||
BotCommand("help", "Help menu"),
|
|
||||||
BotCommand("balance", "Card's balance"),
|
|
||||||
BotCommand("topup", "Refill card"),
|
|
||||||
BotCommand("setcard", "Link card"),
|
|
||||||
BotCommand("resetcard", "Unlink card"),
|
|
||||||
]
|
|
||||||
) # type: ignore
|
|
||||||
|
|
||||||
app.set_bot_commands(
|
|
||||||
[
|
|
||||||
BotCommand("help", "Help menu"),
|
|
||||||
BotCommand("balance", "Card's balance"),
|
|
||||||
BotCommand("topup", "Refill card"),
|
|
||||||
BotCommand("setcard", "Link card"),
|
|
||||||
BotCommand("resetcard", "Unlink card"),
|
|
||||||
BotCommand("shutdown", "Turn off the bot"),
|
|
||||||
],
|
|
||||||
scope=BotCommandScopeChat(chat_id=owner_id),
|
|
||||||
) # type: ignore
|
|
||||||
|
|
||||||
idle()
|
|
||||||
|
|
||||||
app.send_message(owner_id, f"Shutting down bot with pid **{pid}**") # type: ignore
|
|
||||||
print(f"\n{nowtime()} {WHITE}Shutting down with PID {YELLOW}{pid}{RESET}")
|
|
||||||
|
|
||||||
call(f"kill -9 {pid}", shell=True)
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"owner_id": 0,
|
"owner_id": 0,
|
||||||
"log_size": 1024,
|
"bot": {
|
||||||
"api_id": 0,
|
"api_id": 0,
|
||||||
"api_hash": "",
|
"api_hash": "",
|
||||||
"bot_token": "",
|
"bot_token": "",
|
||||||
"bot_name": "",
|
"workers": 1
|
||||||
|
},
|
||||||
"use_compiled_page_saver": false
|
"use_compiled_page_saver": false
|
||||||
}
|
}
|
125
functions.py
125
functions.py
@ -1,125 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from os import makedirs, stat
|
|
||||||
from gzip import open as gzipopen
|
|
||||||
from shutil import copyfileobj
|
|
||||||
from time import sleep
|
|
||||||
from ujson import loads, dumps
|
|
||||||
from modules.colors import *
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
users_path = "users/"
|
|
||||||
logs_folder = "logs/"
|
|
||||||
|
|
||||||
|
|
||||||
def jsonSave(filename, value):
|
|
||||||
with open(filename, "w", encoding="utf-8") as f:
|
|
||||||
f.write(dumps(value, indent=4, ensure_ascii=False))
|
|
||||||
|
|
||||||
|
|
||||||
def jsonLoad(filename):
|
|
||||||
with open(filename, "r", encoding="utf-8") as f:
|
|
||||||
value = loads(f.read())
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
config = jsonLoad(f"config.json")
|
|
||||||
|
|
||||||
log_size = config["log_size"]
|
|
||||||
owner_id = config["owner_id"]
|
|
||||||
|
|
||||||
|
|
||||||
def nowtime():
|
|
||||||
return f'{BBLACK}[{CYAN}{datetime.now().strftime("%H:%M:%S")}{BBLACK}]{RESET}'
|
|
||||||
|
|
||||||
|
|
||||||
def checkSize():
|
|
||||||
global logs_folder, log_size
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
while i < 2:
|
|
||||||
try:
|
|
||||||
log = stat(logs_folder + "latest.log")
|
|
||||||
|
|
||||||
if (log.st_size / 1024) > log_size:
|
|
||||||
with open(logs_folder + "latest.log", "rb") as f_in:
|
|
||||||
with gzipopen(
|
|
||||||
f'{logs_folder}{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.zip',
|
|
||||||
"wb",
|
|
||||||
) as f_out:
|
|
||||||
copyfileobj(f_in, f_out)
|
|
||||||
|
|
||||||
open(logs_folder + "latest.log", "w").close()
|
|
||||||
|
|
||||||
i = 2
|
|
||||||
|
|
||||||
except FileNotFoundError:
|
|
||||||
try:
|
|
||||||
log = open(logs_folder + "latest.log", "a")
|
|
||||||
open(logs_folder + "latest.log", "a").close()
|
|
||||||
except:
|
|
||||||
try:
|
|
||||||
makedirs(logs_folder, exist_ok=True)
|
|
||||||
log = open(logs_folder + "latest.log", "a")
|
|
||||||
open(logs_folder + "latest.log", "a").close()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
|
|
||||||
def appendLog(message):
|
|
||||||
global logs_folder
|
|
||||||
|
|
||||||
checkSize()
|
|
||||||
|
|
||||||
try:
|
|
||||||
log = open(logs_folder + "latest.log", "a")
|
|
||||||
open(logs_folder + "latest.log", "a").close()
|
|
||||||
except:
|
|
||||||
try:
|
|
||||||
makedirs(logs_folder, exist_ok=True)
|
|
||||||
log = open(logs_folder + "latest.log", "a")
|
|
||||||
open(logs_folder + "latest.log", "a").close()
|
|
||||||
except:
|
|
||||||
sleep(2)
|
|
||||||
print("Log file could not be created")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(message, flush=True)
|
|
||||||
log.write(f'[{datetime.now().strftime("%H:%M:%S | %d.%m.%Y")}] {message}\n')
|
|
||||||
|
|
||||||
log.close()
|
|
||||||
|
|
||||||
|
|
||||||
def string(key: str, *args: str, userlocale="uk"):
|
|
||||||
locales = jsonLoad("strings.json")
|
|
||||||
strings = locales[userlocale]
|
|
||||||
string = strings
|
|
||||||
for dict_key in args:
|
|
||||||
string = string[dict_key]
|
|
||||||
return string[key]
|
|
||||||
|
|
||||||
|
|
||||||
def userSet(userid, key: str, value):
|
|
||||||
database = jsonLoad("data/database.json")
|
|
||||||
if str(userid) not in database:
|
|
||||||
database[str(userid)] = {}
|
|
||||||
database[str(userid)][key] = value
|
|
||||||
jsonSave("data/database.json", database)
|
|
||||||
|
|
||||||
|
|
||||||
def userReset(userid, key: str):
|
|
||||||
database = jsonLoad("data/database.json")
|
|
||||||
del database[str(userid)][key]
|
|
||||||
jsonSave("data/database.json", database)
|
|
||||||
|
|
||||||
|
|
||||||
def userGet(userid, key: str):
|
|
||||||
try:
|
|
||||||
return jsonLoad("data/database.json")[str(userid)][key]
|
|
||||||
except KeyError:
|
|
||||||
return None
|
|
||||||
except FileNotFoundError:
|
|
||||||
return None
|
|
59
modules/app.py
Normal file
59
modules/app.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import logging
|
||||||
|
from os import getpid
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
|
from libbot import config_get
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.errors import BadRequest
|
||||||
|
from pyrogram.raw.all import layer
|
||||||
|
from ujson import loads
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PyroClient(Client):
|
||||||
|
def __init__(self):
|
||||||
|
with open("config.json", "r", encoding="utf-8") as f:
|
||||||
|
config = loads(f.read())
|
||||||
|
super().__init__(
|
||||||
|
name="bwtbot",
|
||||||
|
api_id=config["bot"]["api_id"],
|
||||||
|
api_hash=config["bot"]["api_hash"],
|
||||||
|
bot_token=config["bot"]["bot_token"],
|
||||||
|
workers=config["bot"]["workers"],
|
||||||
|
plugins=dict(root="plugins", exclude=config["disabled_plugins"]),
|
||||||
|
sleep_threshold=120,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
await super().start()
|
||||||
|
|
||||||
|
self.start_time = time()
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Bot is running with Pyrogram v%s (Layer %s) and has started as @%s on PID %s.",
|
||||||
|
pyrogram.__version__,
|
||||||
|
layer,
|
||||||
|
self.me.username,
|
||||||
|
getpid(),
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self.send_message(
|
||||||
|
chat_id=await config_get("chat_id", "reports"),
|
||||||
|
text=f"Bot started PID `{getpid()}`",
|
||||||
|
)
|
||||||
|
except BadRequest:
|
||||||
|
logger.warning("Unable to send message to report chat.")
|
||||||
|
|
||||||
|
async def stop(self):
|
||||||
|
try:
|
||||||
|
await self.send_message(
|
||||||
|
chat_id=await config_get("chat_id", "reports"),
|
||||||
|
text=f"Bot stopped with PID `{getpid()}`",
|
||||||
|
)
|
||||||
|
except BadRequest:
|
||||||
|
logger.warning("Unable to send message to report chat.")
|
||||||
|
await super().stop()
|
||||||
|
logger.warning(f"Bot stopped with PID {getpid()}.")
|
@ -1,13 +1,17 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
from os import makedirs, path
|
from os import makedirs, path
|
||||||
from subprocess import check_output
|
from subprocess import check_output
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from functions import *
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
|
|
||||||
config = jsonLoad("config.json")
|
from bs4 import BeautifulSoup
|
||||||
|
from libbot import config_get
|
||||||
|
|
||||||
|
from modules.utils import *
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EmptyCardException(Exception):
|
class EmptyCardException(Exception):
|
||||||
@ -21,9 +25,9 @@ async def getWaterLeft(cardid, filename, app=None):
|
|||||||
# if path.exists(f"data/pages/{str(filename)}.html") is False:
|
# if path.exists(f"data/pages/{str(filename)}.html") is False:
|
||||||
# run(["touch", f"data/pages/{str(filename)}.html"])
|
# run(["touch", f"data/pages/{str(filename)}.html"])
|
||||||
|
|
||||||
appendLog(f"Trying to get liters for url '{url}'")
|
logger.info(f"Trying to get liters for url '{url}'")
|
||||||
|
|
||||||
if config["use_compiled_page_saver"] is True:
|
if await config_get("use_compiled_page_saver") is True:
|
||||||
proc = check_output(
|
proc = check_output(
|
||||||
[
|
[
|
||||||
"PageSaver/pageSaver",
|
"PageSaver/pageSaver",
|
||||||
@ -58,12 +62,14 @@ async def getWaterLeft(cardid, filename, app=None):
|
|||||||
.replace(" л", "")
|
.replace(" л", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
appendLog(
|
logger.info(
|
||||||
f"Parsed {output} liters of water remaining (user: {str(filename)}, cardid: {cardid})"
|
f"Parsed {output} liters of water remaining (user: {str(filename)}, cardid: {cardid})"
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as exp:
|
except Exception as exp:
|
||||||
appendLog(f"Exception occured: {exp} (user: {str(filename)}, cardid: {cardid})")
|
logger.exception(
|
||||||
|
f"Exception occured: {exp} (user: {str(filename)}, cardid: {cardid})", exp
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tmp_name = str(uuid4())
|
tmp_name = str(uuid4())
|
||||||
@ -72,16 +78,16 @@ async def getWaterLeft(cardid, filename, app=None):
|
|||||||
f.write(html_file)
|
f.write(html_file)
|
||||||
except NameError:
|
except NameError:
|
||||||
tmp_name = "N/A"
|
tmp_name = "N/A"
|
||||||
appendLog(f"'html_file' is not defined so I won't gather any tmp data")
|
logger.warning(f"'html_file' is not defined so I won't gather any tmp data")
|
||||||
|
|
||||||
if app != None:
|
if app != None:
|
||||||
await app.send_message(
|
await app.send_message(
|
||||||
config["owner_id"],
|
await config_get("owner_id"),
|
||||||
f"**Exception occured:**\n • User: `{str(filename)}`\n • Card: [{cardid}]({url})\n • Exception: `{exp}`\n • TMP UUID: `{tmp_name}`\n • Traceback: `{format_exc()}`",
|
f"**Exception occured:**\n • User: `{str(filename)}`\n • Card: [{cardid}]({url})\n • Exception: `{exp}`\n • TMP UUID: `{tmp_name}`\n • Traceback: `{format_exc()}`",
|
||||||
disable_web_page_preview=True,
|
disable_web_page_preview=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
appendLog(f"Exception occured and could not send to user: {exp}")
|
logger.warning(f"Exception occurred and could not send to user: {exp}")
|
||||||
|
|
||||||
output = "Failure"
|
output = "Failure"
|
||||||
|
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
RESET = "\u001b[0m"
|
|
||||||
|
|
||||||
BLACK = "\u001b[30m"
|
|
||||||
RED = "\u001b[31m"
|
|
||||||
GREEN = "\u001b[32m"
|
|
||||||
YELLOW = "\u001b[33m"
|
|
||||||
BLUE = "\u001b[34m"
|
|
||||||
MAGENTA = "\u001b[35m"
|
|
||||||
CYAN = "\u001b[36m"
|
|
||||||
WHITE = "\u001b[37m"
|
|
||||||
|
|
||||||
BBLACK = "\u001b[30;1m"
|
|
||||||
BRED = "\u001b[31;1m"
|
|
||||||
BGREEN = "\u001b[32;1m"
|
|
||||||
BYELLOW = "\u001b[33;1m"
|
|
||||||
BBLUE = "\u001b[34;1m"
|
|
||||||
BMAGENTA = "\u001b[35;1m"
|
|
||||||
BCYAN = "\u001b[36;1m"
|
|
||||||
BWHITE = "\u001b[37;1m"
|
|
||||||
|
|
||||||
ULINE = "\u001b[4m"
|
|
||||||
REVERSE = "\u001b[7m"
|
|
35
modules/utils.py
Normal file
35
modules/utils.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from libbot import json_read, sync
|
||||||
|
|
||||||
|
|
||||||
|
async def string(key: str, *args: str, userlocale="uk"):
|
||||||
|
locales = await json_read("strings.json")
|
||||||
|
strings = locales[userlocale]
|
||||||
|
string = strings
|
||||||
|
for dict_key in args:
|
||||||
|
string = string[dict_key]
|
||||||
|
return string[key]
|
||||||
|
|
||||||
|
|
||||||
|
def userSet(userid, key: str, value):
|
||||||
|
database = sync.json_read("data/database.json")
|
||||||
|
if str(userid) not in database:
|
||||||
|
database[str(userid)] = {}
|
||||||
|
database[str(userid)][key] = value
|
||||||
|
sync.json_write(database, "data/database.json")
|
||||||
|
|
||||||
|
|
||||||
|
def userReset(userid, key: str):
|
||||||
|
database = sync.json_read("data/database.json")
|
||||||
|
del database[str(userid)][key]
|
||||||
|
sync.json_write(database, "data/database.json")
|
||||||
|
|
||||||
|
|
||||||
|
def userGet(userid, key: str):
|
||||||
|
try:
|
||||||
|
return sync.json_read("data/database.json")[str(userid)][key]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
except FileNotFoundError:
|
||||||
|
return None
|
63
plugins/balance.py
Normal file
63
plugins/balance.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from traceback import format_exc
|
||||||
|
|
||||||
|
from libbot import config_get, json_read
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.enums.chat_action import ChatAction
|
||||||
|
from pyrogram.types import Message
|
||||||
|
|
||||||
|
from modules.utils import string, userGet
|
||||||
|
from modules.bwt import getWaterLeft
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(
|
||||||
|
~filters.scheduled & filters.command(["balance", "баланс"], prefixes=["/", ""]) # type: ignore
|
||||||
|
)
|
||||||
|
async def command_balance(app: Client, msg: Message):
|
||||||
|
try:
|
||||||
|
if "card" in (await json_read("data/database.json"))[str(msg.from_user.id)]:
|
||||||
|
await app.send_chat_action(chat_id=msg.chat.id, action=ChatAction.TYPING)
|
||||||
|
water_left = await getWaterLeft(
|
||||||
|
userGet(msg.from_user.id, "card"), msg.from_user.id, app
|
||||||
|
)
|
||||||
|
if water_left == "":
|
||||||
|
await msg.reply_text(
|
||||||
|
(await string("error_new")).format(
|
||||||
|
f'https://bwtaqua.com.ua/card-topup/?id={userGet(msg.from_user.id, "card")}'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# raise EmptyCardException("Card information is empty")
|
||||||
|
elif water_left == "Failure":
|
||||||
|
await msg.reply_text(
|
||||||
|
(await string("error_occured")).format(await string("get_number"))
|
||||||
|
)
|
||||||
|
logger.warning(
|
||||||
|
f"User {str(msg.from_user.id)} could not get left water amount"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await msg.reply_text((await string("card_balance")).format(water_left))
|
||||||
|
logger.info(
|
||||||
|
f"User {str(msg.from_user.id)} has {water_left} liters remaining"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await msg.reply_text(
|
||||||
|
(await string("card_not_linked")).format(await string("get_number"))
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
f"User {str(msg.from_user.id)} tried to get balance without card set"
|
||||||
|
)
|
||||||
|
except Exception as exp:
|
||||||
|
if msg.from_user.id != await config_get("owner_id"):
|
||||||
|
await msg.reply_text(
|
||||||
|
(await string("error_occured")).format(await string("get_number"))
|
||||||
|
)
|
||||||
|
await app.send_message(
|
||||||
|
await config_get("owner_id"),
|
||||||
|
f"Error occured by {str(msg.from_user.id)}:\nException: `{exp}`\nTraceback: `{format_exc()}`",
|
||||||
|
)
|
||||||
|
logger.warning(f"User {str(msg.from_user.id)} could not get left water amount")
|
24
plugins/help.py
Normal file
24
plugins/help.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from libbot import json_read
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.types import Message
|
||||||
|
|
||||||
|
from modules.utils import string, userSet
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(
|
||||||
|
~filters.scheduled
|
||||||
|
& filters.command(["start", "help", "допомога"], prefixes=["/", ""]) # type: ignore
|
||||||
|
)
|
||||||
|
async def command_help(app: Client, msg: Message):
|
||||||
|
await msg.reply_text((await string("welcome")).format(await string("get_number")))
|
||||||
|
if msg.from_user.language_code in await json_read("strings.json"):
|
||||||
|
userSet(msg.from_user.id, "locale", msg.from_user.language_code)
|
||||||
|
else:
|
||||||
|
userSet(msg.from_user.id, "locale", "en")
|
60
plugins/register_commands.py
Normal file
60
plugins/register_commands.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from libbot import config_get
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.types import BotCommand, BotCommandScopeChat, Message
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(
|
||||||
|
~filters.scheduled & filters.command(["register_commands"], prefixes="/") # type: ignore
|
||||||
|
)
|
||||||
|
async def command_register_commands(app: Client, msg: Message):
|
||||||
|
if msg.from_user.id == await config_get("owner_id"):
|
||||||
|
app.set_bot_commands(
|
||||||
|
[
|
||||||
|
BotCommand("help", "Меню допомоги"),
|
||||||
|
BotCommand("balance", "Баланс картки"),
|
||||||
|
BotCommand("topup", "Поповнити картку"),
|
||||||
|
BotCommand("setcard", "Прив'язати картку"),
|
||||||
|
BotCommand("resetcard", "Відв'язати картку"),
|
||||||
|
],
|
||||||
|
language_code="uk",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
app.set_bot_commands(
|
||||||
|
[
|
||||||
|
BotCommand("help", "Меню допомоги"),
|
||||||
|
BotCommand("balance", "Баланс картки"),
|
||||||
|
BotCommand("topup", "Поповнити картку"),
|
||||||
|
BotCommand("setcard", "Прив'язати картку"),
|
||||||
|
BotCommand("resetcard", "Відв'язати картку"),
|
||||||
|
],
|
||||||
|
language_code="ru",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
app.set_bot_commands(
|
||||||
|
[
|
||||||
|
BotCommand("help", "Help menu"),
|
||||||
|
BotCommand("balance", "Card's balance"),
|
||||||
|
BotCommand("topup", "Refill card"),
|
||||||
|
BotCommand("setcard", "Link card"),
|
||||||
|
BotCommand("resetcard", "Unlink card"),
|
||||||
|
]
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
app.set_bot_commands(
|
||||||
|
[
|
||||||
|
BotCommand("help", "Help menu"),
|
||||||
|
BotCommand("balance", "Card's balance"),
|
||||||
|
BotCommand("topup", "Refill card"),
|
||||||
|
BotCommand("setcard", "Link card"),
|
||||||
|
BotCommand("resetcard", "Unlink card"),
|
||||||
|
BotCommand("shutdown", "Turn off the bot"),
|
||||||
|
],
|
||||||
|
scope=BotCommandScopeChat(chat_id=await config_get("owner_id")),
|
||||||
|
) # type: ignore
|
28
plugins/resetcard.py
Normal file
28
plugins/resetcard.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from libbot import json_read
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.types import Message
|
||||||
|
|
||||||
|
from modules.utils import string, userReset
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(
|
||||||
|
~filters.scheduled
|
||||||
|
& filters.command(["resetcard", "забути картку"], prefixes=["/", ""]) # type: ignore
|
||||||
|
)
|
||||||
|
async def command_resetcard(app: Client, msg: Message):
|
||||||
|
if "card" in (await json_read("data/database.json"))[str(msg.from_user.id)]:
|
||||||
|
userReset(msg.from_user.id, "card")
|
||||||
|
await msg.reply_text(await string("card_unlinked"))
|
||||||
|
logger.info(f"User {str(msg.from_user.id)} reseted his card")
|
||||||
|
else:
|
||||||
|
await msg.reply_text(
|
||||||
|
(await string("card_not_linked")).format(await string("get_number"))
|
||||||
|
)
|
||||||
|
logger.info(f"User {str(msg.from_user.id)} tried to reset non-existent card")
|
35
plugins/setcard.py
Normal file
35
plugins/setcard.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from convopyro import listen_message
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.types import ForceReply, Message, ReplyKeyboardRemove
|
||||||
|
|
||||||
|
from modules.utils import string, userSet
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(
|
||||||
|
~filters.scheduled
|
||||||
|
& filters.command(["setcard", "задать карту"], prefixes=["/", ""]) # type: ignore
|
||||||
|
)
|
||||||
|
async def command_setcard(app: Client, msg: Message):
|
||||||
|
await msg.reply_text(
|
||||||
|
await string("send_number"),
|
||||||
|
reply_markup=ForceReply(placeholder=await string("enter_number")),
|
||||||
|
)
|
||||||
|
answer = await listen_message(app, msg.chat.id, timeout=None)
|
||||||
|
if answer is None:
|
||||||
|
return
|
||||||
|
elif answer.text.strip() in ["/cancel", "cancel", "/відміна", "відміна"]:
|
||||||
|
await msg.reply_text(await string("cancel"), reply_markup=ReplyKeyboardRemove())
|
||||||
|
return
|
||||||
|
userSet(answer.from_user.id, "card", answer.text)
|
||||||
|
logger.info(f"User {str(msg.from_user.id)} set card id to {answer.text}")
|
||||||
|
await msg.reply_text(
|
||||||
|
(await string("card_linked")).format(answer.text),
|
||||||
|
reply_markup=ReplyKeyboardRemove(),
|
||||||
|
)
|
21
plugins/shutdown.py
Normal file
21
plugins/shutdown.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from os import getpid
|
||||||
|
|
||||||
|
from libbot import config_get
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.types import Message
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(
|
||||||
|
~filters.scheduled & filters.command(["kill", "die", "shutdown"], prefixes="/") # type: ignore
|
||||||
|
)
|
||||||
|
async def kill(app: Client, msg: Message):
|
||||||
|
if msg.from_user.id == await config_get("owner_id"):
|
||||||
|
await msg.reply_text(f"Shutting down bot with pid **{getpid()}**")
|
||||||
|
logger.info(f"Shutting down as requested by {msg.from_user.id}")
|
||||||
|
exit()
|
36
plugins/topup.py
Normal file
36
plugins/topup.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from libbot import json_read
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.enums.chat_action import ChatAction
|
||||||
|
from pyrogram.types import Message
|
||||||
|
|
||||||
|
from modules.utils import string, userGet
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(
|
||||||
|
~filters.scheduled
|
||||||
|
& filters.command(["topup", "refill", "поповнити"], prefixes=["/", ""]) # type: ignore
|
||||||
|
)
|
||||||
|
async def command_topup(app: Client, msg: Message):
|
||||||
|
try:
|
||||||
|
if "card" in (await json_read("data/database.json"))[str(msg.from_user.id)]:
|
||||||
|
await app.send_chat_action(chat_id=msg.chat.id, action=ChatAction.TYPING)
|
||||||
|
await msg.reply_text(
|
||||||
|
(await string("top_up")).format(str(userGet(msg.from_user.id, "card")))
|
||||||
|
)
|
||||||
|
logger.info(f"User {str(msg.from_user.id)} requested top up")
|
||||||
|
else:
|
||||||
|
await msg.reply_text(
|
||||||
|
(await string("card_not_linked")).format(await string("get_number"))
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
f"User {str(msg.from_user.id)} tried to request top up without card set"
|
||||||
|
)
|
||||||
|
except Exception as exp:
|
||||||
|
await msg.reply_text(str(exp))
|
@ -4,3 +4,6 @@ pathlib~=1.0.1
|
|||||||
pyrogram==2.0.106
|
pyrogram==2.0.106
|
||||||
tgcrypto==1.2.5
|
tgcrypto==1.2.5
|
||||||
ujson==5.7.0
|
ujson==5.7.0
|
||||||
|
uvloop==0.17.0
|
||||||
|
--extra-index-url https://git.end-play.xyz/api/packages/profitroll/pypi/simple
|
||||||
|
libbot[speed,pyrogram]==0.4
|
Reference in New Issue
Block a user