`"
141 | "\nUsage: Creates a message that selfdestructs in x seconds."
142 | "\nKeep the seconds under 100 since it puts your bot to sleep.",
143 | }
144 | )
145 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ProjectAlf UserBot
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | ```
17 | /**
18 | Your Telegram account may get banned.
19 | I am not responsible for any improper use of this bot
20 | This bot is intended for the purpose of having fun with memes,
21 | as well as efficiently managing groups.
22 | You ended up spamming groups, getting reported left and right,
23 | and you ended up in a Finale Battle with Telegram and at the end
24 | Telegram Team deleted your account?
25 | And after that, then you pointed your fingers at us
26 | for getting your acoount deleted?
27 | I will be rolling on the floor laughing at you.
28 | /**
29 | ```
30 |
31 | A modular Telegram userbot running on Python3 with sqlalchemy database.
32 |
33 | Based on RaphielGang's [Telegram-Paperplane](https://github.com/RaphielGang/Telegram-Paperplane) And [ProjectDils](https://github.com/aidilaryanto/ProjectDils)
34 |
35 | ## How To Host
36 | The easiest way to deploy this userbot
37 | 
38 |
39 | ## Generate String
40 | Generate string using repl.it
41 | 
42 |
43 | ## Usefull guides
44 | How to deploy this UserBot
45 | 
46 |
47 | ## Groups and Support
48 | Join [Userbot Indonesia Channel](https://t.me/userbotindocloud) for update notifications or announcement.
49 |
50 | Join [Userbotindo Support Group](https://t.me/userbotindo) for discussion, bug reporting, and help.
51 |
52 | ## Credits
53 | * [RaphielGang](https://github.com/RaphielGang) - Telegram-Paperplane
54 | * [AvinashReddy3108](https://github.com/AvinashReddy3108) - PaperplaneExtended
55 | * [Mkaraniya](https://github.com/mkaraniya) & [Dev73](https://github.com/Devp73) - OpenUserBot
56 | * [Mr.Miss](https://github.com/keselekpermen69) - UserButt
57 | * [adekmaulana](https://github.com/adekmaulana) - ProjectBish
58 | * [MoveAngel](https://github.com/MoveAngel) - One4uBot
59 | * [AidilAryanto](https://github.com/aidilaryanto) - ProjectDils
60 | * [AnggaR69s](https://github.com/GengKapak/DCLXVI) - DCLXVI
61 | * [others](https://github.com/alfianandaa/ProjectAlf/graphs/contributors) that help to make this userbot awesome.
62 |
63 | ## License
64 | Licensed under [Raphielscape Public License](https://github.com/alfianandaa/ProjectAlf/blob/master/LICENSE) - Version 1.d, February 2020
65 |
--------------------------------------------------------------------------------
/userbot/modules/github.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 | from datetime import datetime
4 |
5 | import aiohttp
6 | from github import Github
7 |
8 | from userbot import CMD_HELP, GIT_REPO_NAME, GITHUB_ACCESS_TOKEN, bot
9 | from userbot.events import register
10 |
11 | GIT_TEMP_DIR = "./projectalf/temp/"
12 |
13 |
14 | @register(pattern=r"\.git (.*)", outgoing=True)
15 | async def github(event):
16 | URL = f"https://api.github.com/users/{event.pattern_match.group(1)}"
17 | await event.get_chat()
18 | async with aiohttp.ClientSession() as session:
19 | async with session.get(URL) as request:
20 | if request.status == 404:
21 | return await event.reply(
22 | "`" + event.pattern_match.group(1) + " not found`"
23 | )
24 |
25 | result = await request.json()
26 |
27 | url = result.get("html_url", None)
28 | name = result.get("name", None)
29 | company = result.get("company", None)
30 | bio = result.get("bio", None)
31 | created_at = result.get("created_at", "Not Found")
32 |
33 | REPLY = (
34 | f"GitHub Info for `{event.pattern_match.group(1)}`"
35 | f"\nUsername: `{name}`\nBio: `{bio}`\nURL: {url}"
36 | f"\nCompany: `{company}`\nCreated at: `{created_at}`"
37 | )
38 |
39 | if not result.get("repos_url", None):
40 | return await event.edit(REPLY)
41 | async with session.get(result.get("repos_url", None)) as request:
42 | result = request.json
43 | if request.status == 404:
44 | return await event.edit(REPLY)
45 |
46 | result = await request.json()
47 |
48 | REPLY += "\nRepos:\n"
49 |
50 | for nr in range(len(result)):
51 | REPLY += f"[{result[nr].get('name', None)}]({result[nr].get('html_url', None)})\n"
52 |
53 | await event.edit(REPLY)
54 |
55 |
56 | @register(outgoing=True, pattern=r"^\.commit(?: |$)(.*)")
57 | async def download(event):
58 | if event.fwd_from:
59 | return
60 | if GITHUB_ACCESS_TOKEN is None:
61 | await event.edit("`Please ADD Proper Access Token from github.com`")
62 | return
63 | if GIT_REPO_NAME is None:
64 | await event.edit("`Please ADD Proper Github Repo Name of your userbot`")
65 | return
66 | mone = await event.reply("Processing ...")
67 | if not os.path.isdir(GIT_TEMP_DIR):
68 | os.makedirs(GIT_TEMP_DIR)
69 | start = datetime.now()
70 | reply_message = await event.get_reply_message()
71 | try:
72 | time.time()
73 | print("Downloading to TEMP directory")
74 | downloaded_file_name = await bot.download_media(
75 | reply_message.media, GIT_TEMP_DIR
76 | )
77 | except Exception as e:
78 | await mone.edit(str(e))
79 | else:
80 | end = datetime.now()
81 | ms = (end - start).seconds
82 | await event.delete()
83 | await mone.edit(
84 | "Downloaded to `{}` in {} seconds.".format(downloaded_file_name, ms)
85 | )
86 | await mone.edit("Committing to Github....")
87 | await git_commit(downloaded_file_name, mone)
88 |
89 |
90 | async def git_commit(file_name, mone):
91 | content_list = []
92 | access_token = GITHUB_ACCESS_TOKEN
93 | g = Github(access_token)
94 | file = open(file_name, "r", encoding="utf-8")
95 | commit_data = file.read()
96 | repo = g.get_repo(GIT_REPO_NAME)
97 | print(repo.name)
98 | create_file = True
99 | contents = repo.get_contents("")
100 | for content_file in contents:
101 | content_list.append(str(content_file))
102 | print(content_file)
103 | for i in content_list:
104 | create_file = True
105 | if i == 'ContentFile(path="' + file_name + '")':
106 | return await mone.edit("`File Already Exists`")
107 | file_name = "userbot/modules/" + file_name
108 | if create_file:
109 | file_name = file_name.replace("./projectalf/temp/", "")
110 | print(file_name)
111 | try:
112 | repo.create_file(
113 | file_name, "ProjectAlf: Add new module", commit_data, branch="master"
114 | )
115 | print("Committed File")
116 | ccess = GIT_REPO_NAME
117 | ccess = ccess.strip()
118 | await mone.edit(
119 | f"`Commited On UserBot Repo`\n\n[Your Modules](https://github.com/{ccess}/tree/master/{file_name})"
120 | )
121 | except BaseException:
122 | print("Cannot Create Module")
123 | await mone.edit("Cannot Upload Module")
124 | else:
125 | return await mone.edit("`Committed Suicide`")
126 |
127 |
128 | CMD_HELP.update(
129 | {
130 | "github": ">`.git `"
131 | "\nUsage: Like .whois but for GitHub usernames."
132 | "\n\n>`.commit `"
133 | "\nUsage: GITHUB File Uploader."
134 | }
135 | )
136 |
--------------------------------------------------------------------------------
/userbot/modules/ascii.py:
--------------------------------------------------------------------------------
1 | # based on https://gist.github.com/wshanshan/c825efca4501a491447056849dd207d6
2 | # Ported for ProjectAlf by Alfiananda P.A
3 |
4 | import os
5 | import random
6 |
7 | import numpy as np
8 | from colour import Color
9 | from hachoir.metadata import extractMetadata
10 | from hachoir.parser import createParser
11 | from PIL import Image, ImageDraw, ImageFont
12 | from telethon.tl.types import DocumentAttributeFilename
13 |
14 | from userbot import CMD_HELP, bot
15 | from userbot.events import register
16 |
17 | bground = "black"
18 |
19 |
20 | @register(outgoing=True, pattern=r"^\.(ascii|asciis)$")
21 | async def ascii(event):
22 | if not event.reply_to_msg_id:
23 | await event.edit("`Reply to Any media..`")
24 | return
25 | reply_message = await event.get_reply_message()
26 | if not reply_message.media:
27 | await event.edit("`reply to a image/sticker/video`")
28 | return
29 | await event.edit("`Downloading Media..`")
30 | if reply_message.photo:
31 | IMG = await bot.download_media(
32 | reply_message,
33 | "ascii.png",
34 | )
35 | elif (
36 | DocumentAttributeFilename(file_name="AnimatedSticker.tgs")
37 | in reply_message.media.document.attributes
38 | ):
39 | await bot.download_media(
40 | reply_message,
41 | "ASCII.tgs",
42 | )
43 | os.system("lottie_convert.py ASCII.tgs ascii.png")
44 | IMG = "ascii.png"
45 | elif reply_message.video:
46 | video = await bot.download_media(
47 | reply_message,
48 | "ascii.mp4",
49 | )
50 | extractMetadata(createParser(video))
51 | os.system("ffmpeg -i ascii.mp4 -vframes 1 -an -s 480x360 -ss 1 ascii.png")
52 | IMG = "ascii.png"
53 | else:
54 | IMG = await bot.download_media(
55 | reply_message,
56 | "ascii.png",
57 | )
58 | try:
59 | await event.edit("`Processing..`")
60 | list = await random_color()
61 | color1 = list[0]
62 | color2 = list[1]
63 | bgcolor = bground
64 | await asciiart(IMG, color1, color2, bgcolor)
65 | cmd = event.pattern_match.group(1)
66 | if cmd == "asciis":
67 | os.system("cp ascii.png ascii.webp")
68 | ascii_file = "ascii.webp"
69 | else:
70 | ascii_file = "ascii.png"
71 | await event.client.send_file(
72 | event.chat_id,
73 | ascii_file,
74 | force_document=False,
75 | reply_to=event.reply_to_msg_id,
76 | )
77 | await event.delete()
78 | os.system("rm *.png *.webp *.mp4 *.tgs")
79 | except BaseException as e:
80 | os.system("rm *.png *.webp *.mp4 *.tgs")
81 | return await event.edit(str(e))
82 |
83 |
84 | async def asciiart(IMG, color1, color2, bgcolor):
85 | chars = np.asarray(list(" .,:irs?@9B"))
86 | font = ImageFont.load_default()
87 | letter_width = font.getsize("x")[0]
88 | letter_height = font.getsize("x")[1]
89 | WCF = letter_height / letter_width
90 | img = Image.open(IMG)
91 | widthByLetter = round(img.size[0] * 0.15 * WCF)
92 | heightByLetter = round(img.size[1] * 0.15)
93 | S = (widthByLetter, heightByLetter)
94 | img = img.resize(S)
95 | img = np.sum(np.asarray(img), axis=2)
96 | img -= img.min()
97 | img = (1.0 - img / img.max()) ** 2.2 * (chars.size - 1)
98 | lines = ("\n".join(("".join(r) for r in chars[img.astype(int)]))).split("\n")
99 | nbins = len(lines)
100 | colorRange = list(Color(color1).range_to(Color(color2), nbins))
101 | newImg_width = letter_width * widthByLetter
102 | newImg_height = letter_height * heightByLetter
103 | newImg = Image.new("RGBA", (newImg_width, newImg_height), bgcolor)
104 | draw = ImageDraw.Draw(newImg)
105 | leftpadding = 0
106 | y = 0
107 | lineIdx = 0
108 | for line in lines:
109 | color = colorRange[lineIdx]
110 | lineIdx += 1
111 | draw.text((leftpadding, y), line, color.hex, font=font)
112 | y += letter_height
113 | IMG = newImg.save("ascii.png")
114 | return IMG
115 |
116 |
117 | # this is from userge
118 | async def random_color():
119 | color = [
120 | "#" + "".join([random.choice("0123456789ABCDEF") for k in range(6)])
121 | for i in range(2)
122 | ]
123 | return color
124 |
125 |
126 | @register(outgoing=True, pattern=r"^\.asciibg(?: |$)(.*)")
127 | async def _(event):
128 | BG = event.pattern_match.group(1)
129 | if BG.isnumeric():
130 | return await event.edit("`Please input a color not a number!`")
131 | elif BG:
132 | global bground
133 | bground = BG
134 | else:
135 | return await event.edit("`please insert bg of ascii`")
136 | await event.edit(f"`Successfully set bg of ascii to` **{BG}**")
137 |
138 |
139 | CMD_HELP.update(
140 | {
141 | "ascii": ">`.ascii`\n"
142 | "Usage: create ascii art from media\n\n"
143 | ">`.asciis`\n"
144 | "Usage: same but upload the result as sticker\n\n"
145 | ">`.asciibg `\n"
146 | "Usage: to change background color of this ascii module"
147 | }
148 | )
149 |
--------------------------------------------------------------------------------
/userbot/modules/qrcode.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 The Raphielscape Company LLC.
2 | #
3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License");
4 | # you may not use this file except in compliance with the License.
5 | #
6 | # The entire source code is OSSRPL except 'makeqr and getqr' which is MPL
7 | # License: MPL and OSSRPL
8 |
9 | import asyncio
10 | import os
11 |
12 | import barcode
13 | import qrcode
14 | from barcode.writer import ImageWriter
15 | from bs4 import BeautifulSoup
16 |
17 | from userbot import CMD_HELP, LOGS
18 | from userbot.events import register
19 |
20 |
21 | @register(pattern=r"^\.decode$", outgoing=True)
22 | async def parseqr(qr_e):
23 | downloaded_file_name = await qr_e.client.download_media(
24 | await qr_e.get_reply_message()
25 | )
26 | # parse the Official ZXing webpage to decode the QRCode
27 | command_to_exec = [
28 | "curl",
29 | "-X",
30 | "POST",
31 | "-F",
32 | "f=@" + downloaded_file_name + "",
33 | "https://zxing.org/w/decode",
34 | ]
35 | process = await asyncio.create_subprocess_exec(
36 | *command_to_exec,
37 | # stdout must a pipe to be accessible as process.stdout
38 | stdout=asyncio.subprocess.PIPE,
39 | stderr=asyncio.subprocess.PIPE,
40 | )
41 | # Wait for the subprocess to finish
42 | stdout, stderr = await process.communicate()
43 | e_response = stderr.decode().strip()
44 | t_response = stdout.decode().strip()
45 | os.remove(downloaded_file_name)
46 | if not t_response:
47 | LOGS.info(e_response)
48 | LOGS.info(t_response)
49 | return await qr_e.edit("Failed to decode.")
50 | soup = BeautifulSoup(t_response, "html.parser")
51 | qr_contents = soup.find_all("pre")[0].text
52 | await qr_e.edit(qr_contents)
53 |
54 |
55 | @register(pattern=r"\.barcode(?: |$)([\s\S]*)", outgoing=True)
56 | async def bq(event):
57 | await event.edit("`Processing..`")
58 | input_str = event.pattern_match.group(1)
59 | message = "SYNTAX: `.barcode `"
60 | reply_msg_id = event.message.id
61 | if input_str:
62 | message = input_str
63 | elif event.reply_to_msg_id:
64 | previous_message = await event.get_reply_message()
65 | reply_msg_id = previous_message.id
66 | if previous_message.media:
67 | downloaded_file_name = await event.client.download_media(previous_message)
68 | m_list = None
69 | with open(downloaded_file_name, "rb") as fd:
70 | m_list = fd.readlines()
71 | message = ""
72 | for m in m_list:
73 | message += m.decode("UTF-8") + "\r\n"
74 | os.remove(downloaded_file_name)
75 | else:
76 | message = previous_message.message
77 | else:
78 | return event.edit("SYNTAX: `.barcode `")
79 |
80 | bar_code_type = "code128"
81 | try:
82 | bar_code_mode_f = barcode.get(bar_code_type, message, writer=ImageWriter())
83 | filename = bar_code_mode_f.save(bar_code_type)
84 | await event.client.send_file(event.chat_id, filename, reply_to=reply_msg_id)
85 | os.remove(filename)
86 | except Exception as e:
87 | return await event.edit(str(e))
88 | await event.delete()
89 |
90 |
91 | @register(pattern=r"\.makeqr(?: |$)([\s\S]*)", outgoing=True)
92 | async def make_qr(makeqr):
93 | input_str = makeqr.pattern_match.group(1)
94 | message = "SYNTAX: `.makeqr `"
95 | reply_msg_id = None
96 | if input_str:
97 | message = input_str
98 | elif makeqr.reply_to_msg_id:
99 | previous_message = await makeqr.get_reply_message()
100 | reply_msg_id = previous_message.id
101 | if previous_message.media:
102 | downloaded_file_name = await makeqr.client.download_media(previous_message)
103 | m_list = None
104 | with open(downloaded_file_name, "rb") as file:
105 | m_list = file.readlines()
106 | message = ""
107 | for media in m_list:
108 | message += media.decode("UTF-8") + "\r\n"
109 | os.remove(downloaded_file_name)
110 | else:
111 | message = previous_message.message
112 |
113 | qr = qrcode.QRCode(
114 | version=1,
115 | error_correction=qrcode.constants.ERROR_CORRECT_L,
116 | box_size=10,
117 | border=4,
118 | )
119 | qr.add_data(message)
120 | qr.make(fit=True)
121 | img = qr.make_image(fill_color="black", back_color="white")
122 | img.save("img_file.webp", "PNG")
123 | await makeqr.client.send_file(
124 | makeqr.chat_id, "img_file.webp", reply_to=reply_msg_id
125 | )
126 | os.remove("img_file.webp")
127 | await makeqr.delete()
128 |
129 |
130 | CMD_HELP.update(
131 | {
132 | "qr": ">`.makeqr `"
133 | "\nUsage: Make a QR Code from the given content."
134 | "\nExample: .makeqr www.google.com"
135 | "\nNote: use `.decode ` to get decoded content.",
136 | "barcode": ">`.barcode `"
137 | "\nUsage: Make a BarCode from the given content."
138 | "\nExample: .barcode www.google.com"
139 | "\nNote: use `.decode ` to get decoded content.",
140 | }
141 | )
142 |
--------------------------------------------------------------------------------
/userbot/modules/time.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 The Raphielscape Company LLC.
2 | #
3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License");
4 | # you may not use this file except in compliance with the License.
5 | #
6 |
7 | from datetime import datetime as dt
8 |
9 | from pytz import country_names as c_n
10 | from pytz import country_timezones as c_tz
11 | from pytz import timezone as tz
12 |
13 | from userbot import CMD_HELP, COUNTRY, TZ_NUMBER
14 | from userbot.events import register
15 |
16 |
17 | async def get_tz(con):
18 | if "(Uk)" in con:
19 | con = con.replace("Uk", "UK")
20 | if "(Us)" in con:
21 | con = con.replace("Us", "US")
22 | if " Of " in con:
23 | con = con.replace(" Of ", " of ")
24 | if "(Western)" in con:
25 | con = con.replace("(Western)", "(western)")
26 | if "Minor Outlying Islands" in con:
27 | con = con.replace("Minor Outlying Islands", "minor outlying islands")
28 | if "Nl" in con:
29 | con = con.replace("Nl", "NL")
30 |
31 | for c_code in c_n:
32 | if con == c_n[c_code]:
33 | return c_tz[c_code]
34 | try:
35 | if c_n[con]:
36 | return c_tz[con]
37 | except KeyError:
38 | return
39 |
40 |
41 | @register(outgoing=True, pattern=r"^\.time(?: |$)(.*)(? 4:
50 | try:
51 | c_name = c_n[con]
52 | except KeyError:
53 | c_name = con
54 | timezones = await get_tz(con)
55 | elif COUNTRY:
56 | c_name = COUNTRY
57 | tz_num = TZ_NUMBER
58 | timezones = await get_tz(COUNTRY)
59 | else:
60 | return await tdata.edit(f"`It's` **{dt.now().strftime(t_form)}** `here.`")
61 |
62 | if not timezones:
63 | return await tdata.edit("`Invaild country.`")
64 |
65 | if len(timezones) == 1:
66 | time_zone = timezones[0]
67 | elif len(timezones) > 1:
68 | if tz_num:
69 | tz_num = int(tz_num)
70 | time_zone = timezones[tz_num - 1]
71 | else:
72 | return_str = f"`{c_name} has multiple timezones:`\n\n"
73 |
74 | for i, item in enumerate(timezones):
75 | return_str += f"`{i+1}. {item}`\n"
76 |
77 | return_str += "\n`Choose one by typing the number "
78 | return_str += "in the command.`\n"
79 | return_str += f"`Example: .time {c_name} 2`"
80 |
81 | return await tdata.edit(return_str)
82 |
83 | dtnow = dt.now(tz(time_zone)).strftime(t_form)
84 |
85 | if c_name != COUNTRY:
86 | return await tdata.edit(
87 | f"`It's` **{dtnow}** `in {c_name}({time_zone} timezone).`"
88 | )
89 | elif COUNTRY:
90 | return await tdata.edit(
91 | f"`It's` **{dtnow}** `here, in {COUNTRY}" f"({time_zone} timezone).`"
92 | )
93 |
94 |
95 | @register(outgoing=True, pattern=r"^\.date(?: |$)(.*)(? 4:
104 | try:
105 | c_name = c_n[con]
106 | except KeyError:
107 | c_name = con
108 | timezones = await get_tz(con)
109 | elif COUNTRY:
110 | c_name = COUNTRY
111 | tz_num = TZ_NUMBER
112 | timezones = await get_tz(COUNTRY)
113 | else:
114 | return await dat.edit(f"`It's` **{dt.now().strftime(d_form)}** `here.`")
115 |
116 | if not timezones:
117 | return await dat.edit("`Invaild country.`")
118 |
119 | if len(timezones) == 1:
120 | time_zone = timezones[0]
121 | elif len(timezones) > 1:
122 | if tz_num:
123 | tz_num = int(tz_num)
124 | time_zone = timezones[tz_num - 1]
125 | else:
126 | return_str = f"`{c_name} has multiple timezones:`\n"
127 |
128 | for i, item in enumerate(timezones):
129 | return_str += f"`{i+1}. {item}`\n"
130 |
131 | return_str += "\n`Choose one by typing the number "
132 | return_str += "in the command.`\n"
133 | return_str += f"Example: .date {c_name} 2"
134 |
135 | return await dat.edit(return_str)
136 |
137 | dtnow = dt.now(tz(time_zone)).strftime(d_form)
138 |
139 | if c_name != COUNTRY:
140 | return await dat.edit(
141 | f"`It's` **{dtnow}** `in {c_name}({time_zone} timezone).`"
142 | )
143 | elif COUNTRY:
144 | return await dat.edit(
145 | f"`It's` **{dtnow}** `here, in {COUNTRY}" f"({time_zone} timezone).`"
146 | )
147 |
148 |
149 | CMD_HELP.update(
150 | {
151 | "time": ">`.time `"
152 | "\nUsage: Get the time of a country. If a country has "
153 | "multiple timezones, it will list all of them and let you select one.",
154 | "date": ">`.date `"
155 | "\nUsage: Get the date of a country. If a country has "
156 | "multiple timezones, it will list all of them and let you select one.",
157 | }
158 | )
159 |
--------------------------------------------------------------------------------
/userbot/modules/torrent_search.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2020 GengKapak and AnggaR96s.
2 | # All rights reserved.
3 | import codecs
4 | import json
5 | import os
6 |
7 | import requests
8 | from bs4 import BeautifulSoup as bs
9 |
10 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY
11 | from userbot.events import register
12 |
13 |
14 | @register(outgoing=True, pattern=r"^\.ts (.*)")
15 | async def gengkapak(e):
16 | await e.edit("`Please wait, fetching results...`")
17 | query = e.pattern_match.group(1)
18 | response = requests.get(
19 | f"https://sjprojectsapi.herokuapp.com/torrent/?query={query}"
20 | )
21 | ts = json.loads(response.text)
22 | if ts != response.json():
23 | await e.edit("**Some error occured**\n`Try Again Later`")
24 | return
25 | listdata = ""
26 | run = 0
27 | while True:
28 | try:
29 | run += 1
30 | r1 = ts[run]
31 | list1 = "<-----{}----->\nName: {}\nSeeders: {}\nSize: {}\nAge: {}\n<--Magnet Below-->\n{}\n\n\n".format(
32 | run, r1["name"], r1["seeder"], r1["size"], r1["age"], r1["magnet"]
33 | )
34 | listdata += list1
35 | except BaseException:
36 | break
37 |
38 | if not listdata:
39 | return await e.edit("`Error: No results found`")
40 |
41 | tsfileloc = f"{TEMP_DOWNLOAD_DIRECTORY}/{query}.txt"
42 | with open(tsfileloc, "w+", encoding="utf8") as out_file:
43 | out_file.write(str(listdata))
44 | fd = codecs.open(tsfileloc, "r", encoding="utf-8")
45 | data = fd.read()
46 | key = (
47 | requests.post("https://nekobin.com/api/documents", json={"content": data})
48 | .json()
49 | .get("result")
50 | .get("key")
51 | )
52 | url = f"https://nekobin.com/raw/{key}"
53 | caption = (
54 | f"`Here the results for the query: {query}`\n\nPasted to: [Nekobin]({url})"
55 | )
56 | os.remove(tsfileloc)
57 | await e.edit(caption, link_preview=False)
58 |
59 |
60 | def dogbin(magnets):
61 | counter = 0
62 | urls = []
63 | while counter != len(magnets):
64 | message = magnets[counter]
65 | url = "https://del.dog/documents"
66 | r = requests.post(url, data=message.encode("UTF-8")).json()
67 | url = f"https://del.dog/raw/{r['key']}"
68 | urls.append(url)
69 | counter += 1
70 | return urls
71 |
72 |
73 | @register(outgoing=True, pattern=r"^\.tos(?: |$)(.*)")
74 | async def tor_search(event):
75 | if event.fwd_from:
76 | return
77 | headers = {
78 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
79 | }
80 |
81 | search_str = event.pattern_match.group(1)
82 |
83 | print(search_str)
84 | await event.edit("Searching for " + search_str + ".....")
85 | if " " in search_str:
86 | search_str = search_str.replace(" ", "+")
87 | print(search_str)
88 | res = requests.get(
89 | "https://www.torrentdownloads.me/search/?new=1&s_cat=0&search="
90 | + search_str,
91 | headers,
92 | )
93 |
94 | else:
95 | res = requests.get(
96 | "https://www.torrentdownloads.me/search/?search=" + search_str, headers
97 | )
98 |
99 | source = bs(res.text, "lxml")
100 | urls = []
101 | magnets = []
102 | titles = []
103 | counter = 0
104 | for div in source.find_all("div", {"class": "grey_bar3 back_none"}):
105 | # print("https://www.torrentdownloads.me"+a['href'])
106 | try:
107 | title = div.p.a["title"]
108 | title = title[20:]
109 | titles.append(title)
110 | urls.append("https://www.torrentdownloads.me" + div.p.a["href"])
111 | except KeyError:
112 | pass
113 | except TypeError:
114 | pass
115 | except AttributeError:
116 | pass
117 | if counter == 11:
118 | break
119 | counter += 1
120 | if not urls:
121 | await event.edit("Either the Keyword was restricted or not found..")
122 | return
123 |
124 | print("Found URLS...")
125 | for url in urls:
126 | res = requests.get(url, headers)
127 | # print("URl: "+url)
128 | source = bs(res.text, "lxml")
129 | for div in source.find_all("div", {"class": "grey_bar1 back_none"}):
130 | try:
131 | mg = div.p.a["href"]
132 | magnets.append(mg)
133 | except Exception:
134 | pass
135 | print("Found Magnets...")
136 | shorted_links = dogbin(magnets)
137 | print("Dogged Magnets to del.dog...")
138 | msg = ""
139 | try:
140 | search_str = search_str.replace("+", " ")
141 | except BaseException:
142 | pass
143 | msg = "**Torrent Search Query**\n`{}`".format(search_str) + "\n**Results**\n"
144 | counter = 0
145 | while counter != len(titles):
146 | msg = (
147 | msg
148 | + "⁍ [{}]".format(titles[counter])
149 | + "({})".format(shorted_links[counter])
150 | + "\n\n"
151 | )
152 | counter += 1
153 | await event.edit(msg, link_preview=False)
154 |
155 |
156 | CMD_HELP.update(
157 | {
158 | "torrent": ">`.ts` Search query."
159 | "\nUsage: Search for torrent query and post to dogbin.\n\n"
160 | ">`.tos` Search query."
161 | "\nUsage: Search for torrent magnet from query."
162 | }
163 | )
164 |
--------------------------------------------------------------------------------
/userbot/modules/misc.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 The Raphielscape Company LLC.
2 | #
3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License");
4 | # you may not use this file except in compliance with the License.
5 | #
6 | # You can find misc modules, which dont fit in anything xD
7 |
8 | import io
9 | import sys
10 | from os import execl
11 | from random import randint
12 | from time import sleep
13 |
14 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, bot
15 | from userbot.events import register
16 | from userbot.utils import time_formatter
17 |
18 |
19 | @register(outgoing=True, pattern=r"^\.random")
20 | async def randomise(items):
21 | itemo = (items.text[8:]).split()
22 | if len(itemo) < 2:
23 | return await items.edit(
24 | "`2 or more items are required! Check .help random for more info.`"
25 | )
26 | index = randint(1, len(itemo) - 1)
27 | await items.edit(
28 | "**Query: **\n`" + items.text[8:] + "`\n**Output: **\n`" + itemo[index] + "`"
29 | )
30 |
31 |
32 | @register(outgoing=True, pattern=r"^\.sleep ([0-9]+)$")
33 | async def sleepybot(time):
34 | counter = int(time.pattern_match.group(1))
35 | await time.edit("`I am sulking and snoozing...`")
36 | if BOTLOG:
37 | str_counter = time_formatter(counter)
38 | await time.client.send_message(
39 | BOTLOG_CHATID,
40 | f"You put the bot to sleep for {str_counter}.",
41 | )
42 | sleep(counter)
43 | await time.edit("`OK, I'm awake now.`")
44 |
45 |
46 | @register(outgoing=True, pattern=r"^\.shutdown$")
47 | async def killthebot(event):
48 | await event.edit("`Goodbye...`")
49 | if BOTLOG:
50 | await event.client.send_message(BOTLOG_CHATID, "#SHUTDOWN \n" "Bot shut down")
51 | await bot.disconnect()
52 |
53 |
54 | @register(outgoing=True, pattern=r"^\.restart$")
55 | async def killdabot(event):
56 | await event.edit("`*i would be back in a moment*`")
57 | if BOTLOG:
58 | await event.client.send_message(BOTLOG_CHATID, "#RESTART \n" "Bot Restarted")
59 | await bot.disconnect()
60 | # Spin a new instance of bot
61 | execl(sys.executable, sys.executable, *sys.argv)
62 | # Shut the existing one down
63 | sys.exit()
64 |
65 |
66 | @register(outgoing=True, pattern=r"^\.readme$")
67 | async def reedme(e):
68 | await e.edit(
69 | "Here's something for you to read:\n"
70 | "\n[ProjectAlf's README.md file](https://github.com/alfianandaa/ProjectAlf/blob/master/README.md)"
71 | "\n[Setup Guide - Basic](https://telegra.ph/How-to-host-a-Telegram-Userbot-11-02)"
72 | "\n[Setup Guide - Google Drive](https://telegra.ph/How-To-Setup-Google-Drive-04-03)"
73 | "\n[Setup Guide - LastFM Module](https://telegra.ph/How-to-set-up-LastFM-module-for-Paperplane-userbot-11-02)"
74 | "\n[Video Tutorial - 576p](https://mega.nz/#!ErwCESbJ!1ZvYAKdTEfb6y1FnqqiLhHH9vZg4UB2QZNYL9fbQ9vs)"
75 | "\n[Video Tutorial - 1080p](https://mega.nz/#!x3JVhYwR!u7Uj0nvD8_CyyARrdKrFqlZEBFTnSVEiqts36HBMr-o)"
76 | "\n[Special - Note](https://telegra.ph/Special-Note-11-02)"
77 | )
78 |
79 |
80 | # Copyright (c) Gegham Zakaryan | 2019
81 | @register(outgoing=True, pattern=r"^\.repeat (.*)")
82 | async def repeat(rep):
83 | cnt, txt = rep.pattern_match.group(1).split(" ", 1)
84 | replyCount = int(cnt)
85 | toBeRepeated = txt
86 |
87 | replyText = toBeRepeated + "\n"
88 |
89 | for _ in range(replyCount - 1):
90 | replyText += toBeRepeated + "\n"
91 |
92 | await rep.edit(replyText)
93 |
94 |
95 | @register(outgoing=True, pattern=r"^\.repo$")
96 | async def repo_is_here(wannasee):
97 | await wannasee.edit(
98 | "[Here](https://github.com/alfianandaa/ProjectAlf) is ProjectAlf repo."
99 | )
100 |
101 |
102 | @register(outgoing=True, pattern=r"^\.raw$")
103 | async def raw(event):
104 | the_real_message = None
105 | reply_to_id = None
106 | if event.reply_to_msg_id:
107 | previous_message = await event.get_reply_message()
108 | the_real_message = previous_message.stringify()
109 | reply_to_id = event.reply_to_msg_id
110 | else:
111 | the_real_message = event.stringify()
112 | reply_to_id = event.message.id
113 | with io.BytesIO(str.encode(the_real_message)) as out_file:
114 | out_file.name = "raw_message_data.txt"
115 | await event.edit("`Check the userbot log for the decoded message data !!`")
116 | await event.client.send_file(
117 | BOTLOG_CHATID,
118 | out_file,
119 | force_document=True,
120 | allow_cache=False,
121 | reply_to=reply_to_id,
122 | caption="`Here's the decoded message data !!`",
123 | )
124 |
125 |
126 | CMD_HELP.update(
127 | {
128 | "random": ">`.random ... `"
129 | "\nUsage: Get a random item from the list of items.",
130 | "sleep": ">`.sleep `" "\nUsage: Let yours snooze for a few seconds.",
131 | "shutdown": ">`.shutdown`" "\nUsage: Shutdown bot",
132 | "repo": ">`.repo`" "\nUsage: Github Repo of this bot",
133 | "readme": ">`.readme`"
134 | "\nUsage: Provide links to setup the userbot and it's modules.",
135 | "repeat": ">`.repeat `"
136 | "\nUsage: Repeats the text for a number of times. Don't confuse this with spam tho.",
137 | "restart": ">`.restart`" "\nUsage: Restarts the bot !!",
138 | "raw": ">`.raw`"
139 | "\nUsage: Get detailed JSON-like formatted data about replied message.",
140 | }
141 | )
142 |
--------------------------------------------------------------------------------
/userbot/modules/transform.py:
--------------------------------------------------------------------------------
1 | # Authored by @Khrisna_Singhal
2 | # Ported from Userge by Alfiananda P.A
3 |
4 | import os
5 |
6 | from hachoir.metadata import extractMetadata
7 | from hachoir.parser import createParser
8 | from PIL import Image, ImageOps
9 | from telethon.tl.types import DocumentAttributeFilename
10 |
11 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY, bot
12 | from userbot.events import register
13 |
14 | Converted = TEMP_DOWNLOAD_DIRECTORY + "sticker.webp"
15 |
16 |
17 | @register(outgoing=True, pattern=r"^\.(mirror|flip|ghost|bw|poster)$")
18 | async def transform(event):
19 | if not event.reply_to_msg_id:
20 | await event.edit("`Reply to Any media..`")
21 | return
22 | reply_message = await event.get_reply_message()
23 | if not reply_message.media:
24 | await event.edit("`reply to a image/sticker`")
25 | return
26 | await event.edit("`Downloading Media..`")
27 | if reply_message.photo:
28 | transform = await bot.download_media(
29 | reply_message,
30 | "transform.png",
31 | )
32 | elif (
33 | DocumentAttributeFilename(file_name="AnimatedSticker.tgs")
34 | in reply_message.media.document.attributes
35 | ):
36 | await bot.download_media(
37 | reply_message,
38 | "transform.tgs",
39 | )
40 | os.system("lottie_convert.py transform.tgs transform.png")
41 | transform = "transform.png"
42 | elif reply_message.video:
43 | video = await bot.download_media(
44 | reply_message,
45 | "transform.mp4",
46 | )
47 | extractMetadata(createParser(video))
48 | os.system(
49 | "ffmpeg -i transform.mp4 -vframes 1 -an -s 480x360 -ss 1 transform.png"
50 | )
51 | transform = "transform.png"
52 | else:
53 | transform = await bot.download_media(
54 | reply_message,
55 | "transform.png",
56 | )
57 | try:
58 | await event.edit("`Transforming this media..`")
59 | cmd = event.pattern_match.group(1)
60 | im = Image.open(transform).convert("RGB")
61 | if cmd == "mirror":
62 | IMG = ImageOps.mirror(im)
63 | elif cmd == "flip":
64 | IMG = ImageOps.flip(im)
65 | elif cmd == "ghost":
66 | IMG = ImageOps.invert(im)
67 | elif cmd == "bw":
68 | IMG = ImageOps.grayscale(im)
69 | elif cmd == "poster":
70 | IMG = ImageOps.posterize(im, 2)
71 | IMG.save(Converted, quality=95)
72 | await event.client.send_file(
73 | event.chat_id, Converted, reply_to=event.reply_to_msg_id
74 | )
75 | await event.delete()
76 | os.system("rm *.mp4 *.tgs")
77 | os.remove(transform)
78 | os.remove(Converted)
79 | except BaseException:
80 | return
81 |
82 |
83 | @register(outgoing=True, pattern=r"^\.rotate(?: |$)(.*)")
84 | async def rotate(event):
85 | if not event.reply_to_msg_id:
86 | await event.edit("`Reply to any media..`")
87 | return
88 | reply_message = await event.get_reply_message()
89 | if not reply_message.media:
90 | await event.edit("`reply to a image/sticker`")
91 | return
92 | await event.edit("`Downloading Media..`")
93 | if reply_message.photo:
94 | rotate = await bot.download_media(
95 | reply_message,
96 | "transform.png",
97 | )
98 | elif (
99 | DocumentAttributeFilename(file_name="AnimatedSticker.tgs")
100 | in reply_message.media.document.attributes
101 | ):
102 | await bot.download_media(
103 | reply_message,
104 | "transform.tgs",
105 | )
106 | os.system("lottie_convert.py transform.tgs transform.png")
107 | rotate = "transform.png"
108 | elif reply_message.video:
109 | video = await bot.download_media(
110 | reply_message,
111 | "transform.mp4",
112 | )
113 | extractMetadata(createParser(video))
114 | os.system(
115 | "ffmpeg -i transform.mp4 -vframes 1 -an -s 480x360 -ss 1 transform.png"
116 | )
117 | rotate = "transform.png"
118 | else:
119 | rotate = await bot.download_media(
120 | reply_message,
121 | "transform.png",
122 | )
123 | try:
124 | value = int(event.pattern_match.group(1))
125 | if value > 360:
126 | raise ValueError
127 | except ValueError:
128 | value = 90
129 | await event.edit("`Rotating your media..`")
130 | im = Image.open(rotate).convert("RGB")
131 | IMG = im.rotate(value, expand=1)
132 | IMG.save(Converted, quality=95)
133 | await event.client.send_file(
134 | event.chat_id, Converted, reply_to=event.reply_to_msg_id
135 | )
136 | await event.delete()
137 | os.system("rm *.mp4 *.tgs")
138 | os.remove(rotate)
139 | os.remove(Converted)
140 |
141 |
142 | CMD_HELP.update(
143 | {
144 | "transform": ">`.ghost`"
145 | "\nUsage: Enchance your image to become a ghost!."
146 | "\n\n>`.flip`"
147 | "\nUsage: To flip your image"
148 | "\n\n>`.mirror`"
149 | "\nUsage: To mirror your image"
150 | "\n\n>`.bw`"
151 | "\nUsage: To Change your colorized image to b/w image!"
152 | "\n\n>`.poster`"
153 | "\nUsage: To posterize your image!"
154 | "\n\n>`.rotate `"
155 | "\nUsage: To rotate your image\n* The value is range 1-360 if not it'll give default value which is 90"
156 | }
157 | )
158 |
--------------------------------------------------------------------------------
/userbot/modules/whois.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 The Raphielscape Company LLC.
2 | #
3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License");
4 | # you may not use this file except in compliance with the License.
5 | #
6 | # The entire source code is OSSRPL except 'whois' which is MPL
7 | # License: MPL and OSSRPL
8 |
9 | import os
10 |
11 | from telethon.tl.functions.photos import GetUserPhotosRequest
12 | from telethon.tl.functions.users import GetFullUserRequest
13 | from telethon.tl.types import MessageEntityMentionName
14 | from telethon.utils import get_input_location
15 |
16 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY
17 | from userbot.events import register
18 |
19 |
20 | @register(pattern=r"^\.whois(?: |$)(.*)", outgoing=True)
21 | async def who(event):
22 |
23 | await event.edit(
24 | "`Sit tight while I steal some data from *Global Network Zone*...`"
25 | )
26 |
27 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY):
28 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY)
29 |
30 | replied_user = await get_user(event)
31 | if replied_user is None:
32 | await event.edit(
33 | "`This is anonymous admin in this group.\nCan't fetch the info`"
34 | )
35 | return
36 |
37 | try:
38 | photo, caption = await fetch_info(replied_user, event)
39 | except AttributeError:
40 | return await event.edit("`Could not fetch info of that user.`")
41 |
42 | message_id_to_reply = event.message.reply_to_msg_id
43 |
44 | if not message_id_to_reply:
45 | message_id_to_reply = None
46 |
47 | try:
48 | await event.client.send_file(
49 | event.chat_id,
50 | photo,
51 | caption=caption,
52 | link_preview=False,
53 | force_document=False,
54 | reply_to=message_id_to_reply,
55 | parse_mode="html",
56 | )
57 |
58 | if not photo.startswith("http"):
59 | os.remove(photo)
60 | await event.delete()
61 |
62 | except TypeError:
63 | await event.edit(caption, parse_mode="html")
64 |
65 |
66 | async def get_user(event):
67 | if event.reply_to_msg_id and not event.pattern_match.group(1):
68 | previous_message = await event.get_reply_message()
69 | if previous_message.from_id is None: # Anonymous admin seems don't have id attr
70 | return None
71 | replied_user = await event.client(GetFullUserRequest(previous_message.from_id))
72 | else:
73 | user = event.pattern_match.group(1)
74 |
75 | if user.isnumeric():
76 | user = int(user)
77 |
78 | if not user:
79 | self_user = await event.client.get_me()
80 | user = self_user.id
81 |
82 | if event.message.entities is not None:
83 | probable_user_mention_entity = event.message.entities[0]
84 |
85 | if isinstance(probable_user_mention_entity, MessageEntityMentionName):
86 | user_id = probable_user_mention_entity.user_id
87 | replied_user = await event.client(GetFullUserRequest(user_id))
88 | return replied_user
89 | try:
90 | user_object = await event.client.get_entity(user)
91 | replied_user = await event.client(GetFullUserRequest(user_object.id))
92 | except (TypeError, ValueError) as err:
93 | return await event.edit(str(err))
94 |
95 | return replied_user
96 |
97 |
98 | async def fetch_info(replied_user, event):
99 | replied_user_profile_photos = await event.client(
100 | GetUserPhotosRequest(
101 | user_id=replied_user.user.id, offset=42, max_id=0, limit=80
102 | )
103 | )
104 | replied_user_profile_photos_count = (
105 | "Person needs help with uploading profile picture."
106 | )
107 | try:
108 | replied_user_profile_photos_count = replied_user_profile_photos.count
109 | except AttributeError:
110 | pass
111 | user_id = replied_user.user.id
112 | first_name = replied_user.user.first_name
113 | last_name = replied_user.user.last_name
114 | try:
115 | dc_id, location = get_input_location(replied_user.profile_photo)
116 | except Exception as e:
117 | dc_id = "Couldn't fetch DC ID!"
118 | str(e)
119 | common_chat = replied_user.common_chats_count
120 | username = replied_user.user.username
121 | user_bio = replied_user.about
122 | is_bot = replied_user.user.bot
123 | restricted = replied_user.user.restricted
124 | verified = replied_user.user.verified
125 | photo = await event.client.download_profile_photo(
126 | user_id, TEMP_DOWNLOAD_DIRECTORY + str(user_id) + ".jpg", download_big=True
127 | )
128 | first_name = (
129 | first_name.replace("\u2060", "")
130 | if first_name
131 | else ("This User has no First Name")
132 | )
133 | last_name = (
134 | last_name.replace("\u2060", "") if last_name else ("This User has no Last Name")
135 | )
136 | username = "@{}".format(username) if username else ("This User has no Username")
137 | user_bio = "This User has no About" if not user_bio else user_bio
138 |
139 | caption = "USER INFO:\n\n"
140 | caption += f"First Name: {first_name}\n"
141 | caption += f"Last Name: {last_name}\n"
142 | caption += f"Username: {username}\n"
143 | caption += f"Data Centre ID: {dc_id}\n"
144 | caption += f"Number of Profile Pics: {replied_user_profile_photos_count}\n"
145 | caption += f"Is Bot: {is_bot}\n"
146 | caption += f"Is Restricted: {restricted}\n"
147 | caption += f"Is Verified by Telegram: {verified}\n"
148 | caption += f"ID: {user_id}\n\n"
149 | caption += f"Bio: \n{user_bio}\n\n"
150 | caption += f"Common Chats with this user: {common_chat}\n"
151 | caption += "Permanent Link To Profile: "
152 | caption += f'{first_name}'
153 |
154 | return photo, caption
155 |
156 |
157 | CMD_HELP.update(
158 | {
159 | "whois": ">`.whois or reply to someones text with .whois`"
160 | "\nUsage: Gets info of an user."
161 | }
162 | )
163 |
--------------------------------------------------------------------------------
/userbot/modules/notes.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 The Raphielscape Company LLC.
2 | #
3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License");
4 | # you may not use this file except in compliance with the License.
5 | #
6 |
7 | from asyncio import sleep
8 |
9 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP
10 | from userbot.events import register
11 |
12 |
13 | @register(outgoing=True, pattern=r"^\.notes$")
14 | async def notes_active(svd):
15 | try:
16 | from userbot.modules.sql_helper.notes_sql import get_notes
17 | except AttributeError:
18 | return await svd.edit("`Running on Non-SQL mode!`")
19 | message = "`There are no saved notes in this chat`"
20 | notes = get_notes(svd.chat_id)
21 | for note in notes:
22 | if message == "`There are no saved notes in this chat`":
23 | message = "Notes saved in this chat:\n"
24 | message += "`#{}`\n".format(note.keyword)
25 | await svd.edit(message)
26 |
27 |
28 | @register(outgoing=True, pattern=r"^\.clear (\w*)")
29 | async def remove_notes(clr):
30 | try:
31 | from userbot.modules.sql_helper.notes_sql import rm_note
32 | except AttributeError:
33 | return await clr.edit("`Running on Non-SQL mode!`")
34 | notename = clr.pattern_match.group(1)
35 | if rm_note(clr.chat_id, notename) is False:
36 | return await clr.edit("`Couldn't find note:` **{}**".format(notename))
37 | else:
38 | return await clr.edit("`Successfully deleted note:` **{}**".format(notename))
39 |
40 |
41 | @register(outgoing=True, pattern=r"^\.save (\w*)")
42 | async def add_note(fltr):
43 | try:
44 | from userbot.modules.sql_helper.notes_sql import add_note
45 | except AttributeError:
46 | return await fltr.edit("`Running on Non-SQL mode!`")
47 | keyword = fltr.pattern_match.group(1)
48 | string = fltr.text.partition(keyword)[2]
49 | msg = await fltr.get_reply_message()
50 | msg_id = None
51 | if msg and msg.media and not string:
52 | if BOTLOG_CHATID:
53 | await fltr.client.send_message(
54 | BOTLOG_CHATID,
55 | f"#NOTE\nCHAT ID: {fltr.chat_id}\nKEYWORD: {keyword}"
56 | "\n\nThe following message is saved as the note's reply data for the chat, please do NOT delete it !!",
57 | )
58 | msg_o = await fltr.client.forward_messages(
59 | entity=BOTLOG_CHATID, messages=msg, from_peer=fltr.chat_id, silent=True
60 | )
61 | msg_id = msg_o.id
62 | else:
63 | return await fltr.edit(
64 | "`Saving media as data for the note requires the BOTLOG_CHATID to be set.`"
65 | )
66 | elif fltr.reply_to_msg_id and not string:
67 | rep_msg = await fltr.get_reply_message()
68 | string = rep_msg.text
69 | success = "`Note {} successfully. Use` #{} `to get it`"
70 | if add_note(str(fltr.chat_id), keyword, string, msg_id) is False:
71 | return await fltr.edit(success.format("updated", keyword))
72 | else:
73 | return await fltr.edit(success.format("added", keyword))
74 |
75 |
76 | @register(pattern=r"#\w*", disable_edited=True, disable_errors=True, ignore_unsafe=True)
77 | async def incom_note(getnt):
78 | try:
79 | if not (await getnt.get_sender()).bot:
80 | try:
81 | from userbot.modules.sql_helper.notes_sql import get_note
82 | except AttributeError:
83 | return
84 | notename = getnt.text[1:]
85 | note = get_note(getnt.chat_id, notename)
86 | message_id_to_reply = getnt.message.reply_to_msg_id
87 | if not message_id_to_reply:
88 | message_id_to_reply = None
89 | if note:
90 | if note.f_mesg_id:
91 | msg_o = await getnt.client.get_messages(
92 | entity=BOTLOG_CHATID, ids=int(note.f_mesg_id)
93 | )
94 | await getnt.client.send_message(
95 | getnt.chat_id,
96 | msg_o.mesage,
97 | reply_to=message_id_to_reply,
98 | file=msg_o.media,
99 | )
100 | elif note.reply:
101 | await getnt.client.send_message(
102 | getnt.chat_id, note.reply, reply_to=message_id_to_reply
103 | )
104 | except AttributeError:
105 | pass
106 |
107 |
108 | @register(outgoing=True, pattern=r"^\.rmbotnotes (.*)")
109 | async def kick_marie_notes(kick):
110 | bot_type = kick.pattern_match.group(1).lower()
111 | if bot_type not in ["marie", "rose"]:
112 | return await kick.edit("`That bot is not yet supported!`")
113 | await kick.edit("```Will be kicking away all Notes!```")
114 | await sleep(3)
115 | resp = await kick.get_reply_message()
116 | filters = resp.text.split("-")[1:]
117 | for i in filters:
118 | if bot_type == "marie":
119 | await kick.reply("/clear %s" % (i.strip()))
120 | if bot_type == "rose":
121 | i = i.replace("`", "")
122 | await kick.reply("/clear %s" % (i.strip()))
123 | await sleep(0.3)
124 | await kick.respond("```Successfully purged bots notes yaay!```\n Gimme cookies!")
125 | if BOTLOG:
126 | await kick.client.send_message(
127 | BOTLOG_CHATID, "I cleaned all Notes at " + str(kick.chat_id)
128 | )
129 |
130 |
131 | CMD_HELP.update(
132 | {
133 | "notes": "`#`"
134 | "\nUsage: Gets the specified note."
135 | "\n\n>`.save ` or reply to a message with >`.save `"
136 | "\nUsage: Saves the replied message as a note with the notename. "
137 | "(Works with pics, docs, and stickers too!)"
138 | "\n\n>`.notes`"
139 | "\nUsage: Gets all saved notes in a chat."
140 | "\n\n>`.clear `"
141 | "\nUsage: Deletes the specified note."
142 | "\n\n>`.rmbotnotes `"
143 | "\nUsage: Removes all notes of admin bots"
144 | " (Currently supported: Marie, Rose and their clones.) in the chat."
145 | }
146 | )
147 |
--------------------------------------------------------------------------------
/userbot/modules/locks.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 The Raphielscape Company LLC.
2 | #
3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License");
4 | # you may not use this file except in compliance with the License.
5 |
6 | from telethon.tl.functions.messages import EditChatDefaultBannedRightsRequest
7 | from telethon.tl.types import ChatBannedRights
8 |
9 | from userbot import CMD_HELP
10 | from userbot.events import register
11 |
12 |
13 | @register(outgoing=True, pattern=r"^\.lock ?(.*)")
14 | async def locks(event):
15 | input_str = event.pattern_match.group(1).lower()
16 | peer_id = event.chat_id
17 | msg = None
18 | media = None
19 | sticker = None
20 | gif = None
21 | gamee = None
22 | ainline = None
23 | gpoll = None
24 | adduser = None
25 | cpin = None
26 | changeinfo = None
27 | if input_str == "msg":
28 | msg = True
29 | what = "messages"
30 | elif input_str == "media":
31 | media = True
32 | what = "media"
33 | elif input_str == "sticker":
34 | sticker = True
35 | what = "stickers"
36 | elif input_str == "gif":
37 | gif = True
38 | what = "GIFs"
39 | elif input_str == "game":
40 | gamee = True
41 | what = "games"
42 | elif input_str == "inline":
43 | ainline = True
44 | what = "inline bots"
45 | elif input_str == "poll":
46 | gpoll = True
47 | what = "polls"
48 | elif input_str == "invite":
49 | adduser = True
50 | what = "invites"
51 | elif input_str == "pin":
52 | cpin = True
53 | what = "pins"
54 | elif input_str == "info":
55 | changeinfo = True
56 | what = "chat info"
57 | elif input_str == "all":
58 | msg = True
59 | media = True
60 | sticker = True
61 | gif = True
62 | gamee = True
63 | ainline = True
64 | gpoll = True
65 | adduser = True
66 | cpin = True
67 | changeinfo = True
68 | what = "everything"
69 | else:
70 | if not input_str:
71 | return await event.edit("`I can't lock nothing !!`")
72 | else:
73 | return await event.edit(f"`Invalid lock type:` {input_str}")
74 |
75 | lock_rights = ChatBannedRights(
76 | until_date=None,
77 | send_messages=msg,
78 | send_media=media,
79 | send_stickers=sticker,
80 | send_gifs=gif,
81 | send_games=gamee,
82 | send_inline=ainline,
83 | send_polls=gpoll,
84 | invite_users=adduser,
85 | pin_messages=cpin,
86 | change_info=changeinfo,
87 | )
88 | try:
89 | await event.client(
90 | EditChatDefaultBannedRightsRequest(peer=peer_id, banned_rights=lock_rights)
91 | )
92 | await event.edit(f"`Locked {what} for this chat !!`")
93 | except BaseException as e:
94 | return await event.edit(
95 | f"`Do I have proper rights for that ??`\n**Error:** {str(e)}"
96 | )
97 |
98 |
99 | @register(outgoing=True, pattern=r"^\.unlock ?(.*)")
100 | async def rem_locks(event):
101 | input_str = event.pattern_match.group(1).lower()
102 | peer_id = event.chat_id
103 | msg = None
104 | media = None
105 | sticker = None
106 | gif = None
107 | gamee = None
108 | ainline = None
109 | gpoll = None
110 | adduser = None
111 | cpin = None
112 | changeinfo = None
113 | if input_str == "msg":
114 | msg = False
115 | what = "messages"
116 | elif input_str == "media":
117 | media = False
118 | what = "media"
119 | elif input_str == "sticker":
120 | sticker = False
121 | what = "stickers"
122 | elif input_str == "gif":
123 | gif = False
124 | what = "GIFs"
125 | elif input_str == "game":
126 | gamee = False
127 | what = "games"
128 | elif input_str == "inline":
129 | ainline = False
130 | what = "inline bots"
131 | elif input_str == "poll":
132 | gpoll = False
133 | what = "polls"
134 | elif input_str == "invite":
135 | adduser = False
136 | what = "invites"
137 | elif input_str == "pin":
138 | cpin = False
139 | what = "pins"
140 | elif input_str == "info":
141 | changeinfo = False
142 | what = "chat info"
143 | elif input_str == "all":
144 | msg = False
145 | media = False
146 | sticker = False
147 | gif = False
148 | gamee = False
149 | ainline = False
150 | gpoll = False
151 | adduser = False
152 | cpin = False
153 | changeinfo = False
154 | what = "everything"
155 | else:
156 | if not input_str:
157 | return await event.edit("`I can't unlock nothing !!`")
158 | else:
159 | return await event.edit(f"`Invalid unlock type:` {input_str}")
160 |
161 | unlock_rights = ChatBannedRights(
162 | until_date=None,
163 | send_messages=msg,
164 | send_media=media,
165 | send_stickers=sticker,
166 | send_gifs=gif,
167 | send_games=gamee,
168 | send_inline=ainline,
169 | send_polls=gpoll,
170 | invite_users=adduser,
171 | pin_messages=cpin,
172 | change_info=changeinfo,
173 | )
174 | try:
175 | await event.client(
176 | EditChatDefaultBannedRightsRequest(
177 | peer=peer_id, banned_rights=unlock_rights
178 | )
179 | )
180 | await event.edit(f"`Unlocked {what} for this chat !!`")
181 | except BaseException as e:
182 | return await event.edit(
183 | f"`Do I have proper rights for that ??`\n**Error:** {str(e)}"
184 | )
185 |
186 |
187 | CMD_HELP.update(
188 | {
189 | "locks": ">`.lock ` or >`.unlock `"
190 | "\nUsage: Allows you to lock/unlock some common message types in the chat."
191 | "\n[NOTE: Requires proper admin rights in the chat !!]"
192 | "\n\nAvailable message types to lock/unlock are: "
193 | "\n`all, msg, media, sticker, gif, game, inline, poll, invite, pin, info`"
194 | }
195 | )
196 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | RAPHIELSCAPE PUBLIC LICENSE
2 | Version 1.d, February 2020
3 |
4 | Copyright (C) 2020 Devscapes Open Source Holding GmbH.
5 |
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, and changing it is prohibited.
8 |
9 | RAPHIELSCAPE PUBLIC LICENSE
10 | A-1. DEFINITIONS
11 |
12 | 0. “This License” refers to version 1.d of the Raphielscape Public License.
13 |
14 | 1. “Copyright” also means copyright-like laws that apply to other kinds of works.
15 |
16 | 2. “The Work" refers to any copyrightable work licensed under this License.
17 | Each licensee is addressed as “you”. “Licensees” and “recipients” may be
18 | individuals or organizations.
19 |
20 | 3. To “modify” a work means to copy from or adapt all or part of the work
21 | in a fashion requiring copyright permission, other than the making of
22 | an exact copy. The resulting work is called a “modified version” of
23 | the earlier work or a work “based on” the earlier work.
24 |
25 | 4. Source Form. The “source form” for a work means the preferred form
26 | of the work for making modifications to it. “Object code” means any
27 | non-source form of a work.
28 |
29 | The “Corresponding Source” for a work in object code form means all
30 | the source code needed to generate, install, and (for an executable work)
31 | run the object code and to modify the work, including scripts to control
32 | those activities.
33 |
34 | The Corresponding Source need not include anything that users can
35 | regenerate automatically from other parts of the Corresponding Source.
36 | The Corresponding Source for a work in source code form is that same work.
37 |
38 | 5. "The author" refers to "author" of the code, which is the one that made
39 | the particular code that exists inside of the Corresponding Source.
40 |
41 | 6. "Owner" refers to any parties which are owning the Corresponding Source.
42 |
43 | 7. "Maintainers" refers to any parties which are keeping in existence or
44 | continuance, preserving and retaining The Work and the Corresponding Source.
45 |
46 | 8. “Deprecation” refers to an act of The author and Owner without Maintainers'
47 | agreement to discontinuing the maintainership of The Work.
48 |
49 | 9. "Discontinuation" refers to all Maintainers, The Author, and Owner to
50 | discontinuing the maintainership of The Work.
51 |
52 | 10. "Upstream" refers to the place or site where The Work and the
53 | Corresponding Source getting worked on and where all Maintainers,
54 | The Author, and Owner keeping the existence, continuance, preservation,
55 | and retainment of The Work and Corresponding Source.
56 |
57 | A-2. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
58 |
59 | 0. You must give any other recipients of the Work or Derivative
60 | Works a copy of this License; and
61 |
62 | 1. You must cause any modified files to carry prominent notices
63 | stating that You changed the files; and
64 |
65 | 2. You must retain, in the Source form of any Derivative Works
66 | that You distribute, this license, all copyright, patent, trademark,
67 | authorships, and attribution notices from the Source form of the Work; and
68 |
69 | 3. You must cause the maintainers of the works to democratically
70 | selecting the new Owner in case of Deprecation with the Signoffs from
71 | all Maintainers and final Signoff from The Author of The Work and the
72 | Corresponding Source.
73 |
74 | If the works are Discontinued, the Owner should archive The Work and
75 | the Corresponding Source or optionally removing The Work entirely and
76 | may stop the distribution of The Work and the Corresponding Source.
77 |
78 | The Owner or The Author may give The Work or the Corresponding Source
79 | to a specific person for a new maintainership structure in case
80 | The Owner, Author, and The Maintainers failed to democratically
81 | selecting a new Owner to continuing, preserving and retaining
82 | The Work and the Corresponding Source; and
83 |
84 | 4. Respecting the author and owner of works that are distributed in
85 | any way. In the means that decisions that are taken by Upstream are
86 | immediately imposed on both Upstream and Modified Version of
87 | The Works and Corresponding Source.
88 |
89 | Any use, reproduction, or distribution of Your modifications, or
90 | for any such Derivative Works as a whole, provided Your use, reproduction,
91 | and distribution of the Work should comply with the conditions stated in
92 | this License.
93 |
94 | B. DISCLAIMER OF WARRANTY
95 |
96 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
97 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
98 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
99 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
100 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
101 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
102 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
103 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
104 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
105 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
106 |
107 |
108 | C. REVISED VERSION OF THIS LICENSE
109 |
110 | The Devscapes Open Source Holding GmbH. may publish revised and/or new versions
111 | of the Raphielscape Public License from time to time. Such new versions will be
112 | similar in spirit to the present version but may differ in detail to address new
113 | problems or concerns.
114 |
115 | Each version is given a distinguishing version number. If the Program specifies
116 | that a certain numbered version of the Raphielscape Public License
117 | "or any later version" applies to it, you have the option of following the terms
118 | and conditions either of that numbered version or of any later version published
119 | by the Devscapes Open Source Holding GmbH. If the Program does not specify a
120 | version number of the Raphielscape Public License, you may use the latest version
121 | published by the Devscapes Open Source Holding GmbH.
122 |
123 | END OF LICENSE
124 |
--------------------------------------------------------------------------------
/userbot/modules/filter.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 The Raphielscape Company LLC.
2 | #
3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License");
4 | # you may not use this file except in compliance with the License.
5 | #
6 |
7 | from asyncio import sleep
8 | from re import IGNORECASE, escape, search
9 |
10 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP
11 | from userbot.events import register
12 |
13 |
14 | @register(incoming=True, disable_edited=True, disable_errors=True)
15 | async def filter_incoming_handler(handler):
16 | try:
17 | if not (await handler.get_sender()).bot:
18 | try:
19 | from userbot.modules.sql_helper.filter_sql import get_filters
20 | except AttributeError:
21 | await handler.edit("`Running on Non-SQL mode!`")
22 | return
23 | name = handler.raw_text
24 | filters = get_filters(handler.chat_id)
25 | if not filters:
26 | return
27 | for trigger in filters:
28 | pattern = r"( |^|[^\w])" + escape(trigger.keyword) + r"( |$|[^\w])"
29 | pro = search(pattern, name, flags=IGNORECASE)
30 | if pro:
31 | if trigger.f_mesg_id:
32 | msg_o = await handler.client.get_messages(
33 | entity=BOTLOG_CHATID, ids=int(trigger.f_mesg_id)
34 | )
35 | await handler.reply(msg_o.message, file=msg_o.media)
36 | elif trigger.reply:
37 | await handler.reply(trigger.reply)
38 | except AttributeError:
39 | pass
40 |
41 |
42 | @register(outgoing=True, pattern=r"^\.filter (.*)")
43 | async def add_new_filter(new_handler):
44 | try:
45 | from userbot.modules.sql_helper.filter_sql import add_filter
46 | except AttributeError:
47 | await new_handler.edit("`Running on Non-SQL mode!`")
48 | return
49 | value = new_handler.pattern_match.group(1).split(None, 1)
50 | keyword = value[0]
51 | try:
52 | string = value[1]
53 | except IndexError:
54 | string = None
55 | msg = await new_handler.get_reply_message()
56 | msg_id = None
57 | if msg and msg.media and not string:
58 | if BOTLOG_CHATID:
59 | await new_handler.client.send_message(
60 | BOTLOG_CHATID,
61 | f"#FILTER\nCHAT ID: {new_handler.chat_id}\nTRIGGER: {keyword}"
62 | "\n\nThe following message is saved as the filter's reply data for the chat, please do NOT delete it !!",
63 | )
64 | msg_o = await new_handler.client.forward_messages(
65 | entity=BOTLOG_CHATID,
66 | messages=msg,
67 | from_peer=new_handler.chat_id,
68 | silent=True,
69 | )
70 | msg_id = msg_o.id
71 | else:
72 | return await new_handler.edit(
73 | "`Saving media as reply to the filter requires the BOTLOG_CHATID to be set.`"
74 | )
75 | elif new_handler.reply_to_msg_id and not string:
76 | rep_msg = await new_handler.get_reply_message()
77 | string = rep_msg.text
78 | success = "`Filter` **{}** `{} successfully`."
79 | if add_filter(str(new_handler.chat_id), keyword, string, msg_id) is True:
80 | await new_handler.edit(success.format(keyword, "added"))
81 | else:
82 | await new_handler.edit(success.format(keyword, "updated"))
83 |
84 |
85 | @register(outgoing=True, pattern=r"^\.stop (.*)")
86 | async def remove_a_filter(r_handler):
87 | try:
88 | from userbot.modules.sql_helper.filter_sql import remove_filter
89 | except AttributeError:
90 | return await r_handler.edit("`Running on Non-SQL mode!`")
91 | filt = r_handler.pattern_match.group(1)
92 | if not remove_filter(r_handler.chat_id, filt):
93 | await r_handler.edit("`Filter` **{}** `doesn't exist`.".format(filt))
94 | else:
95 | await r_handler.edit(
96 | "`Filter` **{}** `was deleted successfully`.".format(filt)
97 | )
98 |
99 |
100 | @register(outgoing=True, pattern=r"^\.rmbotfilters (.*)")
101 | async def kick_marie_filter(event):
102 | event.text[0]
103 | bot_type = event.pattern_match.group(1).lower()
104 | if bot_type not in ["marie", "rose"]:
105 | return await event.edit("`That bot is not yet supported!`")
106 | await event.edit("```Will be kicking away all Filters!```")
107 | await sleep(3)
108 | resp = await event.get_reply_message()
109 | filters = resp.text.split("-")[1:]
110 | for i in filters:
111 | if bot_type.lower() == "marie":
112 | await event.reply("/stop %s" % (i.strip()))
113 | if bot_type.lower() == "rose":
114 | i = i.replace("`", "")
115 | await event.reply("/stop %s" % (i.strip()))
116 | await sleep(0.3)
117 | await event.respond("```Successfully purged bots filters yaay!```\n Gimme cookies!")
118 | if BOTLOG:
119 | await event.client.send_message(
120 | BOTLOG_CHATID, "I cleaned all filters at " + str(event.chat_id)
121 | )
122 |
123 |
124 | @register(outgoing=True, pattern=r"^\.filters$")
125 | async def filters_active(event):
126 | try:
127 | from userbot.modules.sql_helper.filter_sql import get_filters
128 | except AttributeError:
129 | return await event.edit("`Running on Non-SQL mode!`")
130 | transact = "`There are no filters in this chat.`"
131 | filters = get_filters(event.chat_id)
132 | for filt in filters:
133 | if transact == "`There are no filters in this chat.`":
134 | transact = "Active filters in this chat:\n"
135 | transact += "`{}`\n".format(filt.keyword)
136 | await event.edit(transact)
137 |
138 |
139 | CMD_HELP.update(
140 | {
141 | "filter": ">`.filters`"
142 | "\nUsage: Lists all active userbot filters in a chat."
143 | "\n\n>`.filter ` or reply to a message with >`.filter `"
144 | "\nUsage: Saves the replied message as a reply to the 'keyword'."
145 | "\nThe bot will reply to the message whenever 'keyword' is mentioned."
146 | "\nWorks with everything from files to stickers."
147 | "\n\n>`.stop `"
148 | "\nUsage: Stops the specified filter."
149 | "\n\n>`.rmbotfilters `"
150 | "\nUsage: Removes all filters of admin bots (Currently supported: Marie, Rose and their clones.) in the chat."
151 | }
152 | )
153 |
--------------------------------------------------------------------------------
/userbot/modules/dogbin.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 The Raphielscape Company LLC.
2 | #
3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License");
4 | # you may not use this file except in compliance with the License.
5 | #
6 |
7 | import os
8 |
9 | from requests import exceptions, get, post
10 |
11 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, TEMP_DOWNLOAD_DIRECTORY
12 | from userbot.events import register
13 |
14 | DOGBIN_URL = "https://del.dog/"
15 | NEKOBIN_URL = "https://nekobin.com/"
16 |
17 |
18 | @register(outgoing=True, pattern=r"^\.paste(?: |$)([\s\S]*)")
19 | async def paste(pstl):
20 | dogbin_final_url = ""
21 | match = pstl.pattern_match.group(1).strip()
22 | reply_id = pstl.reply_to_msg_id
23 |
24 | if not match and not reply_id:
25 | return await pstl.edit("`Elon Musk said I cannot paste void.`")
26 |
27 | if match:
28 | message = match
29 | elif reply_id:
30 | message = await pstl.get_reply_message()
31 | if message.media:
32 | downloaded_file_name = await pstl.client.download_media(
33 | message,
34 | TEMP_DOWNLOAD_DIRECTORY,
35 | )
36 | m_list = None
37 | with open(downloaded_file_name, "rb") as fd:
38 | m_list = fd.readlines()
39 | message = ""
40 | for m in m_list:
41 | message += m.decode("UTF-8")
42 | os.remove(downloaded_file_name)
43 | else:
44 | message = message.message
45 |
46 | # Dogbin
47 | await pstl.edit("`Pasting text . . .`")
48 | resp = post(DOGBIN_URL + "documents", data=message.encode("utf-8"))
49 |
50 | if resp.status_code == 200:
51 | response = resp.json()
52 | key = response["key"]
53 | dogbin_final_url = DOGBIN_URL + key
54 |
55 | if response["isUrl"]:
56 | reply_text = (
57 | "`Pasted successfully!`\n\n"
58 | f"[Shortened URL]({dogbin_final_url})\n\n"
59 | "`Original(non-shortened) URLs`\n"
60 | f"[Dogbin URL]({DOGBIN_URL}v/{key})\n"
61 | f"[View RAW]({DOGBIN_URL}raw/{key})"
62 | )
63 | else:
64 | reply_text = (
65 | "`Pasted successfully!`\n\n"
66 | f"[Dogbin URL]({dogbin_final_url})\n"
67 | f"[View RAW]({DOGBIN_URL}raw/{key})"
68 | )
69 | else:
70 | reply_text = "`Failed to reach Dogbin`"
71 |
72 | await pstl.edit(reply_text)
73 | if BOTLOG:
74 | await pstl.client.send_message(
75 | BOTLOG_CHATID,
76 | "Paste query was executed successfully",
77 | )
78 |
79 |
80 | @register(outgoing=True, pattern=r"^\.getpaste(?: |$)(.*)")
81 | async def get_dogbin_content(dog_url):
82 | textx = await dog_url.get_reply_message()
83 | message = dog_url.pattern_match.group(1)
84 | await dog_url.edit("`Getting dogbin content...`")
85 |
86 | if textx:
87 | message = str(textx.message)
88 |
89 | format_normal = f"{DOGBIN_URL}"
90 | format_view = f"{DOGBIN_URL}v/"
91 |
92 | if message.startswith(format_view):
93 | message = message[len(format_view) :]
94 | elif message.startswith(format_normal):
95 | message = message[len(format_normal) :]
96 | elif message.startswith("del.dog/"):
97 | message = message[len("del.dog/") :]
98 | else:
99 | return await dog_url.edit("`Is that even a dogbin url?`")
100 |
101 | resp = get(f"{DOGBIN_URL}raw/{message}")
102 |
103 | try:
104 | resp.raise_for_status()
105 | except exceptions.HTTPError as HTTPErr:
106 | await dog_url.edit(
107 | "Request returned an unsuccessful status code.\n\n" + str(HTTPErr)
108 | )
109 | return
110 | except exceptions.Timeout as TimeoutErr:
111 | await dog_url.edit("Request timed out." + str(TimeoutErr))
112 | return
113 | except exceptions.TooManyRedirects as RedirectsErr:
114 | await dog_url.edit(
115 | "Request exceeded the configured number of maximum redirections."
116 | + str(RedirectsErr)
117 | )
118 | return
119 |
120 | reply_text = (
121 | "`Fetched dogbin URL content successfully!`" "\n\n`Content:` " + resp.text
122 | )
123 |
124 | await dog_url.edit(reply_text)
125 | if BOTLOG:
126 | await dog_url.client.send_message(
127 | BOTLOG_CHATID,
128 | "Get dogbin content query was executed successfully",
129 | )
130 |
131 |
132 | @register(outgoing=True, pattern=r"^\.neko(?: |$)([\s\S]*)")
133 | async def neko(nekobin):
134 | """For .paste command, pastes the text directly to dogbin."""
135 | nekobin_final_url = ""
136 | match = nekobin.pattern_match.group(1).strip()
137 | reply_id = nekobin.reply_to_msg_id
138 |
139 | if not match and not reply_id:
140 | return await pstl.edit("`Cannot paste text.`")
141 |
142 | if match:
143 | message = match
144 | elif reply_id:
145 | message = await nekobin.get_reply_message()
146 | if message.media:
147 | downloaded_file_name = await nekobin.client.download_media(
148 | message,
149 | TEMP_DOWNLOAD_DIRECTORY,
150 | )
151 | m_list = None
152 | with open(downloaded_file_name, "rb") as fd:
153 | m_list = fd.readlines()
154 | message = ""
155 | for m in m_list:
156 | message += m.decode("UTF-8")
157 | os.remove(downloaded_file_name)
158 | else:
159 | message = message.text
160 |
161 | # Nekobin
162 | await nekobin.edit("`Pasting text . . .`")
163 | resp = post(NEKOBIN_URL + "api/documents", json={"content": message})
164 |
165 | if resp.status_code == 201:
166 | response = resp.json()
167 | key = response["result"]["key"]
168 | nekobin_final_url = NEKOBIN_URL + key
169 | reply_text = (
170 | "`Pasted successfully!`\n\n"
171 | f"[Nekobin URL]({nekobin_final_url})\n"
172 | f"[View RAW]({NEKOBIN_URL}raw/{key})"
173 | )
174 | else:
175 | reply_text = "`Failed to reach Nekobin`"
176 |
177 | await nekobin.edit(reply_text)
178 | if BOTLOG:
179 | await nekobin.client.send_message(
180 | BOTLOG_CHATID,
181 | "Paste query was executed successfully",
182 | )
183 |
184 |
185 | CMD_HELP.update(
186 | {
187 | "dogbin": ">`.paste `"
188 | "\nUsage: Create a paste or a shortened url using dogbin (https://del.dog/)"
189 | "\n\n>`.getpaste`"
190 | "\nUsage: Gets the content of a paste or shortened url from dogbin (https://del.dog/)"
191 | "\n\n>`.neko `"
192 | "\nUsage: Create a paste or a shortened url using nekobin (https://nekobin.com/)"
193 | }
194 | )
195 |
--------------------------------------------------------------------------------