feat: add stories plugin

fix autopic
This commit is contained in:
New-dev0
2025-05-31 20:15:06 +05:30
parent a7cc8ce073
commit dba2b01dcd
6 changed files with 202 additions and 69 deletions

View File

@@ -10,17 +10,94 @@ import asyncio
import os
import random
from random import shuffle
import aiohttp
import re
from telethon.tl.functions.photos import UploadProfilePhotoRequest
from PIL import Image
from pyUltroid.fns.helper import download_file
from pyUltroid.fns.tools import get_google_images
from pyUltroid.fns.helper import download_file, fast_download
from . import LOGS, get_help, get_string, udB, ultroid_bot, ultroid_cmd
__doc__ = get_help("help_autopic")
async def get_google_images(query: str):
"""Extract image URLs from Google Images search results with fallbacks"""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
search_url = f"https://www.google.com/search?q={query}&tbm=isch"
# Domains to exclude
excluded_domains = [
'gstatic.com',
'google.com',
'googleusercontent.com',
'ssl.google.com'
]
def is_valid_url(url):
return not any(domain in url.lower() for domain in excluded_domains)
try:
async with aiohttp.ClientSession() as session:
async with session.get(search_url, headers=headers) as response:
html = await response.text()
# Try to extract from search results div first
img_urls = []
search_pattern = r'<div id="search".*?>(.*?)</div>'
search_match = re.search(search_pattern, html, re.DOTALL)
if search_match:
search_content = search_match.group(1)
url_pattern = r'https://[^\"]*?\.(?:jpg|jpeg|png|webp)'
url_matches = re.finditer(url_pattern, search_content, re.IGNORECASE)
for url_match in url_matches:
url = url_match.group(0)
if url not in img_urls and is_valid_url(url):
img_urls.append(url)
# Fallback to tdeeNb div if no results
if not img_urls:
pattern = r'<div jsname="tdeeNb"[^>]*>(.*?)</div>'
matches = re.finditer(pattern, html, re.DOTALL)
for match in matches:
div_content = match.group(1)
url_pattern = r'https://[^\"]*?\.(?:jpg|jpeg|png|webp)'
url_matches = re.finditer(url_pattern, div_content, re.IGNORECASE)
for url_match in url_matches:
url = url_match.group(0)
if url not in img_urls and is_valid_url(url):
img_urls.append(url)
# Fallback to general image search if still no results
if not img_urls:
pattern = r"https://[^\"]*?\.(?:jpg|jpeg|png|webp)"
matches = re.finditer(pattern, html, re.IGNORECASE)
for match in matches:
url = match.group(0)
if url not in img_urls and is_valid_url(url):
img_urls.append(url)
# Final fallback to data URLs if still no results
if not img_urls:
pattern = r'data:image/(?:jpeg|png|webp);base64,[^\"]*'
matches = re.finditer(pattern, html, re.IGNORECASE)
for match in matches:
url = match.group(0)
if url not in img_urls:
img_urls.append(url)
return img_urls
except Exception as e:
print(f"Error fetching Google images: {e}")
return []
@ultroid_cmd(pattern="autopic( (.*)|$)")
async def autopic(e):
search = e.pattern_match.group(1).strip()
@@ -30,32 +107,25 @@ async def autopic(e):
if not search:
return await e.eor(get_string("autopic_1"), time=5)
e = await e.eor(get_string("com_1"))
gi = googleimagesdownload()
args = {
"keywords": search,
"limit": 50,
"format": "jpg",
"output_directory": "./resources/downloads/",
}
try:
pth = await gi.download(args)
ok = pth[0][search]
except Exception as er:
LOGS.exception(er)
return await e.eor(str(er))
if not ok:
images = await get_google_images(search)
if not images:
return await e.eor(get_string("autopic_2").format(search), time=5)
await e.eor(get_string("autopic_3").format(search))
udB.set_key("AUTOPIC", search)
SLEEP_TIME = udB.get_key("SLEEP_TIME") or 1221
while True:
for lie in ok:
for lie in images:
if udB.get_key("AUTOPIC") != search:
return
file = await e.client.upload_file(lie)
await e.client(UploadProfilePhotoRequest(file))
download_path, stime = await fast_download(lie, "resources/downloads/autopic.jpg")
img = Image.open(download_path)
img.save("resources/downloads/autopic.jpg")
file = await e.client.upload_file("resources/downloads/autopic.jpg")
await e.client(UploadProfilePhotoRequest(file=file))
os.remove("resources/downloads/autopic.jpg")
await asyncio.sleep(SLEEP_TIME)
shuffle(ok)
shuffle(images)
if search := udB.get_key("AUTOPIC"):
@@ -69,9 +139,11 @@ if search := udB.get_key("AUTOPIC"):
if not images.get(search):
return
img = random.choice(images[search])
filee = await download_file(img["original"], "resources/downloads/autopic.jpg")
file = await ultroid_bot.upload_file(filee)
await ultroid_bot(UploadProfilePhotoRequest(file))
filee, stime = await fast_download(img, "resources/downloads/autopic.jpg")
img = Image.open(filee)
img.save("resources/downloads/autopic.jpg")
file = await ultroid_bot.upload_file("resources/downloads/autopic.jpg")
await ultroid_bot(UploadProfilePhotoRequest(file=file))
os.remove(filee)
try:

97
plugins/stories.py Normal file
View File

@@ -0,0 +1,97 @@
# Ultroid - UserBot
# Copyright (C) 2021-2023 TeamUltroid
#
# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
# PLease read the GNU Affero General Public License in
# <https://www.github.com/TeamUltroid/Ultroid/blob/main/LICENSE/>.
"""
✘ Commands Available -
• `{i}setstory <reply media>`
Set replied media as your story.
• `{i}storydl <username/reply user>`
Download and upload user stories!
"""
import os
from contextlib import suppress
from . import ultroid_cmd, get_string, LOGS
from telethon import TelegramClient
from telethon.tl.functions.channels import GetFullChannelRequest
from telethon.tl.types import User, UserFull, InputPeerSelf, InputPrivacyValueAllowAll, Channel
from telethon.tl.functions.stories import SendStoryRequest
from telethon.tl.functions.users import GetFullUserRequest
from telethon.events import NewMessage
@ultroid_cmd("setstory")
async def setStory(event: NewMessage.Event):
reply = await event.get_reply_message()
if not (reply and (reply.photo or reply.video)):
await event.eor("Please reply to a photo or video!", time=5)
return
msg = await event.eor(get_string("com_1"))
try:
await event.client(
SendStoryRequest(
InputPeerSelf(),
reply.media,
privacy_rules=[
InputPrivacyValueAllowAll()
]
)
)
await msg.eor("🔥 **Story is Live!**", time=5)
except Exception as er:
await msg.edit(f"__ERROR: {er}__")
LOGS.exception(er)
@ultroid_cmd("storydl")
async def downloadUserStories(event: NewMessage.Event):
replied = await event.get_reply_message()
await event.eor(get_string("com_1"))
try:
username = event.text.split(maxsplit=1)[1]
except IndexError:
if replied and isinstance(replied.sender, User):
username = replied.sender_id
else:
return await event.eor(
"Please reply to a user or provide username!"
# get_string("story_1")
)
with suppress(ValueError):
username = int(username)
stories = None
try:
entity = await event.client.get_entity(username)
if isinstance(entity, Channel):
full_user: UserFull = (
await event.client(GetFullChannelRequest(entity.id))
).full_channel
stories = full_user.stories
else:
full_user: UserFull = (
await event.client(GetFullUserRequest(id=username))
).full_user
stories = full_user.stories
except Exception as er:
await event.eor(f"ERROR: __{er}__")
return
if not (stories and stories.stories):
await event.eor("ERROR: Stories not found!")
return
for story in stories.stories:
client: TelegramClient = event.client
file = await client.download_media(story.media)
await event.reply(
story.caption,
file=file
)
os.remove(file)
await event.eor("**Uploaded Stories!**", time=5)

View File

@@ -18,7 +18,6 @@ def main():
WasItRestart,
autopilot,
customize,
fetch_ann,
plug,
ready,
startup_stuff,
@@ -86,12 +85,6 @@ def main():
if not udB.get_key("LOG_OFF"):
ultroid_bot.run_in_loop(ready())
# TODO: Announcement API IS DOWN
# if AsyncIOScheduler:
# scheduler = AsyncIOScheduler()
# scheduler.add_job(fetch_ann, "interval", minutes=12 * 60)
# scheduler.start()
# Edit Restarting Message (if It's restarting)
ultroid_bot.run_in_loop(WasItRestart(udB))

View File

@@ -33,6 +33,7 @@ from telethon.tl.functions.channels import (
EditPhotoRequest,
InviteToChannelRequest,
)
from telethon.tl.functions.channels import JoinChannelRequest
from telethon.tl.functions.contacts import UnblockRequest
from telethon.tl.types import (
ChatAdminRights,
@@ -431,41 +432,6 @@ async def plug(plugin_channels):
LOGS.exception(er)
# some stuffs
async def fetch_ann():
from .. import asst, udB
from ..fns.tools import async_searcher
get_ = udB.get_key("OLDANN") or []
chat_id = udB.get_key("LOG_CHANNEL")
try:
updts = await async_searcher(
"https://ultroid-api.vercel.app/announcements", post=True, re_json=True
)
for upt in updts:
key = list(upt.keys())[0]
if key not in get_:
cont = upt[key]
if isinstance(cont, dict) and cont.get("lang"):
if cont["lang"] != (udB.get_key("language") or "en"):
continue
cont = cont["msg"]
if isinstance(cont, str):
await asst.send_message(chat_id, cont)
elif isinstance(cont, dict) and cont.get("chat"):
await asst.forward_messages(chat_id, cont["msg_id"], cont["chat"])
else:
LOGS.info(cont)
LOGS.info(
"Invalid Type of Announcement Detected!\nMake sure you are on latest version.."
)
get_.append(key)
udB.set_key("OLDANN", get_)
except Exception as er:
LOGS.exception(er)
async def ready():
from .. import asst, udB, ultroid_bot
@@ -506,7 +472,11 @@ async def ready():
LOGS.exception(ef)
if spam_sent and not spam_sent.media:
udB.set_key("LAST_UPDATE_LOG_SPAM", spam_sent.id)
# TODO: await fetch_ann()
try:
await ultroid_bot(JoinChannelRequest("TheUltroid"))
except Exception as er:
LOGS.exception(er)
async def WasItRestart(udb):

View File

@@ -1,2 +1,2 @@
__version__ = "2025.02.23"
ultroid_version = "2.1"
__version__ = "2025.05.31"
ultroid_version = "2.1.1"

View File

@@ -1,5 +1,6 @@
# Important Requirements here.
telethon
gitpython
https://github.com/New-dev0/Telethon-Patch/archive/main.zip
python-decouple
python-dotenv