diff --git a/.env.dist b/.env.dist index 7722fb75..c8e60b89 100644 --- a/.env.dist +++ b/.env.dist @@ -16,9 +16,6 @@ STRINGSESSION={@string_session} # Set if you want to use music bot SECOND_SESSION={@second_session} -# Music handler for music bot -MUSIC_HANDLER={@music_handler} - # PM LIMIT for AntiPM plugin PM_LIMIT={@pm_limit} diff --git a/.github/workflows/cloud-image.yml b/.github/workflows/cloud-image.yml new file mode 100644 index 00000000..7b1299ec --- /dev/null +++ b/.github/workflows/cloud-image.yml @@ -0,0 +1,27 @@ +name: Cloud Docker Image CI + +on: + push: + branches: + - main +jobs: + push_to_registry: + name: Cloud Docker Image CI + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: ./ + file: ./Cloudfile + push: true + tags: qbtaumai/moonubcloud:latest-cloud diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 7d3c5431..18e096f7 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -22,5 +22,6 @@ jobs: uses: docker/build-push-action@v4 with: context: ./ + file: ./Dockerfile push: true tags: qbtaumai/moonuserbot:latest diff --git a/Cloudfile b/Cloudfile new file mode 100644 index 00000000..f5d8283f --- /dev/null +++ b/Cloudfile @@ -0,0 +1,8 @@ +FROM python:3.11 +WORKDIR /app +COPY . /app +RUN apt-get -qq update && apt-get -qq install -y git wget ffmpeg mediainfo \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* +RUN pip install --no-cache-dir -r requirements.txt +CMD ["bash", "cloud.sh"] \ No newline at end of file diff --git a/DISCLAIMER.md b/DISCLAIMER.md new file mode 100644 index 00000000..c5bf3976 --- /dev/null +++ b/DISCLAIMER.md @@ -0,0 +1,6 @@ +## Disclaimer +> [!WARNING] +> The use of this Telegram Userbot is entirely at your own risk. The developer of this Userbot is not responsible for any misuse, damage, or legal consequences that may arise from your use of this software. +>> It is your responsibility to ensure that you use this Userbot in accordance with all applicable laws and regulations, and that you do not engage in any activities that may cause harm to others or violate their privacy. This includes, but is not limited to, the use of this Userbot to send spam, harass others, or engage in any other form of unlawful or malicious activity. +>> The developer of this Userbot does not endorse or condone any such activities, and any such use of this software is strictly prohibited. By using this Userbot, you acknowledge that you are solely responsible for your own actions and that the developer of this Userbot shall not be held liable for any damages or consequences that may arise from your use of this software. +>> It is your responsibility to ensure that you have obtained all necessary permissions and consents before using this Userbot to interact with others, and that you respect their privacy and rights. The developer of this Userbot shall not be held liable for any breach of privacy or rights that may occur as a result of your use of this software. diff --git a/README.md b/README.md index 2acd35a7..b9a68b6e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ [](https://github.com/The-MoonTg-project/Moon-Userbot/blob/main/LICENSE) [](https://makeapullrequest.com) -
+ ***A Simple, Fast, Customizable, Ai powered Userbot for Telegram made after Dragon-Userbot abandoned*** @@ -79,6 +79,8 @@ - **YT Video [How to deploy on Koyeb]**:{AFK_REASON.upper()}\n"
- f"See you after I'm done doing whatever I'm doing."
- )
+ text = db.get("core.afk", "afk_msg", None)
+ if text is None:
+ text = (
+ f"Beep boop. This is an automated message.\n"
+ f"I am not available right now.\n"
+ f"Last seen: {last_seen}\n"
+ f"Reason: {AFK_REASON.upper()}\n"
+ f"See you after I'm done doing whatever I'm doing."
+ )
+ else:
+ last_seen = last_seen.replace("ago", "").strip()
+ text = text.format(last_seen=last_seen, reason=AFK_REASON)
await bot.send_message(
chat_id=GetChatID(message),
text=text,
@@ -144,6 +150,39 @@ async def afk_unset(_, message: Message):
await message.delete()
+@Client.on_message(filters.command("setafkmsg", prefix) & filters.me, group=3)
+async def set_afk_msg(_, message: Message):
+ if not message.reply_to_message:
+ return await message.edit("Reply to a message to set it as your AFK message.")
+
+ msg = message.reply_to_message
+ afk_msg = msg.text or msg.caption
+
+ if not afk_msg:
+ return await message.edit(
+ "Reply to a text or caption message to set it as your AFK message."
+ )
+
+ if len(afk_msg) > 200:
+ return await message.edit(
+ "AFK message is too long. It should be less than 200 characters."
+ )
+ if "{reason}" not in afk_msg:
+ return await message.edit(
+ "AFK message should contain {reason} to indicate where the reason will be placed."
+ )
+ if "{last_seen}" not in afk_msg:
+ return await message.edit(
+ "AFK message should contain {last_seen} to indicate where the last seen time will be placed."
+ )
+
+ old_afk_msg = db.get("core.afk", "afk_msg", None)
+ if old_afk_msg:
+ db.remove("core.afk", "afk_msg")
+ db.set("core.afk", "afk_msg", afk_msg)
+ await message.edit(f"AFK message set to:\n\n{afk_msg}")
+
+
@Client.on_message(filters.me, group=3)
async def auto_afk_unset(_, message: Message):
global AFK, AFK_TIME, AFK_REASON, USERS, GROUPS
@@ -166,4 +205,5 @@ async def auto_afk_unset(_, message: Message):
modules_help["afk"] = {
"afk [reason]": "Go to AFK mode with reason as anything after .afk\nUsage: .afk ",
"unafk": "Get out of AFK",
+ "setafkmsg [reply to message]*": "Set your AFK message. Use {reason} and {last_seen} to indicate where the reason and last seen time will be placed.",
}
diff --git a/modules/antipm.py b/modules/antipm.py
index be51996c..6823d869 100644
--- a/modules/antipm.py
+++ b/modules/antipm.py
@@ -52,14 +52,18 @@ async def anti_pm_handler(client: Client, message: Message):
user = await client.get_users(ids)
u_f = user.first_name
user_info = await client.resolve_peer(ids)
- default_text = f"""Hello, {u_f}!
+ default_text = db.get("core.antipm", "antipm_msg", None)
+ if default_text is None:
+ default_text = f"""Hello, {u_f}!
This is the Assistant Of {u_n}.
My Boss is away or busy as of now, You can wait for him to respond.
Do not spam further messages else I may have to block you!
This is an automated message by the assistant.
Currently You Have {warns} Warnings.
-"""
+ """
+ else:
+ default_text = default_text.format(user=u_f, my_name=u_n, warns=warns)
if db.get("core.antipm", "spamrep", False):
await client.invoke(functions.messages.ReportSpam(peer=user_info))
if db.get("core.antipm", "block", False):
@@ -179,10 +183,52 @@ async def del_contact(_, message: Message):
await message.edit("User DisApproved!")
+@Client.on_message(filters.command(["setantipmmsg", "sam"], prefix) & filters.me)
+async def set_antipm_msg(_, message: Message):
+ if not message.reply_to_message:
+ return await message.edit(
+ "Reply to a message to set it as your antipm message."
+ )
+
+ msg = message.reply_to_message
+ afk_msg = msg.text or msg.caption
+
+ if not afk_msg:
+ return await message.edit(
+ "Reply to a text or caption message to set it as your antipm message."
+ )
+
+ if len(afk_msg) > 200:
+ return await message.edit(
+ "antipm message is too long. It should be less than 200 characters."
+ )
+
+ if "{user}" not in afk_msg:
+ return await message.edit(
+ "antipm message must contain {user} to mention the user."
+ )
+ if "{my_name}" not in afk_msg:
+ return await message.edit(
+ "antipm message must contain {my_name} to mention your name."
+ )
+ if "{warns}" not in afk_msg:
+ return await message.edit(
+ "antipm message must contain {warns} to mention the warns count."
+ )
+
+ old_afk_msg = db.get("core.antipm", "antipm_msg", None)
+ if old_afk_msg:
+ db.remove("core.antipm", "antipm_msg")
+ db.set("core.antipm", "antipm_msg", afk_msg)
+ await message.edit(f"antipm message set to:\n\n{afk_msg}")
+
+
modules_help["antipm"] = {
"antipm [enable|disable]*": "Enable Pm permit",
"antipm_report [enable|disable]*": "Enable spam reporting",
"antipm_block [enable|disable]*": "Enable user blocking",
+ "setantipmmsg [reply to message]*": "Set antipm message. Use {user} to mention the user and {my_name} to mention your name and {warns} to mention the warns count.",
+ "sam [reply to message]*": "Set antipm message. Use {user} to mention the user and {my_name} to mention your name and {warns} to mention the warns count.",
"a": "Approve User",
"d": "DisApprove User",
}
diff --git a/modules/help.py b/modules/help.py
index a0edcbb9..7c0ff3de 100644
--- a/modules/help.py
+++ b/modules/help.py
@@ -21,13 +21,13 @@
total_pages = 0
-async def send_page(message, module_list, page, total_pages):
+async def send_page(message, module_list, page, total_page):
start_index = (page - 1) * 10
end_index = start_index + 10
page_modules = module_list[start_index:end_index]
- text = f"Help for Moon-Userbot\n"
+ text = "Help for Moon-Userbot\n"
text += f"For more help on how to use a command, type {prefix}help [module]\n\n"
- text += f"Page {page}/{total_pages}\n\n"
+ text += f"Help Page No: {page}/{total_page}\n\n"
for module_name in page_modules:
commands = modules_help[module_name]
text += f"• {module_name.title()}: {', '.join([f'{prefix + cmd_name.split()[0]}' for cmd_name in commands.keys()])}\n"
@@ -68,7 +68,7 @@ async def help_cmd(_, message: Message):
@Client.on_message(filters.command(["pn", "pp", "pq"], prefix) & filters.me)
@with_reply
async def handle_navigation(_, message: Message):
- if message.reply_to_message:
+ if message.reply_to_message and "Help Page No:" in message.reply_to_message.text:
global current_page
if message.command[0].lower() == "pn":
if current_page < total_pages:
@@ -77,8 +77,7 @@ async def handle_navigation(_, message: Message):
message, list(modules_help.keys()), current_page, total_pages
)
return await message.reply_to_message.delete()
- else:
- await message.edit("No more pages available.")
+ await message.edit("No more pages available.")
elif message.command[0].lower() == "pp":
if current_page > 1:
current_page -= 1
@@ -86,8 +85,7 @@ async def handle_navigation(_, message: Message):
message, list(modules_help.keys()), current_page, total_pages
)
return await message.reply_to_message.delete()
- else:
- return await message.edit("This is the first page.")
+ return await message.edit("This is the first page.")
elif message.command[0].lower() == "pq":
await message.reply_to_message.delete()
return await message.edit("Help closed.")
diff --git a/modules/loader.py b/modules/loader.py
index 7c5ad3b6..56ba1e0d 100644
--- a/modules/loader.py
+++ b/modules/loader.py
@@ -29,6 +29,22 @@
BASE_PATH = os.path.abspath(os.getcwd())
+CATEGORIES = [
+ "ai",
+ "dl",
+ "admin",
+ "anime",
+ "fun",
+ "images",
+ "info",
+ "misc",
+ "music",
+ "news",
+ "paste",
+ "rev",
+ "tts",
+ "utils",
+]
@Client.on_message(filters.command(["modhash", "mh"], prefix) & filters.me)
@@ -73,25 +89,31 @@ async def loadmod(_, message: Message):
module_name = url.lower()
url = f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{module_name}.py"
else:
- modules_hashes = requests.get(
- "https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt"
- ).text
- resp = requests.get(url)
-
- if not resp.ok:
- await message.edit(
- f"Troubleshooting with downloading module {url}",
- )
- return
-
- if hashlib.sha256(resp.content).hexdigest() not in modules_hashes:
- return await message.edit(
- "Only "
- "verified modules or from the official "
- ""
- "custom_modules repository are supported!",
- disable_web_page_preview=True,
- )
+ if "/" in url:
+ for category in CATEGORIES:
+ if url.startswith(f"{category}/"):
+ url = f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{url}.py"
+ break
+ else:
+ modules_hashes = requests.get(
+ "https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt"
+ ).text
+ resp = requests.get(url)
+
+ if not resp.ok:
+ await message.edit(
+ f"Troubleshooting with downloading module {url}",
+ )
+ return
+
+ if hashlib.sha256(resp.content).hexdigest() not in modules_hashes:
+ return await message.edit(
+ "Only "
+ "verified modules or from the official "
+ ""
+ "custom_modules repository are supported!",
+ disable_web_page_preview=True,
+ )
module_name = url.split("/")[-1].split(".")[0]
diff --git a/modules/safone.py b/modules/safone.py
deleted file mode 100644
index fe9c188e..00000000
--- a/modules/safone.py
+++ /dev/null
@@ -1,517 +0,0 @@
-# Moon-Userbot - telegram userbot
-# Copyright (C) 2020-present Moon Userbot Organization
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see " + formatted_content + "
" - - data = {"title": title, "content": formatted_content, "author_name": user_name} - - response = requests.post( - url=f"{url}/telegraph/text", headers=headers, json=data, timeout=5 - ) - - result = response.json() - - return result["url"] - - -async def voice_characters(): - response = requests.get(url=f"{url}/speech/characters", headers=headers, timeout=5) - - result = response.json() - - return ", ".join(result["characters"]) - - -async def make_rayso(code: str, title: str, theme: str): - data = { - "code": code, - "title": title, - "theme": theme, - "padding": 64, - "language": "auto", - "darkMode": False, - } - response = requests.post(f"{url}/rayso", data=data, headers=headers) - if response.status_code != 200: - return None - result = response.json() - try: - if result["error"] is not None: - return None - except KeyError: - pass - image_data = result["image"] - file_name = "rayso.png" - with open(file_name, "wb") as f: - f.write(base64.b64decode(image_data)) - return file_name - - -@Client.on_message(filters.command("asq", prefix) & filters.me) -async def asq(_, message: Message): - if len(message.command) > 1: - query = message.text.split(maxsplit=1)[1] - else: - await message.edit_text("Query not provided!") - return - await message.edit_text("Processing...") - response = requests.get(url=f"{url}/asq?query={query}", headers=headers, timeout=5) - if response.status_code != 200: - await message.edit_text("Something went wrong!") - return - - result = response.json() - - ans = result["answer"] - await message.edit_text( - f"Q. {query}\n A. {ans}", parse_mode=enums.ParseMode.MARKDOWN - ) - - -@Client.on_message(filters.command("sgemini", prefix) & filters.me) -async def sgemini(_, message: Message): - if len(message.command) > 1: - prompt = message.text.split(maxsplit=1)[1] - else: - await message.edit_text("prompt not provided!") - return - await message.edit_text("Processing...") - response = requests.get(url=f"{url}/bard?query={prompt}", headers=headers) - if response.status_code != 200: - await message.edit_text("Something went wrong!") - return - - result = response.json() - - ans = result["message"] - await message.edit_text( - f"Prompt: {prompt}\n Ans: {ans}", parse_mode=enums.ParseMode.MARKDOWN - ) - - -@Client.on_message(filters.command("app", prefix) & filters.me) -async def app(client: Client, message: Message): - try: - chat_id = message.chat.id - await message.edit_text("Processing...") - if len(message.command) > 1: - query = message.text.split(maxsplit=1)[1] - else: - message.edit_text( - "What should i search? You didn't provided me with any value to search" - ) - - response = requests.get( - url=f"{url}/apps?query={query}&limit=1", headers=headers, timeout=5 - ) - if response.status_code != 200: - await message.edit_text("Something went wrong") - return - - result = response.json() - - try: - coverImage_url = result["results"][0]["icon"] - coverImage = requests.get(url=coverImage_url).content - async with aiofiles.open("coverImage.jpg", mode="wb") as f: - await f.write(coverImage) - - except Exception: - coverImage = None - - description = result["results"][0]["description"] - developer = result["results"][0]["developer"] - IsFree = result["results"][0]["free"] - genre = result["results"][0]["genre"] - package_name = result["results"][0]["id"] - title = result["results"][0]["title"] - price = result["results"][0]["price"] - link = result["results"][0]["link"] - rating = result["results"][0]["rating"] - - await message.delete() - await client.send_media_group( - chat_id, - [ - InputMediaPhoto( - "coverImage.jpg", - caption=f"Title:{title}\nRating: {rating}\nIsFree: {IsFree}\nPrice: {price}\nPackage Name: {package_name}\nGenres: {genre}\nDeveloper: {developer}\nDescription: {description}\nLink: {link}",
- )
- ],
- )
-
- except MediaCaptionTooLong:
- description = description[:850]
- await message.delete()
- await client.send_media_group(
- chat_id,
- [
- InputMediaPhoto(
- "coverImage.jpg",
- caption=f"Title: {title}\nRating: {rating}\nIsFree: {IsFree}\nPrice: {price}\nPackage Name: {package_name}\nGenres: {genre}\nDeveloper: {developer}\nDescription: {description}\nLink: {link}",
- )
- ],
- )
- except Exception as e:
- await message.edit_text(format_exc(e))
- finally:
- if os.path.exists("coverImage.jpg"):
- os.remove("coverImage.jpg")
-
-
-@Client.on_message(filters.command("tsearch", prefix) & filters.me)
-async def tsearch(client: Client, message: Message):
- try:
- chat_id = message.chat.id
- limit = 10
- await message.edit_text("Processing...")
- if len(message.command) > 1:
- query = message.text.split(maxsplit=1)[1]
- else:
- message.edit_text(
- "What should i search? You didn't provided me with any value to search"
- )
-
- response = requests.get(
- url=f"{url}/torrent?query={query}&limit={limit}", headers=headers
- )
- if response.status_code != 200:
- await message.edit_text("Something went wrong")
- return
-
- result = response.json()
-
- coverImage_url = result["results"][0]["thumbnail"]
- description = result["results"][0]["description"]
- genre = result["results"][0]["genre"]
- category = result["results"][0]["category"]
- title = result["results"][0]["name"]
- link = result["results"][0]["magnetLink"]
- link_result = await telegraph(
- title=title, user_name=message.from_user.first_name, content=link
- )
- language = result["results"][0]["language"]
- size = result["results"][0]["size"]
-
- results = []
-
- for i in range(min(limit, len(result["results"]))):
- descriptions = result["results"][i]["description"]
- genres = result["results"][i]["genre"]
- categorys = result["results"][i]["category"]
- titles = result["results"][i]["name"]
- links = result["results"][i]["magnetLink"]
- languages = result["results"][i]["language"]
- sizes = result["results"][i]["size"]
-
- r = f"Title: {titles}\nCategory: {categorys}\nLanguage: {languages}\nSize: {sizes}\nGenres: {genres}\nDescription: {descriptions}\nMagnet Link: {links}
"
- results.append(r)
-
- all_results_content = "
".join(results)
-
- link_results = await telegraph(
- title="Search Results",
- user_name=message.from_user.first_name,
- content=all_results_content,
- )
-
- if coverImage_url is not None:
- coverImage = requests.get(url=coverImage_url).content
- async with aiofiles.open("coverImage.jpg", mode="wb") as f:
- await f.write(coverImage)
-
- await message.delete()
- await client.send_media_group(
- chat_id,
- [
- InputMediaPhoto(
- "coverImage.jpg",
- caption=f"Title: {title}\nCategory: {category}\nLanguage: {language}\nSize: {size}\nGenres: {genre}\nDescription: {description}\nMagnet Link: Click Here\nMore Results: Click Here",
- )
- ],
- )
- else:
- await message.edit_text(
- f"Title: {title}\nCategory: {category}\nLanguage: {language}\nSize: {size}\nGenres: {genre}\nDescription: {description}\nMagnet Link: Click Here\nMore Results: Click Here",
- disable_web_page_preview=True,
- )
-
- except MediaCaptionTooLong:
- description = description[:850]
- await message.delete()
- await client.send_media_group(
- chat_id,
- [
- InputMediaPhoto(
- "coverImage.jpg",
- caption=f"Title: {title}\nCategory: {category}\nLanguage: {language}\nSize: {size}\nGenres: {genre}\nDescription: {description}\nMagnet Link: Click Here",
- )
- ],
- )
-
- except MessageTooLong:
- description = description[:150]
- await message.edit_text(
- f"Title: {title}\nCategory: {category}\nLanguage: {language}\nSize: {size}\nGenres: {genre}\nDescription: {description}\nMagnet Link: Click Here",
- disable_web_page_preview=True,
- )
-
- except Exception as e:
- await message.edit_text(format_exc(e))
- finally:
- if os.path.exists("coverImage.jpg"):
- os.remove("coverImage.jpg")
-
-
-@Client.on_message(filters.command("tts", prefix) & filters.me)
-async def tts(client: Client, message: Message):
- characters = await voice_characters()
- await message.edit_text("Please Wait...")
- try:
- if len(message.command) > 2:
- character, prompt = message.text.split(maxsplit=2)[1:]
- if character not in characters:
- await message.edit_text(
- f"Usage: {prefix}tts [character]* [text/reply to text]*\n Available Characters: {characters}
"
- )
- return
-
- elif message.reply_to_message and len(message.command) > 1:
- character = message.text.split(maxsplit=1)[1]
- if character in characters:
- prompt = message.reply_to_message.text
- else:
- await message.edit_text(
- f"Usage: {prefix}tts [character]* [text/reply to text]*\n Available Characters: {characters}
"
- )
- return
-
- else:
- await message.edit_text(
- f"Usage: {prefix}tts [character]* [text/reply to text]*\n Available Characters: {characters}
"
- )
- return
-
- data = {"text": prompt, "character": character}
- response = requests.post(url=f"{url}/speech", headers=headers, json=data)
- if response.status_code != 200:
- await message.edit_text("Something went wrong")
- return
-
- result = response.json()
- audio_data = result["audio"]
- audio_data = base64.b64decode(audio_data)
- async with aiofiles.open(f"{prompt}.mp3", mode="wb") as f:
- await f.write(audio_data)
-
- await message.delete()
- await client.send_audio(
- chat_id=message.chat.id,
- audio=f"{prompt}.mp3",
- caption=f"Characters: {character}\nPrompt: {prompt}",
- )
- if os.path.exists(f"{prompt}.mp3"):
- os.remove(f"{prompt}.mp3")
-
- except KeyError:
- try:
- error = result["error"]
- await message.edit_text(error)
- except KeyError:
- await message.edit_text(
- f"Usage: {prefix}tts [character]* [text/reply to text]*\n Available Characters: {characters}
"
- )
- except Exception as e:
- await message.edit_text(format_exc(e))
-
-
-@Client.on_message(
- filters.command(["carbonnowsh", "carboon", "carbon", "cboon"], prefix) & filters.me
-)
-async def carbon(client: Client, message: Message):
- if message.reply_to_message:
- text = message.reply_to_message.text
- message_id = message.reply_to_message.id
- elif len(message.command) > 1:
- message_id = None
- text = message.text.split(maxsplit=1)[1]
- else:
- await message.edit_text("Query not provided!")
- return
- await message.edit_text("Processing...")
-
- image_file = await make_carbon(text)
-
- await message.delete()
- try:
- await client.send_photo(
- chat_id=message.chat.id,
- photo=image_file,
- caption=f"Text: {text}",
- reply_to_message_id=message_id,
- )
- except MediaCaptionTooLong:
- cap = text[:850]
- await client.send_photo(
- chat_id=message.chat.id,
- photo=image_file,
- caption=f"Text: {cap}",
- reply_to_message_id=message_id,
- )
- except Exception as e:
- await message.edit_text(format_exc(e))
- if os.path.exists("carbon.png"):
- os.remove("carbon.png")
-
-
-@Client.on_message(filters.command("ccgen", prefix) & filters.me)
-async def ccgen(_, message: Message):
- if len(message.command) > 1:
- bins = message.text.split(maxsplit=1)[1]
- else:
- await message.edit_text("Code not provided!")
- return
- await message.edit_text("Processing...")
- response = requests.get(url=f"{url}/ccgen?bins={bins}", headers=headers)
- if response.status_code != 200:
- await message.edit_text("Something went wrong")
- return
-
- result = response.json()
-
- cards = result["results"][0]["cards"]
- cards_str = "\n".join([f'"{card}"' for card in cards])
- bins = result["results"][0]["bin"]
- await message.edit_text(
- f"Bins: {bins}\nTotal: {len(cards)}\nCards: \n{cards_str}"
- )
-
-
-@Client.on_message(filters.command("rayso", prefix) & filters.me)
-async def rayso(client: Client, message: Message):
- title = "Untitled"
- themes = [
- "vercel",
- "supabase",
- "tailwind",
- "clerk",
- "mintlify",
- "prisma",
- "bitmap",
- "noir",
- "ice",
- "sand",
- "forest",
- "mono",
- "breeze",
- "candy",
- "crimson",
- "falcon",
- "meadow",
- "midnight",
- "raindrop",
- "sunset",
- ]
- if message.reply_to_message:
- text = message.reply_to_message.text
- message_id = message.reply_to_message.id
- if 2 <= len(message.command) <= 3:
- title = message.text.split(maxsplit=2)[1]
- theme = message.text.split(maxsplit=2)[2].lower()
- if theme not in themes:
- theme = "breeze"
- elif len(message.command) > 1:
- message_id = message.id
- title = message.text.split(maxsplit=3)[1]
- theme = message.text.split(maxsplit=3)[2]
- if theme not in themes:
- theme = "breeze"
- text = message.text.split(maxsplit=3)[3]
- else:
- await message.edit_text("Query not provided!")
- return
- await message.edit_text("Processing...")
-
- image_file = await make_rayso(text, title, theme)
-
- if image_file is None:
- await message.edit_text("Something went wrong")
- return
- try:
- await client.send_photo(
- chat_id=message.chat.id,
- photo=image_file,
- caption=f"Text: {text}",
- reply_to_message_id=message_id,
- )
- await message.delete()
- except MediaCaptionTooLong:
- cap = text[:850]
- await client.send_photo(
- chat_id=message.chat.id,
- photo=image_file,
- caption=f"Text: {cap}",
- reply_to_message_id=message_id,
- )
- await message.delete()
- except Exception as e:
- await message.edit_text(format_exc(e))
- if os.path.exists(image_file):
- os.remove(image_file)
-
-
-modules_help["safone"] = {
- "asq [query]*": "Asq",
- "app [query]*": "Search for an app on Play Store",
- "tsearch [query]*": "Search Torrent",
- "tts [character]* [text/reply to text]*": "Convert Text to Speech",
- "sgemini [prompt]*": "Gemini Model through safone api",
- "carbon [code/file/reply]": "Create beautiful image with your code",
- "ccgen [bins]*": "Generate credit cards",
- "rayso [title]* [theme]* [text/reply to text]*": "Create beautiful image with your text",
-}
diff --git a/start b/start
new file mode 100755
index 00000000..cb333fff
--- /dev/null
+++ b/start
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+if [ -d ".venv" ]; then
+ . .venv/bin/activate
+elif [ -d "venv" ]; then
+ . venv/bin/activate
+fi
+
+python3 main.py
diff --git a/utils/scripts.py b/utils/scripts.py
index ac45ed88..89813ba3 100644
--- a/utils/scripts.py
+++ b/utils/scripts.py
@@ -24,13 +24,11 @@
import sys
import time
import traceback
-from PIL import Image, ImageEnhance
+from PIL import Image
from io import BytesIO
-import aiohttp
from types import ModuleType
from typing import Dict, Tuple
-from PIL import Image
import psutil
from pyrogram import Client, errors, enums
from pyrogram.errors import FloodWait, MessageNotModified, UserNotParticipant
@@ -216,25 +214,6 @@ def text(message: Message) -> str:
return message.text if message.text else message.caption
-async def make_carbon(code):
- url = "https://carbonara.solopov.dev/api/cook"
-
- async with aiohttp.ClientSession() as session:
- async with session.post(url, json={"code": code}) as resp:
- image_data = await resp.read()
-
- carbon_image = Image.open(BytesIO(image_data))
-
- enhancer = ImageEnhance.Brightness(carbon_image)
- bright_image = enhancer.enhance(1.0)
-
- output_image = BytesIO()
- bright_image.save(output_image, format="PNG", quality=95)
- output_image.name = "carbon.png"
-
- return output_image
-
-
def restart() -> None:
music_bot_pid = db.get("custom.musicbot", "music_bot_pid", None)
if music_bot_pid is not None: