diff --git a/.github/workflows/autotranslate.yml b/.github/workflows/autotranslate.yml
deleted file mode 100644
index 58de97e1f8b8c850372fa49efa4b3cab417d3c88..0000000000000000000000000000000000000000
--- a/.github/workflows/autotranslate.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-name: Strings Translation
-
-on:
- workflow_dispatch:
- push:
- branches: [ dev ]
- paths:
- - strings/strings/en.yml
-
-env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
-jobs:
- analyze:
- name: Checkout Strings
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Setup Python
- uses: actions/setup-python@v2
- with:
- python-version: 3.9.x
- - name: Update Translations
- run: |
- git config --global user.email "newdev0@outlook.com"
- git config --global user.name "New-Dev0"
- git branch translation && git checkout translation
- pip install pyyaml requests telethon
- wget -O run.py https://gist.githubusercontent.com/New-dev0/c7d0d1eb514d311e8e3b687ae5cbe5f3/raw/350cc6d451a02a4b07d0f9bbc27b0e7c9465d3d4/updater.py
- python3 run.py
- rm run.py
- git add . && git commit -m "[Auto] Translate" && git push --set-upstream origin translation
- gh pr create --title "[Auto] Translation" -B dev --body "Update Translation"
diff --git a/.github/workflows/pylint.yaml b/.github/workflows/pylint.yaml
index 23fcec8a249e81ff4260550f5b17560f074b6551..8c71add5c50692cd21911df7d46a8c3e3c91d114 100644
--- a/.github/workflows/pylint.yaml
+++ b/.github/workflows/pylint.yaml
@@ -13,6 +13,7 @@ jobs:
uses: actions/setup-python@v1
with:
python-version: 3.8
+ cache: "pip"
- name: Install Python lint libraries
run: pip install autopep8 autoflake isort black
- name: Check for showstoppers
diff --git a/.gitignore b/.gitignore
index 26e851a55c3b07d4f024517eaf496d9540692971..794eba8b5a534f7b44a7b32f51a0ccb82f2cdbf4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,12 +8,14 @@ test*
*.webp
*.mp4
*.tgs
+*.txt
/*.jpg
/*.png
/*.mp4
*.log
target/npmlist.json
package-lock.json
+ultroid.json
resources/extras/thumbnail.jpg
# Directories
diff --git a/README.md b/README.md
index 1488acf7885596685daac61575940019eb8b83c3..b60ac89d0d597f4fb4232fc23d820da120acc914 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
A stable pluggable Telegram userbot + Voice & Video Call music bot, based on Telethon.
-[](#)
+[](#)
[](https://github.com/TeamUltroid/Ultroid/stargazers)
[](https://github.com/TeamUltroid/Ultroid/fork)
[](https://github.com/TeamUltroid/Ultroid/)
@@ -84,20 +84,6 @@ Get the [Necessary Variables](#Necessary-Variables) and then click the button be
`bash startup`
- Windows Users:
`python(3) -m pyUltroid`
-
-[OUTDATED] Ultroid CLI
-
-[Ultroid CLI](https://github.com/BLUE-DEVIL1134/UltroidCli) is a command-line interface for deploying Ultroid.
-
-- **Installing** -
-Run the following code on a terminal, with curl installed.
-`ver=$(curl https://raw.githubusercontent.com/BLUE-DEVIL1134/UltroidCli/main/version.txt) && curl -L -o ultroid https://github.com/BLUE-DEVIL1134/UltroidCli/releases/download/$ver/ultroid.exe`
-OR
-Go to [UltroidCli](https://github.com/BLUE-DEVIL1134/UltroidCli) and install the version release from the Github Releases. Add the executable to your system path as specified in the [Readme](https://github.com/BLUE-DEVIL1134/UltroidCli#how-to-use-ultroidcli-).
-
-- **Documentation** -
-Take a look at the [`docs`](https://blue-devil1134.github.io/UltroidCli/) for more detailed information.
-
---
## Necessary Variables
diff --git a/app.json b/app.json
index 7ffa52c375e93893dd5f10a4499f65e6a5943bc5..d192badba483b4ed8a94535876f392c504624720 100644
--- a/app.json
+++ b/app.json
@@ -50,7 +50,7 @@
"formation": {
"ultroid": {
"quantity": 1,
- "size": "free"
+ "size": "eco"
}
}
}
diff --git a/assistant/__init__.py b/assistant/__init__.py
index d4d248aed02561e0e9d5ce286c6c488f700c6ba8..e98ddeb85d3070ece8788cde2f00ad4b9c608c66 100644
--- a/assistant/__init__.py
+++ b/assistant/__init__.py
@@ -25,7 +25,8 @@ AST_PLUGINS = {}
async def setit(event, name, value):
try:
udB.set_key(name, value)
- except BaseException:
+ except BaseException as er:
+ LOGS.exception(er)
return await event.edit("`Something Went Wrong`")
diff --git a/assistant/callbackstuffs.py b/assistant/callbackstuffs.py
index 5829115980037ae4742f26eba46b3d7a02a7c0b0..316faa46a68fb26549e23542e926bbf5fb5d5761 100644
--- a/assistant/callbackstuffs.py
+++ b/assistant/callbackstuffs.py
@@ -5,7 +5,7 @@
# PLease read the GNU Affero General Public License in
# .
-
+import ast
import asyncio
import re
import sys
@@ -426,9 +426,12 @@ async def convo_handler(event: events.CallbackQuery):
back = get_["back"]
async with event.client.conversation(event.sender_id) as conv:
await conv.send_message(get_["text"])
- response = conv.wait_event(events.NewMessage(chats=event.sender_id))
- response = await response
- themssg = response.message.message
+ response = await conv.get_response()
+ themssg = response.message
+ try:
+ themssg = ast.literal_eval(themssg)
+ except Exception:
+ pass
if themssg == "/cancel":
return await conv.send_message(
"Cancelled!!",
@@ -1182,7 +1185,7 @@ async def name(event):
async def chon(event):
var = "PMBOT"
await setit(event, var, "True")
- Loader(path="assistant/pmbot.py", key="PM Bot").load_single()
+ Loader(path="assistant/pmbot.py", key="PM Bot").load()
if AST_PLUGINS.get("pmbot"):
for i, e in AST_PLUGINS["pmbot"]:
event.client.remove_event_handler(i)
diff --git a/assistant/pmbot.py b/assistant/pmbot.py
index b591adaf7aff461f676c2f276e37cb2395ecee03..62b06e20affe4850ac01d85cb8f59005ab2bd74d 100644
--- a/assistant/pmbot.py
+++ b/assistant/pmbot.py
@@ -18,12 +18,13 @@ from telethon.tl.functions.messages import GetFullChatRequest
from telethon.tl.types import Channel, Chat
from telethon.utils import get_display_name
-from pyUltroid.dB.asst_fns import *
+from pyUltroid.dB.base import KeyManager
from pyUltroid.dB.botchat_db import *
from pyUltroid.fns.helper import inline_mention
from . import *
+botb = KeyManager("BOTBLS", cast=list)
FSUB = udB.get_key("PMBOT_FSUB")
CACHE = {}
# --------------------------------------- Incoming -------------------------------------------- #
@@ -32,7 +33,7 @@ CACHE = {}
@asst_cmd(
load=AST_PLUGINS,
incoming=True,
- func=lambda e: e.is_private and not is_blacklisted(e.sender_id),
+ func=lambda e: e.is_private and not botb.contains(e.sender_id),
)
async def on_new_mssg(event):
who = event.sender_id
@@ -49,6 +50,7 @@ async def on_new_mssg(event):
if not MSG:
MSG += get_string("pmbot_1")
try:
+ uri = ""
TAHC_ = await event.client.get_entity(chat)
if hasattr(TAHC_, "username") and TAHC_.username:
uri = f"t.me/{TAHC_.username}"
@@ -119,10 +121,10 @@ async def banhammer(event):
if not event.is_reply:
return await event.reply(get_string("pmbot_2"))
target = get_who(event.reply_to_msg_id)
- if is_blacklisted(target):
+ if botb.contains(target):
return await event.reply(get_string("pmbot_3"))
- blacklist_user(target)
+ botb.add(target)
await event.reply(f"#BAN\nUser : {target}")
await asst.send_message(target, get_string("pmbot_4"))
@@ -137,10 +139,10 @@ async def unbanhammer(event):
if not event.is_reply:
return await event.reply(get_string("pmbot_5"))
target = get_who(event.reply_to_msg_id)
- if not is_blacklisted(target):
+ if not botb.contains(target):
return await event.reply(get_string("pmbot_6"))
- rem_blacklist(target)
+ botb.remove(target)
await event.reply(f"#UNBAN\nUser : {target}")
await asst.send_message(target, get_string("pmbot_7"))
diff --git a/assistant/start.py b/assistant/start.py
index cc224f6c6dbb22b0cbfc671262fcf574fd7f79f8..f3f16b05b5fae3273fc43350f13c7c8eab32f8cf 100644
--- a/assistant/start.py
+++ b/assistant/start.py
@@ -13,7 +13,7 @@ from telethon.errors.rpcerrorlist import MessageDeleteForbiddenError
from telethon.utils import get_display_name
from pyUltroid._misc import SUDO_M, owner_and_sudos
-from pyUltroid.dB.asst_fns import *
+from pyUltroid.dB.base import KeyManager
from pyUltroid.fns.helper import inline_mention
from strings import get_string
@@ -87,8 +87,9 @@ async def closet(lol):
@asst_cmd(pattern="start( (.*)|$)", forwards=False, func=lambda x: not x.is_group)
async def ultroid(event):
args = event.pattern_match.group(1).strip()
- if not is_added(event.sender_id) and event.sender_id not in owner_and_sudos():
- add_user(event.sender_id)
+ keym = KeyManager("BOT_USERS", cast=list)
+ if not keym.contains(event.sender_id) and event.sender_id not in owner_and_sudos():
+ keym.add(event.sender_id)
kak_uiw = udB.get_key("OFF_START_LOG")
if not kak_uiw or kak_uiw != True:
msg = f"{inline_mention(event.sender)} `[{event.sender_id}]` started your [Assistant bot](@{asst.me.username})."
@@ -158,7 +159,7 @@ async def ultroid(event):
@callback("stat", owner=True)
async def botstat(event):
- ok = len(get_all_users("BOT_USERS"))
+ ok = len(udB.get_key("BOT_USERS") or [])
msg = """Ultroid Assistant - Stats
Total Users - {}""".format(
ok,
@@ -168,8 +169,9 @@ Total Users - {}""".format(
@callback("bcast", owner=True)
async def bdcast(event):
- ok = get_all_users("BOT_USERS")
- await event.edit(f"⢠Broadcast to {len(ok)} users.")
+ keym = KeyManager("BOT_USERS", cast=list)
+ total = keym.count()
+ await event.edit(f"⢠Broadcast to {total} users.")
async with event.client.conversation(OWNER_ID) as conv:
await conv.send_message(
"Enter your broadcast message.\nUse /cancel to stop the broadcast.",
@@ -179,9 +181,9 @@ async def bdcast(event):
return await conv.send_message("Cancelled!!")
success = 0
fail = 0
- await conv.send_message(f"Starting a broadcast to {len(ok)} users...")
+ await conv.send_message(f"Starting a broadcast to {total} users...")
start = datetime.now()
- for i in ok:
+ for i in keym.get():
try:
await asst.send_message(int(i), response)
success += 1
@@ -192,7 +194,7 @@ async def bdcast(event):
await conv.send_message(
f"""
**Broadcast completed in {time_taken} seconds.**
-Total Users in Bot - {len(ok)}
+Total Users in Bot - {total}
**Sent to** : `{success} users.`
**Failed for** : `{fail} user(s).`""",
)
diff --git a/installer.sh b/installer.sh
index e8067a73ccbb70a03adc1e39612cfc10b14e3ce0..5c2b8f00f3a7532327adc6a64ed1571ff4e71030 100644
--- a/installer.sh
+++ b/installer.sh
@@ -1,99 +1,241 @@
#!/usr/bin/env bash
REPO="https://github.com/TeamUltroid/Ultroid.git"
+CURRENT_DIR="$(pwd)"
+ENV_FILE_PATH=".env"
DIR="/root/TeamUltroid"
-spinner(){
- local pid=$!
- while [ "$(ps a | awk '{print $1}' | grep $pid)" ];
- do
- for i in "Ooooo" "oOooo" "ooOoo" "oooOo" "ooooO" "oooOo" "ooOoo" "oOooo" "Ooooo"
- do
- echo -ne "\r⢠$i"
- sleep 0.2
- done
- done
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --dir=*)
+ DIR="${1#*=}" || DIR="/root/TeamUltroid"
+ ;;
+ --branch=*)
+ BRANCH="${1#*=}" || BRANCH="main"
+ ;;
+ --env-file=*)
+ ENV_FILE_PATH="${1#*=}" || ENV_FILE_PATH=".env"
+ ;;
+ --no-root)
+ NO_ROOT=true
+ ;;
+ *)
+ echo "Unknown parameter passed: $1"
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+check_dependencies() {
+ # check if debian
+ echo "Checking dependencies..."
+ # read file with root access
+ if ! [[ $(ls -l "/etc/sudoers" | cut -d " " -f1) =~ "r" ]]; then
+ # check dependencies if installed
+ echo -e "Root access not found. Checking if dependencies are installed." >&2
+ if ! [ -x "$(command -v python3)" ] || ! [ -x "$(command -v python)" ]; then
+ echo -e "Python3 isn't installed. Please install python3.8 or higher to run this bot." >&2
+ exit 1
+ fi
+ if [ $(python3 -c "import sys; print(sys.version_info[1])") -lt 8 ] || [ $(python -c "import sys; print(sys.version_info[1])") -lt 8 ]; then
+ echo -e "Python 3.8 or higher is required to run this bot." >&2
+ exit 1
+ fi
+ # check if any of ffmpeg, mediainfo, neofetch, git is not installed
+ if ! command -v ffmpeg &>/dev/null || ! command -v mediainfo &>/dev/null || ! command -v neofetch &>/dev/null || ! command -v git &>/dev/null; then
+ echo -e "Some dependencies aren't installed. Please install ffmpeg, mediainfo, neofetch and git to run this bot." >&2
+ exit 1
+ fi
+ fi
+ if [ -x "$(command -v apt-get)" ]; then
+ echo -e "Installing dependencies..."
+ # check if any of ffmpeg, mediainfo, neofetch, git is not installed via dpkg
+ if dpkg -l | grep -q ffmpeg || dpkg -l | grep -q mediainfo || dpkg -l | grep -q neofetch || dpkg -l | grep -q git; then
+ sudo apt-get -qq -o=Dpkg::Use-Pty=0 update
+ sudo apt-get install -qq -o=Dpkg::Use-Pty=0 python3 python3-pip ffmpeg mediainfo neofetch git -y
+ fi
+ elif [ -x "$(command -v pacman)" ]; then
+ echo -e "Installing dependencies..."
+ if pacman -Q | grep -q ffmpeg || pacman -Q | grep -q mediainfo || pacman -Q | grep -q neofetch || pacman -Q | grep -q git; then
+ sudo pacman -Sy python python-pip git ffmpeg mediainfo neofetch --noconfirm
+ fi
+ else
+ echo -e "Unknown OS. Checking if dependecies are installed" >&2
+ if ! [ -x "$(command -v python3)" ] || ! [ -x "$(command -v python)" ]; then
+ echo -e "Python3 isn't installed. Please install python3.8 or higher to run this bot." >&2
+ exit 1
+ fi
+ if [ $(python3 -c "import sys; print(sys.version_info[1])") -lt 8 ] || [ $(python -c "import sys; print(sys.version_info[1])") -lt 8 ]; then
+ echo -e "Python 3.8 or higher is required to run this bot." >&2
+ exit 1
+ fi
+ if ! command -v ffmpeg &>/dev/null || ! command -v mediainfo &>/dev/null || ! command -v neofetch &>/dev/null || ! command -v git &>/dev/null; then
+ echo -e "Some dependencies aren't installed. Please install ffmpeg, mediainfo, neofetch and git to run this bot." >&2
+ exit 1
+ fi
+ fi
}
-clone_repo(){
- if [ ! $BRANCH ]
- then export BRANCH="main"
+check_python() {
+ # check if python is installed
+ if ! command -v python3 &>/dev/null; then
+ echo -e "Python3 isn't installed. Please install python3.8 or higher to run this bot."
+ exit 1
+ elif ! command -v python &>/dev/null; then
+ echo -e "Python3 isn't installed. Please install python3.8 or higher to run this bot."
+ exit 1
+ fi
+ if [ $(python3 -c "import sys; print(sys.version_info[1])") -lt 8 ]; then
+ echo -e "Python 3.8 or higher is required to run this bot."
+ exit 1
+ elif [ $(python -c "import sys; print(sys.version_info[1])") -lt 3 ]; then
+ if [ $(python -c "import sys; print(sys.version_info[1])") -lt 8 ]; then
+ echo -e "Python 3.8 or higher is required to run this bot."
+ exit 1
+ fi
fi
- if [ -d $DIR ]
- then
- echo -e $DIR "Already exists.."
+}
+
+clone_repo() {
+ # check if pyultroid, startup, plugins folders exist
+ cd $DIR
+ if [ -d $DIR ]; then
+ if [ -d $DIR/.git ]; then
+ echo -e "Updating Ultroid ${BRANCH}... "
cd $DIR
git pull
currentbranch="$(git rev-parse --abbrev-ref HEAD)"
- if [ currentbranch != $BRANCH ]
- then
- git checkout $BRANCH
+ if [ ! $BRANCH ]; then
+ export BRANCH=$currentbranch
fi
- if [ -d "addons" ]
- then
- cd addons
- git pull
- fi
- return
+ case $currentbranch in
+ $BRANCH)
+ # do nothing
+ ;;
+ *)
+ echo -e "Switching to branch ${BRANCH}... "
+ echo -e $currentbranch
+ git checkout $BRANCH
+ ;;
+ esac
+ else
+ rm -rf $DIR
+ exit 1
+ fi
+ if [ -d "addons" ]; then
+ cd addons
+ git pull
+ fi
+ return
+ else
+ if [ ! $BRANCH ]; then
+ export BRANCH="main"
+ fi
+ mkdir -p $DIR
+ echo -e "Cloning Ultroid ${BRANCH}... "
+ git clone -b $BRANCH $REPO $DIR
fi
- echo -e "Cloning Ultroid ${BRANCH}... "
- git clone -b $BRANCH $REPO $DIR
}
-install_requirements(){
- pip install --upgrade pip
+install_requirements() {
+ pip3 install -q --upgrade pip
echo -e "\n\nInstalling requirements... "
pip3 install -q --no-cache-dir -r $DIR/requirements.txt
pip3 install -q -r $DIR/resources/startup/optional-requirements.txt
}
-railways_dep(){
- if [ $RAILWAY_STATIC_URL ]
- then
- echo -e "Installing YouTube dependency... "
- pip3 install -q yt-dlp
+railways_dep() {
+ if [ $RAILWAY_STATIC_URL ]; then
+ echo -e "Installing YouTube dependency... "
+ pip3 install -q yt-dlp
fi
}
-misc_install(){
- if [ $OKTETO_TOKEN ]
- then
- echo -e "Installing Okteto-CLI... "
- curl https://get.okteto.com -sSfL | sh
- elif [ $VCBOT ]
- then
- if [ -d $DIR/vcbot ]
- then
- cd $DIR/vcbot
- git pull
- else
- echo -e "Cloning VCBOT.."
- git clone https://github.com/TeamUltroid/VcBot $DIR/vcbot
- fi
- pip3 install pytgcalls>=3.0.0.dev21 && pip3 install av -q --no-binary av
+misc_install() {
+ if [ $SETUP_PLAYWRIGHT ]
+ then
+ echo -e "Installing playwright."
+ pip3 install playwright
+ playwright install
+ fi
+ if [ $OKTETO_TOKEN ]; then
+ echo -e "Installing Okteto-CLI... "
+ curl https://get.okteto.com -sSfL | sh
+ elif [ $VCBOT ]; then
+ if [ -d $DIR/vcbot ]; then
+ cd $DIR/vcbot
+ git pull
+ else
+ echo -e "Cloning VCBOT.."
+ git clone https://github.com/TeamUltroid/VcBot $DIR/vcbot
+ fi
+ pip3 install pytgcalls==3.0.0.dev23 && pip3 install av -q --no-binary av
fi
}
-dep_install(){
+dep_install() {
echo -e "\n\nInstalling DB Requirement..."
- if [ $MONGO_URI ]
- then
- pip3 install -q pymongo[srv]
- elif [ $DATABASE_URL ]
- then
- pip3 install -q psycopg2-binary
- elif [ $REDIS_URI ]
- then
- pip3 install -q redis hiredis
+ if [ $MONGO_URI ]; then
+ echo -e " Installing MongoDB Requirements..."
+ pip3 install -q pymongo[srv]
+ elif [ $DATABASE_URL ]; then
+ echo -e " Installing PostgreSQL Requirements..."
+ pip3 install -q psycopg2-binary
+ elif [ $REDIS_URI ]; then
+ echo -e " Installing Redis Requirements..."
+ pip3 install -q redis hiredis
fi
}
-main(){
+main() {
+ echo -e "Starting Ultroid Setup..."
+ if [ -d "pyUltroid" ] && [ -d "resources" ] && [ -d "plugins" ]; then
+ DIR=$CURRENT_DIR
+ fi
+ if [ -f $ENV_FILE_PATH ]
+ then
+ set -a
+ source <(cat $ENV_FILE_PATH | sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g")
+ set +a
+ cp $ENV_FILE_PATH .env
+ fi
+ (check_dependencies)
+ (check_python)
(clone_repo)
(install_requirements)
(railways_dep)
(dep_install)
(misc_install)
+ echo -e "\n\nSetup Completed."
}
-main
+if [ $NO_ROOT ]; then
+ echo -e "Running with non root"
+ main
+ return 0
+elif [ -t 0 ]; then
+ unameOut="$(uname -s)"
+ case "${unameOut}" in
+ Linux*) machine=Linux;;
+ Darwin*) machine=Mac;;
+ CYGWIN*) machine=Cygwin;;
+ MINGW*) machine=MinGw;;
+ *) machine="UNKNOWN:${unameOut}"
+ esac
+ if machine != "Linux"; then
+ echo -e "This script is only for Linux. Please use the Windows installer."
+ exit 1
+ fi
+ # check if sudo is installed
+ if ! command -v sudo &>/dev/null; then
+ echo -e "Sudo isn't installed. Please install sudo to run this bot."
+ exit 1
+ fi
+ sudo echo "Sudo permission granted."
+ main
+else
+ echo "Not an interactive terminal, skipping sudo."
+ # run main function
+ main
+fi
diff --git a/plugins/__init__.py b/plugins/__init__.py
index 66476549322bb360f568caf640a5a229c6b6ad84..e4314ca9df303d362651a8a786858aefde58bad6 100644
--- a/plugins/__init__.py
+++ b/plugins/__init__.py
@@ -20,18 +20,23 @@ from pyUltroid._misc._decorators import ultroid_cmd
from pyUltroid._misc._wrappers import eod, eor
from pyUltroid.dB import DEVLIST, ULTROID_IMAGES
from pyUltroid.fns.helper import *
-from pyUltroid.fns.info import *
from pyUltroid.fns.misc import *
from pyUltroid.fns.tools import *
+from pyUltroid.startup._database import _BaseDatabase as Database
from pyUltroid.version import __version__, ultroid_version
from strings import get_help, get_string
+udB: Database
+
Redis = udB.get_key
con = TgConverter
quotly = Quotly()
OWNER_NAME = ultroid_bot.full_name
OWNER_ID = ultroid_bot.uid
+ultroid_bot: UltroidClient
+asst: UltroidClient
+
LOG_CHANNEL = udB.get_key("LOG_CHANNEL")
diff --git a/plugins/_chatactions.py b/plugins/_chatactions.py
index 94fd7b34f0889c8d6288b596ca7d0e23966a57fd..9f7f6965f21a676965b70c573fe70f54bf27f80d 100644
--- a/plugins/_chatactions.py
+++ b/plugins/_chatactions.py
@@ -13,6 +13,7 @@ from telethon.tl.functions.channels import GetParticipantRequest
from telethon.utils import get_display_name
from pyUltroid.dB import stickers
+from pyUltroid.dB.echo_db import check_echo
from pyUltroid.dB.forcesub_db import get_forcesetting
from pyUltroid.dB.gban_mute_db import is_gbanned
from pyUltroid.dB.greetings_db import get_goodbye, get_welcome, must_thank
@@ -90,8 +91,7 @@ async def DummyHandler(ult):
user.id,
view_messages=False,
)
- await ult.client.send_message(
- chat.id,
+ await ult.respond(
f'**@UltroidBans:** Banned user detected and banned!\n`{str(is_banned)}`.\nBan reason: {is_banned["reason"]}',
)
@@ -196,8 +196,13 @@ async def DummyHandler(ult):
@ultroid_bot.on(events.NewMessage(incoming=True))
async def chatBot_replies(e):
sender = await e.get_sender()
- if not isinstance(sender, types.User):
+ if not isinstance(sender, types.User) or sender.bot:
return
+ if check_echo(e.chat_id, e.sender_id):
+ try:
+ await e.respond(e)
+ except Exception as er:
+ LOGS.exception(er)
key = udB.get_key("CHATBOT_USERS") or {}
if e.text and key.get(e.chat_id) and sender.id in key[e.chat_id]:
msg = await get_chatbot_reply(e.message.message)
@@ -206,12 +211,10 @@ async def chatBot_replies(e):
await asyncio.sleep(sleep)
await e.reply(msg)
chat = await e.get_chat()
- if e.is_group and not sender.bot:
- if sender.username:
- await uname_stuff(e.sender_id, sender.username, sender.first_name)
- elif e.is_private and not sender.bot:
- if chat.username:
- await uname_stuff(e.sender_id, chat.username, chat.first_name)
+ if e.is_group and sender.username:
+ await uname_stuff(e.sender_id, sender.username, sender.first_name)
+ elif e.is_private and chat.username:
+ await uname_stuff(e.sender_id, chat.username, chat.first_name)
if detector and is_profan(e.chat_id) and e.text:
x, y = detector(e.text)
if y:
@@ -220,7 +223,7 @@ async def chatBot_replies(e):
@ultroid_bot.on(events.Raw(types.UpdateUserName))
async def uname_change(e):
- await uname_stuff(e.user_id, e.username, e.first_name)
+ await uname_stuff(e.user_id, e.usernames[0] if e.usernames else None, e.first_name)
async def uname_stuff(id, uname, name):
diff --git a/plugins/_userlogs.py b/plugins/_userlogs.py
index d2fcdde1ce7d52bb03129843e41c19e7cb0182fb..61491445d55eed2e3fe018872e3ee43da55d2bef 100644
--- a/plugins/_userlogs.py
+++ b/plugins/_userlogs.py
@@ -51,10 +51,7 @@ async def all_messages_catcher(e):
return
if not udB.get_key("TAG_LOG"):
return
- try:
- NEEDTOLOG = int(udB.get_key("TAG_LOG"))
- except Exception:
- return LOGS.info(get_string("userlogs_1"))
+ NEEDTOLOG = udB.get_key("TAG_LOG")
buttons = await parse_buttons(e)
try:
sent = await asst.send_message(NEEDTOLOG, e.message, buttons=buttons)
@@ -63,7 +60,8 @@ async def all_messages_catcher(e):
else:
TAG_EDITS.update({e.chat_id: {e.id: {"id": sent.id, "msg": e}}})
tag_add(sent.id, e.chat_id, e.id)
- except MediaEmptyError:
+ except MediaEmptyError as er:
+ LOGS.debug(f"handling {er}.")
try:
msg = await asst.get_messages(e.chat_id, ids=e.id)
sent = await asst.send_message(NEEDTOLOG, msg, buttons=buttons)
@@ -89,7 +87,8 @@ async def all_messages_catcher(e):
except Exception as er:
LOGS.exception(er)
await asst.send_message(NEEDTOLOG, get_string("com_4"), buttons=buttons)
- except (PeerIdInvalidError, ValueError):
+ except (PeerIdInvalidError, ValueError) as er:
+ LOGS.exception(er)
try:
CACHE_SPAM[NEEDTOLOG]
except KeyError:
@@ -225,7 +224,7 @@ async def when_added_or_joined(event):
text = f"#APPROVAL_LOG\n\n{inline_mention(user)} just got Chat Join Approval to {chat}."
else:
text = f"#JOIN_LOG\n\n{inline_mention(user)} just joined {chat}."
- await asst.send_message(int(udB.get_key("LOG_CHANNEL")), text, buttons=buttons)
+ await asst.send_message(udB.get_key("LOG_CHANNEL"), text, buttons=buttons)
asst.add_event_handler(
diff --git a/plugins/_wspr.py b/plugins/_wspr.py
index d30da90c12c3170a30311c4fe430aafdfc8d2923..19323558ca68e65bae9215730a58205567c3bf09 100644
--- a/plugins/_wspr.py
+++ b/plugins/_wspr.py
@@ -66,7 +66,7 @@ async def _(e):
if not isinstance(logi, types.User):
raise ValueError("Invalid Username.")
except IndexError:
- sur = e.builder.article(
+ sur = await e.builder.article(
title="Give Username",
description="You Didn't Type Username or id.",
text="You Didn't Type Username or id.",
@@ -74,7 +74,7 @@ async def _(e):
return await e.answer([sur])
except ValueError as er:
LOGS.exception(er)
- sur = e.builder.article(
+ sur = await e.builder.article(
title="User Not Found",
description="Make sure username or id is correct.",
text="Make sure username or id is correct.",
@@ -83,14 +83,23 @@ async def _(e):
try:
desc = zzz[2]
except IndexError:
- sur = e.builder.article(title="Type ur msg", text="You Didn't Type Your Msg")
+ sur = await e.builder.article(
+ title="Type ur msg", text="You Didn't Type Your Msg"
+ )
return await e.answer([sur])
button = [
- Button.inline("Secret Msg", data=f"dd_{e.id}"),
- Button.inline("Delete Msg", data=f"del_{e.id}"),
+ [
+ Button.inline("Secret Msg", data=f"dd_{e.id}"),
+ Button.inline("Delete Msg", data=f"del_{e.id}"),
+ ],
+ [
+ Button.switch_inline(
+ "New", query=f"wspr {logi.username or logi.id}", same_peer=True
+ )
+ ],
]
us = logi.username or logi.first_name
- sur = e.builder.article(
+ sur = await e.builder.article(
title=logi.first_name,
description=desc,
text=get_string("wspr_1").format(us),
diff --git a/plugins/admintools.py b/plugins/admintools.py
index 75224dc0cb5879f294c75f2a50ebc29d0ed73cf7..bb4c6d0e71c20e903d4a5c24575283433b1a4247 100644
--- a/plugins/admintools.py
+++ b/plugins/admintools.py
@@ -20,18 +20,9 @@ from telethon.utils import get_display_name
from pyUltroid.dB import DEVLIST
from pyUltroid.fns.admins import ban_time
+from pyUltroid.fns.info import get_uinfo
-from . import (
- HNDLR,
- LOGS,
- eod,
- eor,
- get_string,
- get_uinfo,
- inline_mention,
- types,
- ultroid_cmd,
-)
+from . import HNDLR, LOGS, eod, eor, get_string, inline_mention, types, ultroid_cmd
@ultroid_cmd(
diff --git a/plugins/afk.py b/plugins/afk.py
index 99d466f9055031ba21e53174fdc7bd813138a405..30028387e8f912cca842f4608d53d552bc52cb9d 100644
--- a/plugins/afk.py
+++ b/plugins/afk.py
@@ -16,7 +16,7 @@ from telegraph import upload_file as uf
from telethon import events
from pyUltroid.dB.afk_db import add_afk, del_afk, is_afk
-from pyUltroid.dB.pmpermit_db import is_approved
+from pyUltroid.dB.base import KeyManager
from . import (
LOG_CHANNEL,
@@ -32,6 +32,8 @@ from . import (
old_afk_msg = []
+is_approved = KeyManager("PMPERMIT", cast=list).contains
+
@ultroid_cmd(pattern="afk( (.*)|$)", owner_only=True)
async def set_afk(event):
diff --git a/plugins/audiotools.py b/plugins/audiotools.py
index 79ea7ce85454256a39225cb928e63bd84234aed2..ab87e86e907ee687ae8ec427db0f92c42e1a4d66 100644
--- a/plugins/audiotools.py
+++ b/plugins/audiotools.py
@@ -151,12 +151,10 @@ async def ex_aud(e):
except FileNotFoundError:
return await eor(msg, get_string("audiotools_9"))
- await e.client.send_file(
- e.chat_id,
- fo,
- caption=get_string("audiotools_10"),
+ await e.reply(
+ get_string("audiotools_10"),
+ file=fo,
thumb=ULTConfig.thumb,
attributes=attributes,
- reply_to=e.reply_to_msg_id,
)
await msg.delete()
diff --git a/plugins/autoban.py b/plugins/autoban.py
index ce64f1edd40c326d987ad38002d29052b8ead670..0c3e2e3a37f683049225882ab0a86ee6815274f6 100644
--- a/plugins/autoban.py
+++ b/plugins/autoban.py
@@ -10,43 +10,26 @@ from . import get_help
__doc__ = get_help("help_autoban")
from telethon import events
-from telethon.tl.types import Channel
-from pyUltroid.dB import autoban_db, dnd_db
-from pyUltroid.fns.admins import get_update_linked_chat
+from pyUltroid.dB.base import KeyManager
-from . import LOGS, asst, get_string, inline_mention, ultroid_bot, ultroid_cmd
+from . import LOGS, asst, ultroid_bot, ultroid_cmd
+Keym = KeyManager("DND_CHATS", cast=list)
-async def dnd_func(event):
- if event.chat_id in dnd_db.get_dnd_chats():
- for user in event.users:
- try:
- await (
- await event.client.kick_participant(event.chat_id, user)
- ).delete()
- except Exception as ex:
- LOGS.error("Error in DND:")
- LOGS.exception(ex)
- await event.delete()
+
+def join_func(e):
+ return e.user_joined and Keym.contains(e.chat_id)
-async def channel_del(event):
- if not autoban_db.is_autoban_enabled(event.chat_id):
- return
- if autoban_db.is_whitelisted(event.chat_id, event.sender_id):
- return
- linked = await get_update_linked_chat(event)
- if linked == event.sender.id:
- return
- if event.chat.creator or event.chat.admin_rights.ban_users:
+async def dnd_func(event):
+ for user in event.users:
try:
- await event.client.edit_permissions(
- event.chat_id, event.sender_id, view_messages=False
- )
- except Exception as er:
- LOGS.exception(er)
- await event.try_delete()
+ await (await event.client.kick_participant(event.chat_id, user)).delete()
+ except Exception as ex:
+ LOGS.error("Error in DND:")
+ LOGS.exception(ex)
+ await event.delete()
@ultroid_cmd(
@@ -59,84 +42,18 @@ async def channel_del(event):
async def _(event):
match = event.pattern_match.group(1)
if match == "on":
- if dnd_db.chat_in_dnd(event.chat_id):
+ if Keym.contains(event.chat_id):
return await event.eor("`Chat already in do not disturb mode.`", time=3)
- dnd_db.add_dnd(event.chat_id)
- event.client.add_handler(
- dnd_func, events.ChatAction(func=lambda x: x.user_joined)
- )
+ Keym.add(event.chat_id)
+ event.client.add_handler(dnd_func, events.ChatAction(func=join_func))
await event.eor("`Do not disturb mode activated for this chat.`", time=3)
elif match == "off":
- if not dnd_db.chat_in_dnd(event.chat_id):
+ if not Keym.contains(event.chat_id):
return await event.eor("`Chat is not in do not disturb mode.`", time=3)
- dnd_db.del_dnd(event.chat_id)
+ Keym.remove(event.chat_id)
await event.eor("`Do not disturb mode deactivated for this chat.`", time=3)
-@ultroid_cmd(pattern="cban$", admins_only=True)
-async def ban_cha(ult):
- if autoban_db.is_autoban_enabled(ult.chat_id):
- autoban_db.del_channel(ult.chat_id)
- return await ult.eor("`Disabled Auto ChannelBan...`")
- if not (
- ult.chat.creator
- or (ult.chat.admin_rights.delete_messages or ult.chat.admin_rights.ban_users)
- ):
- return await ult.eor(
- "You are missing required admin rights!\nYou can't use ChannelBan without Ban/del privilege..`"
- )
- autoban_db.add_channel(ult.chat_id)
- await ult.eor("`Enabled Auto ChannelBan Successfully!`")
- ult.client.add_handler(
- channel_del,
- events.NewMessage(
- func=lambda x: not x.is_private and isinstance(x.sender, Channel)
- ),
- )
-
-
-@ultroid_cmd(pattern="(list|add|rem)wl( (.*)|$)")
-async def do_magic(event):
- match = event.pattern_match.group(1)
- msg = await event.eor(get_string("com_1"))
- if match == "list":
- cha = autoban_db.get_whitelisted_channels(event.chat_id)
- if not cha:
- return await msg.edit("`No Whitelisted channels for current chat.`")
- Msg = "**Whitelist Channels in Current Chat**\n\n"
- for ch in cha:
- Msg += f"(`{ch}`) "
- try:
- Msg += inline_mention(await event.client.get_entity(ch))
- except Exception:
- Msg += "\n"
- return await msg.edit(Msg)
- usea = event.pattern_match.group(2).strip()
- if not usea:
- return await Msg.edit(
- "`Please provide a channel username/id to add/remove to/from whitelist..`"
- )
- try:
- u_id = await event.client.parse_id(usea)
- cha = await event.client.get_entity(u_id)
- except Exception as er:
- LOGS.exception(er)
- return await msg.edit(f"Error Broke Out!\n`{er}`")
- if match == "add":
- autoban_db.add_to_whitelist(event.chat_id, u_id)
- return await msg.edit(f"`Added` {inline_mention(cha)} `to WhiteList..`")
- autoban_db.del_from_whitelist(event.chat_id, u_id)
- await msg.edit(f"`Removed` {inline_mention(cha)} `from WhiteList.`")
-
-
-if dnd_db.get_dnd_chats():
- ultroid_bot.add_handler(dnd_func, events.ChatAction(func=lambda x: x.user_joined))
- asst.add_handler(dnd_func, events.ChatAction(func=lambda x: x.user_joined))
-
-if autoban_db.get_all_channels():
- ultroid_bot.add_handler(
- channel_del,
- events.NewMessage(
- func=lambda x: not x.is_private and isinstance(x.sender, Channel)
- ),
- )
+if Keym.get():
+ ultroid_bot.add_handler(dnd_func, events.ChatAction(func=join_func))
+ asst.add_handler(dnd_func, events.ChatAction(func=join_func))
diff --git a/plugins/autopic.py b/plugins/autopic.py
index 17faeb9e0518ac6978c4daf6db11d10783f00dcc..a3ca45231b0b993a6d8a038fbf051cc468484109 100644
--- a/plugins/autopic.py
+++ b/plugins/autopic.py
@@ -9,12 +9,12 @@
import asyncio
import os
import random
-from glob import glob
from random import shuffle
from telethon.tl.functions.photos import UploadProfilePhotoRequest
-from pyUltroid.fns.google_image import googleimagesdownload
+from pyUltroid.fns.helper import download_file
+from pyUltroid.fns.tools import get_google_images
from . import LOGS, get_help, get_string, udB, ultroid_bot, ultroid_cmd
@@ -59,35 +59,20 @@ async def autopic(e):
if search := udB.get_key("AUTOPIC"):
- gi = googleimagesdownload()
- args = {
- "keywords": search,
- "limit": 50,
- "format": "jpg",
- "output_directory": "./resources/downloads/",
- }
- images = []
- if os.path.exists(f"./resources/downloads/{search}"):
- images = glob(f"resources/downloads/{search}/*")
+ images = {}
sleep = udB.get_key("SLEEP_TIME") or 1221
async def autopic_func():
- if udB.get_key("AUTOPIC") != search:
+ search = udB.get_key("AUTOPIC")
+ if images.get(search) is None:
+ images[search] = await get_google_images(search)
+ if not images.get(search):
return
- if not images:
- try:
- pth = await gi.download(args)
- ok = pth[0][search]
- images.extend(ok)
- except Exception as er:
- LOGS.exception(er)
- return
- else:
- ok = images
- img = random.choice(ok)
- file = await ultroid_bot.upload_file(img)
+ img = random.choice(images[search])
+ filee = await download_file(img["original"], "resources/downloads/autopic.jpg")
+ file = await ultroid_bot.upload_file(filee)
await ultroid_bot(UploadProfilePhotoRequest(file))
- shuffle(ok)
+ os.remove(filee)
try:
from apscheduler.schedulers.asyncio import AsyncIOScheduler
diff --git a/plugins/beautify.py b/plugins/beautify.py
index 023116c8f25d7f58f3af973222ceec868907b4ee..939da5c256548dc44e7c2f26ff076af901b4b425 100644
--- a/plugins/beautify.py
+++ b/plugins/beautify.py
@@ -10,11 +10,12 @@ from . import get_help
__doc__ = get_help("help_beautify")
+import os
import random
from telethon.utils import get_display_name
-from . import Carbon, eor, get_string, inline_mention, os, ultroid_cmd
+from . import Carbon, ultroid_cmd, get_string, inline_mention
_colorspath = "resources/colorlist.txt"
@@ -28,7 +29,7 @@ else:
@ultroid_cmd(
pattern="(rc|c)arbon",
)
-async def crbn(event):
+async def cr_bn(event):
xxxx = await event.eor(get_string("com_1"))
te = event.pattern_match.group(1)
col = random.choice(all_col) if te[0] == "r" else "White"
@@ -45,8 +46,11 @@ async def crbn(event):
try:
code = event.text.split(" ", maxsplit=1)[1]
except IndexError:
- return await eor(xxxx, get_string("carbon_2"))
+ return await xxxx.eor(get_string("carbon_2"))
xx = await Carbon(code=code, file_name="ultroid_carbon", backgroundColor=col)
+ if isinstance(xx, dict):
+ await xxxx.edit(f"`{xx}`")
+ return
await xxxx.delete()
await event.reply(
f"Carbonised by {inline_mention(event.sender)}",
@@ -77,7 +81,7 @@ async def crbn(event):
code = match[1]
match = match[0]
except IndexError:
- return await eor(msg, get_string("carbon_2"))
+ return await msg.eor(get_string("carbon_2"))
xx = await Carbon(code=code, backgroundColor=match)
await msg.delete()
await event.reply(
@@ -125,7 +129,7 @@ async def pass_on(ult):
theme = random.choice(RaySoTheme)
if ult.is_reply:
msg = await ult.get_reply_message()
- text = msg.text
+ text = msg.message
title = get_display_name(msg.sender)
await ult.reply(
file=await Carbon(text, rayso=True, title=title, theme=theme, darkMode=dark)
diff --git a/plugins/blacklist.py b/plugins/blacklist.py
index 306351eb66129ba4a19741965fffe5ff2e14bde2..ac31c8d265cbeb7ee8ee9e881658988590a33a6b 100644
--- a/plugins/blacklist.py
+++ b/plugins/blacklist.py
@@ -57,14 +57,12 @@ async def lsnote(e):
async def blacklist(e):
if x := get_blacklist(e.chat_id):
- for z in e.text.lower().split():
- for zz in x:
- if z == zz:
- try:
- await e.delete()
- break
- except BaseException:
- break
+ text = e.text.lower().split()
+ if any((z in text) for z in x):
+ try:
+ await e.delete()
+ except BaseException:
+ pass
if udB.get_key("BLACKLIST_DB"):
diff --git a/plugins/bot.py b/plugins/bot.py
index 792511407c33b1fccd5e787b671ca9e5d1b4a27a..6886de72d4352f9311390580bea9eb30214f8d79 100644
--- a/plugins/bot.py
+++ b/plugins/bot.py
@@ -84,7 +84,7 @@ The Ultroid Userbot
â Telethon - {}
"""
-in_alive = "{}\n\nđ Ultroid Version -> {}
\nđ PyUltroid -> {}
\nđ Python -> {}
\nđ Uptime -> {}
\nđ Branch -> [ {} ]\n\n⢠Join @TeamUltroid"
+in_alive = "{}\n\nđ Ultroid Version -> {}
\nđ PyUltroid -> {}
\nđ Python -> {}
\nđ Uptime -> {}
\nđ Branch ->[ {} ]\n\n⢠Join @TeamUltroid"
@callback("alive")
@@ -243,6 +243,9 @@ async def _(event):
code=code,
backgroundColor=choice(ATRA_COL),
)
+ if isinstance(file, dict):
+ await event.eor(f"`{file}`")
+ return
await event.reply("**Ultroid Logs.**", file=file)
elif opt == "open":
with open("ultroid.log", "r") as f:
@@ -296,7 +299,7 @@ async def inline_alive(ult):
]
return await ult.answer(results)
except BaseException as er:
- LOGS.info(er)
+ LOGS.exception(er)
result = [
await builder.article(
"Alive", text=als, parse_mode="html", link_preview=False, buttons=buttons
diff --git a/plugins/broadcast.py b/plugins/broadcast.py
index 6e97036ba2e56bb652cc69b106ee9ad067c0db51..a10c996d556370f39ba0fefd5e3a92374eeeb2cb 100644
--- a/plugins/broadcast.py
+++ b/plugins/broadcast.py
@@ -15,10 +15,12 @@ import io
from telethon.utils import get_display_name
-from pyUltroid.dB.broadcast_db import *
+from pyUltroid.dB.base import KeyManager
from . import HNDLR, LOGS, eor, get_string, udB, ultroid_bot, ultroid_cmd
+KeyM = KeyManager("BROADCAST", cast=list)
+
@ultroid_cmd(
pattern="addch( (.*)|$)",
@@ -40,14 +42,14 @@ async def broadcast_adder(event):
if (
i.broadcast
and (i.creator or i.admin_rights)
- and not is_channel_added(i.id)
+ and not KeyM.contains(i.id)
):
new += 1
cid = f"-100{i.id}"
- add_channel(int(cid))
+ KeyM.add(int(cid))
except Exception as Ex:
LOGS.exception(Ex)
- await x.edit(get_string("bd_3").format(get_no_channels(), new))
+ await x.edit(get_string("bd_3").format(KeyM.count(), new))
return
if event.reply_to_msg_id:
previous_message = await event.get_reply_message()
@@ -56,8 +58,8 @@ async def broadcast_adder(event):
length = len(lines)
for line_number in range(1, length - 2):
channel_id = lines[line_number][4:-1]
- if not is_channel_added(channel_id):
- add_channel(channel_id)
+ if not KeyM.contains(channel_id):
+ KeyM.add(channel_id)
await x.edit(get_string("bd_4"))
await asyncio.sleep(3)
await event.delete()
@@ -65,9 +67,9 @@ async def broadcast_adder(event):
chat_id = event.chat_id
if chat_id == udB.get_key("LOG_CHANNEL"):
return
- if is_channel_added(chat_id):
+ if KeyM.contains(chat_id):
await x.edit(get_string("bd_6"))
- elif xx := add_channel(chat_id):
+ elif xx := KeyM.add(chat_id):
await x.edit(get_string("bd_5"))
else:
await x.edit(get_string("sf_8"))
@@ -87,8 +89,8 @@ async def broadcast_remover(event):
udB.del_key("BROADCAST")
await x.edit("Database cleared.")
return
- if is_channel_added(chat_id):
- rem_channel(chat_id)
+ if KeyM.contains(chat_id):
+ KeyM.remove(chat_id)
await x.edit(get_string("bd_7"))
else:
await x.edit(get_string("bd_9"))
@@ -101,8 +103,8 @@ async def broadcast_remover(event):
)
async def list_all(event):
x = await event.eor(get_string("com_1"))
- channels = get_channels()
- num = len(channels)
+ channels = KeyM.get()
+ num = KeyM.count()
if not channels:
return await eor(x, "No chats were added.", time=5)
msg = "Channels in database:\n"
@@ -137,14 +139,13 @@ async def forw(event):
if not event.is_reply:
return await event.eor(get_string("ex_1"))
ultroid_bot = event.client
- channels = get_channels()
+ channels = KeyM.get()
x = await event.eor("Sending...")
if not channels:
return await x.edit(f"Please add channels by using `{HNDLR}add` in them.")
error_count = 0
sent_count = 0
- if event.reply_to_msg_id:
- previous_message = await event.get_reply_message()
+ previous_message = await event.get_reply_message()
error_count = 0
for channel in channels:
try:
@@ -156,7 +157,7 @@ async def forw(event):
except Exception:
try:
await ultroid_bot.send_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
f"Error in sending at {channel}.",
)
except Exception as Em:
@@ -168,7 +169,7 @@ async def forw(event):
await x.edit(f"{sent_count} messages sent with {error_count} errors.")
if error_count > 0:
await ultroid_bot.send_message(
- int(udB.get_key("LOG_CHANNEL")), f"{error_count} Errors"
+ udB.get_key("LOG_CHANNEL"), f"{error_count} Errors"
)
@@ -180,7 +181,7 @@ async def sending(event):
x = await event.eor(get_string("com_1"))
if not event.is_reply:
return await x.edit(get_string("ex_1"))
- channels = get_channels()
+ channels = KeyM.get()
if not channels:
return await x.edit(f"Please add channels by using `{HNDLR}add` in them.")
await x.edit("Sending....")
@@ -199,7 +200,6 @@ async def sending(event):
f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}",
)
except Exception as error:
-
await ultroid_bot.send_message(
udB.get_key("LOG_CHANNEL"),
f"Error in sending at {channel}.\n\n{error}",
@@ -211,6 +211,6 @@ async def sending(event):
await x.edit(f"{sent_count} messages sent with {error_count} errors.")
if error_count > 0:
await ultroid_bot.send_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
f"{error_count} Errors",
)
diff --git a/plugins/channelhacks.py b/plugins/channelhacks.py
index b814d2432e305e6a5d8de595289357700b76732c..712c18b08a6fc18dafc34ed2b6f929dcb4fa0651 100644
--- a/plugins/channelhacks.py
+++ b/plugins/channelhacks.py
@@ -15,32 +15,23 @@ import io
from telethon.errors.rpcerrorlist import FloodWaitError
from telethon.utils import get_display_name, get_peer_id
-from pyUltroid.dB.ch_db import (
- add_destination,
- add_source_channel,
- get_destinations,
- get_no_destinations,
- get_no_source_channels,
- get_source_channels,
- is_destination_added,
- is_source_channel_added,
- rem_destination,
- rem_source_channel,
-)
+from pyUltroid.dB.base import KeyManager
from . import LOGS, asst, eor, events, get_string, udB, ultroid_bot, ultroid_cmd
ERROR = {}
+SourceM = KeyManager("CH_SOURCE", cast=list)
+DestiM = KeyManager("CH_DESTINATIONS", cast=list)
async def autopost_func(e):
if not udB.get_key("AUTOPOST"):
return
- x = get_source_channels()
+ x = SourceM.get()
th = await e.get_chat()
if get_peer_id(th) not in x:
return
- y = get_destinations()
+ y = DestiM.get()
for ys in y:
try:
await e.client.send_message(int(ys), e.message)
@@ -91,11 +82,11 @@ async def source(e):
return
else:
y = e.chat_id
- if not is_source_channel_added(y):
- add_source_channel(y)
+ if not SourceM.contains(y):
+ SourceM.add(y)
await e.eor(get_string("cha_2"))
ultroid_bot.add_handler(autopost_func, events.NewMessage())
- elif is_source_channel_added(y):
+ else:
await e.eor(get_string("cha_3"))
@@ -116,24 +107,21 @@ async def dd(event):
return
else:
y = event.chat_id
- if is_source_channel_added(y):
- rem_source_channel(y)
- await eor(x, get_string("cha_5"), time=3)
- elif is_source_channel_added(y):
- rem_source_channel(y)
+ if SourceM.contains(y):
+ SourceM.remove(y)
await eor(x, get_string("cha_5"), time=5)
- elif not is_source_channel_added(y):
+ else:
await eor(x, "Source channel is already removed from database. ", time=3)
@ultroid_cmd(pattern="listsource")
async def list_all(event):
x = await event.eor(get_string("com_1"))
- num = get_no_source_channels()
+ num = SourceM.count()
if not num:
return await eor(x, "No chats were added.", time=5)
msg = get_string("cha_8")
- channels = get_source_channels()
+ channels = SourceM.get()
for channel in channels:
name = ""
try:
@@ -141,18 +129,16 @@ async def list_all(event):
except BaseException:
name = ""
msg += f"\n=> **{name}** [`{channel}`]"
- msg += f"\nTotal {get_no_source_channels()} channels."
+ msg += f"\nTotal {num} channels."
if len(msg) > 4096:
MSG = msg.replace("*", "").replace("`", "")
with io.BytesIO(str.encode(MSG)) as out_file:
out_file.name = "channels.txt"
- await event.client.send_file(
- event.chat_id,
- out_file,
+ await event.reply(
+ "Channels in database",
+ file=out_file,
force_document=True,
allow_cache=False,
- caption="Channels in database",
- reply_to=event,
)
await x.delete()
else:
@@ -169,10 +155,10 @@ async def destination(e):
return
else:
y = e.chat_id
- if not is_destination_added(y):
- add_destination(y)
+ if not DestiM.contains(y):
+ DestiM.add(y)
await e.eor("Destination added succesfully")
- elif is_destination_added(y):
+ else:
await e.eor("Destination channel already added")
@@ -193,13 +179,10 @@ async def dd(event):
return
else:
y = event.chat_id
- if is_destination_added(y):
- rem_destination(y)
+ if DestiM.contains(y):
+ DestiM.remove(y)
await eor(x, "Destination removed from database")
- elif is_destination_added(y):
- rem_destination(y)
- await eor(x, "Destination removed from database", time=5)
- elif not is_destination_added(y):
+ else:
await eor(x, "Destination channel is already removed from database. ", time=5)
@@ -207,8 +190,8 @@ async def dd(event):
async def list_all(event):
ultroid_bot = event.client
x = await event.eor(get_string("com_1"))
- channels = get_destinations()
- num = get_no_destinations()
+ channels = DestiM.get()
+ num = len(channels)
if not num:
return await eor(x, "No chats were added.", time=5)
msg = get_string("cha_7")
@@ -219,7 +202,7 @@ async def list_all(event):
except BaseException:
name = ""
msg += f"\n=> **{name}** [`{channel}`]"
- msg += f"\nTotal {get_no_destinations()} channels."
+ msg += f"\nTotal {num} channels."
if len(msg) > 4096:
MSG = msg.replace("*", "").replace("`", "")
with io.BytesIO(str.encode(MSG)) as out_file:
diff --git a/plugins/chatbot.py b/plugins/chatbot.py
index 75ade5571ea3dadf310b2e5e7997ff4f61d939ec..705eeb2bd2f84e63fe402e80eb1e263889e304cf 100644
--- a/plugins/chatbot.py
+++ b/plugins/chatbot.py
@@ -12,7 +12,7 @@ __doc__ = get_help("help_chatbot")
from pyUltroid.fns.tools import get_chatbot_reply
-from . import eod, get_string, inline_mention, udB, ultroid_cmd, LOGS
+from . import LOGS, eod, get_string, inline_mention, udB, ultroid_cmd
@ultroid_cmd(pattern="repai")
@@ -67,8 +67,8 @@ async def chat_bot_fn(event, type_):
user_ = event.chat if event.is_private else None
if not user_:
return await eod(
- event,
- get_string("chab_1"),
+ event,
+ get_string("chab_1"),
)
key = udB.get_key("CHATBOT_USERS") or {}
chat = event.chat_id
diff --git a/plugins/cleanaction.py b/plugins/cleanaction.py
index b174789f3c270cdb6233ceba5fdb4d94620f04b9..d6efd0beb99878234aaf03541657c27cffb5ccd6 100644
--- a/plugins/cleanaction.py
+++ b/plugins/cleanaction.py
@@ -44,6 +44,5 @@ async def _(e):
except BaseException:
title = get_string("clan_3")
o += f"{x} {title}\n"
- await e.eor(o)
- else:
- await e.eor(get_string("clan_4"), time=5)
+ return await e.eor(o)
+ await e.eor(get_string("clan_4"), time=5)
diff --git a/plugins/devtools.py b/plugins/devtools.py
index f128c579c8003f17c414c01f7edff244dd10c382..bc3cd5a734fb6bef69cc639cee4ae4c2ebc82bc8 100644
--- a/plugins/devtools.py
+++ b/plugins/devtools.py
@@ -50,22 +50,28 @@ async def _(e):
x, y = await bash("neofetch|sed 's/\x1B\\[[0-9;\\?]*[a-zA-Z]//g' >> neo.txt")
if y and y.endswith("NOT_FOUND"):
return await xx.edit(f"Error: `{y}`")
- with open("neo.txt", "r") as neo:
+ with open("neo.txt", "r", encoding="utf-8") as neo:
p = (neo.read()).replace("\n\n", "")
haa = await Carbon(code=p, file_name="neofetch", backgroundColor=choice(ATRA_COL))
- await e.reply(file=haa)
- await xx.delete()
+ if isinstance(haa, dict):
+ await xx.edit(f"`{haa}`")
+ else:
+ await e.reply(file=haa)
+ await xx.delete()
remove("neo.txt")
@ultroid_cmd(pattern="bash", fullsudo=True, only_devs=True)
async def _(event):
- carb, yamlf = None, False
+ carb, rayso, yamlf = None, None, False
try:
cmd = event.text.split(" ", maxsplit=1)[1]
if cmd.split()[0] in ["-c", "--carbon"]:
cmd = cmd.split(maxsplit=1)[1]
carb = True
+ if cmd.split()[0] in ["-r", "--rayso"]:
+ cmd = cmd.split(maxsplit=1)[1]
+ rayso = True
except IndexError:
return await event.eor(get_string("devs_1"), time=10)
xx = await event.eor(get_string("com_1"))
@@ -88,6 +94,33 @@ async def _(event):
download=True,
backgroundColor=choice(ATRA_COL),
)
+ if isinstance(li, dict):
+ await xx.edit(
+ f"Unknown Response from Carbon: `{li}`\n\nstdout`:{stdout}`\nstderr: `{stderr}`"
+ )
+ return
+ url = f"https://graph.org{uf(li)[-1]}"
+ OUT = f"[\xad]({url}){OUT}"
+ out = "**⢠OUTPUT:**"
+ remove(li)
+ elif (rayso or udB.get_key("RAYSO_ON_BASH")) and (
+ event.is_private
+ or event.chat.admin_rights
+ or event.chat.creator
+ or event.chat.default_banned_rights.embed_links
+ ):
+ li = await Carbon(
+ code=stdout,
+ file_name="bash",
+ download=True,
+ backgroundColor=choice(ATRA_COL),
+ rayso=True,
+ )
+ if isinstance(li, dict):
+ await xx.edit(
+ f"Unknown Response from Carbon: `{li}`\n\nstdout`:{stdout}`\nstderr: `{stderr}`"
+ )
+ return
url = f"https://graph.org{uf(li)[-1]}"
OUT = f"[\xad]({url}){OUT}"
out = "**⢠OUTPUT:**"
@@ -136,7 +169,7 @@ bot = ultroid = ultroid_bot
class u:
- ...
+ _ = ""
def _parse_eval(value=None):
@@ -152,6 +185,14 @@ def _parse_eval(value=None):
return json_parser(value, indent=1)
except BaseException:
pass
+ elif isinstance(value, list):
+ newlist = "["
+ for index, child in enumerate(value):
+ newlist += "\n " + str(_parse_eval(child))
+ if index < len(value) - 1:
+ newlist += ","
+ newlist += "\n]"
+ return newlist
return str(value)
@@ -161,7 +202,8 @@ async def _(event):
cmd = event.text.split(maxsplit=1)[1]
except IndexError:
return await event.eor(get_string("devs_2"), time=5)
- silent, gsource, xx = False, False, None
+ xx = None
+ mode = ""
spli = cmd.split()
async def get_():
@@ -174,17 +216,19 @@ async def _(event):
if spli[0] in ["-s", "--silent"]:
await event.delete()
- silent = True
- cmd = await get_()
+ mode = "silent"
elif spli[0] in ["-n", "-noedit"]:
- cmd = await get_()
+ mode = "no-edit"
xx = await event.reply(get_string("com_1"))
elif spli[0] in ["-gs", "--source"]:
- gsource = True
+ mode = "gsource"
+ elif spli[0] in ["-ga", "--args"]:
+ mode = "g-args"
+ if mode:
cmd = await get_()
if not cmd:
return
- if not silent and not xx:
+ if not mode == "silent" and not xx:
xx = await event.eor(get_string("com_1"))
if black:
try:
@@ -220,13 +264,20 @@ async def _(event):
stderr = redirected_error.getvalue()
sys.stdout = old_stdout
sys.stderr = old_stderr
- if value and gsource:
+ if value:
try:
- exc = inspect.getsource(value)
+ if mode == "gsource":
+ exc = inspect.getsource(value)
+ elif mode == "g-args":
+ args = inspect.signature(value).parameters.values()
+ name = ""
+ if hasattr(value, "__name__"):
+ name = value.__name__
+ exc = f"**{name}**\n\n" + "\n ".join([str(arg) for arg in args])
except Exception:
exc = traceback.format_exc()
evaluation = exc or stderr or stdout or _parse_eval(value) or get_string("instu_4")
- if silent:
+ if mode == "silent":
if exc:
msg = f"⢠EVAL ERROR\n\n⢠CHAT: {get_display_name(event.chat)}
[{event.chat_id}
]"
msg += f"\n\nâ CODE:\n{cmd}
\n\nâ ERROR:\n{exc}
"
diff --git a/plugins/echo.py b/plugins/echo.py
index 168d256cd4a7ef053ca8cde2d93333c0c0730b3c..04c7dd4a0f37191acfb6f7ff2fe5af357e345ec1 100644
--- a/plugins/echo.py
+++ b/plugins/echo.py
@@ -14,7 +14,7 @@ from telethon.utils import get_display_name
from pyUltroid.dB.echo_db import add_echo, check_echo, list_echo, rem_echo
-from . import LOGS, events, ultroid_bot, ultroid_cmd
+from . import inline_mention, ultroid_cmd
@ultroid_cmd(pattern="addecho( (.*)|$)")
@@ -36,7 +36,7 @@ async def echo(e):
return await e.eor("Echo already activated for this user.", time=5)
add_echo(e.chat_id, user)
ok = await e.client.get_entity(user)
- user = f"[{get_display_name(ok)}](tg://user?id={ok.id})"
+ user = inline_mention(ok)
await e.eor(f"Activated Echo For {user}.")
@@ -63,16 +63,6 @@ async def rm(e):
await e.eor("Echo not activated for this user")
-@ultroid_bot.on(events.NewMessage(incoming=True))
-async def okk(e):
- if check_echo(e.chat_id, e.sender_id):
- try:
- ok = await e.client.get_messages(e.chat_id, ids=e.id)
- return await e.client.send_message(e.chat_id, ok)
- except Exception as er:
- LOGS.info(er)
-
-
@ultroid_cmd(pattern="listecho$")
async def lstecho(e):
if k := list_echo(e.chat_id):
diff --git a/plugins/fontgen.py b/plugins/fontgen.py
index 507de3b5c5cc2742b325844632003fe0faf76555..b284862e56790bc5b101072df6027abcc6189dab 100644
--- a/plugins/fontgen.py
+++ b/plugins/fontgen.py
@@ -11,7 +11,7 @@ __doc__ = get_help("help_fontgen")
import string
-from . import HNDLR, eod, ultroid_cmd
+from . import eod, ultroid_cmd
_default = string.ascii_letters
Fonts = {
diff --git a/plugins/giftools.py b/plugins/giftools.py
index abd60f711e153e58ebe07ac07321b7e19117101c..f9e2687bea850065dc343875ada5422188b35396 100644
--- a/plugins/giftools.py
+++ b/plugins/giftools.py
@@ -60,7 +60,7 @@ async def igif(e):
async def reverse_gif(event):
a = await event.get_reply_message()
if not (a and a.media) and "video" not in mediainfo(a.media):
- return await e.eor("`Reply To Video only`", time=5)
+ return await event.eor("`Reply To Video only`", time=5)
msg = await event.eor(get_string("com_1"))
file = await a.download_media()
await bash(f'ffmpeg -i "{file}" -vf reverse -af areverse reversed.mp4 -y')
diff --git a/plugins/glitch.py b/plugins/glitch.py
index eeb3c5671f3609811773004a249301533d0b4429..c59192f9916ffea39cdcee32ea3587ca7fb312a0 100644
--- a/plugins/glitch.py
+++ b/plugins/glitch.py
@@ -35,7 +35,7 @@ async def _(e):
else:
return await xx.eor(get_string("com_4"))
cmd = f"glitch_me gif --line_count 200 -f 10 -d 50 '{ok}' ult.gif"
- stdout, stderr = await bash(cmd)
+ await bash(cmd)
await e.reply(file="ult.gif", force_document=False)
await xx.delete()
os.remove(ok)
diff --git a/plugins/globaltools.py b/plugins/globaltools.py
index 67f1de6a1cedc4972147c333423cae60fb0896bb..074aad9c36f2e7d091bac1820afbd1d731f6685c 100644
--- a/plugins/globaltools.py
+++ b/plugins/globaltools.py
@@ -45,6 +45,7 @@ from telethon.tl.functions.contacts import BlockRequest, UnblockRequest
from telethon.tl.types import ChatAdminRights, User
from pyUltroid.dB import DEVLIST
+from pyUltroid.dB.base import KeyManager
from pyUltroid.dB.gban_mute_db import (
gban,
gmute,
@@ -54,11 +55,6 @@ from pyUltroid.dB.gban_mute_db import (
ungban,
ungmute,
)
-from pyUltroid.dB.gcast_blacklist_db import (
- add_gblacklist,
- is_gblacklisted,
- rem_gblacklist,
-)
from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button
from . import (
@@ -93,6 +89,8 @@ _gdemote_rights = ChatAdminRights(
pin_messages=False,
)
+keym = KeyManager("GBLACKLISTS", cast=list)
+
@ultroid_cmd(pattern="gpromote( (.*)|$)", fullsudo=True)
async def _(e):
@@ -462,7 +460,7 @@ async def gcast(event):
if x.is_group:
chat = x.entity.id
if (
- not is_gblacklisted(chat)
+ not keym.contains(chat)
and int(f"-100{str(chat)}") not in NOSPAM_CHAT
and (
(
@@ -545,7 +543,7 @@ async def gucast(event):
for x in dialog:
if x.is_user and not x.entity.bot:
chat = x.id
- if not is_gblacklisted(chat):
+ if not keym.contains(chat):
try:
if btn:
bt = create_tl_btn(btn)
@@ -749,7 +747,7 @@ async def gblacker(event, type_):
except IndexError:
chat_id = event.chat_id
if type_ == "add":
- add_gblacklist(chat_id)
+ keym.add(chat_id)
elif type_ == "remove":
- rem_gblacklist(chat_id)
+ keym.remove(chat_id)
await event.eor(f"Global Broadcasts: \n{type_}ed {chat_id}")
diff --git a/plugins/imagetools.py b/plugins/imagetools.py
index fda7619ac19dfe5b9fd22ba30d83911b77d718f2..fa65830b1dbec946fc3ea51fcc02a4d06fbe9f75 100644
--- a/plugins/imagetools.py
+++ b/plugins/imagetools.py
@@ -177,11 +177,9 @@ async def ult_tools(event):
ish = centers[labels.flatten()]
ultroid = ish.reshape(ult.shape)
cv2.imwrite("ult.jpg", ultroid)
- await event.client.send_file(
- event.chat_id,
- "ult.jpg",
+ await ureply.reply(
+ file="ult.jpg",
force_document=False,
- reply_to=event.reply_to_msg_id,
)
await xx.delete()
os.remove("ult.jpg")
@@ -196,9 +194,7 @@ async def sampl(ult):
try:
try:
await ult.delete()
- await ult.client.send_message(
- ult.chat_id, f"Colour Sample for `{color}` !", file="csample.png"
- )
+ await ult.respond(f"Colour Sample for `{color}` !", file="csample.png")
except MessageDeleteForbiddenError:
await ult.reply(f"Colour Sample for `{color}` !", file="csample.png")
except ChatSendMediaForbiddenError:
@@ -275,7 +271,7 @@ async def ok(event):
@ultroid_cmd(pattern="pixelator( (.*)|$)")
async def pixelator(event):
reply_message = await event.get_reply_message()
- if not (reply_message and reply_message.photo):
+ if not (reply_message and (reply_message.photo or reply_message.sticker)):
return await event.eor("`Reply to a photo`")
hw = 50
try:
diff --git a/plugins/instagram.py b/plugins/instagram.py
deleted file mode 100644
index 74286603e944c08a0efa7800b80a7ff903165c3f..0000000000000000000000000000000000000000
--- a/plugins/instagram.py
+++ /dev/null
@@ -1,267 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-"""
-â Commands Available -
-
-⢠`{i}instadl `
- `Download Instagram Media...`
-
-⢠`{i}instadata `
- `Get Instagram Data of someone or self`
-
-⢠`{i}instaul `
- `Upload Media to Instagram...`
-
-⢠`{i}igtv `
- `Upload Media to Igtv...`
-
-⢠`{i}reels `
- `Upload Media to Instagram reels...`
-
-⢠Go Inline with Your Assistant with query `instatm`
- To get home page's posts...
-
-⢠Fill `INSTA_USERNAME` and `INSTA_PASSWORD`
- before using it..
-"""
-
-import os
-from re import compile
-
-from telethon.errors.rpcerrorlist import ChatSendInlineForbiddenError
-from telethon.tl.types import (
- DocumentAttributeFilename,
- InputWebDocument,
- MessageMediaWebPage,
- WebPage,
-)
-
-from pyUltroid.fns.helper import numerize
-from pyUltroid.fns.misc import create_instagram_client
-
-from . import (
- LOGS,
- Button,
- asst,
- callback,
- eor,
- get_string,
- in_pattern,
- udB,
- ultroid_cmd,
-)
-
-
-@ultroid_cmd(pattern="instadl( (.*)|$)")
-async def insta_dl(e):
- match = e.pattern_match.group(1).strip()
- replied = await e.get_reply_message()
- tt = await e.eor(get_string("com_1"))
- if match:
- text = match
- elif e.is_reply and "insta" in replied.message:
- text = replied.message
- else:
- return await eor(tt, "Provide a Link to Download...")
- CL = await create_instagram_client(e)
- if CL:
- try:
- mpk = CL.media_pk_from_url(text)
- media = CL.media_info(mpk)
- if media.media_type == 1: # photo
- media = CL.photo_download(mpk)
- elif media.media_type == 2 and media.product_type == "feed": # video:
- media = CL.video_download(mpk)
- elif media.media_type == 2 and media.product_type == "igtv": # igtv:
- media = CL.igtv_download(mpk)
- elif (
- media.media_type == 2 and media.product_type == "clips"
- ): # clips/reels:
- media = CL.clip_download(mpk)
- elif media.media_type == 8: # Album:
- media = CL.album_download(mpk)
- else:
- LOGS.info(f"UnPredictable Media Type : {mpk}")
- return
- await e.reply(
- f"**⢠Uploaded Successfully\n⢠Link :** {text}\n",
- file=media,
- )
- await tt.delete()
- if not isinstance(media, list):
- os.remove(media)
- else:
- [os.remove(media) for media in media]
- return
- except Exception as B:
- LOGS.exception(B)
- return await eor(tt, str(B))
- if isinstance(e.media, MessageMediaWebPage) and isinstance(
- e.media.webpage, WebPage
- ):
- if photo := e.media.webpage.photo or e.media.webpage.document:
- await tt.delete()
- return await e.reply(
- f"**Link** :{text}\n\nIf This Wasnt Excepted Result, Please Fill `INSTA_USERNAME` and `INSTA_PASSWORD`...",
- file=photo,
- )
- # await eor(tt, "Please Fill Instagram Credential to Use this Command...")
-
-
-@ultroid_cmd(pattern="instadata( (.*)|$)")
-async def soon_(e):
- cl = await create_instagram_client(e)
- if not cl:
- return
- match = e.pattern_match.group(1).strip()
- ew = await e.eor(get_string("com_1"))
- if match:
- try:
- iid = cl.user_id_from_username(match)
- data = cl.user_info(iid)
- except Exception as g:
- return await eor(ew, f"**ERROR** : `{g}`")
- else:
- data = cl.account_info()
- data = cl.user_info(data.pk)
- photo = data.profile_pic_url
- unam = f"https://instagram.com/{data.username}"
- msg = f"⢠**Full Name** : __{data.full_name}__"
- if hasattr(data, "biography") and data.biography:
- msg += f"\n⢠**Bio** : `{data.biography}`"
- msg += f"\n⢠**UserName** : [@{data.username}]({unam})"
- msg += f"\n⢠**Verified** : {data.is_verified}"
- msg += f"\n⢠**Posts Count** : {numerize(data.media_count)}"
- msg += f"\n⢠**Followers** : {numerize(data.follower_count)}"
- msg += f"\n⢠**Following** : {numerize(data.following_count)}"
- msg += f"\n⢠**Category** : {data.category_name}"
- await e.reply(
- msg,
- file=photo,
- force_document=True,
- attributes=[DocumentAttributeFilename("InstaUltroid.jpg")],
- )
- await ew.delete()
-
-
-@ultroid_cmd(pattern="(instaul|reels|igtv)( (.*)|$)")
-async def insta_karbon(event):
- cl = await create_instagram_client(event)
- if not cl:
- return
- msg = await event.eor(get_string("com_1"))
- replied = await event.get_reply_message()
- type_ = event.pattern_match.group(1).strip()
- if not (replied and (replied.photo or replied.video)):
- return await event.eor("`Reply to Photo Or Video...`")
- caption = (
- event.pattern_match.group(2) + "\n\n⢠By #Ultroid"
- or replied.message + "\n\n⢠By #Ultroid"
- or "Telegram To Instagram Upload\nBy #Ultroid.."
- )
- dle = await replied.download_media()
- title = None
- if replied.photo:
- method = cl.photo_upload
- elif type_ == "instaul":
- method = cl.video_upload
- elif type_ == "igtv":
- method = cl.igtv_upload
- title = caption
- elif type_ == "reels":
- method = cl.clip_upload
- else:
- return await eor(msg, "`Use In Proper Format...`")
- try:
- if title:
- uri = method(dle, caption=caption, title=title)
- else:
- uri = method(dle, caption=caption)
- os.remove(dle)
- except Exception as er:
- LOGS.exception(er)
- return await msg.edit(str(er))
- if not event.client._bot:
- try:
- que = await event.client.inline_query(
- asst.me.username, f"instp-{uri.code}_{uri.pk}"
- )
- await que[0].click(event.chat_id, reply_to=replied.id)
- await msg.delete()
- except ChatSendInlineForbiddenError:
- pass
- except Exception as er:
- return await msg.edit(str(er))
- await msg.edit(
- f"__Uploaded To Instagram!__\n~ https://instagram.com/p/{uri.code}",
- buttons=Button.inline("â˘Deleteâ˘", f"instd{uri.pk}"),
- link_preview=False,
- )
-
-
-@in_pattern("instp-(.*)", owner=True)
-async def instapl(event):
- match = event.pattern_match.group(1).strip().split("_")
- uri = f"https://instagram.com/p/{match[0]}"
- await event.answer(
- [
- await event.builder.article(
- title="Instagram Post",
- text="**Uploaded on Instagram**",
- buttons=[
- Button.url("â˘Viewâ˘", uri),
- Button.inline("â˘Deleteâ˘", f"instd{match[1]}"),
- ],
- )
- ]
- )
-
-
-@callback(compile("instd(.*)"), owner=True)
-async def dele_post(event):
- CL = await create_instagram_client(event)
- if not CL:
- return await event.answer("Fill Instagram Credentials", alert=True)
- await event.answer("⢠Deleting...")
- try:
- CL.media_delete(event.data_match.group(1).decode("utf-8"))
- except Exception as er:
- return await event.edit(f"ERROR: {str(er)}")
- await event.edit("**⢠Deleted!**")
-
-
-@in_pattern(pattern="instatm", owner=True)
-async def bhoot_ayaa(event):
- if not udB.get_key("INSTA_SET"):
- return await event.answer(
- [], switch_pm="Fill Instagram Credentials First.", switch_pm_param="start"
- )
- insta = await create_instagram_client(event)
- posts = insta.get_timeline_feed()
- res = []
- switch_pm = f"Showing {posts['num_results']} Feeds.."
- for rp in posts["feed_items"]:
- try:
- me = rp["media_or_ad"]
- url = me["image_versions2"]["candidates"][1]["url"] + ".jpg"
- text = (
- f"| Instagram Inline Search |\n~ https://instagram.com/p/{me['code']}"
- )
- file = InputWebDocument(url, 0, "image/jpeg", [])
- res.append(
- await event.builder.article(
- title="Instagram",
- type="photo",
- content=file,
- thumb=file,
- text=text,
- include_media=True,
- )
- )
- except Exception as er:
- LOGS.exception(er)
- await event.answer(res, gallery=True, switch_pm=switch_pm, switch_pm_param="start")
diff --git a/plugins/logo.py b/plugins/logo.py
index 49b949bb3afc1af0e2bc93c19ce90803274ba330..69c0866f8561a45423bd410201c85b2b42209a09 100644
--- a/plugins/logo.py
+++ b/plugins/logo.py
@@ -19,6 +19,10 @@ import random
from telethon.tl.types import InputMessagesFilterPhotos
+try:
+ from PIL import Image
+except ImportError:
+ Image = None
from pyUltroid.fns.misc import unsplashsearch
from pyUltroid.fns.tools import LogoHelper
@@ -45,9 +49,22 @@ async def logo_gen(event):
bg_ = await temp.download_media()
if not bg_:
if event.client._bot:
- SRCH = ["blur background", "background", "neon lights", "wallpaper"]
+ SRCH = [
+ "blur background",
+ "background",
+ "neon lights",
+ "nature",
+ "abstract",
+ "space",
+ "3d render",
+ ]
res = await unsplashsearch(random.choice(SRCH), limit=1)
- bg_ = await download_file(res[0], "resources/downloads/logo.png")
+ bg_, _ = await download_file(res[0], "resources/downloads/logo.png")
+ newimg = "resources/downloads/unsplash-temp.jpg"
+ img_ = Image.open(bg_)
+ img_.resize((5000, 5000)).save(newimg)
+ os.remove(bg_)
+ bg_ = newimg
else:
pics = []
async for i in event.client.iter_messages(
diff --git a/plugins/mediatools.py b/plugins/mediatools.py
index 3ed6d301373f46b42e89c8600cb3b7c0c79d44b1..3c47efe7016a4696f00726dae1e686fb1714abeb 100644
--- a/plugins/mediatools.py
+++ b/plugins/mediatools.py
@@ -73,7 +73,8 @@ async def mi(e):
else:
naam = await r.download_media()
elif match and (
- os.path.isfile(match) or (match.startswith("https://") and is_url_ok(match))
+ os.path.isfile(match)
+ or (match.startswith("https://") and (await is_url_ok(match)))
):
naam, xx = match, "file"
else:
@@ -123,18 +124,18 @@ async def rotate_(ult):
reply = await ult.get_reply_message()
msg = await ult.eor(get_string("com_1"))
photo = reply.game.photo if reply.game else None
- if photo or reply.photo or reply.sticker:
- media = await ult.client.download_media(photo or reply)
- img = cv2.imread(media)
- new_ = rotate_image(img, match)
- file = "ult.png"
- cv2.imwrite(file, new_)
- elif reply.video:
+ if reply.video:
media = await reply.download_media()
file = f"{media}.mp4"
await bash(
f'ffmpeg -i "{media}" -c copy -metadata:s:v:0 rotate={match} "{file}" -y'
)
+ elif photo or reply.photo or reply.sticker:
+ media = await ult.client.download_media(photo or reply)
+ img = cv2.imread(media)
+ new_ = rotate_image(img, match)
+ file = "ult.png"
+ cv2.imwrite(file, new_)
else:
return await msg.edit("`Unsupported Media..\nReply to Photo/Video`")
if os.path.exists(file):
diff --git a/plugins/mute.py b/plugins/mute.py
index 18fc2320cdb0704a08fa0e859ee5cc5de20e427c..c80d19726e0158dc280aa380cf7bea6110cda2f5 100644
--- a/plugins/mute.py
+++ b/plugins/mute.py
@@ -109,16 +109,16 @@ async def _(e):
except IndexError:
return await xx.eor("`Time till mute?`", time=5)
try:
- input = huh[2]
+ input_ = huh[2]
except IndexError:
- pass
+ input_ = ""
chat = await e.get_chat()
if e.reply_to_msg_id:
reply = await e.get_reply_message()
userid = reply.sender_id
name = (await reply.get_sender()).first_name
- elif input:
- userid = await e.client.parse_id(input)
+ elif input_:
+ userid = await e.client.parse_id(input_)
name = (await e.client.get_entity(userid)).first_name
else:
return await xx.eor(get_string("tban_1"), time=3)
diff --git a/plugins/nightmode.py b/plugins/nightmode.py
index 7fd7a5e2c4ee3211fdf5a489af0e184fc7d89266..f96f1eda5c447538d0d04dd04a472689372c654b 100644
--- a/plugins/nightmode.py
+++ b/plugins/nightmode.py
@@ -40,10 +40,12 @@ except ImportError:
from telethon.tl.functions.messages import EditChatDefaultBannedRightsRequest
from telethon.tl.types import ChatBannedRights
-from pyUltroid.dB.night_db import *
+from pyUltroid.dB.base import KeyManager
from . import get_string, udB, ultroid_bot, ultroid_cmd
+keym = KeyManager("NIGHT_CHATS", cast=list)
+
@ultroid_cmd(pattern="nmtime( (.*)|$)")
async def set_time(e):
@@ -64,29 +66,29 @@ async def set_time(e):
async def add_grp(e):
if pat := e.pattern_match.group(1).strip():
try:
- add_night((await ultroid_bot.get_entity(pat)).id)
+ keym.add((await ultroid_bot.get_entity(pat)).id)
return await e.eor(f"Done, Added {pat} To Night Mode.")
except BaseException:
return await e.eor(get_string("nightm_5"), time=5)
- add_night(e.chat_id)
+ keym.add(e.chat_id)
await e.eor(get_string("nightm_3"))
@ultroid_cmd(pattern="remnm( (.*)|$)")
-async def rem_grp(e):
+async def r_em_grp(e):
if pat := e.pattern_match.group(1).strip():
try:
- rem_night((await ultroid_bot.get_entity(pat)).id)
+ keym.remove((await ultroid_bot.get_entity(pat)).id)
return await e.eor(f"Done, Removed {pat} To Night Mode.")
except BaseException:
return await e.eor(get_string("nightm_5"), time=5)
- rem_night(e.chat_id)
+ keym.remove(e.chat_id)
await e.eor(get_string("nightm_4"))
@ultroid_cmd(pattern="listnm$")
async def rem_grp(e):
- chats = night_grps()
+ chats = keym.get()
name = "NightMode Groups Are-:\n\n"
for x in chats:
try:
@@ -98,8 +100,7 @@ async def rem_grp(e):
async def open_grp():
- chats = night_grps()
- for chat in chats:
+ for chat in keym.get():
try:
await ultroid_bot(
EditChatDefaultBannedRightsRequest(
@@ -122,11 +123,10 @@ async def open_grp():
async def close_grp():
- chats = night_grps()
- h1, m1, h2, m2 = 0, 0, 7, 0
+ __, _, h2, m2 = 0, 0, 7, 0
if udB.get_key("NIGHT_TIME"):
- h1, m1, h2, m2 = eval(udB.get_key("NIGHT_TIME"))
- for chat in chats:
+ _, __, h2, m2 = eval(udB.get_key("NIGHT_TIME"))
+ for chat in keym.get():
try:
await ultroid_bot(
EditChatDefaultBannedRightsRequest(
@@ -144,7 +144,7 @@ async def close_grp():
LOGS.info(er)
-if AsyncIOScheduler and night_grps():
+if AsyncIOScheduler and keym.get():
try:
h1, m1, h2, m2 = 0, 0, 7, 0
if udB.get_key("NIGHT_TIME"):
diff --git a/plugins/pdftools.py b/plugins/pdftools.py
index b8e2257c8e4ba40a5f1c523c71616617364db71e..1e5d00bab1e56792fb7c528e37abda5c1cf9e407 100644
--- a/plugins/pdftools.py
+++ b/plugins/pdftools.py
@@ -8,21 +8,22 @@
â Commands Available -
⢠`{i}pdf `
- Extract nd Send page as a Image.(note-: For Extraction all pages just use .pdf)
- You Can use multi pages too like `{i}pdf 1-7`
+ Extract & send page as an Image.(note-: For extracting all pages, just use .pdf)
+ to upload selected range `{i}pdf 1-7`
⢠`{i}pdtext `
Extract Text From the Pdf.(note-: For Extraction all text just use .pdtext)
- You Can use multi pages too like `{i}pdf 1-7`
+ to extract selected pages `{i}pdf 1-7`
⢠`{i}pdscan `
- It scan, crop nd send img as pdf.
+ It scan, crop & send image(s) as pdf.
⢠`{i}pdsave `
- It scan, crop nd save file to merge u can merge many pages as a single pdf.
+ It scan, crop & save file to merge.
+ you can merge many pages in a single pdf.
⢠`{i}pdsend `
- Merge nd send the Pdf to collected from .pdsave.
+ Merge & send the pdf, collected from .pdsave.
"""
import glob
import os
diff --git a/plugins/pmpermit.py b/plugins/pmpermit.py
index b4620b8528c597a54603694f0921593d872ddf51..8749f6ee022a76f9acadc861f0586cf0f7ce0c3c 100644
--- a/plugins/pmpermit.py
+++ b/plugins/pmpermit.py
@@ -43,8 +43,6 @@ import re
from os import remove
from pyUltroid.dB import DEVLIST
-from pyUltroid.dB.logusers_db import *
-from pyUltroid.dB.pmpermit_db import *
try:
from tabulate import tabulate
@@ -60,6 +58,8 @@ from telethon.tl.functions.contacts import (
from telethon.tl.functions.messages import ReportSpamRequest
from telethon.utils import get_display_name, resolve_bot_file_id
+from pyUltroid.dB.base import KeyManager
+
from . import *
# ========================= CONSTANTS =============================
@@ -68,6 +68,11 @@ COUNT_PM = {}
LASTMSG = {}
WARN_MSGS = {}
U_WARNS = {}
+if isinstance(udB.get_key("PMPERMIT"), (int, str)):
+ value = [udB.get_key("PMPERMIT")]
+ udB.set_key("PMPERMIT", value)
+keym = KeyManager("PMPERMIT", cast=list)
+Logm = KeyManager("LOGUSERS", cast=list)
PMPIC = udB.get_key("PMPIC")
LOG_CHANNEL = udB.get_key("LOG_CHANNEL")
UND = get_string("pmperm_1")
@@ -127,10 +132,10 @@ if udB.get_key("PMLOG"):
async def _(e):
if not e.is_private:
return await e.eor("`Use me in Private.`", time=3)
- if not is_logger(e.chat_id):
+ if not Logm.contains(e.chat_id):
return await e.eor("`Wasn't logging msgs from here.`", time=3)
- nolog_user(e.chat_id)
+ Logm.remove(e.chat_id)
return await e.eor("`Now I Will log msgs from here.`", time=3)
@ultroid_cmd(
@@ -139,10 +144,10 @@ if udB.get_key("PMLOG"):
async def _(e):
if not e.is_private:
return await e.eor("`Use me in Private.`", time=3)
- if is_logger(e.chat_id):
+ if Logm.contains(e.chat_id):
return await e.eor("`Wasn't logging msgs from here.`", time=3)
- log_user(e.chat_id)
+ Logm.add(e.chat_id)
return await e.eor("`Now I Won't log msgs from here.`", time=3)
@ultroid_bot.on(
@@ -153,7 +158,7 @@ if udB.get_key("PMLOG"):
)
async def permitpm(event):
user = await event.get_sender()
- if user.bot or user.is_self or user.verified or is_logger(user.id):
+ if user.bot or user.is_self or user.verified or Logm.contains(user.id):
return
await event.forward_to(udB.get_key("PMLOGGROUP") or LOG_CHANNEL)
@@ -171,9 +176,9 @@ if udB.get_key("PMSETTING"):
miss = await e.get_chat()
if miss.bot or miss.is_self or miss.verified or miss.id in DEVLIST:
return
- if is_approved(miss.id):
+ if keym.contains(miss.id):
return
- approve_user(miss.id)
+ keym.add(miss.id)
await delete_pm_warn_msgs(miss.id)
try:
await ultroid_bot.edit_folder(miss.id, folder=0)
@@ -209,7 +214,7 @@ if udB.get_key("PMSETTING"):
async def permitpm(event):
inline_pm = Redis("INLINE_PM") or False
user = event.sender
- if not is_approved(user.id) and event.text != UND:
+ if not keym.contains(user.id) and event.text != UND:
if Redis("MOVE_ARCHIVE"):
try:
await ultroid_bot.edit_folder(user.id, folder=1)
@@ -221,11 +226,11 @@ if udB.get_key("PMSETTING"):
fullname = get_display_name(user)
username = f"@{user.username}"
mention = inline_mention(user)
- count = len(get_approved())
+ count = keym.count()
try:
wrn = COUNT_PM[user.id] + 1
await asst.edit_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
_not_approved[user.id],
f"Incoming PM from **{mention}** [`{user.id}`] with **{wrn}/{WARNS}** warning!",
buttons=[
@@ -235,7 +240,7 @@ if udB.get_key("PMSETTING"):
)
except KeyError:
_not_approved[user.id] = await asst.send_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
f"Incoming PM from **{mention}** [`{user.id}`] with **1/{WARNS}** warning!",
buttons=[
Button.inline("Approve PM", data=f"approve_{user.id}"),
@@ -366,14 +371,14 @@ if udB.get_key("PMSETTING"):
del LASTMSG[user.id]
except KeyError:
await asst.send_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
"PMPermit is messed! Pls restart the bot!!",
)
return LOGS.info("COUNT_PM is messed.")
await ultroid_bot(BlockRequest(user.id))
await ultroid_bot(ReportSpamRequest(peer=user.id))
await asst.edit_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
_not_approved[user.id],
f"**{mention}** [`{user.id}`] was Blocked for spamming.",
)
@@ -407,8 +412,8 @@ if udB.get_key("PMSETTING"):
apprvpm,
"Lol, He is my Developer\nHe is auto Approved",
)
- if not is_approved(user.id):
- approve_user(user.id)
+ if not keym.contains(user.id):
+ keym.add(user.id)
try:
await delete_pm_warn_msgs(user.id)
await apprvpm.client.edit_folder(user.id, folder=0)
@@ -421,7 +426,7 @@ if udB.get_key("PMSETTING"):
)
try:
await asst.edit_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
_not_approved[user.id],
f"#APPROVED\n\n{inline_mention(user, html=True)} [{user.id}
] was approved to PM you!
",
buttons=[
@@ -432,7 +437,7 @@ if udB.get_key("PMSETTING"):
)
except KeyError:
_not_approved[user.id] = await asst.send_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
f"#APPROVED\n\n{inline_mention(user, html=True)} [{user.id}
] was approved to PM you!
",
buttons=[
Button.inline("Disapprove PM", data=f"disapprove_{user.id}"),
@@ -458,8 +463,8 @@ if udB.get_key("PMSETTING"):
e,
"`Lol, He is my Developer\nHe Can't Be DisApproved.`",
)
- if is_approved(user.id):
- disapprove_user(user.id)
+ if keym.contains(user.id):
+ keym.remove(user.id)
await eod(
e,
f"{inline_mention(user, html=True)} Disapproved to PM!
",
@@ -467,7 +472,7 @@ if udB.get_key("PMSETTING"):
)
try:
await asst.edit_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
_not_approved[user.id],
f"#DISAPPROVED\n\n{inline_mention(user, html=True)} [{user.id}
] was disapproved to PM you.
",
buttons=[
@@ -478,7 +483,7 @@ if udB.get_key("PMSETTING"):
)
except KeyError:
_not_approved[user.id] = await asst.send_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
f"#DISAPPROVED\n\n{inline_mention(user, html=True)} [{user.id}
] was disapproved to PM you.
",
buttons=[
Button.inline("Approve PM", data=f"approve_{user.id}"),
@@ -515,12 +520,12 @@ async def blockpm(block):
aname = await block.client.get_entity(user)
await block.eor(f"{inline_mention(aname)} [`{user}`] `has been blocked!`")
try:
- disapprove_user(user)
+ keym.remove(user)
except AttributeError:
pass
try:
await asst.edit_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
_not_approved[user],
f"#BLOCKED\n\n{inline_mention(aname)} [`{user}`] has been **blocked**.",
buttons=[
@@ -529,7 +534,7 @@ async def blockpm(block):
)
except KeyError:
_not_approved[user] = await asst.send_message(
- int(udB.get_key("LOG_CHANNEL")),
+ udB.get_key("LOG_CHANNEL"),
f"#BLOCKED\n\n{inline_mention(aname)} [`{user}`] has been **blocked**.",
buttons=[
Button.inline("UnBlock", data=f"unblock_{user}"),
@@ -604,7 +609,7 @@ async def unblockpm(event):
@ultroid_cmd(pattern="listapproved$", owner=True)
async def list_approved(event):
xx = await event.eor(get_string("com_1"))
- all = get_approved()
+ all = keym.get()
if not all:
return await xx.eor("`You haven't approved anyone yet!`", time=5)
users = []
@@ -641,8 +646,8 @@ async def apr_in(event):
uid = int(event.data_match.group(1).decode("UTF-8"))
if uid in DEVLIST:
await event.edit("It's a dev! Approved!")
- if not is_approved(uid):
- approve_user(uid)
+ if not keym.contains(uid):
+ keym.add(uid)
try:
await ultroid_bot.edit_folder(uid, folder=0)
except BaseException:
@@ -683,8 +688,8 @@ async def apr_in(event):
)
async def disapr_in(event):
uid = int(event.data_match.group(1).decode("UTF-8"))
- if is_approved(uid):
- disapprove_user(uid)
+ if keym.contains(uid):
+ keym.remove(uid)
try:
user = await ultroid_bot.get_entity(uid)
except BaseException:
diff --git a/plugins/polls.py b/plugins/polls.py
index 159c73a0de25fc37e20682f280c9df2707ad87ca..138645c8ddce29a9ab5979fff9482c1602641b76 100644
--- a/plugins/polls.py
+++ b/plugins/polls.py
@@ -58,9 +58,8 @@ async def uri_poll(e):
return await e.eor("`Options Should be More than 1..`", time=5)
m = await e.eor(get_string("com_1"))
OUT = [PollAnswer(option[on], str(on).encode()) for on in range(len(option))]
- await e.client.send_file(
- e.chat_id,
- InputMediaPoll(
+ await e.respond(
+ file=InputMediaPoll(
Poll(20, ques, OUT, multiple_choice=mpp, public_voters=publ, quiz=quizo),
correct_answers=karzo,
),
diff --git a/plugins/profanityfilter.py b/plugins/profanityfilter.py
index a93e21e7e2ea1b9ab5f2b47ccdeb46fdcbb08721..7272b2c93fda2be6f76121d755f2f1fe4807b206 100644
--- a/plugins/profanityfilter.py
+++ b/plugins/profanityfilter.py
@@ -20,13 +20,13 @@ from pyUltroid.dB.nsfw_db import profan_chat, rem_profan
from . import get_string, ultroid_cmd
-@ultroid_cmd(pattern="addprofanity$", admins_only=True)
+@ultroid_cmd(pattern="(add|rem)profanity$", admins_only=True)
async def addp(e):
- profan_chat(e.chat_id, "mute")
- await e.eor(get_string("prof_1"), time=10)
-
-
-@ultroid_cmd(pattern="remprofanity", admins_only=True)
-async def remp(e):
+ cas = e.pattern_match.group(1)
+ add = cas == "add"
+ if add:
+ profan_chat(e.chat_id, "mute")
+ await e.eor(get_string("prof_1"), time=10)
+ return
rem_profan(e.chat_id)
await e.eor(get_string("prof_2"), time=10)
diff --git a/plugins/profile.py b/plugins/profile.py
index 51739508d147316a823a0059800a96b2424c9bfd..d9aa5a5871305fcb6cc9b382349f4bdee3173b40 100644
--- a/plugins/profile.py
+++ b/plugins/profile.py
@@ -19,7 +19,10 @@
⢠`{i}delpfp (optional)`
Delete one profile pic, if no value given, else delete n number of pics.
-⢠`{i}poto `
+⢠`{i}poto /reply`
+ `{i}poto /all`
+
+ Ex: `{i}poto 10` - uploads starting 10 pfps of user.
Upload the photo of Chat/User if Available.
"""
import os
@@ -51,8 +54,7 @@ async def _(ult):
@ultroid_cmd(pattern="setname ?((.|//)*)", fullsudo=True)
async def _(ult):
ok = await ult.eor("...")
- names = ult.pattern_match.group(1).strip()
- first_name = names
+ names = first_name = ult.pattern_match.group(1).strip()
last_name = ""
if "//" in names:
first_name, last_name = names.split("//", 1)
@@ -111,21 +113,56 @@ async def remove_profilepic(delpfp):
@ultroid_cmd(pattern="poto( (.*)|$)")
async def gpoto(e):
ult = e.pattern_match.group(1).strip()
+
+ if e.is_reply:
+ gs = await e.get_reply_message()
+ user_id = gs.sender_id
+ elif ult:
+ split = ult.split()
+ user_id = split[0]
+ if len(ult) > 1:
+ ult = ult[-1]
+ else:
+ ult = None
+ else:
+ user_id = e.chat_id
+
a = await e.eor(get_string("com_1"))
+ limit = None
+
just_dl = ult in ["-dl", "--dl"]
if just_dl:
ult = None
- if not ult:
- if e.is_reply:
- gs = await e.get_reply_message()
- ult = gs.sender_id
- else:
- ult = e.chat_id
- okla = await e.client.download_profile_photo(ult)
+
+ if ult and ult != "all":
+ try:
+ limit = int(ult)
+ except ValueError:
+ pass
+
+ if not limit or e.client._bot:
+ okla = await e.client.download_profile_photo(user_id)
+ else:
+ okla = []
+ if limit == "all":
+ limit = None
+ async for photo in e.client.iter_profile_photos(user_id, limit=limit):
+ photo_path = await e.client.download_media(photo)
+ if photo.video_sizes:
+ await e.respond(file=photo_path)
+ os.remove(photo_path)
+ else:
+ okla.append(photo_path)
if not okla:
return await eor(a, "`Pfp Not Found...`")
if not just_dl:
await a.delete()
await e.reply(file=okla)
- return os.remove(okla)
+ if not isinstance(okla, list):
+ okla = [okla]
+ for file in okla:
+ os.remove(file)
+ return
+ if isinstance(okla, list):
+ okla = "\n".join(okla)
await a.edit(f"Downloaded pfp to [ `{okla}` ].")
diff --git a/plugins/qrcode.py b/plugins/qrcode.py
index 529da6edff5926fec09fd43025e4a6c453682e54..5335ee9a73c036482601bf732e283f76b7d7f589 100644
--- a/plugins/qrcode.py
+++ b/plugins/qrcode.py
@@ -28,7 +28,6 @@ except ImportError:
import qrcode
from PIL import Image
from telethon.tl.types import MessageMediaDocument as doc
-from telethon.tl.types import MessageMediaPhoto as photu
from . import check_filename, get_string, ultroid_bot, ultroid_cmd
@@ -70,11 +69,10 @@ async def cd(e):
async def qrwater(e):
msg = e.pattern_match.group(1).strip()
r = await e.get_reply_message()
- if isinstance(r.media, photu):
- dl = await e.client.download_media(r.media)
- elif isinstance(r.media, doc):
- dl = await e.client.download_media(r, thumb=-1)
- else:
+ dl = await e.client.download_media(
+ r, thumb=-1 if isinstance(r.media, doc) else None
+ )
+ if not dl:
return await e.eor("`Reply Any Media and Give Text`", time=5)
kk = await e.eor(get_string("com_1"))
img_bg = Image.open(dl)
@@ -96,11 +94,10 @@ async def decod(e):
if not (r and r.media):
return await e.eor("`Reply to Qrcode Media`", time=5)
kk = await e.eor(get_string("com_1"))
- if isinstance(r.media, photu):
- dl = await r.download_media()
- elif isinstance(r.media, doc):
- dl = await r.download_media(thumb=-1)
- else:
+ dl = await e.client.download_media(
+ r, thumb=-1 if isinstance(r.media, doc) else None
+ )
+ if not dl:
return
im = cv2.imread(dl)
try:
diff --git a/plugins/resize.py b/plugins/resize.py
index 6d7ba4d4ae555c465e05fdc8c2f895e7d701eb51..5654adbff7c0d1c6a94e976b3069d316c79f0e17 100644
--- a/plugins/resize.py
+++ b/plugins/resize.py
@@ -36,7 +36,7 @@ async def size(e):
@ultroid_cmd(pattern="resize( (.*)|$)")
-async def size(e):
+async def resize(e):
r = await e.get_reply_message()
if not (r and r.media):
return await e.eor(get_string("ascii_1"))
diff --git a/plugins/schedulemsg.py b/plugins/schedulemsg.py
index 1cfc5735736b31332ff3ee22482e6e6521d3d4bf..d2b2f89b187aa67698714ffd25debc153014d943 100644
--- a/plugins/schedulemsg.py
+++ b/plugins/schedulemsg.py
@@ -34,20 +34,18 @@ async def _(e):
else:
try:
z = ban_time(y)
- await e.client.send_message(e.chat_id, k, schedule=z)
+ await e.respond(k, schedule=z)
await e.eor(get_string("schdl_1"), time=5)
except BaseException:
await e.eor(get_string("schdl_2"), time=5)
elif xx and x:
if x.isdigit():
- await e.client.send_message(
- e.chat_id, xx, schedule=timedelta(seconds=int(x))
- )
+ await e.respond(xx, schedule=timedelta(seconds=int(x)))
await e.eor(get_string("schdl_1"), time=5)
else:
try:
z = ban_time(x)
- await e.client.send_message(e.chat_id, xx, schedule=z)
+ await e.respond(xx, schedule=z)
await e.eor(get_string("schdl_1"), time=5)
except BaseException:
await e.eor(get_string("schdl_2"), time=5)
diff --git a/plugins/search.py b/plugins/search.py
index 9a7de1e75445930ef1db1d8433c894f48f521581..125734b4d99c3958d8a16ce1ca5bd8da162f91d6 100644
--- a/plugins/search.py
+++ b/plugins/search.py
@@ -24,7 +24,6 @@
Reply an Image or sticker to find its sauce.
"""
import os
-from shutil import rmtree
import requests
from bs4 import BeautifulSoup as bs
@@ -39,11 +38,10 @@ except ImportError:
cv2 = None
from telethon.tl.types import DocumentAttributeAudio
-from pyUltroid.fns.google_image import googleimagesdownload
from pyUltroid.fns.misc import google_search
-from pyUltroid.fns.tools import saavn_search
+from pyUltroid.fns.tools import get_google_images, saavn_search
-from . import async_searcher, con, eod, fast_download, get_string, ultroid_cmd
+from . import LOGS, async_searcher, con, eod, fast_download, get_string, ultroid_cmd
@ultroid_cmd(
@@ -122,20 +120,12 @@ async def goimg(event):
query = query.split(";")[0]
except BaseException:
pass
- try:
- gi = googleimagesdownload()
- args = {
- "keywords": query,
- "limit": lmt,
- "format": "jpg",
- "output_directory": "./resources/downloads/",
- }
- pth = await gi.download(args)
- ok = pth[0][query]
- except BaseException:
- return await nn.edit(get_string("autopic_2").format(query))
- await event.reply(file=ok, message=query)
- rmtree(f"./resources/downloads/{query}/")
+ images = await get_google_images(query)
+ for img in images[:lmt]:
+ try:
+ await event.client.send_file(event.chat_id, file=img["original"])
+ except Exception as er:
+ LOGS.exception(er)
await nn.delete()
@@ -168,22 +158,16 @@ async def reverse(event):
link = alls["href"]
text = alls.text
await ult.edit(f"`Dimension ~ {x} : {y}`\nSauce ~ [{text}](google.com{link})")
- gi = googleimagesdownload()
- args = {
- "keywords": text,
- "limit": 2,
- "format": "jpg",
- "output_directory": "./resources/downloads/",
- }
- pth = await gi.download(args)
- ok = pth[0][text]
- await event.client.send_file(
- event.chat_id,
- ok,
- album=True,
- caption="Similar Images Realted to Search",
- )
- rmtree(f"./resources/downloads/{text}/")
+ images = await get_google_images(text)
+ for z in images[:2]:
+ try:
+ await event.client.send_file(
+ event.chat_id,
+ file=z["original"],
+ caption="Similar Images Realted to Search",
+ )
+ except Exception as er:
+ LOGS.exception(er)
os.remove(file)
diff --git a/plugins/snips.py b/plugins/snips.py
index 90788c74459148ea93f755727b76abb60c3919e6..d876b25a51d973ca90565300f708af0669a13e1f 100644
--- a/plugins/snips.py
+++ b/plugins/snips.py
@@ -88,9 +88,8 @@ async def rs(e):
async def lsnote(e):
if x := list_snip():
sd = "SNIPS Found :\n\n"
- await e.eor(sd + x)
- else:
- await e.eor("No Snips Found Here")
+ return await e.eor(sd + x)
+ await e.eor("No Snips Found Here")
async def add_snips(e):
diff --git a/plugins/specialtools.py b/plugins/specialtools.py
index b7a1c2bb3be8db2d4140556d3e300f8128a9009b..8cabf4fdf76fed3073745ab9da056b92dda7ae87 100644
--- a/plugins/specialtools.py
+++ b/plugins/specialtools.py
@@ -35,14 +35,12 @@ import os
import time
from datetime import datetime as dt
from random import choice
-from shutil import rmtree
import pytz
from bs4 import BeautifulSoup as bs
from telethon.tl.types import DocumentAttributeVideo
-from pyUltroid.fns.google_image import googleimagesdownload
-from pyUltroid.fns.tools import metadata
+from pyUltroid.fns.tools import get_google_images, metadata
from . import (
HNDLR,
@@ -284,17 +282,9 @@ async def wall(event):
return await event.eor("`Give me something to search..`")
nn = await event.eor(get_string("com_1"))
query = f"hd {inp}"
- gi = googleimagesdownload()
- args = {
- "keywords": query,
- "limit": 10,
- "format": "jpg",
- "output_directory": "./resources/downloads/",
- }
- await gi.download(args)
- xx = choice(os.listdir(os.path.abspath(f"./resources/downloads/{query}/")))
- await event.client.send_file(event.chat_id, f"./resources/downloads/{query}/{xx}")
- rmtree(f"./resources/downloads/{query}/")
+ images = await get_google_images(query)
+ for z in range(5):
+ await event.client.send_file(event.chat_id, file=images[z]["original"])
await nn.delete()
diff --git a/plugins/tools.py b/plugins/tools.py
index 030ca7cb5972b0e3912b685b10ea0d8b2d2232b6..4171a134ed04bd459d37afe6a10695f47573b0df 100644
--- a/plugins/tools.py
+++ b/plugins/tools.py
@@ -39,6 +39,7 @@
import glob
import io
import os
+import secrets
from asyncio.exceptions import TimeoutError as AsyncTimeout
try:
@@ -46,10 +47,15 @@ try:
except ImportError:
cv2 = None
+try:
+ from playwright.async_api import async_playwright
+except ImportError:
+ async_playwright = None
try:
from htmlwebshot import WebShot
except ImportError:
WebShot = None
+
from telethon.errors.rpcerrorlist import MessageTooLongError, YouBlockedUserError
from telethon.tl.types import (
ChannelParticipantAdmin,
@@ -67,12 +73,12 @@ from . import (
bash,
check_filename,
con,
+ download_file,
eor,
- fast_download,
get_string,
)
from . import humanbytes as hb
-from . import inline_mention, is_url_ok, mediainfo, ultroid_cmd
+from . import inline_mention, is_url_ok, json_parser, mediainfo, ultroid_cmd
@ultroid_cmd(pattern="tr( (.*)|$)", manager=True)
@@ -337,16 +343,16 @@ async def _(e):
)
async def lastname(steal):
mat = steal.pattern_match.group(1).strip()
- if not steal.is_reply and not mat:
- return await steal.eor("`Use this command with reply or give Username/id...`")
+ message = await steal.get_reply_message()
if mat:
try:
user_id = await steal.client.parse_id(mat)
except ValueError:
user_id = mat
- message = await steal.get_reply_message()
- if message:
- user_id = message.sender.id
+ elif message:
+ user_id = message.sender_id
+ else:
+ return await steal.eor("`Use this command with reply or give Username/id...`")
chat = "@SangMataInfo_bot"
id = f"/search_id {user_id}"
lol = await steal.eor(get_string("com_1"))
@@ -389,20 +395,37 @@ async def webss(event):
xurl = event.pattern_match.group(1).strip()
if not xurl:
return await xx.eor(get_string("wbs_1"), time=5)
- if not is_url_ok(xurl):
+ if not (await is_url_ok(xurl)):
return await xx.eor(get_string("wbs_2"), time=5)
- try:
- shot = WebShot(
- quality=88, flags=["--enable-javascript", "--no-stop-slow-scripts"]
- )
- pic = await shot.create_pic_async(url=xurl)
- except FileNotFoundError:
- pic = (
- await fast_download(
- f"https://shot.screenshotapi.net/screenshot?&url={xurl}&output=image&file_type=png&wait_for_event=load",
- filename=check_filename("shot.png"),
+ path, pic = check_filename("shot.png"), None
+ if async_playwright:
+ try:
+ async with async_playwright() as playwright:
+ chrome = await playwright.chromium.launch()
+ page = await chrome.new_page()
+ await page.goto(xurl)
+ await page.screenshot(path=path, full_page=True)
+ pic = path
+ except Exception as er:
+ LOGS.exception(er)
+ await xx.respond(f"Error with playwright:\n`{er}`")
+ if WebShot and not pic:
+ try:
+ shot = WebShot(
+ quality=88, flags=["--enable-javascript", "--no-stop-slow-scripts"]
)
- )[0]
+ pic = await shot.create_pic_async(url=xurl)
+ except Exception as er:
+ LOGS.exception(er)
+ if not pic:
+ pic, msg = await download_file(
+ f"https://shot.screenshotapi.net/screenshot?&url={xurl}&output=image&file_type=png&wait_for_event=load",
+ path,
+ validate=True,
+ )
+ if msg:
+ await xx.edit(json_parser(msg, indent=1))
+ return
if pic:
await xx.reply(
get_string("wbs_3").format(xurl),
@@ -420,12 +443,10 @@ async def magic(event):
match = event.text.split(maxsplit=1)[1].strip()
except IndexError:
return await event.eor("`Provide url to turn into tiny...`")
- match, id_ = match.split(), None
- data = {}
- if len(match) > 1:
- data["id"] = match[1]
- url = match[0]
- data["link"] = url
+ data = {
+ "url": match.split()[0],
+ "id": match[1] if len(match) > 1 else secrets.token_urlsafe(6),
+ }
data = await async_searcher(
"https://tiny.ultroid.tech/api/new",
data=data,
diff --git a/plugins/unsplash.py b/plugins/unsplash.py
index 2a8980af5a758395df5aaeb89d5242c99785b2c5..c412af23814973f83558b68032c705ebfd696e22 100644
--- a/plugins/unsplash.py
+++ b/plugins/unsplash.py
@@ -30,9 +30,7 @@ async def searchunsl(ult):
if not res:
return await ult.eor(get_string("unspl_1"), time=5)
CL = [download_file(rp, f"{match}-{e}.png") for e, rp in enumerate(res)]
- imgs = [z for z in (await asyncio.gather(*CL)) if z]
- await ult.client.send_file(
- ult.chat_id, imgs, caption=f"Uploaded {len(imgs)} Images!"
- )
+ imgs = [z[0] for z in (await asyncio.gather(*CL)) if z]
+ await ult.respond(f"Uploaded {len(imgs)} Images!", file=imgs)
await tep.delete()
[os.remove(img) for img in imgs]
diff --git a/plugins/utilities.py b/plugins/utilities.py
index 7265ca8ec6332cb04031c54cb10de3030e8d06a6..ab4961fee0c9f88cac26e871ada6c37a0bac395e 100644
--- a/plugins/utilities.py
+++ b/plugins/utilities.py
@@ -82,9 +82,19 @@ from telethon.tl.functions.channels import (
from telethon.tl.functions.contacts import GetBlockedRequest
from telethon.tl.functions.messages import AddChatUserRequest, GetAllStickersRequest
from telethon.tl.functions.users import GetFullUserRequest
-from telethon.tl.types import Channel, Chat, InputMediaPoll, Poll, PollAnswer, User
+from telethon.tl.types import (
+ Channel,
+ Chat,
+ InputMediaPoll,
+ Poll,
+ PollAnswer,
+ TLObject,
+ User,
+)
from telethon.utils import get_peer_id
+from pyUltroid.fns.info import get_chat_info
+
from . import (
HNDLR,
LOGS,
@@ -97,7 +107,6 @@ from . import (
check_filename,
eod,
eor,
- get_chat_info,
get_paste,
get_string,
inline_mention,
@@ -512,16 +521,28 @@ async def _(event):
else:
msg = event
reply_to_id = event.message.id
- if match and hasattr(msg, match):
- msg = getattr(msg, match)
- if hasattr(msg, "to_json"):
- try:
- msg = json_parser(msg.to_json(ensure_ascii=False), indent=1)
- except Exception as e:
- LOGS.exception(e)
+ if match and hasattr(msg, match.split()[0]):
+ msg = getattr(msg, match.split()[0])
+ try:
+ if hasattr(msg, "to_json"):
+ msg = msg.to_json(ensure_ascii=False, indent=1)
+ elif hasattr(msg, "to_dict"):
+ msg = json_parser(msg.to_dict(), indent=1)
+ else:
+ msg = TLObject.stringify(msg)
+ except Exception:
+ pass
msg = str(msg)
else:
msg = json_parser(msg.to_json(), indent=1)
+ if "-t" in match:
+ try:
+ data = json_parser(msg)
+ msg = json_parser(
+ {key: data[key] for key in data.keys() if data[key]}, indent=1
+ )
+ except Exception:
+ pass
if len(msg) > 4096:
with io.BytesIO(str.encode(msg)) as out_file:
out_file.name = "json-ult.txt"
diff --git a/plugins/videotools.py b/plugins/videotools.py
index e95efac351e5a26d8d4adbcfd224d121a1bd168b..77e5578271a80a1bf760b2eed9e5100fa1461dfa 100644
--- a/plugins/videotools.py
+++ b/plugins/videotools.py
@@ -91,7 +91,7 @@ async def gen_shots(e):
if not pic:
text = "`Failed to Take Screenshots..`"
pic = None
- await e.client.send_message(e.chat_id, text, file=pic)
+ await e.respond(text, file=pic)
await bash("rm -rf ss")
await xxx.delete()
diff --git a/pyUltroid/__init__.py b/pyUltroid/__init__.py
index bde4d32e40a5c8eceb99c39c545258926230727c..b104de6da869451eb55bc83154e4d568f8e528ae 100644
--- a/pyUltroid/__init__.py
+++ b/pyUltroid/__init__.py
@@ -10,15 +10,15 @@ import sys
from .version import __version__
-run_as_module = False
+run_as_module = __package__ in sys.argv or sys.argv[0] == "-m"
+
class ULTConfig:
lang = "en"
thumb = "resources/extras/ultroid.jpg"
-if sys.argv[0] == "-m":
- run_as_module = True
+if run_as_module:
import time
from .configs import Var
@@ -49,6 +49,10 @@ if sys.argv[0] == "-m":
BOT_MODE = udB.get_key("BOTMODE")
DUAL_MODE = udB.get_key("DUAL_MODE")
+ USER_MODE = udB.get_key("USER_MODE")
+ if USER_MODE:
+ DUAL_MODE = False
+
if BOT_MODE:
if DUAL_MODE:
udB.del_key("DUAL_MODE")
@@ -70,7 +74,10 @@ if sys.argv[0] == "-m":
)
ultroid_bot.run_in_loop(autobot())
- asst = UltroidClient(None, bot_token=udB.get_key("BOT_TOKEN"), udB=udB)
+ if USER_MODE:
+ asst = ultroid_bot
+ else:
+ asst = UltroidClient(None, bot_token=udB.get_key("BOT_TOKEN"), udB=udB)
if BOT_MODE:
ultroid_bot = asst
@@ -81,7 +88,7 @@ if sys.argv[0] == "-m":
)
except Exception as er:
LOGS.exception(er)
- elif not asst.me.bot_inline_placeholder:
+ elif not asst.me.bot_inline_placeholder and asst._bot:
ultroid_bot.run_in_loop(enable_inline(ultroid_bot, asst.me.username))
vcClient = vc_connection(udB, ultroid_bot)
diff --git a/pyUltroid/__main__.py b/pyUltroid/__main__.py
index 56a4d607e5fa534658a246dc473951521a66fb4d..c5249e86919e5f1f82933caecb8b6df8564e8502 100644
--- a/pyUltroid/__main__.py
+++ b/pyUltroid/__main__.py
@@ -13,17 +13,23 @@ def main():
import sys
import time
- from .fns.helper import time_formatter, updater, bash
+ from .fns.helper import bash, time_formatter, updater
from .startup.funcs import (
WasItRestart,
autopilot,
customize,
+ fetch_ann,
plug,
ready,
startup_stuff,
)
from .startup.loader import load_other_plugins
+ try:
+ from apscheduler.schedulers.asyncio import AsyncIOScheduler
+ except ImportError:
+ AsyncIOScheduler = None
+
# Option to Auto Update On Restarts..
if (
udB.get_key("UPDATE_ON_RESTART")
@@ -32,7 +38,7 @@ def main():
):
ultroid_bot.run_in_loop(bash("bash installer.sh"))
- os.execl(sys.executable, "python3", "-m", "pyUltroid")
+ os.execl(sys.executable, sys.executable, "-m", "pyUltroid")
ultroid_bot.run_in_loop(startup_stuff())
@@ -79,6 +85,10 @@ def main():
# Send/Ignore Deploy Message..
if not udB.get_key("LOG_OFF"):
ultroid_bot.run_in_loop(ready())
+ if AsyncIOScheduler:
+ scheduler = AsyncIOScheduler()
+ scheduler.add_job(fetch_ann, "interval", minutes=12 * 60)
+ scheduler.start()
# Edit Restarting Message (if It's restarting)
ultroid_bot.run_in_loop(WasItRestart(udB))
diff --git a/pyUltroid/_misc/_assistant.py b/pyUltroid/_misc/_assistant.py
index c326ee73bc2f7cd2fd5858d7e8f28346986e54dc..83afa459d4b993113079caadef027dd6ac563929 100644
--- a/pyUltroid/_misc/_assistant.py
+++ b/pyUltroid/_misc/_assistant.py
@@ -50,9 +50,16 @@ def asst_cmd(pattern=None, load=None, owner=False, **kwargs):
def ult(func):
if pattern:
kwargs["pattern"] = re.compile(f"^/{pattern}")
- if owner:
- kwargs["from_users"] = owner_and_sudos
- asst.add_event_handler(func, NewMessage(**kwargs))
+
+ async def handler(event):
+ if owner and event.sender_id not in owner_and_sudos():
+ return
+ try:
+ await func(event)
+ except Exception as er:
+ LOGS.exception(er)
+
+ asst.add_event_handler(handler, NewMessage(**kwargs))
if load is not None:
append_or_update(load, func, name, kwargs)
diff --git a/pyUltroid/_misc/_decorators.py b/pyUltroid/_misc/_decorators.py
index 72f1b87ed3aea4eaeecb32036097e644f1fcfdf6..bc93c9247e179037895556cddca8b1fdb03b6211 100644
--- a/pyUltroid/_misc/_decorators.py
+++ b/pyUltroid/_misc/_decorators.py
@@ -14,7 +14,6 @@ from pathlib import Path
from time import gmtime, strftime
from traceback import format_exc
-from strings import get_string
from telethon import Button
from telethon import __version__ as telever
from telethon import events
@@ -35,6 +34,9 @@ from telethon.errors.rpcerrorlist import (
from telethon.events import MessageEdited, NewMessage
from telethon.utils import get_display_name
+from pyUltroid.exceptions import DependencyMissingError
+from strings import get_string
+
from .. import *
from .. import _ignore_eval
from ..dB import DEVLIST
@@ -96,19 +98,16 @@ def ultroid_cmd(
and not (ult.sender_id in DEVLIST)
):
return
- if admins_only:
- if ult.is_private:
- return await eod(ult, get_string("py_d3"))
- if not (chat.admin_rights or chat.creator):
- return await eod(ult, get_string("py_d5"))
+ if ult.is_private and (groups_only or admins_only):
+ return await eod(ult, get_string("py_d3"))
+ elif admins_only and not (chat.admin_rights or chat.creator):
+ return await eod(ult, get_string("py_d5"))
if only_devs and not udB.get_key("I_DEV"):
return await eod(
ult,
get_string("py_d4").format(HNDLR),
time=10,
)
- if groups_only and ult.is_private:
- return await eod(ult, get_string("py_d5"))
try:
await dec(ult)
except FloodWaitError as fwerr:
@@ -135,7 +134,7 @@ def ultroid_cmd(
ult,
get_string("py_d7"),
)
- except (BotInlineDisabledError) as er:
+ except (BotInlineDisabledError, DependencyMissingError) as er:
return await eod(ult, f"`{er}`")
except (
MessageIdInvalidError,
diff --git a/pyUltroid/_misc/_wrappers.py b/pyUltroid/_misc/_wrappers.py
index 01c4378ee6eb7ee6db6aa8e86379a9550bca98de..ee6dd345d3ba9d6238a1691812e071d1eddd8733 100644
--- a/pyUltroid/_misc/_wrappers.py
+++ b/pyUltroid/_misc/_wrappers.py
@@ -19,7 +19,7 @@ async def eor(event, text=None, time=None, link_preview=False, edit_time=None, *
if event.out and not isinstance(event, MessageService):
if edit_time:
await sleep(edit_time)
- if "file" in args and args["file"] and not event.media:
+ if args.get("file") and not event.media:
await event.delete()
ok = await event.client.send_message(
event.chat_id,
diff --git a/pyUltroid/dB/asst_fns.py b/pyUltroid/dB/asst_fns.py
deleted file mode 100644
index 9a6b933aa461908ab5bcc51844c0d8acd634c312..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/asst_fns.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-
-from .. import udB
-
-
-def get_all_users(key):
- return udB.get_key(key) or []
-
-
-def is_added(id_):
- return id_ in get_all_users("BOT_USERS")
-
-
-def add_user(id_):
- users = get_all_users("BOT_USERS")
- users.append(id_)
- return udB.set_key("BOT_USERS", users)
-
-
-def is_blacklisted(id_):
- return id_ in get_all_users("BOT_BLS")
-
-
-def blacklist_user(id_):
- users = get_all_users("BOT_BLS")
- users.append(id_)
- return udB.set_key("BOT_BLS", users)
-
-
-def rem_blacklist(id_):
- users = get_all_users("BOT_BLS")
- users.remove(id_)
- return udB.set_key("BOT_BLS", users)
diff --git a/pyUltroid/dB/autoban_db.py b/pyUltroid/dB/autoban_db.py
deleted file mode 100644
index dd91d21249830e2ee988f0a45782295ff55bb288..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/autoban_db.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from .. import udB
-
-
-def get_all_channels() -> dict:
- """List all chats where channels are banned."""
- return udB.get_key("AUTOBAN_CHANNELS") or {}
-
-
-def is_autoban_enabled(chat_id: int) -> bool:
- """Check whether channels are banned in a specific chat or not."""
- return chat_id in get_all_channels()
-
-
-def add_channel(chat_id: int) -> bool:
- """Enable channel ban in a given chat."""
- if not is_autoban_enabled(int(chat_id)):
- channels = get_all_channels()
- channels[int(chat_id)] = []
- return udB.set_key("AUTOBAN_CHANNELS", channels)
-
-
-def del_channel(chat_id: int) -> bool:
- """Disable channel ban in a given chat."""
- if is_autoban_enabled(chat_id):
- channels = get_all_channels()
- channels.pop(int(chat_id))
- return udB.set_key("AUTOBAN_CHANNELS", channels)
-
-
-def get_whitelisted_channels(chat_id: int) -> list:
- """Get list of whitelisted channels in a given chat."""
- return get_all_channels()[chat_id] if is_autoban_enabled(chat_id) else []
-
-
-def is_whitelisted(chat_id: int, channel_id: int) -> bool:
- """Check whether given channel is whitelisted in given chat or not."""
- return channel_id in get_whitelisted_channels(chat_id)
-
-
-def add_to_whitelist(chat_id: int, channel_id: int) -> bool:
- """Add a channel in whitelist in a chat."""
- if is_autoban_enabled(chat_id):
- if not is_whitelisted(chat_id, channel_id):
- channels = get_all_channels()
- channels[int(chat_id)].append(int(channel_id))
- return udB.set_key("AUTOBAN_CHANNELS", channels)
-
-
-def del_from_whitelist(chat_id: int, channel_id: int) -> bool:
- """Remove a channel from whitelist in a chat."""
- if is_autoban_enabled(chat_id):
- if is_whitelisted(chat_id, channel_id):
- channels = get_all_channels()
- channels[int(chat_id)].remove(int(channel_id))
- return udB.set_key("AUTOBAN_CHANNELS", channels)
diff --git a/pyUltroid/dB/base.py b/pyUltroid/dB/base.py
new file mode 100644
index 0000000000000000000000000000000000000000..de26c1542de1ee1144bd70f458e83a3f45e8b3d5
--- /dev/null
+++ b/pyUltroid/dB/base.py
@@ -0,0 +1,44 @@
+from .. import udB
+
+
+class KeyManager:
+ def __init__(self, key, cast=None) -> None:
+ self._key = key
+ self._cast = cast
+
+ def get(self):
+ _data = udB.get_key(self._key)
+ if self._cast and not isinstance(_data, self._cast):
+ return [_data] if self._cast == list else self._cast(_data)
+ return _data or (self._cast() if callable(self._cast) else self._cast)
+
+ def get_child(self, key):
+ return self.get()[key]
+
+ def count(self):
+ return len(self.get())
+
+ def add(self, item):
+ content = self.get()
+ if content == None and callable(type(item)):
+ content = type(item)()
+ if isinstance(content, dict) and isinstance(item, dict):
+ content.update(item)
+ elif isinstance(content, list) and item not in content:
+ content.append(item)
+ else:
+ return
+ udB.set_key(self._key, content)
+
+ def remove(self, item):
+ content = self.get()
+ if isinstance(content, list) and item in content:
+ content.remove(item)
+ elif isinstance(content, dict) and content.get(item):
+ del content[item]
+ else:
+ return
+ udB.set_key(self._key, content)
+
+ def contains(self, item):
+ return item in self.get()
diff --git a/pyUltroid/dB/broadcast_db.py b/pyUltroid/dB/broadcast_db.py
deleted file mode 100644
index d391aa3d5fe30293791944547a908bc0f7830550..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/broadcast_db.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-
-from .. import udB
-
-
-def get_channels(): # Returns List
- return udB.get_key("BROADCAST") or []
-
-
-def is_channel_added(id_):
- return id_ in get_channels()
-
-
-def add_channel(id_):
- channels = get_channels()
- if id_ not in channels:
- channels.append(id_)
- udB.set_key("BROADCAST", channels)
- return True
-
-
-def rem_channel(id_):
- channels = get_channels()
- if id_ in channels:
- channels.remove(id_)
- udB.set_key("BROADCAST", channels)
- return True
- return False
diff --git a/pyUltroid/dB/ch_db.py b/pyUltroid/dB/ch_db.py
deleted file mode 100644
index 142a1b821af411e3e6c50357f56f7fe70b54a191..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/ch_db.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-
-from .. import udB
-
-
-def get_source_channels(): # Returns List
- return udB.get_key("CH_SOURCE") or []
-
-
-def get_no_source_channels(): # Returns List
- channels = udB.get_key("CH_SOURCE") or []
- return len(channels)
-
-
-def is_source_channel_added(id_):
- channels = get_source_channels()
- return id_ in channels
-
-
-def add_source_channel(id_): # Take int or str with numbers only , Returns Boolean
- channels = get_source_channels()
- if id_ not in channels:
- channels.append(id_)
- udB.set_key("CH_SOURCE", channels)
- return True
-
-
-def rem_source_channel(id_):
- channels = get_source_channels()
- if id_ in channels:
- channels.remove(id_)
- udB.set_key("CH_SOURCE", channels)
- return True
-
-
-#########################
-
-
-def get_destinations(): # Returns List
- return udB.get_key("CH_DESTINATION") or []
-
-
-def get_no_destinations(): # Returns List
- channels = udB.get_key("CH_DESTINATION") or []
- return len(channels)
-
-
-def is_destination_added(id_):
- channels = get_destinations()
- return id_ in channels
-
-
-def add_destination(id_): # Take int or str with numbers only , Returns Boolean
- channels = get_destinations()
- if id_ not in channels:
- channels.append(id_)
- udB.set_key("CH_DESTINATION", channels)
- return True
-
-
-def rem_destination(id_):
- channels = get_destinations()
- if id_ in channels:
- channels.remove(id_)
- udB.set_key("CH_DESTINATION", channels)
- return True
diff --git a/pyUltroid/dB/dnd_db.py b/pyUltroid/dB/dnd_db.py
deleted file mode 100644
index be49e9de710a8d85e44a86a6344c7a52d4b0fbae..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/dnd_db.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-
-
-from .. import udB
-
-
-def get_dnd_chats():
- return udB.get_key("DND_CHATS") or []
-
-
-def add_dnd(chat_id):
- x = get_dnd_chats()
- x.append(int(chat_id))
- return udB.set_key("DND_CHATS", x)
-
-
-def del_dnd(chat_id):
- x = get_dnd_chats()
- x.remove(int(chat_id))
- return udB.set_key("DND_CHATS", x)
-
-
-def chat_in_dnd(chat_id):
- return int(chat_id) in get_dnd_chats()
diff --git a/pyUltroid/dB/gcast_blacklist_db.py b/pyUltroid/dB/gcast_blacklist_db.py
deleted file mode 100644
index 2622944bf7ec84657564c7ff41bced8fcfc846e2..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/gcast_blacklist_db.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-from .. import udB
-
-
-def get_stuff():
- return udB.get_key("GBLACKLISTS") or []
-
-
-def add_gblacklist(id):
- ok = get_stuff()
- if id not in ok:
- ok.append(id)
- return udB.set_key("GBLACKLISTS", ok)
-
-
-def rem_gblacklist(id):
- ok = get_stuff()
- if id in ok:
- ok.remove(id)
- return udB.set_key("GBLACKLISTS", ok)
-
-
-def is_gblacklisted(id):
- return id in get_stuff()
diff --git a/pyUltroid/dB/logusers_db.py b/pyUltroid/dB/logusers_db.py
deleted file mode 100644
index e77cba970dae7f78647967ffb9e761b0db580faa..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/logusers_db.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-
-from .. import udB
-
-
-def get_logger():
- return udB.get_key("LOGUSERS") or []
-
-
-def is_logger(id_):
- return id_ in get_logger()
-
-
-def log_user(id_):
- pmperm = get_logger()
- pmperm.append(id_)
- return udB.set_key("LOGUSERS", pmperm)
-
-
-def nolog_user(id_):
- pmperm = get_logger()
- pmperm.remove(id_)
- return udB.set_key("LOGUSERS", pmperm)
diff --git a/pyUltroid/dB/night_db.py b/pyUltroid/dB/night_db.py
deleted file mode 100644
index daf2a113bed33ecde0e629689076c57621e7e052..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/night_db.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-
-from .. import udB
-
-
-def night_grps():
- return udB.get_key("NIGHT_CHATS") or []
-
-
-def add_night(chat):
- chats = night_grps()
- if chat not in chats:
- chats.append(chat)
- return udB.set_key("NIGHT_CHATS", chats)
- return
-
-
-def rem_night(chat):
- chats = night_grps()
- if chat in chats:
- chats.remove(chat)
- return udB.set_key("NIGHT_CHATS", chats)
diff --git a/pyUltroid/dB/pmpermit_db.py b/pyUltroid/dB/pmpermit_db.py
deleted file mode 100644
index 28842dccba81307f1ccd2f70a5882ce6de91ef15..0000000000000000000000000000000000000000
--- a/pyUltroid/dB/pmpermit_db.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Ultroid - UserBot
-# Copyright (C) 2021-2022 TeamUltroid
-#
-# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
-# PLease read the GNU Affero General Public License in
-# .
-
-from .. import udB
-
-
-def get_approved():
- return udB.get_key("PMPERMIT") or []
-
-
-def approve_user(id):
- ok = get_approved()
- if id in ok:
- return True
- ok.append(id)
- return udB.set_key("PMPERMIT", ok)
-
-
-def disapprove_user(id):
- ok = get_approved()
- if id in ok:
- ok.remove(id)
- return udB.set_key("PMPERMIT", ok)
-
-
-def is_approved(id):
- return id in get_approved()
diff --git a/pyUltroid/exceptions.py b/pyUltroid/exceptions.py
index 3c14e4e9a2db226a1d2dfc7a891da234e3a65dc4..c53ea7d3c6a1722a2d36531c1a3a467c7c0ceb6e 100644
--- a/pyUltroid/exceptions.py
+++ b/pyUltroid/exceptions.py
@@ -14,10 +14,6 @@ class pyUltroidError(Exception):
...
-class TelethonMissingError(ImportError):
- ...
-
-
class DependencyMissingError(ImportError):
...
diff --git a/pyUltroid/fns/FastTelethon.py b/pyUltroid/fns/FastTelethon.py
index fe3d7756433b326243f44ce1057a7d30ce8d2e1b..991b6175d51716992f143c3985c879b6aa123370 100644
--- a/pyUltroid/fns/FastTelethon.py
+++ b/pyUltroid/fns/FastTelethon.py
@@ -173,7 +173,7 @@ class ParallelTransferrer:
def _get_connection_count(
file_size: int,
) -> int:
- full_size = 100 * (1024**2)
+ full_size = 100 * (1024 ** 2)
if file_size > full_size:
return 20
return math.ceil((file_size / full_size) * 20)
@@ -283,7 +283,7 @@ class ParallelTransferrer:
connection_count = connection_count or self._get_connection_count(file_size)
part_size = (part_size_kb or utils.get_appropriated_part_size(file_size)) * 1024
part_count = (file_size + part_size - 1) // part_size
- is_large = file_size > 10 * (1024**2)
+ is_large = file_size > 10 * (1024 ** 2)
await self._init_upload(connection_count, file_id, part_count, is_large)
return part_size, part_count, is_large
diff --git a/pyUltroid/fns/executor.py b/pyUltroid/fns/executor.py
index 4cd972769903d38352bbe1a920506f6f986e536e..06226842b577d0d8d8c3d29d026812227e1c8def 100644
--- a/pyUltroid/fns/executor.py
+++ b/pyUltroid/fns/executor.py
@@ -74,7 +74,3 @@ class Terminal:
self._processes.pop(proc)
except KeyError:
pass
-
-
-class Executor:
- pass
diff --git a/pyUltroid/fns/google_image.py b/pyUltroid/fns/google_image.py
deleted file mode 100644
index b6e2a7384587487c69b5058b85c9bbfcf37941ce..0000000000000000000000000000000000000000
--- a/pyUltroid/fns/google_image.py
+++ /dev/null
@@ -1,1159 +0,0 @@
-#!/usr/bin/env python
-# In[ ]:
-# coding: utf-8
-
-###### Searching and Downloading Google Images to the local disk ######
-
-
-import codecs
-import datetime
-import http.client
-import json
-import os
-import re
-import ssl
-import sys
-import time # Importing the time library to check the time of code execution
-import urllib.request
-from http.client import BadStatusLine
-from urllib.parse import quote
-from urllib.request import HTTPError, Request, URLError, urlopen
-
-# Import Libraries
-from .. import LOGS
-from .tools import async_searcher
-
-http.client._MAXHEADERS = 1000
-
-args_list = [
- "keywords",
- "keywords_from_file",
- "prefix_keywords",
- "suffix_keywords",
- "limit",
- "format",
- "color",
- "color_type",
- "usage_rights",
- "size",
- "exact_size",
- "aspect_ratio",
- "type",
- "time",
- "time_range",
- "delay",
- "url",
- "single_image",
- "output_directory",
- "image_directory",
- "no_directory",
- "proxy",
- "similar_images",
- "specific_site",
- "metadata",
- "extract_metadata",
- "socket_timeout",
- "thumbnail",
- "thumbnail_only",
- "language",
- "prefix",
- "chromedriver",
- "related_images",
- "safe_search",
- "no_numbering",
- "offset",
- "no_download",
- "save_source",
- "ignore_urls",
-]
-
-
-class googleimagesdownload:
- def __init__(self):
- pass
-
- # Downloading entire Web Document (Raw Page Content)
- async def download_page(self, url):
- try:
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36"
- }
-
- # req = urllib.request.Request(url, headers=headers)
- # resp = urllib.request.urlopen(req)
- # return str(resp.read())
- resp = await async_searcher(url, re_content=True, headers=headers)
- return str(resp)
- except Exception as er:
- LOGS.exception(
- "Could not open URL. Please check your internet connection and/or ssl settings \n"
- "If you are using proxy, make sure your proxy settings is configured correctly"
- )
- raise er
-
- # Download Page for more than 100 images
-
- def download_extended_page(self, url, chromedriver):
- from selenium import webdriver
- from selenium.webdriver.common.keys import Keys
-
- options = webdriver.ChromeOptions()
- options.add_argument("--no-sandbox")
- options.add_argument("--headless")
-
- try:
- browser = webdriver.Chrome(chromedriver, chrome_options=options)
- except Exception as e:
- LOGS.info(
- "Looks like we cannot locate the path the 'chromedriver' (use the '--chromedriver' "
- "argument to specify the path to the executable.) or google chrome browser is not "
- "installed on your machine (exception: %s)" % e
- )
- sys.exit()
- browser.set_window_size(1024, 768)
-
- # Open the link
- browser.get(url)
- time.sleep(1)
-
- element = browser.find_element_by_tag_name("body")
- # Scroll down
- for i in range(30):
- element.send_keys(Keys.PAGE_DOWN)
- time.sleep(0.3)
-
- try:
- browser.find_element_by_id("smb").click()
- for _ in range(50):
- element.send_keys(Keys.PAGE_DOWN)
- time.sleep(0.3) # bot id protection
- except BaseException:
- for _ in range(10):
- element.send_keys(Keys.PAGE_DOWN)
- time.sleep(0.3) # bot id protection
-
- time.sleep(0.5)
-
- source = browser.page_source # page source
- # close the browser
- browser.close()
-
- return source
-
- # Correcting the escape characters for python2
-
- def replace_with_byte(self, match):
- return chr(int(match.group(0)[1:], 8))
-
- def repair(self, brokenjson):
- # up to 3 digits for byte values up to FF
- invalid_escape = re.compile(r"\\[0-7]{1,3}")
- return invalid_escape.sub(self.replace_with_byte, brokenjson)
-
- # Finding 'Next Image' from the given raw page
-
- def get_next_tab(self, s):
- start_line = s.find('class="dtviD"')
- if start_line == -1: # If no links are found then give an error!
- end_quote = 0
- link = "no_tabs"
- return link, "", end_quote
- start_line = s.find('class="dtviD"')
- start_content = s.find('href="', start_line + 1)
- end_content = s.find('">', start_content + 1)
- url_item = "https://www.google.com" + str(s[start_content + 6 : end_content])
- url_item = url_item.replace("&", "&")
- start_line_2 = s.find('class="dtviD"')
- s = s.replace("&", "&")
- start_content_2 = s.find(":", start_line_2 + 1)
- end_content_2 = s.find("&usg=", start_content_2 + 1)
- url_item_name = str(s[start_content_2 + 1 : end_content_2])
- chars = url_item_name.find(",g_1:")
- chars_end = url_item_name.find(":", chars + 6)
- if chars_end == -1:
- updated_item_name = (url_item_name[chars + 5 :]).replace("+", " ")
- else:
- updated_item_name = (url_item_name[chars + 5 : chars_end]).replace("+", " ")
- return url_item, updated_item_name, end_content
-
- # Getting all links with the help of '_images_get_next_image'
-
- def get_all_tabs(self, page):
- tabs = {}
- while True:
- item, item_name, end_content = self.get_next_tab(page)
- if item == "no_tabs":
- break
- if len(item_name) > 100 or item_name == "background-color":
- break
- # Append all the links in the list named 'Links'
- tabs[item_name] = item
- # Timer could be used to slow down the request for image
- # downloads
- time.sleep(0.1)
- page = page[end_content:]
- return tabs
-
- # Format the object in readable format
-
- def format_object(self, object):
- data = object[1]
- main = data[3]
- info = data[9]
- return {
- "image_height": main[2],
- "image_width": main[1],
- "image_link": main[0],
- "image_format": main[0][-1 * (len(main[0]) - main[0].rfind(".") - 1) :],
- "image_description": info["2003"][3],
- "image_source": info["2003"][2],
- "image_thumbnail_url": data[2][0],
- }
-
- # function to download single image
-
- def single_image(self, image_url):
- main_directory = "downloads"
- extensions = (".jpg", ".gif", ".png", ".bmp", ".svg", ".webp", ".ico")
- url = image_url
- try:
- os.makedirs(main_directory)
- except OSError as e:
- if e.errno != 17:
- raise
- req = Request(
- url,
- headers={
- "User-Agent": "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17"
- },
- )
-
- response = urlopen(req, None, 10)
- data = response.read()
- response.close()
-
- image_name = str(url[(url.rfind("/")) + 1 :])
- if "?" in image_name:
- image_name = image_name[: image_name.find("?")]
- # if ".jpg" in image_name or ".gif" in image_name or ".png" in
- # image_name or ".bmp" in image_name or ".svg" in image_name or ".webp"
- # in image_name or ".ico" in image_name:
- if any(map(lambda extension: extension in image_name, extensions)):
- file_name = main_directory + "/" + image_name
- else:
- file_name = main_directory + "/" + image_name + ".jpg"
- image_name = image_name + ".jpg"
-
- try:
- with open(file_name, "wb") as output_file:
- output_file.write(data)
- except OSError as e:
- raise e
-
- def similar_images(self, similar_images):
- try:
- searchUrl = (
- "https://www.google.com/searchbyimage?site=search&sa=X&image_url="
- + similar_images
- )
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
- }
-
- req1 = urllib.request.Request(searchUrl, headers=headers)
- resp1 = urllib.request.urlopen(req1)
- content = str(resp1.read())
- l1 = content.find("AMhZZ")
- l2 = content.find("&", l1)
- urll = content[l1:l2]
-
- newurl = (
- "https://www.google.com/search?tbs=sbi:" + urll + "&site=search&sa=X"
- )
- req2 = urllib.request.Request(newurl, headers=headers)
- urllib.request.urlopen(req2)
- l3 = content.find("/search?sa=X&q=")
- l4 = content.find(";", l3 + 19)
- return content[l3 + 19 : l4]
- except BaseException:
- return "Cloud not connect to Google Images endpoint"
-
- # Building URL parameters
- def build_url_parameters(self, arguments):
- if arguments["language"]:
- lang = "&lr="
- lang_param = {
- "Arabic": "lang_ar",
- "Chinese (Simplified)": "lang_zh-CN",
- "Chinese (Traditional)": "lang_zh-TW",
- "Czech": "lang_cs",
- "Danish": "lang_da",
- "Dutch": "lang_nl",
- "English": "lang_en",
- "Estonian": "lang_et",
- "Finnish": "lang_fi",
- "French": "lang_fr",
- "German": "lang_de",
- "Greek": "lang_el",
- "Hebrew": "lang_iw ",
- "Hungarian": "lang_hu",
- "Icelandic": "lang_is",
- "Italian": "lang_it",
- "Japanese": "lang_ja",
- "Korean": "lang_ko",
- "Latvian": "lang_lv",
- "Lithuanian": "lang_lt",
- "Norwegian": "lang_no",
- "Portuguese": "lang_pt",
- "Polish": "lang_pl",
- "Romanian": "lang_ro",
- "Russian": "lang_ru",
- "Spanish": "lang_es",
- "Swedish": "lang_sv",
- "Turkish": "lang_tr",
- }
- lang_url = lang + lang_param[arguments["language"]]
- else:
- lang_url = ""
-
- if arguments["time_range"]:
- json_acceptable_string = arguments["time_range"].replace("'", '"')
- d = json.loads(json_acceptable_string)
- time_range = ",cdr:1,cd_min:" + d["time_min"] + ",cd_max:" + d["time_max"]
- else:
- time_range = ""
-
- if arguments["exact_size"]:
- size_array = [x.strip() for x in arguments["exact_size"].split(",")]
- exact_size = (
- ",isz:ex,iszw:" + str(size_array[0]) + ",iszh:" + str(size_array[1])
- )
- else:
- exact_size = ""
-
- built_url = "&tbs="
- counter = 0
- params = {
- "color": [
- arguments["color"],
- {
- "red": "ic:specific,isc:red",
- "orange": "ic:specific,isc:orange",
- "yellow": "ic:specific,isc:yellow",
- "green": "ic:specific,isc:green",
- "teal": "ic:specific,isc:teel",
- "blue": "ic:specific,isc:blue",
- "purple": "ic:specific,isc:purple",
- "pink": "ic:specific,isc:pink",
- "white": "ic:specific,isc:white",
- "gray": "ic:specific,isc:gray",
- "black": "ic:specific,isc:black",
- "brown": "ic:specific,isc:brown",
- },
- ],
- "color_type": [
- arguments["color_type"],
- {
- "full-color": "ic:color",
- "black-and-white": "ic:gray",
- "transparent": "ic:trans",
- },
- ],
- "usage_rights": [
- arguments["usage_rights"],
- {
- "labeled-for-reuse-with-modifications": "sur:fmc",
- "labeled-for-reuse": "sur:fc",
- "labeled-for-noncommercial-reuse-with-modification": "sur:fm",
- "labeled-for-nocommercial-reuse": "sur:f",
- },
- ],
- "size": [
- arguments["size"],
- {
- "large": "isz:l",
- "medium": "isz:m",
- "icon": "isz:i",
- ">400*300": "isz:lt,islt:qsvga",
- ">640*480": "isz:lt,islt:vga",
- ">800*600": "isz:lt,islt:svga",
- ">1024*768": "visz:lt,islt:xga",
- ">2MP": "isz:lt,islt:2mp",
- ">4MP": "isz:lt,islt:4mp",
- ">6MP": "isz:lt,islt:6mp",
- ">8MP": "isz:lt,islt:8mp",
- ">10MP": "isz:lt,islt:10mp",
- ">12MP": "isz:lt,islt:12mp",
- ">15MP": "isz:lt,islt:15mp",
- ">20MP": "isz:lt,islt:20mp",
- ">40MP": "isz:lt,islt:40mp",
- ">70MP": "isz:lt,islt:70mp",
- },
- ],
- "type": [
- arguments["type"],
- {
- "face": "itp:face",
- "photo": "itp:photo",
- "clipart": "itp:clipart",
- "line-drawing": "itp:lineart",
- "animated": "itp:animated",
- },
- ],
- "time": [
- arguments["time"],
- {
- "past-24-hours": "qdr:d",
- "past-7-days": "qdr:w",
- "past-month": "qdr:m",
- "past-year": "qdr:y",
- },
- ],
- "aspect_ratio": [
- arguments["aspect_ratio"],
- {
- "tall": "iar:t",
- "square": "iar:s",
- "wide": "iar:w",
- "panoramic": "iar:xw",
- },
- ],
- "format": [
- arguments["format"],
- {
- "jpg": "ift:jpg",
- "gif": "ift:gif",
- "png": "ift:png",
- "bmp": "ift:bmp",
- "svg": "ift:svg",
- "webp": "webp",
- "ico": "ift:ico",
- "raw": "ift:craw",
- },
- ],
- }
- for value in params.values():
- if value[0] is not None:
- ext_param = value[1][value[0]]
- # counter will tell if it is first param added or not
- if counter == 0:
- # add it to the built url
- built_url += ext_param
- else:
- built_url = built_url + "," + ext_param
- counter += 1
- built_url = lang_url + built_url + exact_size + time_range
- return built_url
-
- # building main search URL
-
- def build_search_url(
- self, search_term, params, url, similar_images, specific_site, safe_search
- ):
- # check the args and choose the URL
- if url:
- url = url
- elif similar_images:
- keywordem = self.similar_images(similar_images)
- url = (
- "https://www.google.com/search?q="
- + keywordem
- + "&espv=2&biw=1366&bih=667&site=webhp&source=lnms&tbm=isch&sa=X&ei=XosDVaCXD8TasATItgE&ved=0CAcQ_AUoAg"
- )
- elif specific_site:
- url = (
- "https://www.google.com/search?q="
- + quote(search_term.encode("utf-8"))
- + "&as_sitesearch="
- + specific_site
- + "&espv=2&biw=1366&bih=667&site=webhp&source=lnms&tbm=isch"
- + params
- + "&sa=X&ei=XosDVaCXD8TasATItgE&ved=0CAcQ_AUoAg"
- )
- else:
- url = (
- "https://www.google.com/search?q="
- + quote(search_term.encode("utf-8"))
- + "&espv=2&biw=1366&bih=667&site=webhp&source=lnms&tbm=isch"
- + params
- + "&sa=X&ei=XosDVaCXD8TasATItgE&ved=0CAcQ_AUoAg"
- )
-
- # safe search check
- if safe_search:
- # check safe_search
- safe_search_string = "&safe=active"
- url = url + safe_search_string
-
- return url
-
- # measures the file size
-
- def file_size(self, file_path):
- if os.path.isfile(file_path):
- file_info = os.stat(file_path)
- size = file_info.st_size
- for x in ["bytes", "KB", "MB", "GB", "TB"]:
- if size < 1024.0:
- return "%3.1f %s" % (size, x)
- size /= 1024.0
- return size
-
- # keywords from file
- def keywords_from_file(self, file_name):
- search_keyword = []
- with codecs.open(file_name, "r", encoding="utf-8-sig") as f:
- if ".csv" in file_name or ".txt" in file_name:
- for line in f:
- if line not in ["\n", "\r\n"]:
- search_keyword.append(line.replace("\n", "").replace("\r", ""))
- else:
- LOGS.info(
- "Invalid file type: Valid file types are either .txt or .csv \n"
- "exiting..."
- )
- sys.exit()
- return search_keyword
-
- # make directories
- def create_directories(self, main_directory, dir_name, thumbnail, thumbnail_only):
- dir_name_thumbnail = dir_name + " - thumbnail"
- # make a search keyword directory
- try:
- if not os.path.exists(main_directory):
- os.makedirs(main_directory)
- time.sleep(0.15)
- path = dir_name
- sub_directory = os.path.join(main_directory, path)
- if not os.path.exists(sub_directory):
- os.makedirs(sub_directory)
- if thumbnail or thumbnail_only:
- sub_directory_thumbnail = os.path.join(
- main_directory, dir_name_thumbnail
- )
- if not os.path.exists(sub_directory_thumbnail):
- os.makedirs(sub_directory_thumbnail)
- except OSError as e:
- if e.errno != 17:
- raise
-
- # Download Image thumbnails
-
- def download_image_thumbnail(
- self,
- image_url,
- main_directory,
- dir_name,
- return_image_name,
- socket_timeout,
- no_download,
- save_source,
- img_src,
- ):
- if no_download:
- return "success", "Printed url without downloading"
- try:
- req = Request(
- image_url,
- headers={
- "User-Agent": "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17"
- },
- )
- try:
- # timeout time to download an image
- timeout = float(socket_timeout) if socket_timeout else 10
- response = urlopen(req, None, timeout)
- data = response.read()
- response.close()
-
- path = (
- main_directory
- + "/"
- + dir_name
- + " - thumbnail"
- + "/"
- + return_image_name
- )
-
- try:
- with open(path, "wb") as output_file:
- output_file.write(data)
- if save_source:
- list_path = main_directory + "/" + save_source + ".txt"
- with open(list_path, "a") as list_file:
- list_file.write(path + "\t" + img_src + "\n")
- except OSError as e:
- download_status = "fail"
- download_message = (
- "OSError on an image...trying next one..." + " Error: " + str(e)
- )
-
- download_status = "success"
- download_message = (
- "Completed Image Thumbnail ====> " + return_image_name
- )
-
- except UnicodeEncodeError as e:
- download_status = "fail"
- download_message = (
- "UnicodeEncodeError on an image...trying next one..."
- + " Error: "
- + str(e)
- )
-
- except HTTPError as e: # If there is any HTTPError
- download_status = "fail"
- download_message = (
- "HTTPError on an image...trying next one..." + " Error: " + str(e)
- )
-
- except URLError as e:
- download_status = "fail"
- download_message = (
- "URLError on an image...trying next one..." + " Error: " + str(e)
- )
-
- except ssl.CertificateError as e:
- download_status = "fail"
- download_message = (
- "CertificateError on an image...trying next one..."
- + " Error: "
- + str(e)
- )
-
- except IOError as e: # If there is any IOError
- download_status = "fail"
- download_message = (
- "IOError on an image...trying next one..." + " Error: " + str(e)
- )
- return download_status, download_message
-
- # Download Images
-
- def download_image(
- self,
- image_url,
- image_format,
- main_directory,
- dir_name,
- count,
- socket_timeout,
- prefix,
- no_numbering,
- no_download,
- save_source,
- img_src,
- thumbnail_only,
- format,
- ignore_urls,
- ):
- if ignore_urls and any(url in image_url for url in ignore_urls.split(",")):
- return (
- "fail",
- "Image ignored due to 'ignore url' parameter",
- None,
- image_url,
- )
- if thumbnail_only:
- return (
- "success",
- "Skipping image download...",
- str(image_url[(image_url.rfind("/")) + 1 :]),
- image_url,
- )
- if no_download:
- return "success", "Printed url without downloading", None, image_url
- try:
- req = Request(
- image_url,
- headers={
- "User-Agent": "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17"
- },
- )
- try:
- # timeout time to download an image
- timeout = float(socket_timeout) if socket_timeout else 10
- response = urlopen(req, None, timeout)
- data = response.read()
- response.close()
-
- extensions = [
- ".jpg",
- ".jpeg",
- ".gif",
- ".png",
- ".bmp",
- ".svg",
- ".webp",
- ".ico",
- ]
- # keep everything after the last '/'
- image_name = str(image_url[(image_url.rfind("/")) + 1 :])
- if format and (not image_format or image_format != format):
- download_status = "fail"
- download_message = "Wrong image format returned. Skipping..."
- return_image_name = ""
- absolute_path = ""
- return (
- download_status,
- download_message,
- return_image_name,
- absolute_path,
- )
-
- if (
- image_format == ""
- or not image_format
- or "." + image_format not in extensions
- ):
- download_status = "fail"
- download_message = "Invalid or missing image format. Skipping..."
- return_image_name = ""
- absolute_path = ""
- return (
- download_status,
- download_message,
- return_image_name,
- absolute_path,
- )
- if image_name.lower().find("." + image_format) < 0:
- image_name = image_name + "." + image_format
- else:
- image_name = image_name[
- : image_name.lower().find("." + image_format)
- + (len(image_format) + 1)
- ]
-
- # prefix name in image
- prefix = prefix + " " if prefix else ""
- if no_numbering:
- path = main_directory + "/" + dir_name + "/" + prefix + image_name
- else:
- path = (
- main_directory
- + "/"
- + dir_name
- + "/"
- + prefix
- + str(count)
- + "."
- + image_name
- )
- try:
- with open(path, "wb") as output_file:
- output_file.write(data)
- if save_source:
- list_path = main_directory + "/" + save_source + ".txt"
- with open(list_path, "a") as list_file:
- list_file.write(path + "\t" + img_src + "\n")
- absolute_path = os.path.abspath(path)
- except OSError as e:
- download_status = "fail"
- download_message = (
- "OSError on an image...trying next one..." + " Error: " + str(e)
- )
- return_image_name = ""
- absolute_path = ""
-
- # return image name back to calling method to use it for
- # thumbnail downloads
- download_status = "success"
- download_message = (
- "Completed Image ====> " + prefix + str(count) + "." + image_name
- )
- return_image_name = prefix + str(count) + "." + image_name
-
- except UnicodeEncodeError as e:
- download_status = "fail"
- download_message = (
- "UnicodeEncodeError on an image...trying next one..."
- + " Error: "
- + str(e)
- )
- return_image_name = ""
- absolute_path = ""
-
- except URLError as e:
- download_status = "fail"
- download_message = (
- "URLError on an image...trying next one..." + " Error: " + str(e)
- )
- return_image_name = ""
- absolute_path = ""
-
- except BadStatusLine as e:
- download_status = "fail"
- download_message = (
- "BadStatusLine on an image...trying next one..."
- + " Error: "
- + str(e)
- )
- return_image_name = ""
- absolute_path = ""
-
- except HTTPError as e: # If there is any HTTPError
- download_status = "fail"
- download_message = (
- "HTTPError on an image...trying next one..." + " Error: " + str(e)
- )
- return_image_name = ""
- absolute_path = ""
-
- except URLError as e:
- download_status = "fail"
- download_message = (
- "URLError on an image...trying next one..." + " Error: " + str(e)
- )
- return_image_name = ""
- absolute_path = ""
-
- except ssl.CertificateError as e:
- download_status = "fail"
- download_message = (
- "CertificateError on an image...trying next one..."
- + " Error: "
- + str(e)
- )
- return_image_name = ""
- absolute_path = ""
-
- except IOError as e: # If there is any IOError
- download_status = "fail"
- download_message = (
- "IOError on an image...trying next one..." + " Error: " + str(e)
- )
- return_image_name = ""
- absolute_path = ""
-
- return download_status, download_message, return_image_name, absolute_path
-
- # Finding 'Next Image' from the given raw page
-
- def _get_next_item(self, s):
- start_line = s.find("rg_meta notranslate")
- if start_line == -1: # If no links are found then give an error!
- end_quote = 0
- link = "no_links"
- return link, end_quote
- start_line = s.find('class="rg_meta notranslate">')
- start_object = s.find("{", start_line + 1)
- end_object = s.find("", start_object + 1)
- object_raw = str(s[start_object:end_object])
- # remove escape characters based on python version
- try:
- object_decode = bytes(object_raw, "utf-8").decode("unicode_escape")
- final_object = json.loads(object_decode)
- except BaseException:
- final_object = ""
- return final_object, end_object
-
- # Getting all links with the help of '_images_get_next_image'
-
- def _get_image_objects(self, s):
- start_line = s.find("AF_initDataCallback({key: \\'ds:1\\'") - 10
- start_object = s.find("[", start_line + 1)
- end_object = s.find("", start_object + 1) - 4
- object_raw = str(s[start_object:end_object])
- object_decode = bytes(object_raw[:-1], "utf-8").decode("unicode_escape")
- # LOGS.info(_format.paste_text(object_decode[:-15]))
- return json.loads(object_decode[:-15])[31][0][12][2]
-
- def _get_all_items(self, page, main_directory, dir_name, limit, arguments):
- items = []
- abs_path = []
- errorCount = 0
- i = 0
- count = 1
- # LOGS.info(f"page : {_format.paste_text(page)}")
- image_objects = self._get_image_objects(page)
- while count < limit + 1:
- if not image_objects:
- print("no_links")
- break
- else:
- # format the item for readability
- try:
- object = self.format_object(image_objects[i])
- # download the images
- (
- download_status,
- download_message,
- return_image_name,
- absolute_path,
- ) = self.download_image(
- object["image_link"],
- object["image_format"],
- main_directory,
- dir_name,
- count,
- arguments["socket_timeout"],
- arguments["prefix"],
- arguments["no_numbering"],
- arguments["no_download"],
- arguments["save_source"],
- object["image_source"],
- arguments["thumbnail_only"],
- arguments["format"],
- arguments["ignore_urls"],
- )
- except (TypeError, IndexError) as er:
- LOGS.debug(er)
- download_status = None
-
- if download_status == "success":
-
- # download image_thumbnails
- if arguments["thumbnail"] or arguments["thumbnail_only"]:
- (
- download_status,
- download_message_thumbnail,
- ) = self.download_image_thumbnail(
- object["image_thumbnail_url"],
- main_directory,
- dir_name,
- return_image_name,
- arguments["socket_timeout"],
- arguments["no_download"],
- arguments["save_source"],
- object["image_source"],
- arguments["ignore_urls"],
- )
-
- count += 1
- object["image_filename"] = return_image_name
- # Append all the links in the list named 'Links'
- items.append(object)
- abs_path.append(absolute_path)
- else:
- errorCount += 1
-
- # delay param
- if arguments["delay"]:
- time.sleep(int(arguments["delay"]))
- i += 1
- if count < limit:
- LOGS.info(
- "\n\nUnfortunately all "
- + str(limit)
- + " could not be downloaded because some images were not downloadable. "
- + str(count - 1)
- + " is all we got for this search filter!"
- )
- return items, errorCount, abs_path
-
- # Bulk Download
-
- async def download(self, arguments):
- paths_agg = {}
- # for input coming from other python files
- if __name__ != "__main__":
- # if the calling file contains config_file param
- if "config_file" in arguments:
- records = []
- json_file = json.load(open(arguments["config_file"]))
- for item in json_file["Records"]:
- arguments = {}
- for i in args_list:
- arguments[i] = None
- for key, value in item.items():
- arguments[key] = value
- records.append(arguments)
- total_errors = 0
- for rec in records:
- paths, errors = await self.download_executor(rec)
- for i in paths:
- paths_agg[i] = paths[i]
- total_errors += errors
- return paths_agg, total_errors
- # if the calling file contains params directly
- paths, errors = await self.download_executor(arguments)
- for i in paths:
- paths_agg[i] = paths[i]
- return paths_agg, errors
- # for input coming from CLI
- paths, errors = await self.download_executor(arguments)
- for i in paths:
- paths_agg[i] = paths[i]
- return paths_agg, errors
-
- async def download_executor(self, arguments):
- paths = {}
- errorCount = None
- for arg in args_list:
- if arg not in arguments:
- arguments[arg] = None
- # Initialization and Validation of user arguments
- if arguments["keywords"]:
- search_keyword = [str(item) for item in arguments["keywords"].split(",")]
-
- if arguments["keywords_from_file"]:
- search_keyword = self.keywords_from_file(arguments["keywords_from_file"])
-
- # both time and time range should not be allowed in the same query
- if arguments["time"] and arguments["time_range"]:
- raise ValueError(
- "Either time or time range should be used in a query. Both cannot be used at the same time."
- )
-
- # both time and time range should not be allowed in the same query
- if arguments["size"] and arguments["exact_size"]:
- raise ValueError(
- 'Either "size" or "exact_size" should be used in a query. Both cannot be used at the same time.'
- )
-
- # both image directory and no image directory should not be allowed in
- # the same query
- if arguments["image_directory"] and arguments["no_directory"]:
- raise ValueError(
- "You can either specify image directory or specify no image directory, not both!"
- )
-
- # Additional words added to keywords
- if arguments["suffix_keywords"]:
- suffix_keywords = [
- " " + str(sk) for sk in arguments["suffix_keywords"].split(",")
- ]
- else:
- suffix_keywords = [""]
-
- # Additional words added to keywords
- if arguments["prefix_keywords"]:
- prefix_keywords = [
- str(sk) + " " for sk in arguments["prefix_keywords"].split(",")
- ]
- else:
- prefix_keywords = [""]
-
- # Setting limit on number of images to be downloaded
- limit = int(arguments["limit"]) if arguments["limit"] else 100
- if arguments["url"]:
- current_time = str(datetime.datetime.now()).split(".")[0]
- search_keyword = [current_time.replace(":", "_")]
-
- if arguments["similar_images"]:
- current_time = str(datetime.datetime.now()).split(".")[0]
- search_keyword = [current_time.replace(":", "_")]
-
- # If single_image or url argument not present then keywords is
- # mandatory argument
- if (
- arguments["single_image"] is None
- and arguments["url"] is None
- and arguments["similar_images"] is None
- and arguments["keywords"] is None
- and arguments["keywords_from_file"] is None
- ):
- LOGS.info(
- "-------------------------------\n"
- "Uh oh! Keywords is a required argument \n\n"
- "Please refer to the documentation on guide to writing queries \n"
- "https://github.com/hardikvasa/google-images-download#examples"
- "\n\nexiting!\n"
- "-------------------------------"
- )
- sys.exit()
-
- # If this argument is present, set the custom output directory
- main_directory = arguments["output_directory"] or "downloads"
- # Proxy settings
- if arguments["proxy"]:
- os.environ["http_proxy"] = arguments["proxy"]
- os.environ["https_proxy"] = arguments["proxy"]
- # Initialization Complete
- total_errors = 0
- for pky in prefix_keywords: # 1.for every prefix keywords
- for sky in suffix_keywords: # 2.for every suffix keywords
- for ii, e in enumerate(search_keyword): # 3.for every main keyword
- iteration = (
- "\n"
- + "Item no.: "
- + str(ii + 1)
- + " -->"
- + " Item name = "
- + (pky)
- + (e)
- + (sky)
- )
- search_term = pky + e + sky
-
- if arguments["image_directory"]:
- dir_name = arguments["image_directory"]
- elif arguments["no_directory"]:
- dir_name = ""
- else:
- dir_name = search_term + (
- "-" + arguments["color"] if arguments["color"] else ""
- ) # sub-directory
-
- if not arguments["no_download"]:
- self.create_directories(
- main_directory,
- dir_name,
- arguments["thumbnail"],
- arguments["thumbnail_only"],
- ) # create directories in OS
-
- params = self.build_url_parameters(
- arguments
- ) # building URL with params
-
- url = self.build_search_url(
- search_term,
- params,
- arguments["url"],
- arguments["similar_images"],
- arguments["specific_site"],
- arguments["safe_search"],
- ) # building main search url
-
- if limit < 101:
- # download page
- raw_html = await self.download_page(url)
- else:
- raw_html = self.download_extended_page(
- url, arguments["chromedriver"]
- )
-
- items, errorCount, abs_path = self._get_all_items(
- raw_html, main_directory, dir_name, limit, arguments
- ) # get all image items and download images
- paths[pky + e + sky] = abs_path
-
- # dumps into a json file
- if arguments["extract_metadata"]:
- try:
- if not os.path.exists("logs"):
- os.makedirs("logs")
- except OSError as e:
- LOGS.exception(e)
- with open("logs/" + e + ".json", "w") as json_file:
- json.dump(items, json_file, indent=4, sort_keys=True)
- # Related images
- if arguments["related_images"]:
- tabs = self.get_all_tabs(raw_html)
- for key, value in tabs.items():
- final_search_term = search_term + " - " + key
- if limit < 101:
- new_raw_html = await self.download_page(
- value
- ) # download page
- else:
- new_raw_html = self.download_extended_page(
- value, arguments["chromedriver"]
- )
- self.create_directories(
- main_directory,
- final_search_term,
- arguments["thumbnail"],
- arguments["thumbnail_only"],
- )
- self._get_all_items(
- new_raw_html,
- main_directory,
- search_term + " - " + key,
- limit,
- arguments,
- )
-
- total_errors += errorCount
- return paths, total_errors
diff --git a/pyUltroid/fns/helper.py b/pyUltroid/fns/helper.py
index e787fcdcb920dddb79fe27f1364e4a6a202d7507..d9396d141356356e6a3bf92328ec52bd8a16fb3e 100644
--- a/pyUltroid/fns/helper.py
+++ b/pyUltroid/fns/helper.py
@@ -20,10 +20,11 @@ from .. import run_as_module
if run_as_module:
from ..configs import Var
+
try:
- import aiohttp
+ from aiohttp import ClientSession as aiohttp_client
except ImportError:
- aiohttp = None
+ aiohttp_client = None
try:
import requests
except ImportError:
@@ -52,6 +53,7 @@ from telethon.utils import get_display_name
from .._misc import CMD_HELP
from .._misc._wrappers import eod, eor
+from ..exceptions import DependencyMissingError
from . import *
if run_as_module:
@@ -215,11 +217,10 @@ if run_as_module:
await xx.delete()
async def def_logs(ult, file):
- await ult.client.send_file(
- ult.chat_id,
+ await ult.respond(
+ "**Ultroid Logs.**",
file=file,
thumb=ULTConfig.thumb,
- caption="**Ultroid Logs.**",
)
async def updateme_requirements():
@@ -262,9 +263,8 @@ async def bash(cmd, run_code=0):
err = stderr.decode().strip() or None
out = stdout.decode().strip()
if not run_code and err:
- split = cmd.split()[0]
- if f"{split}: not found" in err:
- return out, f"{split.upper()}_NOT_FOUND"
+ if match := re.match("\/bin\/sh: (.*): ?(\w+): not found", err):
+ return out, f"{match.group(2).upper()}_NOT_FOUND"
return out, err
@@ -347,30 +347,70 @@ async def downloader(filename, file, event, taime, msg):
return result
+# ~~~~~~~~~~~~~~~Async Searcher~~~~~~~~~~~~~~~
+# @buddhhu
+
+
+async def async_searcher(
+ url: str,
+ post: bool = False,
+ head: bool = False,
+ headers: dict = None,
+ evaluate=None,
+ object: bool = False,
+ re_json: bool = False,
+ re_content: bool = False,
+ *args,
+ **kwargs,
+):
+ if aiohttp_client:
+ async with aiohttp_client(headers=headers) as client:
+ method = client.head if head else (client.post if post else client.get)
+ data = await method(url, *args, **kwargs)
+ if evaluate:
+ return await evaluate(data)
+ if re_json:
+ return await data.json()
+ if re_content:
+ return await data.read()
+ if head or object:
+ return data
+ return await data.text()
+ # elif requests:
+ # method = requests.head if head else (requests.post if post else requests.get)
+ # data = method(url, headers=headers, *args, **kwargs)
+ # if re_json:
+ # return data.json()
+ # if re_content:
+ # return data.content
+ # if head or object:
+ # return data
+ # return data.text
+ else:
+ raise DependencyMissingError("install 'aiohttp' to use this.")
+
+
# ~~~~~~~~~~~~~~~~~~~~DDL Downloader~~~~~~~~~~~~~~~~~~~~
# @buddhhu @new-dev0
-async def download_file(link, name):
+async def download_file(link, name, validate=False):
"""for files, without progress callback with aiohttp"""
- if aiohttp:
- async with aiohttp.ClientSession() as ses:
- async with ses.get(link) as re_ses:
- with open(name, "wb") as file:
- file.write(await re_ses.read())
- elif requests:
- content = requests.get(link).content
+
+ async def _download(content):
+ if validate and "application/json" in content.headers.get("Content-Type"):
+ return None, await content.json()
with open(name, "wb") as file:
- file.write(content)
- else:
- raise Exception("Aiohttp or requests is not installed.")
- return name
+ file.write(await content.read())
+ return name, ""
+
+ return await async_searcher(link, evaluate=_download)
async def fast_download(download_url, filename=None, progress_callback=None):
- if not aiohttp:
- return await download_file(download_url, filename)
- async with aiohttp.ClientSession() as session:
+ if not aiohttp_client:
+ return await download_file(download_url, filename)[0], None
+ async with aiohttp_client() as session:
async with session.get(download_url, timeout=None) as response:
if not filename:
filename = unquote(download_url.rpartition("/")[-1])
@@ -467,6 +507,7 @@ def humanbytes(size):
def numerize(number):
if not number:
return None
+ unit = ""
for unit in ["", "K", "M", "B", "T"]:
if number < 1000:
break
diff --git a/pyUltroid/fns/info.py b/pyUltroid/fns/info.py
index 76a8f4c7439cd2bb396360889d783e26a56b2987..f57b8b0bbd48bc08d3d3e6c07e402a3eae06b63e 100644
--- a/pyUltroid/fns/info.py
+++ b/pyUltroid/fns/info.py
@@ -10,14 +10,7 @@
import math
-from ..exceptions import TelethonMissingError
-
-try:
- from telethon.tl import functions, types
-except ImportError:
- raise TelethonMissingError(
- f"'Telethon is not Installed!'\nfunctions present in '{__name__}' needs telethon to be installed!"
- )
+from telethon.tl import functions, types
from .. import LOGS
diff --git a/pyUltroid/fns/misc.py b/pyUltroid/fns/misc.py
index d852025df6da9b711817c317b4dcd2ccdeece948..6438570c9cdc8e7d5090e2e19f6b664f994124fe 100644
--- a/pyUltroid/fns/misc.py
+++ b/pyUltroid/fns/misc.py
@@ -32,21 +32,13 @@ if run_as_module:
from ..dB._core import LIST
from . import some_random_headers
-from .tools import async_searcher, check_filename, json_parser
+from .helper import async_searcher
+from .tools import check_filename, json_parser
try:
- import aiofiles
import aiohttp
except ImportError:
aiohttp = None
- aiofiles = None
-
-try:
- from instagrapi import Client
- from instagrapi.exceptions import LoginRequired, ManualInputRequired
-except ImportError:
- Client = None
- ManualInputRequired = None
try:
from PIL import Image
@@ -116,9 +108,9 @@ async def YtDataScraper(url: str):
common_data["videoActions"]["menuRenderer"]["topLevelButtons"][0][
"toggleButtonRenderer"
]["defaultText"]["simpleText"]
- or like_dislike[0]["toggleButtonRenderer"]["defaultText"]["accessibility"][
- "accessibilityData"
- ]["label"]
+ # or like_dislike[0]["toggleButtonRenderer"]["defaultText"]["accessibility"][
+ # "accessibilityData"
+ # ]["label"]
)
to_return["description"] = description
return to_return
@@ -184,9 +176,8 @@ async def ReTrieveFile(input_file_name):
return False, (await out.json())
name = check_filename("ult-rmbg.png")
- file = await aiofiles.open(name, "wb")
- await file.write(await out.read())
- await file.close()
+ with open(name, "wb") as file:
+ file.write(await out.read())
return True, name
@@ -199,11 +190,10 @@ async def unsplashsearch(query, limit=None, shuf=True):
link = "https://unsplash.com/s/photos/" + query
extra = await async_searcher(link, re_content=True)
res = BeautifulSoup(extra, "html.parser", from_encoding="utf-8")
- all_ = res.find_all("img", "YVj9w")
+ all_ = res.find_all("img", srcset=re.compile("images.unsplash.com/photo"))
if shuf:
shuffle(all_)
- all_ = all_[:limit]
- return [image["src"] for image in all_]
+ return list(map(lambda e: e['src'], all_[:limit]))
# ---------------- Random User Gen ----------------
@@ -278,96 +268,6 @@ async def get_synonyms_or_antonyms(word, type_of_words):
return [y["term"] for y in li_1]
-# --------------------- Instagram Plugin ------------------------- #
-# @New-dev0
-
-INSTA_CLIENT = []
-
-
-async def _insta_login():
- if "insta_creds" in ultroid_bot._cache:
- return ultroid_bot._cache["insta_creds"]
- username = udB.get_key("INSTA_USERNAME")
- password = udB.get_key("INSTA_PASSWORD")
- if username and password:
- settings = eval(udB["INSTA_SET"]) if udB.get_key("INSTA_SET") else {}
- cl = Client(settings)
- try:
- cl.login(username, password)
- ultroid_bot._cache.update({"insta_creds": cl})
- except ManualInputRequired:
- LOGS.exception(format_exc())
- # await get_insta_code(cl, username, password)
- return False
- except LoginRequired:
- udB.del_key("INSTA_SET")
- return await _insta_login()
- except Exception:
- udB.del_key(iter(["INSTA_USERNAME", "INSTA_PASSWORD"]))
- LOGS.exception(format_exc())
- return False
- udB.set_key("INSTA_SET", str(cl.get_settings()))
- cl.logger.setLevel(WARNING)
- return ultroid_bot._cache["insta_creds"]
- return False
-
-
-async def get_insta_code(username, choice):
- from .. import asst, ultroid_bot
-
- async with asst.conversation(ultroid_bot.uid, timeout=60 * 2) as conv:
- await conv.send_message(
- "Enter The **Instagram Verification Code** Sent to Your Email.."
- )
- ct = await conv.get_response()
- while not ct.text.isdigit():
- if ct.message == "/cancel":
- await conv.send_message("Cancelled Verification!")
- return
- await conv.send_message(
- "CODE SHOULD BE INTEGER\nSend The Code Back or\nUse /cancel to Cancel Process..."
- )
- ct = await conv.get_response()
- return ct.text
-
-
-async def create_instagram_client(event):
- if not Client:
- await event.eor("`Instagrapi not Found\nInstall it to use Instagram plugin...`")
- return
- try:
- return INSTA_CLIENT[0]
- except IndexError:
- pass
- from .. import udB
-
- username = udB.get_key("INSTA_USERNAME")
- password = udB.get_key("INSTA_PASSWORD")
- if not (username and password):
- await event.eor("`Please Fill Instagram Credentials to Use This...`")
- return
- settings = udB.get_key("INSTA_SET") or {}
- cl = Client(settings)
- cl.challenge_code_handler = get_insta_code
- try:
- cl.login(username, password)
- except ManualInputRequired:
- await eor(event, f"Check Pm From @{asst.me.username}")
- await get_insta_code(cl, username, password)
- except LoginRequired:
- # "login required" refers to relogin...
- udB.del_key("INSTA_SET")
- return await create_instagram_client(event)
- except Exception as er:
- LOGS.exception(er)
- await eor(event, str(er))
- return False
- udB.set_key("INSTA_SET", str(cl.get_settings()))
- cl.logger.setLevel(WARNING)
- INSTA_CLIENT.append(cl)
- return cl
-
-
# Quotly
@@ -421,11 +321,9 @@ class Quotly:
last_name = None
if sender and sender.id not in DEVLIST:
id_ = get_peer_id(sender)
- name = get_display_name(sender)
elif not is_fwd:
id_ = event.sender_id
sender = await event.get_sender()
- name = get_display_name(sender)
else:
id_, sender = None, None
name = is_fwd.from_name
@@ -433,11 +331,12 @@ class Quotly:
id_ = get_peer_id(is_fwd.from_id)
try:
sender = await event.client.get_entity(id_)
- name = get_display_name(sender)
except ValueError:
pass
- if sender and hasattr(sender, "last_name"):
- last_name = sender.last_name
+ if sender:
+ name = get_display_name(sender)
+ if hasattr(sender, "last_name"):
+ last_name = sender.last_name
entities = []
if event.entities:
for entity in event.entities:
@@ -455,6 +354,7 @@ class Quotly:
text += f" in {rep.game.title}"
elif isinstance(event.action, types.MessageActionPinMessage):
text = "pinned a message."
+ # TODO: Are there any more events with sender?
message = {
"entities": entities,
"chatId": id_,
@@ -467,7 +367,7 @@ class Quotly:
"username": sender.username if sender else None,
"language_code": "en",
"title": name,
- "name": name or "Unknown",
+ "name": name or "Deleted Account",
"type": type_,
},
"text": text,
@@ -483,7 +383,7 @@ class Quotly:
async def create_quotly(
self,
event,
- url="https://qoute-api-akashpattnaik.koyeb.app/generate",
+ url="https://bot.lyo.su/quote/generate",
reply={},
bg=None,
sender=None,
@@ -531,9 +431,6 @@ class Quotly:
raise Exception(str(request))
-# Some Sarcasm
-
-
def split_list(List, index):
new_ = []
while List:
diff --git a/pyUltroid/fns/tools.py b/pyUltroid/fns/tools.py
index e625ceac2018900b28c3deca484d55ab131fe637..646f738e0830b4f3fe3cc83b5bb6737d0b948496 100644
--- a/pyUltroid/fns/tools.py
+++ b/pyUltroid/fns/tools.py
@@ -16,9 +16,12 @@ from io import BytesIO
from json.decoder import JSONDecodeError
from traceback import format_exc
+import requests
+
from .. import *
from ..exceptions import DependencyMissingError
-from .helper import bash, run_async
+from . import some_random_headers
+from .helper import async_searcher, bash, run_async
try:
import certifi
@@ -33,11 +36,6 @@ except ImportError:
from urllib.parse import quote, unquote
-try:
- import requests
- from requests.exceptions import MissingSchema
-except ImportError:
- requests = None
from telethon import Button
from telethon.tl.types import DocumentAttributeAudio, DocumentAttributeVideo
@@ -54,6 +52,11 @@ try:
except ImportError:
Telegraph = None
+try:
+ from bs4 import BeautifulSoup
+except ImportError:
+ BeautifulSoup = None
+
# ~~~~~~~~~~~~~~~~~~~~OFOX API~~~~~~~~~~~~~~~~~~~~
# @buddhhu
@@ -69,46 +72,6 @@ async def get_ofox(codename):
return device, releases
-# ~~~~~~~~~~~~~~~Async Searcher~~~~~~~~~~~~~~~
-# @buddhhu
-
-
-async def async_searcher(
- url: str,
- post: bool = None,
- headers: dict = None,
- params: dict = None,
- json: dict = None,
- data: dict = None,
- ssl=None,
- re_json: bool = False,
- re_content: bool = False,
- real: bool = False,
- *args,
- **kwargs,
-):
- try:
- import aiohttp
- except ImportError:
- raise DependencyMissingError(
- "'aiohttp' is not installed!\nthis function requires aiohttp to be installed."
- )
- async with aiohttp.ClientSession(headers=headers) as client:
- if post:
- data = await client.post(
- url, json=json, data=data, ssl=ssl, *args, **kwargs
- )
- else:
- data = await client.get(url, params=params, ssl=ssl, *args, **kwargs)
- if re_json:
- return await data.json()
- if re_content:
- return await data.read()
- if real:
- return data
- return await data.text()
-
-
# ~~~~~~~~~~~~~~~JSON Parser~~~~~~~~~~~~~~~
# @buddhhu
@@ -138,18 +101,12 @@ def json_parser(data, indent=None, ascii=False):
# ~~~~~~~~~~~~~~~~Link Checker~~~~~~~~~~~~~~~~~
-def is_url_ok(url: str):
- try:
- import requests
- except ImportError:
- raise DependencyMissingError("This function needs 'requests' to be installed.")
+async def is_url_ok(url: str):
try:
- r = requests.head(url)
- except MissingSchema:
- return None
- except BaseException:
+ return await async_searcher(url, head=True)
+ except BaseException as er:
+ LOGS.debug(er)
return False
- return r.ok
# ~~~~~~~~~~~~~~~~ Metadata ~~~~~~~~~~~~~~~~~~~~
@@ -158,7 +115,9 @@ def is_url_ok(url: str):
async def metadata(file):
out, _ = await bash(f'mediainfo "{_unquote_text(file)}" --Output=JSON')
if _ and _.endswith("NOT_FOUND"):
- raise Exception(_)
+ raise DependencyMissingError(
+ f"'{_}' is not installed!\nInstall it to use this command."
+ )
data = {}
_info = json.loads(out)["media"]["track"]
info = _info[0]
@@ -403,6 +362,77 @@ async def get_paste(data: str, extension: str = "txt"):
return None, str(e)
+# --------------------------------------
+# https://stackoverflow.com/a/74563494
+
+
+async def get_google_images(query):
+ soup = BeautifulSoup(
+ await async_searcher(
+ "https://google.com/search",
+ params={"q": query, "tbm": "isch"},
+ headers={"User-Agent": random.choice(some_random_headers)},
+ ),
+ "lxml",
+ )
+ google_images = []
+ all_script_tags = soup.select("script")
+ matched_images_data = "".join(
+ re.findall(r"AF_initDataCallback\(([^<]+)\);", str(all_script_tags))
+ )
+ matched_images_data_fix = json.dumps(matched_images_data)
+ matched_images_data_json = json.loads(matched_images_data_fix)
+ matched_google_image_data = re.findall(
+ r"\"b-GRID_STATE0\"(.*)sideChannel:\s?{}}", matched_images_data_json
+ )
+ matched_google_images_thumbnails = ", ".join(
+ re.findall(
+ r"\[\"(https\:\/\/encrypted-tbn0\.gstatic\.com\/images\?.*?)\",\d+,\d+\]",
+ str(matched_google_image_data),
+ )
+ ).split(", ")
+ thumbnails = [
+ bytes(bytes(thumbnail, "ascii").decode("unicode-escape"), "ascii").decode(
+ "unicode-escape"
+ )
+ for thumbnail in matched_google_images_thumbnails
+ ]
+ removed_matched_google_images_thumbnails = re.sub(
+ r"\[\"(https\:\/\/encrypted-tbn0\.gstatic\.com\/images\?.*?)\",\d+,\d+\]",
+ "",
+ str(matched_google_image_data),
+ )
+ matched_google_full_resolution_images = re.findall(
+ r"(?:'|,),\[\"(https:|http.*?)\",\d+,\d+\]",
+ removed_matched_google_images_thumbnails,
+ )
+ full_res_images = [
+ bytes(bytes(img, "ascii").decode("unicode-escape"), "ascii").decode(
+ "unicode-escape"
+ )
+ for img in matched_google_full_resolution_images
+ ]
+ for index, (metadata, thumbnail, original) in enumerate(
+ zip(soup.select(".isv-r.PNCib.MSM1fd.BUooTd"), thumbnails, full_res_images),
+ start=1,
+ ):
+ google_images.append(
+ {
+ "title": metadata.select_one(".VFACy.kGQAp.sMi44c.lNHeqe.WGvvNb")[
+ "title"
+ ],
+ "link": metadata.select_one(".VFACy.kGQAp.sMi44c.lNHeqe.WGvvNb")[
+ "href"
+ ],
+ "source": metadata.select_one(".fxgdke").text,
+ "thumbnail": thumbnail,
+ "original": original,
+ }
+ )
+ random.shuffle(google_images)
+ return google_images
+
+
# Thanks https://t.me/KukiUpdates/23 for ChatBotApi
@@ -555,24 +585,29 @@ def make_html_telegraph(title, html=""):
async def Carbon(
code,
- base_url="https://rayso-api-desvhu-33.koyeb.app/generate",
+ base_url="https://carbonara.vercel.app/api/cook",
file_name="ultroid",
download=False,
rayso=False,
**kwargs,
):
- # if rayso:
- kwargs["text"] = code
- kwargs["theme"] = kwargs.get("theme", "meadow")
- kwargs["darkMode"] = kwargs.get("darkMode", True)
- kwargs["title"] = kwargs.get("title", "Ultroid")
- # else:
- # kwargs["code"] = code
+ if rayso:
+ base_url = "https://rayso-api-desvhu-33.koyeb.app/generate"
+ kwargs["text"] = code
+ kwargs["theme"] = kwargs.get("theme", "breeze")
+ kwargs["darkMode"] = kwargs.get("darkMode", True)
+ kwargs["title"] = kwargs.get("title", "Ultroid")
+ else:
+ kwargs["code"] = code
con = await async_searcher(base_url, post=True, json=kwargs, re_content=True)
if not download:
file = BytesIO(con)
file.name = file_name + ".jpg"
else:
+ try:
+ return json_parser(con.decode())
+ except Exception:
+ pass
file = file_name + ".jpg"
with open(file, "wb") as f:
f.write(con)
diff --git a/pyUltroid/loader.py b/pyUltroid/loader.py
index aa1f4a8d14a0ba9e3e2dbfecf547f31e20c0b3e4..79e8374ba2bdef45d7fae8b2404c67703eb7811a 100644
--- a/pyUltroid/loader.py
+++ b/pyUltroid/loader.py
@@ -30,6 +30,7 @@ class Loader:
after_load=None,
load_all=False,
):
+ _single = os.path.isfile(self.path)
if include:
if log:
self._logger.info("Including: {}".format("⢠".join(include)))
@@ -38,6 +39,8 @@ class Loader:
path = f"{self.path}/{file}.py"
if os.path.exists(path):
files.append(path)
+ elif _single:
+ files = [self.path]
else:
if load_all:
files = get_all_files(self.path, ".py")
@@ -48,7 +51,7 @@ class Loader:
if not path.startswith("_"):
with contextlib.suppress(ValueError):
files.remove(f"{self.path}/{path}.py")
- if log:
+ if log and not _single:
self._logger.info(
f"⢠Installing {self.key} Plugins || Count : {len(files)} â˘"
)
@@ -60,22 +63,15 @@ class Loader:
except ModuleNotFoundError as er:
modl = None
self._logger.error(f"{plugin}: '{er.name}' not installed!")
+ continue
except Exception as exc:
modl = None
self._logger.error(f"pyUltroid - {self.key} - ERROR - {plugin}")
self._logger.exception(exc)
+ continue
+ if _single and log:
+ self._logger.info(f"Successfully Loaded {plugin}!")
if callable(after_load):
if func == import_module:
plugin = plugin.split(".")[-1]
after_load(self, modl, plugin_name=plugin)
-
- def load_single(self, log=False):
- """To Load Single File"""
- plugin = self.path.replace(".py", "").replace("/", ".")
- try:
- import_module(plugin)
- except Exception as er:
- self._logger.info(f"Error while Loading {plugin}")
- return self._logger.exception(er)
- if log and self._logger:
- self._logger.info(f"Successfully Loaded {plugin}!")
diff --git a/pyUltroid/startup/BaseClient.py b/pyUltroid/startup/BaseClient.py
index 3d037b4f63737c48601ca28fbb9ae7d33392dcea..bcee8aee27b2f3dba811458b94057c372fae1cd8 100644
--- a/pyUltroid/startup/BaseClient.py
+++ b/pyUltroid/startup/BaseClient.py
@@ -114,7 +114,7 @@ class UltroidClient(TelegramClient):
by_bot = self._bot
size = os.path.getsize(file)
# Don't show progress bar when file size is less than 5MB.
- if size < 5 * 2**20:
+ if size < 5 * 2 ** 20:
show_progress = False
if use_cache and self._cache and self._cache.get("upload_cache"):
for files in self._cache["upload_cache"]:
@@ -170,11 +170,11 @@ class UltroidClient(TelegramClient):
"""Download files in a faster way"""
# Set to True and pass event to show progress bar.
show_progress = kwargs.get("show_progress", False)
- filename = kwargs.get("filename", None)
+ filename = kwargs.get("filename", "")
if show_progress:
event = kwargs["event"]
# Don't show progress bar when file size is less than 10MB.
- if file.size < 10 * 2**20:
+ if file.size < 10 * 2 ** 20:
show_progress = False
import mimetypes
diff --git a/pyUltroid/startup/__init__.py b/pyUltroid/startup/__init__.py
index 313035633684c6e460fbfd101fdf7ca44252da63..30c3e92f3db60b4e83b34370c800683184a8cf52 100644
--- a/pyUltroid/startup/__init__.py
+++ b/pyUltroid/startup/__init__.py
@@ -11,6 +11,7 @@ import sys
from logging import INFO, WARNING, FileHandler, StreamHandler, basicConfig, getLogger
from .. import run_as_module
+from ._extra import _ask_input
if run_as_module:
from ..configs import Var
@@ -28,6 +29,8 @@ def where_hosted():
if os.getenv("KUBERNETES_PORT"):
return "qovery | kubernetes"
if os.getenv("RUNNER_USER") or os.getenv("HOSTNAME"):
+ if os.getenv("USER") == "codespace":
+ return "codespace"
return "github actions"
if os.getenv("ANDROID_ROOT"):
return "termux"
@@ -60,10 +63,7 @@ if run_as_module:
_fix_logging(FileHandler)
- if HOSTED_ON == "local":
- from ._extra import _ask_input
-
- _ask_input()
+ _ask_input()
_LOG_FORMAT = "%(asctime)s | %(name)s [%(levelname)s] : %(message)s"
basicConfig(
diff --git a/pyUltroid/startup/_database.py b/pyUltroid/startup/_database.py
index 98a5be9d0b4553f36dc54e1254194be49fdad3e6..5a87bfdb3f505302e525f66ede8bf717b811cd9c 100644
--- a/pyUltroid/startup/_database.py
+++ b/pyUltroid/startup/_database.py
@@ -17,33 +17,33 @@ if run_as_module:
Redis = MongoClient = psycopg2 = Database = None
-if (Var.REDIS_URI or Var.REDISHOST):
+if Var.REDIS_URI or Var.REDISHOST:
try:
from redis import Redis
except ImportError:
LOGS.info("Installing 'redis' for database.")
- os.system("pip3 install -q redis hiredis")
+ os.system(f"{sys.executable} -m pip install -q redis hiredis")
from redis import Redis
elif Var.MONGO_URI:
try:
from pymongo import MongoClient
except ImportError:
LOGS.info("Installing 'pymongo' for database.")
- os.system("pip3 install -q pymongo[srv]")
+ os.system(f"{sys.executable} -m pip install -q pymongo[srv]")
from pymongo import MongoClient
elif Var.DATABASE_URL:
try:
import psycopg2
except ImportError:
LOGS.info("Installing 'pyscopg2' for database.")
- os.system("pip3 install -q psycopg2-binary")
+ os.system(f"{sys.executable} -m pip install -q psycopg2-binary")
import psycopg2
else:
try:
from localdb import Database
except ImportError:
LOGS.info("Using local file as database.")
- os.system("pip3 install -q localdb.json")
+ os.system(f"{sys.executable} -m pip install -q localdb.json")
from localdb import Database
# --------------------------------------------------------------------------------------------- #
@@ -84,16 +84,18 @@ class _BaseDatabase:
def _get_data(self, key=None, data=None):
if key:
data = self.get(str(key))
- if data:
+ if data and isinstance(data, str):
try:
data = ast.literal_eval(data)
except BaseException:
pass
return data
- def set_key(self, key, value):
+ def set_key(self, key, value, cache_only=False):
value = self._get_data(data=value)
self._cache[key] = value
+ if cache_only:
+ return
return self.set(str(key), str(value))
def rename(self, key1, key2):
@@ -129,12 +131,11 @@ class MongoDB(_BaseDatabase):
def keys(self):
return self.db.list_collection_names()
- def set_key(self, key, value):
+ def set(self, key, value):
if key in self.keys():
self.db[key].replace_one({"_id": key}, {"value": str(value)})
else:
self.db[key].insert_one({"_id": key, "value": str(value)})
- self._cache.update({key: value})
return True
def delete(self, key):
@@ -278,9 +279,9 @@ class RedisDB(_BaseDatabase):
if var:
hash_ = var.split("_", maxsplit=2)[1].split("_")[0]
if hash:
- kwargs["host"] = os.environ(f"QOVERY_REDIS_{hash_}_HOST")
- kwargs["port"] = os.environ(f"QOVERY_REDIS_{hash_}_PORT")
- kwargs["password"] = os.environ(f"QOVERY_REDIS_{hash_}_PASSWORD")
+ kwargs["host"] = os.environ.get(f"QOVERY_REDIS_{hash_}_HOST")
+ kwargs["port"] = os.environ.get(f"QOVERY_REDIS_{hash_}_PORT")
+ kwargs["password"] = os.environ.get(f"QOVERY_REDIS_{hash_}_PASSWORD")
self.db = Redis(**kwargs)
self.set = self.db.set
self.get = self.db.get
@@ -303,8 +304,15 @@ class RedisDB(_BaseDatabase):
class LocalDB(_BaseDatabase):
def __init__(self):
self.db = Database("ultroid")
+ self.get = self.db.get
+ self.set = self.db.set
+ self.delete = self.db.delete
super().__init__()
+ @property
+ def name(self):
+ return "LocalDB"
+
def keys(self):
return self._cache.keys()
@@ -315,6 +323,7 @@ class LocalDB(_BaseDatabase):
def UltroidDB():
_er = False
from .. import HOSTED_ON
+
try:
if Redis:
return RedisDB(
@@ -337,8 +346,9 @@ def UltroidDB():
LOGS.critical(
"No DB requirement fullfilled!\nPlease install redis, mongo or sql dependencies...\nTill then using local file as database."
)
- if HOSTED_ON == "termux":
+ if HOSTED_ON == "local":
return LocalDB()
exit()
+
# --------------------------------------------------------------------------------------------- #
diff --git a/pyUltroid/startup/connections.py b/pyUltroid/startup/connections.py
index 521ec385acc85ec3545df2b85566d72ddc5d184b..fd9086aca8880abc1bc76a5f3d3b23ced6bb3dbb 100644
--- a/pyUltroid/startup/connections.py
+++ b/pyUltroid/startup/connections.py
@@ -32,6 +32,7 @@ DC_IPV4 = {
def validate_session(session, logger=LOGS, _exit=True):
from strings import get_string
+
if session:
# Telethon Session
if session.startswith(CURRENT_VERSION):
@@ -39,18 +40,18 @@ def validate_session(session, logger=LOGS, _exit=True):
logger.exception(get_string("py_c1"))
sys.exit()
return StringSession(session)
+
# Pyrogram Session
elif len(session) in _PYRO_FORM.keys():
+ data_ = struct.unpack(
+ _PYRO_FORM[len(session)],
+ base64.urlsafe_b64decode(session + "=" * (-len(session) % 4)),
+ )
if len(session) in [351, 356]:
- dc_id, _, auth_key, _, _ = struct.unpack(
- _PYRO_FORM[len(session)],
- base64.urlsafe_b64decode(session + "=" * (-len(session) % 4)),
- )
+ auth_id = 2
else:
- dc_id, _, _, auth_key, _, _ = struct.unpack(
- _PYRO_FORM[len(session)],
- base64.urlsafe_b64decode(session + "=" * (-len(session) % 4)),
- )
+ auth_id = 3
+ dc_id, auth_key = data_[0], data_[auth_id]
return StringSession(
CURRENT_VERSION
+ base64.urlsafe_b64encode(
@@ -74,6 +75,7 @@ def validate_session(session, logger=LOGS, _exit=True):
def vc_connection(udB, ultroid_bot):
from strings import get_string
+
VC_SESSION = Var.VC_SESSION or udB.get_key("VC_SESSION")
if VC_SESSION and VC_SESSION != Var.SESSION:
LOGS.info("Starting up VcClient.")
@@ -81,7 +83,7 @@ def vc_connection(udB, ultroid_bot):
return UltroidClient(
validate_session(VC_SESSION, _exit=False),
log_attempt=False,
- exit_on_error=False
+ exit_on_error=False,
)
except (AuthKeyDuplicatedError, EOFError):
LOGS.info(get_string("py_c3"))
diff --git a/pyUltroid/startup/funcs.py b/pyUltroid/startup/funcs.py
index 530fd00d26556e679fda03cbb670f7d01797c703..f4ac3615ba9a11acd46e91e14be7b2a33b6e8e35 100644
--- a/pyUltroid/startup/funcs.py
+++ b/pyUltroid/startup/funcs.py
@@ -6,11 +6,14 @@
# .
import asyncio
-import os, shutil
+import os
import random
+import shutil
import time
from random import randint
+from ..configs import Var
+
try:
from pytz import timezone
except ImportError:
@@ -46,7 +49,7 @@ db_url = 0
async def autoupdate_local_database():
- from .. import asst, udB, ultroid_bot, Var
+ from .. import Var, asst, udB, ultroid_bot
global db_url
db_url = (
@@ -88,7 +91,10 @@ def update_envs():
from .. import udB
for envs in list(os.environ):
- if envs in ["LOG_CHANNEL", "BOT_TOKEN"] or envs in udB.keys():
+ if (
+ envs in ["LOG_CHANNEL", "BOT_TOKEN", "BOTMODE", "DUAL_MODE", "language"]
+ or envs in udB.keys()
+ ):
udB.set_key(envs, os.environ[envs])
@@ -302,7 +308,7 @@ async def autopilot():
LOGS.info("Error while promoting assistant in Log Channel..")
LOGS.exception(er)
if isinstance(chat.photo, ChatPhotoEmpty):
- photo = await download_file(
+ photo, _ = await download_file(
"https://graph.org/file/27c6812becf6f376cbb10.jpg", "channelphoto.jpg"
)
ll = await ultroid_bot.upload_file(photo)
@@ -340,7 +346,7 @@ async def customize():
]
)
if not os.path.exists(file):
- file = await download_file(file, "profile.jpg")
+ file, _ = await download_file(file, "profile.jpg")
rem = True
msg = await asst.send_message(
chat_id, "**Auto Customisation** Started on @Botfather"
@@ -410,12 +416,12 @@ async def plug(plugin_channels):
if x.text == "#IGNORE":
continue
plugin = await x.download_media(plugin)
- try:
- load_addons(plugin)
- except Exception as e:
- LOGS.info(f"Ultroid - PLUGIN_CHANNEL - ERROR - {plugin}")
- LOGS.exception(e)
- os.remove(plugin)
+ try:
+ load_addons(plugin)
+ except Exception as e:
+ LOGS.info(f"Ultroid - PLUGIN_CHANNEL - ERROR - {plugin}")
+ LOGS.exception(e)
+ os.remove(plugin)
except Exception as er:
LOGS.exception(er)
@@ -423,9 +429,42 @@ async def plug(plugin_channels):
# some stuffs
+async def fetch_ann():
+ from .. import asst, udB
+ from ..fns.tools import async_searcher
+
+ get_ = udB.get_key("OLDANN") or []
+ chat_id = udB.get_key("LOG_CHANNEL")
+
+ try:
+ updts = await async_searcher(
+ "https://ultroid-api.vercel.app/announcements", post=True, re_json=True
+ )
+ for upt in updts:
+ key = list(upt.keys())[0]
+ if key not in get_:
+ cont = upt[key]
+ if isinstance(cont, dict) and cont.get("lang"):
+ if cont["lang"] != (udB.get_key("language") or "en"):
+ continue
+ cont = cont["msg"]
+ if isinstance(cont, str):
+ await asst.send_message(chat_id, cont)
+ elif isinstance(cont, dict) and cont.get("chat"):
+ await asst.forward_messages(chat_id, cont["msg_id"], cont["chat"])
+ else:
+ LOGS.info(cont)
+ LOGS.info(
+ "Invalid Type of Announcement Detected!\nMake sure you are on latest version.."
+ )
+ get_.append(key)
+ udB.set_key("OLDANN", get_)
+ except Exception as er:
+ LOGS.exception(er)
+
+
async def ready():
from .. import asst, udB, ultroid_bot
- from ..fns.tools import async_searcher
chat_id = udB.get_key("LOG_CHANNEL")
spam_sent = None
@@ -460,31 +499,10 @@ async def ready():
try:
spam_sent = await ultroid_bot.send_message(chat_id, MSG)
except Exception as ef:
- LOGS.info(ef)
+ LOGS.exception(ef)
if spam_sent and not spam_sent.media:
udB.set_key("LAST_UPDATE_LOG_SPAM", spam_sent.id)
- get_ = udB.get_key("OLDANN") or []
- try:
- updts = await async_searcher(
- "https://ultroid-api.vercel.app/announcements", post=True, re_json=True
- )
- for upt in updts:
- key = list(upt.keys())[0]
- if key not in get_:
- cont = upt[key]
- if isinstance(cont, str):
- await asst.send_message(chat_id, cont)
- elif isinstance(cont, dict) and cont.get("chat"):
- await asst.forward_messages(chat_id, cont["msg_id"], cont["chat"])
- else:
- LOGS.info(cont)
- LOGS.info(
- "Invalid Type of Announcement Detected!\nMake sure you are on latest version.."
- )
- get_.append(key)
- udB.set_key("OLDANN", get_)
- except Exception as er:
- LOGS.exception(er)
+ await fetch_ann()
async def WasItRestart(udb):
diff --git a/pyUltroid/startup/loader.py b/pyUltroid/startup/loader.py
index 021d12e0b48872ab419d39890a7ac2ad94f80f94..edf15a1d9f88ab261a90e85d94cf7a2532fdd5e9 100644
--- a/pyUltroid/startup/loader.py
+++ b/pyUltroid/startup/loader.py
@@ -5,11 +5,14 @@
# PLease read the GNU Affero General Public License in
# .
-import os, subprocess
+import os
+import subprocess
+import sys
from shutil import rmtree
from decouple import config
from git import Repo
+
from .. import *
from ..dB._core import HELP
from ..loader import Loader
@@ -54,7 +57,7 @@ def load_other_plugins(addons=None, pmbot=None, manager=None, vcbot=None):
Loader().load(include=_in_only, exclude=_exclude, after_load=_after_load)
# for assistant
- if not udB.get_key("DISABLE_AST_PLUGINS"):
+ if not USER_MODE and not udB.get_key("DISABLE_AST_PLUGINS"):
_ast_exc = ["pmbot"]
if _in_only and "games" not in _in_only:
_ast_exc.append("games")
@@ -86,7 +89,10 @@ def load_other_plugins(addons=None, pmbot=None, manager=None, vcbot=None):
# subprocess.run(
# "rm -rf /usr/local/lib/python3.*/site-packages/pip/_vendor/.wh*"
# )
- subprocess.run("pip3 install --no-cache-dir -q -r ./addons/addons.txt", shell=True)
+ subprocess.run(
+ f"{sys.executable} -m pip install --no-cache-dir -q -r ./addons/addons.txt",
+ shell=True,
+ )
_exclude = udB.get_key("EXCLUDE_ADDONS")
_exclude = _exclude.split() if _exclude else []
@@ -101,13 +107,14 @@ def load_other_plugins(addons=None, pmbot=None, manager=None, vcbot=None):
load_all=True,
)
- # group manager
- if manager:
- Loader(path="assistant/manager", key="Group Manager").load()
+ if not USER_MODE:
+ # group manager
+ if manager:
+ Loader(path="assistant/manager", key="Group Manager").load()
- # chat via assistant
- if pmbot:
- Loader(path="assistant/pmbot.py").load_single(log=False)
+ # chat via assistant
+ if pmbot:
+ Loader(path="assistant/pmbot.py").load(log=False)
# vc bot
if vcbot and not vcClient._bot:
@@ -120,7 +127,9 @@ def load_other_plugins(addons=None, pmbot=None, manager=None, vcbot=None):
else:
rmtree("vcbot")
if not os.path.exists("vcbot"):
- subprocess.run("git clone https://github.com/TeamUltroid/VcBot vcbot", shell=True)
+ subprocess.run(
+ "git clone https://github.com/TeamUltroid/VcBot vcbot", shell=True
+ )
try:
if not os.path.exists("vcbot/downloads"):
os.mkdir("vcbot/downloads")
@@ -128,4 +137,4 @@ def load_other_plugins(addons=None, pmbot=None, manager=None, vcbot=None):
except FileNotFoundError as e:
LOGS.error(f"{e} Skipping VCBot Installation.")
except ModuleNotFoundError:
- LOGS.error("'pytgcalls' not installed!\nSkipping load of VcBot.")
+ LOGS.error("'pytgcalls' not installed!\nSkipping loading of VCBOT.")
diff --git a/pyUltroid/startup/utils.py b/pyUltroid/startup/utils.py
index 25503aa9503b21cc7a24aefc241fda2bfa1d70bc..95246afe7976abfdb5c2f70b5e8d7db352537ccb 100644
--- a/pyUltroid/startup/utils.py
+++ b/pyUltroid/startup/utils.py
@@ -10,14 +10,32 @@ from sys import modules
# for addons
+configPaths = [
+ "ub",
+ "var",
+ "support",
+ "userbot",
+ "telebot",
+ "fridaybot",
+ "uniborg.util",
+ "telebot.utils",
+ "userbot.utils",
+ "userbot.events",
+ "userbot.config",
+ "fridaybot.utils",
+ "fridaybot.Config",
+ "userbot.uniborgConfig",
+]
+
def load_addons(plugin_name):
base_name = plugin_name.split("/")[-1].split("\\")[-1].replace(".py", "")
if base_name.startswith("__"):
return
- from .. import HNDLR, LOGS, asst, udB, ultroid_bot
- from .._misc import _supporter as xxx
from pyUltroid import fns
+
+ from .. import HNDLR, LOGS, asst, udB, ultroid_bot
+ from .._misc import _supporter as config
from .._misc._assistant import asst_cmd, callback, in_pattern
from .._misc._decorators import ultroid_cmd
from .._misc._supporter import Config, admin_cmd, sudo_cmd
@@ -25,9 +43,12 @@ def load_addons(plugin_name):
from ..configs import Var
from ..dB._core import HELP
- name = plugin_name.replace("/", ".").replace("\\", ".").replace(".py","")
+ name = plugin_name.replace("/", ".").replace("\\", ".").replace(".py", "")
spec = util.spec_from_file_location(name, plugin_name)
mod = util.module_from_spec(spec)
+ for path in configPaths:
+ modules[path] = config
+ modules["pyUltroid.functions"] = fns
mod.LOG_CHANNEL = udB.get_key("LOG_CHANNEL")
mod.udB = udB
mod.asst = asst
@@ -61,21 +82,7 @@ def load_addons(plugin_name):
mod.sudo_cmd = sudo_cmd
mod.HELP = HELP.get("Addons", {})
mod.CMD_HELP = HELP.get("Addons", {})
- modules["ub"] = xxx
- modules["var"] = xxx
- modules["support"] = xxx
- modules["userbot"] = xxx
- modules["telebot"] = xxx
- modules["fridaybot"] = xxx
- modules["uniborg.util"] = xxx
- modules["telebot.utils"] = xxx
- modules["userbot.utils"] = xxx
- modules["userbot.events"] = xxx
- modules["userbot.config"] = xxx
- modules["fridaybot.utils"] = xxx
- modules["fridaybot.Config"] = xxx
- modules["userbot.uniborgConfig"] = xxx
- modules["pyUltroid.functions"] = fns
+
spec.loader.exec_module(mod)
modules[name] = mod
doc = modules[name].__doc__.format(i=HNDLR) if modules[name].__doc__ else ""
diff --git a/pyUltroid/version.py b/pyUltroid/version.py
index 17ee6c6c55f822b7ed0c9a6f2865a789d50f4c8b..8c7b646d7733f90eaf46d959c67df1b9e9cdaf7c 100644
--- a/pyUltroid/version.py
+++ b/pyUltroid/version.py
@@ -1,2 +1,2 @@
-__version__ = "2022.12.18"
-ultroid_version = "0.7.2"
+__version__ = "2023.02.20"
+ultroid_version = "0.8"
diff --git a/requirements.txt b/requirements.txt
index a7d7d9aa4d3f331f808d3ce96321306de0649981..9ca5b3894feeeae53924e5c72578573ad47b8086 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,5 @@
# Important Requirements here.
-https://github.com/New-dev0/Telethon/archive/diamond.zip
+https://github.com/New-dev0/Telethon/archive/platy.zip
python-decouple
python-dotenv
diff --git a/resources/session/ssgen.py b/resources/session/ssgen.py
index 794260e96f31638c4ddbabf26deded7094c3f74d..8c9f1ba9c7bc887253f89df23026aff37bcb1af2 100644
--- a/resources/session/ssgen.py
+++ b/resources/session/ssgen.py
@@ -131,14 +131,18 @@ def pyro_session():
# generate a session
API_ID, API_HASH = get_api_id_and_hash()
print("Enter phone number when asked.\n\n")
- with Client(name="ultroid", api_id=API_ID, api_hash=API_HASH, in_memory=True) as pyro:
- ss = pyro.export_session_string()
- pyro.send_message(
- "me",
- f"`{ss}`\n\nAbove is your Pyrogram Session String for @TheUltroid. **DO NOT SHARE it.**",
- )
- print("Session has been sent to your saved messages!")
- exit(0)
+ try:
+ with Client(name="ultroid", api_id=API_ID, api_hash=API_HASH, in_memory=True) as pyro:
+ ss = pyro.export_session_string()
+ pyro.send_message(
+ "me",
+ f"`{ss}`\n\nAbove is your Pyrogram Session String for @TheUltroid. **DO NOT SHARE it.**",
+ )
+ print("Session has been sent to your saved messages!")
+ exit(0)
+ except Exception as er:
+ print("Unexpected error occurred while creating session, make sure to validate your inputs.")
+ print(er)
def main():
diff --git a/resources/startup/_termux.py b/resources/startup/_termux.py
index acaba8e1d4cedd7a252ef399611f4514f2c897d7..6efe89cc6584d2f1c71a39e7ad7a50702bf572f2 100644
--- a/resources/startup/_termux.py
+++ b/resources/startup/_termux.py
@@ -6,10 +6,12 @@
# Please read the GNU Affero General Public License in
# .
-from os import system, path
-from time import sleep
from datetime import datetime
-from colorama import Style, Fore, Back
+from os import path, system
+from time import sleep
+
+from colorama import Back, Fore, Style
+
# clear screen
def clear():
@@ -18,10 +20,11 @@ def clear():
MANDATORY_REQS = [
"https://github.com/New-dev0/Telethon/archive/Cartoon.zip",
- "py-Ultroid==2022.6.6",
"gitpython",
- "enhancer==0.3.4",
+ "enhancer",
"telegraph",
+ "requests",
+ "python-decouple",
"aiohttp",
]
@@ -33,7 +36,7 @@ OPT_PACKAGES = {
"psutil": "Used for .usage command.",
"lottie": "Used for animated sticker related conversion.",
"apscheduler": "Used in autopic/nightmode (scheduling tasks.)",
- #"git+https://github.com/1danish-00/google_trans_new.git": "Used for translation purposes.",
+ # "git+https://github.com/1danish-00/google_trans_new.git": "Used for translation purposes.",
}
APT_PACKAGES = ["ffmpeg", "neofetch", "mediainfo"]
diff --git a/resources/startup/locals.py b/resources/startup/locals.py
index d0f0e13c8004c77bdf0d0d6f4e41ca85af3cc4a2..2a89268ac9cfc02c4be073e2a9d1463457ce06c4 100644
--- a/resources/startup/locals.py
+++ b/resources/startup/locals.py
@@ -76,10 +76,14 @@ def start():
print("\nCongrats. All done!\nTime to start the bot!")
print("\nInstalling requirements... This might take a while...")
os.system("pip3 install --no-cache-dir -r requirements.txt")
- ask = input("Enter 'yes/y' to Install other requirements, required for local deployment.")
- if ask.lower().startswith("y") :
+ ask = input(
+ "Enter 'yes/y' to Install other requirements, required for local deployment."
+ )
+ if ask.lower().startswith("y"):
print("Started Installing...")
- os.system("pip3 install --no-cache-dir -r resources/startup/optional-requirements.txt")
+ os.system(
+ "pip3 install --no-cache-dir -r resources/startup/optional-requirements.txt"
+ )
else:
print("Skipped!")
clear_screen()
diff --git a/resources/startup/optional-requirements.txt b/resources/startup/optional-requirements.txt
index 28a8e43c1e1d0ad1354fcb95bab87872548040fc..a52145449533b96a06167b1bcbbdb10231b3ad7a 100644
--- a/resources/startup/optional-requirements.txt
+++ b/resources/startup/optional-requirements.txt
@@ -13,6 +13,7 @@ gitpython
google-api-python-client
htmlwebshot
lottie
+lxml
numpy>=1.21.2
oauth2client
opencv-python-headless
diff --git a/strings/README.md b/strings/README.md
index 5133377dbd425b0d6bca37410f1795e142d7b579..0a19fba7f3167c120ca9b8dc80d6668eb58c053e 100644
--- a/strings/README.md
+++ b/strings/README.md
@@ -12,14 +12,14 @@
| fa | Persian [Farsi] | 491 | 3 |
| fr | French [Français] | 490 | 4 |
| gu | Gujarati [ŕŞŕŤŕŞŕŞ°ŕŞžŕŞ¤ŕŤ] | 490 | 4 |
-| hi | Hindi [चिŕ¤ŕ¤ŚŕĽ] | 490 | 4 |
+| hi | Hindi [चिŕ¤ŕ¤ŚŕĽ] | 489 | 5 |
| id | Indonesia [Indonesia] | 490 | 4 |
| it | Italian [italiano] | 490 | 4 |
| jp | Japanese [ćĽćŹ] | 490 | 4 |
| ka | Kannada [ŕ˛ŕ˛¨ŕłŕ˛¨ŕ˛Ą] | 490 | 4 |
| ml | Malayalam [എലയഞളŕ´] | 490 | 4 |
| mr | Marathi [ऎरञठŕĽ] | 491 | 3 |
-| my | Malay [Bahasa Melayu] | 490 | 4 |
+| ms | Malay [Bahasa Melayu] | 494 | NULL |
| or | Odia [ŕŹŕŹĄŕŹżŕŹ] | 490 | 4 |
| pt-br | PortuguĂŞs [PortuguĂŞs] | 490 | 4 |
| ru | Russian [Đ ŃŃŃкиК] | 490 | 4 |
diff --git a/strings/__init__.py b/strings/__init__.py
index cdf135417f414a582a95e6360048fb388b73cdf1..30e79706b4719699a8169b6c7f4d49c27249a5c4 100644
--- a/strings/__init__.py
+++ b/strings/__init__.py
@@ -1,9 +1,11 @@
-import sys
import os
-from typing import Any, Dict, List, Union
+import sys
from glob import glob
+from typing import Any, Dict, List, Union
+
from pyUltroid import *
from pyUltroid.fns.tools import translate
+
try:
from yaml import safe_load
except ModuleNotFoundError:
@@ -12,17 +14,25 @@ except ModuleNotFoundError:
ULTConfig.lang = udB.get_key("language") or os.getenv("LANGUAGE", "en")
languages = {}
+PATH = "strings/strings/{}.yml"
+
+
+def load(file):
+ if not file.endswith(".yml"):
+ return
+ elif not os.path.exists(file):
+ file = PATH.format("en")
+ code = file.split("/")[-1].split("\\")[-1][:-4]
+ try:
+ languages[code] = safe_load(
+ open(file, encoding="UTF-8"),
+ )
+ except Exception as er:
+ LOGS.info(f"Error in {file[:-4]} language file")
+ LOGS.exception(er)
-for file in glob("strings/strings/*yml"):
- if file.endswith(".yml"):
- code = file.split("/")[-1].split("\\")[-1][:-4]
- try:
- languages[code] = safe_load(
- open(file, encoding="UTF-8"),
- )
- except Exception as er:
- LOGS.info(f"Error in {file[:-4]} language file")
- LOGS.exception(er)
+
+load(PATH.format(ULTConfig.lang))
def get_string(key: str, _res: bool = True) -> Any:
@@ -52,12 +62,16 @@ def get_string(key: str, _res: bool = True) -> Any:
return None
return languages["en"].get(key) or f"Failed to load language string '{key}'"
+
def get_help(key):
doc = get_string(f"help_{key}", _res=False)
if doc:
return get_string("cmda") + doc
+
def get_languages() -> Dict[str, Union[str, List[str]]]:
+ for file in glob("strings/strings/*yml"):
+ load(file)
return {
code: {
"name": languages[code]["name"],
diff --git a/strings/strings/en.yml b/strings/strings/en.yml
index 2e7e31c5196cb0ce4da32270760ed02993aa98ec..85dd02758f0b98439702565b174d1ff320b4eb38 100644
--- a/strings/strings/en.yml
+++ b/strings/strings/en.yml
@@ -588,7 +588,7 @@ help_afk: " -\n\n⢠`{i}afk `\n AFK means away from keyboar
help_antiflood: " -\n\n⢠`{i}setflood `\n Set flood limit in a chat.\n\n⢠`{i}remflood`\n Remove flood limit from a chat.\n\n⢠`{i}getflood`\n Get flood limit of a chat.\n"
help_asstcmd: " -\n\nâ˘`{i}addcmd `\n It will set new cmd for your assistant bot with that reply message.\n\nâ˘`{i}remcmd `\n It will remove your cmd.\n\nâ˘`{i}listcmd`\n To Get list of all your custom cmd.\n"
help_audiotools: "â Commands Available - \n`.makevoice `\n creates a voice note from Audio.\n\n`.atrim - `\n trim audio as per given time.\n time must be in seconds. `.atrim 50-70`\n\n`.extractaudio `\n To extract the audio from it.\n\n"
-help_autoban: "\n\n⢠`{i}autokick `\n on - To enable.\n off - To disable.\n Automatically kick new joined users from the group.\n\n⢠`{i}cban`\n Enable/Disable autobanning send as channel in used chat.\n\n⢠`{i}addwl `\n Add Channel to channelban whitelist.\n\n⢠`{i}remwl `\n Remove Channel from channelban whitelist.\n\n⢠`{i}listwl` : List all whitelist channels.\n"
+help_autoban: "\n\n⢠`{i}autokick `\n on - To enable.\n off - To disable.\n Automatically kick new joined users from the group.\n"
help_beautify: " -\n\n⢠`{i}carbon `\n Carbonise the text with default settings.\n\n⢠`{i}rcarbon `\n Carbonise the text, with random bg colours.\n\n⢠`{i}ccarbon `\n Carbonise the text, with custom bg colours.\n\n⢠`{i}rayso /`\n `{i}rayso list` - `Get list of themes.`\n"
help_blacklist: " -\n\n⢠`{i}blacklist `\n blacklist the choosen word in that chat.\n\n⢠`{i}remblacklist `\n Remove the word from blacklist..\n\n⢠`{i}listblacklist`\n list all blacklisted words.\n\n 'if a person uses blacklist Word his/her msg will be deleted'\n 'And u Must be Admin in that Chat'\n"
help_bot: "\n\n⢠`{i}alive` | `{i}alive inline`\n Check if your bot is working.\n\n⢠`{i}ping`\n Check Ultroid's response time.\n\n⢠`{i}update`\n See changelogs if any update is available.\n\n⢠`{i}cmds`\n View all plugin names.\n\n⢠`{i}restart`\n To restart your bot.\n\n⢠`{i}logs (sys)`\n Get the full terminal logs.\n⢠`{i}logs carbon`\n Get the carbonized sys logs.\n⢠`{i}logs heroku`\n Get the latest 100 lines of heroku logs.\n\n⢠`{i}shutdown`\n Turn off your bot.\n"
diff --git a/strings/strings/ms.yml b/strings/strings/ms.yml
new file mode 100644
index 0000000000000000000000000000000000000000..04ec596d1ac19d1f9dc26ba71903aa97445d47a7
--- /dev/null
+++ b/strings/strings/ms.yml
@@ -0,0 +1,647 @@
+name: Malay
+natively: Bahasa Melayu
+
+authors:
+ - yuno74
+ - DarkBeamerYT
+
+# pyUltroid
+py_c1: "Sesi string yang salah. Salin tampal dengan betul!"
+py_c2: "Tiada sesi string yang dijumpai. Berhenti..."
+py_c3: "VC_SESSION anda telah tamat tempoh. Membuang VC_SESSION daripada redis...\nMemperbaharuikan/Ubahkan nya untuk mengguna Perbualan Suara/Video daripada akaun VC..."
+py_d1: "`Anda tidak dapat mengguna perintah ini buat masa kini. Hubungi pemilik bot ini!`"
+py_d2: "`Sudo User Penuh Diperlukan...`"
+py_d3: "`Gunakan ini di dalam group/channel.`"
+py_d4: "**â ď¸ Terhad kepada Developer sahaja!**\nJika anda tahu perkara ini lakukan, dan ingin meneruskan, gunakan\n`{}setdb I_DEV True`.\n\nIni mungkin berbahaya."
+py_d5: "`Saya bukanlah admin.`"
+py_d6: "Perintah ini tidak dapat digunakan oleh bot!"
+py_d7: "Perbualan sudah dihidupkan, sila tunggu kemudian dan cuba lagi."
+py_d8: "`Menghantar media atau pelekat tidak dibenarkan dalam group ini.`"
+
+# commons
+com_1: "`Memproses...`"
+com_2: "`Mencari...`"
+com_3: "`Input tidak sah`"
+com_4: "`Media tidak disokong..`"
+com_5: "Sedang muat turun..."
+com_6: "Sedang muat naik..."
+com_7: "`Ada sesuatu yang tidak kena.`"
+
+#chatactions
+can_1: "#GBanned_User telah menyertai.\n\n**Pengguna** : {}\n**Sebab**: {}\n\n`Pengguna telah diban.`"
+can_2: "â #UsernameUpdate\n\n@{} telah menukar usernamenya kepada @{}"
+can_3: "â #UsernameUpdate\n\n{} telah membuang usernamenya. (@{})"
+can_4: "â Username #UsernameUpdate\n\n{} yang baharu --> @{}"
+
+# help
+help_1: "`{}` bukan plugin yang sah!"
+help_2: "Bot tidak bertindak balas terhadap pertanyaan sebaris.\nDicadangkan untuk menggunakan `{}restart`"
+help_3: "`Sila hidupkan mod sebaris untuk bot anda dari` @BotFather."
+help_4: "⢠Plugins"
+help_5: "Tambahan â˘"
+help_6: "â˘â˘Voice Chat"
+help_7: "Tambahan Inlineâ˘â˘"
+help_8: "âď¸ Alatan Pemilik"
+help_9: "Tetapan âď¸"
+help_10: "â˘â˘á´á´á´á´á´â˘â˘"
+help_11: "Nama Plugin-{}\nâ Perintah Tersedia -\n\n"
+help_12: "Voice Chat Bot tidak aktif! Gunakan .setdb VCBOT True untuk mengaktifkan!"
+help_13: "Gunakan '{}setdb ADDONS True' untuk memuatkan tambahan yang sah"
+
+# userlogs
+userlogs_1: "Chat Id yang anda telah letak di dalam Tag Logger salah , Tolong memperbetulkannya."
+userlogs_2: "Tambah saya ke dalam chat Tag Logger anda untuk menlog tags"
+userlogs_3: "Tinggalkan Chat"
+userlogs_4: "Bot Pembantu Anda Tidak Dapat Menghantar Mesej di dalam chat tag log.\nTambahkannya untuk mendapat Tag Logs anda.."
+userlogs_5: "Tinggalkan `{}`"
+
+# admintools
+adm_1: "`Saya tidak dapat teka siapakah dia!`"
+adm_2: "`Hmm.. Nampaknya saya tiada hak di sini!`"
+adm_3: "`Berikan lah masa juga..`"
+pro_1: "`Balas kepada pengguna untuk mempromosikannya!`"
+pro_2: "{} `sekarang lah admin {} dengan tajuk {}.`"
+de_1: "`Balas kepada pengguna untuk menurunkan pangkatnya!`"
+de_2: "{} `bukan lagi admin di dalam {}`"
+ban_1: "`Balas kepada pengguna atau berikan username untuk melarangnya!`"
+ban_2: " `Maaf, tapi saya tidak boleh melarang developer saya đ`"
+ban_3: "`Saya tidak mempunyai hak untuk melarang orang.`"
+ban_4: "{} **telah dilarang oleh** {} **di dalam** `{}`"
+ban_5: "\n**Sebab**: `{}`"
+tban_1: "`Balas kepada seseorang atau memberi ID nya...`"
+tban_2: "`Berjaya melarang` {} `di dalam {} kerana {}`"
+unban_1: "`Balas kepada pengguna atau berikan username untuk unban nya!`"
+unban_2: "`Saya tidak mempunyai hak untuk unban orang.`"
+unban_3: "{} **telah diban oleh** {} **di dalam** `{}`"
+kick_1: "`Saya tidak mempunyai hak untuk mengeluarkan pengguna.`"
+kick_2: " `Maaf, tapi saya tidak boleh mengeluarkan developer saya`đ"
+kick_3: "`Saya tidak boleh mengeluarkannya...`"
+kick_4: "{} **telah dikeluarkan oleh** {} **di dalam** `{}`"
+pin_1: "`Balas mesej untuk menyematkannya!`"
+pinned_1: "Tiada mesej yang disemat dijumpa!"
+pinned_2: "Mesej yang disemat di dalam chat semasa adalah di [sini]({})."
+unpin_1: "Sama ada membalas mesej, atau gunakan `{}unpin all`"
+listpin_1: "Tiada mesej yang disematkan dalam group ini!"
+purge_1: "`Balas kepada mesej sebagai permulaan purge.`"
+purgeall_1: "`Balas kepada mesej seseorang untuk dipadamkan.`"
+purgeall_2: "Berjaya purge semua mesej daripada {}"
+
+# akinator
+aki_1: "Permainan telah ditamatkan...."
+aki_2: "Mulakan Permainan"
+aki_3: "Masa tamat !"
+
+# antiflood
+antiflood_1: "`Tetapan Antiflood telah disable`"
+antiflood_2: "`Tiada had flood di dalam chat ini.`"
+antiflood_3: "`Anda telah dimute.`"
+antiflood_4: "`Berjaya mengemas kini tetapan antiflood kepada {} dalam sembang ini.`"
+antiflood_5: "`Had flood di dalam chat ini adalah {}.`"
+
+# ascii
+ascii_1: "`Balas kepada imej.`"
+ascii_2: "`Sedang menukar kepada html...`"
+
+# audiotools
+audiotools_1: "Balas kepada audio atau video.."
+audiotools_2: "Berjaya muat turun, sekarang menukar kepada voice"
+audiotools_3: "`Beri masa dalam format untuk trim`"
+audiotools_4: "`Data yang salah`"
+audiotools_5: "`Mencuba untuk muat turun...`"
+audiotools_6: "`Masa trim yang salah`"
+audiotools_7: "Audio telah ditrim daripada `{}` kepada `{}`"
+audiotools_8: "`Balas kepada fail video..`"
+audiotools_9: "`Audio tidak dijumpai...`"
+audiotools_10: "`Audio yang telah diekstrak daripada Video...`"
+
+# asstcmd
+asstcmd_1: "`Gunakan perintah ini dengan Balas dan perkataan untuk menggunakan perintah.`"
+asstcmd_2: "`Beri saya perintah yang anda mahu buang.`"
+asstcmd_3: "Berjaya Perintah: `/{}` Dibuang."
+asstcmd_4: "Berjaya Perintah : `/{}` disimpan."
+asstcmd_5: "Tiada perintah dijumpa"
+asstcmd_6: "**SEMUA PERINTAH PEMBANTU**\n\n"
+
+# autocorrect
+act_1: "Ciri AUTOCORRECT Hidup"
+act_2: "Ciri AUTOCORRECT Tutup"
+
+# autopic
+autopic_1: "`Berikan sesuatu untuk dicari...`"
+autopic_2: "Tiada keputusan ditemui untuk `{}`"
+autopic_3: "Mempunyai koleksi `{}` berkaitan dengan carian anda !\nMemulakan Autopic !"
+autopic_4: "AUTOPIC tidak digunakan !!"
+autopic_5: "AUTOPIC Berhenti!"
+
+# inline
+inline_1: "[Ęá´É´á´á´á´É´ á´Ęá´Ęá´ÉŞá´
](t.me/UltroidSupportChat)\n\n**á´á´É´á´ Ęá´É´á´á´á´É´ á´
á´ĘÉŞá´á´á´
á´ {}.\n\nPĘá´É˘ÉŞÉ´s ~ {}**"
+inline_2: "[Ęá´É´á´á´á´É´ á´Ęá´Ęá´ÉŞá´
](t.me/UltroidSupportChat)\n\n**á´á´É´á´ Ęá´É´á´á´á´É´ á´
á´ĘÉŞá´á´á´
á´ {}.\n\nAá´
á´
á´É´s ~ {}**"
+inline_3: "[Ęá´É´á´á´á´É´ á´Ęá´Ęá´ÉŞá´
](t.me/UltroidSupportChat)\n\n**á´á´É´á´ Ęá´É´á´á´á´É´ á´
á´ĘÉŞá´á´á´
á´ {}.\n\nAá´
á´
á´É´s ~ {}\n\nBuat **`.setdb ADDONS True`** á´
á´É´ Ęá´sá´á´Ęá´ á´É´á´á´á´ á´á´É´á´
á´á´á´á´ á´á´
á´
á´É´s..**"
+inline_4: "** Bá´á´ {}\n\ná´á´É´á´ á´á´á´á´á´\n\nPĘá´É˘ÉŞÉ´s ~ {}\nAá´
á´
á´É´s ~ {}\ná´á´á´Ęá´Ę á´á´ĘÉŞÉ´á´á´Ę ~ {}**"
+inline_5: "**Má´É´á´ á´á´Ęá´Ę á´
ÉŞá´á´á´á´á´**"
+inline_6: "**Menu Bantuan Voice Chat untuk {}**\n**Perintah yang ada:** `{}`\n\n@TeamUltroid"
+inline_7: "Taip .help {} untuk mendapatkan senarai perintah."
+inline_8: "Klik butang di bawah untuk mengemaskini!"
+inline_9: "Anda Sudah Pada Versi Terkini"
+
+# tagnotif
+tagnot_1: "{} telah tag anda di dalam {}\n\n```{}```\n\n[đ¨ Mesej đ¨]({})"
+tagnot_2: "{} telah tag anda di dalam {}\n\n [đ¨ Mesej đ¨]({})"
+
+# whisper
+wspr_1: "@{} mesej rahsia untuk anda.\nPadamkan mesej anda selepas membaca.\nAtau mesej seterusnya tidak akan dikemas kini."
+wspr_2: "Mesej dipadam"
+wspr_3: "Tambah beberapa id atau username juga"
+wspr_4: "User {} Tidak Dijumpai\nCari Lagi"
+wspr_5: "Anda tidak boleh melakukan ini"
+
+# afk
+afk_1: "`Tidak lagi Afk\n\nTidak ada untuk ~ {}`"
+afk_2: "#AFK\nSet mod AFK kepada **tidak aktif**\n
+Tidak ada untuk `{}`"
+afk_3: "`Saya sedang AFK.\nTerakhir dilihat {} lepas.`\n\n**Sebab:** `{}`"
+afk_4: "`Saya sedang AFK.\n\nTerakhir dilihat {} lepas.`"
+afk_5: "`Saya akan pergi AFK.`\n\n**Sebab:** `{}`"
+afk_6: "Saya akan pergi AFK."
+
+# bot
+bot_1: "Hi, saya hidup."
+bot_2: "Statistik"
+bot_3: "Repo"
+bot_4: "Bantuan"
+bot_5: "⢠`Sedang restart...`"
+alive_1: "**Userbot Ultroid...**\n\n**{}**\n\nâľ **Pemilik** - `{}`\nâľ **Ultroid** - `{}`\nâľ **Py-Ultroid** - `{}`\nâľ **Masa Beroperasi** - `{}`\nâľ **Python** - `{}`\nâľ **Telethon** - `{}`\nâľ **Branch** - `{}`"
+log: "**Heroku** Log Ultroid.\nDitampal [disini]({}) juga!"
+ping: "**Pong !!** `{}ms`\n**Masa beroperasi** - `{}`"
+usage: "**âď¸ Dyno Usage âď¸**:\n\n-> **Pengunaan dyno untuk** `{}`:\n ⢠**{}h** **{}m |** `[{}%]`\n-> **Baki kuota jam dyno bulan ini**:\n ⢠**{}h** **{}m |** `[{}%]`\n\n**Jumlah Ruang Cakera**: `{}`\n**Telah diguna**: `{}`\n**Yang tertinggal**: `{}`\n\n**đ Pengunaan Data đ**\n**Muat naik**: `{}`\n**Muat turun**: `{}`\n\n**CPU**: `{}%`\n**RAM**: `{}%`\n**DISK**: `{}%`"
+usage_simple: "**Total Disk Space**: `{}`\n**Used**: `{}`\n**Free**: `{}`\n\n**đ Data Usage đ**\n**Upload**: `{}`\n**Down**: `{}`\n\n**CPU**: `{}%`\n**RAM**: `{}%`\n**DISK**: `{}%`"
+shutdown: "Bye {}.\n`Sedang menutup...`"
+
+# blacklist
+blk_1: "`Beri kata untuk disenarai hitamkan..`"
+blk_2: "Berjaya : `{}` Disenarai hitam di sini."
+blk_3: "`Beri kata untuk dibuang dari senarai hitam..`"
+blk_4: "Berjaya : `{}` Dibuang dari senarai hitam."
+blk_5: "Senarai hitam yang telah dijumpa dalam perbualan ini ialah :\n\n"
+blk_6: "Tiada perkataan yang disenarai hitamkan di sini"
+
+# broadcast
+bd_1: "`Menambah ke dalam db...`"
+bd_2: "`Cuba menambah semua saluran admin ke db...`"
+bd_3: "**Berjaya.**\nPerbualan yang telah ada di dalam database: {}\nBaru ditambah: {}"
+bd_4: "Saluran ditambah!"
+bd_5: "`Ditambah ke dalam database!`"
+bd_6: "`Saluran ini sudah ada di dalam database!`"
+bd_7: "Dibuang daripada database"
+bd_8: "`Membuang...`"
+bd_9: "Saluran ini sudah dibuang daripada database. "
+
+# calculator
+calc_1: "⢠Kalkulator Inline Ultroid â˘"
+calc_2: "Buka Kalkulator Lagi"
+
+# channel hacks
+cha_1: "Saluran yang tidak sah diberi"
+cha_2: "Sumber ditambah dengan jayanya"
+cha_3: "Saluran sumber sudah ditambah"
+cha_4: "Database sumber dibersihkan."
+cha_5: "Sumber telah dibuang dari database"
+cha_6: "Saluran sumber sudah dibuang dari database."
+cha_7: "Saluran destinasi dalam database:"
+cha_8: "Saluran sumber dalam database:"
+
+# carbon
+carbon_1: "Dikarbonkan oleh [{}](tg://user?id={})"
+carbon_2: "`Balas kepada mesej atau fail yang boleh dibaca..`"
+carbon_3: "`Bagi warna khas untuk membuat karbon...`"
+
+# chat_bot
+chab_1: "Reply to a user or give me his id/username to add an AI ChatBot!"
+chab_2: "`No user has AI added.`"
+chab_3: "**Total List Of AI Enabled Users In This Chat :**\n\n"
+
+# chats
+chats_1: "`Cant delete this chat.`"
+chats_2: "`I m not an admin`"
+chats_3: "#Deleted\nDeleted {}"
+chats_4: "Your [{}]({}) Group Made Boss!"
+chats_5: "Join @TeamUltroid"
+chats_6: "Your {} Group/Channel Has been made Boss!"
+
+# clean action
+clan_1: "Added Clean Action Setting For this Chat"
+clan_2: "Removed Clean Action Setting For this Chat"
+clan_3: "`Invalid ID`"
+clan_4: "`No Chat Added`"
+clan_5: "Clean Actions are already enabled in this Chat."
+
+# converter
+cvt_1: "`Reply to any media/Document.`"
+cvt_2: "Give The name and extension of file"
+cvt_3: "`Reply to media..`"
+cvt_4: "`Reply to img or file with thumbnail.`"
+cvt_5: "Replied file has no thumbnail.`"
+cvt_6: "Added [This]({}) As Your Custom Thumbnail"
+cvt_7: "`Reply to a readable file`"
+cvt_8: "`Not A Readable File.`"
+
+# eventsofday
+eod_1: "đ **Events of the Day**\n\n"
+eod_2: "⢠**Events for {}/2022**\n\n"
+
+# core
+core_1: "Module Found"
+core_2: "{}.py use .paste to paste in neko and raw.."
+core_3: "Search Again..?"
+core_4: "Module {} Found"
+core_5: "{}.py use .paste to paste in neko and raw.."
+core_6: "Module {}.py Not Found"
+core_7: "No Such Module"
+core_8: "No Module Named {}.py"
+core_9: "`Give name of plugin which u want to unload`"
+core_10: "**UÉ´Ęá´á´á´
á´á´
** `{}` **Sá´á´á´á´ssŇá´ĘĘĘ.**"
+core_11: "**Yá´á´ Cá´É´'á´ UÉ´Ęá´á´á´
OŇŇÉŞá´ÉŞá´Ę PĘá´É˘ÉŞÉ´s**"
+core_12: "**Ná´ PĘá´É˘ÉŞÉ´ Ná´á´á´á´
** `{}`"
+core_13: "`Give name of plugin which u want to uninstall`"
+core_14: "**UÉ´ÉŞÉ´sá´á´ĘĘá´á´
** `{}` **Sá´á´á´á´ssŇá´ĘĘĘ.**"
+core_15: "**Yá´á´ Cá´É´'á´ UÉ´ÉŞÉ´sá´á´ĘĘ OŇŇÉŞá´ÉŞá´Ę PĘá´É˘ÉŞÉ´s**"
+core_16: "`Give name of plugin which u want to load`"
+core_17: "**Sá´á´á´á´ssŇá´ĘĘĘ Lá´á´á´
á´á´
** `{}`"
+core_18: "**Could not load** `{}` **because of the following error.**\n`{}`"
+
+# devtools
+devs_1: "`No cmd given`"
+devs_2: "`Give some python cmd`"
+devs_3: "`Give Some C++ Code..`"
+
+# dm
+dm_1: "`Give Chat username or id where to send.`"
+dm_2: "`Give text to send or reply to msg`"
+dm_3: "âď¸ Message Delivered! âď¸"
+dm_4: "Error : {}\nRead Usage : `{}help other`"
+dm_5: "`Check in Private.`"
+dm_6: "`No message found to deliver :(`"
+
+# echo
+echo_1: "**Activated Echo For Users:**\n\n"
+
+# fake action
+fka_1: "Starting Fake Action For {} sec."
+
+# fedutils
+sf_1: "Starting a Mass-FedBan..."
+sf_2: "`No user designated!`"
+sf_3: "You can't ban my dev you noob!!"
+sf_4: "`Seems like rose isn't responding, or, the plugin is misbehaving`"
+sf_5: "You can only use fed commands once every 5 minutes"
+sf_6: "Try again after 5 mins."
+sf_7: "Unable to collect FedAdminList. Retrying ({}/3)..."
+sf_8: "Error"
+sf_9: "Unable to collect FedAdminList."
+sf_10: "FBaning in {} feds."
+sf_11: "Specified FBan Group ID is incorrect."
+sf_12: "{} Excluded."
+sf_13: "Error in removing FedAdmin file.\n{}"
+sf_14: "SuperFBan Completed.\nTotal Feds - {}.\nExcluded - {}.\n Affected {} feds.\n#TB"
+sf_15: "Starting a Mass-UnFedBan..."
+sf_16: "SuperUnFBan Completed.\nTotal Feds - {}.\nExcluded - {}.\n Affected {} feds.\n#TB"
+sf_17: "`Give me someones id, or reply to somones message to check his/her fedstat.`"
+sf_18: "List of feds {} has been banned in.\n\nCollected using Ultroid."
+sf_19: "**Error**\n `Unblock` @MissRose_Bot `and try again!"
+sf_20: "`Extracting information...`"
+sf_21: "\n\nFedInfo Extracted by Ultroid"
+sf_22: "No user was designated."
+sf_23: "**Error**\n `Unblock` @MissRose_Bot `and try again!"
+
+# filter
+flr_1: "`Use this command word to set as filter and reply...`"
+flr_2: "Filters Found In This Chats Are\n\n"
+flr_3: "`Give the filter to remove..`"
+flr_4: "Done : Filter `{}` Saved."
+flr_5: "Done : Filter `{}` Removed."
+flr_6: "No Filters Found Here"
+
+# fontgen
+fgn_1: "**Available Fonts**\n\n"
+
+# force subscribe
+fsub_1: "Give Channel where you want User to Join !"
+fsub_2: "Give Correct Channel Username or id"
+fsub_3: "ForceSub was not Active in this Chat !"
+fsub_4: "Join Channel"
+fsub_5: "Unmute Me"
+fsub_6: "Please Join That Channel !\nThen Click This Button !"
+fsub_7: "This Message is Not for You"
+fsub_8: "Thanks For Joining ! "
+
+# extra
+ex_1: "`Reply to message..`"
+
+# gdrive
+gdrive_1: "`You have already authorised with Google Drive`"
+gdrive_2: "Go [here](https://console.developers.google.com/flows/enableapi?apiid=drive) and get your `GDRIVE_CLIENT_ID` and `GDRIVE_CLIENT_SECRET`\n\nSend your GDRIVE_CLIENT_ID and GDRIVE_CLIENT_SECRET as this.\n`GDRIVE_CLIENT_ID GDRIVE_CLIENT_SECRET` separated by space."
+gdrive_3: "`Wrong Client Id`"
+gdrive_4: "`Something went wrong! Authorise again.\nIf the same happens, contact `@TeamUltroid"
+gdrive_5: "`Success!\nYou are all set to use Google Drive with Ultroid Userbot.`"
+gdrive_6: "`Go `[here](t.me/{}?start=set)` and setup G-Drive`"
+gdrive_7: "Successfully uploaded [{}]({}) on G-Drive"
+
+# get addons
+gas_1: "Please provide a raw link!"
+
+# greetings
+grt_1: "`Welcome note saved`"
+grt_2: "Please use this in a group and not PMs!"
+grt_3: "`Reply to message which u want to set as welcome`"
+grt_4: "`No welcome was set!`"
+grt_5: "`Welcome Note Deleted`"
+grt_6: "`No goodbye was set!`"
+grt_7: "`Reply to message which u want to set as goodbye`"
+
+# glitch
+glitch_1: "`Glitching...`"
+
+# mediainfo
+mdi_1: "More Explained Info"
+
+# nightmode
+nightm_1: "Give Time in correct format"
+nightm_2: "Setted time successfully"
+nightm_3: "Done, Added Current Chat To Night Mode"
+nightm_4: "Done, Removed Current Chat from Night Mode"
+nightm_5: "Something Went Wrong"
+
+# pmpermit
+pmperm_1: "Please wait for me to respond or you will be blocked and reported as spam!!"
+pmperm_2: "Eyy, I told you not to spam!\nYou've been blocked and reported, for now."
+pmperm_3: "Reply to someone's message or try this command in private."
+
+# schedule_msg
+schdl_1: "`Scheduled msg Succesfully`"
+schdl_2: "`Incorrect Format`"
+
+# searches
+srch_1: "`Search for whom? Give me a user name!!`"
+srch_2: "`No such user found...`"
+srch_3: "`Song not found...`"
+
+# snip
+snip_1: "Give word to set as snip and reply to a message."
+snip_2: "Give the word to remove..."
+snip_3: "No Snips Found Here."
+
+# specialtools
+spcltool_1: "Reply To Audio or video."
+spcltool_2: "`Done.. Now reply to video In which u want to add this Audio`"
+spcltool_3: "Reply To video"
+spcltool_4: "`First reply an audio with .raw`"
+spcltool_5: "Downloaded Successfully, Now Adding Your Audio to video"
+spcltool_6: "`Put input in dd/mm/yyyy format`"
+spcltool_7: "`Happy Birthday To Uđđ`"
+spcltool_8: "Give something to search.."
+spcltool_9: "Found Nothing"
+
+# sudo
+sudo_1: "`Reply to a msg or add it's id/username.`"
+sudo_2: "You cant add yourself as Sudo User..."
+sudo_3: "`No SUDO User was assigned ...`"
+sudo_4: "`Bots can't be added as Sudo Users.`"
+
+# unsplash
+unspl_1: "No Results Found !"
+
+# updater
+upd_1: "`Checking for updates...`"
+upd_2: "`Oops.. Updater cannot continue due to some problems.`\n\n**LOGTRACE:**\n"
+upd_3: "**New UPDATE available for [[{}]]({}/tree/{}):\n\nCHANGELOG**\n\n{}"
+upd_4: "`Changelog is too big, view the file to see it.`"
+upd_5: "Click the below button to update."
+upd_6: "\n`Your BOT is` **up-to-date** `with` **[[{}]]({}/tree/{})**\n"
+upd_7: "`Fast Soft Updating...`"
+
+# upload download
+udl_1: "`Reply to the file/media you want to download...`"
+udl_2: "Download Successful..\nTo\n`{}`\nin `{}`"
+udl_3: "`Give a specific path to file`"
+udl_4: "`Trying to download...`"
+udl_5: "`You forgot to give link :(`"
+udl_6: "`This Directory is Empty.`"
+udl_7: "`You can't do that!`"
+
+# vctools
+vct_1: "`Voice Chat Started...`"
+vct_2: "**Successfully Changed VC Title to** `{}`"
+vct_3: "`Inviting Members to Voice Chat...`"
+vct_4: "`Voice Chat Stopped...`"
+vct_5: "`Invited {} users`"
+vct_6: "No input Found!"
+
+# words
+wrd_1: "⢠**Word :** `{}`\n⢠**Meaning :** __{}__\n\n⢠**Example :** __{}__"
+wrd_2: "**Word** - `{}`\n\n**Synonyms** - \n"
+wrd_3: "**Word** - `{}`\n\n**Antonyms** - \n"
+wrd_4: "`Give a Word to Find Its Meaning..`"
+wrd_5: "Synonyms"
+wrd_6: "Antonyms"
+wrd_7: "No synonym found!!\n\n`{}`"
+wrd_8: "No Antonyms found!!\n\n`{}`"
+
+# profanitY
+prof_1: "`Added This Chat for Profanity Filtering!`"
+prof_2: "`Removed This Chat from Profanity Filtering!`"
+
+# notes
+notes_1: "`Use this Command with Reply and word to use a note.`"
+notes_2: "Done Note : `#{}` saved."
+notes_3: "`Give me the note handler which you want to remove.`"
+notes_4: "Notes Found In This Chats Are\n\n"
+notes_5: "No Notes Found Here"
+
+# stickertools
+sts_1: "`You haven't written any article, Waifu is going away.`"
+sts_2: "`Reply to an Animated Sticker...`"
+sts_3: "**Please select from {} **"
+sts_4: "`Reply to Non Animated Sticker.`"
+sts_5: "**Pack Kanged Successfully**.\n**Kanged Pack:** [link]({})"
+sts_6: "`Reply to message/media...`"
+sts_7: "`Sticker added in a Different Pack !\nThis Pack is Newly created!\nYour pack can be found` [here](t.me/addstickers/{})"
+sts_8: "`Failed to add sticker, use` @Stickers `bot to add the sticker manually.`"
+sts_9: "`Ooo Animated Sticker đ...`"
+sts_10: "`Reply to any media...`"
+sts_11: "Kanging this Sticker..."
+sts_12: "`Kanged!`\n`Emoji-` {}\n`Sticker Pack` [here](t.me/addstickers/{})"
+sts_13: "`Switching to Pack {} due to insufficient space`"
+
+# whichsong
+whs_1: "<⢠Reply to Audio File â˘>"
+whs_2: "`Trying to identify the song....`"
+whs_3: "Failed to Identify song :("
+whs_4: "**Song Recognised!**\nName: __{}__"
+
+# webupload
+wbl_1: "`Provide a File Name pls..`"
+
+# writer
+writer_1: "`Give Some Text Too`"
+
+# webshot
+wbs_1: "`Give a URL please!`"
+wbs_2: "Invalid URL!"
+wbs_3: "**WebShot Generated**\n**URL**: {}"
+
+# youtube
+youtube_1: "Give me a (youtube) URL to download audio from!"
+youtube_2: "`Give A Direct Audio Link To Download`"
+youtube_3: "Give me a (youtube) URL to download video from!"
+youtube_4: "`Give A Direct Video Link To Download`"
+youtube_5: "Give me a (youtube) search query to download audio from!"
+youtube_6: "`Downloading audio song...`"
+youtube_7: "Give me a (youtube) search query to download video from!"
+youtube_8: "`Downloading video song...`"
+
+# ziptools
+zip_1: "Reply to any media/Document."
+zip_2: "First add All Files Via `{}addzip` then doZip to zip all files at one."
+zip_3: "`Reply to zip file only`"
+
+# file share
+fsh_1: "**List of files stored.:**"
+fsh_2: "**File has been stored!**\n\n**Shareable link:** {}"
+fsh_3: "`Reply to a message to make a shareable link!`"
+fsh_4: "**No files stored!**"
+
+# getmsgs
+gms_1: "Provide a valid message link!"
+ls1: "`File doesn't exist or path is incorrect!`"
+th_1: "`Please reply to a file to download its thumbnail!`"
+th_2: "`Replied file has no thumbnail.`"
+
+# ------------------------- assistant --------------------------#
+
+ast_1: "Choose which API you want to set."
+ast_2: "**remove.bg API**\nEnter your API key from remove.bg.\n\nUse /cancel to terminate the operation."
+ast_3: "Hey {}. Please browse through the options"
+ast_4: "List Of Available Languages."
+
+# inlinestuff
+instu_1: "App search. Enter app name!"
+instu_2: "Recent Searches.."
+instu_3: "Enter Query to Search"
+instu_4: "Success"
+
+# games
+games_1: "Choose The Game đŽ"
+games_2: "Choose Category!"
+games_3: "Choose Difficulty Level"
+games_4: "Choose Number of Questions.."
+games_5: "Choose Time Interval..."
+games_6: "**⢠Starting Quiz in 5 secs.** \n**⢠Level :** {}\n**⢠Qs :** {}"
+
+# callbackstuffs
+clst_1: "`Userbot dyno build in progress, please wait for it to complete.`"
+clst_2: "`Successfully Updated!\nRestarting, please wait...`"
+clst_3: "â Generating Changelogs..."
+clst_4: "Something went wrong..."
+clst_5: "Done!"
+
+# pmbot
+pmbot_1: "**You need to join below chat(s) in order to chat with my master!\n\n**"
+pmbot_2: "Please reply to someone to ban him."
+pmbot_3: "User is already banned!"
+pmbot_4: "`GoodBye! You have been banned.`\n**Further messages you send will not be forwarded.**"
+pmbot_5: "Please reply to someone to Unban him."
+pmbot_6: "User was never banned!"
+pmbot_7: "`Congrats! You have been unbanned.`"
+
+# -------------------------- VcBot ------------------------------- #
+
+vcbot_1: "`Left the voice chat.`"
+vcbot_2: "**ERROR:**\n{}"
+vcbot_3: "⢠Volume Changed to `{}%` â˘"
+vcbot_4: "`Please specify a volume from 1 to 200!`"
+vcbot_5: "`Re-joining this voice chat.`"
+vcbot_6: "You haven't connected to a voice chat!"
+vcbot_7: "`Keep patience... It'll take some time.`"
+vcbot_8: "Give only youtube playlist"
+vcbot_9: "Are You Kidding Me?\nWhat to Play?"
+vcbot_10: "Removed Chat from Vc AUTH Groups!"
+vcbot_11: "`Getting Voice Chat Bot Users List...`"
+vcbot_12: "`Muted playback in this chat.`"
+vcbot_13: "`Resumed playback in this chat.`"
+vcbot_14: "`Paused playback in this chat.`"
+vcbot_15: "Please specify a song name or reply to a video file !"
+vcbot_16: "Chat is Not in Vc Auth list..."
+vcbot_17: "`Reply to user's msg or add it's id/username...`"
+vcbot_18: "⢠Vc Auth List is Empty.."
+vcbot_19: "Already Authed This Chat!"
+vcbot_20: "`Downloading and converting...`"
+vcbot_21: "⢠Nothing in queue!"
+vcbot_22: "`Cleaned All Queues In Chat`"
+
+# Help Menus
+
+cmda: "â Commands Available"
+help_admintools: "-\n\n⢠`.promote `\n⢠`.demote`\n Promote/Demote the user in the chat.\n\n⢠`.ban `\n⢠`.unban`\n Ban/Unban the user from the chat.\n\n⢠`.kick `\n Kick the user from the chat.\n\n⢠`.pin `\n Pin the message in the chat\n⢠`.tpin