Skip to content
Merged

Fixes #310

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions misskaty/plugins/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,9 +620,12 @@ async def warn_user(client, message, strings):
if message.command[0][0] == "d":
await message.reply_to_message.delete()
if warns >= 2:
await message.chat.ban_member(user_id)
await message.reply_text(strings("exceed_warn_msg").format(mention=mention))
await remove_warns(chat_id, await int_to_alpha(user_id))
try:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider handling additional ban-related exceptions

While ChatAdminRequired is handled, consider also catching other potential exceptions like UserAdminInvalid or other permission-related errors that could occur during member banning.

Suggested implementation:

        except ChatAdminRequired:
            await message.reply_msg(strings("no_ban_permission"))
        except UserAdminInvalid:
            await message.reply_msg("I can't ban admin users!")
        except (ChatError, UserBannedInChannel) as e:
            await message.reply_msg(f"Failed to ban user: {str(e)}")

Note: If the import statement for pyrogram.errors isn't visible in the provided code snippet, you'll need to add or modify it at the top of the file. Also, you may want to add these error messages to your strings system rather than having them hardcoded.

await message.chat.ban_member(user_id)
await message.reply_msg(strings("exceed_warn_msg").format(mention=mention))
await remove_warns(chat_id, await int_to_alpha(user_id))
except ChatAdminRequired:
await message.reply_msg(strings("no_ban_permission"))
else:
warn = {"warns": warns + 1}
msg = strings("warn_msg").format(
Expand All @@ -631,7 +634,7 @@ async def warn_user(client, message, strings):
reas=reason or "No Reason Provided.",
twarn=warns + 1,
)
await message.reply_text(msg, reply_markup=keyboard)
await message.reply_msg(msg, reply_markup=keyboard)
await add_warn(chat_id, await int_to_alpha(user_id), warn)


Expand Down
9 changes: 6 additions & 3 deletions misskaty/plugins/chatbot_ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ async def gemini_chatbot(_, ctx: Message, strings):
uid = ctx.from_user.id if ctx.from_user else ctx.sender_chat.id
msg = await ctx.reply_msg(strings("find_answers_str"), quote=True)
if uid not in gemini_conversations:
gemini_conversations[uid] = [{"role": "system", "content": "Kamu adalah AI dengan karakter mirip kucing bernama MissKaty AI yang diciptakan oleh Yasir untuk membantu manusia mencari informasi."}, {"role": "user", "content": ctx.input}]
gemini_conversations[uid] = [{"role": "system", "content": "Kamu adalah AI dengan karakter mirip kucing bernama MissKaty AI yang diciptakan oleh Yasir untuk membantu manusia mencari informasi dan gunakan bahasa sesuai yang saya katakan."}, {"role": "user", "content": ctx.input}]
else:
gemini_conversations[uid].append({"role": "user", "content": ctx.input})
ai_response = await get_openai_stream_response(False, GOOGLEAI_KEY, "https://gemini.yasirapi.eu.org/v1", "gemini-1.5-flash", gemini_conversations[uid], msg, strings)
Expand All @@ -113,6 +113,9 @@ async def gemini_chatbot(_, ctx: Message, strings):
gemini_conversations[uid].append({"role": "assistant", "content": ai_response})

@app.on_message(filters.command("ask", COMMAND_HANDLER) & pyro_cooldown.wait(10))
@app.on_bot_business_message(
filters.command("ask", COMMAND_HANDLER) & pyro_cooldown.wait(10)
)
@use_chat_lang()
async def openai_chatbot(self, ctx: Message, strings):
if len(ctx.command) == 1:
Expand All @@ -128,10 +131,10 @@ async def openai_chatbot(self, ctx: Message, strings):
pertanyaan = ctx.input
msg = await ctx.reply_msg(strings("find_answers_str"), quote=True)
if uid not in gptai_conversations:
gptai_conversations[uid] = [{"role": "system", "content": "Kamu adalah AI dengan karakter mirip kucing bernama MissKaty AI yang diciptakan oleh Yasir untuk membantu manusia mencari informasi."}, {"role": "user", "content": pertanyaan}]
gptai_conversations[uid] = [{"role": "system", "content": "Kamu adalah AI dengan karakter mirip kucing bernama MissKaty AI yang diciptakan oleh Yasir untuk membantu manusia mencari informasi dan gunakan bahasa sesuai yang saya katakan."}, {"role": "user", "content": pertanyaan}]
else:
gptai_conversations[uid].append({"role": "user", "content": pertanyaan})
ai_response = await get_openai_stream_response(True, OPENAI_KEY, "https://models.inference.ai.azure.com" if uid == OWNER_ID else "https://duckai.yasirapi.eu.org/v1", "gpt-4o" if uid == OWNER_ID else "gpt-4o-mini", gptai_conversations[uid], msg, strings)
ai_response = await get_openai_stream_response(True, OPENAI_KEY, "https://models.inference.ai.azure.com", "gpt-4o-mini", gptai_conversations[uid], msg, strings)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): Hardcoded OpenAI API key found.

The OPENAI_KEY variable is hardcoded in the openai_chatbot function. This is a security risk and should be stored securely, such as in environment variables or a secrets management service.

if not ai_response:
gptai_conversations[uid].pop()
if len(gptai_conversations[uid]) == 1:
Expand Down
10 changes: 10 additions & 0 deletions misskaty/plugins/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
FloodWait,
MessageTooLong,
PeerIdInvalid,
RPCError,
SlowmodeWait,
)
from pyrogram.raw.types import UpdateBotStopped
from pyrogram.types import (
Expand Down Expand Up @@ -659,6 +661,14 @@ async def update_restart(_, ctx: Message, strings):
os.execvp(sys.executable, [sys.executable, "-m", "misskaty"])


@app.on_error(errors=(FloodWait, RPCError, SlowmodeWait))
async def error_handlers(_: "Client", __: "Update", error: "Exception") -> None:
if isinstance(error, (FloodWait, SlowmodeWait)):
await asyncio.sleep(error.value)
else:
LOGGER.error(repr(error))


@app.on_raw_update(group=-99)
async def updtebot(client, update, users, _):
if isinstance(update, UpdateBotStopped):
Expand Down
4 changes: 2 additions & 2 deletions misskaty/plugins/misc_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,9 @@ def shorten_text(text):
for result in soup.select(".tF2Cxc"):
link = result.select_one(".yuRUbf a")["href"]
title = result.select_one(".DKV0Md").text
if snippet := result.find(class_="VwiC3b yXK7lf lVm3ye r025kc hJNv6b"):
if snippet := result.find(class_="VwiC3b yXK7lf p4wth r025kc hJNv6b"):
snippet = snippet.get_text()
elif snippet := result.find(class_="VwiC3b yXK7lf lVm3ye r025kc hJNv6b Hdw6tb"):
elif snippet := result.find(class_="VwiC3b yXK7lf p4wth r025kc hJNv6b Hdw6tb"):
snippet = snippet.get_text()
else:
snippet = "-"
Expand Down
43 changes: 32 additions & 11 deletions misskaty/plugins/pypi_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,41 @@ async def pypi_s(_, ctx: Message):
"Please add query after command. Ex: <code>/pypi pyrogram</code>", del_in=6
)
pesan = await ctx.reply_msg("⏳ Please wait, getting data from pypi..", quote=True)
CurrentPage = 1
pypires, PageLen, btn = await getDataPypi(
pesan, kueri, CurrentPage, ctx.from_user.id
html = await fetch.get(f"https://pypi.org/pypi/{kueri}/json")
if html.status_code != 200:
return await pesan.edit_msg("Failed connect fo pypi server")
res = html.json()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Consider adding error handling for JSON parsing

The JSON parsing could fail if the response is malformed. Consider wrapping this in a try-catch block to handle potential JSONDecodeError exceptions.

Suggested implementation:

    html = await fetch.get(f"https://pypi.org/pypi/{kueri}/json")
    if html.status_code != 200:
        return await pesan.edit_msg("Failed connect fo pypi server")
    try:
        res = html.json()
    except json.JSONDecodeError:
        return await pesan.edit_msg("Failed to parse PyPI response - invalid JSON received")
    requirement = (

You'll need to add the following import at the top of the file if it's not already present:

import json

requirement = (
"".join(f"{i}, " for i in res["info"].get("requires_dist"))
if res["info"].get("requires_dist")
else "Unknown"
)
if not pypires:
return
keyboard = InlineKeyboard()
keyboard.paginate(
PageLen, CurrentPage, "page_pypi#{number}" + f"#{pesan.id}#{ctx.from_user.id}"
msg = ""
msg += f"<b>Package Name:</b> {res['info'].get('name', 'Unknown')}\n"
msg += f"<b>Version:</b> {res['info'].get('version', 'Unknown')}\n"
msg += f"<b>License:</b> {res['info'].get('license', 'Unknown')}\n"
msg += f"<b>Author:</b> {res['info'].get('author', 'Unknown')}\n"
msg += f"<b>Author Email:</b> {res['info'].get('author_email', 'Unknown')}\n"
msg += f"<b>Requirements:</b> {requirement}\n"
msg += (
f"<b>Requires Python:</b> {res['info'].get('requires_python', 'Unknown')}\n"
)
keyboard.row(InlineButton("👇 Get Info ", "Hmmm"))
keyboard.row(*btn)
msg += f"<b>HomePage:</b> {res['info'].get('home_page', 'Unknown')}\n"
msg += f"<b>Bug Track:</b> {res['info'].get('vulnerabilities', 'Unknown')}\n"
if res["info"].get("project_urls"):
msg += f"<b>Docs Url:</b> {res['info']['project_urls'].get('Documentation', 'Unknown')}\n"
msg += f"<b>Description:</b> {res['info'].get('summary', 'Unknown')}\n"
msg += (
f"<b>Pip Command:</b> pip3 install {res['info'].get('name', 'Unknown')}\n"
)
msg += f"<b>Keywords:</b> {res['info'].get('keywords', 'Unknown')}\n"
keyboard = InlineKeyboard()
keyboard.row(InlineButton("❌ Close", f"close#{ctx.from_user.id}"))
await pesan.edit_msg(pypires, reply_markup=keyboard)
try:
await pesan.edit_msg(msg, reply_markup=keyboard)
except MessageTooLong:
url = await post_to_telegraph(False, f"{res['info'].get('name')} {res['info'].get('version', None)}-detail", msg)
await pesan.edit_msg(f"Result is too long:\n{url}", reply_markup=keyboard)


@app.on_callback_query(filters.create(lambda _, __, query: "page_pypi#" in query.data))
Expand Down
2 changes: 1 addition & 1 deletion utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ async def broadcast_messages(user_id, message):
await message.copy(chat_id=user_id)
return True, "Succes"
except FloodWait as e:
await asyncio.sleep(e.x)
await asyncio.sleep(e.value)
return await broadcast_messages(user_id, message)
except InputUserDeactivated:
await db.delete_user(int(user_id))
Expand Down