Compare commits

...

11 Commits

Author SHA1 Message Date
Profitroll
3b22cb0130 Using HoloUser 2022-12-11 23:32:35 +01:00
Profitroll
0e06c2a7a5 Now using HoloUser messaging 2022-12-11 23:32:20 +01:00
Profitroll
c5f9e96414 small notice added 2022-12-11 23:32:04 +01:00
Profitroll
a8d17237e1 now using global app 2022-12-11 23:31:36 +01:00
Profitroll
5af5bea805 nickname is now label 2022-12-11 23:31:12 +01:00
Profitroll
3aefe710e5 Slightly improved structure 2022-12-11 19:52:38 +01:00
Profitroll
b185dff664 Start is now Mongo-ready 2022-12-11 19:52:14 +01:00
Profitroll
199f470192 Reboot does not require kill anymore 2022-12-11 19:52:02 +01:00
Profitroll
ed748f70d3 Scheduler is now using asyncio 2022-12-11 19:51:46 +01:00
Profitroll
d40a17e668 Improving class 2022-12-11 19:12:41 +01:00
Profitroll
03ebeafdd4 Messages command updated 2022-12-11 18:50:50 +01:00
9 changed files with 113 additions and 75 deletions

View File

@ -1,9 +1,11 @@
from app import isAnAdmin
from typing import List, Union
from pyrogram.types import User, ChatMember, ChatPrivileges, Chat
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 modules.database import col_users, col_context, col_warnings, col_applications, col_sponsorships
from modules.utils import configGet
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"""
@ -20,7 +22,7 @@ class UserInvalidError(Exception):
class HoloUser():
def __init__(self, user: Union[List[User], User, ChatMember, int]) -> None:
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:
@ -31,6 +33,13 @@ class HoloUser():
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)
@ -42,9 +51,33 @@ class HoloUser():
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
async def set_label(self, app: Client, chat: Chat, label: str):
### 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:
@ -52,17 +85,19 @@ class HoloUser():
* 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, app: Client, chat: Chat):
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(

View File

@ -10,7 +10,7 @@ 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 NICKNAME`")
await msg.reply_text("Invalid syntax:\n`/label USER LABEL`")
return
target = await find_user(app, msg.command[1])
@ -19,15 +19,15 @@ async def cmd_label(app, msg):
target = HoloUser(target)
nickname = " ".join(msg.command[2:])
label = " ".join(msg.command[2:])
if nickname.lower() == "reset":
await target.reset_label(app, msg.chat)
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(app, msg.chat, nickname)
await msg.reply_text(f"Setting **{target.id}**'s label to **{nickname}**...", quote=should_quote(msg))
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")

View File

@ -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'")

View File

@ -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()
# ==============================================================================================================================

View File

@ -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))
# ==============================================================================================================================

View File

@ -5,19 +5,19 @@ 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)
@ -32,9 +32,7 @@ async def any_stage(app, msg):
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")
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))

View File

@ -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"))

View File

@ -1,4 +1,4 @@
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from datetime import datetime
from os import fsdecode, listdir, sep
from app import app
@ -6,7 +6,7 @@ from modules.utils import configGet, jsonLoad, locale, logWrite
from dateutil.relativedelta import relativedelta
from modules.database import col_applications
scheduler = BackgroundScheduler()
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}")

View File

@ -3,6 +3,7 @@
"required": [
"user",
"link",
"label",
"tg_name",
"tg_phone",
"tg_locale",
@ -14,23 +15,27 @@
"description": "Telegram ID of user"
},
"link": {
"bsonType": "string",
"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",
"bsonType": ["string", "null"],
"description": "Telegram phone number"
},
"tg_locale": {
"bsonType": "string",
"bsonType": ["string", "null"],
"description": "Telegram locale"
},
"tg_username": {
"bsonType": "string",
"bsonType": ["string", "null"],
"description": "Telegram username"
}
}