Compare commits
148 Commits
e61aa17a72
...
v.1.2
Author | SHA1 | Date | |
---|---|---|---|
95be1e72d3 | |||
ecbf7d8b78 | |||
92386ac8ce | |||
dabfa2ecef | |||
00a408ac6c | |||
b67b1daf7c | |||
f83751c07d | |||
f5e3cd5a50 | |||
478fb174c5 | |||
30dfe4ff04 | |||
bdc775dcbd | |||
717d636497 | |||
64b0562bc4 | |||
eced1b7984 | |||
da3dd3a2fe | |||
3e166a3fca | |||
d090b18655 | |||
e2d28f442c | |||
496240c48b | |||
|
0bf5ae70eb | ||
|
bcaf80e2e1 | ||
|
21bf460b28 | ||
|
a4bbb837d7 | ||
|
1a438fc32e | ||
234b73add0 | |||
742b529c33 | |||
78a37ca186 | |||
374effd5d7 | |||
|
1195df894c | ||
|
67f1ce535f | ||
|
b6d45545fc | ||
|
59dafc004d | ||
|
57518399a1 | ||
|
ee288a1983 | ||
373f2332a0 | |||
f4fb85f7a4 | |||
02a6960391 | |||
7939f8b65e | |||
5b28f9f588 | |||
6e44177907 | |||
4f0b9f8e3a | |||
78dee0591c | |||
b0b0f04a9b | |||
9e009aea43 | |||
42d00383bf | |||
4fba305b05 | |||
47e62946ab | |||
68c7cc0ada | |||
646db667d9 | |||
2e8277d6d2 | |||
19fc9308e4 | |||
c90495eb1c | |||
|
bdb2338ab9 | ||
|
496bb7d4a6 | ||
|
b437092fe7 | ||
|
9431763e6b | ||
|
4977b8f31a | ||
|
0739eeb87d | ||
|
0214a29a2e | ||
|
6b80b7d0fa | ||
|
3fd56e8b41 | ||
|
3eef04794a | ||
|
d59a1671b3 | ||
|
ccbc135ee4 | ||
083281e784 | |||
8cb3ef283b | |||
|
1268c33830 | ||
|
aad5c4f9f2 | ||
|
3d4dd29205 | ||
|
ff95d9556d | ||
|
b3c5f060a1 | ||
|
096a0498f8 | ||
|
d7936fa600 | ||
3442a478d4 | |||
ee7f9712c8 | |||
79304816b0 | |||
ccebccf086 | |||
b383ab6001 | |||
db60a538b2 | |||
e79edf1dff | |||
7edffd0b40 | |||
c8f89a7447 | |||
ea1dc542a3 | |||
6aa8128fc6 | |||
7854f88217 | |||
b401028dd1 | |||
642c23dd61 | |||
b2613c25a4 | |||
a7038e9d8f | |||
|
a59a7b738c | ||
626492fb3c | |||
1aed7bff7b | |||
ba13f36769 | |||
a82adc4d1f | |||
fe6d2514c7 | |||
2cfa5a8f8d | |||
950666e4ad | |||
ace71fd6be | |||
|
25be843cd8 | ||
|
e6589fc3e5 | ||
|
8b2abc2cfa | ||
|
c763fc537b | ||
|
22011829a5 | ||
|
e59aa98fd5 | ||
|
082acc85cf | ||
|
87d9afe74a | ||
|
5e06859b56 | ||
|
47896faf06 | ||
|
85112dc653 | ||
|
af862a3454 | ||
|
1eb98750a7 | ||
|
eecb71a91e | ||
|
426b1550f6 | ||
|
0302d8c1ae | ||
|
5a6a96d3f9 | ||
|
12da1b2376 | ||
|
7db8c9ac5c | ||
95e9fdf460 | |||
ac5a0d112f | |||
2db19acf6c | |||
6874268154 | |||
a906c0a1cc | |||
bc54abcc97 | |||
1b6f429be9 | |||
be55f8a3b1 | |||
d3945eea0c | |||
|
b345a5d776 | ||
|
f905a5c4df | ||
|
f4a2e655a6 | ||
|
741a01cff6 | ||
|
6b00f181f6 | ||
|
41eb6e46ee | ||
|
1d5ebd02fe | ||
|
43ce2d73b6 | ||
|
797d9de7e4 | ||
|
438f8f8c44 | ||
|
a769ea9ef5 | ||
|
fa08679b11 | ||
|
e5514cac7c | ||
|
8ccd2a858a | ||
|
8bb7c58c2a | ||
3b71cb3d85 | |||
09e5048d7f | |||
de4126b1a3 | |||
11da9de887 | |||
a3830f672f | |||
085a833b16 | |||
bc8cd8a8ce |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -157,11 +157,10 @@ config.json
|
|||||||
config_debug.json
|
config_debug.json
|
||||||
*.session
|
*.session
|
||||||
*.session-journal
|
*.session-journal
|
||||||
users
|
data
|
||||||
!users/.gitkeep
|
|
||||||
TASK.md
|
TASK.md
|
||||||
inline_bot.py
|
inline_bot.py
|
||||||
data/applications.json
|
.vscode
|
||||||
!data/cache/avatars/.gitkeep
|
migrate.py
|
||||||
data/cache/avatars/*
|
validation/*
|
||||||
.vscode
|
!validation/*.json
|
201
README.md
201
README.md
@@ -32,14 +32,16 @@ You can see config file with all the comments below:
|
|||||||
"locale": "uk",
|
"locale": "uk",
|
||||||
"debug": false,
|
"debug": false,
|
||||||
"owner": 0,
|
"owner": 0,
|
||||||
"bot_id": 0,
|
|
||||||
"age_allowed": 0,
|
"age_allowed": 0,
|
||||||
"api": "http://example.com",
|
"api": "http://example.com",
|
||||||
"inline_preview_count": 7,
|
"inline_preview_count": 7,
|
||||||
"admin_group": 0,
|
|
||||||
"destination_group": 0,
|
|
||||||
"remove_application_time": -1,
|
"remove_application_time": -1,
|
||||||
|
"search_radius": 50,
|
||||||
"admins": [],
|
"admins": [],
|
||||||
|
"groups": {
|
||||||
|
"admin": 0,
|
||||||
|
"users": 0
|
||||||
|
},
|
||||||
"bot": {
|
"bot": {
|
||||||
"api_id": 0,
|
"api_id": 0,
|
||||||
"api_hash": "",
|
"api_hash": "",
|
||||||
@@ -59,6 +61,29 @@ You can see config file with all the comments below:
|
|||||||
"size": 512,
|
"size": 512,
|
||||||
"location": "logs"
|
"location": "logs"
|
||||||
},
|
},
|
||||||
|
"features": {
|
||||||
|
"general": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"applications": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"sponsorships": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"warnings": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"invites_check": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"dinovoice": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"spoilers": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"scheduler": {
|
"scheduler": {
|
||||||
"birthdays": {
|
"birthdays": {
|
||||||
"time": 9,
|
"time": 9,
|
||||||
@@ -67,6 +92,18 @@ You can see config file with all the comments below:
|
|||||||
"sponsorships": {
|
"sponsorships": {
|
||||||
"time": 9,
|
"time": 9,
|
||||||
"enabled": true
|
"enabled": true
|
||||||
|
},
|
||||||
|
"cache_avatars": {
|
||||||
|
"interval": 6,
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"cache_members": {
|
||||||
|
"interval": 30,
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"cache_admins": {
|
||||||
|
"interval": 120,
|
||||||
|
"enabled": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"locations": {
|
"locations": {
|
||||||
@@ -74,28 +111,134 @@ You can see config file with all the comments below:
|
|||||||
"locale": "locale"
|
"locale": "locale"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"rules": "Check out the rules",
|
"rules": {
|
||||||
"reapply": "Resubmit the application",
|
"permissions": [
|
||||||
"sponsorship": "Apply for sponsor role"
|
"users",
|
||||||
},
|
"admins"
|
||||||
"commands_admin": {
|
],
|
||||||
"reboot": "Restart the bot",
|
"modules": [
|
||||||
"message": "Send a message",
|
"general"
|
||||||
"label": "Set user's nickname",
|
]
|
||||||
"warnings": "Check user's warnings",
|
},
|
||||||
"application": "Check user's application",
|
"spoiler": {
|
||||||
"applications": "Retrieve all applications as a JSON"
|
"permissions": [
|
||||||
},
|
"users",
|
||||||
"commands_group_admin": {
|
"admins"
|
||||||
"reboot": "Restart the bot",
|
],
|
||||||
"message": "Send a message",
|
"modules": [
|
||||||
"label": "Set user's nickname",
|
"spoilers"
|
||||||
"warnings": "Check user's warnings",
|
]
|
||||||
"application": "Check user's application",
|
},
|
||||||
"applications": "Retrieve all applications as a JSON"
|
"cancel": {
|
||||||
},
|
"permissions": [
|
||||||
"commands_group_destination": {
|
"users",
|
||||||
"warn": "Warn a user"
|
"admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"spoilers",
|
||||||
|
"applications",
|
||||||
|
"sponsorships"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nearby": {
|
||||||
|
"permissions": [
|
||||||
|
"users",
|
||||||
|
"admins",
|
||||||
|
"group_users",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"warn": {
|
||||||
|
"permissions": [
|
||||||
|
"group_users"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"warnings"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reapply": {
|
||||||
|
"permissions": [
|
||||||
|
"users",
|
||||||
|
"admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sponsorship": {
|
||||||
|
"permissions": [
|
||||||
|
"users",
|
||||||
|
"admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"sponsorships"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reboot": {
|
||||||
|
"permissions": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"general"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"general"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"identify": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications",
|
||||||
|
"sponsorships"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"applications": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"resetcommands": {
|
||||||
|
"permissions": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"general"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -104,6 +247,10 @@ After all of that you're good to go! Happy using :)
|
|||||||
|
|
||||||
## To-Do
|
## To-Do
|
||||||
|
|
||||||
|
* [ ] Stats and infographics
|
||||||
|
* [ ] Check group members without completed application
|
||||||
|
* [x] Replicate some functions of @spoilerobot
|
||||||
|
* [x] Check sponsorship on Holo girls
|
||||||
|
* [x] /nearby command
|
||||||
* [x] Complete messenger between user and admins
|
* [x] Complete messenger between user and admins
|
||||||
* [ ] Check sponsorship on Holo girls
|
* [x] Get application by id and user_id
|
||||||
* [ ] Get application by id and user_id
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
from os import makedirs, path, sep
|
from os import makedirs, path, sep
|
||||||
from fastapi import FastAPI, HTTPException
|
from fastapi import FastAPI, HTTPException
|
||||||
from fastapi.responses import FileResponse, JSONResponse
|
from fastapi.responses import FileResponse, JSONResponse, Response
|
||||||
from starlette.status import HTTP_404_NOT_FOUND
|
from starlette.status import HTTP_404_NOT_FOUND
|
||||||
from modules.utils import configGet
|
from modules.utils import configGet
|
||||||
|
|
||||||
@@ -9,12 +9,20 @@ 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 = FastAPI(title="HoloUA Avatars API", docs_url=None, redoc_url=None, version="1.0")
|
||||||
|
|
||||||
@app.get("/check", response_class=JSONResponse, include_in_schema=False)
|
@app.get("/check", response_class=JSONResponse, include_in_schema=False)
|
||||||
|
@app.head("/check", response_class=JSONResponse, include_in_schema=False)
|
||||||
async def check():
|
async def check():
|
||||||
return JSONResponse({"detail": "I'm alright, thank you"})
|
return JSONResponse({"detail": "I'm alright, thank you"})
|
||||||
|
|
||||||
@app.get("/", response_class=FileResponse, include_in_schema=False)
|
@app.get("/", response_class=FileResponse, include_in_schema=False)
|
||||||
async def favicon(avatar_id: str):
|
async def avatar_get(avatar_id: str):
|
||||||
if path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}'):
|
if path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}'):
|
||||||
return FileResponse(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}', media_type="image/jpg")
|
return FileResponse(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}', media_type="image/jpg")
|
||||||
|
else:
|
||||||
|
raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="File not found")
|
||||||
|
|
||||||
|
@app.head("/", response_class=Response, include_in_schema=False)
|
||||||
|
async def avatar_head(avatar_id: str):
|
||||||
|
if path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}'):
|
||||||
|
return Response(headers={"Content-Length": path.getsize(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}')})
|
||||||
else:
|
else:
|
||||||
raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="File not found")
|
raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="File not found")
|
18
app.py
18
app.py
@@ -1,18 +1,32 @@
|
|||||||
|
from os import path, sep
|
||||||
|
from ujson import JSONDecodeError
|
||||||
from modules.logging import logWrite
|
from modules.logging import logWrite
|
||||||
from modules.utils import configGet
|
from modules.utils import configGet, jsonLoad
|
||||||
from pyrogram.client import Client
|
from pyrogram.client import Client
|
||||||
from pyrogram.errors import bad_request_400
|
from pyrogram.errors import bad_request_400
|
||||||
|
|
||||||
app = Client("holochecker", bot_token=configGet("bot_token", "bot"), api_id=configGet("api_id", "bot"), api_hash=configGet("api_hash", "bot"))
|
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):
|
async def isAnAdmin(admin_id):
|
||||||
|
|
||||||
|
# Check if user is mentioned in config
|
||||||
if (admin_id == configGet("owner")) or (admin_id in configGet("admins")):
|
if (admin_id == configGet("owner")) or (admin_id in configGet("admins")):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# Check if user is probably in cache
|
||||||
|
if path.exists(f"cache{sep}admins") is True:
|
||||||
|
try:
|
||||||
|
return True if admin_id in jsonLoad(f"cache{sep}admins") else False
|
||||||
|
except (FileNotFoundError, JSONDecodeError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Check if user is in admin group
|
||||||
try:
|
try:
|
||||||
async for member in app.get_chat_members(configGet("admin_group")):
|
async for member in app.get_chat_members(configGet("admin", "groups")):
|
||||||
if member.user.id == admin_id:
|
if member.user.id == admin_id:
|
||||||
return True
|
return True
|
||||||
except bad_request_400.ChannelInvalid:
|
except bad_request_400.ChannelInvalid:
|
||||||
logWrite(f"Could not get users in admin group to answer isAnAdmin(). Bot is likely not in the group.")
|
logWrite(f"Could not get users in admin group to answer isAnAdmin(). Bot is likely not in the group.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return False
|
return False
|
5
classes/errors/geo.py
Normal file
5
classes/errors/geo.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class PlaceNotFoundError(Exception):
|
||||||
|
"""Query provided did not lead to any city or populated area"""
|
||||||
|
def __init__(self, query):
|
||||||
|
self.query = query
|
||||||
|
super().__init__(f"Could not find any place on geonames.org of feature classes A and P by query '{self.query}'")
|
24
classes/errors/holo_user.py
Normal file
24
classes/errors/holo_user.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
"""Exceptions that are meant to be used by HoloUser class
|
||||||
|
and other modules that handle those exceptions"""
|
||||||
|
|
||||||
|
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 LabelTooLongError(Exception):
|
||||||
|
def __init__(self, label: str) -> None:
|
||||||
|
self.label = label
|
||||||
|
super().__init__(f"Could not set label to '{label}' because it is {len(label)} characters long (16 is maximum)")
|
||||||
|
|
||||||
|
class LabelSettingError(Exception):
|
||||||
|
def __init__(self, exp: Exception, trace: str) -> None:
|
||||||
|
super().__init__(f"❌ **Could not set label**\n\nException: `{exp}`\n\n**Traceback:**\n```\n{trace}\n```")
|
@@ -1,52 +1,18 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from requests import get
|
from asyncio import sleep
|
||||||
from traceback import print_exc
|
from ftfy import fix_text
|
||||||
|
from traceback import format_exc
|
||||||
from app import app, isAnAdmin
|
from app import app, isAnAdmin
|
||||||
from typing import Any, List, Literal, Union
|
from typing import Any, List, Literal, Union
|
||||||
from pyrogram.types import User, ChatMember, ChatPrivileges, Chat, Message, Photo, Video, Document, Animation, Voice, ForceReply, ReplyKeyboardMarkup
|
from pyrogram.types import User, ChatMember, ChatPrivileges, Chat, Message, Photo, Video, Document, Animation, Voice, ForceReply, ReplyKeyboardMarkup
|
||||||
from pyrogram.errors import bad_request_400
|
from pyrogram.errors import bad_request_400
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from modules.database import col_tmp, col_users, col_context, col_warnings, col_applications, col_sponsorships, col_messages
|
from classes.errors.geo import PlaceNotFoundError
|
||||||
|
from classes.errors.holo_user import UserInvalidError, UserNotFoundError, LabelTooLongError, LabelSettingError
|
||||||
|
from classes.templates import DefaultApplicationTemp, DefaultSponsorshipTemp
|
||||||
|
from modules.database import col_tmp, col_users, col_applications, col_sponsorships, col_messages, col_spoilers
|
||||||
from modules.logging import logWrite
|
from modules.logging import logWrite
|
||||||
from modules.utils import configGet, locale, should_quote
|
from modules.utils import configGet, find_location, locale, should_quote
|
||||||
|
|
||||||
class DefaultApplicationTemp(dict):
|
|
||||||
def __init__(self, user: int):
|
|
||||||
super().__init__({})
|
|
||||||
self.dict = {
|
|
||||||
"user": user,
|
|
||||||
"type": "application",
|
|
||||||
"complete": False,
|
|
||||||
"sent": False,
|
|
||||||
"state": "fill",
|
|
||||||
"reapply": False,
|
|
||||||
"stage": 1,
|
|
||||||
"application": {
|
|
||||||
"1": None,
|
|
||||||
"2": None,
|
|
||||||
"3": None,
|
|
||||||
"4": None,
|
|
||||||
"5": None,
|
|
||||||
"6": None,
|
|
||||||
"7": None,
|
|
||||||
"8": None,
|
|
||||||
"9": None,
|
|
||||||
"10": None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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():
|
class HoloUser():
|
||||||
"""This object represents a user of HoloChecker bot.
|
"""This object represents a user of HoloChecker bot.
|
||||||
@@ -99,8 +65,22 @@ class HoloUser():
|
|||||||
self.phone = holo_user["tg_phone"]
|
self.phone = holo_user["tg_phone"]
|
||||||
self.locale = holo_user["tg_locale"]
|
self.locale = holo_user["tg_locale"]
|
||||||
self.username = holo_user["tg_username"]
|
self.username = holo_user["tg_username"]
|
||||||
|
|
||||||
|
if isinstance(user, User):
|
||||||
|
|
||||||
|
if (self.name != user.first_name) and hasattr(user, "first_name") and (user.first_name is not None):
|
||||||
|
self.set("name", user.first_name, db_key="tg_name")
|
||||||
|
|
||||||
|
if (self.phone != user.phone_number) and hasattr(user, "phone") and (user.phone_number is not None):
|
||||||
|
self.set("phone", user.phone_number, db_key="tg_phone")
|
||||||
|
|
||||||
|
if (self.locale != user.language_code) and hasattr(user, "locale") and (user.language_code is not None):
|
||||||
|
self.set("locale", user.language_code, db_key="tg_locale")
|
||||||
|
|
||||||
|
if (self.username != user.username) and hasattr(user, "username") and (user.username is not None):
|
||||||
|
self.set("username", user.username, db_key="tg_username")
|
||||||
|
|
||||||
def set(self, key: str, value: Any) -> None:
|
def set(self, key: str, value: Any, db_key: Union[str, None] = None) -> None:
|
||||||
"""Set attribute data and save it into database
|
"""Set attribute data and save it into database
|
||||||
|
|
||||||
### Args:
|
### Args:
|
||||||
@@ -110,7 +90,8 @@ class HoloUser():
|
|||||||
if not hasattr(self, key):
|
if not hasattr(self, key):
|
||||||
raise AttributeError()
|
raise AttributeError()
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
col_users.update_one(filter={"_id": self.db_id}, update={ "$set": { key: value } }, upsert=True)
|
db_key = key if db_key is None else db_key
|
||||||
|
col_users.update_one(filter={"_id": self.db_id}, update={ "$set": { db_key: value } }, upsert=True)
|
||||||
logWrite(f"Set attribute {key} of user {self.id} to {value}")
|
logWrite(f"Set attribute {key} of user {self.id} to {value}")
|
||||||
|
|
||||||
async def message(self,
|
async def message(self,
|
||||||
@@ -142,13 +123,18 @@ class HoloUser():
|
|||||||
* adm_context (`bool`, *optional*): Whether context sender is an admin. Defaults to False.
|
* adm_context (`bool`, *optional*): Whether context sender is an admin. Defaults to False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if text is not None:
|
||||||
|
text = fix_text(text)
|
||||||
|
elif caption is not None:
|
||||||
|
caption = fix_text(caption)
|
||||||
|
|
||||||
# Check if any text available and log message sending
|
# Check if any text available and log message sending
|
||||||
if text is not None:
|
if text is not None:
|
||||||
logWrite(f"{context.from_user.id} sent message '{text}' to {self.id}")
|
logWrite(f"{context.from_user.id} sent message '{text}' to {self.id} (source message: {context.id})")
|
||||||
elif caption is not None:
|
elif caption is not None:
|
||||||
logWrite(f"{context.from_user.id} sent message '{caption}' to {self.id}")
|
logWrite(f"{context.from_user.id} sent message '{caption}' to {self.id} (source message: {context.id})")
|
||||||
else:
|
else:
|
||||||
logWrite(f"{context.from_user.id} sent message to {self.id}")
|
logWrite(f"{context.from_user.id} sent message to {self.id} (source message: {context.id})")
|
||||||
|
|
||||||
# Add notices for admin or user
|
# Add notices for admin or user
|
||||||
if text is not None:
|
if text is not None:
|
||||||
@@ -177,19 +163,19 @@ class HoloUser():
|
|||||||
if photo is not None:
|
if photo is not None:
|
||||||
if isinstance(photo, Photo):
|
if isinstance(photo, Photo):
|
||||||
photo = photo.file_id
|
photo = photo.file_id
|
||||||
new_message = await origin.reply_photo(photo, caption=caption, quote=True)
|
new_message = await origin.reply_cached_media(photo, caption=caption, quote=True)
|
||||||
elif video is not None:
|
elif video is not None:
|
||||||
if isinstance(video, Video):
|
if isinstance(video, Video):
|
||||||
video = video.file_id
|
video = video.file_id
|
||||||
new_message = await origin.reply_video(video, caption=caption, quote=True)
|
new_message = await origin.reply_cached_media(video, caption=caption, quote=True)
|
||||||
elif file is not None:
|
elif file is not None:
|
||||||
if isinstance(file, Document):
|
if isinstance(file, Document):
|
||||||
file = file.file_id
|
file = file.file_id
|
||||||
new_message = await origin.reply_document(file, caption=caption, quote=True)
|
new_message = await origin.reply_cached_media(file, caption=caption, quote=True)
|
||||||
elif animation is not None:
|
elif animation is not None:
|
||||||
if isinstance(animation, Animation):
|
if isinstance(animation, Animation):
|
||||||
animation = animation.file_id
|
animation = animation.file_id
|
||||||
new_message = await origin.reply_animation(animation, caption=caption, quote=True)
|
new_message = await origin.reply_cached_media(animation, caption=caption, quote=True)
|
||||||
elif voice is not None:
|
elif voice is not None:
|
||||||
if isinstance(voice, Voice):
|
if isinstance(voice, Voice):
|
||||||
voice = voice.file_id
|
voice = voice.file_id
|
||||||
@@ -202,23 +188,23 @@ class HoloUser():
|
|||||||
if photo is not None:
|
if photo is not None:
|
||||||
if isinstance(photo, Photo):
|
if isinstance(photo, Photo):
|
||||||
photo = photo.file_id
|
photo = photo.file_id
|
||||||
new_message = await app.send_photo(self.id, photo, caption=caption)
|
new_message = await app.send_cached_media(self.id, photo, caption=caption)
|
||||||
elif video is not None:
|
elif video is not None:
|
||||||
if isinstance(video, Video):
|
if isinstance(video, Video):
|
||||||
video = video.file_id
|
video = video.file_id
|
||||||
new_message = await app.send_video(self.id, video, caption=caption)
|
new_message = await app.send_cached_media(self.id, video, caption=caption)
|
||||||
elif file is not None:
|
elif file is not None:
|
||||||
if isinstance(file, Document):
|
if isinstance(file, Document):
|
||||||
file = file.file_id
|
file = file.file_id
|
||||||
new_message = await app.send_document(self.id, file, caption=caption)
|
new_message = await app.send_cached_media(self.id, file, caption=caption)
|
||||||
elif animation is not None:
|
elif animation is not None:
|
||||||
if isinstance(animation, Animation):
|
if isinstance(animation, Animation):
|
||||||
animation = animation.file_id
|
animation = animation.file_id
|
||||||
new_message = await app.send_animation(animation, caption=caption, quote=True)
|
new_message = await app.send_cached_media(self.id, animation, caption=caption)
|
||||||
elif voice is not None:
|
elif voice is not None:
|
||||||
if isinstance(voice, Voice):
|
if isinstance(voice, Voice):
|
||||||
voice = voice.file_id
|
voice = voice.file_id
|
||||||
new_message = await app.send_voice(voice, caption=caption, quote=True)
|
new_message = await app.send_cached_media(self.id, voice, caption=caption)
|
||||||
else:
|
else:
|
||||||
new_message = await app.send_message(self.id, text)
|
new_message = await app.send_message(self.id, text)
|
||||||
|
|
||||||
@@ -228,27 +214,34 @@ class HoloUser():
|
|||||||
|
|
||||||
# Report to admin and to sender about message sending failure
|
# Report to admin and to sender about message sending failure
|
||||||
except Exception as exp:
|
except Exception as exp:
|
||||||
logWrite(f"Exception {exp} happened as {context.from_user.id} tried to send message to {self.id}. Traceback:\n{print_exc()}")
|
logWrite(f"Exception {exp} happened as {context.from_user.id} tried to send message to {self.id}. Traceback:\n{format_exc()}")
|
||||||
try:
|
try:
|
||||||
await app.send_message(configGet("owner"), locale("message_traceback", "message").format(context.from_user.id, self.id, exp, print_exc()))
|
await app.send_message(configGet("owner"), locale("message_traceback", "message").format(context.from_user.id, self.id, exp, format_exc()))
|
||||||
except bad_request_400.PeerIdInvalid:
|
except bad_request_400.PeerIdInvalid:
|
||||||
logWrite(f"Could not notify admin about failure when sending message! Admin has never interacted with bot!")
|
logWrite(f"Could not notify admin about failure when sending message! Admin has never interacted with bot!")
|
||||||
await context.reply_text(locale("message_error", "message"), quote=should_quote(context))
|
await context.reply_text(locale("message_error", "message"), quote=should_quote(context))
|
||||||
|
|
||||||
async def set_label(self, chat: Chat, label: str) -> None:
|
async def label_set(self, chat: Chat, label: str) -> None:
|
||||||
"""Set label in destination group
|
"""Set label in destination group
|
||||||
|
|
||||||
### Args:
|
### Args:
|
||||||
* chat (`Chat`): Telegram chat
|
* chat (`Chat`): Telegram chat
|
||||||
* label (`str`): Label you want to set
|
* label (`str`): Label you want to set
|
||||||
"""
|
"""
|
||||||
|
if len(label) > 16:
|
||||||
|
raise LabelTooLongError(label)
|
||||||
self.label = label
|
self.label = label
|
||||||
self.set("label", label)
|
try:
|
||||||
await app.promote_chat_member(configGet("destination_group"), self.id)
|
await app.promote_chat_member(configGet("users", "groups"), self.id, privileges=ChatPrivileges(can_pin_messages=True, can_manage_video_chats=True))
|
||||||
if not await isAnAdmin(self.id):
|
if not await isAnAdmin(self.id):
|
||||||
await app.set_administrator_title(configGet("destination_group"), self.id, label)
|
await sleep(0.5)
|
||||||
|
await app.set_administrator_title(configGet("users", "groups"), self.id, label)
|
||||||
|
self.set("label", label)
|
||||||
|
except Exception as exp:
|
||||||
|
logWrite(f"Could not set {self.id}'s title to '{self.label}' due to {exp}")
|
||||||
|
raise LabelSettingError(exp, format_exc())
|
||||||
|
|
||||||
async def reset_label(self, chat: Chat) -> None:
|
async def label_reset(self, chat: Chat) -> None:
|
||||||
"""Reset label in destination group
|
"""Reset label in destination group
|
||||||
|
|
||||||
### Args:
|
### Args:
|
||||||
@@ -256,10 +249,12 @@ class HoloUser():
|
|||||||
"""
|
"""
|
||||||
self.label = ""
|
self.label = ""
|
||||||
self.set("label", "")
|
self.set("label", "")
|
||||||
await app.set_administrator_title(configGet("destination_group"), self.id, "")
|
await app.set_administrator_title(configGet("users", "groups"), self.id, "")
|
||||||
if not await isAnAdmin(self.id):
|
if not await isAnAdmin(self.id):
|
||||||
await app.promote_chat_member(configGet("destination_group"), self.id, privileges=ChatPrivileges(
|
await app.promote_chat_member(configGet("users", "groups"), self.id, privileges=ChatPrivileges(
|
||||||
can_manage_chat=False
|
can_manage_chat=False,
|
||||||
|
can_pin_messages=False,
|
||||||
|
can_manage_video_chats=False
|
||||||
))
|
))
|
||||||
|
|
||||||
def application_state(self) -> tuple[Literal["none", "fill", "approved", "rejected"], bool]:
|
def application_state(self) -> tuple[Literal["none", "fill", "approved", "rejected"], bool]:
|
||||||
@@ -282,14 +277,13 @@ class HoloUser():
|
|||||||
"""
|
"""
|
||||||
return True if col_applications.find_one({"user": self.id}) is not None else False
|
return True if col_applications.find_one({"user": self.id}) is not None else False
|
||||||
|
|
||||||
def application_restart(self) -> None:
|
def application_restart(self, reapply: bool = False) -> None:
|
||||||
"""Reset application of a user in tmp collection and replace it with an empty one
|
"""Reset application of a user in tmp collection and replace it with an empty one
|
||||||
"""
|
"""
|
||||||
if col_tmp.find_one({"user": self.id, "type": "application"}) is None:
|
if col_tmp.find_one({"user": self.id, "type": "application"}) is None:
|
||||||
col_tmp.insert_one(document=DefaultApplicationTemp(self.id).dict)
|
col_tmp.insert_one(document=DefaultApplicationTemp(self.id, reapply=reapply).dict)
|
||||||
else:
|
else:
|
||||||
col_tmp.delete_one({"user": self.id, "type": "application"})
|
col_tmp.find_one_and_replace({"user": self.id, "type": "application"}, DefaultApplicationTemp(self.id, reapply=reapply).dict)
|
||||||
col_tmp.insert_one(document=DefaultApplicationTemp(self.id).dict)
|
|
||||||
|
|
||||||
async def application_next(self, query: str, msg: Message) -> None:
|
async def application_next(self, query: str, msg: Message) -> None:
|
||||||
"""Move on filling application of user
|
"""Move on filling application of user
|
||||||
@@ -299,16 +293,33 @@ class HoloUser():
|
|||||||
* msg (`Message`): Message that should receive replies
|
* msg (`Message`): Message that should receive replies
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if col_tmp.find_one({"user": self.id, "type": "application"}) is None:
|
# if col_tmp.find_one({"user": self.id, "type": "application"}) is None:
|
||||||
|
|
||||||
col_tmp.insert_one(
|
if self.sponsorship_state()[0] == "fill":
|
||||||
document=DefaultApplicationTemp(self.id).dict
|
return
|
||||||
)
|
|
||||||
|
if self.spoiler_state() is True:
|
||||||
|
return
|
||||||
|
|
||||||
|
# col_tmp.insert_one(
|
||||||
|
# document=DefaultApplicationTemp(self.id).dict
|
||||||
|
# )
|
||||||
|
|
||||||
progress = col_tmp.find_one({"user": self.id, "type": "application"})
|
progress = col_tmp.find_one({"user": self.id, "type": "application"})
|
||||||
stage = progress["stage"]
|
|
||||||
|
|
||||||
if progress["state"] == "fill":
|
if progress is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
stage = progress["stage"]
|
||||||
|
|
||||||
|
# if self.sponsorship_state()[0] == "fill":
|
||||||
|
# await msg.reply_text(locale("finish_sponsorship", "message"), quote=should_quote(msg))
|
||||||
|
# return
|
||||||
|
|
||||||
|
if progress["state"] == "fill" and progress["sent"] is False:
|
||||||
|
|
||||||
|
if msg.text is not None:
|
||||||
|
msg.text = fix_text(msg.text)
|
||||||
|
|
||||||
if stage == 2:
|
if stage == 2:
|
||||||
|
|
||||||
@@ -316,44 +327,49 @@ class HoloUser():
|
|||||||
input_dt = datetime.strptime(query, "%d.%m.%Y")
|
input_dt = datetime.strptime(query, "%d.%m.%Y")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
|
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
|
||||||
await msg.reply_text(locale(f"question2_invalid", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply"))))
|
await msg.reply_text(locale(f"question2_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
|
||||||
return
|
return
|
||||||
|
|
||||||
if datetime.now() <= input_dt:
|
if datetime.now() <= input_dt:
|
||||||
logWrite(f"User {msg.from_user.id} failed stage {stage} due to joking")
|
logWrite(f"User {msg.from_user.id} failed stage {stage} due to joking")
|
||||||
await msg.reply_text(locale("question2_joke", "message"), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
await msg.reply_text(locale("question2_joke", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply", locale=self.locale))))
|
||||||
return
|
return
|
||||||
|
|
||||||
elif ((datetime.now() - input_dt).days) < ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days):
|
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 {stage} due to being underage")
|
logWrite(f"User {msg.from_user.id} failed stage {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"))))
|
await msg.reply_text(locale("question2_underage", "message", locale=self.locale).format(str(configGet("age_allowed"))), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply", locale=self.locale))))
|
||||||
return
|
return
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f'Look: {((datetime.now() - input_dt).days)} > {(datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days}')
|
|
||||||
progress["application"][str(stage)] = input_dt
|
progress["application"][str(stage)] = input_dt
|
||||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
|
||||||
await msg.reply_text(locale(f"question{stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply"))))
|
await msg.reply_text(locale(f"question{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply", locale=self.locale))))
|
||||||
|
|
||||||
elif stage == 3:
|
elif stage == 3:
|
||||||
try:
|
try:
|
||||||
result = (get(f"http://api.geonames.org/searchJSON?q={query}&maxRows=1&countryBias=UA&lang=uk&orderby=relevance&featureClass=P&featureClass=A&username={configGet('username', 'geocoding')}")).json()
|
progress["application"][str(stage)] = find_location(query)
|
||||||
progress["application"][str(stage)] = result["geonames"][0]
|
if ("lat" in progress["application"][str(stage)] and "lng" in progress["application"][str(stage)]):
|
||||||
|
progress["application"][str(stage)]["location"] = [float(progress["application"][str(stage)]["lng"]), float(progress["application"][str(stage)]["lat"])]
|
||||||
|
del progress["application"][str(stage)]["lat"]
|
||||||
|
del progress["application"][str(stage)]["lng"]
|
||||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
|
||||||
await msg.reply_text(locale(f"question3_found", "message").format(result["geonames"][0]["name"], result["geonames"][0]["adminName1"]))
|
await msg.reply_text(locale("question3_found", "message", locale=self.locale).format(progress["application"][str(stage)]["name"], progress["application"][str(stage)]["adminName1"]))
|
||||||
await msg.reply_text(locale(f"question{stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply"))))
|
await msg.reply_text(locale(f"question{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply", locale=self.locale))))
|
||||||
except (ValueError, KeyError, IndexError):
|
except PlaceNotFoundError:
|
||||||
await msg.reply_text(locale(f"question3_invalid", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply"))))
|
await msg.reply_text(locale("question3_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
|
||||||
return
|
return
|
||||||
except Exception as exp:
|
except Exception as exp:
|
||||||
await msg.reply_text(locale("question3_error", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply"))))
|
await msg.reply_text(locale("question3_error", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
|
||||||
try:
|
try:
|
||||||
await app.send_message(configGet("owner"), locale("question3_traceback", "message").format(query, exp, print_exc()))
|
await app.send_message(configGet("owner"), locale("question3_traceback", "message", locale=self.locale).format(query, exp, format_exc()))
|
||||||
except bad_request_400.PeerIdInvalid:
|
except bad_request_400.PeerIdInvalid:
|
||||||
logWrite(f"Could not notify admin about failure when sending message! Admin has never interacted with bot!")
|
logWrite(f"Could not notify admin about failure when sending message! Admin has never interacted with bot!")
|
||||||
return
|
return
|
||||||
|
|
||||||
elif stage == 10:
|
elif stage == 10:
|
||||||
|
if len(query) > 1024:
|
||||||
|
await msg.reply_text(locale("question10_too_long", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
|
||||||
|
return
|
||||||
progress["application"][str(stage)] = query
|
progress["application"][str(stage)] = query
|
||||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "complete": True}})
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "complete": True}})
|
||||||
application_content = []
|
application_content = []
|
||||||
@@ -361,20 +377,144 @@ class HoloUser():
|
|||||||
for question in progress["application"]:
|
for question in progress["application"]:
|
||||||
if i == 2:
|
if i == 2:
|
||||||
age = relativedelta(datetime.now(), progress['application']['2'])
|
age = relativedelta(datetime.now(), progress['application']['2'])
|
||||||
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {progress['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
||||||
elif i == 3:
|
elif i == 3:
|
||||||
if progress['application']['3']['countryCode'] == "UA":
|
if progress['application']['3']['countryCode'] == "UA":
|
||||||
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {progress['application']['3']['name']} ({progress['application']['3']['adminName1']})")
|
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['3']['name']} ({progress['application']['3']['adminName1']})")
|
||||||
else:
|
else:
|
||||||
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {progress['application']['3']['name']} ({progress['application']['3']['adminName1']}, {progress['application']['3']['countryName']})")
|
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['3']['name']} ({progress['application']['3']['adminName1']}, {progress['application']['3']['countryName']})")
|
||||||
else:
|
else:
|
||||||
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {progress['application'][question]}")
|
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application'][question]}")
|
||||||
i += 1
|
i += 1
|
||||||
await msg.reply_text(locale("confirm", "message").format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard"), resize_keyboard=True))
|
await msg.reply_text(locale("confirm", "message", locale=self.locale).format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard", locale=self.locale), resize_keyboard=True))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
if len(query) > 256:
|
||||||
|
await msg.reply_text(locale("question_too_long", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
|
||||||
|
return
|
||||||
progress["application"][str(stage)] = query
|
progress["application"][str(stage)] = query
|
||||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
|
||||||
await msg.reply_text(locale(f"question{stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply"))))
|
await msg.reply_text(locale(f"question{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply", locale=self.locale))))
|
||||||
|
|
||||||
logWrite(f"User {self.id} completed stage {stage} of application")
|
logWrite(f"User {self.id} completed stage {stage} of application")
|
||||||
|
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
def sponsorship_state(self) -> tuple[Literal["none", "fill", "approved", "rejected"], bool]:
|
||||||
|
"""Check the current state of sponsorship in tmp collection
|
||||||
|
|
||||||
|
### Returns:
|
||||||
|
* `tuple[Literal["none", "fill", "approved", "rejected"], bool]`: First element is an enum of a state and the second one is whether sponsorship application is complete.
|
||||||
|
"""
|
||||||
|
tmp_sponsorship = col_tmp.find_one({"user": self.id, "type": "sponsorship"})
|
||||||
|
if tmp_sponsorship is None:
|
||||||
|
return "none", False
|
||||||
|
else:
|
||||||
|
return tmp_sponsorship["state"], tmp_sponsorship["complete"]
|
||||||
|
|
||||||
|
def sponsorship_valid(self) -> bool:
|
||||||
|
"""Check whether user has a valid sponsorship
|
||||||
|
|
||||||
|
### Returns:
|
||||||
|
* `bool`: `True` if yes and `False` if no
|
||||||
|
"""
|
||||||
|
return True if col_sponsorships.find_one({"user": self.id, "expires": {"$gt": datetime.now()}}) is not None else False
|
||||||
|
|
||||||
|
def sponsorship_restart(self) -> None:
|
||||||
|
"""Reset sponsorship of a user in tmp collection and replace it with an empty one
|
||||||
|
"""
|
||||||
|
if col_tmp.find_one({"user": self.id, "type": "sponsorship"}) is None:
|
||||||
|
col_tmp.insert_one(document=DefaultSponsorshipTemp(self.id).dict)
|
||||||
|
else:
|
||||||
|
col_tmp.delete_one({"user": self.id, "type": "sponsorship"})
|
||||||
|
col_tmp.insert_one(document=DefaultSponsorshipTemp(self.id).dict)
|
||||||
|
|
||||||
|
async def sponsorship_next(self, query: str, msg: Message, photo: Union[Photo, None] = None) -> None:
|
||||||
|
"""Move on filling sponsorship of user
|
||||||
|
|
||||||
|
### Args:
|
||||||
|
* query (`str`): Some kind of input
|
||||||
|
* msg (`Message`): Message that should receive replies
|
||||||
|
"""
|
||||||
|
|
||||||
|
progress = col_tmp.find_one({"user": self.id, "type": "sponsorship"})
|
||||||
|
|
||||||
|
if progress is not None:
|
||||||
|
|
||||||
|
stage = progress["stage"]
|
||||||
|
|
||||||
|
if msg.text is not None:
|
||||||
|
msg.text = fix_text(msg.text)
|
||||||
|
elif msg.caption is not None:
|
||||||
|
msg.caption = fix_text(msg.caption)
|
||||||
|
|
||||||
|
if progress["state"] == "fill" and progress["sent"] is False:
|
||||||
|
|
||||||
|
if stage == 1:
|
||||||
|
|
||||||
|
if len(query) > 240:
|
||||||
|
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
|
||||||
|
await msg.reply_text(locale(f"sponsor1_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage}", "force_reply", locale=self.locale))))
|
||||||
|
return
|
||||||
|
|
||||||
|
progress["sponsorship"]["streamer"] = query
|
||||||
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}})
|
||||||
|
await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale))))
|
||||||
|
|
||||||
|
elif stage == 2:
|
||||||
|
|
||||||
|
try:
|
||||||
|
input_dt = datetime.strptime(query, "%d.%m.%Y")
|
||||||
|
except ValueError:
|
||||||
|
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
|
||||||
|
await msg.reply_text(locale(f"sponsor2_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage}", "force_reply", locale=self.locale))))
|
||||||
|
return
|
||||||
|
|
||||||
|
if datetime.now() >= input_dt:
|
||||||
|
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending date in the past")
|
||||||
|
await msg.reply_text(locale("sponsor2_past", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale("sponsor2", "force_reply", locale=self.locale))))
|
||||||
|
return
|
||||||
|
|
||||||
|
else:
|
||||||
|
progress["sponsorship"]["expires"] = input_dt
|
||||||
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}})
|
||||||
|
await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale))))
|
||||||
|
|
||||||
|
elif stage == 3:
|
||||||
|
|
||||||
|
if photo is not None:
|
||||||
|
progress["sponsorship"]["proof"] = photo.file_id
|
||||||
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}})
|
||||||
|
await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale))))
|
||||||
|
|
||||||
|
elif stage == 4:
|
||||||
|
if len(query) > 16:
|
||||||
|
await msg.reply_text(locale("label_too_long", "message"), reply_markup=ForceReply(placeholder=str(locale("sponsor4", "force_reply", locale=self.locale))))
|
||||||
|
return
|
||||||
|
progress["sponsorship"]["label"] = query
|
||||||
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "complete": True}})
|
||||||
|
await msg.reply_cached_media(
|
||||||
|
progress["sponsorship"]["proof"],
|
||||||
|
caption=locale("sponsor_confirm", "message", locale=self.locale).format(
|
||||||
|
progress["sponsorship"]["streamer"],
|
||||||
|
progress["sponsorship"]["expires"].strftime("%d.%m.%Y"),
|
||||||
|
progress["sponsorship"]["label"]
|
||||||
|
),
|
||||||
|
reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard", locale=self.locale), resize_keyboard=True))
|
||||||
|
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
logWrite(f"User {self.id} completed stage {stage} of sponsorship")
|
||||||
|
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
def spoiler_state(self) -> bool:
|
||||||
|
"""Check if user has any started but not finished spoilers
|
||||||
|
|
||||||
|
### Returns:
|
||||||
|
* `bool`: `True` if any not finished spoilers available and `False` if none.
|
||||||
|
"""
|
||||||
|
return False if col_spoilers.find_one({"user": self.id, "completed": False}) is None else True
|
46
classes/templates.py
Normal file
46
classes/templates.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
"""Templates for temporary application/sponsorship records"""
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class DefaultApplicationTemp(dict):
|
||||||
|
def __init__(self, user: int, reapply: bool = False):
|
||||||
|
super().__init__({})
|
||||||
|
self.dict = {
|
||||||
|
"user": user,
|
||||||
|
"type": "application",
|
||||||
|
"complete": False,
|
||||||
|
"sent": False,
|
||||||
|
"state": "fill",
|
||||||
|
"reapply": reapply,
|
||||||
|
"stage": 1,
|
||||||
|
"application": {
|
||||||
|
"1": None,
|
||||||
|
"2": None,
|
||||||
|
"3": None,
|
||||||
|
"4": None,
|
||||||
|
"5": None,
|
||||||
|
"6": None,
|
||||||
|
"7": None,
|
||||||
|
"8": None,
|
||||||
|
"9": None,
|
||||||
|
"10": None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultSponsorshipTemp(dict):
|
||||||
|
def __init__(self, user: int):
|
||||||
|
super().__init__({})
|
||||||
|
self.dict = {
|
||||||
|
"user": user,
|
||||||
|
"type": "sponsorship",
|
||||||
|
"complete": False,
|
||||||
|
"sent": False,
|
||||||
|
"state": "fill",
|
||||||
|
"stage": 1,
|
||||||
|
"sponsorship": {
|
||||||
|
"streamer": None,
|
||||||
|
"expires": datetime.fromtimestamp(0),
|
||||||
|
"proof": None,
|
||||||
|
"label": ""
|
||||||
|
}
|
||||||
|
}
|
@@ -2,14 +2,16 @@
|
|||||||
"locale": "uk",
|
"locale": "uk",
|
||||||
"debug": false,
|
"debug": false,
|
||||||
"owner": 0,
|
"owner": 0,
|
||||||
"bot_id": 0,
|
|
||||||
"age_allowed": 0,
|
"age_allowed": 0,
|
||||||
"api": "http://example.com",
|
"api": "http://example.com",
|
||||||
"inline_preview_count": 7,
|
"inline_preview_count": 7,
|
||||||
"admin_group": 0,
|
|
||||||
"destination_group": 0,
|
|
||||||
"remove_application_time": -1,
|
"remove_application_time": -1,
|
||||||
|
"search_radius": 50,
|
||||||
"admins": [],
|
"admins": [],
|
||||||
|
"groups": {
|
||||||
|
"admin": 0,
|
||||||
|
"users": 0
|
||||||
|
},
|
||||||
"bot": {
|
"bot": {
|
||||||
"api_id": 0,
|
"api_id": 0,
|
||||||
"api_hash": "",
|
"api_hash": "",
|
||||||
@@ -29,6 +31,29 @@
|
|||||||
"size": 512,
|
"size": 512,
|
||||||
"location": "logs"
|
"location": "logs"
|
||||||
},
|
},
|
||||||
|
"features": {
|
||||||
|
"general": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"applications": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"sponsorships": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"warnings": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"invites_check": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"dinovoice": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"spoilers": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"scheduler": {
|
"scheduler": {
|
||||||
"birthdays": {
|
"birthdays": {
|
||||||
"time": 9,
|
"time": 9,
|
||||||
@@ -37,6 +62,18 @@
|
|||||||
"sponsorships": {
|
"sponsorships": {
|
||||||
"time": 9,
|
"time": 9,
|
||||||
"enabled": true
|
"enabled": true
|
||||||
|
},
|
||||||
|
"cache_avatars": {
|
||||||
|
"interval": 6,
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"cache_members": {
|
||||||
|
"interval": 30,
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"cache_admins": {
|
||||||
|
"interval": 120,
|
||||||
|
"enabled": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"locations": {
|
"locations": {
|
||||||
@@ -44,30 +81,132 @@
|
|||||||
"locale": "locale"
|
"locale": "locale"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"rules": "Check out the rules",
|
"rules": {
|
||||||
"nearby": "Show users near the area",
|
"permissions": [
|
||||||
"reapply": "Resubmit the application",
|
"users",
|
||||||
"sponsorship": "Apply for sponsor role"
|
"admins"
|
||||||
},
|
],
|
||||||
"commands_admin": {
|
"modules": [
|
||||||
"reboot": "Restart the bot",
|
"general"
|
||||||
"message": "Send a message",
|
]
|
||||||
"label": "Set user's nickname",
|
},
|
||||||
"warnings": "Check user's warnings",
|
"spoiler": {
|
||||||
"application": "Check user's application",
|
"permissions": [
|
||||||
"applications": "Retrieve all applications as a JSON"
|
"users",
|
||||||
},
|
"admins"
|
||||||
"commands_group_admin": {
|
],
|
||||||
"reboot": "Restart the bot",
|
"modules": [
|
||||||
"message": "Send a message",
|
"spoilers"
|
||||||
"label": "Set user's nickname",
|
]
|
||||||
"nearby": "Show users near the area",
|
},
|
||||||
"warnings": "Check user's warnings",
|
"cancel": {
|
||||||
"application": "Check user's application",
|
"permissions": [
|
||||||
"applications": "Retrieve all applications as a JSON"
|
"users",
|
||||||
},
|
"admins"
|
||||||
"commands_group_destination": {
|
],
|
||||||
"warn": "Warn a user",
|
"modules": [
|
||||||
"nearby": "Show users near the area"
|
"spoilers",
|
||||||
|
"applications",
|
||||||
|
"sponsorships"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nearby": {
|
||||||
|
"permissions": [
|
||||||
|
"users",
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"warn": {
|
||||||
|
"permissions": [
|
||||||
|
"group_users_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"warnings"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reapply": {
|
||||||
|
"permissions": [
|
||||||
|
"users",
|
||||||
|
"admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sponsorship": {
|
||||||
|
"permissions": [
|
||||||
|
"users",
|
||||||
|
"admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"sponsorships"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reboot": {
|
||||||
|
"permissions": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"general"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"general"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"identify": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications",
|
||||||
|
"sponsorships"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"applications": {
|
||||||
|
"permissions": [
|
||||||
|
"admins",
|
||||||
|
"group_admins"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"applications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"resetcommands": {
|
||||||
|
"permissions": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"general"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,9 +1,9 @@
|
|||||||
from os import getpid, makedirs
|
from os import getpid, makedirs
|
||||||
|
from time import time
|
||||||
from modules.utils import *
|
from modules.utils import *
|
||||||
from modules.inline import *
|
from modules.inline import *
|
||||||
from app import app
|
from app import app
|
||||||
|
|
||||||
from modules.commands_register import commands_register
|
|
||||||
from pyrogram import idle
|
from pyrogram import idle
|
||||||
|
|
||||||
pid = getpid()
|
pid = getpid()
|
||||||
@@ -13,12 +13,16 @@ makedirs(f'{configGet("cache", "locations")}{sep}avatars', exist_ok=True)
|
|||||||
# Importing
|
# Importing
|
||||||
from modules.commands.application import *
|
from modules.commands.application import *
|
||||||
from modules.commands.applications import *
|
from modules.commands.applications import *
|
||||||
|
from modules.commands.cancel import *
|
||||||
|
from modules.commands.identify import *
|
||||||
from modules.commands.label import *
|
from modules.commands.label import *
|
||||||
from modules.commands.message import *
|
from modules.commands.message import *
|
||||||
from modules.commands.nearby import *
|
from modules.commands.nearby import *
|
||||||
from modules.commands.reapply import *
|
from modules.commands.reapply import *
|
||||||
from modules.commands.reboot import *
|
from modules.commands.reboot import *
|
||||||
|
from modules.commands.resetcommands import *
|
||||||
from modules.commands.rules import *
|
from modules.commands.rules import *
|
||||||
|
from modules.commands.spoiler import *
|
||||||
from modules.commands.sponsorship import *
|
from modules.commands.sponsorship import *
|
||||||
from modules.commands.start import *
|
from modules.commands.start import *
|
||||||
from modules.commands.warn import *
|
from modules.commands.warn import *
|
||||||
@@ -27,12 +31,15 @@ from modules.commands.warnings import *
|
|||||||
from modules.callbacks.nothing import *
|
from modules.callbacks.nothing import *
|
||||||
from modules.callbacks.reapply import *
|
from modules.callbacks.reapply import *
|
||||||
from modules.callbacks.rules import *
|
from modules.callbacks.rules import *
|
||||||
|
from modules.callbacks.sid import *
|
||||||
|
from modules.callbacks.sponsorship import *
|
||||||
from modules.callbacks.sub import *
|
from modules.callbacks.sub import *
|
||||||
from modules.callbacks.sus import *
|
from modules.callbacks.sus import *
|
||||||
|
|
||||||
from modules.handlers.confirmation import *
|
from modules.handlers.confirmation import *
|
||||||
from modules.handlers.contact import *
|
from modules.handlers.contact import *
|
||||||
from modules.handlers.group_join import *
|
from modules.handlers.group_join import *
|
||||||
|
from modules.handlers.voice import *
|
||||||
from modules.handlers.welcome import *
|
from modules.handlers.welcome import *
|
||||||
from modules.handlers.everything import *
|
from modules.handlers.everything import *
|
||||||
|
|
||||||
@@ -46,42 +53,32 @@ if __name__ == "__main__":
|
|||||||
# I did compare performance, almost no difference and it's much more useful this way. Change my mind.
|
# I did compare performance, almost no difference and it's much more useful this way. Change my mind.
|
||||||
app.start()
|
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:
|
try:
|
||||||
app.send_message(configGet("owner"), f"Starting up with pid `{pid}`")
|
if path.exists(path.join(configGet("cache", "locations"), "shutdown_time")):
|
||||||
|
downtime = relativedelta(datetime.now(), datetime.fromtimestamp(jsonLoad(path.join(configGet("cache", "locations"), "shutdown_time"))["timestamp"]))
|
||||||
|
if downtime.days >= 1:
|
||||||
|
app.send_message(configGet("owner"), locale("startup_downtime_days", "message").format(pid, downtime.days))
|
||||||
|
elif downtime.hours >= 1:
|
||||||
|
app.send_message(configGet("owner"), locale("startup_downtime_hours", "message").format(pid, downtime.hours))
|
||||||
|
else:
|
||||||
|
app.send_message(configGet("owner"), locale("startup_downtime_minutes", "message").format(pid, downtime.minutes))
|
||||||
|
else:
|
||||||
|
app.send_message(configGet("owner"), locale("startup", "message").format(pid))
|
||||||
except bad_request_400.PeerIdInvalid:
|
except bad_request_400.PeerIdInvalid:
|
||||||
logWrite(f"Could not send startup message to bot owner. Perhaps user has not started the bot yet.")
|
logWrite(f"Could not send startup message to bot owner. Perhaps user has not started the bot yet.")
|
||||||
|
|
||||||
commands_register(app)
|
|
||||||
|
|
||||||
scheduler.start()
|
scheduler.start()
|
||||||
|
|
||||||
idle()
|
idle()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
app.send_message(configGet("owner"), f"Shutting with pid `{pid}`")
|
app.send_message(configGet("owner"), locale("shutdown", "message").format(pid))
|
||||||
except bad_request_400.PeerIdInvalid:
|
except bad_request_400.PeerIdInvalid:
|
||||||
logWrite(f"Could not send shutdown message to bot owner. Perhaps user has not started the bot yet.")
|
logWrite(f"Could not send shutdown message to bot owner. Perhaps user has not started the bot yet.")
|
||||||
|
|
||||||
app.stop()
|
app.stop()
|
||||||
|
|
||||||
|
makedirs(configGet("cache", "locations"), exist_ok=True)
|
||||||
|
jsonSave({"timestamp": time()}, path.join(configGet("cache", "locations"), "shutdown_time"))
|
||||||
|
|
||||||
killProc(pid)
|
killProc(pid)
|
215
locale/en.disabled
Normal file
215
locale/en.disabled
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
{
|
||||||
|
"message": {
|
||||||
|
"start": "Hello and welcome! This bot was created to accept applications for joining our community. To continue, we are interested in the answer to one question:\n\nDo you want to join the Ukrainian community of Hololive fans?",
|
||||||
|
"goodbye": "Ok, thanks for your honesty! Sorry, but under such conditions we will not add you to the community. If you change your mind and want to join, just click the button.",
|
||||||
|
"privacy_notice": "We're glad to hear that!\n\nTo continue, you will need to fill out a short Application. Please take it seriously. We take personal data very seriously, so this Application will not be shared with any third parties, but will only be used for the community.",
|
||||||
|
"question1": "How can I contact you?",
|
||||||
|
"question2": "When is your birthday?",
|
||||||
|
"question3": "What city are you from or where do you live now?\n\n⚠️ Please do not provide exact addresses! \"Kyiv\" or \"Kyiv Oblast\" is a sufficient specification.\n\nExamples:\n- Kyiv\n- Odesa oblast\n- Makiivka (Luhansk oblast)",
|
||||||
|
"question4": "When did you first learn about Hololive?",
|
||||||
|
"question5": "What made you interested in Hololive?",
|
||||||
|
"question6": "Which girl's content do you like the most?",
|
||||||
|
"question7": "Name the content of at least five Japanese girls you like the most.",
|
||||||
|
"question8": "Do you watch streams of Hololive girls?",
|
||||||
|
"question9": "Whose songs from Hololive do you like the most?",
|
||||||
|
"question10": "And finally, tell us a little about yourself. About hobbies, what you like to do. In one message, please.",
|
||||||
|
"question2_underage": "Sorry, but you must be {0} years old to join us. These restrictions are in place to ensure that everyone in the community has fun with each other.",
|
||||||
|
"question2_invalid": "Please enter a date in the format `DD.MM.YYYY`.",
|
||||||
|
"question2_joke": "Joke, we get it. But please enter the real value.",
|
||||||
|
"question3_invalid": "City/population not found. Use the examples below to indicate where you live and try again:\n\n- Kyiv\n- Odesa region\n- Makiivka (Luhansk region).",
|
||||||
|
"question3_found": "Using the following result:\n- {0} ({1})",
|
||||||
|
"question3_error": "⚠️ **Error**\nCould not retrieve the geographic label. The developer has been notified of this error. Please try again.",
|
||||||
|
"question3_traceback": "⚠️ **Error occurred**\nError retrieving geocoding for `{0}`\nError: `{1}`\n\nTraceback:\n```\n{2}\n```",
|
||||||
|
"confirm": "Great, thanks!\n\nPlease check the data is correct:\n{0}\n\nEverything correct?",
|
||||||
|
"application_sent": "Thank you! We have sent your application for verification. You will receive a message as soon as it is checked and a decision is made. Until then, nothing more is required from you. Have a nice day :)",
|
||||||
|
"application_got": "Received an application from `{0}`\n\nName in tg: `{1}`\nUsername: @{2}\n\n**Application data:**\n{3}",
|
||||||
|
"reapply_got": "Received application change from `{0}`\n\nUsername: `{1}`\nUsername: @{2}\n\n**Application data:**\n{3}",
|
||||||
|
"shutdown": "Shutting down the bot with PID `{0}`",
|
||||||
|
"startup": "Starting the bot with PID `{0}`",
|
||||||
|
"startup_downtime": "Starting bot with PID `{0}` (was down for {1})",
|
||||||
|
"approved": "Congratulations! Your application has been reviewed and your eligibility has been confirmed. Use the button below the notification to join our lamp community!",
|
||||||
|
"approved_joined": "Congratulations! Your application has been reviewed and confirmed as correct. Thank you for your time and have a nice day!",
|
||||||
|
"read_rules": "Please read these rules before clicking the button and joining the chat.",
|
||||||
|
"rejected.": "Oh dear! Your application has been reviewed but not confirmed as eligible to join the community. Better luck next time!\n\nYou can try to reapply with the /reapply command.",
|
||||||
|
"rejected_aggressive": "Oh dear! Your application has been reviewed, but not confirmed as eligible to join the community.",
|
||||||
|
"rejected_russian": "Russian warship, go fuck yourself!",
|
||||||
|
"approved_by": "✅ **Application approved**\nAdmin **{0}** has reviewed and approved application `{1}`.",
|
||||||
|
"rejected_by": "❌ **Form rejected**\nAdmin **{0}** has reviewed and rejected form `{1}`.",
|
||||||
|
"rejected_by_agr": "❌ **Application rejected**\nAdmin **{0}** has reviewed and rejected application `{1}`, banning you from the community",
|
||||||
|
"rejected_by_rus": "❌ **Application rejected**\nAdmin **{0}** has reviewed and rejected the profile `{1}`, banning you from the community",
|
||||||
|
"contact": "Application `{0}`\n\n**Application data:**\n{1}\n\n{2}",
|
||||||
|
"application_status_accepted": "Accepted `{0}` on {1}",
|
||||||
|
"application_status_rejected": "Rejected `{0}` from {1}",
|
||||||
|
"application_status_on_hold": "Application still under review",
|
||||||
|
"application_status_not_send": "The application has not been sent yet",
|
||||||
|
"contact_invalid": "The submitted contact does not have a completed application form.",
|
||||||
|
"contact_not_member": "The sent contact is not a Telegram member.",
|
||||||
|
"already_sent": "The Application has already been sent, just wait. You will be informed immediately what decision will be made.",
|
||||||
|
"sus_joined": "User **{0}** (`{1}`) has joined the group without a personal invitation.",
|
||||||
|
"sus_allowed_by": "✅ **Access Allowed**\nAdmin **{0}** has allowed `{1}` to join the community without being personally invited.",
|
||||||
|
"sus_rejected_by": "❌ **Access denied**\nAdmin **{0}** has banned `{1}` for not being allowed to join the community via a personal link.",
|
||||||
|
"reapply_forbidden": "❌ **Action not possible**\nYour past application has not been approved or rejected yet.",
|
||||||
|
"reapply_in_progress": "❌ **Action not possible**\nYou are already filling out an application right now. If there is an error, just click the button below to start filling it out again.",
|
||||||
|
"reapply_restarted": "🔁 **Restarted**\nStarted filling out the application form again.",
|
||||||
|
"reapply_left_chat": "⚠️ **Reminder**\nIt seems that you left the chat in the past, but your profile is still available for use. Would you like to request membership using your old profile?",
|
||||||
|
"birthday": "User **{0}** (@{1}) has a birthday today! Turned {2} years old",
|
||||||
|
"application_invalid_syntax": "Invalid syntax! `/application ID/NAME/USERNAME`",
|
||||||
|
"warned": "**{0}** (`{1}`) rule violation warned",
|
||||||
|
"warned_reason": "Warned **{0}** (`{1}`)\n\n**Cause:**\n{2}",
|
||||||
|
"warnings_1": "User **{0}** (`{1}`) has **{2}** warnings",
|
||||||
|
"warnings_2": "User **{0}** (`{1}`) has **{2}** warnings",
|
||||||
|
"no_warnings": "User **{0}** (`{1}`) has no warnings",
|
||||||
|
"no_user_warnings": "No users found for query **{0}**",
|
||||||
|
"syntax_warnings": "Invalid syntax! `/warnings ID/NAME/USERNAME`",
|
||||||
|
"message_sent": "Message sent",
|
||||||
|
"message_no_user": "⚠️ **Sending Error**\nThe user ID provided is incorrect, so it was not possible to send the message to the user. Check if the ID is the same as the number that was shown in the Application.",
|
||||||
|
"message_invalid_syntax": "Invalid syntax! `/message ID MESSAGE`",
|
||||||
|
"message_from": "Message from **{0}** (`{1}`):\n\n",
|
||||||
|
"message_reply_notice": "\n\n**To send a reply to this message, tag it.**",
|
||||||
|
"message_error": "⚠️ **Error occurred**\nYour message could not be sent. The developer has been notified of this error.",
|
||||||
|
"message_traceback": "⚠️ **Error occurred**\nMessage error: `{0}` -> `{1}`\nError: `{2}`\n\nTraceback:\n```\n{3}\n```",
|
||||||
|
"no_user_application": "No users found for the query **{0}**",
|
||||||
|
"user_invalid": "The submitted user does not have a completed application.",
|
||||||
|
"joined_false_link": "User **{0}** (`{1}`) did not join the group using their link.",
|
||||||
|
"question_titles": {
|
||||||
|
"question1": "Name:",
|
||||||
|
"question2": "Birthday:",
|
||||||
|
"question3": "Residence:",
|
||||||
|
"question4": "Learned about Hololive:",
|
||||||
|
"question5": "Found interesting about Holo:",
|
||||||
|
"question6": "Like the content of:",
|
||||||
|
"question7": "Japanese hololive girls:",
|
||||||
|
"question8": "Watching streams:",
|
||||||
|
"question9": "Like songs:",
|
||||||
|
"question10": "About me:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keyboard": {
|
||||||
|
"welcome": [
|
||||||
|
[
|
||||||
|
"Yes, of course"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"No, thank you."
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"return": [
|
||||||
|
[
|
||||||
|
"I changed my mind, I want to"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"confirm": [
|
||||||
|
[
|
||||||
|
"Yes, everything is correct"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"No, re-fill"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"force_reply": {
|
||||||
|
"question1": "Name",
|
||||||
|
"question2": "Birthday",
|
||||||
|
"question3": "City or region",
|
||||||
|
"question4": "Approximate time",
|
||||||
|
"question5": "Reasons, features",
|
||||||
|
"question6": "Girl's name",
|
||||||
|
"question7": "Five Japanese Holo girls",
|
||||||
|
"question8": "Yes or no",
|
||||||
|
"question9": "Name of the girl or girls",
|
||||||
|
"question10": "A bit about yourself"
|
||||||
|
},
|
||||||
|
"button": {
|
||||||
|
"sub_yes": "✅ Accept",
|
||||||
|
"sub_no": "❌ Reject",
|
||||||
|
"sub_aggressive": "🤡 Reject (Toxic)",
|
||||||
|
"sub_russian": "🇷🇺 Reject (Russian)",
|
||||||
|
"accepted": "✅ Accepted",
|
||||||
|
"declined": "❌ Rejected",
|
||||||
|
"join": "Join",
|
||||||
|
"sus_allow": "✅ Confirm permission",
|
||||||
|
"sus_reject": "❌ Permanently block",
|
||||||
|
"sus_allowed": "✅ Permission granted",
|
||||||
|
"sus_rejected": "❌ User blocked",
|
||||||
|
"reapply_yes": "✅ Accept",
|
||||||
|
"reapply_no": "❌ Reject",
|
||||||
|
"reapply_old_one": "✅ Send old one",
|
||||||
|
"reapply_new_one": "🔁 Fill in again",
|
||||||
|
"rules_home": "🏠 Home",
|
||||||
|
"rules_additional": "➕ Additional",
|
||||||
|
"rules_next": "Next ➡️",
|
||||||
|
"rules_prev": "⬅️ Back",
|
||||||
|
"applying_stop": "🛑 Interrupt filling",
|
||||||
|
"done": "✅ Done"
|
||||||
|
},
|
||||||
|
"callback": {
|
||||||
|
"sub_accepted": "✅ Application {0} has been approved",
|
||||||
|
"sub_rejected": "❌ Application {0} rejected",
|
||||||
|
"sub_aggressive": "🤡 Application {0} rejected",
|
||||||
|
"sub_russian": "🇷🇺 Application {0} rejected",
|
||||||
|
"sus_allowed": "✅ Access {0} allowed",
|
||||||
|
"sus_rejected": "❌ Access {0} denied",
|
||||||
|
"nothing": "🔔 Action already performed",
|
||||||
|
"rules_page": "ℹ️ Rule {0} shown",
|
||||||
|
"rules_home": "ℹ️ Home rule shown",
|
||||||
|
"rules_additional": "ℹ️ Additional rules shown",
|
||||||
|
"reapply_stopped": "ℹ️ Application stopped."
|
||||||
|
},
|
||||||
|
"inline": {
|
||||||
|
"forbidden": {
|
||||||
|
"title": "Action not available",
|
||||||
|
"description": "You do not have permission to view this",
|
||||||
|
"message_content": "No permission to view this."
|
||||||
|
},
|
||||||
|
"not_pm": {
|
||||||
|
"title": "Action not available",
|
||||||
|
"description": "This command is not available in channels.",
|
||||||
|
"message_content": "Action not available in channels."
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"title": "",
|
||||||
|
"description": "View {0}'s application (@{1})",
|
||||||
|
"message_content": "{0} (@{1})\n\n**Application Data:**\n{2}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rules_msg": "📢The rules can be supplemented and changed, depending on the need. In this case, violations that were committed before the introduction (change) of the rule will not be considered violations. You will be informed about all changes in the rules by means of pinned messages. But they will not be pinned on a permanent basis, so, from time to time, check the relevance of the rules in the bot.\n\n🔔If you see how one of the participants has violated the rules, tag one of the admins in response to a message that you think is a violation. In the post to the tag, indicate on which point you saw the violation. Or send a message to any of the administrators in private messages, and briefly describe the situation.\nList of administrators: @Chirkopol @Za_NerZula @Denialvapr\nFor questions about the functioning of the bot, please contact @Profitroll2281337\n\n❗️Any prohibited content can be sent to the chat using the bot - https://t.me/spoilerobot with a full description of the content contained under the spoiler. For an incorrect or incorrect description, a warning may be issued.\n\n‼️ Deleted or modified messages are still messages on your behalf that could be seen by chat participants and can be tracked through the admin panel.\n\n🔨 For violations - you will receive a warning. If you have 3 warnings, you will be banned for a day. For repeated violations, you will be immediately punished, without additional warnings.",
|
||||||
|
"rules": [
|
||||||
|
"1️⃣) \"HoloKyiv Chat\" and \"HoloUA (Hololive Ukraine) Chat\" are created exclusively for Ukrainians (13+). They can only contain people who: \n- Were born in Ukraine and currently reside in it.\n- Were born outside Ukraine but reside in it.\n- Were born in Ukraine but currently do not reside in it.\n\"HoloUA (Hololive Ukraine) Chat\" is open to all Ukrainians. To get into it, please fill in the form and wait for it to be approved by the administrators.\n\n\"HoloKyiv Chat\" can be accessed only in person if you live in Kyiv or are a close friend of one of the chat participants. To be added to the chat, write @Chirkopol in private messages.\n🔨 If in the process of communication it turns out that you are not Ukrainian, you will be removed from the chat until you become one. No offense. We are creating an exclusively Ukrainian community.",
|
||||||
|
"2️⃣) Distribution of NSFW content with direct or partially hidden pornographic content is prohibited. The content of \"erotic nature\" should be covered with \"questionable\" body parts.\nShock content with a large presence of blood and/or physical injuries is prohibited.",
|
||||||
|
"3️⃣) Anonymity of Hololive and Holostars participants is prohibited: \n- Photos\n- Names\n- Place of residence\n- Exact age (the word \"holohegs\" does not apply)\n- Details of personal life\n- Posts from rummage accounts or mentioning them with specific data (i.e. the phrase \"something happened on Kalli's irl channel\" is allowed, but \"something happened on *irl channel name*\" - no) \n- Details from the girls' past - only superficially and without specifics (i.e. \"was an office worker\" - ok, \"was in *company_name\" - no). \nExceptions - if the girls themselves mentioned it on the archive(!) streams.... This rule does not apply to those who are no longer in Hololive, or have never been part of it. But, please, treat the personal life of other vloggers with respect, and do not exaggerate with the deanons of their personalities.",
|
||||||
|
"4️⃣) Flooding with the same type of messages, emojis, emoticons, stickers, gifs, etc. is prohibited. The approximate number of messages that can receive a warning for this rule is 5. Each situation can be considered separately, but put all your thoughts in one message.",
|
||||||
|
"5️⃣) Video and audio messages that are not intended to convey what you have heard or seen are prohibited. If you want to tell us about how your day went, but do not have the opportunity to type a message, use the magical video-to-text converter - https://t.me/voicybot",
|
||||||
|
"6️⃣) Insults, threats, bullying, humiliation, trolling of participants, their family members, friends and other circle that is close to the chat participant are prohibited. Messages like: \"go to ... \" - are also insults. You can get a warning even if it was your friend. It will be removed if your friend confirms that he is not offended by you.\n🔨 If at the request of a member or administrator, you do not change the pace of communication and do not apologize, you will receive a warning.\nIf your behavior causes a member to leave the chat, the punishment may be more severe.",
|
||||||
|
"7️⃣) It is forbidden to provoke conflicts and incite hatred between chat participants.",
|
||||||
|
"8️⃣) Racism, sexism, homophobia and condemnation of political and (or) religious prejudice are prohibited. These topics can still be part of the dialogue if they do not contain direct condemnations, insults, etc.",
|
||||||
|
"9️⃣) Avatars, nicknames, roles that violate other rules are prohibited."
|
||||||
|
],
|
||||||
|
"rules_additional": "Additional rules that are advisory in nature, and have no explicit penalties for violations:\n1️⃣) There is no ban on the Russian language in the chat. We respect every Ukrainian and do not want to incite language conflicts.\n2️↪Mn_e_20E3↩) There is no ban on Russian content in the chat. But, keep in mind that participants, for the most part, will not be interested in discussing it and it may be ignored.) Do not abuse swear words. Try to communicate in clean language.\n4️⃣) Respect the copyright of content makers. If you find art, animation, music, etc., on official resources (pixiv, twitter, deviantart, etc.), send a link to it.\nIf someone sent art from a non-official resource and you want to know its author, send a message with the text `/search` to the message with the art.",
|
||||||
|
"commands": {
|
||||||
|
"rules": "Check out the rules",
|
||||||
|
"nearby": "Show users near the area",
|
||||||
|
"reapply": "Resubmit the application",
|
||||||
|
"sponsorship": "Apply for sponsor role"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"commands_group_admin": {
|
||||||
|
"reboot": "Restart the bot",
|
||||||
|
"message": "Send a message",
|
||||||
|
"label": "Set user's nickname",
|
||||||
|
"nearby": "Show users near the area",
|
||||||
|
"warnings": "Check user's warnings",
|
||||||
|
"application": "Check user's application",
|
||||||
|
"applications": "Retrieve all applications as a JSON"
|
||||||
|
},
|
||||||
|
"commands_group_destination": {
|
||||||
|
"warn": "Warn a user",
|
||||||
|
"nearby": "Show users near the area"
|
||||||
|
}
|
||||||
|
}
|
129
locale/uk.json
129
locale/uk.json
@@ -13,6 +13,7 @@
|
|||||||
"question8": "Чи дивишся ти стріми дівчат Хололайву?",
|
"question8": "Чи дивишся ти стріми дівчат Хололайву?",
|
||||||
"question9": "Чиї пісні з Хололайву тобі подобаються найбільше?",
|
"question9": "Чиї пісні з Хололайву тобі подобаються найбільше?",
|
||||||
"question10": "Ну і нарешті, розкажи трохи про себе. Про хобі, чим тобі подобається займатись. Одним повідомленням, будь ласка.",
|
"question10": "Ну і нарешті, розкажи трохи про себе. Про хобі, чим тобі подобається займатись. Одним повідомленням, будь ласка.",
|
||||||
|
"question_too_long": "Текст занадто довгий. Будь ласка, умісти відповідь у 256 символів.",
|
||||||
"question2_underage": "Вибач, але треба досягти віку {0} років, щоб приєднатись до нас. Такі обмеження існують для того, щоб всім у спільноті було цікаво одне з одним.",
|
"question2_underage": "Вибач, але треба досягти віку {0} років, щоб приєднатись до нас. Такі обмеження існують для того, щоб всім у спільноті було цікаво одне з одним.",
|
||||||
"question2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
"question2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
||||||
"question2_joke": "Шутнік, ми так і поняли. Але будь ласка, введи реальне значення.",
|
"question2_joke": "Шутнік, ми так і поняли. Але будь ласка, введи реальне значення.",
|
||||||
@@ -20,13 +21,29 @@
|
|||||||
"question3_found": "Використовую наступний результат:\n• {0} ({1})",
|
"question3_found": "Використовую наступний результат:\n• {0} ({1})",
|
||||||
"question3_error": "⚠️ **Сталась помилка**\nНе вдалось отримати географічну мітку. Розробника повідомлено про цю помилку. Будь ласка, спробуйте ще раз.",
|
"question3_error": "⚠️ **Сталась помилка**\nНе вдалось отримати географічну мітку. Розробника повідомлено про цю помилку. Будь ласка, спробуйте ще раз.",
|
||||||
"question3_traceback": "⚠️ **Сталась помилка**\nПомилка отримання геокодингу для `{0}`\nПомилка: `{1}`\n\nTraceback:\n```\n{2}\n```",
|
"question3_traceback": "⚠️ **Сталась помилка**\nПомилка отримання геокодингу для `{0}`\nПомилка: `{1}`\n\nTraceback:\n```\n{2}\n```",
|
||||||
|
"question10_too_long": "Текст занадто довгий. Будь ласка, умісти відповідь у 1024 символи.",
|
||||||
|
"sponsorship_apply": "ℹ️ Оформіть платну підписку на когось з Холо, заповніть форму та отримайте особливу роль в якості винагороди!",
|
||||||
|
"sponsorship_applying": "ℹ️ Розпочато заповнення форми на отримання бонусів за платну підписку на холодівчат.",
|
||||||
|
"sponsor1": "На яку саме дівчину платна підписка?",
|
||||||
|
"sponsor1_invalid": "Будь ласка, введіть ім'я не довше за 240 символів",
|
||||||
|
"sponsor2": "До якої дати (`ДД.ММ.РРРР`) підписка?",
|
||||||
|
"sponsor2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
||||||
|
"sponsor2_past": "Вказана дата знаходиться в минулому. Будь ласка, вкажіть правильний термін дії підписки",
|
||||||
|
"sponsor3": "Будь ласка, надішли одне фото для підтвердження дійсності підписки\n\nℹ️ **Підказка**\nПрочитай як правильно скрінити легітимне підтвердження підписки: https://telegra.ph/Pіdpiska-na-holo-dіvchinu-01-02",
|
||||||
|
"sponsor4": "Яку роль ти бажаєш отримати?\n\nℹ️ **Підказка**\nНазва ролі повинна бути якось пов'язана зі вказаною дівчиною, не повинна порушувати правила спільноти а також має бути не довше за 16 символів (обмеження Telegram).",
|
||||||
|
"sponsorship_application_empty": "❌ **Дія неможлива**\nУ тебе немає заповненої та схваленої анкети. Заповни таку за допомогою /reapply та спробуй ще раз після її підтвердження.",
|
||||||
"confirm": "Супер, дякуємо!\n\nБудь ласка, перевір правильність даних:\n{0}\n\nВсе правильно?",
|
"confirm": "Супер, дякуємо!\n\nБудь ласка, перевір правильність даних:\n{0}\n\nВсе правильно?",
|
||||||
"application_sent": "Дякуємо! Ми надіслали твою анкетку на перевірку. Ти отримаєш повідомлення як тільки її перевірять та приймуть рішення. До тих пір від тебе більше нічого не потребується. Гарного дня! :)",
|
"sponsor_confirm": "**Дані форми:**\nСтрімер: {0}\nПідписка до: {1}\nХочу роль: {2}\n\nПеревір чи все правильно та жмакни кнопку на клавіатурі щоб продовжити.",
|
||||||
"application_got": "Отримано анкету від `{0}`\n\nІм'я тг: `{1}`, `{2}`\nЮзернейм: @{3}\n\n**Дані анкети:**\n{4}",
|
"application_sent": "Дякуємо! Ми надіслали твою анкетку на перевірку. Ти отримаєш повідомлення як тільки її перевірять та приймуть рішення. До тих пір від тебе більше нічого не потребується :)",
|
||||||
"reapply_got": "Отримано змінити анкети від `{0}`\n\nІм'я тг: `{1}`, `{2}`\nЮзернейм: @{3}\n\n**Дані анкети:**\n{4}",
|
"sponsorship_sent": "Дякуємо! Ми надіслали форму на перевірку. Ти отримаєш повідомлення як тільки її перевірять та приймуть рішення :)",
|
||||||
|
"application_got": "Отримано анкету від `{0}`\n\nІм'я тг: `{1}`\nЮзернейм: @{2}\n\n**Дані анкети:**\n{3}",
|
||||||
|
"reapply_got": "Отримано оновлення анкети від `{0}`\n\nІм'я тг: `{1}`\nЮзернейм: @{2}\n\n**Дані анкети:**\n{3}",
|
||||||
|
"sponsor_got": "Отримано форму на спонсорство від `{0}`\n\nІм'я тг: `{1}`\nЮзернейм: @{2}\n\n**Дані форми:**\n{3}",
|
||||||
"shutdown": "Вимкнення бота з підом `{0}`",
|
"shutdown": "Вимкнення бота з підом `{0}`",
|
||||||
"startup": "Запуск бота з підом `{0}`",
|
"startup": "Запуск бота з підом `{0}`",
|
||||||
"startup_downtime": "Запуск бота з підом `{0}` (лежав {1})",
|
"startup_downtime_minutes": "Запуск бота з підом `{0}` (лежав {1} хв.)",
|
||||||
|
"startup_downtime_hours": "Запуск бота з підом `{0}` (лежав {1} год.)",
|
||||||
|
"startup_downtime_days": "Запуск бота з підом `{0}` (лежав {1} дн.)",
|
||||||
"approved": "Вітаємо! Твою анкету переглянули та підтвердили твоє право на вступ. Скористайся кнопкою під повідомленням щоб вступити до нашої лампової спільноти!",
|
"approved": "Вітаємо! Твою анкету переглянули та підтвердили твоє право на вступ. Скористайся кнопкою під повідомленням щоб вступити до нашої лампової спільноти!",
|
||||||
"approved_joined": "Вітаємо! Твою анкету переглянули та підтвердили її правильність. Дякуємо за витрачений на заповнення час та гарного дня!",
|
"approved_joined": "Вітаємо! Твою анкету переглянули та підтвердили її правильність. Дякуємо за витрачений на заповнення час та гарного дня!",
|
||||||
"read_rules": "Будь ласка, прочитай ці правила перш ніж натискати на кнопку та приєднуватись до чату.",
|
"read_rules": "Будь ласка, прочитай ці правила перш ніж натискати на кнопку та приєднуватись до чату.",
|
||||||
@@ -37,6 +54,10 @@
|
|||||||
"rejected_by": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`.",
|
"rejected_by": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`.",
|
||||||
"rejected_by_agr": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`, заборонивши вступ до спільноти.\nПричина: агресивна/токсична анкета.",
|
"rejected_by_agr": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`, заборонивши вступ до спільноти.\nПричина: агресивна/токсична анкета.",
|
||||||
"rejected_by_rus": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`, заборонивши вступ до спільноти.\nПричина: русня.",
|
"rejected_by_rus": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`, заборонивши вступ до спільноти.\nПричина: русня.",
|
||||||
|
"sponsor_approved": "Вітаємо! Твою форму переглянули та підтвердили її правильність. Коли термін дії наданої підписки буде добігати кінця - ми нагадаємо, що треба оновити дані аби й надалі отримувати плюшки в чаті. Також можна повторно заповнити форму, якщо хочеться змінити бажане ім'я ролі або подовжити термін дії підписки завчасно, за допомогою команди /sponsorship. Гарного дня!",
|
||||||
|
"sponsor_rejected": "Ой лишенько! Твою форму переглянули, однак не підтвердили її. Можливо, щось не так з датами, або ж бажана роль не може бути надана.\n\nТи можеш спробувати повторно заповнити форму командою /sponsorship",
|
||||||
|
"sponsor_approved_by": "✅ **Підписку схвалено**\nАдмін **{0}** переглянув та схвалив форму `{1}`.",
|
||||||
|
"sponsor_rejected_by": "❌ **Підписку відхилено**\nАдмін **{0}** переглянув та відхилив форму `{1}`.",
|
||||||
"contact": "Анкета `{0}`\n\n**Дані анкети:**\n{1}\n\n{2}",
|
"contact": "Анкета `{0}`\n\n**Дані анкети:**\n{1}\n\n{2}",
|
||||||
"application_status_accepted": "Прийнята `{0}` від {1}",
|
"application_status_accepted": "Прийнята `{0}` від {1}",
|
||||||
"application_status_rejected": "Відхилена `{0}` від {1}",
|
"application_status_rejected": "Відхилена `{0}` від {1}",
|
||||||
@@ -71,6 +92,39 @@
|
|||||||
"no_user_application": "Не знайдено користувачів за запитом **{0}**",
|
"no_user_application": "Не знайдено користувачів за запитом **{0}**",
|
||||||
"user_invalid": "Надісланий користувач не має завершеної анкети.",
|
"user_invalid": "Надісланий користувач не має завершеної анкети.",
|
||||||
"joined_false_link": "Користувач **{0}** (`{1}`) приєднався до групи не за своїм посиланням",
|
"joined_false_link": "Користувач **{0}** (`{1}`) приєднався до групи не за своїм посиланням",
|
||||||
|
"sponsorships_expires": "⚠️ **Нагадування**\nНадана платна підписка припинить діяти **за {0} д**. Будь ласка, оновіть дані про неї командою /sponsorship інакше роль буде втрачено!",
|
||||||
|
"sponsorships_expired": "⚠️ **Нагадування**\nТермін дії вказаної підписки сплив. Для повторного отримання ролі користуйся командою /sponsorship.",
|
||||||
|
"label_too_long": "Довжина назви ролі не повинна перевищувати 16 символів",
|
||||||
|
"finish_sponsorship": "❌ **Дія неможлива**\nПерш ніж заповнювати анкету, треба завершити заповнення форми спонсора або перервати його командою /cancel.",
|
||||||
|
"finish_application": "❌ **Дія неможлива**\nПерш ніж заповнювати форму спонсора, треба завершити заповнення анкети.",
|
||||||
|
"nearby_invalid": "ℹ️ **Місце не знайдено**\nЗа наданим запитом не знайдено місце з координатами. Спробуйте ще раз формулючи запит в стилі \"Чернівці\" або \"Київська область\".",
|
||||||
|
"nearby_error": "⚠️ **Сталась помилка**\n\nПомилка: `{0}`\n\nTraceback:\n```\n{1}\n```",
|
||||||
|
"nearby_result": "Результати пошуку:\n\n{0}",
|
||||||
|
"nearby_empty": "Здається, нікого поблизу немає.",
|
||||||
|
"cancel": "Всі поточні операції скасовано.",
|
||||||
|
"identify_invalid_syntax": "Неправильний синтаксис!\nТреба: `/identify ID/NAME/USERNAME`",
|
||||||
|
"identify_not_found": "Не знайдено користувачів за запитом **{0}**",
|
||||||
|
"identify_success": "Користувач `{0}`\n\nІм'я: {1}\nЮзернейм: {2}\nЄ в чаті: {3}\nЄ адміном: {4}\nРоль: {5}\nНаявна анкета: {6}\nНаявне спонсорство: {7}",
|
||||||
|
"spoiler_started": "Розпочато створення спойлера. Будь ласка, оберіть категорію спойлера за допомогою клавіатури бота.",
|
||||||
|
"spoiler_unfinished": "У вас ще є незавершений спойлер. Надішліть /cancel щоб зупинити його створення",
|
||||||
|
"spoiler_cancel": "Створення спойлера було припинено",
|
||||||
|
"spoiler_empty": "Спойлер категорії \"{0}\" без опису",
|
||||||
|
"spoiler_described": "Спойлер категорії \"{0}\": {1}",
|
||||||
|
"spoiler_description_enter": "Добре, введіть бажаний опис спойлера",
|
||||||
|
"spoiler_description_too_long": "Текст занадто довгий. Будь ласка, умісти опис у 1024 символи.",
|
||||||
|
"spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)",
|
||||||
|
"spoiler_send_description": "Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.",
|
||||||
|
"spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.",
|
||||||
|
"spoiler_incorrect_content": "Бот не підтримує такий контент. Будь ласка, надішли текст, фото, відео, файл або анімацію (гіф).",
|
||||||
|
"spoiler_incorrect_category": "Вказана категорія не є дійсною. Будь ласка, користуйся клавіатурою бота (кнопка біля 📎) для вибору категорії.",
|
||||||
|
"spoiler_in_progress": "❌ **Дія неможлива**\nПерш ніж починати нову дію, треба завершити створення спойлера або перервати його командою /cancel.",
|
||||||
|
"yes": "Так",
|
||||||
|
"no": "Ні",
|
||||||
|
"voice_message": [
|
||||||
|
"why are u gae",
|
||||||
|
"руки відірвало? пиши як людина",
|
||||||
|
"унга-бунга, не маєш клавіатури?"
|
||||||
|
],
|
||||||
"question_titles": {
|
"question_titles": {
|
||||||
"question1": "Ім'я/звертання:",
|
"question1": "Ім'я/звертання:",
|
||||||
"question2": "День народження:",
|
"question2": "День народження:",
|
||||||
@@ -82,6 +136,16 @@
|
|||||||
"question8": "Дивлюсь стріми:",
|
"question8": "Дивлюсь стріми:",
|
||||||
"question9": "Подобаються пісні:",
|
"question9": "Подобаються пісні:",
|
||||||
"question10": "Про себе:"
|
"question10": "Про себе:"
|
||||||
|
},
|
||||||
|
"sponsor_titles": {
|
||||||
|
"question_streamer": "Стрімер:",
|
||||||
|
"question_expires": "Підписка до:",
|
||||||
|
"question_label": "Хоче роль:"
|
||||||
|
},
|
||||||
|
"spoiler_categories": {
|
||||||
|
"nsfw": "NSFW контент",
|
||||||
|
"deanon": "Деанон холо-учасників",
|
||||||
|
"other": "Інше"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"keyboard": {
|
"keyboard": {
|
||||||
@@ -105,6 +169,17 @@
|
|||||||
[
|
[
|
||||||
"Ні, повторно заповнити"
|
"Ні, повторно заповнити"
|
||||||
]
|
]
|
||||||
|
],
|
||||||
|
"spoiler_categories": [
|
||||||
|
[
|
||||||
|
"NSFW контент"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Деанон холо-учасників"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Інше"
|
||||||
|
]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"force_reply": {
|
"force_reply": {
|
||||||
@@ -117,13 +192,21 @@
|
|||||||
"question7": "П'ять японських холодівчат",
|
"question7": "П'ять японських холодівчат",
|
||||||
"question8": "Так або ні",
|
"question8": "Так або ні",
|
||||||
"question9": "Ім'я дівчини або дівчин",
|
"question9": "Ім'я дівчини або дівчин",
|
||||||
"question10": "Трошки про себе"
|
"question10": "Трошки про себе",
|
||||||
|
"sponsor1": "Ім'я дівчини",
|
||||||
|
"sponsor2": "Дата до якої підписка",
|
||||||
|
"sponsor3": "Фото-підтвердження",
|
||||||
|
"sponsor4": "Бажана роль",
|
||||||
|
"spoiler_content": "Вміст спойлера",
|
||||||
|
"spoiler_description": "Опис спойлера"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"sub_yes": "✅ Прийняти",
|
"sub_yes": "✅ Прийняти",
|
||||||
"sub_no": "❌ Відхилити",
|
"sub_no": "❌ Відхилити",
|
||||||
"sub_aggressive": "🤡 Відхилити (Токс)",
|
"sub_aggressive": "🤡 Відхилити (Токс)",
|
||||||
"sub_russian": "🇷🇺 Відхилити (Русак)",
|
"sub_russian": "🇷🇺 Відхилити (Русак)",
|
||||||
|
"sponsor_yes": "✅ Прийняти",
|
||||||
|
"sponsor_no": "❌ Відхилити",
|
||||||
"accepted": "✅ Прийнято",
|
"accepted": "✅ Прийнято",
|
||||||
"declined": "❌ Відхилено",
|
"declined": "❌ Відхилено",
|
||||||
"join": "Приєднатись",
|
"join": "Приєднатись",
|
||||||
@@ -140,7 +223,11 @@
|
|||||||
"rules_next": "Далі ➡️",
|
"rules_next": "Далі ➡️",
|
||||||
"rules_prev": "⬅️ Назад",
|
"rules_prev": "⬅️ Назад",
|
||||||
"applying_stop": "🛑 Перервати заповнення",
|
"applying_stop": "🛑 Перервати заповнення",
|
||||||
"done": "✅ Готово"
|
"done": "✅ Готово",
|
||||||
|
"sponsor_apply": "Заповнити форму",
|
||||||
|
"sponsor_started": "Форму розпочато",
|
||||||
|
"spoiler_send": "Надіслати",
|
||||||
|
"spoiler_view": "Переглянути"
|
||||||
},
|
},
|
||||||
"callback": {
|
"callback": {
|
||||||
"sub_accepted": "✅ Анкету {0} схвалено",
|
"sub_accepted": "✅ Анкету {0} схвалено",
|
||||||
@@ -153,7 +240,10 @@
|
|||||||
"rules_page": "ℹ️ Показано правило {0}",
|
"rules_page": "ℹ️ Показано правило {0}",
|
||||||
"rules_home": "ℹ️ Показано головну правил",
|
"rules_home": "ℹ️ Показано головну правил",
|
||||||
"rules_additional": "ℹ️ Показано додаткові правила",
|
"rules_additional": "ℹ️ Показано додаткові правила",
|
||||||
"reapply_stopped": "ℹ️ Перервано заповнення анкети"
|
"reapply_stopped": "ℹ️ Перервано заповнення анкети",
|
||||||
|
"sponsor_started": "ℹ️ Заповнення форми розпочато",
|
||||||
|
"sponsor_accepted": "✅ Форму {0} схвалено",
|
||||||
|
"sponsor_rejected": "❌ Форму {0} відхилено"
|
||||||
},
|
},
|
||||||
"inline": {
|
"inline": {
|
||||||
"forbidden": {
|
"forbidden": {
|
||||||
@@ -170,9 +260,13 @@
|
|||||||
"title": "",
|
"title": "",
|
||||||
"description": "Переглянути анкету {0} (@{1})",
|
"description": "Переглянути анкету {0} (@{1})",
|
||||||
"message_content": "{0} (@{1})\n\n**Дані анкети:**\n{2}"
|
"message_content": "{0} (@{1})\n\n**Дані анкети:**\n{2}"
|
||||||
|
},
|
||||||
|
"spoiler": {
|
||||||
|
"title": "Відправити",
|
||||||
|
"description": "Надіслати цей спойлер до чату"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rules_msg": "📢Правила можуть доповнюватись та змінюватись, залежно від потреби. У такому разі, порушення, які були вчинені до введення (змінення) правила, порушеннями вважатися не будуть. Про всі зміни в правилах, ви будете проінформовані за допомогою закріплених повідомлень. Але вони не будуть закріплені на постійній основі, тому, час від часу, перевіряйте актуальність правил у боті.\n\n🔔Якщо ви бачите, як хтось із учасників порушив правила, тегніть одного із адмінів, у відповідь на повідомлення, яке, на вашу думку, є порушенням. У дописі до тегу, вкажіть, по якому пункту ви побачили порушення. Або перешліть повідомлення до будь кого із адміністраторів у особисті повідомлення, та коротко опишіть ситуацію.\nСписок адміністраторів: @Chirkopol @Za_NerZula @Denialvapr\nЗ питань функціонування бота звертайтесь до @Profitroll2281337\n\n❗️Будь-який заборонений контент, може бути відправлений до чату за допомогою бота - https://t.me/spoilerobot з повним описом контенту, що міститься під спойлером. За неправильний або некоректний опис, може бути видане попередження.\n\n‼️Видалені або змінені повідомлення, все ще є повідомленнями від вашого імені, які могли побачити учасники чату, і які можуть бути відстежені через адмінську панель.\n\n🔨 За порушення - ви отримаєте попередження. За наявності 3-х попереджень - мут на добу. За повторні порушення, ви одразу отримаєте покарання, без додаткових попереджень.",
|
"rules_msg": "📢Правила можуть доповнюватись та змінюватись, залежно від потреби. У такому разі, порушення, які були вчинені до введення (змінення) правила, порушеннями вважатися не будуть. Про всі зміни в правилах, ви будете проінформовані за допомогою закріплених повідомлень. Але вони не будуть закріплені на постійній основі, тому, час від часу, перевіряйте актуальність правил у боті.\n\n🔔Якщо ви бачите, як хтось із учасників порушив правила, тегніть одного із адмінів, у відповідь на повідомлення, яке, на вашу думку, є порушенням. У дописі до тегу, вкажіть, по якому пункту ви побачили порушення. Або перешліть повідомлення до будь кого із адміністраторів у особисті повідомлення, та коротко опишіть ситуацію.\nСписок адміністраторів: @Chirkopol @Za_NerZula @Denialvapr\nЗ питань функціонування бота звертайтесь до @Profitroll2281337\n\n❗️Будь-який заборонений контент, може бути відправлений допомогою команди /spoiler у бота - з повним описом контенту, що міститься під спойлером. За неправильний або некоректний опис, може бути видане попередження.\n\n‼️Видалені або змінені повідомлення, все ще є повідомленнями від вашого імені, які могли побачити учасники чату, і які можуть бути відстежені через адмінську панель.\n\n🔨 За порушення - ви отримаєте попередження. За наявності 3-х попереджень - мут на добу. За повторні порушення, ви одразу отримаєте покарання, без додаткових попереджень.",
|
||||||
"rules": [
|
"rules": [
|
||||||
"1️⃣) \"HoloKyiv Chat\" та \"HoloUA (Hololive Ukraine) Chat\" створені виключно для українців (13+). В них можуть знаходитись тільки люди які: \n- Народились в Україні, та проживають, на данний момент, у ній.\n- Народились за межами України, але проживають у ній.\n- Народились в Україні але, на даний момент, не проживають у ній.\n\"HoloUA (Hololive Ukraine) Chat\" відкритий для усіх українців. Щоб потрапити до нього, заповніть, будь ласка, анкету, та дочекайтесь, поки її схвалять адміни.\nУ \"HoloKyiv Chat\" можна потрапити тільки особисто, якщо ви проживаєте у Київі, або є близьким другом одного із учасників чату. Із приводу додавання до чату пишіть @Chirkopol у приватні повідомлення.\n🔨 Якщо у процесі спілкування виявиться, що ви не українець, вас буде видалено із чату, до моменту, поки ви їм не станете. Без образ. Ми створюємо виключно українське ком'юніті.",
|
"1️⃣) \"HoloKyiv Chat\" та \"HoloUA (Hololive Ukraine) Chat\" створені виключно для українців (13+). В них можуть знаходитись тільки люди які: \n- Народились в Україні, та проживають, на данний момент, у ній.\n- Народились за межами України, але проживають у ній.\n- Народились в Україні але, на даний момент, не проживають у ній.\n\"HoloUA (Hololive Ukraine) Chat\" відкритий для усіх українців. Щоб потрапити до нього, заповніть, будь ласка, анкету, та дочекайтесь, поки її схвалять адміни.\nУ \"HoloKyiv Chat\" можна потрапити тільки особисто, якщо ви проживаєте у Київі, або є близьким другом одного із учасників чату. Із приводу додавання до чату пишіть @Chirkopol у приватні повідомлення.\n🔨 Якщо у процесі спілкування виявиться, що ви не українець, вас буде видалено із чату, до моменту, поки ви їм не станете. Без образ. Ми створюємо виключно українське ком'юніті.",
|
||||||
"2️⃣) Заборонено поширення NSFW-контенту з прямим або частково прихованим порнографічним змістом. На контенті \"еротичного характеру\" повинні бути закриті \"сумнівні\" ділянки тіл. \nЗаборонено поширення шок-контенту з великою наявністю крові та/або фізичних пошкоджень.",
|
"2️⃣) Заборонено поширення NSFW-контенту з прямим або частково прихованим порнографічним змістом. На контенті \"еротичного характеру\" повинні бути закриті \"сумнівні\" ділянки тіл. \nЗаборонено поширення шок-контенту з великою наявністю крові та/або фізичних пошкоджень.",
|
||||||
@@ -184,5 +278,22 @@
|
|||||||
"8️⃣) Заборонені прояви расизму, сексизму, гомофобії та засудження за політичні та (або) релігійні упередження. Дані теми все ще можуть бути частиною діалогу, якщо не несуть у собі прямих засуджень, образ тощо.",
|
"8️⃣) Заборонені прояви расизму, сексизму, гомофобії та засудження за політичні та (або) релігійні упередження. Дані теми все ще можуть бути частиною діалогу, якщо не несуть у собі прямих засуджень, образ тощо.",
|
||||||
"9️⃣) Заборонені аватарки, нікнейми, ролі, які порушують інші правила."
|
"9️⃣) Заборонені аватарки, нікнейми, ролі, які порушують інші правила."
|
||||||
],
|
],
|
||||||
"rules_additional": "Додаткові правила, які несуть рекомендаційний характер, та не мають явних покарань за порушення:\n1️⃣) У чаті немає заборони на російську мову. Ми поважаємо кожного українця і не бажаємо розпалювати мовні конфлікти.\n2️⃣) У чаті немає заборони на російський контент. Але, майте на увазі, що учасники, здебільшого, не будуть зацікавлені у тому, щоб обговорювати його і він може бути проігнорованим.\n3️⃣) Не зловживайте матами. Намагайтесь спілкуватись чистою мовою.\n4️⃣) Поважайте авторські права контентмейкерів. Якщо ви знаходите арт, анімацію, музику тощо, на офіційних ресурсах (pixiv, twitter, deviantart тощо), відправляйте на нього посилання.\nЯкщо хтось із учасників відправив арт із не офіційного ресурсу і ви бажаєте дізнатись його автора, відправте у відповідь повідомлення із текстом `/search` на повідомлення із артом."
|
"rules_additional": "Додаткові правила, які несуть рекомендаційний характер, та не мають явних покарань за порушення:\n1️⃣) У чаті немає заборони на російську мову. Ми поважаємо кожного українця і не бажаємо розпалювати мовні конфлікти.\n2️⃣) У чаті немає заборони на російський контент. Але, майте на увазі, що учасники, здебільшого, не будуть зацікавлені у тому, щоб обговорювати його і він може бути проігнорованим.\n3️⃣) Не зловживайте матами. Намагайтесь спілкуватись чистою мовою.\n4️⃣) Поважайте авторські права контентмейкерів. Якщо ви знаходите арт, анімацію, музику тощо, на офіційних ресурсах (pixiv, twitter, deviantart тощо), відправляйте на нього посилання.\nЯкщо хтось із учасників відправив арт із не офіційного ресурсу і ви бажаєте дізнатись його автора, відправте у відповідь повідомлення із текстом `/search` на повідомлення із артом.",
|
||||||
|
"commands": {
|
||||||
|
"application": "Переглянути анкету користувача",
|
||||||
|
"applications": "Отримати всі анкети як JSON",
|
||||||
|
"cancel": "Відмінити актуальну дію",
|
||||||
|
"identify": "Дізнатись дані про користувача за айді",
|
||||||
|
"label": "Встановити нікнейм користувачу",
|
||||||
|
"message": "Надіслати користувачу повідомлення",
|
||||||
|
"nearby": "Показати користувачів поблизу",
|
||||||
|
"reapply": "Повторно заповнити анкету",
|
||||||
|
"reboot": "Перезапустити бота",
|
||||||
|
"resetcommands": "Відреєструвати всі команди",
|
||||||
|
"rules": "Правила спільноти",
|
||||||
|
"spoiler": "Почати створювати спойлер",
|
||||||
|
"sponsorship": "Отримати роль за спонсорство",
|
||||||
|
"warn": "Попередити користувача",
|
||||||
|
"warnings": "Переглянути попередження користувача"
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,9 +1,11 @@
|
|||||||
from app import app
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import CallbackQuery
|
||||||
|
from pyrogram.client import Client
|
||||||
from modules.utils import locale
|
from modules.utils import locale
|
||||||
|
|
||||||
# Callback empty ===============================================================================================================
|
# Callback empty ===============================================================================================================
|
||||||
@app.on_callback_query(filters.regex("nothing"))
|
@app.on_callback_query(filters.regex("nothing"))
|
||||||
async def callback_query_nothing(app, clb):
|
async def callback_query_nothing(app: Client, clb: CallbackQuery):
|
||||||
await clb.answer(text=locale("nothing", "callback"))
|
await clb.answer(text=locale("nothing", "callback", locale=clb.from_user))
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,6 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from app import app
|
from app import app
|
||||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardRemove
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardRemove, CallbackQuery
|
||||||
|
from pyrogram.client import Client
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import configGet, locale, logWrite
|
from modules.utils import configGet, locale, logWrite
|
||||||
@@ -10,42 +11,49 @@ from modules.database import col_tmp, col_applications
|
|||||||
|
|
||||||
# Callbacks reapply ============================================================================================================
|
# Callbacks reapply ============================================================================================================
|
||||||
@app.on_callback_query(filters.regex("reapply_yes_[\s\S]*"))
|
@app.on_callback_query(filters.regex("reapply_yes_[\s\S]*"))
|
||||||
async def callback_reapply_query_accept(app, clb):
|
async def callback_reapply_query_accept(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(int(fullclb[2]))
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
await app.send_message(configGet("admin", "groups"), locale("approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
logWrite(f"User {holo_user.id} got their reapplication approved by {clb.from_user.id}")
|
logWrite(f"User {holo_user.id} got their reapplication approved by {clb.from_user.id}")
|
||||||
|
|
||||||
await app.send_message(holo_user.id, locale("approved_joined", "message"))
|
await app.send_message(holo_user.id, locale("approved_joined", "message", locale=holo_user))
|
||||||
|
|
||||||
col_applications.delete_one({"user": {"$eq": holo_user.id}})
|
applications = col_applications.find({"user": holo_user.id})
|
||||||
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
|
||||||
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "approved", "sent": False}})
|
if len(list(applications)) > 1:
|
||||||
|
col_applications.delete_many({"user": holo_user.id})
|
||||||
|
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
||||||
|
elif applications == 1:
|
||||||
|
col_applications.find_one_and_replace({"user": holo_user.id}, {"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
||||||
|
else:
|
||||||
|
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
||||||
|
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"state": "approved", "sent": False}})
|
||||||
|
|
||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
await clb.answer(text=locale("sub_accepted", "callback").format(holo_user.id), show_alert=True)
|
await clb.answer(text=locale("sub_accepted", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
|
||||||
|
|
||||||
need_link = True
|
need_link = True
|
||||||
|
|
||||||
async for member in app.get_chat_members(configGet("destination_group")):
|
async for member in app.get_chat_members(configGet("users", "groups")):
|
||||||
if member.user.id == holo_user.id:
|
if member.user.id == holo_user.id:
|
||||||
need_link = False
|
need_link = False
|
||||||
|
|
||||||
if need_link:
|
if need_link:
|
||||||
link = await app.create_chat_invite_link(configGet("destination_group"), name=f"Invite for {holo_user.id}", member_limit=1) #, expire_date=datetime.now()+timedelta(days=1))
|
link = await app.create_chat_invite_link(configGet("users", "groups"), name=f"Invite for {holo_user.id}", member_limit=1) #, expire_date=datetime.now()+timedelta(days=1))
|
||||||
|
|
||||||
await app.send_message(holo_user.id, locale("read_rules", "message"))
|
await app.send_message(holo_user.id, locale("read_rules", "message", locale=holo_user))
|
||||||
|
|
||||||
for rule_msg in locale("rules"):
|
for rule_msg in locale("rules", locale=holo_user):
|
||||||
await app.send_message(holo_user.id, rule_msg)
|
await app.send_message(holo_user.id, rule_msg)
|
||||||
|
|
||||||
await app.send_message(holo_user.id, locale("approved", "message"), reply_markup=InlineKeyboardMarkup(
|
await app.send_message(holo_user.id, locale("approved", "message"), reply_markup=InlineKeyboardMarkup(
|
||||||
[[
|
[[
|
||||||
InlineKeyboardButton(str(locale("join", "button")), url=link.invite_link)
|
InlineKeyboardButton(str(locale("join", "button", locale=holo_user)), url=link.invite_link)
|
||||||
]]
|
]]
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -53,16 +61,16 @@ async def callback_reapply_query_accept(app, clb):
|
|||||||
logWrite(f"User {holo_user.id} got an invite link {link.invite_link}")
|
logWrite(f"User {holo_user.id} got an invite link {link.invite_link}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await app.send_message(holo_user.id, locale("approved_joined", "message"))
|
await app.send_message(holo_user.id, locale("approved_joined", "message", locale=holo_user))
|
||||||
|
|
||||||
@app.on_callback_query(filters.regex("reapply_no_[\s\S]*"))
|
@app.on_callback_query(filters.regex("reapply_no_[\s\S]*"))
|
||||||
async def callback_query_reapply_reject(app, clb):
|
async def callback_query_reapply_reject(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(int(fullclb[2]))
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("rejected_by", "message").format(clb.from_user.first_name, fullclb[2]), disable_notification=True)
|
await app.send_message(configGet("admin", "groups"), locale("rejected_by", "message").format(clb.from_user.first_name, fullclb[2]), disable_notification=True)
|
||||||
await app.send_message(holo_user.id, locale("rejected", "message"))
|
await app.send_message(holo_user.id, locale("rejected", "message", locale=holo_user))
|
||||||
logWrite(f"User {fullclb[2]} got their reapplication rejected by {clb.from_user.id}")
|
logWrite(f"User {fullclb[2]} got their reapplication rejected by {clb.from_user.id}")
|
||||||
|
|
||||||
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
||||||
@@ -70,39 +78,49 @@ async def callback_query_reapply_reject(app, clb):
|
|||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
await clb.answer(text=locale("sub_rejected", "callback").format(fullclb[2]), show_alert=True)
|
await clb.answer(text=locale("sub_rejected", "callback", locale=clb.from_user).format(fullclb[2]), show_alert=True)
|
||||||
|
|
||||||
# Use old application when user reapplies after leaving the chat
|
# Use old application when user reapplies after leaving the chat
|
||||||
@app.on_callback_query(filters.regex("reapply_old_[\s\S]*"))
|
@app.on_callback_query(filters.regex("reapply_old_[\s\S]*"))
|
||||||
async def callback_query_reapply_old(app, clb):
|
async def callback_query_reapply_old(app: Client, clb: CallbackQuery):
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
|
|
||||||
|
if HoloUser(clb.from_user).sponsorship_state()[0] == "fill":
|
||||||
|
await clb.message.reply_text(locale("finish_sponsorship", "message"), quote=False)
|
||||||
|
return
|
||||||
|
|
||||||
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
|
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
|
||||||
await confirm_yes(app, message)
|
await confirm_yes(app, message, kind="application")
|
||||||
await clb.message.edit(clb.message.text, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("done", "button"), "nothing")]]))
|
await clb.message.edit(clb.message.text, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("done", "button", locale=clb.from_user), "nothing")]]))
|
||||||
|
|
||||||
# Start a new application when user reapplies after leaving the chat
|
# Start a new application when user reapplies after leaving the chat
|
||||||
@app.on_callback_query(filters.regex("reapply_new_[\s\S]*"))
|
@app.on_callback_query(filters.regex("reapply_new_[\s\S]*"))
|
||||||
async def callback_query_reapply_new(app, clb):
|
async def callback_query_reapply_new(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
|
|
||||||
await clb.answer(locale("reapply_stopped", "callback"))
|
if HoloUser(clb.from_user).sponsorship_state()[0] == "fill":
|
||||||
|
await clb.message.reply_text(locale("finish_sponsorship", "message"), quote=False)
|
||||||
|
return
|
||||||
|
|
||||||
|
await clb.answer(locale("reapply_stopped", "callback", locale=clb.from_user))
|
||||||
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
|
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
|
||||||
|
col_tmp.update_one({"user": clb.from_user.id}, {"$set": {"state": "fill", "completed": False, "stage": 1}})
|
||||||
await welcome_pass(app, message, once_again=True)
|
await welcome_pass(app, message, once_again=True)
|
||||||
logWrite(f"User {clb.from_user.id} restarted the application after leaving the chat earlier")
|
logWrite(f"User {clb.from_user.id} restarted the application after leaving the chat earlier")
|
||||||
await clb.message.edit(clb.message.text, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("done", "button"), "nothing")]]))
|
await clb.message.edit(clb.message.text, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("done", "button", locale=clb.from_user), "nothing")]]))
|
||||||
|
|
||||||
# Abort application fill in progress and restart it
|
# Abort application fill in progress and restart it
|
||||||
@app.on_callback_query(filters.regex("reapply_stop_[\s\S]*"))
|
@app.on_callback_query(filters.regex("reapply_stop_[\s\S]*"))
|
||||||
async def callback_query_reapply_stop(app, clb):
|
async def callback_query_reapply_stop(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(clb.from_user)
|
holo_user = HoloUser(clb.from_user)
|
||||||
|
|
||||||
holo_user.application_restart()
|
holo_user.application_restart()
|
||||||
await clb.answer(locale("reapply_stopped", "callback"))
|
await clb.answer(locale("reapply_stopped", "callback", locale=holo_user))
|
||||||
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
|
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
|
||||||
await welcome_pass(app, message, once_again=True)
|
await welcome_pass(app, message, once_again=True)
|
||||||
logWrite(f"User {clb.from_user.id} restarted the application due to typo in it")
|
logWrite(f"User {clb.from_user.id} restarted the application due to typo in it")
|
||||||
await clb.message.edit(locale("reapply_restarted", "message"), reply_markup=ReplyKeyboardRemove())
|
await clb.message.edit(locale("reapply_restarted", "message", locale=holo_user), reply_markup=ReplyKeyboardRemove())
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,13 +1,14 @@
|
|||||||
from app import app
|
from app import app
|
||||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
|
||||||
|
from pyrogram.client import Client
|
||||||
from pyrogram.errors import bad_request_400
|
from pyrogram.errors import bad_request_400
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from modules.utils import locale, logWrite
|
from modules.utils import locale, logWrite
|
||||||
from modules.commands.rules import default_rules_markup
|
from modules.commands.rules import DefaultRulesMarkup
|
||||||
|
|
||||||
# Callback rule ================================================================================================================
|
# Callback rule ================================================================================================================
|
||||||
@app.on_callback_query(filters.regex("rule_[\s\S]*"))
|
@app.on_callback_query(filters.regex("rule_[\s\S]*"))
|
||||||
async def callback_query_rule(app, clb):
|
async def callback_query_rule(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
|
|
||||||
@@ -17,24 +18,24 @@ async def callback_query_rule(app, clb):
|
|||||||
|
|
||||||
if rule_num == len(locale("rules")):
|
if rule_num == len(locale("rules")):
|
||||||
lower_buttons = [
|
lower_buttons = [
|
||||||
InlineKeyboardButton(locale("rules_prev", "button"), callback_data=f"rule_{rule_num-1}")
|
InlineKeyboardButton(locale("rules_prev", "button", locale=clb.from_user), callback_data=f"rule_{rule_num-1}")
|
||||||
]
|
]
|
||||||
elif rule_num == 1:
|
elif rule_num == 1:
|
||||||
lower_buttons = [
|
lower_buttons = [
|
||||||
InlineKeyboardButton(locale("rules_next", "button"), callback_data=f"rule_{rule_num+1}")
|
InlineKeyboardButton(locale("rules_next", "button", locale=clb.from_user), callback_data=f"rule_{rule_num+1}")
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
lower_buttons = [
|
lower_buttons = [
|
||||||
InlineKeyboardButton(locale("rules_prev", "button"), callback_data=f"rule_{rule_num-1}"),
|
InlineKeyboardButton(locale("rules_prev", "button", locale=clb.from_user), callback_data=f"rule_{rule_num-1}"),
|
||||||
InlineKeyboardButton(locale("rules_next", "button"), callback_data=f"rule_{rule_num+1}")
|
InlineKeyboardButton(locale("rules_next", "button", locale=clb.from_user), callback_data=f"rule_{rule_num+1}")
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await clb.message.edit(text=locale("rules")[rule_num-1], disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup(
|
await clb.message.edit(text=locale("rules", locale=clb.from_user)[rule_num-1], disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup(
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
InlineKeyboardButton(locale("rules_home", "button"), callback_data="rules_home"),
|
InlineKeyboardButton(locale("rules_home", "button", locale=clb.from_user), callback_data="rules_home"),
|
||||||
InlineKeyboardButton(locale("rules_additional", "button"), callback_data="rules_additional")
|
InlineKeyboardButton(locale("rules_additional", "button", locale=clb.from_user), callback_data="rules_additional")
|
||||||
],
|
],
|
||||||
lower_buttons
|
lower_buttons
|
||||||
]
|
]
|
||||||
@@ -43,29 +44,29 @@ async def callback_query_rule(app, clb):
|
|||||||
except bad_request_400.MessageNotModified:
|
except bad_request_400.MessageNotModified:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
await clb.answer(text=locale("rules_page", "callback").format(fullclb[1]))
|
await clb.answer(text=locale("rules_page", "callback", locale=clb.from_user).format(fullclb[1]))
|
||||||
|
|
||||||
@app.on_callback_query(filters.regex("rules_home"))
|
@app.on_callback_query(filters.regex("rules_home"))
|
||||||
async def callback_query_rules_home(app, clb):
|
async def callback_query_rules_home(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
logWrite(f"User {clb.from_user.id} requested to check out homepage rules")
|
logWrite(f"User {clb.from_user.id} requested to check out homepage rules")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await clb.message.edit(text=locale("rules_msg"), disable_web_page_preview=True, reply_markup=default_rules_markup)
|
await clb.message.edit(text=locale("rules_msg", locale=clb.from_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(clb.from_user).keyboard)
|
||||||
except bad_request_400.MessageNotModified:
|
except bad_request_400.MessageNotModified:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
await clb.answer(text=locale("rules_home", "callback"))
|
await clb.answer(text=locale("rules_home", "callback", locale=clb.from_user))
|
||||||
|
|
||||||
@app.on_callback_query(filters.regex("rules_additional"))
|
@app.on_callback_query(filters.regex("rules_additional"))
|
||||||
async def callback_query_rules_additional(app, clb):
|
async def callback_query_rules_additional(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
logWrite(f"User {clb.from_user.id} requested to check out additional rules")
|
logWrite(f"User {clb.from_user.id} requested to check out additional rules")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await clb.message.edit(text=locale("rules_additional"), disable_web_page_preview=True, reply_markup=default_rules_markup)
|
await clb.message.edit(text=locale("rules_additional", locale=clb.from_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(clb.from_user).keyboard)
|
||||||
except bad_request_400.MessageNotModified:
|
except bad_request_400.MessageNotModified:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
await clb.answer(text=locale("rules_additional", "callback"))
|
await clb.answer(text=locale("rules_additional", "callback", locale=clb.from_user))
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
10
modules/callbacks/sid.py
Normal file
10
modules/callbacks/sid.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from app import app
|
||||||
|
from pyrogram.types import CallbackQuery
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram import filters
|
||||||
|
|
||||||
|
# Callback rule ================================================================================================================
|
||||||
|
@app.on_callback_query(filters.regex("sid_[\s\S]*"))
|
||||||
|
async def callback_query_rule(app: Client, clb: CallbackQuery):
|
||||||
|
await clb.answer(url=f'https://t.me/{(await app.get_me()).username}?start={clb.data.split("_")[1]}')
|
||||||
|
# ==============================================================================================================================
|
103
modules/callbacks/sponsorship.py
Normal file
103
modules/callbacks/sponsorship.py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from app import app
|
||||||
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ForceReply, CallbackQuery
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram import filters
|
||||||
|
from classes.errors.holo_user import LabelSettingError
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
|
from modules.utils import configGet, locale, logWrite, should_quote
|
||||||
|
from modules.database import col_tmp, col_sponsorships
|
||||||
|
|
||||||
|
# Callbacks sponsorship ========================================================================================================
|
||||||
|
@app.on_callback_query(filters.regex("sponsor_apply_[\s\S]*"))
|
||||||
|
async def callback_query_sponsor_apply(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
|
fullclb = clb.data.split("_")
|
||||||
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
|
if holo_user.application_state()[0] == "fill":
|
||||||
|
await clb.message.reply_text(locale("finish_application", "message"), quote=should_quote(clb.message))
|
||||||
|
return
|
||||||
|
|
||||||
|
logWrite(f"User {holo_user.id} applied for sponsorship")
|
||||||
|
|
||||||
|
holo_user.sponsorship_restart()
|
||||||
|
|
||||||
|
edited_markup = [[InlineKeyboardButton(text=str(locale("sponsor_started", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
|
await clb.message.edit(text=locale("sponsorship_applying", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
|
await app.send_message(holo_user.id, locale(f"sponsor1", "message", locale=holo_user), reply_markup=ForceReply(placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale))))
|
||||||
|
await clb.answer(text=locale("sponsor_started", "callback", locale=holo_user).format(holo_user.id), show_alert=False)
|
||||||
|
|
||||||
|
@app.on_callback_query(filters.regex("sponsor_yes_[\s\S]*"))
|
||||||
|
async def callback_query_sponsor_yes(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
|
fullclb = clb.data.split("_")
|
||||||
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
|
await app.send_message(configGet("admin", "groups"), locale("sponsor_approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
|
await app.send_message(holo_user.id, locale("sponsor_approved", "message", locale=holo_user))
|
||||||
|
logWrite(f"User {holo_user.id} got sponsorship approved by {clb.from_user.id}")
|
||||||
|
|
||||||
|
if col_sponsorships.find_one({"user": holo_user.id}) is not None:
|
||||||
|
col_sponsorships.update_one({"user": holo_user.id},
|
||||||
|
{
|
||||||
|
"$set": {
|
||||||
|
"date": datetime.now(),
|
||||||
|
"admin": clb.from_user.id,
|
||||||
|
"sponsorship": col_tmp.find_one({"user": holo_user.id, "type": "sponsorship"})["sponsorship"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
col_sponsorships.insert_one(
|
||||||
|
{
|
||||||
|
"user": holo_user.id,
|
||||||
|
"date": datetime.now(),
|
||||||
|
"admin": clb.from_user.id,
|
||||||
|
"sponsorship": col_tmp.find_one({"user": holo_user.id, "type": "sponsorship"})["sponsorship"]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
col_tmp.update_one({"user": holo_user.id, "type":"sponsorship"},
|
||||||
|
{
|
||||||
|
"$set": {
|
||||||
|
"state": "approved",
|
||||||
|
"sent": False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await holo_user.label_set(configGet("users", "groups"), col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}})["sponsorship"]["label"])
|
||||||
|
except LabelSettingError as exp:
|
||||||
|
await app.send_message(configGet("admin", "groups"), exp.__str__(), disable_notification=True)
|
||||||
|
|
||||||
|
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
|
await app.edit_message_caption(clb.message.chat.id, clb.message.id, caption=clb.message.caption, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
|
await clb.answer(text=locale("sponsor_accepted", "callback").format(fullclb[2]), show_alert=False)
|
||||||
|
|
||||||
|
@app.on_callback_query(filters.regex("sponsor_no_[\s\S]*"))
|
||||||
|
async def callback_query_sponsor_no(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
|
fullclb = clb.data.split("_")
|
||||||
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
|
await app.send_message(configGet("admin", "groups"), locale("sponsor_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
|
await app.send_message(holo_user.id, locale("sponsor_rejected", "message", locale=holo_user))
|
||||||
|
logWrite(f"User {holo_user.id} got sponsorship rejected by {clb.from_user.id}")
|
||||||
|
|
||||||
|
col_tmp.update_one({"user": holo_user.id, "type": "sponsorship"},
|
||||||
|
{
|
||||||
|
"$set": {
|
||||||
|
"state": "rejected",
|
||||||
|
"sent": False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
|
await app.edit_message_caption(clb.message.chat.id, clb.message.id, caption=clb.message.caption, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
|
await clb.answer(text=locale("sponsor_rejected", "callback").format(fullclb[2]), show_alert=False)
|
@@ -1,38 +1,39 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from app import app
|
from app import app
|
||||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
|
from pyrogram.client import Client
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import configGet, locale, logWrite
|
from modules.utils import configGet, locale, logWrite
|
||||||
from modules.database import col_tmp, col_applications
|
from modules.database import col_tmp, col_applications
|
||||||
from modules.commands.rules import default_rules_markup
|
from modules.commands.rules import DefaultRulesMarkup
|
||||||
|
|
||||||
# Callbacks application ========================================================================================================
|
# Callbacks application ========================================================================================================
|
||||||
@app.on_callback_query(filters.regex("sub_yes_[\s\S]*"))
|
@app.on_callback_query(filters.regex("sub_yes_[\s\S]*"))
|
||||||
async def callback_query_accept(app, clb):
|
async def callback_query_accept(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(int(fullclb[2]))
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
await app.send_message(configGet("admin", "groups"), locale("approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
logWrite(f"User {holo_user.id} got approved by {clb.from_user.id}")
|
logWrite(f"User {holo_user.id} got approved by {clb.from_user.id}")
|
||||||
|
|
||||||
need_link = True
|
need_link = True
|
||||||
|
|
||||||
async for member in app.get_chat_members(configGet("destination_group")):
|
async for member in app.get_chat_members(configGet("users", "groups")):
|
||||||
if member.user.id == holo_user.id:
|
if member.user.id == holo_user.id:
|
||||||
need_link = False
|
need_link = False
|
||||||
|
|
||||||
if need_link:
|
if need_link:
|
||||||
link = await app.create_chat_invite_link(configGet("destination_group"), name=f"Invite for {holo_user.id}", member_limit=1) #, expire_date=datetime.now()+timedelta(days=1))
|
link = await app.create_chat_invite_link(configGet("users", "groups"), name=f"Invite for {holo_user.id}", member_limit=1) #, expire_date=datetime.now()+timedelta(days=1))
|
||||||
|
|
||||||
await app.send_message(holo_user.id, locale("read_rules", "message"))
|
await app.send_message(holo_user.id, locale("read_rules", "message", locale=holo_user))
|
||||||
|
|
||||||
await app.send_message(holo_user.id, locale("rules_msg"), disable_web_page_preview=True, reply_markup=default_rules_markup)
|
await app.send_message(holo_user.id, locale("rules_msg", locale=holo_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(holo_user).keyboard)
|
||||||
|
|
||||||
await app.send_message(holo_user.id, locale("approved", "message"), reply_markup=InlineKeyboardMarkup(
|
await app.send_message(holo_user.id, locale("approved", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup(
|
||||||
[[
|
[[
|
||||||
InlineKeyboardButton(str(locale("join", "button")), url=link.invite_link)
|
InlineKeyboardButton(str(locale("join", "button", locale=holo_user)), url=link.invite_link)
|
||||||
]]
|
]]
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ async def callback_query_accept(app, clb):
|
|||||||
logWrite(f"User {holo_user.id} got an invite link {link.invite_link}")
|
logWrite(f"User {holo_user.id} got an invite link {link.invite_link}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await app.send_message(holo_user.id, locale("approved_joined", "message"))
|
await app.send_message(holo_user.id, locale("approved_joined", "message", locale=holo_user))
|
||||||
|
|
||||||
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
||||||
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "approved", "sent": False}})
|
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "approved", "sent": False}})
|
||||||
@@ -48,16 +49,16 @@ async def callback_query_accept(app, clb):
|
|||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
await clb.answer(text=locale("sub_accepted", "callback").format(holo_user.id), show_alert=True)
|
await clb.answer(text=locale("sub_accepted", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
|
||||||
|
|
||||||
@app.on_callback_query(filters.regex("sub_no_[\s\S]*"))
|
@app.on_callback_query(filters.regex("sub_no_[\s\S]*"))
|
||||||
async def callback_query_reject(app, clb):
|
async def callback_query_reject(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(int(fullclb[2]))
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
await app.send_message(configGet("admin", "groups"), locale("rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
await app.send_message(holo_user.id, locale("rejected", "message"))
|
await app.send_message(holo_user.id, locale("rejected", "message", locale=holo_user))
|
||||||
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id}")
|
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id}")
|
||||||
|
|
||||||
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
||||||
@@ -65,16 +66,16 @@ async def callback_query_reject(app, clb):
|
|||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
await clb.answer(text=locale("sub_rejected", "callback").format(holo_user.id), show_alert=True)
|
await clb.answer(text=locale("sub_rejected", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
|
||||||
|
|
||||||
@app.on_callback_query(filters.regex("sub_aggressive_[\s\S]*"))
|
@app.on_callback_query(filters.regex("sub_aggressive_[\s\S]*"))
|
||||||
async def callback_query_reject_aggressive(app, clb):
|
async def callback_query_reject_aggressive(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(int(fullclb[2]))
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("rejected_by_agr", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
await app.send_message(configGet("admin", "groups"), locale("rejected_by_agr", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
await app.send_message(holo_user.id, locale("rejected_aggressive", "message"))
|
await app.send_message(holo_user.id, locale("rejected_aggressive", "message", locale=holo_user))
|
||||||
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id} due to being aggressive")
|
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id} due to being aggressive")
|
||||||
|
|
||||||
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
||||||
@@ -82,16 +83,16 @@ async def callback_query_reject_aggressive(app, clb):
|
|||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
await clb.answer(text=locale("sub_aggressive", "callback").format(holo_user.id), show_alert=True)
|
await clb.answer(text=locale("sub_aggressive", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
|
||||||
|
|
||||||
@app.on_callback_query(filters.regex("sub_russian_[\s\S]*"))
|
@app.on_callback_query(filters.regex("sub_russian_[\s\S]*"))
|
||||||
async def callback_query_reject_russian(app, clb):
|
async def callback_query_reject_russian(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(int(fullclb[2]))
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("rejected_by_rus", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
await app.send_message(configGet("admin", "groups"), locale("rejected_by_rus", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
await app.send_message(holo_user.id, locale("rejected_russian", "message"))
|
await app.send_message(holo_user.id, locale("rejected_russian", "message", locale=holo_user))
|
||||||
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id} due to being russian")
|
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id} due to being russian")
|
||||||
|
|
||||||
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
||||||
@@ -99,5 +100,5 @@ async def callback_query_reject_russian(app, clb):
|
|||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
await clb.answer(text=locale("sub_russian", "callback").format(holo_user.id), show_alert=True)
|
await clb.answer(text=locale("sub_russian", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,5 +1,6 @@
|
|||||||
from app import app
|
from app import app
|
||||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ChatPermissions
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ChatPermissions, CallbackQuery
|
||||||
|
from pyrogram.client import Client
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import configGet, locale, logWrite
|
from modules.utils import configGet, locale, logWrite
|
||||||
@@ -7,20 +8,20 @@ from modules.database import col_tmp
|
|||||||
|
|
||||||
# Callbacks sus users ==========================================================================================================
|
# Callbacks sus users ==========================================================================================================
|
||||||
@app.on_callback_query(filters.regex("sus_allow_[\s\S]*"))
|
@app.on_callback_query(filters.regex("sus_allow_[\s\S]*"))
|
||||||
async def callback_query_sus_allow(app, clb):
|
async def callback_query_sus_allow(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(int(fullclb[2]))
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("sus_allowed_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
await app.send_message(configGet("admin", "groups"), locale("sus_allowed_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
logWrite(f"User {holo_user.id} was allowed to join with another link by {clb.from_user.id}")
|
logWrite(f"User {holo_user.id} was allowed to join with another link by {clb.from_user.id}")
|
||||||
|
|
||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("sus_allowed", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("sus_allowed", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
await clb.answer(text=locale("sus_allowed", "callback").format(holo_user.id), show_alert=True)
|
await clb.answer(text=locale("sus_allowed", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
|
||||||
|
|
||||||
await app.restrict_chat_member(configGet("destination_group"), holo_user.id, permissions=ChatPermissions(
|
await app.restrict_chat_member(configGet("users", "groups"), holo_user.id, permissions=ChatPermissions(
|
||||||
can_send_messages=True,
|
can_send_messages=True,
|
||||||
can_send_media_messages=True,
|
can_send_media_messages=True,
|
||||||
can_send_other_messages=True,
|
can_send_other_messages=True,
|
||||||
@@ -29,20 +30,20 @@ async def callback_query_sus_allow(app, clb):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@app.on_callback_query(filters.regex("sus_reject_[\s\S]*"))
|
@app.on_callback_query(filters.regex("sus_reject_[\s\S]*"))
|
||||||
async def callback_query_sus_reject(app, clb):
|
async def callback_query_sus_reject(app: Client, clb: CallbackQuery):
|
||||||
|
|
||||||
fullclb = clb.data.split("_")
|
fullclb = clb.data.split("_")
|
||||||
holo_user = HoloUser(int(fullclb[2]))
|
holo_user = HoloUser(int(fullclb[2]))
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("sus_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
await app.send_message(configGet("admin", "groups"), locale("sus_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
|
||||||
logWrite(f"User {holo_user.id} was rejected to join with another link by {clb.from_user.id}")
|
logWrite(f"User {holo_user.id} was rejected to join with another link by {clb.from_user.id}")
|
||||||
|
|
||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("sus_rejected", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("sus_rejected", "button")), callback_data="nothing")]]
|
||||||
|
|
||||||
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
|
||||||
await clb.answer(text=locale("sus_rejected", "callback").format(holo_user.id), show_alert=True)
|
await clb.answer(text=locale("sus_rejected", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
|
||||||
|
|
||||||
await app.ban_chat_member(configGet("destination_group"), holo_user.id)
|
await app.ban_chat_member(configGet("users", "groups"), holo_user.id)
|
||||||
|
|
||||||
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,96 +1,62 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from app import app, isAnAdmin
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.enums.parse_mode import ParseMode
|
from pyrogram.enums.parse_mode import ParseMode
|
||||||
|
from pyrogram.types import Message
|
||||||
from pyrogram.errors import bad_request_400
|
from pyrogram.errors import bad_request_400
|
||||||
from classes.holo_user import HoloUser, UserNotFoundError
|
from pyrogram.client import Client
|
||||||
|
from classes.errors.holo_user import UserNotFoundError
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import logWrite, locale, should_quote
|
from modules.utils import logWrite, locale, should_quote
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from modules.database import col_applications
|
from modules.database import col_applications
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Applications command =========================================================================================================
|
# Application command ==========================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.command(["application"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["application"], prefixes=["/"]) & custom_filters.admin)
|
||||||
async def cmd_application(app, msg):
|
async def cmd_application(app: Client, msg: Message):
|
||||||
|
|
||||||
if await isAnAdmin(msg.from_user.id) is True:
|
try:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
holo_user = HoloUser(int(msg.command[1]))
|
||||||
|
except (ValueError, UserNotFoundError):
|
||||||
try:
|
try:
|
||||||
holo_user = HoloUser(int(msg.command[1]))
|
holo_user = HoloUser((await app.get_users(msg.command[1])).id)
|
||||||
except (ValueError, UserNotFoundError):
|
except (bad_request_400.UsernameInvalid, bad_request_400.PeerIdInvalid, bad_request_400.UsernameNotOccupied):
|
||||||
try:
|
await msg.reply_text(locale("no_user_application", "message", locale=msg.from_user).format(msg.command[1]), quote=should_quote(msg))
|
||||||
holo_user = HoloUser((await app.get_users(msg.command[1])).id)
|
|
||||||
except (bad_request_400.UsernameInvalid, bad_request_400.PeerIdInvalid):
|
|
||||||
await msg.reply_text(locale("no_user_application", "message").format(msg.command[1]), quote=should_quote(msg))
|
|
||||||
return
|
|
||||||
|
|
||||||
application = col_applications.find_one({"user": holo_user.id})
|
|
||||||
|
|
||||||
if application is None:
|
|
||||||
logWrite(f"User {msg.from_user.id} requested application of {holo_user.id} but user does not exists")
|
|
||||||
await msg.reply_text(locale("user_invalid", "message"), quote=should_quote(msg))
|
|
||||||
return
|
return
|
||||||
|
|
||||||
application_content = []
|
application = col_applications.find_one({"user": holo_user.id})
|
||||||
i = 1
|
|
||||||
|
|
||||||
for question in application['application']:
|
if application is None:
|
||||||
|
logWrite(f"User {msg.from_user.id} requested application of {holo_user.id} but user does not exists")
|
||||||
|
await msg.reply_text(locale("user_invalid", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||||
|
return
|
||||||
|
|
||||||
if i == 2:
|
application_content = []
|
||||||
age = relativedelta(datetime.now(), application['application']['2'])
|
i = 1
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
|
||||||
elif i == 3:
|
for question in application['application']:
|
||||||
if application['application']['3']['countryCode'] == "UA":
|
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']}")
|
if i == 2:
|
||||||
else:
|
age = relativedelta(datetime.now(), application['application']['2'])
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
||||||
|
elif i == 3:
|
||||||
|
if application['application']['3']['countryCode'] == "UA":
|
||||||
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['3']['name']}")
|
||||||
else:
|
else:
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application'][question]}")
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
|
||||||
|
else:
|
||||||
i += 1
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application'][question]}")
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
application_status = locale("application_status_accepted", "message").format((await app.get_users(application["admin"])).first_name, application["date"].strftime("%d.%m.%Y, %H:%M"))
|
application_status = locale("application_status_accepted", "message", locale=msg.from_user).format((await app.get_users(application["admin"])).first_name, application["date"].strftime("%d.%m.%Y, %H:%M"))
|
||||||
|
|
||||||
logWrite(f"User {msg.from_user.id} requested application of {holo_user.id}")
|
logWrite(f"User {msg.from_user.id} requested application of {holo_user.id}")
|
||||||
await msg.reply_text(locale("contact", "message").format(holo_user.id, "\n".join(application_content), application_status), parse_mode=ParseMode.MARKDOWN, quote=should_quote(msg))
|
await msg.reply_text(locale("contact", "message", locale=msg.from_user).format(holo_user.id, "\n".join(application_content), application_status), parse_mode=ParseMode.MARKDOWN, quote=should_quote(msg))
|
||||||
|
|
||||||
# if (path.exists(f"{configGet('data', 'locations')}{sep}users{sep}{msg.command[1]}.json") and jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{msg.command[1]}.json")["approved"]):
|
except IndexError:
|
||||||
# user_id = int(msg.command[1])
|
await msg.reply_text(locale("application_invalid_syntax", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||||
# else:
|
|
||||||
# list_of_users = []
|
|
||||||
# async for m in app.get_chat_members(configGet("destination_group"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]):
|
|
||||||
# list_of_users.append(m)
|
|
||||||
# user_id = list_of_users[0].user.id
|
|
||||||
# try:
|
|
||||||
# user_data = jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{user_id}.json")
|
|
||||||
# application = jsonLoad(f"{configGet('data', 'locations')}{sep}applications.json")[str(user_id)]
|
|
||||||
# application_content = []
|
|
||||||
# i = 1
|
|
||||||
# for question in configGet("application", file=str(msg.from_user.id)):
|
|
||||||
# if i == 2:
|
|
||||||
# age = relativedelta(datetime.now(), datetime.strptime(application['application']['2'], '%d.%m.%Y'))
|
|
||||||
# application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {application['application']['2']} ({age.years} р.)")
|
|
||||||
# else:
|
|
||||||
# application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {application['application'][question]}")
|
|
||||||
# i += 1
|
|
||||||
# if user_data["sent"]:
|
|
||||||
# if user_data["approved"]:
|
|
||||||
# application_status = locale("application_status_accepted", "message").format((await app.get_users(application["approved_by"])).first_name, datetime.fromtimestamp(application["approval_date"]).strftime("%d.%m.%Y, %H:%M"))
|
|
||||||
# elif application["rejected"]:
|
|
||||||
# application_status = locale("application_status_rejected", "message").format((await app.get_users(application["rejected_by"])).first_name, datetime.fromtimestamp(application["refusal_date"]).strftime("%d.%m.%Y, %H:%M"))
|
|
||||||
# else:
|
|
||||||
# application_status = locale("application_status_on_hold", "message")
|
|
||||||
# else:
|
|
||||||
# if user_data["approved"]:
|
|
||||||
# application_status = locale("application_status_accepted", "message").format((await app.get_users(application["approved_by"])).first_name, datetime.fromtimestamp(application["approval_date"]).strftime("%d.%m.%Y, %H:%M"))
|
|
||||||
# elif application["rejected"]:
|
|
||||||
# application_status = locale("application_status_rejected", "message").format((await app.get_users(application["rejected_by"])).first_name, datetime.fromtimestamp(application["refusal_date"]).strftime("%d.%m.%Y, %H:%M"))
|
|
||||||
# else:
|
|
||||||
# application_status = locale("application_status_not_send", "message")
|
|
||||||
# logWrite(f"User {msg.from_user.id} requested application of {user_id}")
|
|
||||||
# await msg.reply_text(locale("contact", "message").format(str(user_id), "\n".join(application_content), application_status), quote=should_quote(msg))
|
|
||||||
|
|
||||||
except IndexError:
|
|
||||||
await msg.reply_text(locale("application_invalid_syntax", "message"), quote=should_quote(msg))
|
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,23 +1,30 @@
|
|||||||
from os import sep, makedirs, remove
|
from os import sep, makedirs, remove
|
||||||
from uuid import uuid1
|
from uuid import uuid1
|
||||||
from app import app, isAnAdmin
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
from pyrogram.enums.chat_action import ChatAction
|
from pyrogram.enums.chat_action import ChatAction
|
||||||
|
from modules.logging import logWrite
|
||||||
from modules.utils import should_quote, jsonSave
|
from modules.utils import should_quote, jsonSave
|
||||||
from modules.database import col_applications
|
from modules.database import col_applications
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Applications command =========================================================================================================
|
# Applications command =========================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.command(["applications"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["applications"], prefixes=["/"]) & custom_filters.admin)
|
||||||
async def cmd_applications(app, msg):
|
async def cmd_applications(app: Client, msg: Message):
|
||||||
|
|
||||||
if await isAnAdmin(msg.from_user.id) is True:
|
logWrite(f"Admin {msg.from_user.id} requested export of a database")
|
||||||
await app.send_chat_action(msg.chat.id, ChatAction.UPLOAD_DOCUMENT)
|
await app.send_chat_action(msg.chat.id, ChatAction.UPLOAD_DOCUMENT)
|
||||||
filename = uuid1()
|
filename = uuid1()
|
||||||
output = []
|
output = []
|
||||||
for entry in col_applications.find():
|
for entry in col_applications.find():
|
||||||
output.append(entry)
|
del entry["_id"]
|
||||||
makedirs("tmp", exist_ok=True)
|
entry["date"] = entry["date"].strftime("%d.%m.%Y, %H:%M")
|
||||||
jsonSave(output, f"tmp{sep}{filename}.json")
|
entry["application"]["2"] = entry["application"]["2"].strftime("%d.%m.%Y, %H:%M")
|
||||||
await msg.reply_document(document=f"tmp{sep}{filename}.json", file_name="applications", quote=should_quote(msg))
|
output.append(entry)
|
||||||
remove(f"tmp{sep}{filename}.json")
|
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")
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
16
modules/commands/cancel.py
Normal file
16
modules/commands/cancel.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from app import app
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message, ReplyKeyboardRemove
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from modules.utils import should_quote, logWrite, locale
|
||||||
|
from modules.database import col_tmp, col_spoilers
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
|
# Cancel command ===============================================================================================================
|
||||||
|
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("cancel", prefixes=["/"]))
|
||||||
|
async def command_cancel(app: Client, msg: Message):
|
||||||
|
col_tmp.delete_many( {"user": msg.from_user.id, "sent": False} )
|
||||||
|
col_spoilers.delete_many( {"user": msg.from_user.id, "completed": False} )
|
||||||
|
await msg.reply_text(locale("cancel", "message", locale=msg.from_user), quote=should_quote(msg), reply_markup=ReplyKeyboardRemove())
|
||||||
|
logWrite(f"Cancelling all ongoing tmp operations for {msg.from_user.id}")
|
||||||
|
# ==============================================================================================================================
|
66
modules/commands/identify.py
Normal file
66
modules/commands/identify.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
from os import path
|
||||||
|
from app import app, isAnAdmin
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from pyrogram.errors import bad_request_400
|
||||||
|
from pyrogram.enums.chat_action import ChatAction
|
||||||
|
from classes.errors.holo_user import UserNotFoundError, UserInvalidError
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
|
from modules.utils import jsonLoad, should_quote, logWrite, locale, download_tmp, create_tmp, find_user
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
|
# Identify command =============================================================================================================
|
||||||
|
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("identify", prefixes=["/"]) & custom_filters.admin)
|
||||||
|
async def cmd_identify(app: Client, msg: Message):
|
||||||
|
|
||||||
|
if len(msg.command) != 2:
|
||||||
|
await msg.reply_text(locale("identify_invalid_syntax", "message", locale=msg.from_user))
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
holo_user = HoloUser(int(msg.command[1]))
|
||||||
|
except ValueError:
|
||||||
|
holo_user = HoloUser(await find_user(app, msg.command[1]))
|
||||||
|
except (UserInvalidError, UserNotFoundError, bad_request_400.UsernameInvalid, bad_request_400.PeerIdInvalid, bad_request_400.UsernameNotOccupied, TypeError):
|
||||||
|
await msg.reply_text(locale("identify_not_found", "message", locale=msg.from_user).format(msg.command[1]))
|
||||||
|
return
|
||||||
|
|
||||||
|
role = holo_user.label
|
||||||
|
has_application = locale("yes", "message", locale=msg.from_user) if holo_user.application_approved() is True else locale("no", "message", locale=msg.from_user)
|
||||||
|
has_sponsorship = locale("yes", "message", locale=msg.from_user) if holo_user.sponsorship_valid() is True else locale("no", "message", locale=msg.from_user)
|
||||||
|
|
||||||
|
username = holo_user.username if holo_user.username is not None else "N/A"
|
||||||
|
in_chat = locale("yes", "message", locale=msg.from_user) if (holo_user.id in jsonLoad(path.join("cache", "group_members"))) else locale("no", "message", locale=msg.from_user)
|
||||||
|
is_admin = locale("yes", "message", locale=msg.from_user) if (await isAnAdmin(holo_user.id)) else locale("no", "message", locale=msg.from_user)
|
||||||
|
|
||||||
|
output = locale("identify_success", "message", locale=msg.from_user).format(
|
||||||
|
holo_user.id,
|
||||||
|
holo_user.name,
|
||||||
|
username,
|
||||||
|
in_chat,
|
||||||
|
is_admin,
|
||||||
|
role,
|
||||||
|
has_application,
|
||||||
|
has_sponsorship
|
||||||
|
)
|
||||||
|
|
||||||
|
user = await app.get_users(holo_user.id)
|
||||||
|
|
||||||
|
if user.photo is not None:
|
||||||
|
await app.send_chat_action(msg.chat.id, action=ChatAction.UPLOAD_PHOTO)
|
||||||
|
await msg.reply_photo(
|
||||||
|
create_tmp(await download_tmp(app, user.photo.big_file_id), kind="image"),
|
||||||
|
quote=should_quote(msg),
|
||||||
|
caption=output
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await app.send_chat_action(msg.chat.id, action=ChatAction.TYPING)
|
||||||
|
await msg.reply_text(
|
||||||
|
output,
|
||||||
|
quote=should_quote(msg)
|
||||||
|
)
|
||||||
|
|
||||||
|
logWrite(f"User {msg.from_user.id} identified user {holo_user.id}")
|
||||||
|
# ==============================================================================================================================
|
@@ -1,32 +1,43 @@
|
|||||||
from app import app, isAnAdmin
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from modules.utils import should_quote, find_user
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from modules.utils import configGet, locale, should_quote, find_user
|
||||||
|
from classes.errors.holo_user import LabelTooLongError, LabelSettingError
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
@app.on_message(~ filters.scheduled & filters.private & filters.command(["label"], prefixes=["/"]))
|
# Label command ================================================================================================================
|
||||||
async def cmd_label(app, msg):
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["label"], prefixes=["/"]) & custom_filters.admin)
|
||||||
|
async def cmd_label(app: Client, msg: Message):
|
||||||
|
|
||||||
if await isAnAdmin(msg.from_user.id) is True:
|
if len(msg.command) < 3:
|
||||||
|
await msg.reply_text("Invalid syntax:\n`/label USER LABEL`")
|
||||||
|
return
|
||||||
|
|
||||||
if len(msg.command) < 3:
|
target = await find_user(app, msg.command[1])
|
||||||
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)
|
||||||
|
|
||||||
if target is not None:
|
label = " ".join(msg.command[2:])
|
||||||
|
|
||||||
|
if label.lower() == "reset":
|
||||||
|
await target.label_reset(msg.chat)
|
||||||
|
await msg.reply_text(f"Resetting **{target.id}**'s label...", quote=should_quote(msg))
|
||||||
|
|
||||||
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:
|
else:
|
||||||
await msg.reply_text(f"User not found")
|
try:
|
||||||
|
await target.label_set(msg.chat, label)
|
||||||
|
except LabelTooLongError:
|
||||||
|
await msg.reply_text(locale("label_too_long", "message"))
|
||||||
|
return
|
||||||
|
except LabelSettingError as exp:
|
||||||
|
await app.send_message(configGet("admin", "groups"), exp.__str__(), disable_notification=True)
|
||||||
|
return
|
||||||
|
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")
|
||||||
|
# ==============================================================================================================================
|
@@ -1,32 +1,34 @@
|
|||||||
from app import app, isAnAdmin
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from classes.errors.holo_user import UserInvalidError
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import logWrite, locale, should_quote
|
from modules.utils import logWrite, locale, should_quote, find_user
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Message command ==============================================================================================================
|
# Message command ==============================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.command(["message"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.command(["message"], prefixes=["/"]) & custom_filters.admin)
|
||||||
async def cmd_message(app, msg):
|
async def cmd_message(app: Client, msg: Message):
|
||||||
|
|
||||||
if await isAnAdmin(msg.from_user.id) is True:
|
try:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
destination = HoloUser(int(msg.command[1]))
|
||||||
|
except (ValueError, UserInvalidError):
|
||||||
|
destination = HoloUser(await find_user(app, query=msg.command[1]))
|
||||||
|
|
||||||
try:
|
if ((msg.text is not None) and (len(msg.text.split()) > 2)):
|
||||||
destination = HoloUser(int(msg.command[1]))
|
await destination.message(context=msg, text=" ".join(msg.text.split()[2:]), caption=msg.caption, photo=msg.photo, video=msg.video, file=msg.document, voice=msg.voice, animation=msg.animation, adm_context=True)
|
||||||
except ValueError:
|
elif ((msg.caption is not None) and (len(msg.caption.split()) > 2)):
|
||||||
destination = HoloUser(msg.command[1])
|
await destination.message(context=msg, text=msg.text, caption=" ".join(msg.caption.split()[2:]), photo=msg.photo, video=msg.video, file=msg.document, voice=msg.voice, animation=msg.animation, adm_context=True)
|
||||||
|
else:
|
||||||
if ((msg.text is not None) and (len(msg.text.split()) > 2)):
|
await destination.message(context=msg, text=None, caption=None, photo=msg.photo, video=msg.video, file=msg.document, voice=msg.voice, animation=msg.animation, adm_context=True)
|
||||||
await destination.message(context=msg, text=" ".join(msg.text.split()[2:]), caption=msg.caption, photo=msg.photo, video=msg.video, file=msg.document, adm_context=True)
|
|
||||||
elif ((msg.caption is not None) and (len(msg.caption.split()) > 2)):
|
except IndexError:
|
||||||
await destination.message(context=msg, text=msg.text, caption=" ".join(msg.caption.split()[2:]), photo=msg.photo, video=msg.video, file=msg.document, adm_context=True)
|
await msg.reply_text(locale("message_invalid_syntax", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||||
else:
|
logWrite(f"Admin {msg.from_user.id} tried to send message but 'IndexError'")
|
||||||
await destination.message(context=msg, text=None, caption=None, photo=msg.photo, video=msg.video, file=msg.document, adm_context=True)
|
except ValueError:
|
||||||
|
await msg.reply_text(locale("message_invalid_syntax", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||||
except IndexError:
|
logWrite(f"Admin {msg.from_user.id} tried to send message but 'ValueError'")
|
||||||
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'")
|
|
||||||
except ValueError:
|
|
||||||
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 'ValueError'")
|
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,24 +1,58 @@
|
|||||||
from app import app, isAnAdmin
|
from traceback import print_exc
|
||||||
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from modules.utils import configGet, should_quote
|
from pyrogram.types import Message
|
||||||
from modules.database import col_applications
|
from pyrogram.client import Client
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
|
from modules import custom_filters
|
||||||
|
from modules.logging import logWrite
|
||||||
|
from modules.utils import configGet, locale, should_quote, find_location
|
||||||
|
from modules.database import col_applications, col_users
|
||||||
|
from classes.errors.geo import PlaceNotFoundError
|
||||||
|
|
||||||
# Nearby command ===============================================================================================================
|
# Nearby command ===============================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & (filters.private | (filters.chat(configGet("admin_group")) | filters.chat(configGet("destination_group")))) & filters.command(["nearby"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & (filters.private | (filters.chat(configGet("admin", "groups")) | filters.chat(configGet("users", "groups")))) & filters.command(["nearby"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin))
|
||||||
async def cmd_nearby(app, msg):
|
async def cmd_nearby(app: Client, msg: Message):
|
||||||
if (await isAnAdmin(msg) is True) or (col_applications.find_one({"user": msg.from_user.id}) is not None):
|
|
||||||
await msg.reply_text("Yes, I exist.", quote=should_quote(msg))
|
holo_user = HoloUser(msg.from_user)
|
||||||
# if not path.exists(f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json"):
|
|
||||||
# jsonSave(jsonLoad(f"{configGet('data', 'locations')}{sep}sponsor_default.json"), f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json")
|
# Check if any place provided
|
||||||
# sponsor = jsonLoad(f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json")
|
if len(msg.command) == 1: # Action if no place provided
|
||||||
# if sponsor["approved"]:
|
application = col_applications.find_one({"user": msg.from_user.id})
|
||||||
# if sponsor["expires"] is not None:
|
if application is None:
|
||||||
# if datetime.strptime(sponsor["expires"], "%d.%m.%Y") > datetime.now():
|
await msg.reply_text(locale("nearby_user_empty", "message", locale=holo_user))
|
||||||
# await msg.reply_text(f"You have an active sub til **{sponsor['expires']}**.")
|
return
|
||||||
# else:
|
location = application["application"]["3"]["location"][0], application["application"]["3"]["location"][1]
|
||||||
# await msg.reply_text(f"Your sub expired {int((datetime.now()-datetime.strptime(sponsor['expires'], '%d.%m.%Y')).days)} days ago.")
|
else: # Find a place from input query
|
||||||
# elif sponsor["approved"]:
|
logWrite(f"Looking for the location by query '{' '.join(msg.command[1:])}'")
|
||||||
# await msg.reply_text(f"Your sub expiration date is not valid.")
|
try:
|
||||||
# else:
|
location_coordinates = find_location(" ".join(msg.command[1:]))
|
||||||
# await msg.reply_text(f"You have no active subscription.")
|
location = float(location_coordinates["lng"]), float(location_coordinates["lat"])
|
||||||
|
except PlaceNotFoundError: # Place is not found
|
||||||
|
await msg.reply_text(locale("nearby_invalid", "message", locale=holo_user), quote=should_quote(msg))
|
||||||
|
return
|
||||||
|
except Exception as exp: # Error occurred while finding the place
|
||||||
|
await msg.reply_text(locale("nearby_error", "message", locale=holo_user).format(exp, print_exc()), quote=should_quote(msg))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Find all users registered in the area provided
|
||||||
|
output = []
|
||||||
|
applications_nearby = col_applications.find( {"application.3.location": { "$nearSphere": {"$geometry": {"type": "Point", "coordinates": [location[0], location[1]]}, "$maxDistance": configGet("search_radius")*1000} } } )
|
||||||
|
|
||||||
|
for entry in applications_nearby:
|
||||||
|
if not entry["user"] == msg.from_user.id:
|
||||||
|
user = col_users.find_one( {"user": entry["user"]} )
|
||||||
|
if user is not None:
|
||||||
|
if user["tg_username"] not in [None, "None", ""]: # Check if user has any name
|
||||||
|
output.append(f'• **{user["tg_name"]}** (@{user["tg_username"]}):\n - {entry["application"]["3"]["name"]}, {entry["application"]["3"]["adminName1"]}')
|
||||||
|
else:
|
||||||
|
output.append(f'• **{user["tg_name"]}**:\n - {entry["application"]["3"]["name"]}, {entry["application"]["3"]["adminName1"]}')
|
||||||
|
|
||||||
|
logWrite(f"{holo_user.id} tried to find someone nearby {location[1]} {location[0]} in the radius of {configGet('search_radius')} kilometers")
|
||||||
|
|
||||||
|
# Check if any users found
|
||||||
|
if len(output) > 0:
|
||||||
|
await msg.reply_text(locale("nearby_result", "message", locale=holo_user).format("\n".join(output)), quote=should_quote(msg))
|
||||||
|
else:
|
||||||
|
await msg.reply_text(locale("nearby_empty", "message", locale=holo_user), quote=should_quote(msg))
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,48 +1,78 @@
|
|||||||
from app import app
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
|
||||||
|
from pyrogram.client import Client
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import configGet, locale
|
from modules.logging import logWrite
|
||||||
|
from modules.utils import configGet, locale, should_quote
|
||||||
from modules.handlers.welcome import welcome_pass
|
from modules.handlers.welcome import welcome_pass
|
||||||
from modules.database import col_tmp
|
from modules.database import col_tmp
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Reapply command ==============================================================================================================
|
# Reapply command ==============================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.private & filters.command(["reapply"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(["reapply"], prefixes=["/"]))
|
||||||
async def cmd_reapply(app, msg):
|
async def cmd_reapply(app: Client, msg: Message):
|
||||||
|
|
||||||
holo_user = HoloUser(msg.from_user)
|
holo_user = HoloUser(msg.from_user)
|
||||||
|
|
||||||
if holo_user.application_state()[0] in ["approved", "rejected"]:
|
# Check if user has approved/rejected tmp application
|
||||||
if (holo_user.application_state()[1] is True) and (not col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"]):
|
if ((holo_user.application_state()[0] in ["approved", "rejected"]) or (holo_user.application_state()[0] == "none")) and holo_user.spoiler_state() is False:
|
||||||
|
|
||||||
|
# Check if user's tmp application is already completed or even sent
|
||||||
|
if ((holo_user.application_state()[1] is True) and (not col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"])) or (holo_user.application_state()[0] == "none"):
|
||||||
|
|
||||||
left_chat = True
|
left_chat = True
|
||||||
async for member in app.get_chat_members(configGet("destination_group")):
|
|
||||||
|
async for member in app.get_chat_members(configGet("users", "groups")):
|
||||||
if member.user.id == msg.from_user.id:
|
if member.user.id == msg.from_user.id:
|
||||||
left_chat = False
|
left_chat = False
|
||||||
|
|
||||||
if not left_chat:
|
if not left_chat:
|
||||||
holo_user.application_restart()
|
if holo_user.sponsorship_state()[0] == "fill":
|
||||||
|
await msg.reply_text(locale("finish_sponsorship", "message"), quote=should_quote(msg))
|
||||||
|
return
|
||||||
|
holo_user.application_restart(reapply=True)
|
||||||
await welcome_pass(app, msg, once_again=True)
|
await welcome_pass(app, msg, once_again=True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await msg.reply_text(locale("reapply_left_chat", "message"), reply_markup=InlineKeyboardMarkup([
|
|
||||||
[
|
if holo_user.application_state()[1] is True and holo_user.application_state()[0] != "fill":
|
||||||
InlineKeyboardButton(locale("reapply_old_one", "button"), f"reapply_old_{msg.id}")
|
|
||||||
],
|
await msg.reply_text(locale("reapply_left_chat", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup([
|
||||||
[
|
[
|
||||||
InlineKeyboardButton(locale("reapply_new_one", "button"), f"reapply_new_{msg.id}")
|
InlineKeyboardButton(locale("reapply_old_one", "button", locale=holo_user), f"reapply_old_{msg.id}")
|
||||||
]
|
],
|
||||||
]))
|
[
|
||||||
|
InlineKeyboardButton(locale("reapply_new_one", "button", locale=holo_user), f"reapply_new_{msg.id}")
|
||||||
|
]
|
||||||
|
]))
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
holo_user.application_restart(reapply=True)
|
||||||
|
await welcome_pass(app, msg, once_again=True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await msg.reply_text(locale("reapply_in_progress", "message").format(locale("confirm", "keyboard")[1][0]), reply_markup=InlineKeyboardMarkup([
|
|
||||||
|
await msg.reply_text(locale("reapply_in_progress", "message", locale=holo_user).format(locale("confirm", "keyboard", locale=holo_user)[1][0]), reply_markup=InlineKeyboardMarkup([
|
||||||
[
|
[
|
||||||
InlineKeyboardButton(locale("applying_stop", "button"), f"reapply_stop_{msg.id}")
|
InlineKeyboardButton(locale("applying_stop", "button", locale=holo_user), f"reapply_stop_{msg.id}")
|
||||||
]
|
]
|
||||||
]))
|
]))
|
||||||
|
|
||||||
|
elif holo_user.spoiler_state() is True:
|
||||||
|
|
||||||
|
await msg.reply_text(locale("spoiler_in_progress", "message", locale=holo_user))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
if (holo_user.application_state()[0] == "fill") and (col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"] is True):
|
if (holo_user.application_state()[0] == "fill") and (col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"] is True):
|
||||||
await msg.reply_text(locale("reapply_forbidden", "message"))
|
await msg.reply_text(locale("reapply_forbidden", "message", locale=holo_user))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await msg.reply_text(locale("reapply_in_progress", "message").format(locale("confirm", "keyboard")[1][0]), reply_markup=InlineKeyboardMarkup([
|
await msg.reply_text(locale("reapply_in_progress", "message", locale=holo_user).format(locale("confirm", "keyboard", locale=holo_user)[1][0]), reply_markup=InlineKeyboardMarkup([
|
||||||
[
|
[
|
||||||
InlineKeyboardButton(locale("applying_stop", "button"), f"reapply_stop_{msg.id}")
|
InlineKeyboardButton(locale("applying_stop", "button", locale=holo_user), f"reapply_stop_{msg.id}")
|
||||||
]
|
]
|
||||||
]))
|
]))
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,19 +1,24 @@
|
|||||||
from app import app, isAnAdmin
|
from app import app
|
||||||
from os import getpid
|
from os import getpid, makedirs, path
|
||||||
from sys import exit
|
from sys import exit
|
||||||
|
from time import time
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from modules.utils import logWrite, should_quote
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from modules.utils import configGet, jsonSave, locale, logWrite, should_quote
|
||||||
from modules.scheduled import scheduler
|
from modules.scheduled import scheduler
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
pid = getpid()
|
pid = getpid()
|
||||||
|
|
||||||
# Shutdown command =============================================================================================================
|
# Reboot command ===============================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["/"]) & custom_filters.admin)
|
||||||
async def cmd_kill(app, msg):
|
async def cmd_kill(app: Client, msg: Message):
|
||||||
|
|
||||||
if await isAnAdmin(msg.from_user.id) is True:
|
logWrite(f"Shutting down bot with pid {pid}")
|
||||||
logWrite(f"Shutting down bot with pid {pid}")
|
await msg.reply_text(locale("shutdown", "message", locale=msg.from_user).format(pid), quote=should_quote(msg))
|
||||||
await msg.reply_text(f"Вимкнення бота з підом `{pid}`", quote=should_quote(msg))
|
scheduler.shutdown()
|
||||||
scheduler.shutdown()
|
makedirs(configGet("cache", "locations"), exist_ok=True)
|
||||||
exit()
|
jsonSave({"timestamp": time()}, path.join(configGet("cache", "locations"), "shutdown_time"))
|
||||||
|
exit()
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
58
modules/commands/resetcommands.py
Normal file
58
modules/commands/resetcommands.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
from app import app
|
||||||
|
from os import getpid, listdir
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message, BotCommandScopeDefault, BotCommandScopeChat
|
||||||
|
from pyrogram.errors import bad_request_400
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from modules.utils import logWrite, should_quote, configGet
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
|
pid = getpid()
|
||||||
|
|
||||||
|
# Reset commands command =======================================================================================================
|
||||||
|
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["resetcommands"], prefixes=["/"]) & custom_filters.admin)
|
||||||
|
async def cmd_resetcommands(app: Client, msg: Message):
|
||||||
|
|
||||||
|
if msg.from_user.id == configGet("owner"):
|
||||||
|
|
||||||
|
logWrite(f"Resetting all commands on owner's request")
|
||||||
|
|
||||||
|
valid_locales = []
|
||||||
|
files_locales = listdir(f'{configGet("locale", "locations")}')
|
||||||
|
|
||||||
|
for entry in files_locales:
|
||||||
|
if entry.endswith(".json"):
|
||||||
|
valid_locales.append(".".join(entry.split(".")[:-1]))
|
||||||
|
|
||||||
|
logWrite(f'Resetting commands in groups {configGet("admin", "groups")} and {configGet("users", "groups")}', debug=True)
|
||||||
|
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")))
|
||||||
|
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("users", "groups")))
|
||||||
|
|
||||||
|
for admin in configGet("admins"):
|
||||||
|
try:
|
||||||
|
logWrite(f'Resetting commands for admin {admin}', debug=True)
|
||||||
|
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=admin))
|
||||||
|
except bad_request_400.PeerIdInvalid:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
logWrite(f'Resetting commands for owner {configGet("owner")}', debug=True)
|
||||||
|
for lc in valid_locales:
|
||||||
|
logWrite(f'Resetting commands for owner {configGet("owner")} [{lc}]', debug=True)
|
||||||
|
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")), language_code=lc)
|
||||||
|
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")))
|
||||||
|
except bad_request_400.PeerIdInvalid:
|
||||||
|
pass
|
||||||
|
|
||||||
|
for lc in valid_locales:
|
||||||
|
logWrite(f'Resetting commands for locale {lc}', debug=True)
|
||||||
|
await app.delete_bot_commands(scope=BotCommandScopeDefault(), language_code=lc)
|
||||||
|
|
||||||
|
logWrite(f'Resetting default commands', debug=True)
|
||||||
|
await app.delete_bot_commands()
|
||||||
|
|
||||||
|
await msg.reply_text("OK", quote=should_quote(msg))
|
||||||
|
|
||||||
|
logWrite(str(await app.get_bot_commands()), debug=True)
|
||||||
|
logWrite(str(await app.get_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")))), debug=True)
|
||||||
|
# ==============================================================================================================================
|
@@ -1,34 +1,42 @@
|
|||||||
|
from typing import Union
|
||||||
from app import app
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, User, Message
|
||||||
|
from pyrogram.client import Client
|
||||||
from modules.utils import locale
|
from modules.utils import locale
|
||||||
|
from modules import custom_filters
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
|
|
||||||
|
class DefaultRulesMarkup(list):
|
||||||
|
def __init__(self, language_code: Union[str, HoloUser, User, None]):
|
||||||
|
super().__init__([])
|
||||||
|
self.keyboard = InlineKeyboardMarkup(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(locale("rules_home", "button", locale=language_code), callback_data="rules_home"),
|
||||||
|
InlineKeyboardButton(locale("rules_additional", "button", locale=language_code), callback_data="rules_additional")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("1", callback_data="rule_1"),
|
||||||
|
InlineKeyboardButton("2", callback_data="rule_2"),
|
||||||
|
InlineKeyboardButton("3", callback_data="rule_3")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("4", callback_data="rule_4"),
|
||||||
|
InlineKeyboardButton("5", callback_data="rule_5"),
|
||||||
|
InlineKeyboardButton("6", callback_data="rule_6")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("7", callback_data="rule_7"),
|
||||||
|
InlineKeyboardButton("8", callback_data="rule_8"),
|
||||||
|
InlineKeyboardButton("9", callback_data="rule_9")
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Rules command =============================================================================================================
|
# Rules command =============================================================================================================
|
||||||
default_rules_markup = InlineKeyboardMarkup(
|
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["rules"], prefixes=["/"]))
|
||||||
[
|
async def cmd_rules(app: Client, msg: Message):
|
||||||
[
|
await msg.reply_text(locale("rules_msg", locale=msg.from_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(msg.from_user).keyboard)
|
||||||
InlineKeyboardButton(locale("rules_home", "button"), callback_data="rules_home"),
|
|
||||||
InlineKeyboardButton(locale("rules_additional", "button"), callback_data="rules_additional")
|
|
||||||
],
|
|
||||||
[
|
|
||||||
InlineKeyboardButton("1", callback_data="rule_1"),
|
|
||||||
InlineKeyboardButton("2", callback_data="rule_2"),
|
|
||||||
InlineKeyboardButton("3", callback_data="rule_3")
|
|
||||||
],
|
|
||||||
[
|
|
||||||
InlineKeyboardButton("4", callback_data="rule_4"),
|
|
||||||
InlineKeyboardButton("5", callback_data="rule_5"),
|
|
||||||
InlineKeyboardButton("6", callback_data="rule_6")
|
|
||||||
],
|
|
||||||
[
|
|
||||||
InlineKeyboardButton("7", callback_data="rule_7"),
|
|
||||||
InlineKeyboardButton("8", callback_data="rule_8"),
|
|
||||||
InlineKeyboardButton("9", callback_data="rule_9")
|
|
||||||
]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
@app.on_message(~ filters.scheduled & filters.private & filters.command(["rules"], prefixes=["/"]))
|
|
||||||
async def cmd_rules(app, msg):
|
|
||||||
await msg.reply_text(locale("rules_msg"), disable_web_page_preview=True, reply_markup=default_rules_markup)
|
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
46
modules/commands/spoiler.py
Normal file
46
modules/commands/spoiler.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
from app import app
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message, ReplyKeyboardMarkup
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from classes.errors.holo_user import UserNotFoundError, UserInvalidError
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
|
from modules.logging import logWrite
|
||||||
|
from modules.utils import locale
|
||||||
|
from modules.database import col_spoilers
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
|
# Spoiler command ==============================================================================================================
|
||||||
|
@app.on_message(custom_filters.member & ~filters.scheduled & filters.private & filters.command(["spoiler"], prefixes=["/"]))
|
||||||
|
async def cmd_spoiler(app: Client, msg: Message):
|
||||||
|
|
||||||
|
try:
|
||||||
|
holo_user = HoloUser(msg.from_user)
|
||||||
|
except (UserInvalidError, UserNotFoundError):
|
||||||
|
return
|
||||||
|
|
||||||
|
if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill":
|
||||||
|
|
||||||
|
if col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} ) is None:
|
||||||
|
|
||||||
|
col_spoilers.insert_one(
|
||||||
|
{
|
||||||
|
"user": msg.from_user.id,
|
||||||
|
"completed": False,
|
||||||
|
"category": None,
|
||||||
|
"description": None,
|
||||||
|
"photo": None,
|
||||||
|
"video": None,
|
||||||
|
"audio": None,
|
||||||
|
"animation": None,
|
||||||
|
"document": None,
|
||||||
|
"caption": None,
|
||||||
|
"text": None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await msg.reply_text(locale("spoiler_started", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_categories", "keyboard"), resize_keyboard=True, one_time_keyboard=True))
|
||||||
|
logWrite(f"User {msg.from_user.id} started creating new spoiler")
|
||||||
|
|
||||||
|
else:
|
||||||
|
await msg.reply_text(locale("spoiler_unfinished", "message", locale=msg.from_user))
|
||||||
|
# ==============================================================================================================================
|
@@ -1,25 +1,23 @@
|
|||||||
from datetime import datetime
|
from app import app
|
||||||
from app import app, isAnAdmin
|
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from modules.utils import should_quote
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
|
from modules import custom_filters
|
||||||
|
from modules.utils import locale, should_quote
|
||||||
from modules.database import col_applications
|
from modules.database import col_applications
|
||||||
|
|
||||||
# Sponsorship command ==========================================================================================================
|
# Sponsorship command ==========================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.command(["sponsorship"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_sponsorships & ~filters.scheduled & filters.command(["sponsorship"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin))
|
||||||
async def cmd_sponsorship(app, msg):
|
async def cmd_sponsorship(app: Client, msg: Message):
|
||||||
if (await isAnAdmin(msg) is True) or (col_applications.find_one({"user": msg.from_user.id}) is not None):
|
holo_user = HoloUser(msg.from_user)
|
||||||
await msg.reply_text("Yes, I exist.", quote=should_quote(msg))
|
if holo_user.application_state()[0] == "fill":
|
||||||
# if not path.exists(f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json"):
|
await msg.reply_text(locale("finish_application", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||||
# jsonSave(jsonLoad(f"{configGet('data', 'locations')}{sep}sponsor_default.json"), f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json")
|
return
|
||||||
# sponsor = jsonLoad(f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json")
|
if holo_user.spoiler_state() is True:
|
||||||
# if sponsor["approved"]:
|
await msg.reply_text(locale("spoiler_in_progress", "message", locale=holo_user))
|
||||||
# if sponsor["expires"] is not None:
|
return
|
||||||
# if datetime.strptime(sponsor["expires"], "%d.%m.%Y") > datetime.now():
|
await msg.reply_text(locale("sponsorship_apply", "message", locale=msg.from_user), reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text=str(locale("sponsor_apply", "button", locale=msg.from_user)), callback_data=f"sponsor_apply_{msg.from_user.id}")]]), quote=should_quote(msg))
|
||||||
# await msg.reply_text(f"You have an active sub til **{sponsor['expires']}**.")
|
|
||||||
# else:
|
|
||||||
# await msg.reply_text(f"Your sub expired {int((datetime.now()-datetime.strptime(sponsor['expires'], '%d.%m.%Y')).days)} days ago.")
|
|
||||||
# elif sponsor["approved"]:
|
|
||||||
# await msg.reply_text(f"Your sub expiration date is not valid.")
|
|
||||||
# else:
|
# else:
|
||||||
# await msg.reply_text(f"You have no active subscription.")
|
# await msg.reply_text(locale("sponsorship_application_empty", "message"))
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,12 +1,16 @@
|
|||||||
from app import app
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.types import ReplyKeyboardMarkup
|
from pyrogram.types import ReplyKeyboardMarkup, Message
|
||||||
|
from pyrogram.client import Client
|
||||||
from modules.utils import locale, logWrite
|
from modules.utils import locale, logWrite
|
||||||
from modules.database import col_users
|
from modules.database import col_users, col_spoilers
|
||||||
|
from modules import custom_filters
|
||||||
|
from bson.objectid import ObjectId
|
||||||
|
from bson.errors import InvalidId
|
||||||
|
|
||||||
# Start command ================================================================================================================
|
# Start command ================================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.private & filters.command(["start"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(["start"], prefixes=["/"]))
|
||||||
async def cmd_start(app, msg):
|
async def cmd_start(app: Client, msg: Message):
|
||||||
|
|
||||||
user = col_users.find_one({"user": msg.from_user.id})
|
user = col_users.find_one({"user": msg.from_user.id})
|
||||||
|
|
||||||
@@ -23,5 +27,23 @@ async def cmd_start(app, msg):
|
|||||||
})
|
})
|
||||||
|
|
||||||
logWrite(f"User {msg.from_user.id} started bot interaction")
|
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))
|
await msg.reply_text(locale("start", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("welcome", "keyboard", locale=msg.from_user), resize_keyboard=True))
|
||||||
|
|
||||||
|
if len(msg.command) > 1:
|
||||||
|
try:
|
||||||
|
spoiler = col_spoilers.find_one( {"_id": ObjectId(msg.command[1])} )
|
||||||
|
if spoiler["photo"] is not None:
|
||||||
|
await msg.reply_cached_media(spoiler["photo"], caption=spoiler["caption"])
|
||||||
|
if spoiler["video"] is not None:
|
||||||
|
await msg.reply_cached_media(spoiler["video"], caption=spoiler["caption"])
|
||||||
|
if spoiler["audio"] is not None:
|
||||||
|
await msg.reply_cached_media(spoiler["audio"], caption=spoiler["caption"])
|
||||||
|
if spoiler["animation"] is not None:
|
||||||
|
await msg.reply_cached_media(spoiler["animation"], caption=spoiler["caption"])
|
||||||
|
if spoiler["document"] is not None:
|
||||||
|
await msg.reply_cached_media(spoiler["document"], caption=spoiler["caption"])
|
||||||
|
if spoiler["text"] is not None:
|
||||||
|
await msg.reply_text(spoiler["text"])
|
||||||
|
except InvalidId:
|
||||||
|
await msg.reply_text(f"Got an invalid ID {msg.command[1]}")
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,20 +1,22 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from app import app, isAnAdmin
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
from modules.utils import configGet, locale
|
from modules.utils import configGet, locale
|
||||||
from modules.database import col_warnings
|
from modules.database import col_warnings
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Warn command =================================================================================================================
|
# Warn command =================================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.command(["warn"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_warnings & ~filters.scheduled & filters.command(["warn"], prefixes=["/"]) & custom_filters.admin)
|
||||||
async def cmd_warn(app, msg):
|
async def cmd_warn(app: Client, msg: Message):
|
||||||
|
|
||||||
if msg.chat.id == configGet("destination_group"):
|
if msg.chat.id == configGet("users", "groups"):
|
||||||
if msg.reply_to_message_id != None:
|
if msg.reply_to_message_id != None:
|
||||||
if await isAnAdmin(msg.from_user.id) is True:
|
message = " ".join(msg.command[1:]) if len(msg.command) > 1 else ""
|
||||||
message = " ".join(msg.command[1:]) if len(msg.command) > 1 else ""
|
col_warnings.insert_one({"user": msg.reply_to_message.from_user.id, "admin": msg.from_user.id, "date": datetime.now(), "reason": message})
|
||||||
col_warnings.insert_one({"user": msg.reply_to_message.from_user.id, "admin": msg.from_user.id, "date": datetime.now(), "reason": message})
|
if message == "":
|
||||||
if message == "":
|
await msg.reply_text(locale("warned", "message").format(msg.reply_to_message.from_user.first_name, msg.reply_to_message.from_user.id))
|
||||||
await msg.reply_text(locale("warned", "message").format(msg.reply_to_message.from_user.first_name, msg.reply_to_message.from_user.id))
|
else:
|
||||||
else:
|
await msg.reply_text(locale("warned_reason", "message").format(msg.reply_to_message.from_user.first_name, msg.reply_to_message.from_user.id, message))
|
||||||
await msg.reply_text(locale("warned_reason", "message").format(msg.reply_to_message.from_user.first_name, msg.reply_to_message.from_user.id, message))
|
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,42 +1,44 @@
|
|||||||
from app import app, isAnAdmin
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
from pyrogram.enums.chat_members_filter import ChatMembersFilter
|
from pyrogram.enums.chat_members_filter import ChatMembersFilter
|
||||||
from modules.utils import configGet, locale, should_quote
|
from modules.utils import configGet, locale, should_quote
|
||||||
from modules.database import col_users, col_warnings
|
from modules.database import col_users, col_warnings
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Warnings command =============================================================================================================
|
# Warnings command =============================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.command(["warnings"], prefixes=["/"]))
|
@app.on_message(custom_filters.enabled_warnings & ~filters.scheduled & filters.command(["warnings"], prefixes=["/"]) & custom_filters.admin)
|
||||||
async def cmd_warnings(app, msg):
|
async def cmd_warnings(app: Client, msg: Message):
|
||||||
|
|
||||||
if await isAnAdmin(msg.from_user.id) is True:
|
if len(msg.command) <= 1:
|
||||||
|
await msg.reply_text(locale("syntax_warnings", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||||
|
return
|
||||||
|
|
||||||
if len(msg.command) <= 1:
|
try:
|
||||||
await msg.reply_text(locale("syntax_warnings", "message"), quote=should_quote(msg))
|
user_db = col_users.find_one({"user": int(msg.command[1])})
|
||||||
|
target_id = user_db["user"]
|
||||||
|
target_name = user_db["tg_name"]
|
||||||
|
except:
|
||||||
|
list_of_users = []
|
||||||
|
async for m in app.get_chat_members(configGet("users", "groups"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]):
|
||||||
|
list_of_users.append(m)
|
||||||
|
|
||||||
try:
|
if len(list_of_users) != 0:
|
||||||
user_db = col_users.find_one({"user": int(msg.command[1])})
|
target = list_of_users[0].user
|
||||||
target_id = user_db["user"]
|
target_name = target.first_name
|
||||||
target_name = user_db["tg_name"]
|
target_id = str(target.id)
|
||||||
except:
|
|
||||||
list_of_users = []
|
|
||||||
async for m in app.get_chat_members(configGet("destination_group"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]):
|
|
||||||
list_of_users.append(m)
|
|
||||||
|
|
||||||
if len(list_of_users) != 0:
|
|
||||||
target = list_of_users[0].user
|
|
||||||
target_name = target.first_name
|
|
||||||
target_id = str(target.id)
|
|
||||||
else:
|
|
||||||
await msg.reply_text(locale("no_user_warnings", "message").format(msg.command[1]))
|
|
||||||
return
|
|
||||||
|
|
||||||
warns = len(list(col_warnings.find({"user": target_id})))
|
|
||||||
|
|
||||||
if warns == 0:
|
|
||||||
await msg.reply_text(locale("no_warnings", "message").format(target_name, target_id), quote=should_quote(msg))
|
|
||||||
else:
|
else:
|
||||||
if warns <= 5:
|
await msg.reply_text(locale("no_user_warnings", "message", locale=msg.from_user).format(msg.command[1]))
|
||||||
await msg.reply_text(locale("warnings_1", "message").format(target_name, target_id, warns), quote=should_quote(msg))
|
return
|
||||||
else:
|
|
||||||
await msg.reply_text(locale("warnings_2", "message").format(target_name, target_id, warns), quote=should_quote(msg))
|
warns = len(list(col_warnings.find({"user": target_id})))
|
||||||
|
|
||||||
|
if warns == 0:
|
||||||
|
await msg.reply_text(locale("no_warnings", "message", locale=msg.from_user).format(target_name, target_id), quote=should_quote(msg))
|
||||||
|
else:
|
||||||
|
if warns <= 5:
|
||||||
|
await msg.reply_text(locale("warnings_1", "message", locale=msg.from_user).format(target_name, target_id, warns), quote=should_quote(msg))
|
||||||
|
else:
|
||||||
|
await msg.reply_text(locale("warnings_2", "message", locale=msg.from_user).format(target_name, target_id, warns), quote=should_quote(msg))
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,49 +0,0 @@
|
|||||||
from modules.logging import logWrite
|
|
||||||
from modules.utils import configGet
|
|
||||||
from pyrogram.types import BotCommand, BotCommandScopeChat
|
|
||||||
from pyrogram.errors import bad_request_400
|
|
||||||
|
|
||||||
def commands_register(app):
|
|
||||||
|
|
||||||
# Registering user commands
|
|
||||||
commands_list = []
|
|
||||||
for command in configGet("commands"):
|
|
||||||
commands_list.append(BotCommand(command, configGet("commands")[command]))
|
|
||||||
app.set_bot_commands(commands_list)
|
|
||||||
|
|
||||||
# Registering admin commands
|
|
||||||
commands_admin_list = []
|
|
||||||
for command in configGet("commands"):
|
|
||||||
commands_admin_list.append(BotCommand(command, configGet("commands")[command]))
|
|
||||||
|
|
||||||
for command in configGet("commands_admin"):
|
|
||||||
commands_admin_list.append(BotCommand(command, configGet("commands_admin")[command]))
|
|
||||||
|
|
||||||
for admin in configGet("admins"):
|
|
||||||
try:
|
|
||||||
app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=admin))
|
|
||||||
except bad_request_400.PeerIdInvalid:
|
|
||||||
pass
|
|
||||||
|
|
||||||
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]))
|
|
||||||
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]))
|
|
||||||
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.")
|
|
56
modules/custom_filters.py
Normal file
56
modules/custom_filters.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
"""Custom message filters made to improve commands
|
||||||
|
usage in context of Holo Users."""
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
from app import isAnAdmin
|
||||||
|
from modules.utils import configGet, jsonLoad
|
||||||
|
from modules.database import col_applications, col_tmp
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message
|
||||||
|
|
||||||
|
async def admin_func(_, __, msg: Message):
|
||||||
|
return await isAnAdmin(msg.from_user.id)
|
||||||
|
|
||||||
|
async def member_func(_, __, msg: Message):
|
||||||
|
return True if (msg.from_user.id in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))) else False
|
||||||
|
|
||||||
|
async def allowed_func(_, __, msg: Message):
|
||||||
|
output = False
|
||||||
|
output = True if (col_applications.find_one({"user": msg.from_user.id}) is not None) else False
|
||||||
|
if path.exists(path.join(configGet("cache", "locations"), "group_members")) and (msg.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))):
|
||||||
|
output = False
|
||||||
|
return output
|
||||||
|
|
||||||
|
async def enabled_general_func(_, __, msg: Message):
|
||||||
|
return configGet("enabled", "features", "general")
|
||||||
|
|
||||||
|
async def enabled_applications_func(_, __, msg: Message):
|
||||||
|
return configGet("enabled", "features", "applications")
|
||||||
|
|
||||||
|
async def enabled_sponsorships_func(_, __, msg: Message):
|
||||||
|
return configGet("enabled", "features", "sponsorships")
|
||||||
|
|
||||||
|
async def enabled_warnings_func(_, __, msg: Message):
|
||||||
|
return configGet("enabled", "features", "warnings")
|
||||||
|
|
||||||
|
async def enabled_invites_check_func(_, __, msg: Message):
|
||||||
|
return configGet("enabled", "features", "invites_check")
|
||||||
|
|
||||||
|
async def enabled_dinovoice_func(_, __, msg: Message):
|
||||||
|
return configGet("enabled", "features", "dinovoice")
|
||||||
|
|
||||||
|
async def filling_sponsorship_func(_, __, msg: Message):
|
||||||
|
return True if col_tmp.find_one({"user": msg.from_user.id, "type": "sponsorship"}) is not None else False
|
||||||
|
|
||||||
|
admin = filters.create(admin_func)
|
||||||
|
member = filters.create(member_func)
|
||||||
|
allowed = filters.create(allowed_func)
|
||||||
|
|
||||||
|
enabled_general = filters.create(enabled_general_func)
|
||||||
|
enabled_applications = filters.create(enabled_applications_func)
|
||||||
|
enabled_sponsorships = filters.create(enabled_sponsorships_func)
|
||||||
|
enabled_warnings = filters.create(enabled_warnings_func)
|
||||||
|
enabled_invites_check = filters.create(enabled_invites_check_func)
|
||||||
|
enabled_dinovoice = filters.create(enabled_dinovoice_func)
|
||||||
|
|
||||||
|
filling_sponsorship = filters.create(filling_sponsorship_func)
|
@@ -1,4 +1,7 @@
|
|||||||
from pymongo import MongoClient
|
"""Module that provides all database columns and
|
||||||
|
creates geospatial index for col_applications"""
|
||||||
|
|
||||||
|
from pymongo import MongoClient, GEOSPHERE
|
||||||
from ujson import loads
|
from ujson import loads
|
||||||
|
|
||||||
with open("config.json", "r", encoding="utf-8") as f:
|
with open("config.json", "r", encoding="utf-8") as f:
|
||||||
@@ -25,14 +28,17 @@ db = db_client.get_database(name=db_config["name"])
|
|||||||
|
|
||||||
collections = db.list_collection_names()
|
collections = db.list_collection_names()
|
||||||
|
|
||||||
for collection in ["tmp", "users", "context", "messages", "warnings", "applications", "sponsorships"]:
|
for collection in ["tmp", "users", "context", "spoilers", "messages", "warnings", "applications", "sponsorships"]:
|
||||||
if not collection in collections:
|
if not collection in collections:
|
||||||
db.create_collection(collection)
|
db.create_collection(collection)
|
||||||
|
|
||||||
col_tmp = db.get_collection("tmp")
|
col_tmp = db.get_collection("tmp")
|
||||||
col_users = db.get_collection("users")
|
col_users = db.get_collection("users")
|
||||||
col_context = db.get_collection("context")
|
col_context = db.get_collection("context")
|
||||||
|
col_spoilers = db.get_collection("spoilers")
|
||||||
col_messages = db.get_collection("messages")
|
col_messages = db.get_collection("messages")
|
||||||
col_warnings = db.get_collection("warnings")
|
col_warnings = db.get_collection("warnings")
|
||||||
col_applications = db.get_collection("applications")
|
col_applications = db.get_collection("applications")
|
||||||
col_sponsorships = db.get_collection("sponsorships")
|
col_sponsorships = db.get_collection("sponsorships")
|
||||||
|
|
||||||
|
col_applications.create_index([("application.3.location", GEOSPHERE)])
|
@@ -1,93 +1,169 @@
|
|||||||
|
from typing import Literal
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from app import app
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.types import ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton
|
from pyrogram.types import ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton, ForceReply, Message
|
||||||
|
from pyrogram.client import Client
|
||||||
from pyrogram.enums.parse_mode import ParseMode
|
from pyrogram.enums.parse_mode import ParseMode
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import configGet, locale, logWrite
|
from modules.utils import all_locales, configGet, locale, logWrite
|
||||||
from modules.handlers.welcome import welcome_pass
|
from modules.handlers.welcome import welcome_pass
|
||||||
from modules.database import col_tmp
|
from modules.database import col_tmp, col_applications
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Confirmation =================================================================================================================
|
# Confirmation =================================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.private & (filters.regex(locale("confirm", "keyboard")[0][0])))
|
confirmation_1 = []
|
||||||
async def confirm_yes(app, msg):
|
for pattern in all_locales("confirm", "keyboard"):
|
||||||
|
confirmation_1.append(pattern[0][0])
|
||||||
|
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.private & filters.command(confirmation_1, prefixes=[""]))
|
||||||
|
async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "sponsorship", "unknown"] = "unknown"):
|
||||||
|
|
||||||
holo_user = HoloUser(msg.from_user)
|
holo_user = HoloUser(msg.from_user)
|
||||||
|
|
||||||
if (holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True):
|
if configGet("enabled", "features", "applications") is True:
|
||||||
|
|
||||||
await msg.reply_text(locale("application_sent", "message"), reply_markup=ReplyKeyboardRemove())
|
if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)):
|
||||||
|
|
||||||
tmp_application = col_tmp.find_one({"user": holo_user.id, "type": "application"})
|
tmp_application = col_tmp.find_one({"user": holo_user.id, "type": "application"})
|
||||||
|
|
||||||
|
if tmp_application is None:
|
||||||
|
logWrite(f"Application of {holo_user.id} is nowhere to be found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if tmp_application["sent"] is True:
|
||||||
|
return
|
||||||
|
|
||||||
|
await msg.reply_text(locale("application_sent", "message"), reply_markup=ReplyKeyboardRemove())
|
||||||
|
|
||||||
|
application_content = []
|
||||||
|
i = 1
|
||||||
|
|
||||||
|
for question in tmp_application['application']:
|
||||||
|
|
||||||
|
if i == 2:
|
||||||
|
age = relativedelta(datetime.now(), tmp_application['application']['2'])
|
||||||
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
||||||
|
elif i == 3:
|
||||||
|
if tmp_application['application']['3']['countryCode'] == "UA":
|
||||||
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['3']['name']}")
|
||||||
|
else:
|
||||||
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['3']['name']} ({tmp_application['application']['3']['adminName1']}, {tmp_application['application']['3']['countryName']})")
|
||||||
|
else:
|
||||||
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application'][question]}")
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if tmp_application["reapply"] is True and col_applications.find_one({"user": holo_user.id}) is not None:
|
||||||
|
await app.send_message(
|
||||||
|
chat_id=configGet("admin", "groups"),
|
||||||
|
text=(locale("reapply_got", "message")).format(str(holo_user.id),msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)),
|
||||||
|
parse_mode=ParseMode.MARKDOWN,
|
||||||
|
reply_markup=InlineKeyboardMarkup(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(text=str(locale("reapply_yes", "button")), callback_data=f"reapply_yes_{holo_user.id}")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(text=str(locale("reapply_no", "button")), callback_data=f"reapply_no_{holo_user.id}")
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await app.send_message(
|
||||||
|
chat_id=configGet("admin", "groups"),
|
||||||
|
text=(locale("application_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)),
|
||||||
|
parse_mode=ParseMode.MARKDOWN,
|
||||||
|
reply_markup=InlineKeyboardMarkup(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(text=str(locale("sub_no", "button")), callback_data=f"sub_no_{holo_user.id}")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(text=str(locale("sub_aggressive", "button")), callback_data=f"sub_aggressive_{holo_user.id}")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(text=str(locale("sub_russian", "button")), callback_data=f"sub_russian_{holo_user.id}")
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
logWrite(f"User {holo_user.id} sent his application and it will now be reviewed")
|
||||||
|
|
||||||
|
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"sent": True}})
|
||||||
|
|
||||||
if tmp_application is None:
|
|
||||||
logWrite(f"Application of {holo_user.id} is nowhere to be found.")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
application_content = []
|
if configGet("enabled", "features", "sponsorships") is True:
|
||||||
i = 1
|
|
||||||
|
|
||||||
for question in tmp_application['application']:
|
if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)):
|
||||||
|
|
||||||
if i == 2:
|
tmp_sponsorship = col_tmp.find_one({"user": holo_user.id, "type": "sponsorship"})
|
||||||
age = relativedelta(datetime.now(), tmp_application['application']['2'])
|
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
if tmp_sponsorship is None:
|
||||||
elif i == 3:
|
logWrite(f"Sponsorship of {holo_user.id} is nowhere to be found.")
|
||||||
if tmp_application['application']['3']['countryCode'] == "UA":
|
return
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['3']['name']}")
|
|
||||||
|
if tmp_sponsorship["sent"] is True:
|
||||||
|
return
|
||||||
|
|
||||||
|
await msg.reply_text(locale("sponsorship_sent", "message"), reply_markup=ReplyKeyboardRemove())
|
||||||
|
|
||||||
|
sponsorship_content = []
|
||||||
|
|
||||||
|
for question in tmp_sponsorship['sponsorship']:
|
||||||
|
|
||||||
|
if question == "expires":
|
||||||
|
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question].strftime('%d.%m.%Y')}")
|
||||||
|
elif question == "proof":
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['3']['name']} ({tmp_application['application']['3']['adminName1']}, {tmp_application['application']['3']['countryName']})")
|
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}")
|
||||||
else:
|
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application'][question]}")
|
|
||||||
|
|
||||||
i += 1
|
await app.send_cached_media(configGet("admin", "groups"), tmp_sponsorship["sponsorship"]["proof"], caption=(locale("sponsor_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(sponsorship_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
|
||||||
|
|
||||||
if tmp_application["reapply"]:
|
|
||||||
await app.send_message(chat_id=configGet("admin_group"), text=(locale("reapply_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.last_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
|
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
InlineKeyboardButton(text=str(locale("reapply_yes", "button")), callback_data=f"reapply_yes_{holo_user.id}")
|
InlineKeyboardButton(text=str(locale("sponsor_yes", "button")), callback_data=f"sponsor_yes_{holo_user.id}")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
InlineKeyboardButton(text=str(locale("reapply_no", "button")), callback_data=f"reapply_no_{holo_user.id}")
|
InlineKeyboardButton(text=str(locale("sponsor_no", "button")), callback_data=f"sponsor_no_{holo_user.id}")
|
||||||
]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await app.send_message(chat_id=configGet("admin_group"), text=(locale("application_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.last_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
|
|
||||||
[
|
|
||||||
[
|
|
||||||
InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}")
|
|
||||||
],
|
|
||||||
[
|
|
||||||
InlineKeyboardButton(text=str(locale("sub_no", "button")), callback_data=f"sub_no_{holo_user.id}")
|
|
||||||
],
|
|
||||||
[
|
|
||||||
InlineKeyboardButton(text=str(locale("sub_aggressive", "button")), callback_data=f"sub_aggressive_{holo_user.id}")
|
|
||||||
],
|
|
||||||
[
|
|
||||||
InlineKeyboardButton(text=str(locale("sub_russian", "button")), callback_data=f"sub_russian_{holo_user.id}")
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
logWrite(f"User {holo_user.id} sent his application and it will now be reviewed")
|
# remove(f"tmp{sep}{filename}.jpg")
|
||||||
|
|
||||||
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"sent": True}})
|
logWrite(f"User {holo_user.id} sent his sponsorship application and it will now be reviewed")
|
||||||
|
|
||||||
# configSet(["sent"], True, file=str(holo_user.id))
|
col_tmp.update_one({"user": holo_user.id, "type": "sponsorship"}, {"$set": {"sent": True}})
|
||||||
# configSet(["confirmed"], True, file=str(holo_user.id))
|
|
||||||
|
|
||||||
@app.on_message(~ filters.scheduled & filters.private & (filters.regex(locale("confirm", "keyboard")[1][0])))
|
return
|
||||||
async def confirm_no(app, msg):
|
|
||||||
|
confirmation_2 = []
|
||||||
|
for pattern in all_locales("confirm", "keyboard"):
|
||||||
|
confirmation_2.append(pattern[1][0])
|
||||||
|
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.private & filters.command(confirmation_2, prefixes=[""]))
|
||||||
|
async def confirm_no(app: Client, msg: Message, kind: Literal["application", "sponsorship", "unknown"] = "unknown"):
|
||||||
|
|
||||||
holo_user = HoloUser(msg.from_user)
|
holo_user = HoloUser(msg.from_user)
|
||||||
|
|
||||||
if (holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True):
|
if configGet("enabled", "features", "applications") is True:
|
||||||
holo_user.application_restart()
|
if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)):
|
||||||
await welcome_pass(app, msg, once_again=True)
|
holo_user.application_restart()
|
||||||
logWrite(f"User {msg.from_user.id} restarted the application due to typo in it")
|
await welcome_pass(app, msg, once_again=True)
|
||||||
|
logWrite(f"User {msg.from_user.id} restarted the application due to typo in it")
|
||||||
|
return
|
||||||
|
|
||||||
|
if configGet("enabled", "features", "sponsorships") is True:
|
||||||
|
if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)):
|
||||||
|
holo_user.sponsorship_restart()
|
||||||
|
await app.send_message(holo_user.id, locale(f"sponsor1", "message", locale=holo_user.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale))))
|
||||||
|
logWrite(f"User {msg.from_user.id} restarted the sponsorship application due to typo in it")
|
||||||
|
return
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,53 +1,54 @@
|
|||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from app import app, isAnAdmin
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
from modules.utils import locale, logWrite
|
from modules.utils import locale, logWrite
|
||||||
from modules.database import col_applications
|
from modules.database import col_applications
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Contact getting ==============================================================================================================
|
# Contact getting ==============================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.contact & filters.private)
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.contact & filters.private & (custom_filters.allowed | custom_filters.admin))
|
||||||
async def get_contact(app, msg):
|
async def get_contact(app: Client, msg: Message):
|
||||||
|
|
||||||
holo_user = HoloUser(msg.from_user)
|
holo_user = HoloUser(msg.from_user)
|
||||||
|
|
||||||
if holo_user.application_approved() or (await isAnAdmin(holo_user.id) is True):
|
if msg.contact.user_id != None:
|
||||||
|
|
||||||
if msg.contact.user_id != None:
|
application = col_applications.find_one({"user": msg.contact.user_id})
|
||||||
|
|
||||||
application = col_applications.find_one({"user": msg.contact.user_id})
|
if application is None:
|
||||||
|
logWrite(f"User {holo_user.id} requested application of {msg.contact.user_id} but user does not exists")
|
||||||
|
await msg.reply_text(locale("contact_invalid", "message", locale=holo_user.locale))
|
||||||
|
return
|
||||||
|
|
||||||
if application is None:
|
application_content = []
|
||||||
logWrite(f"User {holo_user.id} requested application of {msg.contact.user_id} but user does not exists")
|
i = 1
|
||||||
await msg.reply_text(locale("contact_invalid", "message"))
|
|
||||||
return
|
|
||||||
|
|
||||||
application_content = []
|
for question in application['application']:
|
||||||
i = 1
|
|
||||||
|
|
||||||
for question in application['application']:
|
if i == 2:
|
||||||
|
age = relativedelta(datetime.now(), application['application']['2'])
|
||||||
if i == 2:
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
||||||
age = relativedelta(datetime.now(), application['application']['2'])
|
elif i == 3:
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
if application['application']['3']['countryCode'] == "UA":
|
||||||
elif i == 3:
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['3']['name']}")
|
||||||
if application['application']['3']['countryCode'] == "UA":
|
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']}")
|
|
||||||
else:
|
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
|
|
||||||
else:
|
else:
|
||||||
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application'][question]}")
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
|
||||||
|
else:
|
||||||
i += 1
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application'][question]}")
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
application_status = locale("application_status_accepted", "message").format((await app.get_users(application["admin"])).first_name, application["date"].strftime("%d.%m.%Y, %H:%M"))
|
application_status = locale("application_status_accepted", "message", locale=holo_user.locale).format((await app.get_users(application["admin"])).first_name, application["date"].strftime("%d.%m.%Y, %H:%M"))
|
||||||
|
|
||||||
logWrite(f"User {holo_user.id} requested application of {msg.contact.user_id}")
|
logWrite(f"User {holo_user.id} requested application of {msg.contact.user_id}")
|
||||||
await msg.reply_text(locale("contact", "message").format(str(msg.contact.user_id), "\n".join(application_content), application_status))
|
await msg.reply_text(locale("contact", "message", locale=holo_user.locale).format(str(msg.contact.user_id), "\n".join(application_content), application_status))
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logWrite(f"User {holo_user.id} requested application of someone but user is not telegram user")
|
logWrite(f"User {holo_user.id} requested application of someone but user is not telegram user")
|
||||||
await msg.reply_text(locale("contact_not_member", "message"))
|
await msg.reply_text(locale("contact_not_member", "message", locale=holo_user.locale))
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,10 +1,13 @@
|
|||||||
|
from traceback import print_exc
|
||||||
from app import app, isAnAdmin
|
from app import app, isAnAdmin
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from ftfy import fix_text
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.types import Message
|
from pyrogram.types import Message, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
from pyrogram.client import Client
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import configGet, logWrite
|
from modules.utils import configGet, logWrite, locale, all_locales
|
||||||
from modules.database import col_messages
|
from modules.database import col_messages, col_spoilers
|
||||||
|
|
||||||
async def message_involved(msg: Message) -> bool:
|
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})
|
message = col_messages.find_one({"destination.id": msg.reply_to_message.id, "destination.chat": msg.reply_to_message.chat.id})
|
||||||
@@ -20,7 +23,7 @@ async def message_context(msg: Message) -> tuple:
|
|||||||
|
|
||||||
# Any other input ==============================================================================================================
|
# Any other input ==============================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.private)
|
@app.on_message(~ filters.scheduled & filters.private)
|
||||||
async def any_stage(app, msg):
|
async def any_stage(app: Client, msg: Message):
|
||||||
|
|
||||||
if msg.via_bot is None:
|
if msg.via_bot is None:
|
||||||
|
|
||||||
@@ -41,79 +44,125 @@ async def any_stage(app, msg):
|
|||||||
photo=msg.photo,
|
photo=msg.photo,
|
||||||
video=msg.video,
|
video=msg.video,
|
||||||
file=msg.document,
|
file=msg.document,
|
||||||
|
animation=msg.animation,
|
||||||
|
voice=msg.voice,
|
||||||
adm_origin=await isAnAdmin(context_message.from_user.id),
|
adm_origin=await isAnAdmin(context_message.from_user.id),
|
||||||
adm_context=await isAnAdmin(msg.from_user.id)
|
adm_context=await isAnAdmin(msg.from_user.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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
|
return
|
||||||
|
|
||||||
await holo_user.application_next(msg.text, msg=msg)
|
if msg.text is not None:
|
||||||
|
|
||||||
# user_stage = configGet("stage", file=str(msg.from_user.id))
|
if configGet("enabled", "features", "applications") is True:
|
||||||
|
await holo_user.application_next(msg.text, msg=msg)
|
||||||
|
|
||||||
|
if configGet("enabled", "features", "sponsorships") is True:
|
||||||
|
|
||||||
|
await holo_user.sponsorship_next(msg.text, msg)
|
||||||
|
|
||||||
|
if msg.photo is not None:
|
||||||
|
await holo_user.sponsorship_next(msg.text, msg=msg, photo=msg.photo)
|
||||||
|
|
||||||
# if user_stage == 1:
|
if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill":
|
||||||
# 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:
|
spoiler = col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} )
|
||||||
|
|
||||||
# try:
|
if spoiler is None:
|
||||||
|
return
|
||||||
|
|
||||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
if spoiler["category"] is None:
|
||||||
|
|
||||||
# input_dt = datetime.strptime(msg.text, "%d.%m.%Y")
|
found = False
|
||||||
|
|
||||||
# if datetime.now() <= input_dt:
|
# Find category in all locales
|
||||||
# logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to joking")
|
for lc in all_locales("spoiler_categories", "message"):
|
||||||
# await msg.reply_text(locale("question2_joke", "message"), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
for key in lc:
|
||||||
|
if lc[key] == msg.text:
|
||||||
|
found = True
|
||||||
|
category = key
|
||||||
|
|
||||||
# elif ((datetime.now() - input_dt).days) < ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days):
|
if found is False:
|
||||||
# logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to being underage")
|
await msg.reply_text(locale("spoiler_incorrect_category", "message", locale=msg.from_user))
|
||||||
# await msg.reply_text(locale("question2_underage", "message").format(str(configGet("age_allowed"))), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
return
|
||||||
|
|
||||||
# else:
|
col_spoilers.find_one_and_update( {"_id": spoiler["_id"]}, {"$set": {"category": category}} )
|
||||||
# logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||||
# await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
return
|
||||||
# configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
|
||||||
|
|
||||||
# except ValueError:
|
if spoiler["description"] is None and (spoiler["photo"] is None and spoiler["video"] is None and spoiler["audio"] is None and spoiler["animation"] is None and spoiler["text"] is None):
|
||||||
# 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"))))
|
# for lc in all_locales("spoiler_description", "keyboard"):
|
||||||
|
# if msg.text == lc[-1][0]:
|
||||||
|
# await msg.reply_text(locale("spoiler_description_enter", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||||
|
# return
|
||||||
|
|
||||||
|
|
||||||
|
if msg.text != "-":
|
||||||
|
msg.text = fix_text(msg.text)
|
||||||
|
if len(msg.text) > 1024:
|
||||||
|
await msg.reply_text(locale("spoiler_description_too_long", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||||
|
return
|
||||||
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text}} )
|
||||||
|
else:
|
||||||
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": ""}} )
|
||||||
|
|
||||||
|
logWrite(f"Adding description '{msg.text}' to {msg.from_user.id}'s spoiler")
|
||||||
|
await msg.reply_text(locale("spoiler_using_description", "message", locale=msg.from_user).format(msg.text), reply_markup=ForceReply(placeholder=locale("spoiler_content", "force_reply", locale=msg.from_user)))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
ready = False
|
||||||
|
|
||||||
|
if msg.photo is not None:
|
||||||
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"photo": msg.photo.file_id, "caption": msg.caption, "completed": True}} )
|
||||||
|
logWrite(f"Adding photo with id {msg.photo.file_id} to {msg.from_user.id}'s spoiler")
|
||||||
|
ready = True
|
||||||
|
|
||||||
|
if msg.video is not None:
|
||||||
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"video": msg.video.file_id, "caption": msg.caption, "completed": True}} )
|
||||||
|
logWrite(f"Adding audio with id {msg.video.file_id} to {msg.from_user.id}'s spoiler")
|
||||||
|
ready = True
|
||||||
|
|
||||||
|
if msg.audio is not None:
|
||||||
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"audio": msg.audio.file_id, "caption": msg.caption, "completed": True}} )
|
||||||
|
logWrite(f"Adding video with id {msg.audio.file_id} to {msg.from_user.id}'s spoiler")
|
||||||
|
ready = True
|
||||||
|
|
||||||
|
if msg.animation is not None:
|
||||||
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"animation": msg.animation.file_id, "caption": msg.caption, "completed": True}} )
|
||||||
|
logWrite(f"Adding animation with id {msg.animation.file_id} to {msg.from_user.id}'s spoiler")
|
||||||
|
ready = True
|
||||||
|
|
||||||
|
if msg.document is not None:
|
||||||
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"document": msg.document.file_id, "caption": msg.caption, "completed": True}} )
|
||||||
|
logWrite(f"Adding document with id {msg.document.file_id} to {msg.from_user.id}'s spoiler")
|
||||||
|
ready = True
|
||||||
|
|
||||||
|
if spoiler["photo"] is None and spoiler["video"] is None and spoiler["audio"] is None and spoiler["animation"] is None and spoiler["document"] is None and spoiler["text"] is None:
|
||||||
|
if msg.text is not None:
|
||||||
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"text": msg.text, "completed": True}} )
|
||||||
|
logWrite(f"Adding text '{msg.text}' to {msg.from_user.id}'s spoiler")
|
||||||
|
ready = True
|
||||||
|
|
||||||
|
if ready is True:
|
||||||
|
await msg.reply_text(locale("spoiler_ready", "message", locale=msg.from_user), reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_send", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")]]))
|
||||||
|
else:
|
||||||
|
await msg.reply_text(locale("spoiler_incorrect_content", "message", locale=msg.from_user))
|
||||||
|
|
||||||
# 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("rejected", 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("rejected", file=str(msg.from_user.id)):
|
|
||||||
# await msg.reply_text(locale("already_sent", "message"))
|
|
||||||
|
|
||||||
@app.on_message(~ filters.scheduled & filters.group)
|
@app.on_message(~ filters.scheduled & filters.group)
|
||||||
async def message_in_group(app, msg):
|
async def message_in_group(app: Client, msg: Message):
|
||||||
if (msg.chat is not None) and (msg.via_bot is not None):
|
if (msg.chat is not None) and (msg.via_bot is not None):
|
||||||
if (msg.via_bot.id == configGet("bot_id")) and (msg.chat.id == configGet("destination_group")):
|
if (msg.via_bot.id == (await app.get_me()).id) and (msg.chat.id == configGet("users", "groups")):
|
||||||
|
if msg.text.startswith(locale("spoiler_described", "message").split()[0]) or msg.text.startswith(locale("spoiler_empty", "message").split()[0]):
|
||||||
|
logWrite(f"User {msg.from_user.id} sent spoiler to user's group")
|
||||||
|
try:
|
||||||
|
logWrite("Forwarding spoiler to admin's group")
|
||||||
|
await msg.copy(configGet("admin", "groups"), disable_notification=True)
|
||||||
|
except Exception as exp:
|
||||||
|
logWrite(f"Could not forward spoiler to admin's group due to '{exp}': {print_exc()}")
|
||||||
|
return
|
||||||
if configGet("remove_application_time") > 0:
|
if configGet("remove_application_time") > 0:
|
||||||
logWrite(f"User {msg.from_user.id} requested application in destination group, removing in {configGet('remove_application_time')} minutes")
|
logWrite(f"User {msg.from_user.id} requested application in destination group, removing in {configGet('remove_application_time')} minutes")
|
||||||
await asyncio.sleep(configGet("remove_application_time")*60)
|
await asyncio.sleep(configGet("remove_application_time")*60)
|
||||||
|
@@ -1,13 +1,15 @@
|
|||||||
from app import app, isAnAdmin
|
from app import app, isAnAdmin
|
||||||
from pyrogram.types import ChatPermissions, InlineKeyboardMarkup, InlineKeyboardButton
|
from pyrogram.types import ChatPermissions, InlineKeyboardMarkup, InlineKeyboardButton, ChatMemberUpdated
|
||||||
|
from pyrogram.client import Client
|
||||||
from modules.utils import configGet, locale
|
from modules.utils import configGet, locale
|
||||||
from modules.logging import logWrite
|
from modules.logging import logWrite
|
||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Filter users on join =========================================================================================================
|
# Filter users on join =========================================================================================================
|
||||||
@app.on_chat_member_updated(group=configGet("destination_group"))
|
@app.on_chat_member_updated(custom_filters.enabled_invites_check, group=configGet("users", "groups"))
|
||||||
#@app.on_message(filters.new_chat_members, group=configGet("destination_group"))
|
#@app.on_message(filters.new_chat_members, group=configGet("users", "groups"))
|
||||||
async def filter_join(app, member):
|
async def filter_join(app: Client, member: ChatMemberUpdated):
|
||||||
|
|
||||||
if member.invite_link != None:
|
if member.invite_link != None:
|
||||||
|
|
||||||
@@ -23,7 +25,7 @@ async def filter_join(app, member):
|
|||||||
|
|
||||||
logWrite(f"User {holo_user.id} joined destination group with stolen/unapproved link {holo_user.link}")
|
logWrite(f"User {holo_user.id} joined destination group with stolen/unapproved link {holo_user.link}")
|
||||||
|
|
||||||
await app.send_message(configGet("admin_group"), locale("joined_false_link", "message").format(member.from_user.first_name, member.from_user.id), reply_markup=InlineKeyboardMarkup(
|
await app.send_message(configGet("admin", "groups"), locale("joined_false_link", "message").format(member.from_user.first_name, member.from_user.id), reply_markup=InlineKeyboardMarkup(
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
InlineKeyboardButton(text=str(locale("sus_allow", "button")), callback_data=f"sus_allow_{member.from_user.id}")
|
InlineKeyboardButton(text=str(locale("sus_allow", "button")), callback_data=f"sus_allow_{member.from_user.id}")
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
from app import app
|
|
13
modules/handlers/voice.py
Normal file
13
modules/handlers/voice.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from random import choice
|
||||||
|
from app import app
|
||||||
|
from pyrogram import filters
|
||||||
|
from pyrogram.types import Message
|
||||||
|
from pyrogram.client import Client
|
||||||
|
from modules.logging import logWrite
|
||||||
|
from modules.utils import configGet, locale
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
|
@app.on_message(custom_filters.enabled_dinovoice & ~filters.scheduled & filters.voice & filters.chat(configGet("users", "groups")))
|
||||||
|
async def voice_message(app: Client, msg: Message):
|
||||||
|
logWrite(f"User {msg.from_user.id} sent voice message in destination group")
|
||||||
|
await msg.reply_text(choice(locale("voice_message", "message")))
|
@@ -1,11 +1,19 @@
|
|||||||
from app import app
|
from app import app
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.types import ForceReply, ReplyKeyboardMarkup
|
from pyrogram.types import ForceReply, ReplyKeyboardMarkup, Message
|
||||||
from modules.utils import locale, logWrite
|
from pyrogram.client import Client
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
|
from modules.utils import all_locales, locale, logWrite
|
||||||
|
from modules import custom_filters
|
||||||
|
|
||||||
# Welcome check ================================================================================================================
|
# Welcome check ================================================================================================================
|
||||||
@app.on_message(~ filters.scheduled & filters.private & (filters.regex(locale("welcome", "keyboard")[0][0]) | filters.regex(locale("return", "keyboard")[0][0])))
|
welcome_1 = []
|
||||||
async def welcome_pass(app, msg, once_again: bool = True) -> None:
|
for pattern in all_locales("welcome", "keyboard"):
|
||||||
|
welcome_1.append(pattern[0][0])
|
||||||
|
for pattern in all_locales("return", "keyboard"):
|
||||||
|
welcome_1.append(pattern[0][0])
|
||||||
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(welcome_1, prefixes=[""]))
|
||||||
|
async def welcome_pass(app: Client, msg: Message, once_again: bool = False) -> None:
|
||||||
"""Set user's stage to 1 and start a fresh application
|
"""Set user's stage to 1 and start a fresh application
|
||||||
|
|
||||||
### Args:
|
### Args:
|
||||||
@@ -16,15 +24,21 @@ async def welcome_pass(app, msg, once_again: bool = True) -> None:
|
|||||||
|
|
||||||
if not once_again:
|
if not once_again:
|
||||||
await msg.reply_text(locale("privacy_notice", "message"))
|
await msg.reply_text(locale("privacy_notice", "message"))
|
||||||
|
|
||||||
|
holo_user = HoloUser(msg.from_user)
|
||||||
|
|
||||||
|
if once_again is False:
|
||||||
|
holo_user.application_restart()
|
||||||
|
|
||||||
logWrite(f"User {msg.from_user.id} confirmed starting the application")
|
logWrite(f"User {msg.from_user.id} confirmed starting the application")
|
||||||
await msg.reply_text(locale("question1", "message"), reply_markup=ForceReply(placeholder=locale("question1", "force_reply")))
|
await msg.reply_text(locale("question1", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("question1", "force_reply", locale=msg.from_user)))
|
||||||
# configSet(["stage"], 1, file=str(msg.from_user.id))
|
|
||||||
# configSet(["sent"], False, file=str(msg.from_user.id))
|
|
||||||
|
|
||||||
@app.on_message(~ filters.scheduled & filters.private & (filters.regex(locale("welcome", "keyboard")[1][0])))
|
welcome_2 = []
|
||||||
async def welcome_reject(app, msg):
|
for pattern in all_locales("welcome", "keyboard"):
|
||||||
|
welcome_2.append(pattern[1][0])
|
||||||
|
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(welcome_2, prefixes=[""]))
|
||||||
|
async def welcome_reject(app: Client, msg: Message):
|
||||||
|
|
||||||
logWrite(f"User {msg.from_user.id} rejected to start the application")
|
logWrite(f"User {msg.from_user.id} rejected to start the application")
|
||||||
await msg.reply_text(locale("goodbye", "message"), reply_markup=ReplyKeyboardMarkup(locale("return", "keyboard"), resize_keyboard=True))
|
await msg.reply_text(locale("goodbye", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("return", "keyboard", locale=msg.from_user), resize_keyboard=True))
|
||||||
# ==============================================================================================================================
|
# ==============================================================================================================================
|
@@ -1,58 +1,129 @@
|
|||||||
|
"""Module responsible for providing answers to
|
||||||
|
all inline queries that bot receives"""
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from os import path, sep
|
from os import path, sep
|
||||||
from pyrogram.types import InlineQueryResultArticle, InputTextMessageContent
|
from app import app, isAnAdmin
|
||||||
|
from pyrogram.types import InlineQueryResultArticle, InputTextMessageContent, InlineQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
from pyrogram.client import Client
|
||||||
from pyrogram.enums.chat_type import ChatType
|
from pyrogram.enums.chat_type import ChatType
|
||||||
from pyrogram.enums.chat_members_filter import ChatMembersFilter
|
from pyrogram.enums.chat_members_filter import ChatMembersFilter
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from classes.errors.holo_user import UserNotFoundError, UserInvalidError
|
||||||
from app import app, isAnAdmin
|
from classes.holo_user import HoloUser
|
||||||
|
from modules.logging import logWrite
|
||||||
from modules.utils import configGet, jsonLoad, locale
|
from modules.utils import configGet, jsonLoad, locale
|
||||||
|
from modules.database import col_applications, col_spoilers
|
||||||
|
from bson.objectid import ObjectId
|
||||||
|
from bson.errors import InvalidId
|
||||||
|
|
||||||
@app.on_inline_query()
|
@app.on_inline_query()
|
||||||
async def inline_answer(client, inline_query):
|
async def inline_answer(client: Client, inline_query: InlineQuery):
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
if inline_query.query.startswith("spoiler:"):
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
spoil = col_spoilers.find_one( {"_id": ObjectId(inline_query.query.removeprefix("spoiler:"))} )
|
||||||
|
|
||||||
|
if spoil is not None:
|
||||||
|
|
||||||
|
desc = locale("spoiler_empty", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories")) if spoil["description"] == "" else locale("spoiler_described", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), spoil["description"])
|
||||||
|
|
||||||
|
results = [
|
||||||
|
InlineQueryResultArticle(
|
||||||
|
title=locale("title", "inline", "spoiler", locale=inline_query.from_user),
|
||||||
|
description=locale("description", "inline", "spoiler", locale=inline_query.from_user),
|
||||||
|
input_message_content=InputTextMessageContent(desc, disable_web_page_preview=True),
|
||||||
|
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=inline_query.from_user), callback_data=f'sid_{inline_query.query.removeprefix("spoiler:")}')]])
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
except InvalidId:
|
||||||
|
results = []
|
||||||
|
|
||||||
|
|
||||||
|
await inline_query.answer(
|
||||||
|
results=results
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
if inline_query.chat_type in [ChatType.CHANNEL]:
|
if inline_query.chat_type in [ChatType.CHANNEL]:
|
||||||
await inline_query.answer(
|
await inline_query.answer(
|
||||||
results=[
|
results=[
|
||||||
InlineQueryResultArticle(
|
InlineQueryResultArticle(
|
||||||
title=locale("title", "inline", "not_pm"),
|
title=locale("title", "inline", "not_pm", locale=inline_query.from_user),
|
||||||
input_message_content=InputTextMessageContent(
|
input_message_content=InputTextMessageContent(
|
||||||
locale("message_content", "inline", "not_pm")
|
locale("message_content", "inline", "not_pm", locale=inline_query.from_user)
|
||||||
),
|
),
|
||||||
description=locale("description", "inline", "not_pm")
|
description=locale("description", "inline", "not_pm", locale=inline_query.from_user)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (path.exists(f"{configGet('data', 'locations')}{sep}users{sep}{inline_query.from_user.id}.json") and jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{inline_query.from_user.id}.json")["approved"]) or (await isAnAdmin(inline_query.from_user.id) is True):
|
results_forbidden = [
|
||||||
|
InlineQueryResultArticle(
|
||||||
|
title=locale("title", "inline", "forbidden", locale=inline_query.from_user),
|
||||||
|
input_message_content=InputTextMessageContent(
|
||||||
|
locale("message_content", "inline", "forbidden", locale=inline_query.from_user)
|
||||||
|
),
|
||||||
|
description=locale("description", "inline", "forbidden", locale=inline_query.from_user)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
holo_user = HoloUser(inline_query.from_user)
|
||||||
|
except (UserNotFoundError, UserInvalidError):
|
||||||
|
logWrite(f"Could not find application of {inline_query.from_user.id}, ignoring inline query", debug=True)
|
||||||
|
await inline_query.answer(
|
||||||
|
results=results_forbidden
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if path.exists(path.join(configGet("cache", "locations"), "group_members")) and (inline_query.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))):
|
||||||
|
if path.exists(path.join(configGet("cache", "locations"), "admins")) and (inline_query.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "admins"))):
|
||||||
|
logWrite(f"{inline_query.from_user.id} is not an admin and not in members group, ignoring inline query", debug=True)
|
||||||
|
await inline_query.answer(
|
||||||
|
results=results_forbidden
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if holo_user.application_approved() or (await isAnAdmin(holo_user.id) is True):
|
||||||
|
|
||||||
|
max_results = configGet("inline_preview_count") if inline_query.query != "" else 200
|
||||||
|
|
||||||
list_of_users = []
|
list_of_users = []
|
||||||
async for m in app.get_chat_members(configGet("destination_group"), limit=configGet("inline_preview_count"), filter=ChatMembersFilter.SEARCH, query=inline_query.query):
|
async for m in app.get_chat_members(configGet("users", "groups"), limit=max_results, filter=ChatMembersFilter.SEARCH, query=inline_query.query):
|
||||||
list_of_users.append(m)
|
list_of_users.append(m)
|
||||||
|
|
||||||
results = []
|
|
||||||
|
|
||||||
applications = jsonLoad(f"{configGet('data', 'locations')}{sep}applications.json")
|
|
||||||
|
|
||||||
for match in list_of_users:
|
for match in list_of_users:
|
||||||
|
|
||||||
try:
|
application = col_applications.find_one({"user": match.user.id})
|
||||||
application_content = []
|
|
||||||
i = 1
|
if application is None:
|
||||||
for question in applications[str(match.user.id)]["application"]:
|
continue
|
||||||
if i == 2:
|
|
||||||
age = relativedelta(datetime.now(), datetime.strptime(applications[str(match.user.id)]['application']['2'], '%d.%m.%Y'))
|
application_content = []
|
||||||
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {applications[str(match.user.id)]['application']['2']} ({age.years} р.)")
|
i = 1
|
||||||
|
|
||||||
|
for question in application['application']:
|
||||||
|
|
||||||
|
if i == 2:
|
||||||
|
age = relativedelta(datetime.now(), application['application']['2'])
|
||||||
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
|
||||||
|
elif i == 3:
|
||||||
|
if application['application']['3']['countryCode'] == "UA":
|
||||||
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['3']['name']}")
|
||||||
else:
|
else:
|
||||||
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {applications[str(match.user.id)]['application'][question]}")
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
|
||||||
i += 1
|
else:
|
||||||
except KeyError:
|
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application'][question]}")
|
||||||
continue
|
|
||||||
except FileNotFoundError:
|
i += 1
|
||||||
continue
|
|
||||||
except TypeError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if match.user.photo != None:
|
if match.user.photo != None:
|
||||||
try:
|
try:
|
||||||
@@ -63,9 +134,9 @@ async def inline_answer(client, inline_query):
|
|||||||
InlineQueryResultArticle(
|
InlineQueryResultArticle(
|
||||||
title=str(match.user.first_name),
|
title=str(match.user.first_name),
|
||||||
input_message_content=InputTextMessageContent(
|
input_message_content=InputTextMessageContent(
|
||||||
locale("message_content", "inline", "user").format(match.user.first_name, match.user.username, "\n".join(application_content))
|
locale("message_content", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username, "\n".join(application_content))
|
||||||
),
|
),
|
||||||
description=locale("description", "inline", "user").format(match.user.first_name, match.user.username),
|
description=locale("description", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username),
|
||||||
thumb_url=f'{configGet("api")}/?avatar_id={match.user.photo.big_file_id}'
|
thumb_url=f'{configGet("api")}/?avatar_id={match.user.photo.big_file_id}'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -74,9 +145,9 @@ async def inline_answer(client, inline_query):
|
|||||||
InlineQueryResultArticle(
|
InlineQueryResultArticle(
|
||||||
title=str(match.user.first_name),
|
title=str(match.user.first_name),
|
||||||
input_message_content=InputTextMessageContent(
|
input_message_content=InputTextMessageContent(
|
||||||
locale("message_content", "inline", "user").format(match.user.first_name, match.user.username, "\n".join(application_content))
|
locale("message_content", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username, "\n".join(application_content))
|
||||||
),
|
),
|
||||||
description=locale("description", "inline", "user").format(match.user.first_name, match.user.username)
|
description=locale("description", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
@@ -84,9 +155,9 @@ async def inline_answer(client, inline_query):
|
|||||||
InlineQueryResultArticle(
|
InlineQueryResultArticle(
|
||||||
title=str(match.user.first_name),
|
title=str(match.user.first_name),
|
||||||
input_message_content=InputTextMessageContent(
|
input_message_content=InputTextMessageContent(
|
||||||
locale("message_content", "inline", "user").format(match.user.first_name, match.user.username, "\n".join(application_content))
|
locale("message_content", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username, "\n".join(application_content))
|
||||||
),
|
),
|
||||||
description=locale("description", "inline", "user").format(match.user.first_name, match.user.username)
|
description=locale("description", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -94,27 +165,14 @@ async def inline_answer(client, inline_query):
|
|||||||
InlineQueryResultArticle(
|
InlineQueryResultArticle(
|
||||||
title=str(match.user.first_name),
|
title=str(match.user.first_name),
|
||||||
input_message_content=InputTextMessageContent(
|
input_message_content=InputTextMessageContent(
|
||||||
locale("message_content", "inline", "user").format(match.user.first_name, match.user.username, "\n".join(application_content))
|
locale("message_content", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username, "\n".join(application_content))
|
||||||
),
|
),
|
||||||
description=locale("description", "inline", "user").format(match.user.first_name, match.user.username)
|
description=locale("description", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
await inline_query.answer(
|
await inline_query.answer(
|
||||||
results=results,
|
results=results,
|
||||||
cache_time=10
|
cache_time=10,
|
||||||
)
|
is_personal=True
|
||||||
|
)
|
||||||
else:
|
|
||||||
await inline_query.answer(
|
|
||||||
results=[
|
|
||||||
InlineQueryResultArticle(
|
|
||||||
title=locale("title", "inline", "forbidden"),
|
|
||||||
input_message_content=InputTextMessageContent(
|
|
||||||
locale("message_content", "inline", "forbidden")
|
|
||||||
),
|
|
||||||
description=locale("description", "inline", "forbidden")
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
return
|
|
@@ -1,39 +1,236 @@
|
|||||||
|
"""Automatically register commands and execute
|
||||||
|
some scheduled tasks is the main idea of this module"""
|
||||||
|
|
||||||
|
from os import listdir, makedirs, path, sep
|
||||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
|
from ujson import dumps
|
||||||
from app import app
|
from app import app
|
||||||
from modules.utils import configGet, locale, logWrite
|
from pyrogram.types import BotCommand, BotCommandScopeChat, BotCommandScopeChatAdministrators
|
||||||
|
from pyrogram.errors import bad_request_400
|
||||||
|
from pyrogram.enums.chat_members_filter import ChatMembersFilter
|
||||||
|
from classes.holo_user import HoloUser
|
||||||
|
from modules.utils import configGet, jsonSave, locale, logWrite
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from modules.database import col_applications
|
from modules.database import col_applications, col_sponsorships
|
||||||
|
|
||||||
scheduler = AsyncIOScheduler()
|
scheduler = AsyncIOScheduler()
|
||||||
|
|
||||||
# for user_file in listdir(f"{configGet('data', 'locations')}{sep}users{sep}"):
|
if configGet("enabled", "scheduler", "cache_members"):
|
||||||
# filename = fsdecode(f"{configGet('data', 'locations')}{sep}users{sep}{user_file}")
|
@scheduler.scheduled_job(trigger="interval", seconds=configGet("interval", "scheduler", "cache_members"))
|
||||||
# if filename.endswith(".json"):
|
async def cache_group_members():
|
||||||
# user = jsonLoad(filename)
|
list_of_users = []
|
||||||
# if isinstance(user["application"]["2"], str):
|
async for member in app.get_chat_members(configGet("users", "groups")):
|
||||||
# try:
|
list_of_users.append(member.user.id)
|
||||||
# if ".".join([((user["application"]["2"]).split("."))[0], ((user["application"]["2"]).split("."))[1]]) == datetime.now().strftime("%d.%m"):
|
makedirs(configGet("cache", "locations"), exist_ok=True)
|
||||||
# tg_user = await app.get_users(int(user_file.replace(".json", "")))
|
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "group_members"))
|
||||||
# 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)) )
|
if configGet("debug") is True:
|
||||||
# except AttributeError:
|
logWrite("User group caching performed", debug=True)
|
||||||
# continue
|
|
||||||
|
|
||||||
if configGet("enabled", "scheduler", "birthdays"):
|
if configGet("enabled", "scheduler", "cache_admins"):
|
||||||
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "birthdays"))
|
@scheduler.scheduled_job(trigger="interval", seconds=configGet("interval", "scheduler", "cache_admins"))
|
||||||
async def check_birthdays():
|
async def cache_admins():
|
||||||
for entry in col_applications.find():
|
list_of_users = []
|
||||||
if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"):
|
async for member in app.get_chat_members(configGet("admin", "groups")):
|
||||||
|
list_of_users.append(member.user.id)
|
||||||
|
makedirs(configGet("cache", "locations"), exist_ok=True)
|
||||||
|
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "admins"))
|
||||||
|
if configGet("debug") is True:
|
||||||
|
logWrite("Admin group caching performed", debug=True)
|
||||||
|
|
||||||
|
# Cache the avatars of group members
|
||||||
|
if configGet("enabled", "scheduler", "cache_avatars"):
|
||||||
|
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=15))
|
||||||
|
@scheduler.scheduled_job(trigger="interval", hours=configGet("interval", "scheduler", "cache_avatars"))
|
||||||
|
async def cache_avatars():
|
||||||
|
list_of_users = []
|
||||||
|
async for member in app.get_chat_members(configGet("users", "groups"), filter=ChatMembersFilter.SEARCH, query=""):
|
||||||
|
list_of_users.append(member.user)
|
||||||
|
for user in list_of_users:
|
||||||
|
if user.photo != None:
|
||||||
|
if not path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{user.photo.big_file_id}'):
|
||||||
|
print(f'Pre-cached avatar {user.photo.big_file_id} of {user.id}', flush=True)
|
||||||
|
await app.download_media(user.photo.big_file_id, file_name=path.join(configGet("cache", "locations"), "avatars", user.photo.big_file_id))
|
||||||
|
logWrite("Avatars caching performed")
|
||||||
|
|
||||||
|
|
||||||
|
# Check for birthdays
|
||||||
|
if configGet("enabled", "features", "applications") is True:
|
||||||
|
if configGet("enabled", "scheduler", "birthdays") is True:
|
||||||
|
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "birthdays"))
|
||||||
|
async def check_birthdays():
|
||||||
|
for entry in col_applications.find():
|
||||||
|
if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"):
|
||||||
|
try:
|
||||||
|
tg_user = await app.get_users(entry["user"])
|
||||||
|
await app.send_message( configGet("admin", "groups"), locale("birthday", "message").format(str(tg_user.first_name), str(tg_user.username), str(relativedelta(datetime.now(), entry["application"]["2"], '%d.%m.%Y').years)) ) # type: ignore
|
||||||
|
logWrite(f"Notified admins about {entry['user']}'s birthday")
|
||||||
|
except Exception as exp:
|
||||||
|
logWrite(f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'")
|
||||||
|
continue
|
||||||
|
logWrite("Birthdays check performed")
|
||||||
|
|
||||||
|
|
||||||
|
# Check for expired sponsorships
|
||||||
|
if configGet("enabled", "features", "sponsorships") is True:
|
||||||
|
if configGet("enabled", "scheduler", "sponsorships") is True:
|
||||||
|
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "sponsorships"))
|
||||||
|
async def check_sponsors():
|
||||||
|
for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()+timedelta(days=2)}}):
|
||||||
try:
|
try:
|
||||||
tg_user = await app.get_users(entry["user"])
|
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(), entry["application"]["2"], '%d.%m.%Y').years)) ) # type: ignore
|
until_expiry = relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days
|
||||||
logWrite(f"Notified admins about {entry['user']}'s birthday")
|
await app.send_message( tg_user.id, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore
|
||||||
|
logWrite(f"Notified user that sponsorship expires in {until_expiry} days")
|
||||||
except Exception as exp:
|
except Exception as exp:
|
||||||
logWrite(f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'")
|
logWrite(f"Could not find user {entry['user']} notify about sponsorship expiry due to '{exp}'")
|
||||||
continue
|
continue
|
||||||
logWrite("Birthdays check performed")
|
for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()}}):
|
||||||
|
try:
|
||||||
|
holo_user = HoloUser(entry["user"])
|
||||||
|
await app.send_message( entry["user"], locale("sponsorships_expired", "message") ) # type: ignore
|
||||||
|
await holo_user.label_reset(configGet("users", "groups"))
|
||||||
|
col_sponsorships.find_one_and_delete({"user": holo_user.id})
|
||||||
|
try:
|
||||||
|
tg_user = await app.get_users(entry["user"])
|
||||||
|
logWrite(f"Notified user that sponsorship expired")
|
||||||
|
except Exception as exp:
|
||||||
|
logWrite(f"Could not find user {entry['user']} notify about sponsorship expired due to '{exp}'")
|
||||||
|
except Exception as exp:
|
||||||
|
logWrite(f"Could not reset label of user {entry['user']} due to '{exp}'")
|
||||||
|
continue
|
||||||
|
logWrite("Sponsorships check performed")
|
||||||
|
|
||||||
if configGet("enabled", "scheduler", "sponsorships"):
|
|
||||||
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "sponsorships"))
|
# Register all bot commands
|
||||||
async def check_sponsors():
|
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=10))
|
||||||
logWrite("Sponsorships check performed")
|
async def commands_register():
|
||||||
|
|
||||||
|
commands = {
|
||||||
|
"users": [],
|
||||||
|
"admins": [],
|
||||||
|
"owner": [],
|
||||||
|
"group_users": [],
|
||||||
|
"group_admins": [],
|
||||||
|
"group_users_admins": [],
|
||||||
|
"locales": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands_raw = {
|
||||||
|
"users": [],
|
||||||
|
"admins": [],
|
||||||
|
"owner": [],
|
||||||
|
"group_users": [],
|
||||||
|
"group_admins": [],
|
||||||
|
"group_users_admins": [],
|
||||||
|
"locales": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_locales = []
|
||||||
|
files_locales = listdir(f'{configGet("locale", "locations")}')
|
||||||
|
|
||||||
|
for entry in files_locales:
|
||||||
|
if entry.endswith(".json"):
|
||||||
|
valid_locales.append(".".join(entry.split(".")[:-1]))
|
||||||
|
commands["locales"][".".join(entry.split(".")[:-1])] = {
|
||||||
|
"users": [],
|
||||||
|
"admins": [],
|
||||||
|
"owner": [],
|
||||||
|
"group_users": [],
|
||||||
|
"group_admins": [],
|
||||||
|
"group_users_admins": []
|
||||||
|
}
|
||||||
|
if configGet("debug") is True:
|
||||||
|
commands_raw["locales"][".".join(entry.split(".")[:-1])] = {
|
||||||
|
"users": [],
|
||||||
|
"admins": [],
|
||||||
|
"owner": [],
|
||||||
|
"group_users": [],
|
||||||
|
"group_admins": [],
|
||||||
|
"group_users_admins": []
|
||||||
|
}
|
||||||
|
|
||||||
|
config_modules = configGet("features")
|
||||||
|
config_commands = configGet("commands")
|
||||||
|
|
||||||
|
|
||||||
|
for command in config_commands:
|
||||||
|
|
||||||
|
enabled = False
|
||||||
|
|
||||||
|
for module in config_commands[command]["modules"]:
|
||||||
|
if config_modules[module]["enabled"] is True:
|
||||||
|
enabled = True
|
||||||
|
|
||||||
|
if enabled is False:
|
||||||
|
logWrite(f"Not registering {command} at all", debug=True)
|
||||||
|
continue
|
||||||
|
|
||||||
|
for permission in config_commands[command]["permissions"]:
|
||||||
|
|
||||||
|
commands[permission].append(BotCommand(command, locale("commands")[command]))
|
||||||
|
|
||||||
|
if configGet("debug") is True:
|
||||||
|
commands_raw[permission].append({f"{command}": locale("commands")[command]})
|
||||||
|
logWrite(f"Registering {command} for {permission}")
|
||||||
|
|
||||||
|
for lc in valid_locales:
|
||||||
|
|
||||||
|
commands["locales"][lc][permission].append(BotCommand(command, locale("commands", locale=lc)[command]))
|
||||||
|
|
||||||
|
if configGet("debug") is True:
|
||||||
|
commands_raw["locales"][lc][permission].append({f"{command}": locale("commands", locale=lc)[command]})
|
||||||
|
logWrite(f"Registering {command} for {permission} [{lc}]")
|
||||||
|
|
||||||
|
|
||||||
|
# Registering user commands
|
||||||
|
await app.set_bot_commands(commands["users"])
|
||||||
|
logWrite("Registered user commands for default locale")
|
||||||
|
|
||||||
|
# Registering user commands for each locale
|
||||||
|
for lc in valid_locales:
|
||||||
|
await app.set_bot_commands(commands["locales"][lc]["users"], language_code=lc)
|
||||||
|
logWrite(f"Registered user commands for locale {lc}")
|
||||||
|
|
||||||
|
# Registering admin commands
|
||||||
|
for admin in configGet("admins"):
|
||||||
|
try:
|
||||||
|
await app.set_bot_commands(commands["admins"]+commands["users"], scope=BotCommandScopeChat(chat_id=admin))
|
||||||
|
logWrite(f"Registered admin commands for admin {admin}")
|
||||||
|
except bad_request_400.PeerIdInvalid:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Registering owner commands
|
||||||
|
try:
|
||||||
|
await app.set_bot_commands(commands["admins"]+commands["owner"]+commands["users"], scope=BotCommandScopeChat(chat_id=configGet("owner")))
|
||||||
|
for lc in valid_locales:
|
||||||
|
await app.set_bot_commands(commands["locales"][lc]["admins"]+commands["locales"][lc]["owner"]+commands["locales"][lc]["users"], scope=BotCommandScopeChat(chat_id=configGet("owner")))
|
||||||
|
logWrite(f"Registered admin commands for owner {configGet('owner')}")
|
||||||
|
except bad_request_400.PeerIdInvalid:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Registering admin group commands
|
||||||
|
try:
|
||||||
|
await app.set_bot_commands(commands["group_admins"], scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")))
|
||||||
|
logWrite("Registered admin group commands for default locale")
|
||||||
|
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
|
||||||
|
try:
|
||||||
|
await app.set_bot_commands(commands["group_users"], scope=BotCommandScopeChat(chat_id=configGet("users", "groups")))
|
||||||
|
logWrite("Registered destination group commands")
|
||||||
|
except bad_request_400.ChannelInvalid:
|
||||||
|
logWrite(f"Could not register commands for destination group. Bot is likely not in the group.")
|
||||||
|
|
||||||
|
# Registering destination group admin commands
|
||||||
|
try:
|
||||||
|
await app.set_bot_commands(commands["group_users_admins"], scope=BotCommandScopeChatAdministrators(chat_id=configGet("users", "groups")))
|
||||||
|
logWrite("Registered destination group admin commands")
|
||||||
|
except bad_request_400.ChannelInvalid:
|
||||||
|
logWrite(f"Could not register admin commands for destination group. Bot is likely not in the group.")
|
||||||
|
|
||||||
|
|
||||||
|
if configGet("debug") is True:
|
||||||
|
print(commands, flush=True)
|
||||||
|
logWrite(f"Complete commands registration:\n{dumps(commands_raw, indent=4, ensure_ascii=False, encode_html_chars=False)}", debug=True)
|
101
modules/utils.py
101
modules/utils.py
@@ -1,4 +1,6 @@
|
|||||||
from typing import Any, Union
|
from typing import Any, Literal, Union
|
||||||
|
from uuid import uuid1
|
||||||
|
from requests import get
|
||||||
from pyrogram.enums.chat_type import ChatType
|
from pyrogram.enums.chat_type import ChatType
|
||||||
from pyrogram.types import User
|
from pyrogram.types import User
|
||||||
from pyrogram.client import Client
|
from pyrogram.client import Client
|
||||||
@@ -7,9 +9,10 @@ from ujson import JSONDecodeError as JSONDecodeError
|
|||||||
from ujson import loads, dumps
|
from ujson import loads, dumps
|
||||||
|
|
||||||
from sys import exit
|
from sys import exit
|
||||||
from os import kill, sep
|
from os import kill, listdir, makedirs, path, sep
|
||||||
from os import name as osname
|
from os import name as osname
|
||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
|
from classes.errors.geo import PlaceNotFoundError
|
||||||
|
|
||||||
from modules.logging import logWrite
|
from modules.logging import logWrite
|
||||||
|
|
||||||
@@ -107,12 +110,14 @@ def locale(key: str, *args: str, locale: Union[str, User] = configGet("locale"))
|
|||||||
### Args:
|
### Args:
|
||||||
* key (`str`): The last key of the locale's keys path.
|
* key (`str`): The last key of the locale's keys path.
|
||||||
* *args (`list`): Path to key like: dict[args][key].
|
* *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.
|
* locale (`Union[str, User, HoloUser]`): Locale to looked up in. Provide User to get his `.language_code`. Defaults to config's locale value.
|
||||||
### Returns:
|
### Returns:
|
||||||
* any: Value of provided locale key. In normal case must be `str`, `dict` or `list`.
|
* any: Value of provided locale key. In normal case must be `str`, `dict` or `list`.
|
||||||
"""
|
"""
|
||||||
if isinstance(locale, User):
|
if isinstance(locale, User):
|
||||||
locale = locale.language_code
|
locale = locale.language_code
|
||||||
|
elif hasattr(locale, "locale"):
|
||||||
|
locale = locale.locale
|
||||||
|
|
||||||
if locale is None:
|
if locale is None:
|
||||||
locale = configGet("locale")
|
locale = configGet("locale")
|
||||||
@@ -134,6 +139,96 @@ def locale(key: str, *args: str, locale: Union[str, User] = configGet("locale"))
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
|
return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
|
||||||
|
|
||||||
|
def all_locales(key: str, *args: str) -> list:
|
||||||
|
"""Get value of the provided key and path in all available locales
|
||||||
|
|
||||||
|
### Args:
|
||||||
|
* key (`str`): The last key of the locale's keys path.
|
||||||
|
* *args (`list`): Path to key like: dict[args][key].
|
||||||
|
|
||||||
|
### Returns:
|
||||||
|
* `list`: List of all values in all locales
|
||||||
|
"""
|
||||||
|
|
||||||
|
output = []
|
||||||
|
valid_locales = []
|
||||||
|
|
||||||
|
files_locales = listdir(f'{configGet("locale", "locations")}')
|
||||||
|
for entry in files_locales:
|
||||||
|
valid_locales.append(".".join(entry.split(".")[:-1]))
|
||||||
|
|
||||||
|
for lc in valid_locales:
|
||||||
|
try:
|
||||||
|
this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{lc}.json')
|
||||||
|
except FileNotFoundError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
this_key = this_dict
|
||||||
|
for dict_key in args:
|
||||||
|
this_key = this_key[dict_key]
|
||||||
|
|
||||||
|
try:
|
||||||
|
output.append(this_key[key])
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def find_location(query: str) -> dict:
|
||||||
|
"""Find location on geonames.org by query. Search is made with feature classes A and P.
|
||||||
|
|
||||||
|
### Args:
|
||||||
|
* query (`str`): Some city/village/state name
|
||||||
|
|
||||||
|
### Raises:
|
||||||
|
* PlaceNotFoundError: Exception is raised when API result is empty
|
||||||
|
|
||||||
|
### Returns:
|
||||||
|
* `dict`: One instance of geonames response
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result = (get(f"http://api.geonames.org/searchJSON?q={query}&maxRows=1&countryBias=UA&lang=uk&orderby=relevance&featureClass=P&featureClass=A&username={configGet('username', 'geocoding')}")).json()
|
||||||
|
return result["geonames"][0]
|
||||||
|
except (ValueError, KeyError, IndexError):
|
||||||
|
raise PlaceNotFoundError(query)
|
||||||
|
|
||||||
|
def create_tmp(bytedata: Union[bytes, bytearray], kind: Union[Literal["image", "video"], None] = None) -> str:
|
||||||
|
"""Create temporary file to help uploading it
|
||||||
|
|
||||||
|
### Args:
|
||||||
|
* bytedata (`Union[bytes, bytearray]`): Some bytes to be written
|
||||||
|
* kind (`Union[Literal["image", "video"], None]`): Kind of upload. Will add `.jpg` or `.mp4` if needed
|
||||||
|
|
||||||
|
### Returns:
|
||||||
|
* `str`: Path to temporary file
|
||||||
|
"""
|
||||||
|
filename = str(uuid1())
|
||||||
|
if kind == "image":
|
||||||
|
filename += ".jpg"
|
||||||
|
elif kind == "video":
|
||||||
|
filename += ".mp4"
|
||||||
|
makedirs("tmp", exist_ok=True)
|
||||||
|
with open(path.join("tmp", filename), "wb") as file:
|
||||||
|
file.write(bytedata)
|
||||||
|
return path.join("tmp", filename)
|
||||||
|
|
||||||
|
async def download_tmp(app: Client, file_id: str) -> bytes:
|
||||||
|
"""Download file by its ID and return its bytes
|
||||||
|
|
||||||
|
### Args:
|
||||||
|
* app (`Client`): App that will download the file
|
||||||
|
* file_id (`str`): File's unique id
|
||||||
|
|
||||||
|
### Returns:
|
||||||
|
* `bytes`: Bytes of downloaded file
|
||||||
|
"""
|
||||||
|
filename = str(uuid1())
|
||||||
|
makedirs("tmp", exist_ok=True)
|
||||||
|
await app.download_media(file_id, path.join("tmp", filename))
|
||||||
|
with open(path.join("tmp", filename), "rb") as f:
|
||||||
|
bytedata = f.read()
|
||||||
|
return bytedata
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from psutil import Process
|
from psutil import Process
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
APScheduler==3.9.1.post1
|
APScheduler==3.9.1.post1
|
||||||
fastapi==0.88.0
|
fastapi~=0.88.0
|
||||||
psutil==5.9.4
|
psutil==5.9.4
|
||||||
pymongo==4.3.3
|
pymongo==4.3.3
|
||||||
Pyrogram==2.0.69
|
Pyrogram~=2.0.96
|
||||||
requests==2.28.1
|
requests==2.28.1
|
||||||
tgcrypto==1.2.5
|
tgcrypto==1.2.5
|
||||||
python_dateutil==2.8.2
|
python_dateutil==2.8.2
|
||||||
starlette==0.22.0
|
starlette~=0.22.0
|
||||||
ujson==5.6.0
|
ujson~=5.7.0
|
||||||
|
ftfy~=6.1.1
|
@@ -1,6 +1,87 @@
|
|||||||
{
|
{
|
||||||
"$jsonSchema": {
|
"$jsonSchema": {
|
||||||
"required": [],
|
"required": [
|
||||||
"properties": {}
|
"user",
|
||||||
|
"date",
|
||||||
|
"admin",
|
||||||
|
"application",
|
||||||
|
"application.1",
|
||||||
|
"application.2",
|
||||||
|
"application.3",
|
||||||
|
"application.3.name",
|
||||||
|
"application.3.adminName1",
|
||||||
|
"application.3.countryCode",
|
||||||
|
"application.3.countryName",
|
||||||
|
"application.3.location",
|
||||||
|
"application.4",
|
||||||
|
"application.5",
|
||||||
|
"application.6",
|
||||||
|
"application.7",
|
||||||
|
"application.8",
|
||||||
|
"application.9",
|
||||||
|
"application.10"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"user": {
|
||||||
|
"bsonType": ["int", "long"],
|
||||||
|
"description": "Telegram ID of user"
|
||||||
|
},
|
||||||
|
"date": {
|
||||||
|
"bsonType": "date",
|
||||||
|
"description": "Date when application was accepted"
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"bsonType": ["int", "long"],
|
||||||
|
"description": "Telegram ID of admin that accepted the application"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"bsonType": "object"
|
||||||
|
},
|
||||||
|
"application.1": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.2": {
|
||||||
|
"bsonType": "date"
|
||||||
|
},
|
||||||
|
"application.3": {
|
||||||
|
"bsonType": "object"
|
||||||
|
},
|
||||||
|
"application.3.name": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.3.adminName1": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.3.countryCode": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.3.countryName": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.3.location": {
|
||||||
|
"bsonType": "array"
|
||||||
|
},
|
||||||
|
"application.4": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.5": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.6": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.7": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.8": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.9": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"application.10": {
|
||||||
|
"bsonType": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
64
validation/spoilers.json
Normal file
64
validation/spoilers.json
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"$jsonSchema": {
|
||||||
|
"required": [
|
||||||
|
"user",
|
||||||
|
"completed",
|
||||||
|
"category",
|
||||||
|
"description",
|
||||||
|
"photo",
|
||||||
|
"video",
|
||||||
|
"audio",
|
||||||
|
"animation",
|
||||||
|
"document",
|
||||||
|
"caption",
|
||||||
|
"text"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"user": {
|
||||||
|
"bsonType": ["int", "long"],
|
||||||
|
"description": "Telegram ID of user"
|
||||||
|
},
|
||||||
|
"completed": {
|
||||||
|
"bsonType": "bool",
|
||||||
|
"description": "Whether spoiler is a completed one"
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"enum": ["nsfw", "deanon", "other"],
|
||||||
|
"description": "Spoiler's category"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"description": "Spoiler's description"
|
||||||
|
},
|
||||||
|
"photo": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"description": "Spoilered photo"
|
||||||
|
},
|
||||||
|
"video": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"description": "Spoilered video"
|
||||||
|
},
|
||||||
|
"audio": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"description": "Spoilered audio"
|
||||||
|
},
|
||||||
|
"animation": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"description": "Spoilered animation/GIF"
|
||||||
|
},
|
||||||
|
"document": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"description": "Spoilered document/file"
|
||||||
|
},
|
||||||
|
"caption": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"description": "Spoilered caption for media"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"bsonType": ["string", "null"],
|
||||||
|
"description": "Spoilered text"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,43 @@
|
|||||||
{
|
{
|
||||||
"$jsonSchema": {
|
"$jsonSchema": {
|
||||||
"required": [],
|
"required": [
|
||||||
"properties": {}
|
"user",
|
||||||
|
"date",
|
||||||
|
"admin",
|
||||||
|
"sponsorship",
|
||||||
|
"sponsorship.streamer",
|
||||||
|
"sponsorship.expires",
|
||||||
|
"sponsorship.proof",
|
||||||
|
"sponsorship.label"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"user": {
|
||||||
|
"bsonType": ["int", "long"],
|
||||||
|
"description": "Telegram ID of user"
|
||||||
|
},
|
||||||
|
"date": {
|
||||||
|
"bsonType": "date",
|
||||||
|
"description": "Date when sponsorship was accepted"
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"bsonType": ["int", "long"],
|
||||||
|
"description": "Telegram ID of admin that accepted the sponsorship"
|
||||||
|
},
|
||||||
|
"sponsorship": {
|
||||||
|
"bsonType": "object"
|
||||||
|
},
|
||||||
|
"sponsorship.streamer": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"sponsorship.expires": {
|
||||||
|
"bsonType": "date"
|
||||||
|
},
|
||||||
|
"sponsorship.proof": {
|
||||||
|
"bsonType": "string"
|
||||||
|
},
|
||||||
|
"sponsorship.label": {
|
||||||
|
"bsonType": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
6
validation/tmp.json
Normal file
6
validation/tmp.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$jsonSchema": {
|
||||||
|
"required": [],
|
||||||
|
"properties": {}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,28 @@
|
|||||||
{
|
{
|
||||||
"$jsonSchema": {
|
"$jsonSchema": {
|
||||||
"required": [],
|
"required": [
|
||||||
"properties": {}
|
"user",
|
||||||
|
"admin",
|
||||||
|
"date",
|
||||||
|
"reason"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"user": {
|
||||||
|
"bsonType": ["int", "long"],
|
||||||
|
"description": "Telegram ID of user"
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"bsonType": ["int", "long"],
|
||||||
|
"description": "Telegram ID of admin"
|
||||||
|
},
|
||||||
|
"date": {
|
||||||
|
"bsonType": "date",
|
||||||
|
"description": "Date and time of getting"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"bsonType": "string",
|
||||||
|
"description": "Broken rule or admin's comment"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user