Ejemplo n.º 1
0
async def graph_cmd(client, message):
    """plot provided function

	This command will run sympy `plot` and return result as image.
	You can add the `-3d` argument to plot in 3d (pass functions with 3 variables!)
	"""
    if len(message.command) < 1:
        return await edit_or_reply(message, "`[!] → ` No input")
    prog = ProgressChatAction(client,
                              message.chat.id,
                              action="upload_document")
    expr = message.command.text
    eq = []
    for a in expr.split(", "):
        eq.append(parse_expr(a).simplify())

    if message.command["-3d"]:
        plot3d(*eq, show=False).save("graph.png")
    else:
        plot(*eq, show=False).save("graph.png")

    await client.send_photo(message.chat.id,
                            "graph.png",
                            reply_to_message_id=message.message_id,
                            caption=f"` → {eq} `",
                            progress=prog.tick)
Ejemplo n.º 2
0
async def color_cmd(client, message):
    """send a solid color image

	Create a solid color image and send it.
	Color can be given as hex or by specifying each channel individally.
	Each channel can range from 0 to 256.
	"""
    clr = None
    if len(message.command) > 0:
        if len(message.command) > 2:
            clr = tuple([int(k) for k in message.command.arg[:3]])
        else:
            clr = message.command[0]
            if not clr.startswith("#"):
                clr = "#" + clr
    else:
        return await edit_or_reply(message, "`[!] → ` Not enough args given")
    prog = ProgressChatAction(client, message.chat.id, action="upload_photo")
    await prog.tick()
    image = Image.new("RGB", (200, 200), clr)
    color_io = io.BytesIO()
    color_io.name = "color.jpg"
    image.save(color_io, "JPEG")
    color_io.seek(0)
    await client.send_photo(message.chat.id,
                            color_io,
                            reply_to_message_id=message.message_id,
                            progress=prog.tick)
Ejemplo n.º 3
0
async def expr_cmd(client, message):
    """convert to LaTeX formula

	This command accepts sympy syntax and will generate a LaTeX formula as image.
	Add flag `-latex` to directly pass LaTeX.
	"""
    if len(message.command) < 1:
        return await edit_or_reply(message, "`[!] → ` No input")
    expr = message.command.text
    prog = ProgressChatAction(client,
                              message.chat.id,
                              action="upload_document")
    if message.command["-latex"]:
        preview(expr,
                viewer='file',
                filename='expr.png',
                dvioptions=[
                    "-T", "bbox", "-D 300", "--truecolor", "-bg", "Transparent"
                ])
    else:
        res = parse_expr(expr)
        preview(res,
                viewer='file',
                filename='expr.png',
                dvioptions=[
                    "-T", "bbox", "-D 300", "--truecolor", "-bg", "Transparent"
                ])
    await client.send_photo(message.chat.id,
                            "expr.png",
                            reply_to_message_id=message.message_id,
                            caption=f"` → {expr} `",
                            progress=prog.tick)
Ejemplo n.º 4
0
async def ascii_cmd(client, message):
	"""make ascii art of picture

	Roughly convert a picture into ascii art.
	You can specify width of the resulting image in characters as command argument (default is 120).
	If the requested width is lower than 50 characters,	the result will be printed directly into telegram. Else, a txt will be attached.
	Code comes from https://github.com/anuragrana/Python-Scripts/blob/master/image_to_ascii.py.
	"""
	msg = message
	if message.reply_to_message is not None:
		msg = message.reply_to_message
	prog = ProgressChatAction(client, message.chat.id, action="upload_document")
	width = int(message.command[0] or 120)
	if msg.media:
		fpath = await client.download_media(msg, file_name="toascii")
		image = Image.open(fpath)

		ascii_result = ascii_image(image, new_width=width)

		if width <= 50:
			await edit_or_reply(message, "``` →\n" + ascii_result + "```")
		else:
			out = io.BytesIO(ascii_result.encode('utf-8'))
			out.name = "ascii.txt"
			await client.send_document(message.chat.id, out, reply_to_message_id=message.message_id,
										caption=f"` → Made ASCII art `", progress=prog.tick)
	else:
		await edit_or_reply(message, "`[!] → ` you need to attach or reply to a file, dummy")
Ejemplo n.º 5
0
async def qrcode_cmd(client, message):
    """generate a qr code

	Make a qr code with given text.
	Size of specific boxes can be specified with `-box`, image border with `-border`, qrcode size with `-size`.
	QR colors can be specified too: background with `-b` and front color with `-f`
	"""
    if len(message.command) < 1:
        return await edit_or_reply(message, "`[!] → ` No input")
    text = message.command.text.replace("-delme", "")  # just in case
    size = int(message.command["size"]) if "size" in message.command else None
    box_size = int(message.command["boxsize"] or 10)
    border = int(message.command["border"] or 4)
    bg_color = message.command["back"] or "black"
    fg_color = message.command["front"] or "white"
    prog = ProgressChatAction(client, message.chat.id, action="upload_photo")
    await prog.tick()
    qr = qrcode.QRCode(
        version=size,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=box_size,
        border=border,
    )
    qr.add_data(text)
    qr.make(fit=True)

    image = qr.make_image(fill_color=fg_color, back_color=bg_color)
    qr_io = io.BytesIO()
    qr_io.name = "qrcode.jpg"
    image.save(qr_io, "JPEG")
    qr_io.seek(0)
    await client.send_photo(message.chat.id,
                            qr_io,
                            reply_to_message_id=message.message_id,
                            progress=prog.tick)
Ejemplo n.º 6
0
async def deepfry_cmd(client, message):
	"""deepfry an image

	Will deepfry an image (won't add "laser eyes").
	The number of frying rounds can be specified with `-c`. Will default to 1.
	Code from https://github.com/Ovyerus/deeppyer.
	"""
	target = message.reply_to_message if message.reply_to_message is not None else message
	prog = ProgressChatAction(client, message.chat.id, action="upload_photo")
	if target.media:
		msg = await edit_or_reply(message, "` → ` Downloading...")
		count = int(message.command["count"] or 1)
		fpath = await client.download_media(target, progress=prog.tick)
		msg.edit(get_text(message) + "\n` → ` Downloading [OK]\n` → ` Frying...")
		image = Image.open(fpath)

		for _ in range(count):
			await prog.tick()
			image = await fry_image(image)
		if message.from_user is not None and message.from_user.is_self:
			await msg.edit(get_text(message) +
				"\n` → ` Downloading [OK]\n` → ` Frying [OK]\n` → ` Uploading...")

		fried_io = io.BytesIO()
		fried_io.name = "fried.jpg"
		image.save(fried_io, "JPEG")
		fried_io.seek(0)
		await client.send_photo(message.chat.id, fried_io, reply_to_message_id=message.message_id,
									caption=f"` → Fried {count} time{'s' if count > 1 else ''}`", progress=prog.tick)
		if message.from_user is not None and message.from_user.is_self:
			await msg.edit(get_text(message) +
				"\n` → ` Downloading [OK]\n` → ` Frying [OK]\n` → ` Uploading [OK]")
		os.remove(fpath)
	else:
		await edit_or_reply(message, "`[!] → ` you need to attach or reply to a file, dummy")
Ejemplo n.º 7
0
async def meme_cmd(client, message):
	"""get a meme from collection

	If a name was specified, get meme matching requested name (regex). Otherwise, get random meme.
	Use flag `-list` to get all meme names and flag `-stats` to get count and disk usage.
	You can send a bunch of random memes together by specifying how many in the `-b` (batch) option \
	(only photos will be sent if a batch is requested).
	Memes can be any filetype.
	"""
	batchsize = max(min(int(message.command["batch"] or 10), 10), 2)
	reply_to = message.message_id
	if is_me(message) and message.reply_to_message is not None:
		reply_to = message.reply_to_message.message_id
	if message.command["-stats"]:
		memenumber = len(os.listdir("plugins/alemibot-tricks/data/meme"))
		proc_meme = await asyncio.create_subprocess_exec( # ewww this is not cross platform but will do for now
			"du", "-b", "plugins/alemibot-tricks/data/meme/",
			stdout=asyncio.subprocess.PIPE,
			stderr=asyncio.subprocess.STDOUT)
		stdout, _stderr = await proc_meme.communicate()
		memesize = float(stdout.decode('utf-8').split("\t")[0])
		await edit_or_reply(message, f"` → ` **{memenumber}** memes collected\n`  → ` folder size **{order_suffix(memesize)}**")
	elif message.command["-list"]:
		memes = os.listdir("plugins/alemibot-tricks/data/meme")
		memes.sort()
		out = f"` → ` **Meme list** ({len(memes)} total) :\n[ "
		out += ", ".join(memes)
		out += "]"
		await edit_or_reply(message, out)
	elif len(message.command) > 0 and (len(message.command) > 1 or message.command[0] != "-delme"):
		search = re.compile(message.command[0])
		found = []
		for meme in os.listdir("plugins/alemibot-tricks/data/meme"):
			if search.match(meme):
				found.append(meme)
		if len(found) > 1:
			await edit_or_reply(message, "`[!] → ` multiple memes match query\n" + "\n".join(f"`  → ` {meme}" for meme in found))
		elif len(found) == 1:
			meme = found[0]
			await send_media(client, message.chat.id, 'plugins/alemibot-tricks/data/meme/' + meme, reply_to_message_id=reply_to,
					caption=f"` → ` **{meme}**")
		elif len(found) < 1:
			await edit_or_reply(message, f"`[!] → ` no meme matching `{message.command[0]}`")
	else: 
		if "batch" in message.command:
			with ProgressChatAction(client, message.chat.id, action="upload_photo") as prog:
				pool = [ x for x in filter(lambda x: x.endswith((".jpg", ".jpeg", ".png")), os.listdir("plugins/alemibot-tricks/data/meme")) ]
				def pick(pool):
					pick = secrets.choice(pool)
					pool.remove(pick)
					return pick
				memes = [InputMediaPhoto("plugins/alemibot-tricks/data/meme/" + pick(pool)) for _ in range(batchsize)]
				await client.send_media_group(message.chat.id, memes)
		else:
			fname = secrets.choice(os.listdir("plugins/alemibot-tricks/data/meme"))
			await send_media(client, message.chat.id, 'plugins/alemibot-tricks/data/meme/' + fname, reply_to_message_id=reply_to,
					caption=f"` → ` [--random--] **{fname}**")
Ejemplo n.º 8
0
async def voice_cmd(client, message):
    """convert text to voice

	Create a voice message using Google Text to Speech.
	By default, english will be	used as lang, but another one can be specified with `-l`.
	You can add `-slow` flag to make the generated speech slower.
	TTS result will be converted to `.ogg`. You can skip this step and send as mp3 by adding the `-mp3` flag.
	You can add the `-file` flag to make tts of a replied to or attached text file.
	"""
    text = ""
    opts = {}
    from_file = bool(message.command["-file"])
    if message.reply_to_message is not None:
        if from_file and message.reply_to_message.media:
            fpath = await client.download_media(message.reply_to_message)
            with open(fpath) as f:
                text = f.read()
            os.remove(fpath)
        else:
            text = get_text(message.reply_to_message)
    elif from_file and message.media:
        fpath = await client.download_media(message)
        with open(fpath) as f:
            text = f.read()
        os.remove(fpath)
    elif len(message.command) > 0:
        text = re.sub(r"-delme(?: |)(?:[0-9]+|)", "", message.command.text)
    else:
        return await edit_or_reply(message, "`[!] → ` No text given")
    prog = ProgressChatAction(client, message.chat.id, action="record_audio")
    lang = message.command["lang"] or "en"
    slow = bool(message.command["-slow"])
    if message.reply_to_message is not None:
        opts["reply_to_message_id"] = message.reply_to_message.message_id
    elif not is_me(message):
        opts["reply_to_message_id"] = message.message_id
    await prog.tick()
    gTTS(text=text, lang=lang, slow=slow).save("data/tts.mp3")
    if message.command["-mp3"]:
        await client.send_audio(message.chat.id,
                                "data/tts.mp3",
                                progress=prog.tick,
                                **opts)
    else:
        AudioSegment.from_mp3("data/tts.mp3").export("data/tts.ogg",
                                                     format="ogg",
                                                     codec="libopus")
        await client.send_voice(message.chat.id,
                                "data/tts.ogg",
                                progress=prog.tick,
                                **opts)
Ejemplo n.º 9
0
async def steal_cmd(client, message):
	"""steal a meme

	Save a meme to collection.
	Either attach an image or reply to one.
	A name for the meme must be given (and must not contain spaces)
	Add flag `-pasta` to save given file (or message text) to copypasta directory
	"""
	is_pasta = message.command["-pasta"]
	dir_path = "pasta" if is_pasta else "meme"
	msg = message
	newname = message.command[0]
	# check if a file with this name already exists
	if newname in [ fname.rsplit(".", 1)[0] for fname in os.listdir(f"plugins/alemibot-tricks/data/{dir_path}/") ]:
		return await edit_or_reply(message, f"`[!] → ` {dir_path} with same name already exists")
	prog = ProgressChatAction(client, message.chat.id, action="record_video")
	if len(message.command) < 1:
		return await edit_or_reply(message, f"`[!] → ` No {dir_path} name provided")
	if message.reply_to_message:
		msg = message.reply_to_message
	if msg.media:
		fpath = await client.download_media(msg, progress=prog.tick) # + message.command[0])
		# await edit_or_reply(message, '` → ` saved meme as {}'.format(fpath))
		path, fname = os.path.splitext(fpath) # this part below is trash, im waiting for my PR on pyrogram
		extension = fname.split(".")
		if len(extension) > 1:
			extension = extension[1]
		else:
			extension = "txt" if is_pasta else "jpg" # cmon most memes will be jpg
		newname = newname + '.' + extension
		os.rename(fpath, f"plugins/alemibot-tricks/data/{dir_path}/{newname}")
		await edit_or_reply(message, f'` → ` saved {dir_path} as {newname}')
	elif message.command["-pasta"]:
		with open(f"plugins/alemibot-tricks/data/pasta/{message.command[0]}.txt", "w") as f:
			f.write(msg.text)
		await edit_or_reply(message, f'` → ` saved pasta as {message.command[0]}.txt')
	else:
		await edit_or_reply(message, "`[!] → ` No input")
Ejemplo n.º 10
0
async def webshot_cmd(client, message):
    """capture a website screenshot

	Will run headlessly firefox in background to create a screenshot, and then upload it.
	Add `-raw` to get the image as a document (uncompressed).
	"""
    if len(message.command) < 1:
        return await edit_or_reply(message, "`[!] → ` No input")
    executable = await check_firefox()
    if not executable:
        return await edit_or_reply(message, "`[!] → ` firefox not installed")
    url = message.command[0]
    if requests.head(url).status_code >= 400:
        return await edit_or_reply(message, "`[!] → ` Invalid URL")
    raw = bool(message.command["-raw"])
    with ProgressChatAction(
            client, message.chat.id,
            "upload_document" if raw else "upload_photo") as prog:
        proc = await asyncio.create_subprocess_exec(
            executable.strip(),
            "--screenshot",
            f"{os.getcwd()}/data/webshot.png",
            url,
            stderr=asyncio.subprocess.STDOUT,
            stdout=asyncio.subprocess.PIPE)
        stdout, _stderr = await proc.communicate()
        caption = f"`→ ` {url}"
        if raw:
            await client.send_document(message.chat.id,
                                       "data/webshot.png",
                                       progress=prog.tick,
                                       caption=caption)
        else:
            await client.send_photo(message.chat.id,
                                    "data/webshot.png",
                                    progress=prog.tick,
                                    caption=caption)
Ejemplo n.º 11
0
async def huggingface_cmd(client: Client, message: Message):
    """will query Huggingface Accelerated Interface API

	Requires an API key in bot config, under [huggingface] ( key = asdasdasd )
	Will query the Accelerated Interface Api with the provided token.
	The default model can be specified with `-m`. Default model will change depending on task
	Some specific tasks are pre-programmed as options:
	-	Use `-conv` to have a conversation (pass `--reset` as argument to reset ongoing). Defaults to `microsoft/DialoGPT-large`.
	-	Use `-ask` to make a question, and specify the context inside `()`. Defaults to `deepset/roberta-base-squad2`.
	-	Use `-sum` to make a summary of given text. Defaults to `facebook/bart-large-cnn`.
	-	Use `-sent` to get sentiment analysis of text. Defaults to `distilbert-base-uncased-finetuned-sst-2-english`.
	-	Use `-gen` to generate text starting from input. Defaults to `gpt2`.
	The API is capable of more tasks (like speech recognition, table searching, zero-shot classification) but \
	these functionalities are not yet implemented in this command.
	To access unsupported tasks, raw json input can be passed with no extra options. It will be fed as-is to requested model.
	If raw json is being passed, default model will be gpt2.
	Will report request time. This will include model load time and net latency. Add flag `-nowait` to fail if the model is not readily available.
	"""
    uid = get_user(message).id
    url = "https://api-inference.huggingface.co/models/"
    headers = {
        "Authorization":
        f"Bearer api_{alemiBot.config.get('huggingface', 'key', fallback='')}"
    }

    payload = {"wait_for_model": True, "inputs": {}}
    if message.command["-nowait"]:
        payload["wait_for_model"] = False

    if message.command["conversation"]:
        if message.command["conversation"] == "--reset":
            _CONV.pop(uid, None)
            return await edit_or_reply(message, "` → ` Cleared conversation")
        payload["inputs"] = (_CONV[uid] if uid in _CONV else {})
        payload["inputs"]["text"] = message.command["conversation"]
        model = "microsoft/DialoGPT-large"
    elif message.command["question"]:
        if "(" in message.command["question"]:
            question, context = message.command["question"].rsplit("(", 1)
            context = context.replace(")", "")
        else:
            question = message.command["question"]
            context = ""
        payload["inputs"] = {"question": question, "context": context}
        model = "deepset/roberta-base-squad2"
    elif message.command["summary"]:
        payload["inputs"] = message.command["summary"]
        model = "facebook/bart-large-cnn"
    elif message.command["sentiment"]:
        payload["inputs"] = message.command["sentiment"]
        model = "distilbert-base-uncased-finetuned-sst-2-english"
    elif message.command["generate"]:
        payload["inputs"] = message.command["generate"]
        model = "gpt2"
    else:
        if not message.command.text:
            return await edit_or_reply(message, "` → ` No input")
        payload = json.loads(message.command[0])
        model = "gpt2"

    if message.command["model"]:
        model = message.command["model"]

    before = time.time()
    with ProgressChatAction(client, message.chat.id, action="typing") as prog:
        async with aiohttp.ClientSession() as sess:
            async with sess.post(url + model, headers=headers,
                                 json=payload) as res:
                reply = await res.json()
    inference_time = time.time() - before

    if isinstance(reply, list):  # cheap trick, sometimes it comes as list
        reply = reply[0]

    if "error" in reply:
        return await edit_or_reply(
            message, f"` → ` [**{inference_time:.1f}**s] {reply['error']}")

    pre = f"` → ` [**{inference_time:.1f}**s] "

    if message.command["conversation"]:
        _CONV[uid] = reply["conversation"]
        await edit_or_reply(message, pre + reply["generated_text"])
    elif message.command["question"]:
        await edit_or_reply(message,
                            pre + f'{reply["answer"]} | {reply["score"]:.3f}')
    elif message.command["summary"]:
        await edit_or_reply(message, pre + reply["summary_text"])
    elif message.command["sentiment"]:
        first, second = reply  # really bad trick, couldn't you put it all in one dict????
        if first["score"] > second["score"]:
            await edit_or_reply(
                message, pre + f'{first["label"]} | {first["score"]:.3f}')
        else:
            await edit_or_reply(
                message, pre + f'{second["label"]} | {second["score"]:.3f}')
    elif message.command["generate"]:
        await edit_or_reply(message, pre + reply["generated_text"])
    else:
        await edit_or_reply(message,
                            pre + tokenize_json(json.dumps(reply, indent=2)))
Ejemplo n.º 12
0
async def pasta_cmd(client, message):
	"""drop a copypasta

	Give copypasta name or path to any file containing long text and bot will drop it in chat.
	List all saved copypastas with `-list` flag.
	Use flag `-stop` to stop ongoing pasta.
	A separator can be specified with `-s` to split the copypasta (for example, at newlines `\\n`).
	Long messages will still be split in chunks of 4096 characters due to telegram limit.
	Messages will be sent at an interval of 1 second by default. A different interval can be specified with `-i`.
	Add flag `-mono` to print pasta monospaced.
	Add flag `-edit` to always edit the first message instead of sending new ones.
	Reply to a message while invoking this command to have all pasta chunks reply to that message.
	"""
	if message.command["-stop"]:
		client.ctx.INTERRUPT_PASTA = True
		return
	if message.command["-list"]:
		return await edit_or_reply(message,\
			"\n".join(f"` → ` {pasta}" for pasta in os.listdir("plugins/alemibot-tricks/data/pasta/"))
		)
	if len(message.command) < 1:
		return await edit_or_reply(message, "`[!] → ` No input")
	repl_id = None
	if message.reply_to_message:
		repl_id = message.reply_to_message.message_id
	sep = message.command["separator"]
	intrv = float(message.command["interval"] or 1.0)
	monospace = bool(message.command["-mono"])
	edit_this = await client.send_message(message.chat.id, "` → ` Starting", reply_to_message_id=repl_id) \
			if bool(message.command["-edit"]) else None
	p_mode = 'html' if monospace else None
	# Find correct path
	path = message.command[0]
	try:
		pattern = re.compile(message.command[0])
		for pasta in os.listdir("plugins/alemibot-tricks/data/pasta"):
			if pattern.match(pasta):
				path = f"plugins/alemibot-tricks/data/pasta/{pasta}"
				break
	except re.error:
		pass
	# load text, make it a list so it's iterable
	with open(path, "rb") as f:
		text = [ f.read().decode('utf-8', 'ignore') ]
	# apply separator if requested
	if sep:
		text = re.split(sep, text[0])
	with ProgressChatAction(client, message.chat.id, action="typing") as prog:
		for section in text:
			for chunk in batchify(section, 4096):
				if len(chunk.strip()) < 1:
					continue
				if monospace:
					chunk = "<code>" + html.escape(chunk) + "</code>"
				if edit_this:
					await edit_this.edit(chunk, parse_mode=p_mode)
				else:
					await client.send_message(message.chat.id, chunk, parse_mode=p_mode, reply_to_message_id=repl_id)
				await asyncio.sleep(intrv)
				if client.ctx.INTERRUPT_PASTA:
					client.ctx.INTERRUPT_PASTA = False
					raise Exception("Interrupted by user")
		if edit_this:
			await edit_this.edit("` → ` Done")