feat: add stories plugin
fix autopic
This commit is contained in:
@@ -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
97
plugins/stories.py
Normal 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)
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
__version__ = "2025.02.23"
|
||||
ultroid_version = "2.1"
|
||||
__version__ = "2025.05.31"
|
||||
ultroid_version = "2.1.1"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Important Requirements here.
|
||||
telethon
|
||||
gitpython
|
||||
https://github.com/New-dev0/Telethon-Patch/archive/main.zip
|
||||
python-decouple
|
||||
python-dotenv
|
||||
|
||||
Reference in New Issue
Block a user