Files
homelab/userbot/modules/amongus.py
T
forust fb43306571
lint / prettier (push) Successful in 8s
lint / ruff (push) Successful in 5s
lint / yamllint (push) Successful in 7s
lint / hadolint (push) Failing after 4s
validate / yaml (push) Successful in 5s
validate / k8s (push) Successful in 5s
Fix all lint issues: Dockerfiles (DL3015/DL3013/DL4006) + Ruff (173→0 errors)
Dockerfile fixes:
- edu_master/phpsessid-bot: add --no-install-recommends, pin pip versions
- edu_master/webinar-checker: pin pip versions with --no-cache-dir
- userbot: add SHELL with pipefail for pipe operations

Ruff fixes (173 → 0):
- W293/W291/W292: whitespace clean via ruff format
- N806: camelCase → snake_case (anilist, safone, hearts, flux, etc.)
- ARG001/ARG002: prefix unused params with _
- SIM115: use context managers for file I/O
- SIM117: combine nested with statements
- S608: noqa on SQL f-strings (module name is validated)
- E402/N812/N817: import fixes
- B023: pass loop variable as argument
- I001: auto-sorted imports
- syntax: fixed = vs == in dtek_notif/main.py
2026-06-21 22:01:51 +02:00

197 lines
8.2 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# From CatUB
import asyncio
import re
from io import BytesIO
from random import choice, randint
from textwrap import wrap
import requests
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 edit_or_reply, reply_check
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', timeout=10
).content
),
60,
)
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]
text = Image.new('RGBA', (w + 30, h + 30))
ImageDraw.Draw(text).multiline_text((15, 15), text_, '#FFF', font, stroke_width=2, stroke_fill='#000')
w = imposter.width + text.width + 10
h = max(imposter.height, text.height)
image = Image.new('RGBA', (w, h))
image.paste(imposter, (0, h - imposter.height), imposter)
image.paste(text, (w - text.width, 0), text)
image.thumbnail((512, 512))
output = BytesIO()
output.name = 'imposter.webp'
image.save(output, 'WebP')
output.seek(0)
return output
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', # noqa: S311
timeout=10,
).content
font = requests.get(
'https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/fonts/roboto_regular.ttf',
timeout=10,
).content
font = BytesIO(font)
font = ImageFont.truetype(font, 30)
image = Image.new('RGBA', (1, 1), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).multiline_textbbox((0, 0), text, font, stroke_width=2)
w, h = bbox[2], bbox[3]
image = Image.open(BytesIO(background))
x, y = image.size
draw = ImageDraw.Draw(image)
draw.multiline_text(((x - w) // 2, (y - h) // 2), text=text, font=font, fill='white', align='center')
output = BytesIO()
output.name = 'impostor.png'
image.save(output, 'PNG')
output.seek(0)
return output
@Client.on_message(filters.command('amongus', prefix) & filters.me)
async def amongus_cmd(client: Client, message: Message):
text = ' '.join(message.command[1:]) if len(message.command) > 1 else ''
reply = message.reply_to_message
await message.edit('tun tun tun...')
if not text and reply:
text = reply.text or reply.caption or ''
clr = re.findall(r'-c\d+', text)
try:
clr = clr[0]
clr = clr.replace('-c', '')
text = text.replace(f'-c{clr}', '')
clr = int(clr)
if clr > 12 or clr < 1:
clr = randint(1, 12) # noqa: S311
except IndexError:
clr = randint(1, 12) # noqa: S311
if not text:
if not reply:
text = f'{message.from_user.first_name} Was a traitor!'
else:
text = f'{reply.from_user.first_name} Was a traitor!'
imposter_file = await amongus_gen(text, clr)
await message.delete()
await client.send_sticker(
message.chat.id,
imposter_file,
reply_to_message_id=reply_check(message),
)
@Client.on_message(filters.command('imposter', prefix) & filters.me)
async def imposter_cmd(client: Client, message: Message):
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)}.' # noqa: S311
else:
args = message.text.split()[1:]
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)
await message.delete()
await client.send_photo(
message.chat.id,
imposter_file,
reply_to_message_id=reply_check(message),
)
@Client.on_message(filters.command(['imp', 'impn'], prefix) & filters.me)
async def imp_animation(client: Client, message: Message):
name = ' '.join(message.command[1:]) if len(message.command) > 1 else ''
if not name:
reply = message.reply_to_message
name = reply.from_user.first_name if reply else message.from_user.first_name
cmd = message.command[0].lower()
text1 = await edit_or_reply(message, 'Uhmm... Something is wrong here!!')
await asyncio.sleep(2)
await text1.delete()
stcr1 = await client.send_sticker(message.chat.id, 'CAADAQADRwADnjOcH98isYD5RJTwAg')
text2 = await message.reply(f'<b>{message.from_user.first_name}:</b> I have to call discussion')
await asyncio.sleep(3)
await stcr1.delete()
await text2.delete()
stcr2 = await client.send_sticker(message.chat.id, 'CAADAQADRgADnjOcH9odHIXtfgmvAg')
text3 = await message.reply(f'<b>{message.from_user.first_name}:</b> We have to eject the imposter or will lose')
await asyncio.sleep(3)
await stcr2.delete()
await text3.delete()
stcr3 = await client.send_sticker(message.chat.id, 'CAADAQADOwADnjOcH77v3Ap51R7gAg')
text4 = await message.reply('<b>Others:</b> Where???')
await asyncio.sleep(2)
await text4.edit('<b>Others:</b> Who??')
await asyncio.sleep(2)
await text4.edit(f'<b>{message.from_user.first_name}:</b> Its {name}, I saw {name} using vent')
await asyncio.sleep(3)
await text4.edit(f'<b>Others:</b> Okay.. Vote {name}')
await asyncio.sleep(2)
await stcr3.delete()
await text4.delete()
stcr4 = await client.send_sticker(message.chat.id, 'CAADAQADLwADnjOcH-wxu-ehy6NRAg')
event = await message.reply(f'{name} is ejected.......')
# Ejection animation
for _ in range(9):
await asyncio.sleep(0.5)
curr_pos = _ + 1
spaces_before = '' * curr_pos
await event.edit(f'{spaces_before}{"" * (9 - curr_pos)}')
await asyncio.sleep(0.5)
await event.edit('')
await asyncio.sleep(0.2)
await stcr4.delete()
if cmd == 'imp':
text = f".    。    •   ゚  。   .\n .      .     。   。 .  \n\n .    。   ඞ 。 .    •     •\n\n{name} was an Imposter. 。 .     。 . 。 . \n  . 。   . \n ' 0 Impostor remains   。 .   . 。 . 。   . 。   . . . , 。\n  ゚   .  . ,   。   .   . 。"
sticker_id = 'CAADAQADLQADnjOcH39IqwyR6Q_0Ag'
else:
text = f".    。    •   ゚  。   .\n .      .     。   。 .  \n\n .    。   ඞ 。 .    •     •\n\n{name} was not an Imposter. 。 .     。 . 。 . \n  . 。   . \n ' 1 Impostor remains   。 .   . 。 . 。   . 。   . . . , 。\n  ゚   .  . ,   。   .   . 。"
sticker_id = 'CAADAQADQAADnjOcH-WOkB8DEctJAg'
await event.edit(text)
await asyncio.sleep(4)
await event.delete()
await client.send_sticker(message.chat.id, sticker_id)
modules_help['amongus'] = {
'amongus': 'Create Among Us themed sticker [text/reply] [-c1 to -c12 for colors]',
'imposter': 'Create Among Us imposter image [username/reply]',
'imp': 'Create Among Us ejection animation (imposter)',
'impn': 'Create Among Us ejection animation (not imposter)',
}