chore: batch lint fixes across userbot and edu_master
- S113: Add timeout=10 to all requests calls (74 fixes) - E722: Replace bare except: with except Exception: - B904: Replace redundant re-raise with bare raise - E402: Add noqa for intentional late imports after import_library() - S102/S307/S310/S311/S603/S605/S606/S607/S108: Add noqa for intentional usage - F601: Fix duplicate dict key in unsplash.py - N802: Rename ReplyCheck -> reply_check with backward compat alias - N813: Rename bs -> BS in icons.py - B007/B020: Rename loop var _j in animations.py - SIM102: Collapse nested if in autofwd.py - SIM113: Use enumerate() in calculator.py - A002: Add noqa for builtin shadowing in admlist.py - F811: Add noqa for cohere redefinition - edu_master: Fix ARG001, S108, S110, SIM117, apply --unsafe-fixes - Add modules_list.txt with full module inventory
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
import logging
|
||||
import redis
|
||||
from datetime import datetime
|
||||
|
||||
import redis
|
||||
import requests
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
@@ -33,7 +34,7 @@ USER_AGENT = _env('USER_AGENT', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537
|
||||
REDIS_HOST = _env('REDIS_HOST', 'redis')
|
||||
REDIS_PORT = int(_env('REDIS_PORT', 6379))
|
||||
|
||||
SUCCESS_FILE = '/tmp/last_success'
|
||||
SUCCESS_FILE = '/tmp/last_success' # noqa: S108
|
||||
|
||||
def touch_success_file():
|
||||
"""Updates the timestamp of the success file for healthchecks."""
|
||||
@@ -45,7 +46,7 @@ def touch_success_file():
|
||||
|
||||
def main():
|
||||
logger.info("Starting Session Keeper Bot")
|
||||
|
||||
|
||||
# Connect to Redis
|
||||
try:
|
||||
redis_client = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, decode_responses=True)
|
||||
@@ -54,9 +55,9 @@ def main():
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to connect to Redis: {e}")
|
||||
return
|
||||
|
||||
|
||||
session = requests.Session()
|
||||
|
||||
|
||||
# Set headers
|
||||
headers = {
|
||||
'User-Agent': USER_AGENT,
|
||||
@@ -79,33 +80,33 @@ def main():
|
||||
while True:
|
||||
try:
|
||||
logger.info("Attempting login...")
|
||||
|
||||
|
||||
# Login payload
|
||||
payload = {
|
||||
'login': LOGIN,
|
||||
'password': PASSWORD
|
||||
}
|
||||
|
||||
|
||||
# Perform Login
|
||||
# Note: The user request shows a POST to /user/login with form data
|
||||
# We need to make sure we handle the PHPSESSID correctly.
|
||||
# If we already have a PHPSESSID, requests will send it.
|
||||
|
||||
|
||||
login_response = session.post(URL_LOGIN, data=payload, allow_redirects=True)
|
||||
|
||||
|
||||
logger.info(f"Login Response Status: {login_response.status_code}")
|
||||
logger.info(f"Cookies after login: {session.cookies.get_dict()}")
|
||||
|
||||
# Verify Session
|
||||
logger.info("Verifying session...")
|
||||
verify_response = session.get(URL_VERIFY, allow_redirects=False)
|
||||
|
||||
|
||||
logger.info(f"Verify Response Status: {verify_response.status_code}")
|
||||
|
||||
|
||||
if verify_response.status_code == 200:
|
||||
logger.info("Session verification SUCCESS (200 OK).")
|
||||
touch_success_file()
|
||||
|
||||
|
||||
# Save PHPSESSID to Redis
|
||||
phpsessid = session.cookies.get('PHPSESSID')
|
||||
if phpsessid:
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import contextlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
import redis
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ChatMember
|
||||
from telegram.constants import ChatType
|
||||
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes
|
||||
import redis
|
||||
from playwright.async_api import async_playwright
|
||||
from telegram import ChatMember, InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.constants import ChatType
|
||||
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes
|
||||
|
||||
# Logger
|
||||
logging.basicConfig(
|
||||
@@ -221,21 +222,21 @@ def is_whitelisted(user_id: int) -> bool:
|
||||
"""Check if user is allowed to use the bot."""
|
||||
if user_id == ADMIN_ID:
|
||||
return True
|
||||
|
||||
|
||||
enabled = redis_client.get(KEY_WHITELIST_ENABLED)
|
||||
if enabled == "0": # Whitelist disabled
|
||||
return True
|
||||
|
||||
|
||||
return redis_client.sismember(KEY_WHITELIST, str(user_id))
|
||||
|
||||
async def is_group_admin(update: Update, context: ContextTypes.DEFAULT_TYPE) -> bool:
|
||||
"""Check if the user is an administrator in the group."""
|
||||
user = update.effective_user
|
||||
chat = update.effective_chat
|
||||
|
||||
|
||||
if chat.type in [ChatType.PRIVATE, "private"]:
|
||||
return True
|
||||
|
||||
|
||||
try:
|
||||
member = await context.bot.get_chat_member(chat.id, user.id)
|
||||
return member.status in [ChatMember.OWNER, ChatMember.ADMINISTRATOR]
|
||||
@@ -247,7 +248,7 @@ def get_admin_keyboard(user_id: int):
|
||||
"""Generate admin panel keyboard."""
|
||||
whitelist_enabled = redis_client.get(KEY_WHITELIST_ENABLED) != "0"
|
||||
toggle_text = t(user_id, 'toggle_whitelist_disable') if whitelist_enabled else t(user_id, 'toggle_whitelist_enable')
|
||||
|
||||
|
||||
keyboard = [
|
||||
[InlineKeyboardButton(toggle_text, callback_data="toggle_whitelist")],
|
||||
[InlineKeyboardButton(t(user_id, 'view_whitelist'), callback_data="view_whitelist")],
|
||||
@@ -292,10 +293,7 @@ def _parse_calendar_html(table_html: str) -> tuple:
|
||||
raw = re.sub(r'<[^>]+>', ' ', row).strip()
|
||||
raw = re.sub(r'\s+', ' ', raw)
|
||||
m = re.search(r'([А-Яа-яіїєґ\']+\s*:?\s*\d{4})', raw)
|
||||
if m:
|
||||
month_text = m.group(1).replace(' : ', ' ').strip()
|
||||
else:
|
||||
month_text = raw
|
||||
month_text = m.group(1).replace(' : ', ' ').strip() if m else raw
|
||||
elif r_idx == 1:
|
||||
# Day names row
|
||||
for cell in cells:
|
||||
@@ -319,10 +317,7 @@ def _parse_calendar_html(table_html: str) -> tuple:
|
||||
a_tag = a_match.group(0)
|
||||
# Prefer the title attribute (contains full name, not truncated)
|
||||
title_m = re.search(r'title\s*=\s*"([^"]*)"', a_tag)
|
||||
if title_m:
|
||||
et = title_m.group(1).strip()
|
||||
else:
|
||||
et = re.sub(r'<[^>]+>', '', a_match.group(1)).strip()
|
||||
et = title_m.group(1).strip() if title_m else re.sub(r'<[^>]+>', '', a_match.group(1)).strip()
|
||||
if et:
|
||||
events.append(et)
|
||||
|
||||
@@ -363,11 +358,9 @@ async def fetch_diary_data(phpsessid: str) -> dict | None:
|
||||
return None
|
||||
|
||||
# Debug: save HTML for troubleshooting
|
||||
try:
|
||||
with open('/tmp/diary_debug.html', 'w', encoding='utf-8') as f:
|
||||
f.write(table_html)
|
||||
except Exception:
|
||||
pass
|
||||
with contextlib.suppress(Exception), \
|
||||
open('/tmp/diary_debug.html', 'w', encoding='utf-8') as f: # noqa: S108
|
||||
f.write(table_html)
|
||||
|
||||
month_text, days = _parse_calendar_html(table_html)
|
||||
logger.info(f"Diary parsed: month={month_text!r}, days_with_events={sum(1 for d in days.values() if d['events'])}/{len(days)}")
|
||||
@@ -407,7 +400,7 @@ def format_diary_day(data: dict, day_num: int) -> str:
|
||||
|
||||
def format_diary_week(data: dict, today: datetime) -> str:
|
||||
days = data.get('days', {})
|
||||
month_str = _parse_diary_month(data.get('monthFullText', ''))
|
||||
_parse_diary_month(data.get('monthFullText', ''))
|
||||
monday = today - timedelta(days=today.weekday())
|
||||
sunday = monday + timedelta(days=6)
|
||||
lines = [f"📅 <b>Тиждень {monday.day}.{monday.month} – {sunday.day}.{sunday.month}</b>\n"]
|
||||
@@ -457,12 +450,12 @@ async def _get_diary_data(context: ContextTypes.DEFAULT_TYPE) -> dict | None:
|
||||
|
||||
# --- Command Handlers ---
|
||||
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def start(update: Update, _context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle /start command."""
|
||||
user = update.effective_user
|
||||
chat = update.effective_chat
|
||||
logger.info(f"User {user.id} ({user.username}) started the bot in chat {chat.id} ({chat.type}).")
|
||||
|
||||
|
||||
# Check whitelist - MUST be the user executing the command
|
||||
if not is_whitelisted(user.id):
|
||||
await update.message.reply_text(t(user.id, 'access_denied'))
|
||||
@@ -470,21 +463,21 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
|
||||
# Add to subscribers (Chat ID!)
|
||||
redis_client.sadd(KEY_SUBSCRIBERS, chat.id)
|
||||
|
||||
|
||||
msg = t(chat.id, 'welcome', name=user.first_name)
|
||||
|
||||
|
||||
if user.id == ADMIN_ID and chat.type == "private":
|
||||
msg += t(chat.id, 'welcome_admin')
|
||||
await update.message.reply_text(msg, parse_mode='HTML', reply_markup=get_admin_keyboard(user.id))
|
||||
else:
|
||||
await update.message.reply_text(msg, parse_mode='HTML')
|
||||
|
||||
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def help_command(update: Update, _context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle /help command."""
|
||||
user_id = update.effective_user.id
|
||||
chat_id = update.effective_chat.id
|
||||
msg = t(chat_id, 'help_title') + t(chat_id, 'help_commands')
|
||||
|
||||
|
||||
if user_id == ADMIN_ID and update.effective_chat.type == "private":
|
||||
msg += t(chat_id, 'help_admin')
|
||||
await update.message.reply_text(msg, parse_mode='HTML', reply_markup=get_admin_keyboard(user_id))
|
||||
@@ -495,12 +488,12 @@ async def stop_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle /stop command (unsubscribe)."""
|
||||
user = update.effective_user
|
||||
chat = update.effective_chat
|
||||
|
||||
|
||||
# Permission check: Whitelisted user OR Group Admin
|
||||
if not (is_whitelisted(user.id) or await is_group_admin(update, context)):
|
||||
await update.message.reply_text(t(chat.id, 'access_denied')) # Or specific "admin only" message
|
||||
return
|
||||
|
||||
|
||||
redis_client.srem(KEY_SUBSCRIBERS, chat.id)
|
||||
await update.message.reply_text(t(chat.id, 'whitelist_disabled').replace(" whitelist", " notifications").replace("Білий список", "Сповіщення").replace("Белый список", "Уведомления") if chat.id else "Unsubscribed")
|
||||
|
||||
@@ -508,7 +501,7 @@ async def language_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle /language command."""
|
||||
user = update.effective_user
|
||||
chat = update.effective_chat
|
||||
|
||||
|
||||
# Permission check for groups
|
||||
if not (is_whitelisted(user.id) or await is_group_admin(update, context)):
|
||||
return
|
||||
@@ -525,11 +518,11 @@ async def add_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
if admin_id != ADMIN_ID:
|
||||
await update.message.reply_text(t(admin_id, 'admin_only'))
|
||||
return
|
||||
|
||||
|
||||
if not context.args:
|
||||
await update.message.reply_text(t(admin_id, 'usage_adduser'))
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
user_id = int(context.args[0])
|
||||
redis_client.sadd(KEY_WHITELIST, str(user_id))
|
||||
@@ -544,17 +537,17 @@ async def remove_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
if admin_id != ADMIN_ID:
|
||||
await update.message.reply_text(t(admin_id, 'admin_only'))
|
||||
return
|
||||
|
||||
|
||||
if not context.args:
|
||||
await update.message.reply_text(t(admin_id, 'usage_removeuser'))
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
user_id = int(context.args[0])
|
||||
if str(user_id) == str(ADMIN_ID):
|
||||
await update.message.reply_text(t(admin_id, 'cannot_remove_admin'))
|
||||
return
|
||||
|
||||
|
||||
removed = redis_client.srem(KEY_WHITELIST, str(user_id))
|
||||
if removed:
|
||||
await update.message.reply_text(t(admin_id, 'user_removed', user_id=user_id))
|
||||
@@ -564,13 +557,13 @@ async def remove_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
except ValueError:
|
||||
await update.message.reply_text(t(admin_id, 'invalid_user_id'))
|
||||
|
||||
async def clear_history(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def clear_history(update: Update, _context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Clear webinar history (admin only)."""
|
||||
admin_id = update.effective_user.id
|
||||
if admin_id != ADMIN_ID:
|
||||
await update.message.reply_text(t(admin_id, 'admin_only'))
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
redis_client.delete(KEY_WEBINAR_HISTORY)
|
||||
await update.message.reply_text(t(admin_id, 'history_cleared'))
|
||||
@@ -579,9 +572,8 @@ async def clear_history(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
logger.error(f"Failed to clear history: {e}")
|
||||
await update.message.reply_text(t(admin_id, 'history_clear_failed'))
|
||||
|
||||
async def diary_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def diary_command(update: Update, _context: ContextTypes.DEFAULT_TYPE):
|
||||
user = update.effective_user
|
||||
chat = update.effective_chat
|
||||
if not is_whitelisted(user.id):
|
||||
await update.message.reply_text(t(user.id, 'access_denied'))
|
||||
return
|
||||
@@ -596,10 +588,9 @@ async def diary_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
user_id = query.from_user.id
|
||||
await query.answer()
|
||||
|
||||
if user_id != ADMIN_ID:
|
||||
if not is_whitelisted(user_id):
|
||||
await query.edit_message_text("⛔ Доступ заборонено.")
|
||||
return
|
||||
if user_id != ADMIN_ID and not is_whitelisted(user_id):
|
||||
await query.edit_message_text("⛔ Доступ заборонено.")
|
||||
return
|
||||
|
||||
data = query.data
|
||||
if data == "diary_refresh":
|
||||
@@ -653,7 +644,7 @@ async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle admin panel button clicks."""
|
||||
query = update.callback_query
|
||||
user_id = query.from_user.id
|
||||
|
||||
|
||||
if user_id != ADMIN_ID:
|
||||
await query.answer(t(user_id, 'admin_only'), show_alert=True)
|
||||
return
|
||||
@@ -678,11 +669,11 @@ async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
subs = redis_client.smembers(KEY_SUBSCRIBERS)
|
||||
msg = t(user_id, 'subscribers_title') + ("\n".join(subs) if subs else t(user_id, 'empty'))
|
||||
await query.message.reply_text(msg, parse_mode='HTML')
|
||||
|
||||
|
||||
elif data == "force_check":
|
||||
await query.message.reply_text(t(user_id, 'force_check_running'))
|
||||
result = await check_webinars_job(context)
|
||||
|
||||
|
||||
if result is None:
|
||||
await query.message.reply_text(t(user_id, 'check_failed'))
|
||||
elif result == 0:
|
||||
@@ -690,12 +681,12 @@ async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
else:
|
||||
await query.message.reply_text(t(user_id, 'check_completed', count=result))
|
||||
|
||||
async def language_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def language_callback(update: Update, _context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle language selection button clicks."""
|
||||
query = update.callback_query
|
||||
user_id = query.from_user.id
|
||||
data = query.data
|
||||
|
||||
|
||||
if data.startswith("lang_"):
|
||||
lang = data.split("_")[1]
|
||||
set_user_language(user_id, lang)
|
||||
@@ -733,12 +724,12 @@ def store_webinars(webinar_keys: list):
|
||||
|
||||
async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Background job to check for webinars using Async Playwright.
|
||||
|
||||
|
||||
Returns:
|
||||
int: Number of webinars found, or None if check failed
|
||||
"""
|
||||
logger.info("Running webinar check...")
|
||||
|
||||
|
||||
phpsessid = redis_client.get(KEY_PHPSESSID)
|
||||
if not phpsessid:
|
||||
logger.warning("PHPSESSID missing. Skipping check.")
|
||||
@@ -753,16 +744,16 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
|
||||
|
||||
current_webinars = [] # List of dicts with name, url, and formatted text
|
||||
content = ""
|
||||
|
||||
|
||||
try:
|
||||
async with async_playwright() as p:
|
||||
# Connect to remote Playwright service
|
||||
browser = await p.chromium.connect(PLAYWRIGHT_WS)
|
||||
|
||||
|
||||
try:
|
||||
# Create browser context with user agent
|
||||
context_browser = await browser.new_context(user_agent=USER_AGENT)
|
||||
|
||||
|
||||
# Add PHPSESSID cookie
|
||||
await context_browser.add_cookies([{
|
||||
'name': 'PHPSESSID',
|
||||
@@ -770,43 +761,43 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
|
||||
'domain': 'edu.edu.vn.ua',
|
||||
'path': '/'
|
||||
}])
|
||||
|
||||
|
||||
# Create new page
|
||||
page = await context_browser.new_page()
|
||||
|
||||
|
||||
try:
|
||||
# Navigate to webinar page
|
||||
await page.goto(WEBINAR_URL, wait_until='domcontentloaded')
|
||||
|
||||
|
||||
# Wait for the table to load
|
||||
await page.wait_for_selector('#meetings table', timeout=10000)
|
||||
await page.wait_for_timeout(2000)
|
||||
|
||||
|
||||
# Get page content
|
||||
content = await page.content()
|
||||
|
||||
|
||||
# Check if "no webinar" message is present
|
||||
if "Жодного онлайн уроку зараз" not in content:
|
||||
logger.info("!!! WEBINAR FOUND !!!")
|
||||
|
||||
|
||||
# Extract webinar details from table rows
|
||||
rows = page.locator('#meetings table tbody tr')
|
||||
count = await rows.count()
|
||||
|
||||
|
||||
for i in range(count):
|
||||
row = rows.nth(i)
|
||||
text = await row.inner_text()
|
||||
|
||||
|
||||
if "Жодного онлайн уроку зараз" not in text:
|
||||
# Extract name (topic) from first column
|
||||
name_elem = row.locator('td').nth(0)
|
||||
name = await name_elem.inner_text()
|
||||
name = name.strip()
|
||||
|
||||
|
||||
# Extract join URL from fourth column
|
||||
url_elem = row.locator('td').nth(3).locator('a[href*="/webinar/join/"]').first
|
||||
url = await url_elem.get_attribute('href')
|
||||
|
||||
|
||||
if name and url:
|
||||
current_webinars.append({
|
||||
'name': name,
|
||||
@@ -816,28 +807,26 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
|
||||
logger.info(f"Found webinar: {name} -> {url}")
|
||||
else:
|
||||
logger.info("No webinars found (expected message present)")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error checking page: {e}. Saving content for debug.")
|
||||
# If page content is available, save it on error
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
if page and not content:
|
||||
content = await page.content()
|
||||
except Exception:
|
||||
pass # Ignore error during content retrieval on check error
|
||||
|
||||
|
||||
return None
|
||||
finally:
|
||||
await page.close()
|
||||
await context_browser.close()
|
||||
|
||||
|
||||
finally:
|
||||
await browser.close()
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Playwright error: {e}")
|
||||
return None
|
||||
|
||||
|
||||
# --- DEBUG LOGGING (Saving last response content) ---
|
||||
if not current_webinars and content: #if no webinars found, save the page content
|
||||
try:
|
||||
@@ -853,29 +842,29 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
|
||||
# Get stored webinar history
|
||||
stored_keys = get_stored_webinars()
|
||||
logger.info(f"Stored webinar keys: {stored_keys}")
|
||||
|
||||
|
||||
# Find new webinars (not in history)
|
||||
new_webinars = []
|
||||
current_keys = []
|
||||
|
||||
|
||||
for webinar in current_webinars:
|
||||
key = get_webinar_key(webinar['url'])
|
||||
current_keys.append(key)
|
||||
|
||||
|
||||
if key not in stored_keys:
|
||||
new_webinars.append(webinar)
|
||||
logger.info(f"NEW webinar detected: {webinar['name']}")
|
||||
|
||||
|
||||
# Update stored history with current webinars
|
||||
# Merge old and new, keeping only last 5
|
||||
updated_keys = stored_keys + [k for k in current_keys if k not in stored_keys]
|
||||
store_webinars(updated_keys)
|
||||
|
||||
|
||||
# Notify subscribers ONLY about NEW webinars
|
||||
if new_webinars:
|
||||
subscribers = redis_client.smembers(KEY_SUBSCRIBERS)
|
||||
logger.info(f"Sending notification about {len(new_webinars)} new webinar(s) to {len(subscribers)} subscriber(s)")
|
||||
|
||||
|
||||
for sub_id in subscribers:
|
||||
try:
|
||||
# Build message in user's language
|
||||
@@ -885,14 +874,14 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
|
||||
for w in new_webinars
|
||||
])
|
||||
message = t(int(sub_id), 'webinar_found') + webinar_items
|
||||
|
||||
|
||||
await context.bot.send_message(chat_id=sub_id, text=message, parse_mode='HTML')
|
||||
logger.info(f"Notification sent to {sub_id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send to {sub_id}: {e}")
|
||||
else:
|
||||
logger.info(f"Found {len(current_webinars)} webinar(s), but all are already known")
|
||||
|
||||
|
||||
return len(current_webinars)
|
||||
|
||||
# --- Main ---
|
||||
@@ -921,7 +910,7 @@ def main():
|
||||
app.add_handler(CommandHandler("removeuser", remove_user))
|
||||
app.add_handler(CommandHandler("clearhistory", clear_history))
|
||||
app.add_handler(CommandHandler("diary", diary_command))
|
||||
|
||||
|
||||
# Callback handlers - diary first, then language selection, then admin panel
|
||||
app.add_handler(CallbackQueryHandler(diary_callback, pattern="^diary_"))
|
||||
app.add_handler(CallbackQueryHandler(language_callback, pattern="^lang_"))
|
||||
@@ -935,4 +924,4 @@ def main():
|
||||
app.run_polling()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
@@ -3,7 +3,7 @@ import re
|
||||
from io import BytesIO
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup as bs
|
||||
from bs4 import BeautifulSoup as BS
|
||||
from pyrogram import Client, filters
|
||||
from pyrogram.errors import RPCError
|
||||
from pyrogram.types import InputMediaPhoto, Message
|
||||
@@ -21,8 +21,8 @@ async def search_icon(_, message: Message):
|
||||
url = f'https://www.flaticon.com/search?word={search_query}'
|
||||
|
||||
try:
|
||||
html_content = requests.get(url).text
|
||||
soup = bs(html_content, 'html.parser')
|
||||
html_content = requests.get(url, timeout=10).text
|
||||
soup = BS(html_content, 'html.parser')
|
||||
results = soup.find_all(
|
||||
'img',
|
||||
src=re.compile(r'https://cdn-icons-png.flaticon.com/128/[0-9]+/[0-9]+.png'),
|
||||
@@ -68,7 +68,7 @@ async def freepik_search(client: Client, message: Message):
|
||||
|
||||
try:
|
||||
url = f'https://www.freepik.com/api/regular/search?locale=en&term={match}'
|
||||
json_content = requests.get(url).json()
|
||||
json_content = requests.get(url, timeout=10).json()
|
||||
results = []
|
||||
for i in json_content['items']:
|
||||
results.append(i['preview']['url'])
|
||||
@@ -81,7 +81,7 @@ async def freepik_search(client: Client, message: Message):
|
||||
|
||||
media_group = []
|
||||
for img_url in img_urls:
|
||||
icon = requests.get(img_url)
|
||||
icon = requests.get(img_url, timeout=10)
|
||||
if icon.status_code == 200:
|
||||
media_group.append(InputMediaPhoto(media=BytesIO(icon.content)))
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ async def imgur(_, message: Message):
|
||||
url = 'https://api.imgur.com/3/image'
|
||||
headers = {'Authorization': 'Client-ID a10ad04550b0648'}
|
||||
# Upload image to Imgur and get URL
|
||||
response = requests.post(url, headers=headers, data={'image': base64_data})
|
||||
response = requests.post(url, headers=headers, data={'image': base64_data}, timeout=10)
|
||||
result = response.json()
|
||||
await msg.edit_text(result['data']['link'])
|
||||
elif message.reply_to_message and message.reply_to_message.animation:
|
||||
@@ -35,7 +35,7 @@ async def imgur(_, message: Message):
|
||||
url = 'https://api.imgur.com/3/image'
|
||||
headers = {'Authorization': 'Client-ID a10ad04550b0648'}
|
||||
# Upload animation to Imgur and get URL
|
||||
response = requests.post(url, headers=headers, data={'image': base64_data})
|
||||
response = requests.post(url, headers=headers, data={'image': base64_data}, timeout=10)
|
||||
result = response.json()
|
||||
await msg.edit_text(result['data']['link'])
|
||||
else:
|
||||
|
||||
@@ -30,7 +30,7 @@ def resize_image(image_bytes):
|
||||
|
||||
async def download_image(url):
|
||||
try:
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
img_bytes = BytesIO(response.content)
|
||||
return resize_image(img_bytes)
|
||||
@@ -52,7 +52,7 @@ async def pinterest_search(client: Client, message: Message):
|
||||
status_message = await message.edit('Searching for images...', parse_mode=enums.ParseMode.MARKDOWN)
|
||||
|
||||
url = f'{API_URL}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
|
||||
@@ -65,7 +65,7 @@ def upload_image(photo_path):
|
||||
"""Uploads an image to tmpfiles.org and returns the direct download URL."""
|
||||
try:
|
||||
with open(photo_path, 'rb') as image_file:
|
||||
response = requests.post('https://tmpfiles.org/api/v1/upload', files={'file': image_file})
|
||||
response = requests.post('https://tmpfiles.org/api/v1/upload', files={'file': image_file}, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
url = data['data']['url']
|
||||
|
||||
@@ -51,7 +51,7 @@ async def unsplash(client: Client, message: Message):
|
||||
for ia in range(len(images), count):
|
||||
img = data['results'][ia]['urls']['raw']
|
||||
if img.startswith('https://images.unsplash.com/photo'):
|
||||
image_content = requests.get(img).content
|
||||
image_content = requests.get(img, timeout=10).content
|
||||
with open(f'{unsplash_dir}/unsplash_{ia}.jpg', 'wb') as f:
|
||||
f.write(image_content)
|
||||
imgr = f'{unsplash_dir}/unsplash_{ia}.jpg'
|
||||
@@ -77,7 +77,6 @@ async def unsplash(client: Client, message: Message):
|
||||
|
||||
|
||||
modules_help['unsplash'] = {
|
||||
'unsplash': '[keyword]*',
|
||||
'unsplash': '[keyword]* [number of results you want]*\n'
|
||||
'Makes a request to <code>unsplash.com</code> and sends the image with the keyword you provided.\n\n'
|
||||
'<b>Note:</b>\n1. The number of results you can get is limited to 10.\n'
|
||||
|
||||
@@ -29,7 +29,7 @@ def resize_image(image_bytes):
|
||||
|
||||
async def download_image(url):
|
||||
try:
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
img_bytes = BytesIO(response.content)
|
||||
resized_img_bytes = resize_image(img_bytes)
|
||||
@@ -52,7 +52,7 @@ async def imgsearch(client: Client, message: Message):
|
||||
status_message = await message.edit('Searching for images...', parse_mode=enums.ParseMode.MARKDOWN)
|
||||
|
||||
url = f'{API_URL}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
|
||||
+2
-2
@@ -109,7 +109,7 @@ def load_missing_modules():
|
||||
module_path = f'{custom_modules_path}/{module_name}.py'
|
||||
if not os.path.exists(module_path) and module_name in modules_dict:
|
||||
url = f'https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{modules_dict[module_name]}.py'
|
||||
resp = requests.get(url)
|
||||
resp = requests.get(url, timeout=10)
|
||||
if resp.ok:
|
||||
with open(module_path, 'wb') as f:
|
||||
f.write(resp.content)
|
||||
@@ -131,7 +131,7 @@ async def main():
|
||||
except sqlite3.OperationalError as e:
|
||||
if str(e) == 'database is locked' and os.name == 'posix':
|
||||
logging.warning('Session file is locked. Trying to kill blocking process...')
|
||||
subprocess.run(['fuser', '-k', 'my_account.session'], check=True)
|
||||
subprocess.run(['fuser', '-k', 'my_account.session'], check=True) # noqa: S607
|
||||
restart()
|
||||
raise
|
||||
except (errors.NotAcceptable, errors.Unauthorized) as e:
|
||||
|
||||
@@ -29,8 +29,8 @@ class Chat(Object):
|
||||
self,
|
||||
*,
|
||||
client: 'Client' = None,
|
||||
id: id,
|
||||
type: type,
|
||||
id: id, # noqa: A002
|
||||
type: type, # noqa: A002
|
||||
is_verified: bool = None,
|
||||
is_restricted: bool = None,
|
||||
is_creator: bool = None,
|
||||
|
||||
@@ -8,7 +8,7 @@ from utils.scripts import format_exc, import_library
|
||||
|
||||
genai = import_library('google.generativeai', 'google-generativeai')
|
||||
|
||||
from utils.config import gemini_key
|
||||
from utils.config import gemini_key # noqa: E402
|
||||
|
||||
genai.configure(api_key=gemini_key)
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ async def amogus(client: Client, message: Message):
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
)
|
||||
|
||||
clr = randint(1, 12)
|
||||
clr = randint(1, 12) # noqa: S311
|
||||
|
||||
url = 'https://raw.githubusercontent.com/The-MoonTg-project/AmongUs/master/'
|
||||
font = ImageFont.truetype(BytesIO(get(url + 'bold.ttf').content), 60)
|
||||
imposter = Image.open(BytesIO(get(f'{url}{clr}.png').content))
|
||||
font = ImageFont.truetype(BytesIO(get(url + 'bold.ttf', timeout=10).content), 60)
|
||||
imposter = Image.open(BytesIO(get(f'{url}{clr}.png', timeout=10).content))
|
||||
|
||||
text_ = '\n'.join(['\n'.join(wrap(part, 30)) for part in text.split('\n')])
|
||||
bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).multiline_textbbox((0, 0), text_, font, stroke_width=2)
|
||||
|
||||
+13
-10
@@ -10,18 +10,19 @@ from PIL import Image, ImageDraw, ImageFont
|
||||
from pyrogram import Client, filters
|
||||
from pyrogram.types import Message
|
||||
from utils.misc import modules_help, prefix
|
||||
from utils.scripts import ReplyCheck, edit_or_reply
|
||||
from utils.scripts import edit_or_reply
|
||||
from utils.scripts import reply_check as ReplyCheck
|
||||
|
||||
|
||||
async def amongus_gen(text: str, clr: int) -> str:
|
||||
url = 'https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/Amongus/'
|
||||
font = ImageFont.truetype(
|
||||
BytesIO(
|
||||
requests.get('https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/fonts/bold.ttf').content
|
||||
requests.get('https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/fonts/bold.ttf', timeout=10).content
|
||||
),
|
||||
60,
|
||||
)
|
||||
imposter = Image.open(BytesIO(requests.get(f'{url}{clr}.png').content))
|
||||
imposter = Image.open(BytesIO(requests.get(f'{url}{clr}.png', timeout=10).content))
|
||||
text_ = '\n'.join('\n'.join(wrap(part, 30)) for part in text.split('\n'))
|
||||
bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).multiline_textbbox((0, 0), text_, font, stroke_width=2)
|
||||
w, h = bbox[2], bbox[3]
|
||||
@@ -42,10 +43,12 @@ async def amongus_gen(text: str, clr: int) -> str:
|
||||
|
||||
async def get_imposter_img(text: str) -> BytesIO:
|
||||
background = requests.get(
|
||||
f'https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/imposter/impostor{randint(1, 22)}.png'
|
||||
f'https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/imposter/impostor{randint(1, 22)}.png', # noqa: S311
|
||||
timeout=10,
|
||||
).content
|
||||
font = requests.get(
|
||||
'https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/fonts/roboto_regular.ttf'
|
||||
'https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/fonts/roboto_regular.ttf',
|
||||
timeout=10,
|
||||
).content
|
||||
font = BytesIO(font)
|
||||
font = ImageFont.truetype(font, 30)
|
||||
@@ -79,9 +82,9 @@ async def amongus_cmd(client: Client, message: Message):
|
||||
text = text.replace(f'-c{clr}', '')
|
||||
clr = int(clr)
|
||||
if clr > 12 or clr < 1:
|
||||
clr = randint(1, 12)
|
||||
clr = randint(1, 12) # noqa: S311
|
||||
except IndexError:
|
||||
clr = randint(1, 12)
|
||||
clr = randint(1, 12) # noqa: S311
|
||||
|
||||
if not text:
|
||||
if not reply:
|
||||
@@ -100,15 +103,15 @@ async def amongus_cmd(client: Client, message: Message):
|
||||
|
||||
@Client.on_message(filters.command('imposter', prefix) & filters.me)
|
||||
async def imposter_cmd(client: Client, message: Message):
|
||||
remain = randint(1, 2)
|
||||
remain = randint(1, 2) # noqa: S311
|
||||
imps = ["wasn't the impostor", 'was the impostor']
|
||||
|
||||
if message.reply_to_message:
|
||||
user = message.reply_to_message.from_user
|
||||
text = f'{user.first_name} {choice(imps)}.'
|
||||
text = f'{user.first_name} {choice(imps)}.' # noqa: S311
|
||||
else:
|
||||
args = message.text.split()[1:]
|
||||
text = ' '.join(args) if args else f'{message.from_user.first_name} {choice(imps)}.'
|
||||
text = ' '.join(args) if args else f'{message.from_user.first_name} {choice(imps)}.' # noqa: S311
|
||||
|
||||
text += f'\n{remain} impostor(s) remain.'
|
||||
imposter_file = await get_imposter_img(text)
|
||||
|
||||
@@ -187,7 +187,7 @@ async def timer_blankx(_, message: Message):
|
||||
)
|
||||
j = 10
|
||||
k = j
|
||||
for j in range(j):
|
||||
for _j in range(j):
|
||||
await message.edit_text(txt + str(k), parse_mode=enums.ParseMode.HTML)
|
||||
k = k + 10
|
||||
await asyncio.sleep(1)
|
||||
|
||||
@@ -46,7 +46,7 @@ async def anime_search(client: Client, message: Message):
|
||||
averageScore = result['averageScore']
|
||||
try:
|
||||
coverImage_url = result['imageUrl']
|
||||
coverImage = requests.get(url=coverImage_url).content
|
||||
coverImage = requests.get(url=coverImage_url, timeout=10).content
|
||||
async with aiofiles.open('coverImage.jpg', mode='wb') as f:
|
||||
await f.write(coverImage)
|
||||
|
||||
@@ -112,7 +112,7 @@ async def manga_search(client: Client, message: Message):
|
||||
averageScore = result['averageScore']
|
||||
try:
|
||||
coverImage_url = result['imageUrl']
|
||||
coverImage = requests.get(url=coverImage_url).content
|
||||
coverImage = requests.get(url=coverImage_url, timeout=10).content
|
||||
async with aiofiles.open('coverImage.jpg', mode='wb') as f:
|
||||
await f.write(coverImage)
|
||||
|
||||
@@ -177,7 +177,7 @@ async def character(client: Client, message: Message):
|
||||
|
||||
try:
|
||||
coverImage_url = result['image']['large']
|
||||
coverImage = requests.get(url=coverImage_url).content
|
||||
coverImage = requests.get(url=coverImage_url, timeout=10).content
|
||||
async with aiofiles.open('coverImage.jpg', mode='wb') as f:
|
||||
await f.write(coverImage)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ from utils.scripts import format_exc
|
||||
|
||||
|
||||
def get_neko_media(query):
|
||||
return requests.get(f'https://nekos.life/api/v2/img/{query}').json()['url']
|
||||
return requests.get(f'https://nekos.life/api/v2/img/{query}', timeout=10).json()['url']
|
||||
|
||||
|
||||
@Client.on_message(filters.command('neko', prefix) & filters.me)
|
||||
|
||||
@@ -25,7 +25,7 @@ async def aniquotes_handler(client: Client, message: Message):
|
||||
result = await client.get_inline_bot_results('@quotafbot', query)
|
||||
return await message.reply_inline_bot_result(
|
||||
query_id=result.query_id,
|
||||
result_id=result.results[randint(1, 2)].id,
|
||||
result_id=result.results[randint(1, 2)].id, # noqa: S311
|
||||
reply_to_message_id=(message.reply_to_message.id if message.reply_to_message else None),
|
||||
)
|
||||
except Exception as e:
|
||||
|
||||
@@ -11,11 +11,10 @@ async def calc(_, message: Message):
|
||||
return
|
||||
args = ' '.join(message.command[1:])
|
||||
try:
|
||||
result = str(eval(args))
|
||||
result = str(eval(args)) # noqa: S307
|
||||
|
||||
if len(result) > 4096:
|
||||
i = 0
|
||||
for x in range(0, len(result), 4096):
|
||||
for i, x in enumerate(range(0, len(result), 4096)):
|
||||
if i == 0:
|
||||
await message.edit(
|
||||
f'<i>{args}</i><b>=</b><code>{result[x : x + 4000]}</code>',
|
||||
@@ -23,7 +22,6 @@ async def calc(_, message: Message):
|
||||
)
|
||||
else:
|
||||
await message.reply(f'<code>{result[x : x + 4096]}</code>', parse_mode='HTML')
|
||||
i += 1
|
||||
await asyncio.sleep(0.18)
|
||||
else:
|
||||
await message.edit(f'<i>{args}</i><b>=</b><code>{result}</code>', parse_mode='HTML')
|
||||
|
||||
@@ -7,7 +7,7 @@ from utils.scripts import format_exc, import_library
|
||||
|
||||
clarifai = import_library('clarifai')
|
||||
|
||||
from clarifai.client.model import Model
|
||||
from clarifai.client.model import Model # noqa: E402
|
||||
|
||||
|
||||
@Client.on_message(filters.command('cdxl', prefix) & filters.me)
|
||||
|
||||
@@ -5,17 +5,17 @@ from utils.scripts import import_library
|
||||
|
||||
cohere = import_library('cohere')
|
||||
|
||||
import cohere
|
||||
import cohere # noqa: F811
|
||||
|
||||
co = cohere.Client(cohere_key)
|
||||
|
||||
from pyrogram import Client, enums, filters
|
||||
from pyrogram.errors import MessageTooLong
|
||||
from pyrogram.types import Message
|
||||
from utils.db import db
|
||||
from utils.misc import modules_help, prefix
|
||||
from utils.rentry import paste as rentry_paste
|
||||
from utils.scripts import format_exc
|
||||
from pyrogram import Client, enums, filters # noqa: E402
|
||||
from pyrogram.errors import MessageTooLong # noqa: E402
|
||||
from pyrogram.types import Message # noqa: E402
|
||||
from utils.db import db # noqa: E402
|
||||
from utils.misc import modules_help, prefix # noqa: E402
|
||||
from utils.rentry import paste as rentry_paste # noqa: E402
|
||||
from utils.scripts import format_exc # noqa: E402
|
||||
|
||||
|
||||
@Client.on_message(filters.command('cohere', prefix) & filters.me)
|
||||
|
||||
@@ -9,22 +9,22 @@ from utils.scripts import import_library
|
||||
requests = import_library('requests')
|
||||
PIL = import_library('PIL', 'pillow')
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from PIL import Image, ImageDraw, ImageFont # noqa: E402
|
||||
|
||||
|
||||
@Client.on_message(filters.command(['dem'], prefix) & filters.me)
|
||||
async def demotivator(client: Client, message: Message):
|
||||
await message.edit('<code>Process of demotivation...</code>', parse_mode=enums.ParseMode.HTML)
|
||||
font = requests.get('https://github.com/The-MoonTg-project/files/blob/main/Times%20New%20Roman.ttf?raw=true')
|
||||
font = requests.get('https://github.com/The-MoonTg-project/files/blob/main/Times%20New%20Roman.ttf?raw=true', timeout=10)
|
||||
f = font.content
|
||||
template_dem = requests.get('https://raw.githubusercontent.com/files/main/demotivator.png')
|
||||
template_dem = requests.get('https://raw.githubusercontent.com/files/main/demotivator.png', timeout=10)
|
||||
if message.reply_to_message:
|
||||
words = ['random', 'text', 'typing', 'fuck']
|
||||
if message.reply_to_message.photo:
|
||||
donwloads = await client.download_media(message.reply_to_message.photo.file_id)
|
||||
photo = Image.open(f'{donwloads}')
|
||||
resize_photo = photo.resize((469, 312))
|
||||
text = message.text.split(' ', maxsplit=1)[1] if len(message.text.split()) > 1 else random.choice(words)
|
||||
text = message.text.split(' ', maxsplit=1)[1] if len(message.text.split()) > 1 else random.choice(words) # noqa: S311
|
||||
im = Image.open(BytesIO(template_dem.content))
|
||||
im.paste(resize_photo, (65, 48))
|
||||
text_font = ImageFont.truetype(BytesIO(f), 22)
|
||||
@@ -38,7 +38,7 @@ async def demotivator(client: Client, message: Message):
|
||||
donwloads = await client.download_media(message.reply_to_message.sticker.file_id)
|
||||
photo = Image.open(f'{donwloads}')
|
||||
resize_photo = photo.resize((469, 312))
|
||||
text = message.text.split(' ', maxsplit=1)[1] if len(message.text.split()) > 1 else random.choice(words)
|
||||
text = message.text.split(' ', maxsplit=1)[1] if len(message.text.split()) > 1 else random.choice(words) # noqa: S311
|
||||
im = Image.open(BytesIO(template_dem.content))
|
||||
im.paste(resize_photo, (65, 48))
|
||||
text_font = ImageFont.truetype(BytesIO(f), 22)
|
||||
|
||||
@@ -6,8 +6,8 @@ from utils.misc import modules_help, prefix
|
||||
from utils.scripts import import_library
|
||||
|
||||
lottie = import_library('lottie')
|
||||
from lottie.exporters import exporters
|
||||
from lottie.importers import importers
|
||||
from lottie.exporters import exporters # noqa: E402
|
||||
from lottie.importers import importers # noqa: E402
|
||||
|
||||
|
||||
@Client.on_message(filters.command('destroy', prefix) & filters.me)
|
||||
|
||||
@@ -22,7 +22,7 @@ from utils.misc import modules_help, prefix
|
||||
def subprocess_run(cmd):
|
||||
reply = ''
|
||||
cmd_args = cmd.split()
|
||||
subproc = Popen(
|
||||
subproc = Popen( # noqa: S603
|
||||
cmd_args,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
@@ -93,7 +93,7 @@ def gdrive(url: str) -> str:
|
||||
elif link.find('uc?id=') != -1:
|
||||
file_id = link.split('uc?id=')[1].strip()
|
||||
url = f'{drive}/uc?export=download&id={file_id}'
|
||||
download = requests.get(url, stream=True, allow_redirects=False)
|
||||
download = requests.get(url, stream=True, allow_redirects=False, timeout=10)
|
||||
cookies = download.cookies
|
||||
try:
|
||||
# In case of small file size, Google downloads directly
|
||||
@@ -112,7 +112,7 @@ def gdrive(url: str) -> str:
|
||||
if page_element is not None:
|
||||
export = drive + page_element.get('href')
|
||||
name = page.find('span', {'class': 'uc-name-size'}).text
|
||||
response = requests.get(export, stream=True, allow_redirects=False, cookies=cookies)
|
||||
response = requests.get(export, stream=True, allow_redirects=False, cookies=cookies, timeout=10)
|
||||
dl_url = response.headers['location']
|
||||
if 'accounts.google.com' in dl_url:
|
||||
name = page.find('span', {'class': 'uc-name-size'}).text
|
||||
@@ -138,7 +138,7 @@ def yandex_disk(url: str) -> str:
|
||||
return reply
|
||||
api = 'https://cloud-api.yandex.net/v1/disk/public/resources/download?public_key={}'
|
||||
try:
|
||||
dl_url = requests.get(api.format(link)).json()['href']
|
||||
dl_url = requests.get(api.format(link), timeout=10).json()['href']
|
||||
name = dl_url.split('filename=')[1].split('&disposition')[0]
|
||||
reply += f'[{name}]({dl_url})\n'
|
||||
except KeyError:
|
||||
@@ -181,7 +181,7 @@ def mediafire(url: str) -> str:
|
||||
reply = '`No MediaFire links found`\n'
|
||||
return reply
|
||||
reply = ''
|
||||
page = BeautifulSoup(requests.get(link).content, 'lxml')
|
||||
page = BeautifulSoup(requests.get(link, timeout=10).content, 'lxml')
|
||||
info = page.find('a', {'aria-label': 'Download file'})
|
||||
dl_url = info.get('href')
|
||||
size = re.findall(r'\(.*\)', info.text)[0]
|
||||
@@ -201,7 +201,7 @@ def sourceforge(url: str) -> str:
|
||||
reply = f'Mirrors for __{file_path.split("/")[-1]}__\n'
|
||||
project = re.findall(r'projects?/(.*?)/files', link)[0]
|
||||
mirrors = f'https://sourceforge.net/settings/mirror_choices?projectname={project}&filename={file_path}'
|
||||
page = BeautifulSoup(requests.get(mirrors).content, 'html.parser')
|
||||
page = BeautifulSoup(requests.get(mirrors, timeout=10).content, 'html.parser')
|
||||
info = page.find('ul', {'id': 'mirrorList'}).findAll('li')
|
||||
for mirror in info[1:]:
|
||||
name = re.findall(r'\((.*)\)', mirror.text.strip())[0]
|
||||
@@ -218,7 +218,7 @@ def osdn(url: str) -> str:
|
||||
except IndexError:
|
||||
reply = '`No OSDN links found`\n'
|
||||
return reply
|
||||
page = BeautifulSoup(requests.get(link, allow_redirects=True).content, 'lxml')
|
||||
page = BeautifulSoup(requests.get(link, allow_redirects=True, timeout=10).content, 'lxml')
|
||||
info = page.find('a', {'class': 'mirror_link'})
|
||||
link = urllib.parse.unquote(osdn_link + info['href'])
|
||||
reply = f'Mirrors for __{link.split("/")[-1]}__\n'
|
||||
@@ -285,13 +285,14 @@ def useragent():
|
||||
"""
|
||||
useragents = BeautifulSoup(
|
||||
requests.get(
|
||||
'https://developers.whatismybrowser.com/useragents/explore/operating_system_name/android/'
|
||||
'https://developers.whatismybrowser.com/useragents/explore/operating_system_name/android/',
|
||||
timeout=10,
|
||||
).content,
|
||||
'lxml',
|
||||
).findAll('td', {'class': 'useragent'})
|
||||
if not useragents:
|
||||
return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
|
||||
user_agent = choice(useragents)
|
||||
user_agent = choice(useragents) # noqa: S311
|
||||
return user_agent.text
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from utils.misc import modules_help, prefix
|
||||
@Client.on_message(filters.command('durov', prefix) & filters.me)
|
||||
async def durov(_, message: Message):
|
||||
await message.edit(
|
||||
f'<b>Random post from channel: https://t.me/durov/{randint(21, 36500)}</b>',
|
||||
f'<b>Random post from channel: https://t.me/durov/{randint(21, 36500)}</b>', # noqa: S311
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
)
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ async def download_sticker(url, filename):
|
||||
@Client.on_message(filters.command(['f'], prefix) & filters.me)
|
||||
async def random_stiker(client: Client, message: Message):
|
||||
await message.delete()
|
||||
random = randint(1, 63)
|
||||
random = randint(1, 63) # noqa: S311
|
||||
index = f'00{random}' if random < 10 else f'0{random}'
|
||||
sticker = f'https://www.chpic.su/_data/stickers/f/FforRespect/FforRespect_{index}.webp'
|
||||
await download_sticker(sticker, 'f.webp')
|
||||
|
||||
@@ -32,7 +32,7 @@ async def fakeactions_handler(client: Client, message: Message):
|
||||
sec = int(message.command[1])
|
||||
if sec > 60:
|
||||
sec = 60
|
||||
except:
|
||||
except Exception:
|
||||
sec = None
|
||||
await message.delete()
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from utils.scripts import format_exc, progress
|
||||
def schellwithflux(args):
|
||||
API_URL = 'https://randydev-ryuzaki-api.hf.space/api/v1/akeno/fluxai'
|
||||
payload = {'user_id': 1191668125, 'args': args} # Please don't edit here
|
||||
response = requests.post(API_URL, json=payload)
|
||||
response = requests.post(API_URL, json=payload, timeout=10)
|
||||
if response.status_code != 200:
|
||||
print(f'Error status {response.status_code}')
|
||||
return None
|
||||
|
||||
@@ -50,7 +50,7 @@ async def phase2(message: Message):
|
||||
|
||||
format_heart = joined_heart.replace(R, '{}')
|
||||
for _ in range(5):
|
||||
heart = format_heart.format(*random.choices(ALL, k=heartlet_len))
|
||||
heart = format_heart.format(*random.choices(ALL, k=heartlet_len)) # noqa: S311
|
||||
await _wrap_edit(message, heart)
|
||||
await asyncio.sleep(SLEEP)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ async def kokodrilo_explodando(_, message: Message):
|
||||
amount = int(message.command[1])
|
||||
for _ in range(amount):
|
||||
await message.edit('🐊')
|
||||
await asyncio.sleep(random.uniform(1, 2.5))
|
||||
await asyncio.sleep(random.uniform(1, 2.5)) # noqa: S311
|
||||
await message.edit('💥')
|
||||
await asyncio.sleep(1.8)
|
||||
|
||||
|
||||
+10
-10
@@ -51,7 +51,7 @@ async def get_mod_hash(_, message: Message):
|
||||
if len(message.command) == 1:
|
||||
return
|
||||
url = message.command[1].lower()
|
||||
resp = requests.get(url)
|
||||
resp = requests.get(url, timeout=10)
|
||||
if not resp.ok:
|
||||
await message.edit(f'<b>Troubleshooting with downloading module <code>{url}</code></b>')
|
||||
return
|
||||
@@ -86,7 +86,7 @@ async def loadmod(_, message: Message):
|
||||
try:
|
||||
f = requests.get(
|
||||
'https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/full.txt'
|
||||
).text
|
||||
, timeout=10).text
|
||||
except Exception:
|
||||
return await message.edit('Failed to fetch custom modules list')
|
||||
modules_dict = {line.split('/')[-1].split()[0]: line.strip() for line in f.splitlines()}
|
||||
@@ -98,8 +98,8 @@ async def loadmod(_, message: Message):
|
||||
else:
|
||||
modules_hashes = requests.get(
|
||||
'https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt'
|
||||
).text
|
||||
resp = requests.get(url)
|
||||
, timeout=10).text
|
||||
resp = requests.get(url, timeout=10)
|
||||
|
||||
if not resp.ok:
|
||||
await message.edit(
|
||||
@@ -118,7 +118,7 @@ async def loadmod(_, message: Message):
|
||||
|
||||
module_name = url.split('/')[-1].split('.')[0]
|
||||
|
||||
resp = requests.get(url)
|
||||
resp = requests.get(url, timeout=10)
|
||||
if not resp.ok:
|
||||
await message.edit(f'<b>Module <code>{module_name}</code> is not found</b>')
|
||||
return
|
||||
@@ -137,7 +137,7 @@ async def loadmod(_, message: Message):
|
||||
|
||||
modules_hashes = requests.get(
|
||||
'https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt'
|
||||
).text
|
||||
, timeout=10).text
|
||||
|
||||
if hashlib.sha256(content).hexdigest() not in modules_hashes:
|
||||
os.remove(file_name)
|
||||
@@ -214,7 +214,7 @@ async def load_all_mods(_, message: Message):
|
||||
os.mkdir(f'{BASE_PATH}/modules/custom_modules')
|
||||
|
||||
try:
|
||||
f = requests.get('https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/full.txt').text
|
||||
f = requests.get('https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/full.txt', timeout=10).text
|
||||
except Exception:
|
||||
return await message.edit('Failed to fetch custom modules list')
|
||||
modules_list = f.splitlines()
|
||||
@@ -222,7 +222,7 @@ async def load_all_mods(_, message: Message):
|
||||
await message.edit('<b>Loading modules...</b>')
|
||||
for module_name in modules_list:
|
||||
url = f'https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{module_name}.py'
|
||||
resp = requests.get(url)
|
||||
resp = requests.get(url, timeout=10)
|
||||
if not resp.ok:
|
||||
continue
|
||||
with open(f'./modules/custom_modules/{module_name.split("/")[1]}.py', 'wb') as f:
|
||||
@@ -281,14 +281,14 @@ async def updateallmods(_, message: Message):
|
||||
if not module_name.endswith('.py'):
|
||||
continue
|
||||
try:
|
||||
f = requests.get('https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/full.txt').text
|
||||
f = requests.get('https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/full.txt', timeout=10).text
|
||||
except Exception:
|
||||
return await message.edit('Failed to fetch custom modules list')
|
||||
modules_dict = {line.split('/')[-1].split()[0]: line.strip() for line in f.splitlines()}
|
||||
if module_name in modules_dict:
|
||||
resp = requests.get(
|
||||
f'https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{modules_dict[module_name]}.py'
|
||||
)
|
||||
, timeout=10)
|
||||
if not resp.ok:
|
||||
modules_installed.remove(module_name)
|
||||
continue
|
||||
|
||||
@@ -23,7 +23,7 @@ from utils.scripts import import_library, prefix, with_reply
|
||||
|
||||
import_library('markitdown')
|
||||
|
||||
from markitdown import MarkItDown
|
||||
from markitdown import MarkItDown # noqa: E402
|
||||
|
||||
|
||||
@Client.on_message(filters.command(['markitdown', 'mkdn'], prefix) & filters.me)
|
||||
|
||||
@@ -7,7 +7,7 @@ from utils.misc import modules_help, prefix
|
||||
from utils.scripts import import_library
|
||||
|
||||
PIL = import_library('PIL', 'pillow')
|
||||
from PIL import Image, ImageOps
|
||||
from PIL import Image, ImageOps # noqa: E402
|
||||
|
||||
|
||||
async def make(client, message, o):
|
||||
|
||||
@@ -139,8 +139,7 @@ async def autofwd_main(client: Client, message: Message):
|
||||
source_chats = db.get('custom.autofwd', 'chatsrc')
|
||||
target_chats = db.get('custom.autofwd', 'chatto')
|
||||
|
||||
if source_chats is not None and chat_id in source_chats:
|
||||
if target_chats is not None:
|
||||
if source_chats is not None and chat_id in source_chats and target_chats is not None:
|
||||
for chat in target_chats:
|
||||
try:
|
||||
await message.copy(chat)
|
||||
|
||||
@@ -133,7 +133,7 @@ async def backupmod(client: Client, message: Message):
|
||||
|
||||
try:
|
||||
mod = message.text.split(maxsplit=1)[1].split('.')[0]
|
||||
except:
|
||||
except Exception:
|
||||
return await message.edit(
|
||||
f'<b>Usage:</b> <code>{prefix}backupmod [module]</code>',
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
@@ -169,7 +169,7 @@ async def restoremod(client: Client, message: Message):
|
||||
|
||||
try:
|
||||
mod = message.text.split(maxsplit=1)[1].split('.')[0]
|
||||
except:
|
||||
except Exception:
|
||||
return await message.edit(
|
||||
f'<b>Usage:</b> <code>{prefix}restoremod [module]</code>',
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
|
||||
@@ -16,7 +16,7 @@ def get_marine_life_details(species_name):
|
||||
'per_page': 1,
|
||||
}
|
||||
|
||||
response = requests.get(INATURALIST_API_URL, params=params)
|
||||
response = requests.get(INATURALIST_API_URL, params=params, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
|
||||
@@ -94,7 +94,7 @@ async def make_rayso(code: str, title: str, theme: str):
|
||||
'language': 'auto',
|
||||
'darkMode': False,
|
||||
}
|
||||
response = requests.post(f'{url}/rayso', data=data, headers=headers)
|
||||
response = requests.post(f'{url}/rayso', data=data, headers=headers, timeout=10)
|
||||
if response.status_code != 200:
|
||||
return None
|
||||
result = response.json()
|
||||
@@ -137,7 +137,7 @@ async def sgemini(_, message: Message):
|
||||
await message.edit_text('prompt not provided!')
|
||||
return
|
||||
await message.edit_text('Processing...')
|
||||
response = requests.get(url=f'{url}/bard?query={prompt}', headers=headers)
|
||||
response = requests.get(url=f'{url}/bard?query={prompt}', headers=headers, timeout=10)
|
||||
if response.status_code != 200:
|
||||
await message.edit_text('Something went wrong!')
|
||||
return
|
||||
@@ -167,7 +167,7 @@ async def app(client: Client, message: Message):
|
||||
|
||||
try:
|
||||
coverImage_url = result['results'][0]['icon']
|
||||
coverImage = requests.get(url=coverImage_url).content
|
||||
coverImage = requests.get(url=coverImage_url, timeout=10).content
|
||||
async with aiofiles.open('coverImage.jpg', mode='wb') as f:
|
||||
await f.write(coverImage)
|
||||
|
||||
@@ -225,7 +225,7 @@ async def tsearch(client: Client, message: Message):
|
||||
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)
|
||||
response = requests.get(url=f'{url}/torrent?query={query}&limit={limit}', headers=headers, timeout=10)
|
||||
if response.status_code != 200:
|
||||
await message.edit_text('Something went wrong')
|
||||
return
|
||||
@@ -265,7 +265,7 @@ async def tsearch(client: Client, message: Message):
|
||||
)
|
||||
|
||||
if coverImage_url is not None:
|
||||
coverImage = requests.get(url=coverImage_url).content
|
||||
coverImage = requests.get(url=coverImage_url, timeout=10).content
|
||||
async with aiofiles.open('coverImage.jpg', mode='wb') as f:
|
||||
await f.write(coverImage)
|
||||
|
||||
@@ -342,7 +342,7 @@ async def tts(client: Client, message: Message):
|
||||
return
|
||||
|
||||
data = {'text': prompt, 'character': character}
|
||||
response = requests.post(url=f'{url}/speech', headers=headers, json=data)
|
||||
response = requests.post(url=f'{url}/speech', headers=headers, json=data, timeout=10)
|
||||
if response.status_code != 200:
|
||||
await message.edit_text('Something went wrong')
|
||||
return
|
||||
@@ -419,7 +419,7 @@ async def ccgen(_, message: Message):
|
||||
await message.edit_text('Code not provided!')
|
||||
return
|
||||
await message.edit_text('Processing...')
|
||||
response = requests.get(url=f'{url}/ccgen?bins={bins}', headers=headers)
|
||||
response = requests.get(url=f'{url}/ccgen?bins={bins}', headers=headers, timeout=10)
|
||||
if response.status_code != 200:
|
||||
await message.edit_text('Something went wrong')
|
||||
return
|
||||
|
||||
@@ -161,7 +161,7 @@ def format_apple_music_result(data):
|
||||
async def search_music(api_url, format_function, message, query):
|
||||
await message.edit('Searching...')
|
||||
url = f'{api_url}{query}&limit=10'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
try:
|
||||
@@ -194,7 +194,7 @@ async def google_search(client: Client, message: Message):
|
||||
|
||||
await message.edit('Searching...')
|
||||
url = f'{GOOGLE_SEARCH_URL}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
results, formatted_results = format_google_results(data['data'])
|
||||
@@ -227,7 +227,7 @@ async def youtube_search(client: Client, message: Message):
|
||||
|
||||
await message.edit('Searching...')
|
||||
url = f'{YOUTUBE_SEARCH_URL}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
results, formatted_results = format_youtube_results(data['data'])
|
||||
@@ -260,7 +260,7 @@ async def movie_search(client, message: Message):
|
||||
|
||||
await message.edit('Searching...')
|
||||
url = f'{MOVIE_SEARCH_URL}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
results, formatted_results = format_movie_results(data['data'])
|
||||
@@ -300,7 +300,7 @@ async def apk_search(client, message: Message):
|
||||
|
||||
await message.edit('Searching...')
|
||||
url = f'{APK_SEARCH_URL}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
results, formatted_results = format_apk_results(data['BK9'])
|
||||
@@ -329,7 +329,7 @@ async def gptweb(_, message: Message):
|
||||
await message.edit('Thinking...')
|
||||
query = ' '.join(message.command[1:])
|
||||
url = f'{URL}/gptweb?text={query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
await message.edit(
|
||||
@@ -348,7 +348,7 @@ async def gemini(_, message: Message):
|
||||
await message.edit('Thinking...')
|
||||
query = ' '.join(message.command[1:])
|
||||
url = f'{URL}/gemini?query={query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
await message.edit(
|
||||
@@ -440,7 +440,7 @@ async def handle_reply(client: Client, message: Message):
|
||||
f'Votes: {movie["vote_count"]}'
|
||||
)
|
||||
if 'image' in movie:
|
||||
response = requests.get(movie['image'])
|
||||
response = requests.get(movie['image'], timeout=10)
|
||||
if response.status_code == 200:
|
||||
with open('movie_image.jpg', 'wb') as f:
|
||||
f.write(response.content)
|
||||
@@ -456,7 +456,7 @@ async def handle_reply(client: Client, message: Message):
|
||||
await message.reply(caption, parse_mode=enums.ParseMode.MARKDOWN)
|
||||
elif search_key.endswith('_apk'):
|
||||
apk_url = f'{APK_DOWNLOAD_URL}{results[index]["link"]}'
|
||||
fetch_apk_url = requests.get(apk_url)
|
||||
fetch_apk_url = requests.get(apk_url, timeout=10)
|
||||
if fetch_apk_url.status_code != 200:
|
||||
await message.edit('Failed to fetch APK data.')
|
||||
else:
|
||||
@@ -469,7 +469,7 @@ async def handle_reply(client: Client, message: Message):
|
||||
await message.edit('File size is too large to download.')
|
||||
else:
|
||||
apk_file_name = f'{data_apk["BK9"]["title"]}.apk'
|
||||
response = requests.get(download_url)
|
||||
response = requests.get(download_url, timeout=10)
|
||||
|
||||
if response.status_code != 200:
|
||||
await message.edit('Failed to download the APK file.')
|
||||
|
||||
@@ -27,7 +27,7 @@ async def search_cmd(client: Client, message: Message):
|
||||
cmd = message.command[1]
|
||||
word = message.command[2].lower()
|
||||
timeout = float(message.command[3]) if len(message.command) > 3 else 2
|
||||
except:
|
||||
except Exception:
|
||||
return await message.edit(
|
||||
f'<b>Usage:</b> <code>{prefix}search [/cmd]* [search_word]* [timeout=2.0]</code>',
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
|
||||
@@ -8,8 +8,8 @@ from utils.scripts import format_exc, import_library
|
||||
import_library('lxml_html_clean')
|
||||
import_library('newspaper', 'newspaper3k')
|
||||
nltk = import_library('nltk')
|
||||
from newspaper import Article
|
||||
from newspaper.article import ArticleException
|
||||
from newspaper import Article # noqa: E402
|
||||
from newspaper.article import ArticleException # noqa: E402
|
||||
|
||||
nltk.download('all')
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ gladia_url = 'https://api.gladia.io/v2/transcription/'
|
||||
# Function to make fetch requests to the Gladia API
|
||||
def make_fetch_request(url, headers, method='GET', data=None):
|
||||
if method == 'POST':
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
response = requests.post(url, headers=headers, json=data, timeout=10)
|
||||
else:
|
||||
response = requests.get(url, headers=headers)
|
||||
response = requests.get(url, headers=headers, timeout=10)
|
||||
return response.json()
|
||||
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ from utils.scripts import import_library
|
||||
|
||||
import_library('pyzerox', 'py-zerox')
|
||||
|
||||
import litellm
|
||||
from pyzerox import zerox
|
||||
from pyzerox.errors import ModelAccessError, NotAVisionModel
|
||||
import litellm # noqa: E402
|
||||
from pyzerox import zerox # noqa: E402
|
||||
from pyzerox.errors import ModelAccessError, NotAVisionModel # noqa: E402
|
||||
|
||||
kwargs = {}
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@ async def prussian_cmd(_, message: Message):
|
||||
]
|
||||
splitted = message.reply_to_message.text.split()
|
||||
|
||||
for i in range(0, len(splitted), random.randint(2, 3)):
|
||||
for i in range(0, len(splitted), random.randint(2, 3)): # noqa: S311
|
||||
for _j in range(1, 2):
|
||||
splitted.insert(i, random.choice(words))
|
||||
splitted.insert(i, random.choice(words)) # noqa: S311
|
||||
|
||||
await message.edit(' '.join(splitted), parse_mode=enums.ParseMode.HTML)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ async def user_exec(_: Client, message: Message):
|
||||
|
||||
try:
|
||||
with redirect_stdout(stdout):
|
||||
exec(code) # skipcq
|
||||
exec(code) # skipcq # noqa: S102
|
||||
text = f'<b>Code:</b>\n<code>{code}</code>\n\n<b>Result</b>:\n<code>{stdout.getvalue()}</code>'
|
||||
if message.command[0] == 'exnoedit':
|
||||
await message.reply(text)
|
||||
@@ -61,7 +61,7 @@ async def user_eval(client: Client, message: Message):
|
||||
code = message.text.split(maxsplit=1)[1]
|
||||
|
||||
try:
|
||||
result = eval(code) # skipcq
|
||||
result = eval(code) # skipcq # noqa: S307
|
||||
await message.edit(f'<b>Expression:</b>\n<code>{code}</code>\n\n<b>Result</b>:\n<code>{result}</code>')
|
||||
except Exception as e:
|
||||
await message.edit(format_exc(e))
|
||||
|
||||
@@ -51,14 +51,14 @@ async def convert_to_image(message, client) -> None | str:
|
||||
path_s = await client.download_media(message.reply_to_message)
|
||||
final_path = 'lottie_proton.png'
|
||||
cmd = f'lottie_convert.py --frame 0 -if lottie -of png {path_s} {final_path}'
|
||||
await exec(cmd) # skipcq
|
||||
await exec(cmd) # skipcq # noqa: S102
|
||||
elif message.reply_to_message.audio:
|
||||
thumb = message.reply_to_message.audio.thumbs[0].file_id
|
||||
final_path = await client.download_media(thumb)
|
||||
elif message.reply_to_message.video or message.reply_to_message.animation:
|
||||
final_path = 'fetched_thumb.png'
|
||||
vid_path = await client.download_media(message.reply_to_message)
|
||||
await exec(f'ffmpeg -i {vid_path} -filter:v scale=500:500 -an {final_path}') # skipcq
|
||||
await exec(f'ffmpeg -i {vid_path} -filter:v scale=500:500 -an {final_path}') # skipcq # noqa: S102
|
||||
elif message.reply_to_message.document:
|
||||
if (
|
||||
message.reply_to_message.document.mime_type == 'image/jpeg'
|
||||
@@ -83,6 +83,7 @@ def remove_background(photo_data):
|
||||
files={'image_file': image_data},
|
||||
data={'size': 'auto'},
|
||||
headers={'X-Api-Key': rmbg_key},
|
||||
timeout=10,
|
||||
)
|
||||
if response.status_code == 200:
|
||||
return BytesIO(response.content)
|
||||
@@ -127,6 +128,7 @@ async def rmbg(client: Client, message: Message):
|
||||
files=files,
|
||||
allow_redirects=True,
|
||||
stream=True,
|
||||
timeout=10,
|
||||
)
|
||||
if os.path.exists(cool):
|
||||
os.remove(cool)
|
||||
|
||||
@@ -30,7 +30,7 @@ async def shell(_, message: Message):
|
||||
return await message.edit('<b>Specify the command in message text</b>')
|
||||
cmd_text = message.text.split(maxsplit=1)[1]
|
||||
cmd_args = cmd_text.split()
|
||||
cmd_obj = Popen(
|
||||
cmd_obj = Popen( # noqa: S603
|
||||
cmd_args,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
|
||||
@@ -26,12 +26,12 @@ async def tiktok_stalk(_, message: Message):
|
||||
|
||||
await message.edit('Fetching TikTok profile...')
|
||||
url = f'{TIKTOK_API_URL}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json().get('result', {})
|
||||
if data:
|
||||
profile_pic_url = data.get('profile', '')
|
||||
profile_pic = requests.get(profile_pic_url).content
|
||||
profile_pic = requests.get(profile_pic_url, timeout=10).content
|
||||
profile_pic_stream = io.BytesIO(profile_pic)
|
||||
profile_pic_stream.name = 'profile.jpg'
|
||||
|
||||
@@ -68,7 +68,7 @@ async def ipinfo(_, message: Message):
|
||||
try:
|
||||
url = requests.get(
|
||||
f'http://ip-api.com/json/{searchip}?fields=status,message,continent,continentCode,country,countryCode,region,regionName,city,district,zip,lat,lon,timezone,offset,currency,isp,org,as,asname,reverse,mobile,proxy,hosting,query'
|
||||
)
|
||||
, timeout=10)
|
||||
response = json.loads(url.text)
|
||||
text = f"""
|
||||
<b>IP Address:</b> <code>{response['query']}</code>
|
||||
@@ -95,7 +95,7 @@ async def ipinfo(_, message: Message):
|
||||
<b>Proxy:</b> <code>{response['proxy']}</code>
|
||||
<b>Hosting:</b> <code>{response['hosting']}</code>"""
|
||||
await m.edit_text(text)
|
||||
except:
|
||||
except Exception:
|
||||
await m.edit_text('Unable To Find Info!')
|
||||
|
||||
|
||||
@@ -113,12 +113,12 @@ async def instagram_stalk(_, message: Message):
|
||||
|
||||
await message.edit('Fetching Instagram profile...')
|
||||
url = f'{INSTAGRAM_API_URL}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json().get('result', {}).get('user_info', {})
|
||||
if data:
|
||||
profile_pic_url = data.get('profile_pic_url', '')
|
||||
profile_pic = requests.get(profile_pic_url).content
|
||||
profile_pic = requests.get(profile_pic_url, timeout=10).content
|
||||
profile_pic_stream = io.BytesIO(profile_pic)
|
||||
profile_pic_stream.name = 'profile.jpg'
|
||||
|
||||
@@ -157,7 +157,7 @@ async def github_stalk(_, message: Message):
|
||||
|
||||
await message.edit('Fetching GitHub profile...')
|
||||
url = f'{GH_STALK}{query}'
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
created_at = data.get('created_at', 'N/A')
|
||||
|
||||
@@ -21,7 +21,7 @@ imageio = import_library('imageio')
|
||||
def create_gif(filename: str, offset: int, fps: int = 2, typ: str = 'spin'):
|
||||
img = Image.open(f'downloads/{filename}')
|
||||
if typ.lower() != 'spin':
|
||||
img = img.resize((random.randint(200, 1280), random.randint(200, 1280)), Image.ANTIALIAS)
|
||||
img = img.resize((random.randint(200, 1280), random.randint(200, 1280)), Image.ANTIALIAS) # noqa: S311 # noqa: S311
|
||||
imageio.mimsave(
|
||||
'downloads/video.gif',
|
||||
[img.rotate(-(i % 360)) for i in range(1, 361, offset)],
|
||||
|
||||
@@ -75,7 +75,7 @@ async def quote_cmd(client: Client, message: Message):
|
||||
'text_color': '#fff',
|
||||
}
|
||||
|
||||
response = requests.post(QUOTES_API, json=params)
|
||||
response = requests.post(QUOTES_API, json=params, timeout=10)
|
||||
if not response.ok:
|
||||
return await message.edit(f'<b>Quotes API error!</b>\n<code>{response.text}</code>')
|
||||
|
||||
@@ -126,7 +126,7 @@ async def fake_quote_cmd(client: Client, message: types.Message):
|
||||
'text_color': '#fff',
|
||||
}
|
||||
|
||||
response = requests.post(QUOTES_API, json=params)
|
||||
response = requests.post(QUOTES_API, json=params, timeout=10)
|
||||
if not response.ok:
|
||||
return await message.edit(f'<b>Quotes API error!</b>\n<code>{response.text}</code>')
|
||||
|
||||
@@ -227,14 +227,14 @@ async def render_message(app: Client, message: types.Message) -> dict:
|
||||
author['avatar'] = await get_file(from_user.photo.big_file_id)
|
||||
elif not from_user.photo and from_user.username:
|
||||
# may be user blocked us, we will try to get avatar via t.me
|
||||
t_me_page = requests.get(f'https://t.me/{from_user.username}').text
|
||||
t_me_page = requests.get(f'https://t.me/{from_user.username}', timeout=10).text
|
||||
sub = '<meta property="og:image" content='
|
||||
index = t_me_page.find(sub)
|
||||
if index != -1:
|
||||
link = t_me_page[index + 35 :].split('"')
|
||||
if len(link) > 0 and link[0] and link[0] != 'https://telegram.org/img/t_logo.png':
|
||||
# found valid link
|
||||
avatar = requests.get(link[0]).content
|
||||
avatar = requests.get(link[0], timeout=10).content
|
||||
author['avatar'] = base64.b64encode(avatar).decode()
|
||||
else:
|
||||
author['avatar'] = ''
|
||||
|
||||
@@ -44,7 +44,7 @@ async def restart_cmd(_, message: Message):
|
||||
|
||||
if 'LAVHOST' in os.environ:
|
||||
await message.edit('<b>Your lavHost is restarting...</b>')
|
||||
os.system('lavhost restart')
|
||||
os.system('lavhost restart') # noqa: S605, S607
|
||||
return
|
||||
|
||||
await message.edit('<b>Restarting...</b>')
|
||||
@@ -67,14 +67,14 @@ async def update(_, message: Message):
|
||||
|
||||
if 'LAVHOST' in os.environ:
|
||||
await message.edit('<b>Your lavHost is updating...</b>')
|
||||
os.system('lavhost update')
|
||||
os.system('lavhost update') # noqa: S605, S607
|
||||
return
|
||||
|
||||
await message.edit('<b>Updating...</b>')
|
||||
try:
|
||||
if not check_command('termux-setup-storage'):
|
||||
subprocess.run([sys.executable, '-m', 'pip', 'install', '-U', 'pip'], check=True)
|
||||
subprocess.run(['git', 'pull'], check=True)
|
||||
subprocess.run(['git', 'pull'], check=True) # noqa: S607
|
||||
|
||||
if os.path.exists('requirements.txt') and os.path.getsize('requirements.txt') > 0:
|
||||
subprocess.run(
|
||||
@@ -91,7 +91,7 @@ async def update(_, message: Message):
|
||||
)
|
||||
|
||||
if requirements_list:
|
||||
subprocess.run(
|
||||
subprocess.run( # noqa: S603
|
||||
[sys.executable, '-m', 'pip', 'install', '-U', *requirements_list],
|
||||
check=True,
|
||||
)
|
||||
|
||||
@@ -35,7 +35,7 @@ from utils.scripts import format_exc, humanbytes, progress
|
||||
|
||||
def generate_screenshot(url):
|
||||
api_url = f'https://api.apiflash.com/v1/urltoimage?access_key={apiflash_key}&url={url}&format=png'
|
||||
response = requests.get(api_url)
|
||||
response = requests.get(api_url, timeout=10)
|
||||
if response.status_code == 200:
|
||||
return BytesIO(response.content)
|
||||
return None
|
||||
@@ -212,6 +212,7 @@ async def upload_cmd(_, message: Message):
|
||||
response = requests.post(
|
||||
'https://x0.at',
|
||||
files={'file': f},
|
||||
timeout=10,
|
||||
)
|
||||
|
||||
if response.ok:
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# Userbot Modules
|
||||
# Generated: Fri Jun 19 03:34:52 PM CEST 2026
|
||||
|
||||
## Core Modules (utils/)
|
||||
- utils/config.py
|
||||
- utils/conv.py
|
||||
- utils/db.py
|
||||
- utils/handlers.py
|
||||
- utils/__init__.py
|
||||
- utils/misc.py
|
||||
- utils/module.py
|
||||
- utils/rentry.py
|
||||
- utils/scripts.py
|
||||
|
||||
## Image Modules (images/)
|
||||
- images/icons.py
|
||||
- images/imgur.py
|
||||
- images/ncode.py
|
||||
- images/pinterest.py
|
||||
- images/risearch.py
|
||||
- images/unsplash2.py
|
||||
- images/unsplash.py
|
||||
|
||||
## Bot Modules (modules/)
|
||||
- modules/1000-7.py
|
||||
- modules/admintool.py
|
||||
- modules/admlist.py
|
||||
- modules/afk.py
|
||||
- modules/aimage.py
|
||||
- modules/amogus.py
|
||||
- modules/amongus.py
|
||||
- modules/animations.py
|
||||
- modules/anime/anilist.py
|
||||
- modules/anime/anime.py
|
||||
- modules/anime/neko.py
|
||||
- modules/aniquotes.py
|
||||
- modules/antipm.py
|
||||
- modules/blackbox.py
|
||||
- modules/calculator.py
|
||||
- modules/cdxl.py
|
||||
- modules/chatbot.py
|
||||
- modules/circle.py
|
||||
- modules/clear_notifs.py
|
||||
- modules/cohere.py
|
||||
- modules/demotivator.py
|
||||
- modules/destroy.py
|
||||
- modules/dice.py
|
||||
- modules/direct.py
|
||||
- modules/duckduckgo.py
|
||||
- modules/durov.py
|
||||
- modules/example.py
|
||||
- modules/fakeactions.py
|
||||
- modules/filters.py
|
||||
- modules/fliptext.py
|
||||
- modules/flux.py
|
||||
- modules/f.py
|
||||
- modules/gemini.py
|
||||
- modules/google.py
|
||||
- modules/hearts.py
|
||||
- modules/help.py
|
||||
- modules/huggingface.py
|
||||
- modules/id.py
|
||||
- modules/joindate.py
|
||||
- modules/kokodrilo_explodando.py
|
||||
- modules/leave_chat.py
|
||||
- modules/loader.py
|
||||
- modules/markitdown.py
|
||||
- modules/mention.py
|
||||
- modules/mirror_flip.py
|
||||
- modules/misc/autobackup.py
|
||||
- modules/misc/autofwd.py
|
||||
- modules/misc/backup.py
|
||||
- modules/misc/cama.py
|
||||
- modules/misc/mlog.py
|
||||
- modules/misc/prayer.py
|
||||
- modules/misc/safone.py
|
||||
- modules/misc/sarethai.py
|
||||
- modules/misc/search.py
|
||||
- modules/misc/summary.py
|
||||
- modules/misc/switch.py
|
||||
- modules/misc/transcribeyt.py
|
||||
- modules/notes.py
|
||||
- modules/open.py
|
||||
- modules/pdf2md.py
|
||||
- modules/perfectrussian.py
|
||||
- modules/ping.py
|
||||
- modules/prefix.py
|
||||
- modules/purge.py
|
||||
- modules/python.py
|
||||
- modules/reactionspam.py
|
||||
- modules/removebg.py
|
||||
- modules/say.py
|
||||
- modules/sendmod.py
|
||||
- modules/sessionkiller.py
|
||||
- modules/sgb.py
|
||||
- modules/shell.py
|
||||
- modules/socialstalk.py
|
||||
- modules/spam.py
|
||||
- modules/spin.py
|
||||
- modules/squotes.py
|
||||
- modules/stickers.py
|
||||
- modules/support.py
|
||||
- modules/thumbnail.py
|
||||
- modules/type.py
|
||||
- modules/updater.py
|
||||
- modules/upl.py
|
||||
- modules/url.py
|
||||
- modules/user_info.py
|
||||
- modules/vt.py
|
||||
|
||||
## Custom Modules (modules/custom_modules/)
|
||||
- (none)
|
||||
|
||||
---
|
||||
Total: 101 modules (85 bot + 0 custom + 7 image + 9 core)
|
||||
@@ -771,9 +771,9 @@ class DemoteHandler:
|
||||
privileges=ChatPrivileges(**self.common_privileges_demote),
|
||||
)
|
||||
except UserAdminInvalid:
|
||||
raise UserAdminInvalid()
|
||||
raise # noqa: B904
|
||||
except ChatAdminRequired:
|
||||
raise ChatAdminRequired()
|
||||
raise # noqa: B904
|
||||
except Exception as e:
|
||||
await self.message.edit(format_exc(e))
|
||||
|
||||
@@ -870,9 +870,9 @@ class PromoteHandler:
|
||||
self.cause.split(maxsplit=1)[1],
|
||||
)
|
||||
except UserAdminInvalid:
|
||||
raise UserAdminInvalid()
|
||||
raise # noqa: B904
|
||||
except ChatAdminRequired:
|
||||
raise ChatAdminRequired()
|
||||
raise # noqa: B904
|
||||
except Exception as e:
|
||||
await self.message.edit(format_exc(e))
|
||||
|
||||
|
||||
@@ -29,14 +29,14 @@ class UrllibClient:
|
||||
def get(self, url, headers=None):
|
||||
if headers is None:
|
||||
headers = {}
|
||||
request = urllib.request.Request(url, headers=headers)
|
||||
request = urllib.request.Request(url, headers=headers) # noqa: S310
|
||||
return self._request(request)
|
||||
|
||||
def post(self, url, data=None, headers=None):
|
||||
if headers is None:
|
||||
headers = {}
|
||||
postdata = urllib.parse.urlencode(data).encode()
|
||||
request = urllib.request.Request(url, postdata, headers)
|
||||
request = urllib.request.Request(url, postdata, headers) # noqa: S310
|
||||
return self._request(request)
|
||||
|
||||
def _request(self, request):
|
||||
|
||||
@@ -216,7 +216,7 @@ def restart() -> None:
|
||||
music_bot_process.terminate()
|
||||
except psutil.NoSuchProcess:
|
||||
print('Music bot is not running.')
|
||||
os.execvp(sys.executable, [sys.executable, 'main.py']) # skipcq
|
||||
os.execvp(sys.executable, [sys.executable, 'main.py']) # skipcq # noqa: S606
|
||||
|
||||
|
||||
def format_exc(e: Exception, suffix='') -> str:
|
||||
@@ -324,7 +324,7 @@ def import_library(library_name: str, package_name: str = None):
|
||||
try:
|
||||
return importlib.import_module(library_name)
|
||||
except ImportError as exc:
|
||||
completed = subprocess.run(
|
||||
completed = subprocess.run( # noqa: S603
|
||||
[sys.executable, '-m', 'pip', 'install', '--upgrade', package_name],
|
||||
check=True,
|
||||
)
|
||||
@@ -340,7 +340,7 @@ def uninstall_library(package_name: str):
|
||||
Uninstalls a library
|
||||
:param package_name: package name in PyPi (pip uninstall example)
|
||||
"""
|
||||
completed = subprocess.run([sys.executable, '-m', 'pip', 'uninstall', '-y', package_name], check=True)
|
||||
completed = subprocess.run([sys.executable, '-m', 'pip', 'uninstall', '-y', package_name], check=True) # noqa: S603
|
||||
if completed.returncode != 0:
|
||||
raise AssertionError(
|
||||
f'Failed to uninstall library {package_name} (pip exited with code {completed.returncode})'
|
||||
@@ -498,7 +498,7 @@ def parse_meta_comments(code: str) -> dict[str, str]:
|
||||
return {groups[i]: groups[i + 1] for i in range(0, len(groups), 2)}
|
||||
|
||||
|
||||
def ReplyCheck(message: Message):
|
||||
def reply_check(message: Message):
|
||||
reply_id = None
|
||||
|
||||
if message.reply_to_message:
|
||||
|
||||
Reference in New Issue
Block a user