Merge branch 'dev'
This commit is contained in:
commit
09e5048d7f
1
.gitignore
vendored
1
.gitignore
vendored
@ -164,3 +164,4 @@ inline_bot.py
|
||||
data/applications.json
|
||||
!data/cache/avatars/.gitkeep
|
||||
data/cache/avatars/*
|
||||
.vscode
|
@ -1,9 +1,11 @@
|
||||
from os import path, sep
|
||||
from os import makedirs, path, sep
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.responses import FileResponse, JSONResponse
|
||||
from starlette.status import HTTP_404_NOT_FOUND
|
||||
from modules.utils import configGet
|
||||
|
||||
makedirs(f'{configGet("cache", "locations")}{sep}avatars', exist_ok=True)
|
||||
|
||||
app = FastAPI(title="HoloUA Avatars API", docs_url=None, redoc_url=None, version="1.0")
|
||||
|
||||
@app.get("/check", response_class=JSONResponse, include_in_schema=False)
|
||||
|
2
app.py
2
app.py
@ -4,7 +4,7 @@ from pyrogram.client import Client
|
||||
app = Client("holochecker", bot_token=configGet("bot_token", "bot"), api_id=configGet("api_id", "bot"), api_hash=configGet("api_hash", "bot"))
|
||||
|
||||
async def isAnAdmin(admin_id):
|
||||
if admin_id == configGet("owner") or admin_id in configGet("admins"):
|
||||
if (admin_id == configGet("owner")) or (admin_id in configGet("admins")):
|
||||
return True
|
||||
async for member in app.get_chat_members(configGet("admin_group")):
|
||||
if member.user.id == admin_id:
|
||||
|
0
cache/.gitkeep
vendored
0
cache/.gitkeep
vendored
0
cache/avatars/.gitkeep
vendored
0
cache/avatars/.gitkeep
vendored
105
classes/holo_user.py
Normal file
105
classes/holo_user.py
Normal file
@ -0,0 +1,105 @@
|
||||
from app import app, isAnAdmin
|
||||
from typing import Any, List, Union
|
||||
from pyrogram.types import User, ChatMember, ChatPrivileges, Chat, Message
|
||||
from pyrogram.client import Client
|
||||
from pyrogram.errors import bad_request_400
|
||||
from modules.database import col_users, col_context, col_warnings, col_applications, col_sponsorships, col_messages
|
||||
from modules.logging import logWrite
|
||||
from modules.utils import configGet, locale, should_quote
|
||||
|
||||
class UserNotFoundError(Exception):
|
||||
"""HoloUser could not find user with such an ID in database"""
|
||||
def __init__(self, user, user_id):
|
||||
self.user = user
|
||||
self.user_id = user_id
|
||||
super().__init__(f"User of type {type(self.user)} with id {self.user_id} was not found")
|
||||
|
||||
class UserInvalidError(Exception):
|
||||
"""Provided to HoloUser object is not supported"""
|
||||
def __init__(self, user):
|
||||
self.user = user
|
||||
super().__init__(f"Could not find HoloUser by using {type(self.user)} as an input type")
|
||||
|
||||
class HoloUser():
|
||||
|
||||
def __init__(self, user: Union[List[User], User, ChatMember, int, str]) -> None:
|
||||
|
||||
# Determine input object class and extract id
|
||||
if isinstance(user, list) and len(user) != 0:
|
||||
self.id = user[0].id
|
||||
elif isinstance(user, User):
|
||||
self.id = user.id
|
||||
elif isinstance(user, ChatMember):
|
||||
self.id = user.user.id
|
||||
elif isinstance(user, int):
|
||||
self.id = user
|
||||
elif isinstance(user, str):
|
||||
try:
|
||||
self.id = (app.get_users(user)).id # this line requires testing though
|
||||
except bad_request_400.UsernameNotOccupied:
|
||||
raise UserInvalidError(user)
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
raise UserInvalidError(user)
|
||||
else:
|
||||
raise UserInvalidError(user)
|
||||
|
||||
# Find user record in DB
|
||||
holo_user = col_users.find_one({"user": self.id})
|
||||
|
||||
if holo_user is None:
|
||||
raise UserNotFoundError(user=user, user_id=self.id)
|
||||
|
||||
self.db_id = holo_user["_id"]
|
||||
|
||||
self.link = holo_user["link"]
|
||||
self.label = holo_user["label"]
|
||||
self.name = holo_user["tg_name"]
|
||||
self.phone = holo_user["tg_phone"]
|
||||
self.locale = holo_user["tg_locale"]
|
||||
self.username = holo_user["tg_username"]
|
||||
|
||||
def set(self, key: str, value: Any) -> None:
|
||||
"""Set attribute data and save it into database
|
||||
|
||||
### Args:
|
||||
* `key` (`str`): Attribute to be changed
|
||||
* `value` (`Any`): Value to set
|
||||
"""
|
||||
if not hasattr(self, key):
|
||||
raise AttributeError()
|
||||
setattr(self, key, value)
|
||||
col_users.update_one(filter={"_id": self.db_id}, update={ "$set": { key: value } }, upsert=True)
|
||||
logWrite(f"Set attribute {key} of user {self.id} to {value}")
|
||||
|
||||
async def message(self, origin: Message, text: Union[str, None] = None, photo: Union[str, None] = None, video: Union[str, None] = None, file: Union[str, None] = None):
|
||||
new_message = await app.send_message(self.id, text+locale("message_reply_notice", "message"))
|
||||
await origin.reply_text(locale("message_sent", "message"), quote=should_quote(origin))
|
||||
logWrite(f"Admin {origin.from_user.id} sent message '{' '.join(origin.command[2:])}' to {self.id}")
|
||||
col_messages.insert_one({"origin": {"chat": origin.chat.id, "id": origin.id}, "destination": {"chat": new_message.chat.id, "id": new_message.id}})
|
||||
|
||||
async def set_label(self, chat: Chat, label: str):
|
||||
"""Set label in destination group
|
||||
|
||||
### Args:
|
||||
* app (`Client`): Pyrogram client
|
||||
* label (`str`): Label you want to set
|
||||
"""
|
||||
self.label = label
|
||||
self.set("label", label)
|
||||
await app.promote_chat_member(configGet("destination_group"), self.id)
|
||||
if (not await isAnAdmin(self.id)) and (chat.id == configGet("admin_group")):
|
||||
await app.set_administrator_title(configGet("destination_group"), self.id, label)
|
||||
|
||||
async def reset_label(self, chat: Chat):
|
||||
"""Reset label in destination group
|
||||
|
||||
### Args:
|
||||
* app (`Client`): Pyrogram client
|
||||
"""
|
||||
self.label = ""
|
||||
self.set("label", "")
|
||||
await app.set_administrator_title(configGet("destination_group"), self.id, "")
|
||||
if (not await isAnAdmin(self.id)) and (chat.id == configGet("admin_group")):
|
||||
await app.promote_chat_member(configGet("destination_group"), self.id, privileges=ChatPrivileges(
|
||||
can_manage_chat=False
|
||||
))
|
@ -4,8 +4,6 @@
|
||||
"owner": 0,
|
||||
"bot_id": 0,
|
||||
"age_allowed": 0,
|
||||
"birthdays_notify": true,
|
||||
"birthdays_time": "09:00",
|
||||
"api": "http://example.com",
|
||||
"inline_preview_count": 7,
|
||||
"admin_group": 0,
|
||||
@ -17,12 +15,28 @@
|
||||
"api_hash": "",
|
||||
"bot_token": ""
|
||||
},
|
||||
"database": {
|
||||
"user": null,
|
||||
"password": null,
|
||||
"host": "127.0.0.1",
|
||||
"port": 27017,
|
||||
"name": "holochecker"
|
||||
},
|
||||
"logging": {
|
||||
"size": 512,
|
||||
"location": "logs"
|
||||
},
|
||||
"scheduler": {
|
||||
"birthdays": {
|
||||
"time": 9,
|
||||
"enabled": true
|
||||
},
|
||||
"sponsorships": {
|
||||
"time": 9,
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"locations": {
|
||||
"data": "data",
|
||||
"cache": "cache",
|
||||
"locale": "locale"
|
||||
},
|
||||
@ -34,6 +48,7 @@
|
||||
"commands_admin": {
|
||||
"reboot": "Restart the bot",
|
||||
"message": "Send a message",
|
||||
"label": "Set user's nickname",
|
||||
"warnings": "Check user's warnings",
|
||||
"application": "Check user's application",
|
||||
"applications": "Retrieve all applications as a JSON"
|
||||
@ -41,6 +56,7 @@
|
||||
"commands_group_admin": {
|
||||
"reboot": "Restart the bot",
|
||||
"message": "Send a message",
|
||||
"label": "Set user's nickname",
|
||||
"warnings": "Check user's warnings",
|
||||
"application": "Check user's application",
|
||||
"applications": "Retrieve all applications as a JSON"
|
||||
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"filling": false,
|
||||
"applied": false,
|
||||
"approved": false,
|
||||
"stage": 0,
|
||||
"paid": null,
|
||||
"expires": null,
|
||||
"nickname": null
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{
|
||||
"stage": 0,
|
||||
"reapply": false,
|
||||
"link": null,
|
||||
"sent": false,
|
||||
"confirmed": false,
|
||||
"approved": false,
|
||||
"refused": false,
|
||||
"telegram_id": null,
|
||||
"telegram_name": null,
|
||||
"telegram_phone": null,
|
||||
"telegram_locale": null,
|
||||
"application": {
|
||||
"1": null,
|
||||
"2": null,
|
||||
"3": null,
|
||||
"4": null,
|
||||
"5": null,
|
||||
"6": null,
|
||||
"7": null,
|
||||
"8": null,
|
||||
"9": null,
|
||||
"10": null
|
||||
}
|
||||
}
|
86
holochecker.py
Normal file
86
holochecker.py
Normal file
@ -0,0 +1,86 @@
|
||||
from os import getpid, makedirs
|
||||
from modules.utils import *
|
||||
from modules.inline import *
|
||||
from app import app
|
||||
|
||||
from modules.commands_register import commands_register
|
||||
from pyrogram import idle
|
||||
|
||||
pid = getpid()
|
||||
|
||||
makedirs(f'{configGet("cache", "locations")}{sep}avatars', exist_ok=True)
|
||||
|
||||
# Importing
|
||||
from modules.commands.application import *
|
||||
from modules.commands.applications import *
|
||||
from modules.commands.label import *
|
||||
from modules.commands.message import *
|
||||
from modules.commands.reapply import *
|
||||
from modules.commands.reboot import *
|
||||
from modules.commands.rules import *
|
||||
from modules.commands.sponsorship import *
|
||||
from modules.commands.start import *
|
||||
from modules.commands.warn import *
|
||||
from modules.commands.warnings import *
|
||||
|
||||
from modules.callbacks.nothing import *
|
||||
from modules.callbacks.reapply import *
|
||||
from modules.callbacks.rules import *
|
||||
from modules.callbacks.sub import *
|
||||
from modules.callbacks.sus import *
|
||||
|
||||
from modules.handlers.confirmation import *
|
||||
from modules.handlers.contact import *
|
||||
from modules.handlers.group_join import *
|
||||
from modules.handlers.welcome import *
|
||||
from modules.handlers.everything import *
|
||||
|
||||
from modules.scheduled import *
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
logWrite(f"Starting up with pid {pid}")
|
||||
|
||||
# Yes, it should be in some kind of async main() function but I don't give a shit.
|
||||
# I did compare performance, almost no difference and it's much more useful this way. Change my mind.
|
||||
app.start()
|
||||
|
||||
# if configGet("birthdays_notify"):
|
||||
|
||||
# every().day.at(configGet("birthdays_time")).do(check_birthdays, app)
|
||||
|
||||
# # Background tasks checker
|
||||
# def background_task():
|
||||
# try:
|
||||
# while True:
|
||||
# try:
|
||||
# run_pending()
|
||||
# #print('Checked')
|
||||
# time.sleep(1)
|
||||
# except:
|
||||
# pass
|
||||
# except KeyboardInterrupt:
|
||||
# print('\nShutting down')
|
||||
# killProc(pid)
|
||||
# t = Thread(target=background_task)
|
||||
# t.start()
|
||||
|
||||
try:
|
||||
app.send_message(configGet("owner"), f"Starting up with pid `{pid}`")
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
logWrite(f"Could not send startup message to bot owner. Perhaps user has not started the bot yet.")
|
||||
|
||||
commands_register(app)
|
||||
|
||||
scheduler.start()
|
||||
|
||||
idle()
|
||||
|
||||
try:
|
||||
app.send_message(configGet("owner"), f"Shutting with pid `{pid}`")
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
logWrite(f"Could not send shutdown message to bot owner. Perhaps user has not started the bot yet.")
|
||||
|
||||
app.stop()
|
||||
|
||||
killProc(pid)
|
95
main.py
95
main.py
@ -1,95 +0,0 @@
|
||||
from threading import Thread
|
||||
from time import time
|
||||
from os import getpid, path
|
||||
from modules.birthdays import check_birthdays
|
||||
from modules.utils import *
|
||||
from modules.inline import *
|
||||
from schedule import run_pending, every
|
||||
from app import app
|
||||
|
||||
from modules.commands_register import commands_register
|
||||
from pyrogram import idle
|
||||
|
||||
|
||||
pid = getpid()
|
||||
|
||||
|
||||
for entry in [f"{configGet('data', 'locations')}{sep}applications.json", f"{configGet('data', 'locations')}{sep}warnings.json"]:
|
||||
mode = 'r' if path.exists(entry) else 'w'
|
||||
with open(entry, mode) as f:
|
||||
try:
|
||||
f.write("{}")
|
||||
except:
|
||||
pass
|
||||
|
||||
for entry in [f"{configGet('data', 'locations')}{sep}messages.json"]:
|
||||
mode = 'r' if path.exists(entry) else 'w'
|
||||
with open(entry, mode) as f:
|
||||
try:
|
||||
f.write("[]")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Importing
|
||||
from modules.commands.application import *
|
||||
from modules.commands.applications import *
|
||||
from modules.commands.message import *
|
||||
from modules.commands.reapply import *
|
||||
from modules.commands.reboot import *
|
||||
from modules.commands.rules import *
|
||||
from modules.commands.sponsorship import *
|
||||
from modules.commands.start import *
|
||||
from modules.commands.warn import *
|
||||
from modules.commands.warnings import *
|
||||
|
||||
from modules.callbacks.nothing import *
|
||||
from modules.callbacks.reapply import *
|
||||
from modules.callbacks.rules import *
|
||||
from modules.callbacks.sub import *
|
||||
from modules.callbacks.sus import *
|
||||
|
||||
from modules.handlers.confirmation import *
|
||||
from modules.handlers.contact import *
|
||||
from modules.handlers.group_join import *
|
||||
from modules.handlers.welcome import *
|
||||
from modules.handlers.everything import *
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
logWrite(f"Starting up with pid {pid}")
|
||||
|
||||
# Yes, it should be in some kind of async main() function but I don't give a shit.
|
||||
# I did compare performance, almost no difference and it's much more useful this way. Change my mind.
|
||||
app.start()
|
||||
|
||||
if configGet("birthdays_notify"):
|
||||
|
||||
every().day.at(configGet("birthdays_time")).do(check_birthdays, app)
|
||||
|
||||
# Background tasks checker
|
||||
def background_task():
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
run_pending()
|
||||
#print('Checked')
|
||||
time.sleep(1)
|
||||
except:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
print('\nShutting down')
|
||||
killProc(pid)
|
||||
t = Thread(target=background_task)
|
||||
t.start()
|
||||
|
||||
app.send_message(configGet("owner"), f"Starting up with pid `{pid}`")
|
||||
|
||||
commands_register(app)
|
||||
|
||||
idle()
|
||||
|
||||
app.send_message(configGet("owner"), f"Shutting with pid `{pid}`")
|
||||
|
||||
app.stop()
|
||||
|
||||
killProc(pid)
|
@ -1,18 +0,0 @@
|
||||
from datetime import datetime
|
||||
from os import fsdecode, listdir, sep
|
||||
from modules.utils import configGet, jsonLoad, locale
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
|
||||
def check_birthdays(app):
|
||||
for user_file in listdir(f"{configGet('data', 'locations')}{sep}users{sep}"):
|
||||
filename = fsdecode(f"{configGet('data', 'locations')}{sep}users{sep}{user_file}")
|
||||
if filename.endswith(".json"):
|
||||
user = jsonLoad(filename)
|
||||
if isinstance(user["application"]["2"], str):
|
||||
try:
|
||||
if ".".join([((user["application"]["2"]).split("."))[0], ((user["application"]["2"]).split("."))[1]]) == datetime.now().strftime("%d.%m"):
|
||||
tg_user = app.get_users(int(user_file.replace(".json", "")))
|
||||
app.send_message( configGet("admin_group"), locale("birthday", "message").format(str(tg_user.first_name), str(tg_user.username), str(relativedelta(datetime.now(), datetime.strptime(user["application"]["2"], '%d.%m.%Y')).years)) )
|
||||
except AttributeError:
|
||||
continue
|
@ -1,8 +1,10 @@
|
||||
from os import sep
|
||||
from os import sep, makedirs, remove
|
||||
from uuid import uuid1
|
||||
from app import app, isAnAdmin
|
||||
from pyrogram import filters
|
||||
from pyrogram.enums.chat_action import ChatAction
|
||||
from modules.utils import configGet, should_quote
|
||||
from modules.utils import configGet, should_quote, jsonSave
|
||||
from modules.database import col_applications
|
||||
|
||||
# Applications command =========================================================================================================
|
||||
@app.on_message(~ filters.scheduled & filters.command(["applications"], prefixes=["/"]))
|
||||
@ -10,5 +12,12 @@ async def cmd_applications(app, msg):
|
||||
|
||||
if (await isAnAdmin(msg.from_user.id)) or (msg.chat.id == configGet("admin_group")):
|
||||
await app.send_chat_action(msg.chat.id, ChatAction.UPLOAD_DOCUMENT)
|
||||
await msg.reply_document(document=f"{configGet('data', 'locations')}{sep}applications.json", quote=should_quote(msg))
|
||||
filename = uuid1()
|
||||
output = []
|
||||
for entry in col_applications.find():
|
||||
output.append(entry)
|
||||
makedirs("tmp", exist_ok=True)
|
||||
jsonSave(output, f"tmp{sep}{filename}.json")
|
||||
await msg.reply_document(document=f"tmp{sep}{filename}.json", file_name="applications", quote=should_quote(msg))
|
||||
remove(f"tmp{sep}{filename}.json")
|
||||
# ==============================================================================================================================
|
33
modules/commands/label.py
Normal file
33
modules/commands/label.py
Normal file
@ -0,0 +1,33 @@
|
||||
from app import app, isAnAdmin
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import ChatPrivileges
|
||||
from modules.utils import should_quote, find_user, configGet
|
||||
from classes.holo_user import HoloUser
|
||||
|
||||
@app.on_message(~ filters.scheduled & filters.private & filters.command(["label"], prefixes=["/"]))
|
||||
async def cmd_label(app, msg):
|
||||
|
||||
if msg.chat.id == configGet("admin_group") or await isAnAdmin(msg.from_user.id):
|
||||
|
||||
if len(msg.command) < 3:
|
||||
await msg.reply_text("Invalid syntax:\n`/label USER LABEL`")
|
||||
return
|
||||
|
||||
target = await find_user(app, msg.command[1])
|
||||
|
||||
if target is not None:
|
||||
|
||||
target = HoloUser(target)
|
||||
|
||||
label = " ".join(msg.command[2:])
|
||||
|
||||
if label.lower() == "reset":
|
||||
await target.reset_label(msg.chat)
|
||||
await msg.reply_text(f"Resetting **{target.id}**'s label...", quote=should_quote(msg))
|
||||
|
||||
else:
|
||||
await target.set_label(msg.chat, label)
|
||||
await msg.reply_text(f"Setting **{target.id}**'s label to **{label}**...", quote=should_quote(msg))
|
||||
|
||||
else:
|
||||
await msg.reply_text(f"User not found")
|
@ -2,7 +2,9 @@ from os import sep
|
||||
from app import app, isAnAdmin
|
||||
from pyrogram import filters
|
||||
from pyrogram.errors import bad_request_400
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.utils import jsonLoad, jsonSave, logWrite, locale, configGet, should_quote
|
||||
from modules.database import col_messages
|
||||
|
||||
# Message command ==============================================================================================================
|
||||
@app.on_message(~ filters.scheduled & filters.command(["message"], prefixes=["/"]))
|
||||
@ -11,36 +13,25 @@ async def cmd_message(app, msg):
|
||||
if msg.chat.id == configGet("admin_group") or await isAnAdmin(msg.from_user.id):
|
||||
|
||||
try:
|
||||
|
||||
try:
|
||||
destination = await app.get_users(int(msg.command[1]))
|
||||
if destination == [] or destination == None:
|
||||
raise TypeError
|
||||
except TypeError:
|
||||
try:
|
||||
destination = await app.get_users(msg.command[1])
|
||||
except bad_request_400.UsernameNotOccupied:
|
||||
await msg.reply_text(locale("message_no_user", "message"), quote=should_quote(msg))
|
||||
logWrite(f"Admin {msg.from_user.id} tried to send message '{' '.join(msg.command[2:])}' to '{msg.command[1]}' but 'UsernameNotOccupied'")
|
||||
return
|
||||
destination = HoloUser(int(msg.command[1]))
|
||||
except ValueError:
|
||||
try:
|
||||
destination = await app.get_users(msg.command[1])
|
||||
except bad_request_400.UsernameNotOccupied:
|
||||
await msg.reply_text(locale("message_no_user", "message"), quote=should_quote(msg))
|
||||
logWrite(f"Admin {msg.from_user.id} tried to send message '{' '.join(msg.command[2:])}' to '{msg.command[1]}' but 'UsernameNotOccupied'")
|
||||
return
|
||||
destination = HoloUser(msg.command[1])
|
||||
|
||||
void = msg.command[2]
|
||||
message = " ".join(msg.command[2:])
|
||||
try:
|
||||
new_message = await app.send_message(destination.id, message+locale("message_reply_notice", "message"))
|
||||
await msg.reply_text(locale("message_sent", "message"), quote=should_quote(msg))
|
||||
logWrite(f"Admin {msg.from_user.id} sent message '{' '.join(msg.command[2:])}' to {destination.id}")
|
||||
messages = jsonLoad(f"{configGet('data', 'locations')}{sep}messages.json")
|
||||
messages.append({"origin": {"chat": msg.chat.id, "id": msg.id}, "destination": {"chat": new_message.chat.id, "id": new_message.id}})
|
||||
jsonSave(messages, f"{configGet('data', 'locations')}{sep}messages.json")
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
await msg.reply_text(locale("message_no_user", "message"), quote=should_quote(msg))
|
||||
logWrite(f"Admin {msg.from_user.id} tried to send message '{' '.join(msg.command[2:])}' to {destination.id} but 'PeerIdInvalid'")
|
||||
|
||||
await destination.message(msg, msg.command[2:])
|
||||
|
||||
# try:
|
||||
# new_message = await app.send_message(destination.id, message+locale("message_reply_notice", "message"))
|
||||
# await msg.reply_text(locale("message_sent", "message"), quote=should_quote(msg))
|
||||
# logWrite(f"Admin {msg.from_user.id} sent message '{' '.join(msg.command[2:])}' to {destination.id}")
|
||||
# col_messages.insert_one({"origin": {"chat": msg.chat.id, "id": msg.id}, "destination": {"chat": new_message.chat.id, "id": new_message.id}})
|
||||
# except bad_request_400.PeerIdInvalid:
|
||||
# await msg.reply_text(locale("message_no_user", "message"), quote=should_quote(msg))
|
||||
# logWrite(f"Admin {msg.from_user.id} tried to send message '{' '.join(msg.command[2:])}' to {destination.id} but 'PeerIdInvalid'")
|
||||
except IndexError:
|
||||
await msg.reply_text(locale("message_invalid_syntax", "message"), quote=should_quote(msg))
|
||||
logWrite(f"Admin {msg.from_user.id} tried to send message but 'IndexError'")
|
||||
|
@ -1,7 +1,9 @@
|
||||
from app import app, isAnAdmin
|
||||
from os import getpid
|
||||
from sys import exit
|
||||
from pyrogram import filters
|
||||
from modules.utils import configGet, logWrite, killProc, should_quote
|
||||
from modules.utils import configGet, logWrite, should_quote
|
||||
from modules.scheduled import scheduler
|
||||
|
||||
pid = getpid()
|
||||
|
||||
@ -12,5 +14,6 @@ async def cmd_kill(app, msg):
|
||||
if msg.chat.id == configGet("admin_group") or await isAnAdmin(msg.from_user.id):
|
||||
logWrite(f"Shutting down bot with pid {pid}")
|
||||
await msg.reply_text(f"Вимкнення бота з підом `{pid}`", quote=should_quote(msg))
|
||||
killProc(pid)
|
||||
scheduler.shutdown()
|
||||
exit()
|
||||
# ==============================================================================================================================
|
@ -2,24 +2,27 @@ from app import app
|
||||
from os import sep
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import ReplyKeyboardMarkup
|
||||
from modules.utils import jsonLoad, jsonSave, configGet, configSet, locale, logWrite
|
||||
from modules.utils import locale, logWrite
|
||||
from modules.database import col_users
|
||||
|
||||
# Start command ================================================================================================================
|
||||
@app.on_message(~ filters.scheduled & filters.private & filters.command(["start"], prefixes=["/"]))
|
||||
async def cmd_start(app, msg):
|
||||
|
||||
try:
|
||||
user_stage = configGet("stage", file=str(msg.from_user.id))
|
||||
if user_stage != 0:
|
||||
return
|
||||
except FileNotFoundError:
|
||||
jsonSave(jsonLoad(f"{configGet('data', 'locations')}{sep}user_default.json"), f"{configGet('data', 'locations')}{sep}users{sep}{msg.from_user.id}.json")
|
||||
user_stage = configGet("stage", file=str(msg.from_user.id))
|
||||
configSet(["telegram_id"], str(msg.from_user.username), file=str(msg.from_user.id))
|
||||
configSet(["telegram_name"], f"{msg.from_user.first_name} {msg.from_user.last_name}", file=str(msg.from_user.id))
|
||||
configSet(["telegram_phone"], str(msg.from_user.phone_number), file=str(msg.from_user.id))
|
||||
configSet(["telegram_locale"], str(msg.from_user.language_code), file=str(msg.from_user.id))
|
||||
user = col_users.find_one({"user": msg.from_user.id})
|
||||
|
||||
logWrite(f"User {msg.from_user.id} started bot interaction")
|
||||
await msg.reply_text(locale("start", "message"), reply_markup=ReplyKeyboardMarkup(locale("welcome", "keyboard"), resize_keyboard=True))
|
||||
if user is None:
|
||||
|
||||
col_users.insert_one({
|
||||
"user": msg.from_user.id,
|
||||
"link": None,
|
||||
"label": "",
|
||||
"tg_name": msg.from_user.first_name,
|
||||
"tg_phone": msg.from_user.phone_number,
|
||||
"tg_locale": msg.from_user.language_code,
|
||||
"tg_username": msg.from_user.username
|
||||
})
|
||||
|
||||
logWrite(f"User {msg.from_user.id} started bot interaction")
|
||||
await msg.reply_text(locale("start", "message"), reply_markup=ReplyKeyboardMarkup(locale("welcome", "keyboard"), resize_keyboard=True))
|
||||
# ==============================================================================================================================
|
@ -1,3 +1,4 @@
|
||||
from modules.logging import logWrite
|
||||
from modules.utils import configGet
|
||||
from pyrogram.types import BotCommand, BotCommandScopeChat
|
||||
from pyrogram.errors import bad_request_400
|
||||
@ -24,16 +25,25 @@ def commands_register(app):
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
pass
|
||||
|
||||
app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=configGet("owner")))
|
||||
try:
|
||||
app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=configGet("owner")))
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
logWrite(f"Could not register commands for bot owner. Perhaps user has not started the bot yet.")
|
||||
|
||||
# Registering admin group commands
|
||||
commands_group_admin_list = []
|
||||
for command in configGet("commands_group_admin"):
|
||||
commands_group_admin_list.append(BotCommand(command, configGet("commands_group_admin")[command]))
|
||||
app.set_bot_commands(commands_group_admin_list, scope=BotCommandScopeChat(chat_id=configGet("admin_group")))
|
||||
try:
|
||||
app.set_bot_commands(commands_group_admin_list, scope=BotCommandScopeChat(chat_id=configGet("admin_group")))
|
||||
except bad_request_400.ChannelInvalid:
|
||||
logWrite(f"Could not register commands for admin group. Bot is likely not in the group.")
|
||||
|
||||
# Registering destination group commands
|
||||
commands_group_destination_list = []
|
||||
for command in configGet("commands_group_destination"):
|
||||
commands_group_destination_list.append(BotCommand(command, configGet("commands_group_destination")[command]))
|
||||
app.set_bot_commands(commands_group_destination_list, scope=BotCommandScopeChat(chat_id=configGet("destination_group")))
|
||||
try:
|
||||
app.set_bot_commands(commands_group_destination_list, scope=BotCommandScopeChat(chat_id=configGet("destination_group")))
|
||||
except bad_request_400.ChannelInvalid:
|
||||
logWrite(f"Could not register commands for destination group. Bot is likely not in the group.")
|
37
modules/database.py
Normal file
37
modules/database.py
Normal file
@ -0,0 +1,37 @@
|
||||
from pymongo import MongoClient
|
||||
from ujson import loads
|
||||
|
||||
with open("config.json", "r", encoding="utf-8") as f:
|
||||
db_config = loads(f.read())["database"]
|
||||
f.close()
|
||||
|
||||
if db_config["user"] is not None and db_config["password"] is not None:
|
||||
con_string = 'mongodb://{0}:{1}@{2}:{3}/{4}'.format(
|
||||
db_config["user"],
|
||||
db_config["password"],
|
||||
db_config["host"],
|
||||
db_config["port"],
|
||||
db_config["name"]
|
||||
)
|
||||
else:
|
||||
con_string = 'mongodb://{0}:{1}/{2}'.format(
|
||||
db_config["host"],
|
||||
db_config["port"],
|
||||
db_config["name"]
|
||||
)
|
||||
|
||||
db_client = MongoClient(con_string)
|
||||
db = db_client.get_database(name=db_config["name"])
|
||||
|
||||
collections = db.list_collection_names()
|
||||
|
||||
for collection in ["users", "context", "messages", "warnings", "applications", "sponsorships"]:
|
||||
if not collection in collections:
|
||||
db.create_collection(collection)
|
||||
|
||||
col_users = db.get_collection("users")
|
||||
col_context = db.get_collection("context")
|
||||
col_messages = db.get_collection("messages")
|
||||
col_warnings = db.get_collection("warnings")
|
||||
col_applications = db.get_collection("applications")
|
||||
col_sponsorships = db.get_collection("sponsorships")
|
@ -5,95 +5,93 @@ import asyncio
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import ForceReply, ReplyKeyboardMarkup, Message
|
||||
from modules.utils import configGet, configSet, jsonLoad, jsonSave, locale, logWrite, should_quote
|
||||
from modules.database import col_messages
|
||||
|
||||
async def message_involved(msg: Message):
|
||||
messages = jsonLoad(f"{configGet('data', 'locations')}{sep}messages.json")
|
||||
for message in messages:
|
||||
if (message["destination"]["id"] == msg.reply_to_message.id) and (message["destination"]["chat"] == msg.reply_to_message.chat.id):
|
||||
return True
|
||||
async def message_involved(msg: Message) -> bool:
|
||||
message = col_messages.find_one({"destination.id": msg.reply_to_message.id, "destination.chat": msg.reply_to_message.chat.id})
|
||||
if message is not None:
|
||||
return True
|
||||
return False
|
||||
|
||||
async def message_context(msg: Message):
|
||||
messages = jsonLoad(f"{configGet('data', 'locations')}{sep}messages.json")
|
||||
for message in messages:
|
||||
if (message["destination"]["id"] == msg.reply_to_message.id) and (message["destination"]["chat"] == msg.reply_to_message.chat.id):
|
||||
return message["origin"]["chat"], message["origin"]["id"]
|
||||
async def message_context(msg: Message) -> tuple:
|
||||
message = col_messages.find_one({"destination.id": msg.reply_to_message.id, "destination.chat": msg.reply_to_message.chat.id})
|
||||
if message is not None:
|
||||
return message["origin"]["chat"], message["origin"]["id"]
|
||||
return 0, 0
|
||||
|
||||
# Any other input ==============================================================================================================
|
||||
@app.on_message(~ filters.scheduled & filters.private)
|
||||
async def any_stage(app, msg):
|
||||
# @app.on_message(~ filters.scheduled & filters.private)
|
||||
# async def any_stage(app, msg):
|
||||
|
||||
if msg.via_bot is None:
|
||||
# if msg.via_bot is None:
|
||||
|
||||
if (msg.reply_to_message != None) and (await message_involved(msg)):
|
||||
context = await message_context(msg)
|
||||
if msg.chat.id == configGet("admin_group") or await isAnAdmin(msg.from_user.id):
|
||||
new_message = await (await app.get_messages(context[0], context[1])).reply_text(msg.text+locale("message_reply_notice", "message"), quote=True)
|
||||
else:
|
||||
new_message = await (await app.get_messages(context[0], context[1])).reply_text(locale("message_from", "message").format(msg.from_user.first_name, msg.from_user.id)+msg.text+locale("message_reply_notice", "message"), quote=True)
|
||||
await msg.reply_text(locale("message_sent", "message"), quote=should_quote(msg))
|
||||
messages = jsonLoad(f"{configGet('data', 'locations')}{sep}messages.json")
|
||||
messages.append({"origin": {"chat": msg.chat.id, "id": msg.id}, "destination": {"chat": new_message.chat.id, "id": new_message.id}})
|
||||
jsonSave(messages, f"{configGet('data', 'locations')}{sep}messages.json")
|
||||
return
|
||||
# if (msg.reply_to_message != None) and (await message_involved(msg)):
|
||||
# context = await message_context(msg)
|
||||
# if msg.chat.id == configGet("admin_group") or await isAnAdmin(msg.from_user.id):
|
||||
# new_message = await (await app.get_messages(context[0], context[1])).reply_text(msg.text+locale("message_reply_notice", "message"), quote=True)
|
||||
# else:
|
||||
# new_message = await (await app.get_messages(context[0], context[1])).reply_text(locale("message_from", "message").format(msg.from_user.first_name, msg.from_user.id)+msg.text+locale("message_reply_notice", "message"), quote=True)
|
||||
# await msg.reply_text(locale("message_sent", "message"), quote=should_quote(msg))
|
||||
# col_messages.insert_one({"origin": {"chat": msg.chat.id, "id": msg.id}, "destination": {"chat": new_message.chat.id, "id": new_message.id}})
|
||||
# return
|
||||
|
||||
user_stage = configGet("stage", file=str(msg.from_user.id))
|
||||
# user_stage = configGet("stage", file=str(msg.from_user.id))
|
||||
|
||||
if user_stage == 1:
|
||||
await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
# if user_stage == 1:
|
||||
# await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
# logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
# configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
|
||||
elif user_stage == 2:
|
||||
# elif user_stage == 2:
|
||||
|
||||
try:
|
||||
# try:
|
||||
|
||||
configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
|
||||
input_dt = datetime.strptime(msg.text, "%d.%m.%Y")
|
||||
# input_dt = datetime.strptime(msg.text, "%d.%m.%Y")
|
||||
|
||||
if datetime.now() <= input_dt:
|
||||
logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to joking")
|
||||
await msg.reply_text(locale("question2_joke", "message"), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
||||
# if datetime.now() <= input_dt:
|
||||
# logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to joking")
|
||||
# await msg.reply_text(locale("question2_joke", "message"), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
||||
|
||||
elif ((datetime.now() - input_dt).days) < ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days):
|
||||
logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to being underage")
|
||||
await msg.reply_text(locale("question2_underage", "message").format(str(configGet("age_allowed"))), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
||||
# elif ((datetime.now() - input_dt).days) < ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days):
|
||||
# logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to being underage")
|
||||
# await msg.reply_text(locale("question2_underage", "message").format(str(configGet("age_allowed"))), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
||||
|
||||
else:
|
||||
logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
# else:
|
||||
# logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
# await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
# configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
|
||||
except ValueError:
|
||||
logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to sending invalid date format")
|
||||
await msg.reply_text(locale(f"question2_invalid", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage}", "force_reply"))))
|
||||
# except ValueError:
|
||||
# logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to sending invalid date format")
|
||||
# await msg.reply_text(locale(f"question2_invalid", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage}", "force_reply"))))
|
||||
|
||||
else:
|
||||
if user_stage <= 9:
|
||||
logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
else:
|
||||
if not configGet("sent", file=str(msg.from_user.id)):
|
||||
if not configGet("confirmed", file=str(msg.from_user.id)):
|
||||
configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
application_content = []
|
||||
i = 1
|
||||
for question in configGet("application", file=str(msg.from_user.id)):
|
||||
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {configGet('application', file=str(msg.from_user.id))[question]}")
|
||||
i += 1
|
||||
await msg.reply_text(locale("confirm", "message").format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard"), resize_keyboard=True))
|
||||
#configSet("sent", True, file=str(msg.from_user.id))
|
||||
#configSet("application_date", int(time()), file=str(msg.from_user.id))
|
||||
else:
|
||||
if not configGet("approved", file=str(msg.from_user.id)) and not configGet("refused", file=str(msg.from_user.id)):
|
||||
await msg.reply_text(locale("already_sent", "message"))
|
||||
else:
|
||||
if not configGet("approved", file=str(msg.from_user.id)) and not configGet("refused", file=str(msg.from_user.id)):
|
||||
await msg.reply_text(locale("already_sent", "message"))
|
||||
# else:
|
||||
# if user_stage <= 9:
|
||||
# logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
# await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
# configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
# else:
|
||||
# if not configGet("sent", file=str(msg.from_user.id)):
|
||||
# if not configGet("confirmed", file=str(msg.from_user.id)):
|
||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
# application_content = []
|
||||
# i = 1
|
||||
# for question in configGet("application", file=str(msg.from_user.id)):
|
||||
# application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {configGet('application', file=str(msg.from_user.id))[question]}")
|
||||
# i += 1
|
||||
# await msg.reply_text(locale("confirm", "message").format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard"), resize_keyboard=True))
|
||||
# #configSet("sent", True, file=str(msg.from_user.id))
|
||||
# #configSet("application_date", int(time()), file=str(msg.from_user.id))
|
||||
# else:
|
||||
# if not configGet("approved", file=str(msg.from_user.id)) and not configGet("refused", file=str(msg.from_user.id)):
|
||||
# await msg.reply_text(locale("already_sent", "message"))
|
||||
# else:
|
||||
# if not configGet("approved", file=str(msg.from_user.id)) and not configGet("refused", file=str(msg.from_user.id)):
|
||||
# await msg.reply_text(locale("already_sent", "message"))
|
||||
|
||||
@app.on_message(~ filters.scheduled & filters.group)
|
||||
async def message_in_group(app, msg):
|
||||
|
@ -1,6 +1,7 @@
|
||||
from app import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import ForceReply, ReplyKeyboardMarkup
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.utils import configGet, configSet, locale, logWrite
|
||||
|
||||
# Welcome check ================================================================================================================
|
||||
@ -14,6 +15,8 @@ async def welcome_pass(app, msg, once_again: bool = True) -> None:
|
||||
* once_again (bool, optional): Set to False if it's the first time as user applies. Defaults to True.
|
||||
"""
|
||||
|
||||
holo_user = HoloUser(msg.from_user)
|
||||
|
||||
if not once_again:
|
||||
await msg.reply_text(locale("privacy_notice", "message"))
|
||||
|
||||
|
35
modules/scheduled.py
Normal file
35
modules/scheduled.py
Normal file
@ -0,0 +1,35 @@
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from datetime import datetime
|
||||
from os import fsdecode, listdir, sep
|
||||
from app import app
|
||||
from modules.utils import configGet, jsonLoad, locale, logWrite
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from modules.database import col_applications
|
||||
|
||||
scheduler = AsyncIOScheduler()
|
||||
|
||||
# for user_file in listdir(f"{configGet('data', 'locations')}{sep}users{sep}"):
|
||||
# filename = fsdecode(f"{configGet('data', 'locations')}{sep}users{sep}{user_file}")
|
||||
# if filename.endswith(".json"):
|
||||
# user = jsonLoad(filename)
|
||||
# if isinstance(user["application"]["2"], str):
|
||||
# try:
|
||||
# if ".".join([((user["application"]["2"]).split("."))[0], ((user["application"]["2"]).split("."))[1]]) == datetime.now().strftime("%d.%m"):
|
||||
# tg_user = await app.get_users(int(user_file.replace(".json", "")))
|
||||
# await app.send_message( configGet("admin_group"), locale("birthday", "message").format(str(tg_user.first_name), str(tg_user.username), str(relativedelta(datetime.now(), datetime.strptime(user["application"]["2"], '%d.%m.%Y')).years)) )
|
||||
# except AttributeError:
|
||||
# continue
|
||||
|
||||
if configGet("enabled", "scheduler", "birthdays"):
|
||||
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "birthdays"))
|
||||
async def check_birthdays():
|
||||
for entry in col_applications.find({"2": datetime.now().strftime("%d.%m.%Y")}):
|
||||
tg_user = await app.get_users(entry["user"])
|
||||
await app.send_message( configGet("admin_group"), locale("birthday", "message").format(str(tg_user.first_name), str(tg_user.username), str(relativedelta(datetime.now(), datetime.strptime(entry["2"], '%d.%m.%Y')).years)) ) # type: ignore
|
||||
logWrite(f"Notified admins about {entry['user']}'s birthday")
|
||||
logWrite("Birthdays check performed")
|
||||
|
||||
if configGet("enabled", "scheduler", "sponsorships"):
|
||||
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "sponsorships"))
|
||||
async def check_sponsors():
|
||||
logWrite("Sponsorships check performed")
|
@ -1,5 +1,8 @@
|
||||
from typing import Any, Union
|
||||
from pyrogram.enums.chat_type import ChatType
|
||||
from pyrogram.types import User
|
||||
from pyrogram.client import Client
|
||||
from pyrogram.errors import bad_request_400
|
||||
from ujson import JSONDecodeError as JSONDecodeError
|
||||
from ujson import loads, dumps
|
||||
|
||||
@ -49,11 +52,11 @@ def nested_set(dic, keys, value, create_missing=True):
|
||||
def configSet(keys: list, value: Any, file: str = "config", create_missing=True):
|
||||
"""Set config's value to provided one
|
||||
|
||||
Args:
|
||||
* keys (list): List of keys from the highest one to target
|
||||
* value (Any): Needed value
|
||||
* file (str, optional): File (if not config). Defaults to "config".
|
||||
* create_missing (bool, optional): Create missing items on the way. Defaults to True.
|
||||
### Args:
|
||||
* keys (`list`): List of keys from the highest one to target
|
||||
* value (`Any`): Needed value
|
||||
* file (`str`, optional): File (if not config). Defaults to "config".
|
||||
* create_missing (`bool`, optional): Create missing items on the way. Defaults to True.
|
||||
"""
|
||||
if file == "config":
|
||||
filepath = ""
|
||||
@ -74,11 +77,11 @@ def configSet(keys: list, value: Any, file: str = "config", create_missing=True)
|
||||
|
||||
def configGet(key: str, *args: str, file: str = "config"):
|
||||
"""Get value of the config key
|
||||
Args:
|
||||
* key (str): The last key of the keys path.
|
||||
* *args (str): Path to key like: dict[args][key].
|
||||
* file (str): User ID to load. Loads config if not provided. Defaults to "config".
|
||||
Returns:
|
||||
### Args:
|
||||
* key (`str`): The last key of the keys path.
|
||||
* *args (`str`): Path to key like: dict[args][key].
|
||||
* file (`str`): User ID to load. Loads config if not provided. Defaults to "config".
|
||||
### Returns:
|
||||
* any: Value of provided key
|
||||
"""
|
||||
if file == "config":
|
||||
@ -99,16 +102,19 @@ def configGet(key: str, *args: str, file: str = "config"):
|
||||
this_key = this_key[dict_key]
|
||||
return this_key[key]
|
||||
|
||||
def locale(key: str, *args: str, locale=configGet("locale")) -> Union[str, list, dict]:
|
||||
def locale(key: str, *args: str, locale: Union[str, User] = configGet("locale")) -> Any:
|
||||
"""Get value of locale string
|
||||
Args:
|
||||
* key (str): The last key of the locale's keys path.
|
||||
* *args (list): Path to key like: dict[args][key].
|
||||
* locale (str): Locale to looked up in. Defaults to config's locale value.
|
||||
Returns:
|
||||
* any: Value of provided locale key
|
||||
### Args:
|
||||
* key (`str`): The last key of the locale's keys path.
|
||||
* *args (`list`): Path to key like: dict[args][key].
|
||||
* locale (`Union[str, User]`): Locale to looked up in. Provide User to get his `.language_code`. Defaults to config's locale value.
|
||||
### Returns:
|
||||
* any: Value of provided locale key. In normal case must be `str`, `dict` or `list`.
|
||||
"""
|
||||
if (locale == None):
|
||||
if isinstance(locale, User):
|
||||
locale = locale.language_code
|
||||
|
||||
if locale is None:
|
||||
locale = configGet("locale")
|
||||
|
||||
try:
|
||||
@ -145,3 +151,19 @@ def killProc(pid):
|
||||
|
||||
def should_quote(msg):
|
||||
return True if msg.chat.type is not ChatType.PRIVATE else False
|
||||
|
||||
async def find_user(app: Client, query: Union[str, int]):
|
||||
try:
|
||||
result = await app.get_users(int(query))
|
||||
if result == [] or result == None:
|
||||
raise TypeError
|
||||
except (TypeError, ValueError):
|
||||
try:
|
||||
result = await app.get_users(query)
|
||||
except bad_request_400.UsernameNotOccupied:
|
||||
return None
|
||||
except bad_request_400.UsernameInvalid:
|
||||
return None
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
return None
|
||||
return result
|
@ -1,7 +1,9 @@
|
||||
pyrogram>=2.0.59
|
||||
tgcrypto>=1.2.4
|
||||
ujson>=5.5.0
|
||||
psutil>=5.9.2
|
||||
schedule
|
||||
fastapi
|
||||
uvicorn[standard]
|
||||
APScheduler==3.9.1.post1
|
||||
fastapi==0.88.0
|
||||
psutil==5.9.4
|
||||
pymongo==4.3.3
|
||||
Pyrogram==2.0.69
|
||||
tgcrypto==1.2.5
|
||||
python_dateutil==2.8.2
|
||||
starlette==0.22.0
|
||||
ujson==5.6.0
|
6
validation/applications.json
Normal file
6
validation/applications.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"$jsonSchema": {
|
||||
"required": [],
|
||||
"properties": {}
|
||||
}
|
||||
}
|
6
validation/context.json
Normal file
6
validation/context.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"$jsonSchema": {
|
||||
"required": [],
|
||||
"properties": {}
|
||||
}
|
||||
}
|
36
validation/messages.json
Normal file
36
validation/messages.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"$jsonSchema": {
|
||||
"required": [
|
||||
"origin",
|
||||
"origin.chat",
|
||||
"origin.id",
|
||||
"destination",
|
||||
"destination.chat",
|
||||
"destination.id"
|
||||
],
|
||||
"properties": {
|
||||
"origin": {
|
||||
"bsonType": "object"
|
||||
},
|
||||
"origin.chat": {
|
||||
"bsonType": ["int", "long"],
|
||||
"description": "Telegram ID of message's origin chat"
|
||||
},
|
||||
"origin.id": {
|
||||
"bsonType": ["int", "long"],
|
||||
"description": "ID of message in origin chat"
|
||||
},
|
||||
"destination": {
|
||||
"bsonType": "object"
|
||||
},
|
||||
"destination.chat": {
|
||||
"bsonType": ["int", "long"],
|
||||
"description": "Telegram ID of message's destination chat"
|
||||
},
|
||||
"destination.id": {
|
||||
"bsonType": ["int", "long"],
|
||||
"description": "ID of message in destination chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
validation/sponsorships.json
Normal file
6
validation/sponsorships.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"$jsonSchema": {
|
||||
"required": [],
|
||||
"properties": {}
|
||||
}
|
||||
}
|
43
validation/users.json
Normal file
43
validation/users.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"$jsonSchema": {
|
||||
"required": [
|
||||
"user",
|
||||
"link",
|
||||
"label",
|
||||
"tg_name",
|
||||
"tg_phone",
|
||||
"tg_locale",
|
||||
"tg_username"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"bsonType": ["int", "long"],
|
||||
"description": "Telegram ID of user"
|
||||
},
|
||||
"link": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Invite link to destination group"
|
||||
},
|
||||
"label": {
|
||||
"bsonType": "string",
|
||||
"description": "Label given by admins"
|
||||
},
|
||||
"tg_name": {
|
||||
"bsonType": "string",
|
||||
"description": "Telegram first name"
|
||||
},
|
||||
"tg_phone": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Telegram phone number"
|
||||
},
|
||||
"tg_locale": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Telegram locale"
|
||||
},
|
||||
"tg_username": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Telegram username"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
validation/warnings.json
Normal file
6
validation/warnings.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"$jsonSchema": {
|
||||
"required": [],
|
||||
"properties": {}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user