├── Dockerfile
├── LICENSE
├── Procfile
├── README.md
├── Script.py
├── app.json
├── bot.py
├── database
├── connections_mdb.py
├── filters_mdb.py
├── ia_filterdb.py
└── users_chats_db.py
├── heroku.yml
├── info.py
├── logging.conf
├── plugins
├── __init__.py
├── banned.py
├── broadcast.py
├── channel.py
├── commands.py
├── connection.py
├── filters.py
├── genlink.py
├── index.py
├── inline.py
├── misc.py
├── p_ttishow.py
├── pm_filter.py
└── route.py
├── requirements.txt
├── runtime.txt
├── start.sh
└── utils.py
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.10-slim-buster
2 |
3 | RUN apt update && apt upgrade -y
4 | RUN apt install git -y
5 | COPY requirements.txt /requirements.txt
6 |
7 | RUN cd /
8 | RUN pip3 install -U pip && pip3 install -U -r requirements.txt
9 | RUN mkdir /LazyPrincessV2
10 | WORKDIR /LazyPrincessV2
11 | COPY start.sh /start.sh
12 | CMD ["/bin/bash", "/start.sh"]
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
2 |
72 |
81 |
3 |
5 | Lazy PrincessV2.0
6 |
7 |
8 |
9 | ## Features
10 |
11 | - [x] 🔥 New feature :
12 | - [+] ⚡️ Support 2GB + Files ⚡️
13 | - [x] Auto Filter
14 | - [x] Manual Filter
15 | - [x] IMDB
16 | - [x] Admin Commands
17 | - [x] Broadcast
18 | - [x] Index
19 | - [x] IMDB search
20 | - [x] Inline Search
21 | - [x] Random pics
22 | - [x] ids and User info
23 | - [x] Stats, Users, Chats, Ban, Unban, Leave, Disable, Channel
24 | - [x] Spelling Check Feature
25 | - [x] File Store
26 | ## • What's New ?
27 |
28 | - [x] URL Shortener Added
29 | - [x] Self Delete Added (Auto delete)
30 | - [x] Filter On Off Option Added
31 | - [x] Custom Welcome Message
32 | - [x] URL Shortener Added
33 | - [x] Custom Download Name And URL
34 | - [x] Custom Texts (About, Help, Stats,More..)
35 | - [x] Custom URL Buttons (Updates channel, Add To Group, Force Sub, More...)
36 |
37 | ## Variables
38 |
39 | Read [this](https://telegram.dog/sources_cods) before you start messing up with your edits.
40 |
41 | ### Required Variables
42 | * `BOT_TOKEN`: Create a bot using [@BotFather](https://telegram.dog/BotFather), and get the Telegram API token.
43 | * `API_ID`: Get this value from [telegram.org](https://my.telegram.org/apps)
44 | * `API_HASH`: Get this value from [telegram.org](https://my.telegram.org/apps)
45 | * `CHANNELS`: Username or ID of channel or group. Separate multiple IDs by space
46 | * `ADMINS`: Username or ID of Admin. Separate multiple Admins by space
47 | * `DATABASE_URI`: [mongoDB](https://www.mongodb.com) URI. Get this value from [mongoDB](https://www.mongodb.com). For more help watch this [video](https://youtu.be/h9QjSSmk5tw)
48 | * `DATABASE_NAME`: Name of the database in [mongoDB](https://www.mongodb.com). For more help watch this [video](https://youtu.be/h9QjSSmk5tw)
49 | * `LOG_CHANNEL` : A channel to log the activities of bot. Make sure bot is an admin in the channel.
50 | ### Optional Variables
51 | * `PICS`: Telegraph links of images to show in start message.( Multiple images can be used separated by space )
52 | * `FILE_STORE_CHANNEL`: Channel from were file store links of posts should be made.Separate multiple IDs by space
53 | * Check [info.py](https://github.com/AM-ROBOTS/AdvAnurag/blob/main/info.py) for more
54 | ## EXTRA FEATURES
55 | * `URL_SHORTENR_WEBSITE`: URL Shortener Website Link ( Without https://)
56 | * `URL_SHORTNER_WEBSITE_API`: URL Shortener Website API key
57 | * `SELF_DELETE`: True if SELF_DELETE is On, False if Off
58 | * `SELF_DELETE_SECONDS`: Enter Seconds to be SELF_DELETE
59 | * `START_TXT`: Enter Your Start Message
60 | * `ABOUT_TXT`: Enter Your About Message
61 |
62 |
63 | ## Deploy
64 | You can deploy this bot anywhere.
65 |
66 |
67 |
68 |
69 |
70 |
Deploy To Heroku
71 |
73 |
74 |
75 |
76 |
Deploy To VPS
80 |
82 | git clone https://github.com/LazyDeveloperr/LazyPrincessv2
83 | # Install Packages
84 | pip3 install -U -r requirements.txt
85 | Edit info.py with variables as given below then run bot
86 | python3 bot.py
87 |
88 |
add a filter in chat
40 | • /filters - list all the filters of a chat
41 | • /del - delete a specific filter in chat
42 | • /delall - delete the whole filters in a chat (chat owner only)
"""
43 | BUTTON_TXT = """Help: Buttons
44 |
45 | - Search Bot Supports both url and alert inline buttons.
46 |
47 | NOTE:
48 | 1. Telegram will not allows you to send buttons without any content, so content is mandatory.
49 | 2. Search Bot supports buttons with any telegram media type.
50 | 3. Buttons should be properly parsed as markdown format
51 |
52 | URL buttons:
53 | [Button Text](buttonurl:https://t.me/LazyDeveloper)
54 |
55 | Alert buttons:
56 | [Button Text](buttonalert:This is an alert message)
"""
57 | AUTOFILTER_TXT = """Help: Auto Filter
58 |
59 | NOTE:
60 | 1. Make me the admin of your channel if it's private.
61 | 2. make sure that your channel does not contains camrips, porn and fake files.
62 | 3. Forward the last message to me with quotes.
63 | I'll add all the files in that channel to my db."""
64 | CONNECTION_TXT = """Help: Connections
65 |
66 | - Used to connect bot to PM for managing filters
67 | - it helps to avoid spamming in groups.
68 |
69 | NOTE:
70 | 1. Only admins can add a connection.
71 | 2. Send /connect
for connecting me to ur PM
72 |
73 | Commands and Usage:
74 | • /connect - connect a particular chat to your PM
75 | • /disconnect - disconnect from a chat
76 | • /connections - list all your connections
"""
77 | EXTRAMOD_TXT = """Help: Extra Modules
78 |
79 | NOTE:
80 | these are the extra features of Search Bot
81 |
82 | Commands and Usage:
83 | • /id - get id of a specified user.
84 | • /info - get information about a user.
85 | • /imdb - get the film information from IMDb source.
86 | • /search - get the film information from various sources.
"""
87 | ADMIN_TXT = """Help: Admin mods
88 |
89 | NOTE:
90 | This module only works for my admins
91 |
92 | Commands and Usage:
93 | • /logs - to get the rescent errors
94 | • /stats - to get status of files in db.
95 | • /delete - to delete a specific file from db.
96 | • /users - to get list of my users and ids.
97 | • /chats - to get list of the my chats and ids
98 | • /leave - to leave from a chat.
99 | • /disable - do disable a chat.
100 | • /ban - to ban a user.
101 | • /unban - to unban a user.
102 | • /channel - to get list of total connected channels
103 | • /broadcast - to broadcast a message to all users
"""
104 | STATUS_TXT = """★ 𝚃𝙾𝚃𝙰𝙻 𝙵𝙸𝙻𝙴𝚂: {}
105 | ★ 𝚃𝙾𝚃𝙰𝙻 𝚄𝚂𝙴𝚁𝚂: {}
106 | ★ 𝚃𝙾𝚃𝙰𝙻 𝙲𝙷𝙰𝚃𝚂: {}
107 | ★ 𝚄𝚂𝙴𝙳 𝚂𝚃𝙾𝚁𝙰𝙶𝙴: {}
𝙼𝚒𝙱
108 | ★ 𝙵𝚁𝙴𝙴 𝚂𝚃𝙾𝚁𝙰𝙶𝙴: {}
𝙼𝚒𝙱"""
109 | LOG_TEXT_G = """#NewGroup
110 | Group = {}({}
)
111 | Total Members = {}
112 | Added By - {}
113 | """
114 | LOG_TEXT_P = """#NewUser
115 | ID - {}
116 | Name - {}
117 | """
118 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "LazyPrincessV2",
3 | "description": "LazyPrincess with Url Shortner",
4 | "stack": "container",
5 | "logo": "https://telegra.ph/file/68d28011b2bc356b5db01.png",
6 | "keywords": [
7 | "telegram",
8 | "auto-filter",
9 | "filter",
10 | "best",
11 | "indian",
12 | "pyrogram",
13 | "media",
14 | "search",
15 | "channel",
16 | "index",
17 | "inline"
18 | ],
19 | "website": "https://github.com/LazyDeveloperr",
20 | "repository": "https://github.com/LazyDeveloperr/LazyPrincessV2",
21 | "env": {
22 | "BOT_TOKEN": {
23 | "description": "Your bot token.",
24 | "required": true
25 | },
26 | "API_ID": {
27 | "description": "Get this value from https://my.telegram.org",
28 | "required": true
29 | },
30 | "API_HASH": {
31 | "description": "Get this value from https://my.telegram.org",
32 | "required": true
33 | },
34 | "CHANNELS": {
35 | "description": "Username or ID of channel or group. Separate multiple IDs by space.",
36 | "required": false
37 | },
38 | "ADMINS": {
39 | "description": "Username or ID of Admin. Separate multiple Admins by space.",
40 | "required": true
41 | },
42 | "PICS": {
43 | "description": "Add some telegraph link of pictures .",
44 | "required": false
45 | },
46 | "LOG_CHANNEL": {
47 | "description": "Bot Logs,Give a channel id with -100xxxxxxx",
48 | "required": true
49 | },
50 | "AUTH_USERS": {
51 | "description": "Username or ID of users to give access of inline search. Separate multiple users by space.\nLeave it empty if you don't want to restrict bot usage.",
52 | "required": false
53 | },
54 | "AUTH_CHANNEL": {
55 | "description": "ID of channel.Make sure bot is admin in this channel. Without subscribing this channel users cannot use bot.",
56 | "required": false
57 | },
58 | "DATABASE_URI": {
59 | "description": "mongoDB URI. Get this value from https://www.mongodb.com",
60 | "required": true
61 | },
62 | "DATABASE_NAME": {
63 | "description": "Name of the database in mongoDB.",
64 | "required": false
65 | },
66 | "COLLECTION_NAME": {
67 | "description": "Name of the collections. Defaults to Telegram_files. If you are using the same database, then use different collection name for each bot",
68 | "value": "Anurag_files",
69 | "required": false
70 | }
71 | },
72 | "addons": [],
73 | "buildpacks": [{
74 | "url": "heroku/python"
75 | }],
76 | "formation": {
77 | "worker": {
78 | "quantity": 1,
79 | "size": "free"
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/bot.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import logging.config
3 | from aiohttp import web
4 | from plugins import web_server
5 |
6 | # Get logging configurations
7 | logging.config.fileConfig('logging.conf')
8 | logging.getLogger().setLevel(logging.INFO)
9 | logging.getLogger("pyrogram").setLevel(logging.ERROR)
10 | logging.getLogger("imdbpy").setLevel(logging.ERROR)
11 |
12 | from pyrogram import Client, __version__
13 | from pyrogram.raw.all import layer
14 | from database.ia_filterdb import Media
15 | from database.users_chats_db import db
16 | from info import *
17 | from utils import temp
18 | from typing import Union, Optional, AsyncGenerator
19 | from pyrogram import types
20 |
21 | class Bot(Client):
22 |
23 | def __init__(self):
24 | super().__init__(
25 | name=SESSION,
26 | api_id=API_ID,
27 | api_hash=API_HASH,
28 | bot_token=BOT_TOKEN,
29 | workers=50,
30 | plugins={"root": "plugins"},
31 | sleep_threshold=5,
32 | )
33 |
34 | async def start(self):
35 | b_users, b_chats = await db.get_banned()
36 | temp.BANNED_USERS = b_users
37 | temp.BANNED_CHATS = b_chats
38 | await super().start()
39 | await Media.ensure_indexes()
40 | me = await self.get_me()
41 | temp.ME = me.id
42 | temp.U_NAME = me.username
43 | temp.B_NAME = me.first_name
44 | self.username = '@' + me.username
45 | #web-response
46 | app = web.AppRunner(await web_server())
47 | await app.setup()
48 | bind_address = "0.0.0.0"
49 | await web.TCPSite(app, bind_address, PORT).start()
50 | logging.info(f"{me.first_name} with for Pyrogram v{__version__} (Layer {layer}) started on {me.username}.")
51 | logging.info(LOG_STR)
52 |
53 | async def stop(self, *args):
54 | await super().stop()
55 | logging.info("Bot stopped. Bye.")
56 |
57 | async def iter_messages(
58 | self,
59 | chat_id: Union[int, str],
60 | limit: int,
61 | offset: int = 0,
62 | ) -> Optional[AsyncGenerator["types.Message", None]]:
63 | """Iterate through a chat sequentially.
64 | This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_messages` in a loop, thus saving
65 | you from the hassle of setting up boilerplate code. It is useful for getting the whole chat messages with a
66 | single call.
67 | Parameters:
68 | chat_id (``int`` | ``str``):
69 | Unique identifier (int) or username (str) of the target chat.
70 | For your personal cloud (Saved Messages) you can simply use "me" or "self".
71 | For a contact that exists in your Telegram address book you can use his phone number (str).
72 |
73 | limit (``int``):
74 | Identifier of the last message to be returned.
75 |
76 | offset (``int``, *optional*):
77 | Identifier of the first message to be returned.
78 | Defaults to 0.
79 | Returns:
80 | ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
81 | Example:
82 | .. code-block:: python
83 | for message in app.iter_messages("pyrogram", 1, 15000):
84 | print(message.text)
85 | """
86 | current = offset
87 | while True:
88 | new_diff = min(200, limit - current)
89 | if new_diff <= 0:
90 | return
91 | messages = await self.get_messages(chat_id, list(range(current, current+new_diff+1)))
92 | for message in messages:
93 | yield message
94 | current += 1
95 |
96 |
97 | app = Bot()
98 | app.run()
99 |
--------------------------------------------------------------------------------
/database/connections_mdb.py:
--------------------------------------------------------------------------------
1 | import pymongo
2 |
3 | from info import DATABASE_URI, DATABASE_NAME
4 |
5 | import logging
6 | logger = logging.getLogger(__name__)
7 | logger.setLevel(logging.ERROR)
8 |
9 | myclient = pymongo.MongoClient(DATABASE_URI)
10 | mydb = myclient[DATABASE_NAME]
11 | mycol = mydb['CONNECTION']
12 |
13 |
14 | async def add_connection(group_id, user_id):
15 | query = mycol.find_one(
16 | { "_id": user_id },
17 | { "_id": 0, "active_group": 0 }
18 | )
19 | if query is not None:
20 | group_ids = [x["group_id"] for x in query["group_details"]]
21 | if group_id in group_ids:
22 | return False
23 |
24 | group_details = {
25 | "group_id" : group_id
26 | }
27 |
28 | data = {
29 | '_id': user_id,
30 | 'group_details' : [group_details],
31 | 'active_group' : group_id,
32 | }
33 |
34 | if mycol.count_documents( {"_id": user_id} ) == 0:
35 | try:
36 | mycol.insert_one(data)
37 | return True
38 | except:
39 | logger.exception('Some error occurred!', exc_info=True)
40 |
41 | else:
42 | try:
43 | mycol.update_one(
44 | {'_id': user_id},
45 | {
46 | "$push": {"group_details": group_details},
47 | "$set": {"active_group" : group_id}
48 | }
49 | )
50 | return True
51 | except:
52 | logger.exception('Some error occurred!', exc_info=True)
53 |
54 |
55 | async def active_connection(user_id):
56 |
57 | query = mycol.find_one(
58 | { "_id": user_id },
59 | { "_id": 0, "group_details": 0 }
60 | )
61 | if not query:
62 | return None
63 |
64 | group_id = query['active_group']
65 | return int(group_id) if group_id != None else None
66 |
67 |
68 | async def all_connections(user_id):
69 | query = mycol.find_one(
70 | { "_id": user_id },
71 | { "_id": 0, "active_group": 0 }
72 | )
73 | if query is not None:
74 | return [x["group_id"] for x in query["group_details"]]
75 | else:
76 | return None
77 |
78 |
79 | async def if_active(user_id, group_id):
80 | query = mycol.find_one(
81 | { "_id": user_id },
82 | { "_id": 0, "group_details": 0 }
83 | )
84 | return query is not None and query['active_group'] == group_id
85 |
86 |
87 | async def make_active(user_id, group_id):
88 | update = mycol.update_one(
89 | {'_id': user_id},
90 | {"$set": {"active_group" : group_id}}
91 | )
92 | return update.modified_count != 0
93 |
94 |
95 | async def make_inactive(user_id):
96 | update = mycol.update_one(
97 | {'_id': user_id},
98 | {"$set": {"active_group" : None}}
99 | )
100 | return update.modified_count != 0
101 |
102 |
103 | async def delete_connection(user_id, group_id):
104 |
105 | try:
106 | update = mycol.update_one(
107 | {"_id": user_id},
108 | {"$pull" : { "group_details" : {"group_id":group_id} } }
109 | )
110 | if update.modified_count == 0:
111 | return False
112 | query = mycol.find_one(
113 | { "_id": user_id },
114 | { "_id": 0 }
115 | )
116 | if len(query["group_details"]) >= 1:
117 | if query['active_group'] == group_id:
118 | prvs_group_id = query["group_details"][len(query["group_details"]) - 1]["group_id"]
119 |
120 | mycol.update_one(
121 | {'_id': user_id},
122 | {"$set": {"active_group" : prvs_group_id}}
123 | )
124 | else:
125 | mycol.update_one(
126 | {'_id': user_id},
127 | {"$set": {"active_group" : None}}
128 | )
129 | return True
130 | except Exception as e:
131 | logger.exception(f'Some error occurred! {e}', exc_info=True)
132 | return False
133 |
134 |
--------------------------------------------------------------------------------
/database/filters_mdb.py:
--------------------------------------------------------------------------------
1 | import pymongo
2 | from pyrogram import enums
3 | from info import DATABASE_URI, DATABASE_NAME
4 | import logging
5 | logger = logging.getLogger(__name__)
6 | logger.setLevel(logging.ERROR)
7 |
8 | myclient = pymongo.MongoClient(DATABASE_URI)
9 | mydb = myclient[DATABASE_NAME]
10 |
11 |
12 |
13 | async def add_filter(grp_id, text, reply_text, btn, file, alert):
14 | mycol = mydb[str(grp_id)]
15 | # mycol.create_index([('text', 'text')])
16 |
17 | data = {
18 | 'text':str(text),
19 | 'reply':str(reply_text),
20 | 'btn':str(btn),
21 | 'file':str(file),
22 | 'alert':str(alert)
23 | }
24 |
25 | try:
26 | mycol.update_one({'text': str(text)}, {"$set": data}, upsert=True)
27 | except:
28 | logger.exception('Some error occured!', exc_info=True)
29 |
30 |
31 | async def find_filter(group_id, name):
32 | mycol = mydb[str(group_id)]
33 |
34 | query = mycol.find( {"text":name})
35 | # query = mycol.find( { "$text": {"$search": name}})
36 | try:
37 | for file in query:
38 | reply_text = file['reply']
39 | btn = file['btn']
40 | fileid = file['file']
41 | try:
42 | alert = file['alert']
43 | except:
44 | alert = None
45 | return reply_text, btn, alert, fileid
46 | except:
47 | return None, None, None, None
48 |
49 |
50 | async def get_filters(group_id):
51 | mycol = mydb[str(group_id)]
52 |
53 | texts = []
54 | query = mycol.find()
55 | try:
56 | for file in query:
57 | text = file['text']
58 | texts.append(text)
59 | except:
60 | pass
61 | return texts
62 |
63 |
64 | async def delete_filter(message, text, group_id):
65 | mycol = mydb[str(group_id)]
66 |
67 | myquery = {'text':text }
68 | query = mycol.count_documents(myquery)
69 | if query == 1:
70 | mycol.delete_one(myquery)
71 | await message.reply_text(
72 | f"'`{text}`' deleted. I'll not respond to that filter anymore.",
73 | quote=True,
74 | parse_mode=enums.ParseMode.MARKDOWN
75 | )
76 | else:
77 | await message.reply_text("Couldn't find that filter!", quote=True)
78 |
79 |
80 | async def del_all(message, group_id, title):
81 | if str(group_id) not in mydb.list_collection_names():
82 | await message.edit_text(f"Nothing to remove in {title}!")
83 | return
84 |
85 | mycol = mydb[str(group_id)]
86 | try:
87 | mycol.drop()
88 | await message.edit_text(f"All filters from {title} has been removed")
89 | except:
90 | await message.edit_text("Couldn't remove all filters from group!")
91 | return
92 |
93 |
94 | async def count_filters(group_id):
95 | mycol = mydb[str(group_id)]
96 |
97 | count = mycol.count()
98 | return False if count == 0 else count
99 |
100 |
101 | async def filter_stats():
102 | collections = mydb.list_collection_names()
103 |
104 | if "CONNECTION" in collections:
105 | collections.remove("CONNECTION")
106 |
107 | totalcount = 0
108 | for collection in collections:
109 | mycol = mydb[collection]
110 | count = mycol.count()
111 | totalcount += count
112 |
113 | totalcollections = len(collections)
114 |
115 | return totalcollections, totalcount
116 |
--------------------------------------------------------------------------------
/database/ia_filterdb.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from struct import pack
3 | import re
4 | import base64
5 | from pyrogram.file_id import FileId
6 | from pymongo.errors import DuplicateKeyError
7 | from umongo import Instance, Document, fields
8 | from motor.motor_asyncio import AsyncIOMotorClient
9 | from marshmallow.exceptions import ValidationError
10 | from info import DATABASE_URI, DATABASE_NAME, COLLECTION_NAME, USE_CAPTION_FILTER
11 |
12 | logger = logging.getLogger(__name__)
13 | logger.setLevel(logging.INFO)
14 |
15 |
16 | client = AsyncIOMotorClient(DATABASE_URI)
17 | db = client[DATABASE_NAME]
18 | instance = Instance.from_db(db)
19 |
20 | @instance.register
21 | class Media(Document):
22 | file_id = fields.StrField(attribute='_id')
23 | file_ref = fields.StrField(allow_none=True)
24 | file_name = fields.StrField(required=True)
25 | file_size = fields.IntField(required=True)
26 | file_type = fields.StrField(allow_none=True)
27 | mime_type = fields.StrField(allow_none=True)
28 | caption = fields.StrField(allow_none=True)
29 |
30 | class Meta:
31 | indexes = ('$file_name', )
32 | collection_name = COLLECTION_NAME
33 |
34 |
35 | async def save_file(media):
36 | """Save file in database"""
37 |
38 | # TODO: Find better way to get same file_id for same media to avoid duplicates
39 | file_id, file_ref = unpack_new_file_id(media.file_id)
40 | file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
41 | try:
42 | file = Media(
43 | file_id=file_id,
44 | file_ref=file_ref,
45 | file_name=file_name,
46 | file_size=media.file_size,
47 | file_type=media.file_type,
48 | mime_type=media.mime_type,
49 | caption=media.caption.html if media.caption else None,
50 | )
51 | except ValidationError:
52 | logger.exception('Error occurred while saving file in database')
53 | return False, 2
54 | else:
55 | try:
56 | await file.commit()
57 | except DuplicateKeyError:
58 | logger.warning(
59 | f'{getattr(media, "file_name", "NO_FILE")} is already saved in database'
60 | )
61 |
62 | return False, 0
63 | else:
64 | logger.info(f'{getattr(media, "file_name", "NO_FILE")} is saved to database')
65 | return True, 1
66 |
67 |
68 |
69 | async def get_search_results(query, file_type=None, max_results=10, offset=0, filter=False):
70 | """For given query return (results, next_offset)"""
71 |
72 | query = query.strip()
73 | #if filter:
74 | #better ?
75 | #query = query.replace(' ', r'(\s|\.|\+|\-|_)')
76 | #raw_pattern = r'(\s|_|\-|\.|\+)' + query + r'(\s|_|\-|\.|\+)'
77 | if not query:
78 | raw_pattern = '.'
79 | elif ' ' not in query:
80 | raw_pattern = r'(\b|[\.\+\-_])' + query + r'(\b|[\.\+\-_])'
81 | else:
82 | raw_pattern = query.replace(' ', r'.*[\s\.\+\-_]')
83 |
84 | try:
85 | regex = re.compile(raw_pattern, flags=re.IGNORECASE)
86 | except:
87 | return []
88 |
89 | if USE_CAPTION_FILTER:
90 | filter = {'$or': [{'file_name': regex}, {'caption': regex}]}
91 | else:
92 | filter = {'file_name': regex}
93 |
94 | if file_type:
95 | filter['file_type'] = file_type
96 |
97 | total_results = await Media.count_documents(filter)
98 | next_offset = offset + max_results
99 |
100 | if next_offset > total_results:
101 | next_offset = ''
102 |
103 | cursor = Media.find(filter)
104 | # Sort by recent
105 | cursor.sort('$natural', -1)
106 | # Slice files according to offset and max results
107 | cursor.skip(offset).limit(max_results)
108 | # Get list of files
109 | files = await cursor.to_list(length=max_results)
110 |
111 | return files, next_offset, total_results
112 |
113 |
114 |
115 | async def get_file_details(query):
116 | filter = {'file_id': query}
117 | cursor = Media.find(filter)
118 | filedetails = await cursor.to_list(length=1)
119 | return filedetails
120 |
121 |
122 | def encode_file_id(s: bytes) -> str:
123 | r = b""
124 | n = 0
125 |
126 | for i in s + bytes([22]) + bytes([4]):
127 | if i == 0:
128 | n += 1
129 | else:
130 | if n:
131 | r += b"\x00" + bytes([n])
132 | n = 0
133 |
134 | r += bytes([i])
135 |
136 | return base64.urlsafe_b64encode(r).decode().rstrip("=")
137 |
138 |
139 | def encode_file_ref(file_ref: bytes) -> str:
140 | return base64.urlsafe_b64encode(file_ref).decode().rstrip("=")
141 |
142 |
143 | def unpack_new_file_id(new_file_id):
144 | """Return file_id, file_ref"""
145 | decoded = FileId.decode(new_file_id)
146 | file_id = encode_file_id(
147 | pack(
148 | "{file_size}
🔥 ↭ Join Now [MoviesAdda™](https://t.me/real_MoviesAdda1) ↭ 🔥")
49 | BATCH_FILE_CAPTION = environ.get("BATCH_FILE_CAPTION", "⚡File uploaded by [Movies Adaa™](https://t.me/real_MoviesAdda1)⚡\n\nName: {file_caption} \n\n⚙️ Size: {file_size}
🔥 ↭ Join Now [MoviesAdda™](https://t.me/real_MoviesAdda1) ↭ 🔥")
50 | IMDB_TEMPLATE = environ.get("IMDB_TEMPLATE", "Your Query: {query} \nIMDb: \n\n🏷 Title: {title}\n🌟 Rating : {rating}/10\n🎭 Genres: {genres}\n📆 Year: {year}\n⏰ Duration : {runtime}\n🎙️ Languages : {languages}\n🔖 Plot : {plot}\n\n♥️ we are nothing without you ♥️ \n\n💛 Please Share Us 💛\n\n⚠️Click on the button 👇 below to get your query privately")
51 | LONG_IMDB_DESCRIPTION = is_enabled(environ.get("LONG_IMDB_DESCRIPTION", "False"), False)
52 | SPELL_CHECK_REPLY = is_enabled(environ.get("SPELL_CHECK_REPLY", "True"), False)
53 | MAX_LIST_ELM = environ.get("MAX_LIST_ELM", None)
54 | INDEX_REQ_CHANNEL = int(environ.get('INDEX_REQ_CHANNEL', LOG_CHANNEL))
55 | FILE_STORE_CHANNEL = [int(ch) for ch in (environ.get('FILE_STORE_CHANNEL', '')).split()]
56 | MELCOW_NEW_USERS = is_enabled((environ.get('MELCOW_NEW_USERS', "True")), True)
57 | PROTECT_CONTENT = is_enabled((environ.get('PROTECT_CONTENT', "False")), False)
58 | PUBLIC_FILE_STORE = is_enabled((environ.get('PUBLIC_FILE_STORE', "False")), True)
59 |
60 | LOG_STR = "Current Cusomized Configurations are:-\n"
61 | LOG_STR += ("IMDB Results are enabled, Bot will be showing imdb details for you queries.\n" if IMDB else "IMBD Results are disabled.\n")
62 | LOG_STR += ("P_TTI_SHOW_OFF found , Users will be redirected to send /start to Bot PM instead of sending file file directly\n" if P_TTI_SHOW_OFF else "P_TTI_SHOW_OFF is disabled files will be send in PM, instead of sending start.\n")
63 | LOG_STR += ("SINGLE_BUTTON is Found, filename and files size will be shown in a single button instead of two separate buttons\n" if SINGLE_BUTTON else "SINGLE_BUTTON is disabled , filename and file_sixe will be shown as different buttons\n")
64 | LOG_STR += (f"CUSTOM_FILE_CAPTION enabled with value {CUSTOM_FILE_CAPTION}, your files will be send along with this customized caption.\n" if CUSTOM_FILE_CAPTION else "No CUSTOM_FILE_CAPTION Found, Default captions of file will be used.\n")
65 | LOG_STR += ("Long IMDB storyline enabled." if LONG_IMDB_DESCRIPTION else "LONG_IMDB_DESCRIPTION is disabled , Plot will be shorter.\n")
66 | LOG_STR += ("Spell Check Mode Is Enabled, bot will be suggesting related movies if movie not found\n" if SPELL_CHECK_REPLY else "SPELL_CHECK_REPLY Mode disabled\n")
67 | LOG_STR += (f"MAX_LIST_ELM Found, long list will be shortened to first {MAX_LIST_ELM} elements\n" if MAX_LIST_ELM else "Full List of casts and crew will be shown in imdb template, restrict them by adding a value to MAX_LIST_ELM\n")
68 | LOG_STR += f"Your current IMDB template is {IMDB_TEMPLATE}"
69 |
70 | ## EXTRA FEATURES ##
71 |
72 | # URL Shortener #
73 |
74 | URL_SHORTENR_WEBSITE = environ.get('URL_SHORTENR_WEBSITE', 'api.shareus.in/shortLink')
75 | URL_SHORTNER_WEBSITE_API = environ.get('URL_SHORTNER_WEBSITE_API', 'I3Khu0fwfbWpd1W2ofcyP2znDA12')
76 |
77 | # Auto Delete For Group Message (Self Delete) #
78 | SELF_DELETE_SECONDS = int(environ.get('SELF_DELETE_SECONDS', 100))
79 | SELF_DELETE = environ.get('SELF_DELETE', True)
80 | if SELF_DELETE == "True":
81 | SELF_DELETE = True
82 |
83 | # Download Tutorial Button #
84 | DOWNLOAD_TEXT_NAME = "📥 HOW TO DOWNLOAD 📥"
85 | DOWNLOAD_TEXT_URL = "https://t.me/LazyDeveloper"
86 |
87 | # Custom Caption Under Button #
88 | CAPTION_BUTTON = "Get Updates"
89 | CAPTION_BUTTON_URL = "https://t.me/LazyDeveloper"
90 |
91 | # Auto Delete For Bot Sending Files #
92 |
--------------------------------------------------------------------------------
/logging.conf:
--------------------------------------------------------------------------------
1 | [loggers]
2 | keys=root
3 |
4 | [handlers]
5 | keys=consoleHandler,fileHandler
6 |
7 | [formatters]
8 | keys=consoleFormatter,fileFormatter
9 |
10 | [logger_root]
11 | level=DEBUG
12 | handlers=consoleHandler,fileHandler
13 |
14 | [handler_consoleHandler]
15 | class=StreamHandler
16 | level=INFO
17 | formatter=consoleFormatter
18 | args=(sys.stdout,)
19 |
20 | [handler_fileHandler]
21 | class=FileHandler
22 | level=ERROR
23 | formatter=fileFormatter
24 | args=('TelegramBot.log','w',)
25 |
26 | [formatter_consoleFormatter]
27 | format=%(asctime)s - %(lineno)d - %(name)s - %(module)s - %(levelname)s - %(message)s
28 | datefmt=%I:%M:%S %p
29 |
30 | [formatter_fileFormatter]
31 | format=[%(asctime)s:%(name)s:%(lineno)d:%(levelname)s] %(message)s
32 | datefmt=%m/%d/%Y %I:%M:%S %p
--------------------------------------------------------------------------------
/plugins/__init__.py:
--------------------------------------------------------------------------------
1 | #@iryme
2 |
3 |
4 |
5 |
6 |
7 |
8 | from aiohttp import web
9 | from .route import routes
10 |
11 |
12 | async def web_server():
13 | web_app = web.Application(client_max_size=30000000)
14 | web_app.add_routes(routes)
15 | return web_app
16 |
--------------------------------------------------------------------------------
/plugins/banned.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | from utils import temp
3 | from pyrogram.types import Message
4 | from database.users_chats_db import db
5 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
6 | from info import SUPPORT_CHAT
7 |
8 | async def banned_users(_, client, message: Message):
9 | return (
10 | message.from_user is not None or not message.sender_chat
11 | ) and message.from_user.id in temp.BANNED_USERS
12 |
13 | banned_user = filters.create(banned_users)
14 |
15 | async def disabled_chat(_, client, message: Message):
16 | return message.chat.id in temp.BANNED_CHATS
17 |
18 | disabled_group=filters.create(disabled_chat)
19 |
20 |
21 | @Client.on_message(filters.private & banned_user & filters.incoming)
22 | async def ban_reply(bot, message):
23 | ban = await db.get_ban_status(message.from_user.id)
24 | await message.reply(f'Sorry Dude, You are Banned to use Me. \nBan Reason: {ban["ban_reason"]}')
25 |
26 | @Client.on_message(filters.group & disabled_group & filters.incoming)
27 | async def grp_bd(bot, message):
28 | buttons = [[
29 | InlineKeyboardButton('Support', url=f'https://t.me/{SUPPORT_CHAT}')
30 | ]]
31 | reply_markup=InlineKeyboardMarkup(buttons)
32 | vazha = await db.get_chat(message.chat.id)
33 | k = await message.reply(
34 | text=f"CHAT NOT ALLOWED 🐞\n\nMy admins has restricted me from working here ! If you want to know more about it contact support..\nReason : {vazha['reason']}
.",
35 | reply_markup=reply_markup)
36 | try:
37 | await k.pin()
38 | except:
39 | pass
40 | await bot.leave_chat(message.chat.id)
41 |
--------------------------------------------------------------------------------
/plugins/broadcast.py:
--------------------------------------------------------------------------------
1 | #https://github.com/AM-ROBOTS
2 | from pyrogram import Client, filters
3 | import datetime
4 | import time
5 | from database.users_chats_db import db
6 | from info import ADMINS
7 | from utils import broadcast_messages
8 | import asyncio
9 |
10 | @Client.on_message(filters.command("broadcast") & filters.user(ADMINS) & filters.reply)
11 | # https://t.me/GetTGLink/4178
12 | async def verupikkals(bot, message):
13 | users = await db.get_all_users()
14 | b_msg = message.reply_to_message
15 | sts = await message.reply_text(
16 | text='Broadcasting your messages...😁...'
17 | )
18 | start_time = time.time()
19 | total_users = await db.total_users_count()
20 | done = 0
21 | blocked = 0
22 | deleted = 0
23 | failed =0
24 |
25 | success = 0
26 | async for user in users:
27 | pti, sh = await broadcast_messages(int(user['id']), b_msg)
28 | if pti:
29 | success += 1
30 | elif pti == False:
31 | if sh == "Blocked":
32 | blocked+=1
33 | elif sh == "Deleted":
34 | deleted += 1
35 | elif sh == "Error":
36 | failed += 1
37 | done += 1
38 | await asyncio.sleep(2)
39 | if not done % 20:
40 | await sts.edit(f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
41 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time))
42 | await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
43 |
--------------------------------------------------------------------------------
/plugins/channel.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | from info import CHANNELS
3 | from database.ia_filterdb import save_file
4 |
5 | media_filter = filters.document | filters.video | filters.audio
6 |
7 |
8 | @Client.on_message(filters.chat(CHANNELS) & media_filter)
9 | async def media(bot, message):
10 | """Media Handler"""
11 | for file_type in ("document", "video", "audio"):
12 | media = getattr(message, file_type, None)
13 | if media is not None:
14 | break
15 | else:
16 | return
17 |
18 | media.file_type = file_type
19 | media.caption = message.caption
20 | await save_file(media)
--------------------------------------------------------------------------------
/plugins/commands.py:
--------------------------------------------------------------------------------
1 | import os
2 | import logging
3 | import random
4 | import asyncio
5 | from Script import script
6 | from pyrogram import Client, filters, enums
7 | from pyrogram.errors import ChatAdminRequired, FloodWait
8 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
9 | from database.ia_filterdb import Media, get_file_details, unpack_new_file_id
10 | from database.users_chats_db import db
11 | from info import *
12 | from utils import get_settings, get_size, is_subscribed, save_group_settings, temp
13 | from database.connections_mdb import active_connection
14 | import re
15 | import json
16 | import base64
17 | logger = logging.getLogger(__name__)
18 |
19 | BATCH_FILES = {}
20 |
21 | @Client.on_message(filters.command("start") & filters.incoming)
22 | async def start(client, message):
23 | if message.chat.type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
24 | buttons = [
25 | [
26 | InlineKeyboardButton('🔔 BOT Updates 🤖', url='https://telegram.me/LazyDeveloper')
27 | ],
28 | [
29 | InlineKeyboardButton('⚡ Movie Updates ⚡', url=f"https://telegram.me/real_MoviesAdda1"),
30 | ],
31 | [
32 | InlineKeyboardButton(text=DOWNLOAD_TEXT_NAME,url=DOWNLOAD_TEXT_URL)
33 | ]
34 | ]
35 | reply_markup = InlineKeyboardMarkup(buttons)
36 | await message.reply(script.START_TXT.format(message.from_user.mention if message.from_user else message.chat.title, temp.U_NAME, temp.B_NAME), reply_markup=reply_markup)
37 | await asyncio.sleep(2) # 😢 https://github.com/EvamariaTG/EvaMaria/blob/master/plugins/p_ttishow.py#L17 😬 wait a bit, before checking.
38 | if not await db.get_chat(message.chat.id):
39 | total=await client.get_chat_members_count(message.chat.id)
40 | await client.send_message(LOG_CHANNEL, script.LOG_TEXT_G.format(message.chat.title, message.chat.id, total, "Unknown"))
41 | await db.add_chat(message.chat.id, message.chat.title)
42 | return
43 | if not await db.is_user_exist(message.from_user.id):
44 | await db.add_user(message.from_user.id, message.from_user.first_name)
45 | await client.send_message(LOG_CHANNEL, script.LOG_TEXT_P.format(message.from_user.id, message.from_user.mention))
46 | if len(message.command) != 2:
47 | buttons = [[
48 | InlineKeyboardButton('➕↖️ Add Me To Your Groups ↗️➕', url=f'http://t.me/{temp.U_NAME}?startgroup=true')
49 | ],[
50 | InlineKeyboardButton('⚡ Movie Updates ⚡', url=f"https://telegram.me/real_MoviesAdda1"),
51 | InlineKeyboardButton('🔔 BOT Updates 🤖', url='https://t.me/LazyDeveloper')
52 | ],[
53 | InlineKeyboardButton('🙆🏻 Help 🦾', callback_data='help'),
54 | InlineKeyboardButton('♥️ About ♥️', callback_data='about')
55 | ]]
56 | reply_markup = InlineKeyboardMarkup(buttons)
57 | await message.reply_photo(
58 | photo=random.choice(PICS),
59 | caption=script.START_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME),
60 | reply_markup=reply_markup,
61 | parse_mode=enums.ParseMode.HTML
62 | )
63 | return
64 | if AUTH_CHANNEL and not await is_subscribed(client, message):
65 | try:
66 | invite_link = await client.create_chat_invite_link(int(AUTH_CHANNEL))
67 | except ChatAdminRequired:
68 | logger.error("Make sure Bot is admin in Force Sub channel")
69 | return
70 | btn = [
71 | [
72 | InlineKeyboardButton(
73 | "🔥 Join Updates Channel 🔥", url=invite_link.invite_link
74 | )
75 | ]
76 | ]
77 |
78 | if message.command[1] != "subscribe":
79 | try:
80 | kk, file_id = message.command[1].split("_", 1)
81 | pre = 'checksubp' if kk == 'filep' else 'checksub'
82 | btn.append([InlineKeyboardButton(" 🔄 Try Again", callback_data=f"{pre}#{file_id}")])
83 | except (IndexError, ValueError):
84 | btn.append([InlineKeyboardButton(" 🔄 Try Again", url=f"https://t.me/{temp.U_NAME}?start={message.command[1]}")])
85 | await client.send_message(
86 | chat_id=message.from_user.id,
87 | text="**Please Join My Updates Channel to use this Bot!**",
88 | reply_markup=InlineKeyboardMarkup(btn),
89 | parse_mode=enums.ParseMode.MARKDOWN
90 | )
91 | return
92 | if len(message.command) == 2 and message.command[1] in ["subscribe", "error", "okay", "help"]:
93 | buttons = [[
94 | InlineKeyboardButton('➕↖️ Add Me To Your Groups ↗️➕', url=f'http://t.me/{temp.U_NAME}?startgroup=true')
95 | ],[
96 | InlineKeyboardButton('⚡ Movie Updates ⚡', url=f"https://telegram.me/real_MoviesAdda1"),
97 | InlineKeyboardButton('🔔 BOT Updates 🤖', url='https://t.me/LazyDeveloper')
98 | ],[
99 | InlineKeyboardButton('🙆🏻 Help 🦾', callback_data='help'),
100 | InlineKeyboardButton('♥️ About ♥️', callback_data='about')
101 | ]]
102 | reply_markup = InlineKeyboardMarkup(buttons)
103 | await message.reply_photo(
104 | photo=random.choice(PICS),
105 | caption=script.START_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME),
106 | reply_markup=reply_markup,
107 | parse_mode=enums.ParseMode.HTML
108 | )
109 | return
110 | data = message.command[1]
111 | try:
112 | pre, file_id = data.split('_', 1)
113 | except:
114 | file_id = data
115 | pre = ""
116 | if data.split("-", 1)[0] == "BATCH":
117 | sts = await message.reply("𝙰𝙲𝙲𝙴𝚂𝚂𝙸𝙽𝙶 𝙵𝙸𝙻𝙴𝚂.../")
118 | file_id = data.split("-", 1)[1]
119 | msgs = BATCH_FILES.get(file_id)
120 | if not msgs:
121 | file = await client.download_media(file_id)
122 | try:
123 | with open(file) as file_data:
124 | msgs=json.loads(file_data.read())
125 | except:
126 | await sts.edit("FAILED")
127 | return await client.send_message(LOG_CHANNEL, "UNABLE TO OPEN FILE.")
128 | os.remove(file)
129 | BATCH_FILES[file_id] = msgs
130 | for msg in msgs:
131 | title = msg.get("title")
132 | size=get_size(int(msg.get("size", 0)))
133 | f_caption=msg.get("caption", "")
134 | if BATCH_FILE_CAPTION:
135 | try:
136 | f_caption=BATCH_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='' if f_caption is None else f_caption)
137 | except Exception as e:
138 | logger.exception(e)
139 | f_caption=f_caption
140 | if f_caption is None:
141 | f_caption = f"{title}"
142 | try:
143 | await client.send_cached_media(
144 | chat_id=message.from_user.id,
145 | file_id=msg.get("file_id"),
146 | caption=f_caption,
147 | protect_content=msg.get('protect', False),
148 | )
149 | except FloodWait as e:
150 | await asyncio.sleep(e.x)
151 | logger.warning(f"Floodwait of {e.x} sec.")
152 | await client.send_cached_media(
153 | chat_id=message.from_user.id,
154 | file_id=msg.get("file_id"),
155 | caption=f_caption,
156 | protect_content=msg.get('protect', False),
157 | )
158 | except Exception as e:
159 | logger.warning(e, exc_info=True)
160 | continue
161 | await asyncio.sleep(1)
162 | await sts.delete()
163 | return
164 | elif data.split("-", 1)[0] == "DSTORE":
165 | sts = await message.reply("𝙰𝙲𝙲𝙴𝚂𝚂𝙸𝙽𝙶 𝙵𝙸𝙻𝙴𝚂.../")
166 | b_string = data.split("-", 1)[1]
167 | decoded = (base64.urlsafe_b64decode(b_string + "=" * (-len(b_string) % 4))).decode("ascii")
168 | try:
169 | f_msg_id, l_msg_id, f_chat_id, protect = decoded.split("_", 3)
170 | except:
171 | f_msg_id, l_msg_id, f_chat_id = decoded.split("_", 2)
172 | protect = "/pbatch" if PROTECT_CONTENT else "batch"
173 | diff = int(l_msg_id) - int(f_msg_id)
174 | async for msg in client.iter_messages(int(f_chat_id), int(l_msg_id), int(f_msg_id)):
175 | if msg.media:
176 | media = getattr(msg, msg.media.value)
177 | if BATCH_FILE_CAPTION:
178 | try:
179 | f_caption=BATCH_FILE_CAPTION.format(file_name=getattr(media, 'file_name', ''), file_size=getattr(media, 'file_size', ''), file_caption=getattr(msg, 'caption', ''))
180 | except Exception as e:
181 | logger.exception(e)
182 | f_caption = getattr(msg, 'caption', '')
183 | else:
184 | media = getattr(msg, msg.media.value)
185 | file_name = getattr(media, 'file_name', '')
186 | f_caption = getattr(msg, 'caption', file_name)
187 | try:
188 | await msg.copy(message.chat.id, caption=f_caption, protect_content=True if protect == "/pbatch" else False)
189 | except FloodWait as e:
190 | await asyncio.sleep(e.x)
191 | await msg.copy(message.chat.id, caption=f_caption, protect_content=True if protect == "/pbatch" else False)
192 | except Exception as e:
193 | logger.exception(e)
194 | continue
195 | elif msg.empty:
196 | continue
197 | else:
198 | try:
199 | await msg.copy(message.chat.id, protect_content=True if protect == "/pbatch" else False)
200 | except FloodWait as e:
201 | await asyncio.sleep(e.x)
202 | await msg.copy(message.chat.id, protect_content=True if protect == "/pbatch" else False)
203 | except Exception as e:
204 | logger.exception(e)
205 | continue
206 | await asyncio.sleep(1)
207 | return await sts.delete()
208 |
209 |
210 | files_ = await get_file_details(file_id)
211 | if not files_:
212 | pre, file_id = ((base64.urlsafe_b64decode(data + "=" * (-len(data) % 4))).decode("ascii")).split("_", 1)
213 | try:
214 | msg = await client.send_cached_media(
215 | chat_id=message.from_user.id,
216 | file_id=file_id,
217 | protect_content=True if pre == 'filep' else False,
218 | )
219 | filetype = msg.media
220 | file = getattr(msg, filetype.value)
221 | title = file.file_name
222 | size=get_size(file.file_size)
223 | f_caption = f"{title}
"
224 | if CUSTOM_FILE_CAPTION:
225 | try:
226 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='')
227 | except:
228 | return
229 | await msg.edit_caption(f_caption)
230 | return
231 | except:
232 | pass
233 | return await message.reply('No such file exist.')
234 | files = files_[0]
235 | title = files.file_name
236 | size=get_size(files.file_size)
237 | f_caption=files.caption
238 | if CUSTOM_FILE_CAPTION:
239 | try:
240 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='' if f_caption is None else f_caption)
241 | except Exception as e:
242 | logger.exception(e)
243 | f_caption=f_caption
244 | if f_caption is None:
245 | f_caption = f"{files.file_name}"
246 | await client.send_cached_media(
247 | chat_id=message.from_user.id,
248 | file_id=file_id,
249 | caption=f_caption,
250 | reply_markup=InlineKeyboardMarkup( [ [InlineKeyboardButton('sᴜʙsᴄʀɪʙᴇ', url='https://youtube.com/@LazyDeveloperr')] ] ),
251 | protect_content=True if pre == 'filep' else False,
252 | )
253 |
254 |
255 | @Client.on_message(filters.command('channel') & filters.user(ADMINS))
256 | async def channel_info(bot, message):
257 |
258 | """Send basic information of channel"""
259 | if isinstance(CHANNELS, (int, str)):
260 | channels = [CHANNELS]
261 | elif isinstance(CHANNELS, list):
262 | channels = CHANNELS
263 | else:
264 | raise ValueError("Unexpected type of CHANNELS")
265 |
266 | text = '📑 **Indexed channels/groups**\n'
267 | for channel in channels:
268 | chat = await bot.get_chat(channel)
269 | if chat.username:
270 | text += '\n@' + chat.username
271 | else:
272 | text += '\n' + chat.title or chat.first_name
273 |
274 | text += f'\n\n**Total:** {len(CHANNELS)}'
275 |
276 | if len(text) < 4096:
277 | await message.reply(text)
278 | else:
279 | file = 'Indexed channels.txt'
280 | with open(file, 'w') as f:
281 | f.write(text)
282 | await message.reply_document(file)
283 | os.remove(file)
284 |
285 |
286 | @Client.on_message(filters.command('logs') & filters.user(ADMINS))
287 | async def log_file(bot, message):
288 | """Send log file"""
289 | try:
290 | await message.reply_document('TelegramBot.log')
291 | except Exception as e:
292 | await message.reply(str(e))
293 |
294 | @Client.on_message(filters.command('delete') & filters.user(ADMINS))
295 | async def delete(bot, message):
296 | """Delete file from database"""
297 | reply = message.reply_to_message
298 | if reply and reply.media:
299 | msg = await message.reply("𝐃𝐞𝐥𝐞𝐭𝐢𝐧𝐠....🗑️", quote=True)
300 | else:
301 | await message.reply('Reply to file with /delete which you want to delete', quote=True)
302 | return
303 |
304 | for file_type in ("document", "video", "audio"):
305 | media = getattr(reply, file_type, None)
306 | if media is not None:
307 | break
308 | else:
309 | await msg.edit('This is not supported file format')
310 | return
311 |
312 | file_id, file_ref = unpack_new_file_id(media.file_id)
313 |
314 | result = await Media.collection.delete_one({
315 | '_id': file_id,
316 | })
317 | if result.deleted_count:
318 | await msg.edit('**𝙵𝙸𝙻𝙴 𝚂𝚄𝙲𝙲𝙴𝚂𝚂𝙵𝚄𝙻𝙻𝚈 𝙳𝙴𝙻𝙴𝚃𝙴𝙳**')
319 | else:
320 | file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
321 | result = await Media.collection.delete_many({
322 | 'file_name': file_name,
323 | 'file_size': media.file_size,
324 | 'mime_type': media.mime_type
325 | })
326 | if result.deleted_count:
327 | await msg.edit('**𝙵𝙸𝙻𝙴 𝚂𝚄𝙲𝙲𝙴𝚂𝚂𝙵𝚄𝙻𝙻𝚈 𝙳𝙴𝙻𝙴𝚃𝙴𝙳**')
328 | else:
329 | # files indexed before https://github.com/EvamariaTG/EvaMaria/commit/f3d2a1bcb155faf44178e5d7a685a1b533e714bf#diff-86b613edf1748372103e94cacff3b578b36b698ef9c16817bb98fe9ef22fb669R39
330 | # have original file name.
331 | result = await Media.collection.delete_many({
332 | 'file_name': media.file_name,
333 | 'file_size': media.file_size,
334 | 'mime_type': media.mime_type
335 | })
336 | if result.deleted_count:
337 | await msg.edit('**𝙵𝙸𝙻𝙴 𝚂𝚄𝙲𝙲𝙴𝚂𝚂𝙵𝚄𝙻𝙻𝚈 𝙳𝙴𝙻𝙴𝚃𝙴𝙳**')
338 | else:
339 | await msg.edit('File not found in database')
340 |
341 |
342 | @Client.on_message(filters.command('deleteall') & filters.user(ADMINS))
343 | async def delete_all_index(bot, message):
344 | await message.reply_text(
345 | '**𝚃𝙷𝙸𝚂 𝙿𝚁𝙾𝙲𝙴𝚂𝚂 𝚆𝙸𝙻𝙻 𝙳𝙴𝙻𝙴𝚃𝙴 𝙰𝙻𝙻 𝚃𝙷𝙴 𝙵𝙸𝙻𝙴𝚂 𝙵𝚁𝙾𝙼 𝚈𝙾𝚄𝚁 𝙳𝙰𝚃𝙰𝙱𝙰𝚂𝙴.\n𝙳𝙾 𝚈𝙾𝚄 𝚆𝙰𝙽𝚃 𝚃𝙾 𝙲𝙾𝙽𝚃𝙸𝙽𝚄𝙴 𝚃𝙷𝙸𝚂..??**',
346 | reply_markup=InlineKeyboardMarkup(
347 | [
348 | [
349 | InlineKeyboardButton(
350 | text="⚡ 𝐘𝐞𝐬 ⚡", callback_data="autofilter_delete"
351 | )
352 | ],
353 | [
354 | InlineKeyboardButton(
355 | text="❄ 𝐂𝐚𝐧𝐜𝐞𝐥 ❄", callback_data="close_data"
356 | )
357 | ],
358 | ]
359 | ),
360 | quote=True,
361 | )
362 |
363 |
364 | @Client.on_callback_query(filters.regex(r'^autofilter_delete'))
365 | async def delete_all_index_confirm(bot, message):
366 | await Media.collection.drop()
367 | await message.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
368 | await message.message.edit('Succesfully Deleted All The Indexed Files.')
369 |
370 |
371 | @Client.on_message(filters.command('settings'))
372 | async def settings(client, message):
373 | userid = message.from_user.id if message.from_user else None
374 | if not userid:
375 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
376 | chat_type = message.chat.type
377 |
378 | if chat_type == enums.ChatType.PRIVATE:
379 | grpid = await active_connection(str(userid))
380 | if grpid is not None:
381 | grp_id = grpid
382 | try:
383 | chat = await client.get_chat(grpid)
384 | title = chat.title
385 | except:
386 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
387 | return
388 | else:
389 | await message.reply_text("I'm not connected to any groups!", quote=True)
390 | return
391 |
392 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
393 | grp_id = message.chat.id
394 | title = message.chat.title
395 |
396 | else:
397 | return
398 |
399 | st = await client.get_chat_member(grp_id, userid)
400 | if (
401 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
402 | and st.status != enums.ChatMemberStatus.OWNER
403 | and str(userid) not in ADMINS
404 | ):
405 | return
406 |
407 | settings = await get_settings(grp_id)
408 |
409 | if settings is not None:
410 | buttons = [
411 | [
412 | InlineKeyboardButton(
413 | '𝐅𝐈𝐋𝐓𝐄𝐑 𝐁𝐔𝐓𝐓𝐎𝐍',
414 | callback_data=f'setgs#button#{settings["button"]}#{grp_id}',
415 | ),
416 | InlineKeyboardButton(
417 | '𝐒𝐈𝐍𝐆𝐋𝐄' if settings["button"] else '𝐃𝐎𝐔𝐁𝐋𝐄',
418 | callback_data=f'setgs#button#{settings["button"]}#{grp_id}',
419 | ),
420 | ],
421 | [
422 | InlineKeyboardButton(
423 | '𝐁𝐎𝐓 𝐏𝐌',
424 | callback_data=f'setgs#botpm#{settings["botpm"]}#{grp_id}',
425 | ),
426 | InlineKeyboardButton(
427 | '✅ 𝐘𝐄𝐒' if settings["botpm"] else '❌ 𝐍𝐎',
428 | callback_data=f'setgs#botpm#{settings["botpm"]}#{grp_id}',
429 | ),
430 | ],
431 | [
432 | InlineKeyboardButton(
433 | '𝐅𝐈𝐋𝐄 𝐒𝐄𝐂𝐔𝐑𝐄',
434 | callback_data=f'setgs#file_secure#{settings["file_secure"]}#{grp_id}',
435 | ),
436 | InlineKeyboardButton(
437 | '✅ 𝐘𝐄𝐒' if settings["file_secure"] else '❌ 𝐍𝐎',
438 | callback_data=f'setgs#file_secure#{settings["file_secure"]}#{grp_id}',
439 | ),
440 | ],
441 | [
442 | InlineKeyboardButton(
443 | '𝐈𝐌𝐃𝐁',
444 | callback_data=f'setgs#imdb#{settings["imdb"]}#{grp_id}',
445 | ),
446 | InlineKeyboardButton(
447 | '✅ 𝐘𝐄𝐒' if settings["imdb"] else '❌ 𝐍𝐎',
448 | callback_data=f'setgs#imdb#{settings["imdb"]}#{grp_id}',
449 | ),
450 | ],
451 | [
452 | InlineKeyboardButton(
453 | '𝐒𝐏𝐄𝐋𝐋 𝐂𝐇𝐄𝐂𝐊',
454 | callback_data=f'setgs#spell_check#{settings["spell_check"]}#{grp_id}',
455 | ),
456 | InlineKeyboardButton(
457 | '✅ 𝐘𝐄𝐒' if settings["spell_check"] else '❌ 𝐍𝐎',
458 | callback_data=f'setgs#spell_check#{settings["spell_check"]}#{grp_id}',
459 | ),
460 | ],
461 | [
462 | InlineKeyboardButton(
463 | '𝐖𝐄𝐋𝐂𝐎𝐌𝐄',
464 | callback_data=f'setgs#welcome#{settings["welcome"]}#{grp_id}',
465 | ),
466 | InlineKeyboardButton(
467 | '✅ 𝐘𝐄𝐒' if settings["welcome"] else '❌ 𝐍𝐎',
468 | callback_data=f'setgs#welcome#{settings["welcome"]}#{grp_id}',
469 | ),
470 | ],
471 | ]
472 |
473 | reply_markup = InlineKeyboardMarkup(buttons)
474 |
475 | await message.reply_text(
476 | text=f"𝙲𝙷𝙰𝙽𝙶𝙴 𝚃𝙷𝙴 𝙱𝙾𝚃 𝚂𝙴𝚃𝚃𝙸𝙽𝙶𝚂 𝙵𝙾𝚁 {title}..⚙",
477 | reply_markup=reply_markup,
478 | disable_web_page_preview=True,
479 | parse_mode=enums.ParseMode.HTML,
480 | reply_to_message_id=message.id
481 | )
482 |
483 |
484 |
485 | @Client.on_message(filters.command('set_template'))
486 | async def save_template(client, message):
487 | sts = await message.reply("**𝙲𝙷𝙴𝙲𝙺𝙸𝙽𝙶 𝙽𝙴𝚆 𝚃𝙴𝙼𝙿𝙻𝙰𝚃𝙴**")
488 | userid = message.from_user.id if message.from_user else None
489 | if not userid:
490 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
491 | chat_type = message.chat.type
492 |
493 | if chat_type == enums.ChatType.PRIVATE:
494 | grpid = await active_connection(str(userid))
495 | if grpid is not None:
496 | grp_id = grpid
497 | try:
498 | chat = await client.get_chat(grpid)
499 | title = chat.title
500 | except:
501 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
502 | return
503 | else:
504 | await message.reply_text("I'm not connected to any groups!", quote=True)
505 | return
506 |
507 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
508 | grp_id = message.chat.id
509 | title = message.chat.title
510 |
511 | else:
512 | return
513 |
514 | st = await client.get_chat_member(grp_id, userid)
515 | if (
516 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
517 | and st.status != enums.ChatMemberStatus.OWNER
518 | and str(userid) not in ADMINS
519 | ):
520 | return
521 |
522 | if len(message.command) < 2:
523 | return await sts.edit("No Input!!")
524 | template = message.text.split(" ", 1)[1]
525 | await save_group_settings(grp_id, 'template', template)
526 | await sts.edit(f"𝚂𝚄𝙲𝙲𝙴𝚂𝚂𝙵𝚄𝙻𝙻𝚈 𝚄𝙿𝙶𝚁𝙰𝙳𝙴𝙳 𝚈𝙾𝚄𝚁 𝚃𝙴𝙼𝙿𝙻𝙰𝚃𝙴 𝙵𝙾𝚁 {title} to\n\n{template}")
527 |
--------------------------------------------------------------------------------
/plugins/connection.py:
--------------------------------------------------------------------------------
1 | from pyrogram import filters, Client, enums
2 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
3 | from database.connections_mdb import add_connection, all_connections, if_active, delete_connection
4 | from info import ADMINS
5 | import logging
6 |
7 | logger = logging.getLogger(__name__)
8 | logger.setLevel(logging.ERROR)
9 |
10 |
11 | @Client.on_message((filters.private | filters.group) & filters.command('connect'))
12 | async def addconnection(client, message):
13 | userid = message.from_user.id if message.from_user else None
14 | if not userid:
15 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
16 | chat_type = message.chat.type
17 |
18 | if chat_type == enums.ChatType.PRIVATE:
19 | try:
20 | cmd, group_id = message.text.split(" ", 1)
21 | except:
22 | await message.reply_text(
23 | "𝙴𝙽𝚃𝙴𝚁 𝙸𝙽 𝙲𝙾𝚁𝚁𝙴𝙲𝚃 𝙵𝙾𝚁𝙼𝙰𝚃!\n\n"
24 | "/connect 𝙶𝚁𝙾𝚄𝙿 𝙸𝙳
\n\n"
25 | "Get your Group id by adding this bot to your group and use /id
",
26 | quote=True
27 | )
28 | return
29 |
30 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
31 | group_id = message.chat.id
32 |
33 | try:
34 | st = await client.get_chat_member(group_id, userid)
35 | if (
36 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
37 | and st.status != enums.ChatMemberStatus.OWNER
38 | and userid not in ADMINS
39 | ):
40 | await message.reply_text("You should be an admin in Given group!", quote=True)
41 | return
42 | except Exception as e:
43 | logger.exception(e)
44 | await message.reply_text(
45 | "Invalid Group ID!\n\nIf correct, Make sure I'm present in your group!!",
46 | quote=True,
47 | )
48 |
49 | return
50 | try:
51 | st = await client.get_chat_member(group_id, "me")
52 | if st.status == enums.ChatMemberStatus.ADMINISTRATOR:
53 | ttl = await client.get_chat(group_id)
54 | title = ttl.title
55 |
56 | addcon = await add_connection(str(group_id), str(userid))
57 | if addcon:
58 | await message.reply_text(
59 | f"𝚂𝚄𝙲𝙲𝙴𝚂𝚂𝙵𝚄𝙻𝙻𝚈 𝙲𝙾𝙽𝙽𝙴𝙲𝚃 𝚃𝙾 **{title}**\n𝙽𝙾𝚆 𝚈𝙾𝚄 𝙲𝙰𝙽 𝙼𝙰𝙽𝙰𝙶𝙴 𝚈𝙾𝚄𝚁 𝙶𝚁𝙾𝚄𝙿 𝙵𝚁𝙾𝙼 𝙷𝙴𝚁𝙴../",
60 | quote=True,
61 | parse_mode=enums.ParseMode.MARKDOWN
62 | )
63 | if chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
64 | await client.send_message(
65 | userid,
66 | f"Connected to **{title}** !",
67 | parse_mode=enums.ParseMode.MARKDOWN
68 | )
69 | else:
70 | await message.reply_text(
71 | "You're already connected to this chat!",
72 | quote=True
73 | )
74 | else:
75 | await message.reply_text("Add me as an admin in group", quote=True)
76 | except Exception as e:
77 | logger.exception(e)
78 | await message.reply_text('Some error occurred! Try again later.', quote=True)
79 | return
80 |
81 |
82 | @Client.on_message((filters.private | filters.group) & filters.command('disconnect'))
83 | async def deleteconnection(client, message):
84 | userid = message.from_user.id if message.from_user else None
85 | if not userid:
86 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
87 | chat_type = message.chat.type
88 |
89 | if chat_type == enums.ChatType.PRIVATE:
90 | await message.reply_text("Run /connections to view or disconnect from groups!", quote=True)
91 |
92 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
93 | group_id = message.chat.id
94 |
95 | st = await client.get_chat_member(group_id, userid)
96 | if (
97 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
98 | and st.status != enums.ChatMemberStatus.OWNER
99 | and str(userid) not in ADMINS
100 | ):
101 | return
102 |
103 | delcon = await delete_connection(str(userid), str(group_id))
104 | if delcon:
105 | await message.reply_text("Successfully disconnected from this chat", quote=True)
106 | else:
107 | await message.reply_text("This chat isn't connected to me!\nDo /connect to connect.", quote=True)
108 |
109 |
110 | @Client.on_message(filters.private & filters.command(["connections"]))
111 | async def connections(client, message):
112 | userid = message.from_user.id
113 |
114 | groupids = await all_connections(str(userid))
115 | if groupids is None:
116 | await message.reply_text(
117 | "There are no active connections!! Connect to some groups first.",
118 | quote=True
119 | )
120 | return
121 | buttons = []
122 | for groupid in groupids:
123 | try:
124 | ttl = await client.get_chat(int(groupid))
125 | title = ttl.title
126 | active = await if_active(str(userid), str(groupid))
127 | act = " - ACTIVE" if active else ""
128 | buttons.append(
129 | [
130 | InlineKeyboardButton(
131 | text=f"{title}{act}", callback_data=f"groupcb:{groupid}:{act}"
132 | )
133 | ]
134 | )
135 | except:
136 | pass
137 | if buttons:
138 | await message.reply_text(
139 | "𝙲𝙾𝙽𝙽𝙴𝙲𝚃𝙴𝙳 𝙶𝚁𝙾𝚄𝙿𝚂 :-\n\n",
140 | reply_markup=InlineKeyboardMarkup(buttons),
141 | quote=True
142 | )
143 | else:
144 | await message.reply_text(
145 | "There are no active connections!! Connect to some groups first.",
146 | quote=True
147 | )
148 |
--------------------------------------------------------------------------------
/plugins/filters.py:
--------------------------------------------------------------------------------
1 | import io
2 | from pyrogram import filters, Client, enums
3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
4 | from database.filters_mdb import(
5 | add_filter,
6 | get_filters,
7 | delete_filter,
8 | count_filters
9 | )
10 |
11 | from database.connections_mdb import active_connection
12 | from utils import get_file_id, parser, split_quotes
13 | from info import ADMINS
14 |
15 |
16 | @Client.on_message(filters.command(['filter', 'add']) & filters.incoming)
17 | async def addfilter(client, message):
18 | userid = message.from_user.id if message.from_user else None
19 | if not userid:
20 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
21 | chat_type = message.chat.type
22 | args = message.text.html.split(None, 1)
23 |
24 | if chat_type == enums.ChatType.PRIVATE:
25 | grpid = await active_connection(str(userid))
26 | if grpid is not None:
27 | grp_id = grpid
28 | try:
29 | chat = await client.get_chat(grpid)
30 | title = chat.title
31 | except:
32 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
33 | return
34 | else:
35 | await message.reply_text("I'm not connected to any groups!", quote=True)
36 | return
37 |
38 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
39 | grp_id = message.chat.id
40 | title = message.chat.title
41 |
42 | else:
43 | return
44 |
45 | st = await client.get_chat_member(grp_id, userid)
46 | if (
47 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
48 | and st.status != enums.ChatMemberStatus.OWNER
49 | and str(userid) not in ADMINS
50 | ):
51 | return
52 |
53 |
54 | if len(args) < 2:
55 | await message.reply_text("Command Incomplete :(", quote=True)
56 | return
57 |
58 | extracted = split_quotes(args[1])
59 | text = extracted[0].lower()
60 |
61 | if not message.reply_to_message and len(extracted) < 2:
62 | await message.reply_text("Add some content to save your filter!", quote=True)
63 | return
64 |
65 | if (len(extracted) >= 2) and not message.reply_to_message:
66 | reply_text, btn, alert = parser(extracted[1], text)
67 | fileid = None
68 | if not reply_text:
69 | await message.reply_text("You cannot have buttons alone, give some text to go with it!", quote=True)
70 | return
71 |
72 | elif message.reply_to_message and message.reply_to_message.reply_markup:
73 | try:
74 | rm = message.reply_to_message.reply_markup
75 | btn = rm.inline_keyboard
76 | msg = get_file_id(message.reply_to_message)
77 | if msg:
78 | fileid = msg.file_id
79 | reply_text = message.reply_to_message.caption.html
80 | else:
81 | reply_text = message.reply_to_message.text.html
82 | fileid = None
83 | alert = None
84 | except:
85 | reply_text = ""
86 | btn = "[]"
87 | fileid = None
88 | alert = None
89 |
90 | elif message.reply_to_message and message.reply_to_message.media:
91 | try:
92 | msg = get_file_id(message.reply_to_message)
93 | fileid = msg.file_id if msg else None
94 | reply_text, btn, alert = parser(extracted[1], text) if message.reply_to_message.sticker else parser(message.reply_to_message.caption.html, text)
95 | except:
96 | reply_text = ""
97 | btn = "[]"
98 | alert = None
99 | elif message.reply_to_message and message.reply_to_message.text:
100 | try:
101 | fileid = None
102 | reply_text, btn, alert = parser(message.reply_to_message.text.html, text)
103 | except:
104 | reply_text = ""
105 | btn = "[]"
106 | alert = None
107 | else:
108 | return
109 |
110 | await add_filter(grp_id, text, reply_text, btn, fileid, alert)
111 |
112 | await message.reply_text(
113 | f"Filter for `{text}` added in **{title}**",
114 | quote=True,
115 | parse_mode=enums.ParseMode.MARKDOWN
116 | )
117 |
118 |
119 | @Client.on_message(filters.command(['viewfilters', 'filters']) & filters.incoming)
120 | async def get_all(client, message):
121 |
122 | chat_type = message.chat.type
123 | userid = message.from_user.id if message.from_user else None
124 | if not userid:
125 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
126 | if chat_type == enums.ChatType.PRIVATE:
127 | grpid = await active_connection(str(userid))
128 | if grpid is not None:
129 | grp_id = grpid
130 | try:
131 | chat = await client.get_chat(grpid)
132 | title = chat.title
133 | except:
134 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
135 | return
136 | else:
137 | await message.reply_text("I'm not connected to any groups!", quote=True)
138 | return
139 |
140 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
141 | grp_id = message.chat.id
142 | title = message.chat.title
143 |
144 | else:
145 | return
146 |
147 | st = await client.get_chat_member(grp_id, userid)
148 | if (
149 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
150 | and st.status != enums.ChatMemberStatus.OWNER
151 | and str(userid) not in ADMINS
152 | ):
153 | return
154 |
155 | texts = await get_filters(grp_id)
156 | count = await count_filters(grp_id)
157 | if count:
158 | filterlist = f"Total number of filters in **{title}** : {count}\n\n"
159 |
160 | for text in texts:
161 | keywords = " × `{}`\n".format(text)
162 |
163 | filterlist += keywords
164 |
165 | if len(filterlist) > 4096:
166 | with io.BytesIO(str.encode(filterlist.replace("`", ""))) as keyword_file:
167 | keyword_file.name = "keywords.txt"
168 | await message.reply_document(
169 | document=keyword_file,
170 | quote=True
171 | )
172 | return
173 | else:
174 | filterlist = f"There are no active filters in **{title}**"
175 |
176 | await message.reply_text(
177 | text=filterlist,
178 | quote=True,
179 | parse_mode=enums.ParseMode.MARKDOWN
180 | )
181 |
182 | @Client.on_message(filters.command('del') & filters.incoming)
183 | async def deletefilter(client, message):
184 | userid = message.from_user.id if message.from_user else None
185 | if not userid:
186 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
187 | chat_type = message.chat.type
188 |
189 | if chat_type == enums.ChatType.PRIVATE:
190 | grpid = await active_connection(str(userid))
191 | if grpid is not None:
192 | grp_id = grpid
193 | try:
194 | chat = await client.get_chat(grpid)
195 | title = chat.title
196 | except:
197 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
198 | return
199 | else:
200 | await message.reply_text("I'm not connected to any groups!", quote=True)
201 | return
202 |
203 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
204 | grp_id = message.chat.id
205 | title = message.chat.title
206 |
207 | else:
208 | return
209 |
210 | st = await client.get_chat_member(grp_id, userid)
211 | if (
212 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
213 | and st.status != enums.ChatMemberStatus.OWNER
214 | and str(userid) not in ADMINS
215 | ):
216 | return
217 |
218 | try:
219 | cmd, text = message.text.split(" ", 1)
220 | except:
221 | await message.reply_text(
222 | "Mention the filtername which you wanna delete!\n\n"
223 | "/del filtername
\n\n"
224 | "Use /viewfilters to view all available filters",
225 | quote=True
226 | )
227 | return
228 |
229 | query = text.lower()
230 |
231 | await delete_filter(message, query, grp_id)
232 |
233 |
234 | @Client.on_message(filters.command('delall') & filters.incoming)
235 | async def delallconfirm(client, message):
236 | userid = message.from_user.id if message.from_user else None
237 | if not userid:
238 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
239 | chat_type = message.chat.type
240 |
241 | if chat_type == enums.ChatType.PRIVATE:
242 | grpid = await active_connection(str(userid))
243 | if grpid is not None:
244 | grp_id = grpid
245 | try:
246 | chat = await client.get_chat(grpid)
247 | title = chat.title
248 | except:
249 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
250 | return
251 | else:
252 | await message.reply_text("I'm not connected to any groups!", quote=True)
253 | return
254 |
255 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
256 | grp_id = message.chat.id
257 | title = message.chat.title
258 |
259 | else:
260 | return
261 |
262 |
263 | st = await client.get_chat_member(grp_id, userid)
264 | if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS):
265 | await message.reply_text(
266 | f"This will delete all filters from '{title}'.\nDo you want to continue??",
267 | reply_markup=InlineKeyboardMarkup([
268 | [InlineKeyboardButton(text="YES",callback_data="delallconfirm")],
269 | [InlineKeyboardButton(text="CANCEL",callback_data="delallcancel")]
270 | ]),
271 | quote=True
272 | )
273 |
274 |
--------------------------------------------------------------------------------
/plugins/genlink.py:
--------------------------------------------------------------------------------
1 | import re
2 | from pyrogram import filters, Client, enums
3 | from pyrogram.errors.exceptions.bad_request_400 import ChannelInvalid, UsernameInvalid, UsernameNotModified
4 | from info import ADMINS, LOG_CHANNEL, FILE_STORE_CHANNEL, PUBLIC_FILE_STORE
5 | from database.ia_filterdb import unpack_new_file_id
6 | from utils import temp
7 | import re
8 | import os
9 | import json
10 | import base64
11 | import logging
12 |
13 | logger = logging.getLogger(__name__)
14 | logger.setLevel(logging.INFO)
15 |
16 | async def allowed(_, __, message):
17 | if PUBLIC_FILE_STORE:
18 | return True
19 | if message.from_user and message.from_user.id in ADMINS:
20 | return True
21 | return False
22 |
23 | @Client.on_message(filters.command(['link', 'plink']) & filters.create(allowed))
24 | async def gen_link_s(bot, message):
25 | replied = message.reply_to_message
26 | if not replied:
27 | return await message.reply('𝚁𝙴𝙿𝙻𝚈 𝚃𝙾 𝙰 𝙼𝙴𝚂𝚂𝙰𝙶𝙴 𝙾𝚁 𝙰 𝙵𝙸𝙻𝙴. 𝙸 𝚆𝙸𝙻𝙻 𝙶𝙸𝚅𝙴 𝚈𝙾𝚄 𝙰 𝚂𝙷𝙰𝚁𝙰𝙱𝙻𝙴 𝙿𝙴𝚁𝙼𝙰𝙽𝙴𝙽𝚃 𝙻𝙸𝙽𝙺')
28 | file_type = replied.media
29 | if file_type not in [enums.MessageMediaType.VIDEO, enums.MessageMediaType.AUDIO, enums.MessageMediaType.DOCUMENT]:
30 | return await message.reply("𝚁𝙴𝙿𝙻𝚈 𝚃𝙾 𝙰 𝚂𝚄𝙿𝙿𝙾𝚁𝚃𝙴𝙳 𝙼𝙴𝙳𝙸𝙰")
31 | if message.has_protected_content and message.chat.id not in ADMINS:
32 | return await message.reply("𝙾𝙺 𝙱𝚁𝙾")
33 | file_id, ref = unpack_new_file_id((getattr(replied, file_type.value)).file_id)
34 | string = 'filep_' if message.text.lower().strip() == "/plink" else 'file_'
35 | string += file_id
36 | outstr = base64.urlsafe_b64encode(string.encode("ascii")).decode().strip("=")
37 | await message.reply(f"⪼ 𝙷𝙴𝚁𝙴 𝙸𝚂 𝚈𝙾𝚄𝚁 𝙻𝙸𝙽𝙺:\nhttps://t.me/{temp.U_NAME}?start={outstr}")
38 |
39 |
40 | @Client.on_message(filters.command(['batch', 'pbatch']) & filters.create(allowed))
41 | async def gen_link_batch(bot, message):
42 | if " " not in message.text:
43 | return await message.reply("𝚄𝚂𝙴 𝙲𝙾𝚁𝚁𝙴𝙲𝚃 𝙵𝙾𝚁𝙼𝙰𝚃.\n𝙴𝚇𝙰𝙼𝙿𝙻𝙴 ›› /batch https://t.me/LazyDeveloper/10 https://t.me/LazyDeveloper/20
.")
44 | links = message.text.strip().split(" ")
45 | if len(links) != 3:
46 | return await message.reply("Use correct format.\nExample /batch https://t.me/LazyDeveloper/10 https://t.me/LazyDeveloper/20
.")
47 | cmd, first, last = links
48 | regex = re.compile("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")
49 | match = regex.match(first)
50 | if not match:
51 | return await message.reply('Invalid link')
52 | f_chat_id = match.group(4)
53 | f_msg_id = int(match.group(5))
54 | if f_chat_id.isnumeric():
55 | f_chat_id = int(("-100" + f_chat_id))
56 |
57 | match = regex.match(last)
58 | if not match:
59 | return await message.reply('Invalid link')
60 | l_chat_id = match.group(4)
61 | l_msg_id = int(match.group(5))
62 | if l_chat_id.isnumeric():
63 | l_chat_id = int(("-100" + l_chat_id))
64 |
65 | if f_chat_id != l_chat_id:
66 | return await message.reply("Chat ids not matched.")
67 | try:
68 | chat_id = (await bot.get_chat(f_chat_id)).id
69 | except ChannelInvalid:
70 | return await message.reply('𝚃𝙷𝙸𝚂 𝙼𝙰𝚈 𝙱𝙴 𝙰 𝙿𝚁𝙸𝚅𝙰𝚃𝙴 𝙲𝙷𝙰𝙽𝙽𝙴𝙻 / 𝙶𝚁𝙾𝚄𝙿. 𝙼𝙰𝙺𝙴 𝙼𝙴 𝙰𝙽 𝙰𝙳𝙼𝙸𝙽 𝙾𝚅𝙴𝚁 𝚃𝙷𝙴𝚁𝙴 𝚃𝙾 𝙸𝙽𝙳𝙴𝚇 𝚃𝙷𝙴 𝙵𝙸𝙻𝙴𝚂.')
71 | except (UsernameInvalid, UsernameNotModified):
72 | return await message.reply('Invalid Link specified.')
73 | except Exception as e:
74 | return await message.reply(f'Errors - {e}')
75 |
76 | sts = await message.reply("𝙶𝚎𝚗𝚎𝚛𝚊𝚝𝚒𝚗𝚐 𝙻𝚒𝚗𝚔 𝙵𝚘𝚛 𝚈𝚘𝚞𝚛 𝙼𝚎𝚜𝚜𝚊𝚐𝚎.\n𝚃𝙷𝙸𝚂 𝙼𝙰𝚈𝙱𝙴 𝚃𝙰𝙺𝙴 𝚃𝙸𝙼𝙴 𝙳𝙴𝙿𝙴𝙽𝙳𝙸𝙽𝙶 𝚄𝙿𝙾𝙽 𝚃𝙷𝙴 𝙽𝚄𝙼𝙱𝙴𝚁 𝙾𝙵 𝙼𝙴𝚂𝚂𝙰𝙶𝙴𝚂")
77 | if chat_id in FILE_STORE_CHANNEL:
78 | string = f"{f_msg_id}_{l_msg_id}_{chat_id}_{cmd.lower().strip()}"
79 | b_64 = base64.urlsafe_b64encode(string.encode("ascii")).decode().strip("=")
80 | return await sts.edit(f"⪼ 𝙷𝙴𝚁𝙴 𝙸𝚂 𝚈𝙾𝚄𝚁 𝙻𝙸𝙽𝙺 ›› https://t.me/{temp.U_NAME}?start=DSTORE-{b_64}")
81 |
82 | FRMT = "╭━━━━━━━━━━━━━━━➣\n┣⪼𝙶𝙴𝙽𝙴𝚁𝙰𝚃𝙸𝙽𝙶 𝙻𝙸𝙽𝙺...\n┣⪼𝚃𝙾𝚃𝙰𝙻 𝙼𝙴𝚂𝚂𝙰𝙶𝙴𝚂: `{total}`\n┣⪼𝙳𝙾𝙽𝙴: `{current}`\n┣⪼𝚁𝙴𝙼𝙰𝙸𝙽𝙸𝙽𝙶: `{rem}`\n┣⪼𝚂𝚃𝙰𝚃𝚄𝚂: `{sts}`\n╰━━━━━━━━━━━━━━━➣"
83 |
84 | outlist = []
85 |
86 | # file store without db channel
87 | og_msg = 0
88 | tot = 0
89 | async for msg in bot.iter_messages(f_chat_id, l_msg_id, f_msg_id):
90 | tot += 1
91 | if msg.empty or msg.service:
92 | continue
93 | if not msg.media:
94 | # only media messages supported.
95 | continue
96 | try:
97 | file_type = msg.media
98 | file = getattr(msg, file_type.value)
99 | caption = getattr(msg, 'caption', '')
100 | if caption:
101 | caption = caption.html
102 | if file:
103 | file = {
104 | "file_id": file.file_id,
105 | "caption": caption,
106 | "title": getattr(file, "file_name", ""),
107 | "size": file.file_size,
108 | "protect": cmd.lower().strip() == "/pbatch",
109 | }
110 |
111 | og_msg +=1
112 | outlist.append(file)
113 | except:
114 | pass
115 | if not og_msg % 20:
116 | try:
117 | await sts.edit(FRMT.format(total=l_msg_id-f_msg_id, current=tot, rem=((l_msg_id-f_msg_id) - tot), sts="Saving Messages"))
118 | except:
119 | pass
120 | with open(f"batchmode_{message.from_user.id}.json", "w+") as out:
121 | json.dump(outlist, out)
122 | post = await bot.send_document(LOG_CHANNEL, f"batchmode_{message.from_user.id}.json", file_name="Batch.json", caption="👩🏻💻 File Store Logs 👩🏻💻")
123 | os.remove(f"batchmode_{message.from_user.id}.json")
124 | file_id, ref = unpack_new_file_id(post.document.file_id)
125 | await sts.edit(f"⪼ 𝙷𝙴𝚁𝙴 𝙸𝚂 𝚈𝙾𝚄𝚁 𝙻𝙸𝙽𝙺\n𝙲𝙾𝙽𝚃𝙰𝙸𝙽𝚂 `{og_msg}` 𝙵𝙸𝙻𝙴𝚂.\n https://t.me/{temp.U_NAME}?start=BATCH-{file_id}")
126 |
--------------------------------------------------------------------------------
/plugins/index.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import asyncio
3 | from pyrogram import Client, filters, enums
4 | from pyrogram.errors import FloodWait
5 | from pyrogram.errors.exceptions.bad_request_400 import ChannelInvalid, ChatAdminRequired, UsernameInvalid, UsernameNotModified
6 | from info import ADMINS
7 | from info import INDEX_REQ_CHANNEL as LOG_CHANNEL
8 | from database.ia_filterdb import save_file
9 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
10 | from utils import temp
11 | import re
12 | logger = logging.getLogger(__name__)
13 | logger.setLevel(logging.INFO)
14 | lock = asyncio.Lock()
15 |
16 |
17 | @Client.on_callback_query(filters.regex(r'^index'))
18 | async def index_files(bot, query):
19 | if query.data.startswith('index_cancel'):
20 | temp.CANCEL = True
21 | return await query.answer("Cancelling Indexing")
22 | _, raju, chat, lst_msg_id, from_user = query.data.split("#")
23 | if raju == 'reject':
24 | await query.message.delete()
25 | await bot.send_message(int(from_user),
26 | f'Your Submission for indexing {chat} has been decliened by our moderators.',
27 | reply_to_message_id=int(lst_msg_id))
28 | return
29 |
30 | if lock.locked():
31 | return await query.answer('Wait until previous process complete.', show_alert=True)
32 | msg = query.message
33 |
34 | await query.answer('Processing...⏳', show_alert=True)
35 | if int(from_user) not in ADMINS:
36 | await bot.send_message(int(from_user),
37 | f'Your Submission for indexing {chat} has been accepted by our moderators and will be added soon.',
38 | reply_to_message_id=int(lst_msg_id))
39 | await msg.edit(
40 | "Starting Indexing",
41 | reply_markup=InlineKeyboardMarkup(
42 | [[InlineKeyboardButton('Cancel', callback_data='index_cancel')]]
43 | )
44 | )
45 | try:
46 | chat = int(chat)
47 | except:
48 | chat = chat
49 | await index_files_to_db(int(lst_msg_id), chat, msg, bot)
50 |
51 |
52 | @Client.on_message((filters.forwarded | (filters.regex("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")) & filters.text ) & filters.private & filters.incoming)
53 | async def send_for_index(bot, message):
54 | if message.text:
55 | regex = re.compile("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")
56 | match = regex.match(message.text)
57 | if not match:
58 | return await message.reply('Invalid link')
59 | chat_id = match.group(4)
60 | last_msg_id = int(match.group(5))
61 | if chat_id.isnumeric():
62 | chat_id = int(("-100" + chat_id))
63 | elif message.forward_from_chat.type == enums.ChatType.CHANNEL:
64 | last_msg_id = message.forward_from_message_id
65 | chat_id = message.forward_from_chat.username or message.forward_from_chat.id
66 | else:
67 | return
68 | try:
69 | await bot.get_chat(chat_id)
70 | except ChannelInvalid:
71 | return await message.reply('This may be a private channel / group. Make me an admin over there to index the files.')
72 | except (UsernameInvalid, UsernameNotModified):
73 | return await message.reply('Invalid Link specified.')
74 | except Exception as e:
75 | logger.exception(e)
76 | return await message.reply(f'Errors - {e}')
77 | try:
78 | k = await bot.get_messages(chat_id, last_msg_id)
79 | except:
80 | return await message.reply('Make Sure That Iam An Admin In The Channel, if channel is private')
81 | if k.empty:
82 | return await message.reply('This may be group and iam not a admin of the group.')
83 |
84 | if message.from_user.id in ADMINS:
85 | buttons = [
86 | [
87 | InlineKeyboardButton('Yes',
88 | callback_data=f'index#accept#{chat_id}#{last_msg_id}#{message.from_user.id}')
89 | ],
90 | [
91 | InlineKeyboardButton('close', callback_data='close_data'),
92 | ]
93 | ]
94 | reply_markup = InlineKeyboardMarkup(buttons)
95 | return await message.reply(
96 | f'Do you Want To Index This Channel/ Group ?\n\nChat ID/ Username: {chat_id}
\nLast Message ID: {last_msg_id}
',
97 | reply_markup=reply_markup)
98 |
99 | if type(chat_id) is int:
100 | try:
101 | link = (await bot.create_chat_invite_link(chat_id)).invite_link
102 | except ChatAdminRequired:
103 | return await message.reply('Make sure iam an admin in the chat and have permission to invite users.')
104 | else:
105 | link = f"@{message.forward_from_chat.username}"
106 | buttons = [
107 | [
108 | InlineKeyboardButton('Accept Index',
109 | callback_data=f'index#accept#{chat_id}#{last_msg_id}#{message.from_user.id}')
110 | ],
111 | [
112 | InlineKeyboardButton('Reject Index',
113 | callback_data=f'index#reject#{chat_id}#{message.id}#{message.from_user.id}'),
114 | ]
115 | ]
116 | reply_markup = InlineKeyboardMarkup(buttons)
117 | await bot.send_message(LOG_CHANNEL,
118 | f'#IndexRequest\n\nBy : {message.from_user.mention} ({message.from_user.id}
)\nChat ID/ Username - {chat_id}
\nLast Message ID - {last_msg_id}
\nInviteLink - {link}',
119 | reply_markup=reply_markup)
120 | await message.reply('ThankYou For the Contribution, Wait For My Moderators to verify the files.')
121 |
122 |
123 | @Client.on_message(filters.command('setskip') & filters.user(ADMINS))
124 | async def set_skip_number(bot, message):
125 | if ' ' in message.text:
126 | _, skip = message.text.split(" ")
127 | try:
128 | skip = int(skip)
129 | except:
130 | return await message.reply("Skip number should be an integer.")
131 | await message.reply(f"Successfully set SKIP number as {skip}")
132 | temp.CURRENT = int(skip)
133 | else:
134 | await message.reply("Give me a skip number")
135 |
136 |
137 | async def index_files_to_db(lst_msg_id, chat, msg, bot):
138 | total_files = 0
139 | duplicate = 0
140 | errors = 0
141 | deleted = 0
142 | no_media = 0
143 | unsupported = 0
144 | async with lock:
145 | try:
146 | current = temp.CURRENT
147 | temp.CANCEL = False
148 | async for message in bot.iter_messages(chat, lst_msg_id, temp.CURRENT):
149 | if temp.CANCEL:
150 | await msg.edit(f"Successfully Cancelled!!\n\nSaved {total_files}
files to dataBase!\nDuplicate Files Skipped: {duplicate}
\nDeleted Messages Skipped: {deleted}
\nNon-Media messages skipped: {no_media + unsupported}
(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}
")
151 | break
152 | current += 1
153 | if current % 20 == 0:
154 | can = [[InlineKeyboardButton('Cancel', callback_data='index_cancel')]]
155 | reply = InlineKeyboardMarkup(can)
156 | await msg.edit_text(
157 | text=f"Total messages fetched: {current}
\nTotal messages saved: {total_files}
\nDuplicate Files Skipped: {duplicate}
\nDeleted Messages Skipped: {deleted}
\nNon-Media messages skipped: {no_media + unsupported}
(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}
",
158 | reply_markup=reply)
159 | if message.empty:
160 | deleted += 1
161 | continue
162 | elif not message.media:
163 | no_media += 1
164 | continue
165 | elif message.media not in [enums.MessageMediaType.VIDEO, enums.MessageMediaType.AUDIO, enums.MessageMediaType.DOCUMENT]:
166 | unsupported += 1
167 | continue
168 | media = getattr(message, message.media.value, None)
169 | if not media:
170 | unsupported += 1
171 | continue
172 | media.file_type = message.media.value
173 | media.caption = message.caption
174 | aynav, vnay = await save_file(media)
175 | if aynav:
176 | total_files += 1
177 | elif vnay == 0:
178 | duplicate += 1
179 | elif vnay == 2:
180 | errors += 1
181 | except Exception as e:
182 | logger.exception(e)
183 | await msg.edit(f'Error: {e}')
184 | else:
185 | await msg.edit(f'Succesfully saved {total_files}
to dataBase!\nDuplicate Files Skipped: {duplicate}
\nDeleted Messages Skipped: {deleted}
\nNon-Media messages skipped: {no_media + unsupported}
(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}
')
186 |
--------------------------------------------------------------------------------
/plugins/inline.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from pyrogram import Client, emoji, filters
3 | from pyrogram.errors.exceptions.bad_request_400 import QueryIdInvalid
4 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, InlineQueryResultCachedDocument, InlineQuery
5 | from database.ia_filterdb import get_search_results
6 | from utils import is_subscribed, get_size, temp
7 | from info import CACHE_TIME, AUTH_USERS, AUTH_CHANNEL, CUSTOM_FILE_CAPTION
8 |
9 | logger = logging.getLogger(__name__)
10 | cache_time = 0 if AUTH_USERS or AUTH_CHANNEL else CACHE_TIME
11 |
12 | async def inline_users(query: InlineQuery):
13 | if AUTH_USERS:
14 | if query.from_user and query.from_user.id in AUTH_USERS:
15 | return True
16 | else:
17 | return False
18 | if query.from_user and query.from_user.id not in temp.BANNED_USERS:
19 | return True
20 | return False
21 |
22 | @Client.on_inline_query()
23 | async def answer(bot, query):
24 | """Show search results for given inline query"""
25 |
26 | if not await inline_users(query):
27 | await query.answer(results=[],
28 | cache_time=0,
29 | switch_pm_text='okDa',
30 | switch_pm_parameter="hehe")
31 | return
32 |
33 | if AUTH_CHANNEL and not await is_subscribed(bot, query):
34 | await query.answer(results=[],
35 | cache_time=0,
36 | switch_pm_text='You have to subscribe my channel to use the bot',
37 | switch_pm_parameter="subscribe")
38 | return
39 |
40 | results = []
41 | if '|' in query.query:
42 | string, file_type = query.query.split('|', maxsplit=1)
43 | string = string.strip()
44 | file_type = file_type.strip().lower()
45 | else:
46 | string = query.query.strip()
47 | file_type = None
48 |
49 | offset = int(query.offset or 0)
50 | reply_markup = get_reply_markup(query=string)
51 | files, next_offset, total = await get_search_results(string,
52 | file_type=file_type,
53 | max_results=10,
54 | offset=offset)
55 |
56 | for file in files:
57 | title=file.file_name
58 | size=get_size(file.file_size)
59 | f_caption=file.caption
60 | if CUSTOM_FILE_CAPTION:
61 | try:
62 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='' if f_caption is None else f_caption)
63 | except Exception as e:
64 | logger.exception(e)
65 | f_caption=f_caption
66 | if f_caption is None:
67 | f_caption = f"{file.file_name}"
68 | results.append(
69 | InlineQueryResultCachedDocument(
70 | title=file.file_name,
71 | document_file_id=file.file_id,
72 | caption=f_caption,
73 | description=f'Size: {get_size(file.file_size)}\nType: {file.file_type}',
74 | reply_markup=reply_markup))
75 |
76 | if results:
77 | switch_pm_text = f"{emoji.FILE_FOLDER} Results - {total}"
78 | if string:
79 | switch_pm_text += f" for {string}"
80 | try:
81 | await query.answer(results=results,
82 | is_personal = True,
83 | cache_time=cache_time,
84 | switch_pm_text=switch_pm_text,
85 | switch_pm_parameter="start",
86 | next_offset=str(next_offset))
87 | except QueryIdInvalid:
88 | pass
89 | except Exception as e:
90 | logging.exception(str(e))
91 | else:
92 | switch_pm_text = f'{emoji.CROSS_MARK} No results'
93 | if string:
94 | switch_pm_text += f' for "{string}"'
95 |
96 | await query.answer(results=[],
97 | is_personal = True,
98 | cache_time=cache_time,
99 | switch_pm_text=switch_pm_text,
100 | switch_pm_parameter="okay")
101 |
102 |
103 | def get_reply_markup(query):
104 | buttons = [
105 | [
106 | InlineKeyboardButton('Search again', switch_inline_query_current_chat=query)
107 | ]
108 | ]
109 | return InlineKeyboardMarkup(buttons)
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/plugins/misc.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyrogram import Client, filters, enums
3 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant, MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty
4 | from info import IMDB_TEMPLATE
5 | from utils import extract_user, get_file_id, get_poster, last_online
6 | import time
7 | from datetime import datetime
8 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
9 | import logging
10 | logger = logging.getLogger(__name__)
11 | logger.setLevel(logging.ERROR)
12 |
13 | @Client.on_message(filters.command('id'))
14 | async def showid(client, message):
15 | chat_type = message.chat.type
16 | if chat_type == enums.ChatType.PRIVATE:
17 | user_id = message.chat.id
18 | first = message.from_user.first_name
19 | last = message.from_user.last_name or ""
20 | username = message.from_user.username
21 | dc_id = message.from_user.dc_id or ""
22 | await message.reply_text(
23 | f"➲ First Name: {first}\n➲ Last Name: {last}\n➲ Username: {username}\n➲ Telegram ID: {user_id}
\n➲ Data Centre: {dc_id}
",
24 | quote=True
25 | )
26 |
27 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
28 | _id = ""
29 | _id += (
30 | "➲ Chat ID: "
31 | f"{message.chat.id}
\n"
32 | )
33 | if message.reply_to_message:
34 | _id += (
35 | "➲ User ID: "
36 | f"{message.from_user.id if message.from_user else 'Anonymous'}
\n"
37 | "➲ Replied User ID: "
38 | f"{message.reply_to_message.from_user.id if message.reply_to_message.from_user else 'Anonymous'}
\n"
39 | )
40 | file_info = get_file_id(message.reply_to_message)
41 | else:
42 | _id += (
43 | "➲ User ID: "
44 | f"{message.from_user.id if message.from_user else 'Anonymous'}
\n"
45 | )
46 | file_info = get_file_id(message)
47 | if file_info:
48 | _id += (
49 | f"{file_info.message_type}: "
50 | f"{file_info.file_id}
\n"
51 | )
52 | await message.reply_text(
53 | _id,
54 | quote=True
55 | )
56 |
57 | @Client.on_message(filters.command(["info"]))
58 | async def who_is(client, message):
59 | # https://github.com/SpEcHiDe/PyroGramBot/blob/master/pyrobot/plugins/admemes/whois.py#L19
60 | status_message = await message.reply_text(
61 | "`𝚂𝙴𝙰𝚁𝙲𝙷𝙸𝙽𝙶 𝚄𝚂𝙴𝚁...`"
62 | )
63 | await status_message.edit(
64 | "`𝙰𝙲𝙲𝙴𝚂𝚂𝙸𝙽𝙶 𝙸𝙽𝙵𝙾𝚁𝙼𝙰𝚃𝙸𝙾𝙽...`"
65 | )
66 | from_user = None
67 | from_user_id, _ = extract_user(message)
68 | try:
69 | from_user = await client.get_users(from_user_id)
70 | except Exception as error:
71 | await status_message.edit(str(error))
72 | return
73 | if from_user is None:
74 | return await status_message.edit("no valid user_id / message specified")
75 | message_out_str = ""
76 | message_out_str += f"➲First Name: {from_user.first_name}\n"
77 | last_name = from_user.last_name or "None"
78 | message_out_str += f"➲Last Name: {last_name}\n"
79 | message_out_str += f"➲Telegram ID: {from_user.id}
\n"
80 | username = from_user.username or "None"
81 | dc_id = from_user.dc_id or "[User Doesn't Have A Valid DP]"
82 | message_out_str += f"➲Data Centre: {dc_id}
\n"
83 | message_out_str += f"➲User Name: @{username}\n"
84 | message_out_str += f"➲User 𝖫𝗂𝗇𝗄: Click Here\n"
85 | if message.chat.type in ((enums.ChatType.SUPERGROUP, enums.ChatType.CHANNEL)):
86 | try:
87 | chat_member_p = await message.chat.get_member(from_user.id)
88 | joined_date = (
89 | chat_member_p.joined_date or datetime.now()
90 | ).strftime("%Y.%m.%d %H:%M:%S")
91 | message_out_str += (
92 | "➲Joined this Chat on: "
93 | f"{joined_date}"
94 | "
\n"
95 | )
96 | except UserNotParticipant:
97 | pass
98 | chat_photo = from_user.photo
99 | if chat_photo:
100 | local_user_photo = await client.download_media(
101 | message=chat_photo.big_file_id
102 | )
103 | buttons = [[
104 | InlineKeyboardButton('🔐 Close', callback_data='close_data')
105 | ]]
106 | reply_markup = InlineKeyboardMarkup(buttons)
107 | await message.reply_photo(
108 | photo=local_user_photo,
109 | quote=True,
110 | reply_markup=reply_markup,
111 | caption=message_out_str,
112 | parse_mode=enums.ParseMode.HTML,
113 | disable_notification=True
114 | )
115 | os.remove(local_user_photo)
116 | else:
117 | buttons = [[
118 | InlineKeyboardButton('🔐 Close', callback_data='close_data')
119 | ]]
120 | reply_markup = InlineKeyboardMarkup(buttons)
121 | await message.reply_text(
122 | text=message_out_str,
123 | reply_markup=reply_markup,
124 | quote=True,
125 | parse_mode=enums.ParseMode.HTML,
126 | disable_notification=True
127 | )
128 | await status_message.delete()
129 |
130 | @Client.on_message(filters.command(["imdb", 'search']))
131 | async def imdb_search(client, message):
132 | if ' ' in message.text:
133 | k = await message.reply('Searching ImDB')
134 | r, title = message.text.split(None, 1)
135 | movies = await get_poster(title, bulk=True)
136 | if not movies:
137 | return await message.reply("No results Found")
138 | btn = [
139 | [
140 | InlineKeyboardButton(
141 | text=f"{movie.get('title')} - {movie.get('year')}",
142 | callback_data=f"imdb#{movie.movieID}",
143 | )
144 | ]
145 | for movie in movies
146 | ]
147 | await k.edit('Here is what i found on IMDb', reply_markup=InlineKeyboardMarkup(btn))
148 | else:
149 | await message.reply('Give me a movie / series Name')
150 |
151 | @Client.on_callback_query(filters.regex('^imdb'))
152 | async def imdb_callback(bot: Client, quer_y: CallbackQuery):
153 | i, movie = quer_y.data.split('#')
154 | imdb = await get_poster(query=movie, id=True)
155 | btn = [
156 | [
157 | InlineKeyboardButton(
158 | text=f"{imdb.get('title')}",
159 | url=imdb['url'],
160 | )
161 | ]
162 | ]
163 | message = quer_y.message.reply_to_message or quer_y.message
164 | if imdb:
165 | caption = IMDB_TEMPLATE.format(
166 | query = imdb['title'],
167 | title = imdb['title'],
168 | votes = imdb['votes'],
169 | aka = imdb["aka"],
170 | seasons = imdb["seasons"],
171 | box_office = imdb['box_office'],
172 | localized_title = imdb['localized_title'],
173 | kind = imdb['kind'],
174 | imdb_id = imdb["imdb_id"],
175 | cast = imdb["cast"],
176 | runtime = imdb["runtime"],
177 | countries = imdb["countries"],
178 | certificates = imdb["certificates"],
179 | languages = imdb["languages"],
180 | director = imdb["director"],
181 | writer = imdb["writer"],
182 | producer = imdb["producer"],
183 | composer = imdb["composer"],
184 | cinematographer = imdb["cinematographer"],
185 | music_team = imdb["music_team"],
186 | distributors = imdb["distributors"],
187 | release_date = imdb['release_date'],
188 | year = imdb['year'],
189 | genres = imdb['genres'],
190 | poster = imdb['poster'],
191 | plot = imdb['plot'],
192 | rating = imdb['rating'],
193 | url = imdb['url'],
194 | **locals()
195 | )
196 | else:
197 | caption = "No Results"
198 | if imdb.get('poster'):
199 | try:
200 | await quer_y.message.reply_photo(photo=imdb['poster'], caption=caption, reply_markup=InlineKeyboardMarkup(btn))
201 | except (MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty):
202 | pic = imdb.get('poster')
203 | poster = pic.replace('.jpg', "._V1_UX360.jpg")
204 | await quer_y.message.reply_photo(photo=poster, caption=caption, reply_markup=InlineKeyboardMarkup(btn))
205 | except Exception as e:
206 | logger.exception(e)
207 | await quer_y.message.reply(caption, reply_markup=InlineKeyboardMarkup(btn), disable_web_page_preview=False)
208 | await quer_y.message.delete()
209 | else:
210 | await quer_y.message.edit(caption, reply_markup=InlineKeyboardMarkup(btn), disable_web_page_preview=False)
211 | await quer_y.answer()
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/plugins/p_ttishow.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters, enums
2 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
3 | from pyrogram.errors.exceptions.bad_request_400 import MessageTooLong, PeerIdInvalid
4 | from info import ADMINS, LOG_CHANNEL, SUPPORT_CHAT, MELCOW_NEW_USERS
5 | from database.users_chats_db import db
6 | from database.ia_filterdb import Media
7 | from utils import get_size, temp, get_settings
8 | from Script import script
9 | from pyrogram.errors import ChatAdminRequired
10 |
11 | """-------------------------------------------------------------------------------"""
12 |
13 | @Client.on_message(filters.new_chat_members & filters.group)
14 | async def save_group(bot, message):
15 | r_j_check = [u.id for u in message.new_chat_members]
16 | if temp.ME in r_j_check:
17 | if not await db.get_chat(message.chat.id):
18 | total=await bot.get_chat_members_count(message.chat.id)
19 | r_j = message.from_user.mention if message.from_user else "Anonymous"
20 | await bot.send_message(LOG_CHANNEL, script.LOG_TEXT_G.format(message.chat.title, message.chat.id, total, r_j))
21 | await db.add_chat(message.chat.id, message.chat.title)
22 | if message.chat.id in temp.BANNED_CHATS:
23 | # Inspired from a boat of a banana tree
24 | buttons = [[
25 | InlineKeyboardButton('𝚂𝚄𝙿𝙿𝙾𝚁𝚃', url=f'https://t.me/{SUPPORT_CHAT}')
26 | ]]
27 | reply_markup=InlineKeyboardMarkup(buttons)
28 | k = await message.reply(
29 | text='CHAT NOT ALLOWED 🐞\n\n𝙼𝚈 𝙰𝙳𝙼𝙸𝙽𝚂 𝙷𝙰𝚂 𝚁𝙴𝚂𝚃𝚁𝙸𝙲𝚃𝙴𝙳 𝙼𝙴 𝙵𝚁𝙾𝙼 𝚆𝙾𝚁𝙺𝙸𝙽𝙶 𝙷𝙴𝚁𝙴 !𝙸𝙵 𝚈𝙾𝚄 𝚆𝙰𝙽𝚃 𝚃𝙾 𝙺𝙽𝙾𝚆 𝙼𝙾𝚁𝙴 𝙰𝙱𝙾𝚄𝚃 𝙸𝚃 𝙲𝙾𝙽𝚃𝙰𝙲𝚃 𝙾𝚆𝙽𝙴𝚁...',
30 | reply_markup=reply_markup,
31 | )
32 |
33 | try:
34 | await k.pin()
35 | except:
36 | pass
37 | await bot.leave_chat(message.chat.id)
38 | return
39 | buttons = [[
40 | InlineKeyboardButton('𝙷𝙾𝚆 𝚃𝙾 𝚄𝚂𝙴 𝙼𝙴', url=f"https://t.me/{temp.U_NAME}?start=help"),
41 | InlineKeyboardButton('📢 UPDATES 📢', url='https://t.me/LazyDeveloper')
42 | ]]
43 | reply_markup=InlineKeyboardMarkup(buttons)
44 | await message.reply_text(
45 | text=f"›› 𝚃𝙷𝙰𝙽𝙺𝚂 𝚃𝙾 𝙰𝙳𝙳 𝙼𝙴 𝚃𝙾 𝚈𝙾𝚄𝚁 𝙶𝚁𝙾𝚄𝙿. {message.chat.title} ❣️\n›› 𝙳𝙾𝙽'𝚃 𝙵𝙾𝚁𝙶𝙴𝚃 𝚃𝙾 𝙼𝙰𝙺𝙴 𝙼𝙴 𝙰𝙳𝙼𝙸𝙽.\n›› 𝙸f 𝙰𝙽𝚈 𝙳𝙾𝚄𝙱𝚃𝚂 𝙰𝙱𝙾𝚄𝚃 𝚄𝚂𝙸𝙽𝙶 𝙼𝙴 𝙲𝙻𝙸𝙲𝙺 𝙱𝙴𝙻𝙾𝚆 𝙱𝚄𝚃𝚃𝙾𝙽..⚡⚡.",
46 | reply_markup=reply_markup)
47 | else:
48 | settings = await get_settings(message.chat.id)
49 | if settings["welcome"]:
50 | for u in message.new_chat_members:
51 | if (temp.MELCOW).get('welcome') is not None:
52 | try:
53 | await (temp.MELCOW['welcome']).delete()
54 | except:
55 | pass
56 | temp.MELCOW['welcome'] = await message.reply_video(
57 | video="https://telegra.ph/file/03691465baa774e46506d.mp4",
58 | caption=f'ʜᴇʏ, {u.mention} 👋🏻\nᴡᴇʟᴄᴏᴍᴇ ᴛᴏ ᴏᴜʀ ɢʀᴏᴜᴘ {message.chat.title}\n\nFind Any Media ! if you need any movie then then enter the movie name + years. 👍\n\nGuys Enter Only movie Or Webseries Name like This 👇\nPushpa ✅\nPushpa 2021 ✅\nPushpa in Hindi ❌\nLucifer ✅\nLucifer S01 ✅\nLucifer all season ❌',
59 | reply_markup=InlineKeyboardMarkup( [ [ InlineKeyboardButton('🔥 ↭ Main Channel ↭ 🔥', url='http://t.me/real_MoviesAdda1') ],
60 | [ InlineKeyboardButton('🔥 ↭ DEV Channel ↭ 🔥', url='http://t.me/LazyDeveloper') ]
61 | ] )
62 | )
63 |
64 | @Client.on_message(filters.command('leave') & filters.user(ADMINS))
65 | async def leave_a_chat(bot, message):
66 | if len(message.command) == 1:
67 | return await message.reply('Give me a chat id')
68 | chat = message.command[1]
69 | try:
70 | chat = int(chat)
71 | except:
72 | chat = chat
73 | try:
74 | buttons = [[
75 | InlineKeyboardButton('𝚂𝚄𝙿𝙿𝙾𝚁𝚃', url=f'https://t.me/{SUPPORT_CHAT}')
76 | ]]
77 | reply_markup=InlineKeyboardMarkup(buttons)
78 | await bot.send_message(
79 | chat_id=chat,
80 | text='Hello Friends, \nMy admin has told me to leave from group so i go! If you wanna add me again contact my support group.',
81 | reply_markup=reply_markup,
82 | )
83 |
84 | await bot.leave_chat(chat)
85 | await message.reply(f"left the chat `{chat}`")
86 | except Exception as e:
87 | await message.reply(f'Error - {e}')
88 |
89 | @Client.on_message(filters.command('disable') & filters.user(ADMINS))
90 | async def disable_chat(bot, message):
91 | if len(message.command) == 1:
92 | return await message.reply('Give me a chat id')
93 | r = message.text.split(None)
94 | if len(r) > 2:
95 | reason = message.text.split(None, 2)[2]
96 | chat = message.text.split(None, 2)[1]
97 | else:
98 | chat = message.command[1]
99 | reason = "No reason Provided"
100 | try:
101 | chat_ = int(chat)
102 | except:
103 | return await message.reply('Give Me A Valid Chat ID')
104 | cha_t = await db.get_chat(int(chat_))
105 | if not cha_t:
106 | return await message.reply("Chat Not Found In DB")
107 | if cha_t['is_disabled']:
108 | return await message.reply(f"This chat is already disabled:\nReason- {cha_t['reason']}
")
109 | await db.disable_chat(int(chat_), reason)
110 | temp.BANNED_CHATS.append(int(chat_))
111 | await message.reply('Chat Successfully Disabled')
112 | try:
113 | buttons = [[
114 | InlineKeyboardButton('𝚂𝚄𝙿𝙿𝙾𝚁𝚃', url=f'https://t.me/{SUPPORT_CHAT}')
115 | ]]
116 | reply_markup=InlineKeyboardMarkup(buttons)
117 | await bot.send_message(
118 | chat_id=chat_,
119 | text=f'Hello Friends, \nMy admin has told me to leave from group so i go! If you wanna add me again contact my support group. \nReason : {reason}
',
120 | reply_markup=reply_markup)
121 | await bot.leave_chat(chat_)
122 | except Exception as e:
123 | await message.reply(f"Error - {e}")
124 |
125 |
126 | @Client.on_message(filters.command('enable') & filters.user(ADMINS))
127 | async def re_enable_chat(bot, message):
128 | if len(message.command) == 1:
129 | return await message.reply('Give me a chat id')
130 | chat = message.command[1]
131 | try:
132 | chat_ = int(chat)
133 | except:
134 | return await message.reply('Give Me A Valid Chat ID')
135 | sts = await db.get_chat(int(chat))
136 | if not sts:
137 | return await message.reply("Chat Not Found In DB !")
138 | if not sts.get('is_disabled'):
139 | return await message.reply('This chat is not yet disabled.')
140 | await db.re_enable_chat(int(chat_))
141 | temp.BANNED_CHATS.remove(int(chat_))
142 | await message.reply("Chat Successfully re-enabled")
143 |
144 |
145 | @Client.on_message(filters.command('stats') & filters.incoming)
146 | async def get_ststs(bot, message):
147 | rju = await message.reply('𝙰𝙲𝙲𝙴𝚂𝚂𝙸𝙽𝙶 𝚂𝚃𝙰𝚃𝚄𝚂 𝙳𝙴𝚃𝙰𝙸𝙻𝚂...')
148 | total_users = await db.total_users_count()
149 | totl_chats = await db.total_chat_count()
150 | files = await Media.count_documents()
151 | size = await db.get_db_size()
152 | free = 536870912 - size
153 | size = get_size(size)
154 | free = get_size(free)
155 | await rju.edit(script.STATUS_TXT.format(files, total_users, totl_chats, size, free))
156 |
157 |
158 | # a function for trespassing into others groups, Inspired by a Vazha
159 | # Not to be used , But Just to showcase his vazhatharam.
160 | # @Client.on_message(filters.command('invite') & filters.user(ADMINS))
161 | async def gen_invite(bot, message):
162 | if len(message.command) == 1:
163 | return await message.reply('Give me a chat id')
164 | chat = message.command[1]
165 | try:
166 | chat = int(chat)
167 | except:
168 | return await message.reply('Give Me A Valid Chat ID')
169 | try:
170 | link = await bot.create_chat_invite_link(chat)
171 | except ChatAdminRequired:
172 | return await message.reply("Invite Link Generation Failed, Iam Not Having Sufficient Rights")
173 | except Exception as e:
174 | return await message.reply(f'Error {e}')
175 | await message.reply(f'Here is your Invite Link {link.invite_link}')
176 |
177 | @Client.on_message(filters.command('ban') & filters.user(ADMINS))
178 | async def ban_a_user(bot, message):
179 | # https://t.me/GetTGLink/4185
180 | if len(message.command) == 1:
181 | return await message.reply('Give me a user id / username')
182 | r = message.text.split(None)
183 | if len(r) > 2:
184 | reason = message.text.split(None, 2)[2]
185 | chat = message.text.split(None, 2)[1]
186 | else:
187 | chat = message.command[1]
188 | reason = "No reason Provided"
189 | try:
190 | chat = int(chat)
191 | except:
192 | pass
193 | try:
194 | k = await bot.get_users(chat)
195 | except PeerIdInvalid:
196 | return await message.reply("This is an invalid user, make sure ia have met him before.")
197 | except IndexError:
198 | return await message.reply("This might be a channel, make sure its a user.")
199 | except Exception as e:
200 | return await message.reply(f'Error - {e}')
201 | else:
202 | jar = await db.get_ban_status(k.id)
203 | if jar['is_banned']:
204 | return await message.reply(f"{k.mention} is already banned\nReason: {jar['ban_reason']}")
205 | await db.ban_user(k.id, reason)
206 | temp.BANNED_USERS.append(k.id)
207 | await message.reply(f"Successfully banned {k.mention}")
208 |
209 |
210 |
211 | @Client.on_message(filters.command('unban') & filters.user(ADMINS))
212 | async def unban_a_user(bot, message):
213 | if len(message.command) == 1:
214 | return await message.reply('Give me a user id / username')
215 | r = message.text.split(None)
216 | if len(r) > 2:
217 | reason = message.text.split(None, 2)[2]
218 | chat = message.text.split(None, 2)[1]
219 | else:
220 | chat = message.command[1]
221 | reason = "No reason Provided"
222 | try:
223 | chat = int(chat)
224 | except:
225 | pass
226 | try:
227 | k = await bot.get_users(chat)
228 | except PeerIdInvalid:
229 | return await message.reply("This is an invalid user, make sure ia have met him before.")
230 | except IndexError:
231 | return await message.reply("Thismight be a channel, make sure its a user.")
232 | except Exception as e:
233 | return await message.reply(f'Error - {e}')
234 | else:
235 | jar = await db.get_ban_status(k.id)
236 | if not jar['is_banned']:
237 | return await message.reply(f"{k.mention} is not yet banned.")
238 | await db.remove_ban(k.id)
239 | temp.BANNED_USERS.remove(k.id)
240 | await message.reply(f"Successfully unbanned {k.mention}")
241 |
242 |
243 |
244 | @Client.on_message(filters.command('users') & filters.user(ADMINS))
245 | async def list_users(bot, message):
246 | # https://t.me/GetTGLink/4184
247 | raju = await message.reply('Getting List Of Users')
248 | users = await db.get_all_users()
249 | out = "Users Saved In DB Are:\n\n"
250 | async for user in users:
251 | out += f"{user['name']}"
252 | if user['ban_status']['is_banned']:
253 | out += '( Banned User )'
254 | out += '\n'
255 | try:
256 | await raju.edit_text(out)
257 | except MessageTooLong:
258 | with open('users.txt', 'w+') as outfile:
259 | outfile.write(out)
260 | await message.reply_document('users.txt', caption="List Of Users")
261 |
262 | @Client.on_message(filters.command('chats') & filters.user(ADMINS))
263 | async def list_chats(bot, message):
264 | raju = await message.reply('Getting List Of chats')
265 | chats = await db.get_all_chats()
266 | out = "Chats Saved In DB Are:\n\n"
267 | async for chat in chats:
268 | out += f"**Title:** `{chat['title']}`\n**- ID:** `{chat['id']}`"
269 | if chat['chat_status']['is_disabled']:
270 | out += '( Disabled Chat )'
271 | out += '\n'
272 | try:
273 | await raju.edit_text(out)
274 | except MessageTooLong:
275 | with open('chats.txt', 'w+') as outfile:
276 | outfile.write(out)
277 | await message.reply_document('chats.txt', caption="List Of Chats")
278 |
--------------------------------------------------------------------------------
/plugins/pm_filter.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import re
3 | import ast
4 | import math
5 | from utils import get_shortlink
6 | from pyrogram.errors.exceptions.bad_request_400 import MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty
7 | from Script import script
8 | import pyrogram
9 | from database.connections_mdb import active_connection, all_connections, delete_connection, if_active, make_active, \
10 | make_inactive
11 | from info import *
12 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
13 | from pyrogram import Client, filters, enums
14 | from pyrogram.errors import FloodWait, UserIsBlocked, MessageNotModified, PeerIdInvalid
15 | from utils import get_size, is_subscribed, get_poster, search_gagala, temp, get_settings, save_group_settings
16 | from database.users_chats_db import db
17 | from database.ia_filterdb import Media, get_file_details, get_search_results
18 | from database.filters_mdb import (
19 | del_all,
20 | find_filter,
21 | get_filters,
22 | )
23 | import logging
24 |
25 | logger = logging.getLogger(__name__)
26 | logger.setLevel(logging.ERROR)
27 |
28 | BUTTONS = {}
29 | SPELL_CHECK = {}
30 | FILTER_MODE = {}
31 |
32 | @Client.on_message(filters.command('autofilter'))
33 | async def fil_mod(client, message):
34 | mode_on = ["yes", "on", "true"]
35 | mode_of = ["no", "off", "false"]
36 |
37 | try:
38 | args = message.text.split(None, 1)[1].lower()
39 | except:
40 | return await message.reply("**𝙸𝙽𝙲𝙾𝙼𝙿𝙻𝙴𝚃𝙴 𝙲𝙾𝙼𝙼𝙰𝙽𝙳...**")
41 |
42 | m = await message.reply("**𝚂𝙴𝚃𝚃𝙸𝙽𝙶.../**")
43 |
44 | if args in mode_on:
45 | FILTER_MODE[str(message.chat.id)] = "True"
46 | await m.edit("**𝙰𝚄𝚃𝙾𝙵𝙸𝙻𝚃𝙴𝚁 𝙴𝙽𝙰𝙱𝙻𝙴𝙳**")
47 |
48 | elif args in mode_of:
49 | FILTER_MODE[str(message.chat.id)] = "False"
50 | await m.edit("**𝙰𝚄𝚃𝙾𝙵𝙸𝙻𝚃𝙴𝚁 𝙳𝙸𝚂𝙰𝙱𝙻𝙴𝙳**")
51 | else:
52 | await m.edit("USE :- /autofilter on 𝙾𝚁 /autofilter off")
53 |
54 | @Client.on_message((filters.group | filters.private) & filters.text & filters.incoming)
55 | async def give_filter(client, message):
56 | k = await manual_filters(client, message)
57 | if k == False:
58 | await auto_filter(client, message)
59 |
60 |
61 | @Client.on_callback_query(filters.regex(r"^next"))
62 | async def next_page(bot, query):
63 | ident, req, key, offset = query.data.split("_")
64 | if int(req) not in [query.from_user.id, 0]:
65 | return await query.answer("oKda", show_alert=True)
66 | try:
67 | offset = int(offset)
68 | except:
69 | offset = 0
70 | search = BUTTONS.get(key)
71 | if not search:
72 | await query.answer("You are using one of my old messages, please send the request again.", show_alert=True)
73 | return
74 |
75 | files, n_offset, total = await get_search_results(search, offset=offset, filter=True)
76 | try:
77 | n_offset = int(n_offset)
78 | except:
79 | n_offset = 0
80 |
81 | if not files:
82 | return
83 | settings = await get_settings(query.message.chat.id)
84 | if settings['button']:
85 | btn = [
86 | [
87 | InlineKeyboardButton(
88 | text=f"[{get_size(file.file_size)}] {file.file_name}",
89 | url=await get_shortlink(f"https://telegram.dog/{temp.U_NAME}?start=files_{file.file_id}")
90 | ),
91 | ]
92 | for file in files
93 | ]
94 | else:
95 | btn = [
96 | [
97 | InlineKeyboardButton(
98 | text=f"[{get_size(file.file_size)}] {file.file_name}",
99 | url=await get_shortlink(f"https://telegram.dog/{temp.U_NAME}?start=files_{file.file_id}")
100 | ),
101 | InlineKeyboardButton(
102 | text=f"[{get_size(file.file_size)}] {file.file_name}",
103 | url=await get_shortlink(f"https://telegram.dog/{temp.U_NAME}?start=files_{file.file_id}")
104 | ),
105 | ]
106 | for file in files
107 | ]
108 |
109 | btn.insert(0,
110 | [
111 | InlineKeyboardButton(text="⚡ʜᴏᴡ ᴛᴏ ᴅᴏᴡɴʟᴏᴀᴅ⚡", url='https://telegram.me/LazyDeveloper')
112 | ]
113 | )
114 |
115 | if 0 < offset <= 10:
116 | off_set = 0
117 | elif offset == 0:
118 | off_set = None
119 | else:
120 | off_set = offset - 10
121 | if n_offset == 0:
122 | btn.append(
123 | [InlineKeyboardButton("⏪ 𝗕𝗮𝗰𝗸", callback_data=f"next_{req}_{key}_{off_set}"),
124 | InlineKeyboardButton(f"📃 𝗣𝗮𝗴𝗲s {math.ceil(int(offset) / 10) + 1} / {math.ceil(total / 10)}",
125 | callback_data="pages")]
126 | )
127 | elif off_set is None:
128 | btn.append(
129 | [InlineKeyboardButton(f"🗓 {math.ceil(int(offset) / 10) + 1} / {math.ceil(total / 10)}", callback_data="pages"),
130 | InlineKeyboardButton("𝗡𝗲𝘅𝘁 ➡️", callback_data=f"next_{req}_{key}_{n_offset}")])
131 | else:
132 | btn.append(
133 | [
134 | InlineKeyboardButton("⏪ 𝗕𝗮𝗰𝗸", callback_data=f"next_{req}_{key}_{off_set}"),
135 | InlineKeyboardButton(f"🗓 {math.ceil(int(offset) / 10) + 1} / {math.ceil(total / 10)}", callback_data="pages"),
136 | InlineKeyboardButton("𝗡𝗲𝘅𝘁 ➡️", callback_data=f"next_{req}_{key}_{n_offset}")
137 | ],
138 | )
139 | try:
140 | await query.edit_message_reply_markup(
141 | reply_markup=InlineKeyboardMarkup(btn)
142 | )
143 | except MessageNotModified:
144 | pass
145 | await query.answer()
146 |
147 |
148 | @Client.on_callback_query(filters.regex(r"^spolling"))
149 | async def advantage_spoll_choker(bot, query):
150 | _, user, movie_ = query.data.split('#')
151 | if int(user) != 0 and query.from_user.id != int(user):
152 | return await query.answer("😁 𝗛𝗲𝘆 𝗙𝗿𝗶𝗲𝗻𝗱,𝗣𝗹𝗲𝗮𝘀𝗲 𝗦𝗲𝗮𝗿𝗰𝗵 𝗬𝗼𝘂𝗿𝘀𝗲𝗹𝗳.", show_alert=True)
153 | if movie_ == "close_spellcheck":
154 | return await query.message.delete()
155 | movies = SPELL_CHECK.get(query.message.reply_to_message.id)
156 | if not movies:
157 | return await query.answer("𝐋𝐢𝐧𝐤 𝐄𝐱𝐩𝐢𝐫𝐞𝐝 𝐊𝐢𝐧𝐝𝐥𝐲 𝐏𝐥𝐞𝐚𝐬𝐞 𝐒𝐞𝐚𝐫𝐜𝐡 𝐀𝐠𝐚𝐢𝐧 🙂.", show_alert=True)
158 | movie = movies[(int(movie_))]
159 | await query.answer('𝙲𝙷𝙴𝙲𝙺𝙸𝙽𝙶 𝙵𝙸𝙻𝙴 𝙾𝙽 𝙼𝚈 𝙳𝙰𝚃𝙰𝙱𝙰𝚂𝙴...//')
160 | k = await manual_filters(bot, query.message, text=movie)
161 | if k == False:
162 | files, offset, total_results = await get_search_results(movie, offset=0, filter=True)
163 | if files:
164 | k = (movie, files, offset, total_results)
165 | await auto_filter(bot, query, k)
166 | else:
167 | k = await query.message.edit('𝚃𝙷𝙸𝚂 𝙼𝙾𝚅𝙸𝙴 I𝚂 𝙽𝙾𝚃 𝚈𝙴𝚃 𝚁𝙴𝙻𝙴𝙰𝚂𝙴𝙳 𝙾𝚁 𝙰𝙳𝙳𝙴𝙳 𝚃𝙾 𝙳𝙰𝚃𝚂𝙱𝙰𝚂𝙴 💌')
168 | await asyncio.sleep(10)
169 | await k.delete()
170 |
171 |
172 | @Client.on_callback_query()
173 | async def cb_handler(client: Client, query: CallbackQuery):
174 | if query.data == "close_data":
175 | await query.message.delete()
176 | elif query.data == "delallconfirm":
177 | userid = query.from_user.id
178 | chat_type = query.message.chat.type
179 |
180 | if chat_type == enums.ChatType.PRIVATE:
181 | grpid = await active_connection(str(userid))
182 | if grpid is not None:
183 | grp_id = grpid
184 | try:
185 | chat = await client.get_chat(grpid)
186 | title = chat.title
187 | except:
188 | await query.message.edit_text("Make sure I'm present in your group!!", quote=True)
189 | return await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
190 | else:
191 | await query.message.edit_text(
192 | "I'm not connected to any groups!\nCheck /connections or connect to any groups",
193 | quote=True
194 | )
195 | return await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
196 |
197 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
198 | grp_id = query.message.chat.id
199 | title = query.message.chat.title
200 |
201 | else:
202 | return await query.answer('Piracy Is Crime')
203 |
204 | st = await client.get_chat_member(grp_id, userid)
205 | if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS):
206 | await del_all(query.message, grp_id, title)
207 | else:
208 | await query.answer("You need to be Group Owner or an Auth User to do that!", show_alert=True)
209 | elif query.data == "delallcancel":
210 | userid = query.from_user.id
211 | chat_type = query.message.chat.type
212 |
213 | if chat_type == enums.ChatType.PRIVATE:
214 | await query.message.reply_to_message.delete()
215 | await query.message.delete()
216 |
217 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
218 | grp_id = query.message.chat.id
219 | st = await client.get_chat_member(grp_id, userid)
220 | if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS):
221 | await query.message.delete()
222 | try:
223 | await query.message.reply_to_message.delete()
224 | except:
225 | pass
226 | else:
227 | await query.answer("Buddy Don't Touch Others Property 😁", show_alert=True)
228 | elif "groupcb" in query.data:
229 | await query.answer()
230 |
231 | group_id = query.data.split(":")[1]
232 |
233 | act = query.data.split(":")[2]
234 | hr = await client.get_chat(int(group_id))
235 | title = hr.title
236 | user_id = query.from_user.id
237 |
238 | if act == "":
239 | stat = "𝙲𝙾𝙽𝙽𝙴𝙲𝚃"
240 | cb = "connectcb"
241 | else:
242 | stat = "𝙳𝙸𝚂𝙲𝙾𝙽𝙽𝙴𝙲𝚃"
243 | cb = "disconnect"
244 |
245 | keyboard = InlineKeyboardMarkup([
246 | [InlineKeyboardButton(f"{stat}", callback_data=f"{cb}:{group_id}"),
247 | InlineKeyboardButton("𝙳𝙴𝙻𝙴𝚃𝙴", callback_data=f"deletecb:{group_id}")],
248 | [InlineKeyboardButton("𝙱𝙰𝙲𝙺", callback_data="backcb")]
249 | ])
250 |
251 | await query.message.edit_text(
252 | f"𝙶𝚁𝙾𝚄𝙿 𝙽𝙰𝙼𝙴 :- **{title}**\n𝙶𝚁𝙾𝚄𝙿 𝙸𝙳 :- `{group_id}`",
253 | reply_markup=keyboard,
254 | parse_mode=enums.ParseMode.MARKDOWN
255 | )
256 | return await query.answer('Piracy Is Crime')
257 | elif "connectcb" in query.data:
258 | await query.answer()
259 |
260 | group_id = query.data.split(":")[1]
261 |
262 | hr = await client.get_chat(int(group_id))
263 |
264 | title = hr.title
265 |
266 | user_id = query.from_user.id
267 |
268 | mkact = await make_active(str(user_id), str(group_id))
269 |
270 | if mkact:
271 | await query.message.edit_text(
272 | f"𝙲𝙾𝙽𝙽𝙴𝙲𝚃𝙴𝙳 𝚃𝙾 **{title}**",
273 | parse_mode=enums.ParseMode.MARKDOWN
274 | )
275 | else:
276 | await query.message.edit_text('Some error occurred!!', parse_mode=enums.ParseMode.MARKDOWN)
277 | return await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
278 | elif "disconnect" in query.data:
279 | await query.answer()
280 |
281 | group_id = query.data.split(":")[1]
282 |
283 | hr = await client.get_chat(int(group_id))
284 |
285 | title = hr.title
286 | user_id = query.from_user.id
287 |
288 | mkinact = await make_inactive(str(user_id))
289 |
290 | if mkinact:
291 | await query.message.edit_text(
292 | f"𝙳𝙸𝚂𝙲𝙾𝙽𝙽𝙴𝙲𝚃 FROM **{title}**",
293 | parse_mode=enums.ParseMode.MARKDOWN
294 | )
295 | else:
296 | await query.message.edit_text(
297 | f"Some error occurred!!",
298 | parse_mode=enums.ParseMode.MARKDOWN
299 | )
300 | return await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
301 | elif "deletecb" in query.data:
302 | await query.answer()
303 |
304 | user_id = query.from_user.id
305 | group_id = query.data.split(":")[1]
306 |
307 | delcon = await delete_connection(str(user_id), str(group_id))
308 |
309 | if delcon:
310 | await query.message.edit_text(
311 | "Successfully deleted connection"
312 | )
313 | else:
314 | await query.message.edit_text(
315 | f"Some error occurred!!",
316 | parse_mode=enums.ParseMode.MARKDOWN
317 | )
318 | return await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
319 | elif query.data == "backcb":
320 | await query.answer()
321 |
322 | userid = query.from_user.id
323 |
324 | groupids = await all_connections(str(userid))
325 | if groupids is None:
326 | await query.message.edit_text(
327 | "There are no active connections!! Connect to some groups first.",
328 | )
329 | return await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
330 | buttons = []
331 | for groupid in groupids:
332 | try:
333 | ttl = await client.get_chat(int(groupid))
334 | title = ttl.title
335 | active = await if_active(str(userid), str(groupid))
336 | act = " - ACTIVE" if active else ""
337 | buttons.append(
338 | [
339 | InlineKeyboardButton(
340 | text=f"{title}{act}", callback_data=f"groupcb:{groupid}:{act}"
341 | )
342 | ]
343 | )
344 | except:
345 | pass
346 | if buttons:
347 | await query.message.edit_text(
348 | "Your connected group details ;\n\n",
349 | reply_markup=InlineKeyboardMarkup(buttons)
350 | )
351 | elif "alertmessage" in query.data:
352 | grp_id = query.message.chat.id
353 | i = query.data.split(":")[1]
354 | keyword = query.data.split(":")[2]
355 | reply_text, btn, alerts, fileid = await find_filter(grp_id, keyword)
356 | if alerts is not None:
357 | alerts = ast.literal_eval(alerts)
358 | alert = alerts[int(i)]
359 | alert = alert.replace("\\n", "\n").replace("\\t", "\t")
360 | await query.answer(alert, show_alert=True)
361 | if query.data.startswith("file"):
362 | ident, file_id = query.data.split("#")
363 | files_ = await get_file_details(file_id)
364 | if not files_:
365 | return await query.answer('No such file exist.')
366 | files = files_[0]
367 | title = files.file_name
368 | size = get_size(files.file_size)
369 | f_caption = files.caption
370 | settings = await get_settings(query.message.chat.id)
371 | if CUSTOM_FILE_CAPTION:
372 | try:
373 | f_caption = CUSTOM_FILE_CAPTION.format(file_name='' if title is None else title,
374 | file_size='' if size is None else size,
375 | file_caption='' if f_caption is None else f_caption)
376 | except Exception as e:
377 | logger.exception(e)
378 | f_caption = f_caption
379 | if f_caption is None:
380 | f_caption = f"{files.file_name}"
381 |
382 | try:
383 | if AUTH_CHANNEL and not await is_subscribed(client, query):
384 | await query.answer(url=f"https://telegram.dog/{temp.U_NAME}?start={ident}_{file_id}")
385 | return
386 | elif settings['botpm']:
387 | await query.answer(url=f"https://telegram.dog/{temp.U_NAME}?start={ident}_{file_id}")
388 | return
389 | else:
390 | await client.send_cached_media(
391 | chat_id=query.from_user.id,
392 | file_id=file_id,
393 | caption=f_caption,
394 | protect_content=True if ident == "filep" else False
395 | )
396 | await query.answer('Check PM, I have sent files in pm', show_alert=True)
397 | except UserIsBlocked:
398 | await query.answer('You Are Blocked to use me !', show_alert=True)
399 | except PeerIdInvalid:
400 | await query.answer(url=f"https://telegram.dog/{temp.U_NAME}?start={ident}_{file_id}")
401 | except Exception as e:
402 | await query.answer(url=f"https://telegram.dog/{temp.U_NAME}?start={ident}_{file_id}")
403 | elif query.data.startswith("checksub"):
404 | if AUTH_CHANNEL and not await is_subscribed(client, query):
405 | await query.answer("I Like Your Smartness, But Don't Be Oversmart Okay 😒", show_alert=True)
406 | return
407 | ident, file_id = query.data.split("#")
408 | files_ = await get_file_details(file_id)
409 | if not files_:
410 | return await query.answer('No such file exist.')
411 | files = files_[0]
412 | title = files.file_name
413 | size = get_size(files.file_size)
414 | f_caption = files.caption
415 | if CUSTOM_FILE_CAPTION:
416 | try:
417 | f_caption = CUSTOM_FILE_CAPTION.format(file_name='' if title is None else title,
418 | file_size='' if size is None else size,
419 | file_caption='' if f_caption is None else f_caption)
420 | except Exception as e:
421 | logger.exception(e)
422 | f_caption = f_caption
423 | if f_caption is None:
424 | f_caption = f"{title}"
425 | await query.answer()
426 | await client.send_cached_media(
427 | chat_id=query.from_user.id,
428 | file_id=file_id,
429 | caption=f_caption,
430 | protect_content=True if ident == 'checksubp' else False
431 | )
432 | elif query.data == "pages":
433 | await query.answer()
434 | elif query.data == "start":
435 | buttons = [[
436 | InlineKeyboardButton('➕↖️ Add Me To Your Groups ↗️➕', url=f'http://t.me/{temp.U_NAME}?startgroup=true')
437 | ],[
438 | InlineKeyboardButton('⚡ Movie Updates ⚡', url=f"https://telegram.me/real_MoviesAdda1"),
439 | InlineKeyboardButton('🔔 BOT Updates 🤖', url='https://t.me/LazyDeveloper')
440 | ],[
441 | InlineKeyboardButton('🙆🏻 Help 🦾', callback_data='help'),
442 | InlineKeyboardButton('♥️ About ♥️', callback_data='about')
443 | ]]
444 | reply_markup = InlineKeyboardMarkup(buttons)
445 | await query.message.edit_text(
446 | text=script.START_TXT.format(query.from_user.mention, temp.U_NAME, temp.B_NAME),
447 | reply_markup=reply_markup,
448 | parse_mode=enums.ParseMode.HTML
449 | )
450 | await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
451 | elif query.data == "help":
452 | buttons = [[
453 | InlineKeyboardButton('𝙼𝙰𝙽𝚄𝙴𝙻 𝙵𝙸𝙻𝚃𝙴𝚁', callback_data='manuelfilter'),
454 | InlineKeyboardButton('𝙰𝚄𝚃𝙾 𝙵𝙸𝙻𝚃𝙴𝚁', callback_data='autofilter')
455 | ], [
456 | InlineKeyboardButton('𝙲𝙾𝙽𝙽𝙴𝙲𝚃𝙸𝙾𝙽𝚂', callback_data='coct'),
457 | InlineKeyboardButton('𝙴𝚇𝚃𝚁𝙰 𝙼𝙾D𝚂', callback_data='extra')
458 | ], [
459 | InlineKeyboardButton('🏠 H𝙾𝙼𝙴 🏠', callback_data='start'),
460 | ]]
461 | reply_markup = InlineKeyboardMarkup(buttons)
462 | await query.message.edit_text(
463 | text=script.HELP_TXT.format(query.from_user.mention),
464 | reply_markup=reply_markup,
465 | parse_mode=enums.ParseMode.HTML
466 | )
467 | elif query.data == "about":
468 | buttons = [[
469 | InlineKeyboardButton('🏠 H𝙾𝙼𝙴 🏠', callback_data='start'),
470 | ]]
471 | reply_markup = InlineKeyboardMarkup(buttons)
472 | await query.message.edit_text(
473 | text=script.ABOUT_TXT.format(temp.B_NAME),
474 | reply_markup=reply_markup,
475 | parse_mode=enums.ParseMode.HTML
476 | )
477 | elif query.data == "source":
478 | buttons = [[
479 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='about')
480 | ]]
481 | reply_markup = InlineKeyboardMarkup(buttons)
482 | await query.message.edit_text(
483 | text=script.SOURCE_TXT,
484 | reply_markup=reply_markup,
485 | parse_mode=enums.ParseMode.HTML
486 | )
487 | elif query.data == "manuelfilter":
488 | buttons = [[
489 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='help'),
490 | InlineKeyboardButton('⏹️ 𝙱𝚄𝚃𝚃𝙾𝙽𝚂', callback_data='button')
491 | ]]
492 | reply_markup = InlineKeyboardMarkup(buttons)
493 | await query.message.edit_text(
494 | text=script.MANUELFILTER_TXT,
495 | reply_markup=reply_markup,
496 | parse_mode=enums.ParseMode.HTML
497 | )
498 | elif query.data == "button":
499 | buttons = [[
500 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='manuelfilter')
501 | ]]
502 | reply_markup = InlineKeyboardMarkup(buttons)
503 | await query.message.edit_text(
504 | text=script.BUTTON_TXT,
505 | reply_markup=reply_markup,
506 | parse_mode=enums.ParseMode.HTML
507 | )
508 | elif query.data == "autofilter":
509 | buttons = [[
510 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='help')
511 | ]]
512 | reply_markup = InlineKeyboardMarkup(buttons)
513 | await query.message.edit_text(
514 | text=script.AUTOFILTER_TXT,
515 | reply_markup=reply_markup,
516 | parse_mode=enums.ParseMode.HTML
517 | )
518 | elif query.data == "coct":
519 | buttons = [[
520 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='help')
521 | ]]
522 | reply_markup = InlineKeyboardMarkup(buttons)
523 | await query.message.edit_text(
524 | text=script.CONNECTION_TXT,
525 | reply_markup=reply_markup,
526 | parse_mode=enums.ParseMode.HTML
527 | )
528 | elif query.data == "extra":
529 | buttons = [[
530 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='help'),
531 | InlineKeyboardButton('👮♂️ 𝙰𝙳𝙼𝙸𝙽', callback_data='admin')
532 | ]]
533 | reply_markup = InlineKeyboardMarkup(buttons)
534 | await query.message.edit_text(
535 | text=script.EXTRAMOD_TXT,
536 | reply_markup=reply_markup,
537 | parse_mode=enums.ParseMode.HTML
538 | )
539 | elif query.data == "admin":
540 | buttons = [[
541 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='extra')
542 | ]]
543 | reply_markup = InlineKeyboardMarkup(buttons)
544 | await query.message.edit_text(
545 | text=script.ADMIN_TXT,
546 | reply_markup=reply_markup,
547 | parse_mode=enums.ParseMode.HTML
548 | )
549 | elif query.data == "stats":
550 | buttons = [[
551 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='help'),
552 | InlineKeyboardButton('♻️ 𝚁𝙴𝙵𝚁𝙴𝚂𝙷', callback_data='rfrsh')
553 | ]]
554 | reply_markup = InlineKeyboardMarkup(buttons)
555 | total = await Media.count_documents()
556 | users = await db.total_users_count()
557 | chats = await db.total_chat_count()
558 | monsize = await db.get_db_size()
559 | free = 536870912 - monsize
560 | monsize = get_size(monsize)
561 | free = get_size(free)
562 | await query.message.edit_text(
563 | text=script.STATUS_TXT.format(total, users, chats, monsize, free),
564 | reply_markup=reply_markup,
565 | parse_mode=enums.ParseMode.HTML
566 | )
567 | elif query.data == "rfrsh":
568 | await query.answer("Fetching MongoDb DataBase")
569 | buttons = [[
570 | InlineKeyboardButton('👩🦯 𝙱𝙰𝙲𝙺', callback_data='help'),
571 | InlineKeyboardButton('♻️ 𝚁𝙴𝙵𝚁𝙴𝚂𝙷', callback_data='rfrsh')
572 | ]]
573 | reply_markup = InlineKeyboardMarkup(buttons)
574 | total = await Media.count_documents()
575 | users = await db.total_users_count()
576 | chats = await db.total_chat_count()
577 | monsize = await db.get_db_size()
578 | free = 536870912 - monsize
579 | monsize = get_size(monsize)
580 | free = get_size(free)
581 | await query.message.edit_text(
582 | text=script.STATUS_TXT.format(total, users, chats, monsize, free),
583 | reply_markup=reply_markup,
584 | parse_mode=enums.ParseMode.HTML
585 | )
586 | elif query.data.startswith("setgs"):
587 | ident, set_type, status, grp_id = query.data.split("#")
588 | grpid = await active_connection(str(query.from_user.id))
589 |
590 | if str(grp_id) != str(grpid):
591 | await query.message.edit("Your Active Connection Has Been Changed. Go To /settings.")
592 | return await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
593 |
594 | if status == "True":
595 | await save_group_settings(grpid, set_type, False)
596 | else:
597 | await save_group_settings(grpid, set_type, True)
598 |
599 | settings = await get_settings(grpid)
600 |
601 | if settings is not None:
602 | buttons = [
603 | [
604 | InlineKeyboardButton('𝐅𝐈𝐋𝐓𝐄𝐑 𝐁𝐔𝐓𝐓𝐎𝐍',
605 | callback_data=f'setgs#button#{settings["button"]}#{str(grp_id)}'),
606 | InlineKeyboardButton('𝐒𝐈𝐍𝐆𝐋𝐄' if settings["button"] else '𝐃𝐎𝐔𝐁𝐋𝐄',
607 | callback_data=f'setgs#button#{settings["button"]}#{str(grp_id)}')
608 | ],
609 | [
610 | InlineKeyboardButton('𝐁𝐎𝐓 𝐏𝐌', callback_data=f'setgs#botpm#{settings["botpm"]}#{str(grp_id)}'),
611 | InlineKeyboardButton('✅ 𝐘𝐄𝐒' if settings["botpm"] else '❌ 𝐍𝐎',
612 | callback_data=f'setgs#botpm#{settings["botpm"]}#{str(grp_id)}')
613 | ],
614 | [
615 | InlineKeyboardButton('𝐅𝐈𝐋𝐄 𝐒𝐄𝐂𝐔𝐑𝐄',
616 | callback_data=f'setgs#file_secure#{settings["file_secure"]}#{str(grp_id)}'),
617 | InlineKeyboardButton('✅ 𝐘𝐄𝐒' if settings["file_secure"] else '❌ 𝐍𝐎',
618 | callback_data=f'setgs#file_secure#{settings["file_secure"]}#{str(grp_id)}')
619 | ],
620 | [
621 | InlineKeyboardButton('𝐈𝐌𝐃𝐁', callback_data=f'setgs#imdb#{settings["imdb"]}#{str(grp_id)}'),
622 | InlineKeyboardButton('✅ 𝐘𝐄𝐒' if settings["imdb"] else '❌ 𝐍𝐎',
623 | callback_data=f'setgs#imdb#{settings["imdb"]}#{str(grp_id)}')
624 | ],
625 | [
626 | InlineKeyboardButton('𝐒𝐏𝐄𝐋𝐋 𝐂𝐇𝐄𝐂𝐊',
627 | callback_data=f'setgs#spell_check#{settings["spell_check"]}#{str(grp_id)}'),
628 | InlineKeyboardButton('✅ 𝐘𝐄𝐒' if settings["spell_check"] else '❌ 𝐍𝐎',
629 | callback_data=f'setgs#spell_check#{settings["spell_check"]}#{str(grp_id)}')
630 | ],
631 | [
632 | InlineKeyboardButton('𝐖𝐄𝐋𝐂𝐎𝐌𝐄', callback_data=f'setgs#welcome#{settings["welcome"]}#{str(grp_id)}'),
633 | InlineKeyboardButton('✅ 𝐘𝐄𝐒' if settings["welcome"] else '❌ 𝐍𝐎',
634 | callback_data=f'setgs#welcome#{settings["welcome"]}#{str(grp_id)}')
635 | ]
636 | ]
637 | reply_markup = InlineKeyboardMarkup(buttons)
638 | await query.message.edit_reply_markup(reply_markup)
639 | await query.answer('𝙿𝙻𝙴𝙰𝚂𝙴 𝚂𝙷𝙰𝚁𝙴 𝙰𝙽𝙳 𝚂𝚄𝙿𝙿𝙾𝚁𝚃')
640 |
641 |
642 | async def auto_filter(client, msg, spoll=False):
643 | if not spoll:
644 | message = msg
645 | settings = await get_settings(message.chat.id)
646 | if message.text.startswith("/"): return # ignore commands
647 | if re.findall("((^\/|^,|^!|^\.|^[\U0001F600-\U000E007F]).*)", message.text):
648 | return
649 | if 2 < len(message.text) < 100:
650 | search = message.text
651 | files, offset, total_results = await get_search_results(search.lower(), offset=0, filter=True)
652 | if not files:
653 | if settings["spell_check"]:
654 | return await advantage_spell_chok(msg)
655 | else:
656 | return
657 | else:
658 | return
659 | else:
660 | settings = await get_settings(msg.message.chat.id)
661 | message = msg.message.reply_to_message # msg will be callback query
662 | search, files, offset, total_results = spoll
663 | pre = 'filep' if settings['file_secure'] else 'file'
664 | if settings["button"]:
665 | btn = [
666 | [
667 | InlineKeyboardButton(
668 | text=f"[{get_size(file.file_size)}] {file.file_name}",
669 | url=await get_shortlink(f"https://telegram.dog/{temp.U_NAME}?start=files_{file.file_id}")
670 | ),
671 | ]
672 | for file in files
673 | ]
674 | else:
675 | btn = [
676 | [
677 | InlineKeyboardButton(
678 | text=f"[{get_size(file.file_size)}] {file.file_name}",
679 | url=await get_shortlink(f"https://telegram.dog/{temp.U_NAME}?start=files_{file.file_id}")
680 | ),
681 | InlineKeyboardButton(
682 | text=f"[{get_size(file.file_size)}] {file.file_name}",
683 | url=await get_shortlink(f"https://telegram.dog/{temp.U_NAME}?start=files_{file.file_id}")
684 | ),
685 | ]
686 | for file in files
687 | ]
688 |
689 | btn.insert(0,
690 | [
691 | InlineKeyboardButton(text="⚡ʜᴏᴡ ᴛᴏ ᴅᴏᴡɴʟᴏᴀᴅ⚡", url='https://telegram.me/LazyDeveloper')
692 | ]
693 | )
694 |
695 | if offset != "":
696 | key = f"{message.chat.id}-{message.id}"
697 | BUTTONS[key] = search
698 | req = message.from_user.id if message.from_user else 0
699 | btn.append(
700 | [InlineKeyboardButton(text=f"🗓 1/{math.ceil(int(total_results) / 10)}", callback_data="pages"),
701 | InlineKeyboardButton(text="𝗡𝗲𝘅𝘁 ⏩", callback_data=f"next_{req}_{key}_{offset}")]
702 | )
703 | else:
704 | btn.append(
705 | [InlineKeyboardButton(text="🗓 1/1", callback_data="pages")]
706 | )
707 | imdb = await get_poster(search, file=(files[0]).file_name) if settings["imdb"] else None
708 | TEMPLATE = settings['template']
709 | if imdb:
710 | cap = TEMPLATE.format(
711 | query=search,
712 | title=imdb['title'],
713 | votes=imdb['votes'],
714 | aka=imdb["aka"],
715 | seasons=imdb["seasons"],
716 | box_office=imdb['box_office'],
717 | localized_title=imdb['localized_title'],
718 | kind=imdb['kind'],
719 | imdb_id=imdb["imdb_id"],
720 | cast=imdb["cast"],
721 | runtime=imdb["runtime"],
722 | countries=imdb["countries"],
723 | certificates=imdb["certificates"],
724 | languages=imdb["languages"],
725 | director=imdb["director"],
726 | writer=imdb["writer"],
727 | producer=imdb["producer"],
728 | composer=imdb["composer"],
729 | cinematographer=imdb["cinematographer"],
730 | music_team=imdb["music_team"],
731 | distributors=imdb["distributors"],
732 | release_date=imdb['release_date'],
733 | year=imdb['year'],
734 | genres=imdb['genres'],
735 | poster=imdb['poster'],
736 | plot=imdb['plot'],
737 | rating=imdb['rating'],
738 | url=imdb['url'],
739 | **locals()
740 | )
741 | else:
742 | cap = f"Rᴇǫᴜᴇsᴛᴇᴅ ᴍᴏᴠɪᴇ ɴᴀᴍᴇ : {search}
\n\n\n😌 ɪꜰ ᴛʜᴇ ᴍᴏᴠɪᴇ ʏᴏᴜ ᴀʀᴇ ʟᴏᴏᴋɪɴɢ ꜰᴏʀ ɪs ɴᴏᴛ ᴀᴠᴀɪʟᴀʙʟᴇ ᴛʜᴇɴ ʟᴇᴀᴠᴇ ᴀ ᴍᴇssᴀɢᴇ ʙᴇʟᴏᴡ 😌 \n\nᴇxᴀᴍᴘʟᴇ : \n\nᴇɴᴛᴇʀ ʏᴏᴜʀ ᴍᴏᴠɪᴇ ɴᴀᴍᴇ (ʏᴇᴀʀ) ᴛᴀɢ @admin"
743 | if imdb and imdb.get('poster'):
744 | try:
745 | hehe = await message.reply_photo(photo=imdb.get('poster'), caption=cap[:1024],
746 | reply_markup=InlineKeyboardMarkup(btn))
747 | if SELF_DELETE:
748 | await asyncio.sleep(SELF_DELETE_SECONDS)
749 | await hehe.delete()
750 |
751 | except (MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty):
752 | pic = imdb.get('poster')
753 | poster = pic.replace('.jpg', "._V1_UX360.jpg")
754 | hmm = await message.reply_photo(photo=poster, caption=cap[:1024], reply_markup=InlineKeyboardMarkup(btn))
755 | if SELF_DELETE:
756 | await asyncio.sleep(SELF_DELETE_SECONDS)
757 | await hmm.delete()
758 | except Exception as e:
759 | logger.exception(e)
760 | fek = await message.reply_text(cap, reply_markup=InlineKeyboardMarkup(btn))
761 | if SELF_DELETE:
762 | await asyncio.sleep(SELF_DELETE_SECONDS)
763 | await fek.delete()
764 | else:
765 | fuk = await message.reply_text(cap, reply_markup=InlineKeyboardMarkup(btn))
766 | if SELF_DELETE:
767 | await asyncio.sleep(SELF_DELETE_SECONDS)
768 | await fuk.delete()
769 |
770 | async def advantage_spell_chok(msg):
771 | query = re.sub(
772 | r"\b(pl(i|e)*?(s|z+|ease|se|ese|(e+)s(e)?)|((send|snd|giv(e)?|gib)(\sme)?)|movie(s)?|new|latest|br((o|u)h?)*|^h(e|a)?(l)*(o)*|mal(ayalam)?|t(h)?amil|file|that|find|und(o)*|kit(t(i|y)?)?o(w)?|thar(u)?(o)*w?|kittum(o)*|aya(k)*(um(o)*)?|full\smovie|any(one)|with\ssubtitle(s)?)",
773 | "", msg.text, flags=re.IGNORECASE) # plis contribute some common words
774 | query = query.strip() + " movie"
775 | g_s = await search_gagala(query)
776 | g_s += await search_gagala(msg.text)
777 | gs_parsed = []
778 | if not g_s:
779 | k = await msg.reply("I couldn't find any movie in that name.")
780 | await asyncio.sleep(8)
781 | await k.delete()
782 | return
783 | regex = re.compile(r".*(imdb|wikipedia).*", re.IGNORECASE) # look for imdb / wiki results
784 | gs = list(filter(regex.match, g_s))
785 | gs_parsed = [re.sub(
786 | r'\b(\-([a-zA-Z-\s])\-\simdb|(\-\s)?imdb|(\-\s)?wikipedia|\(|\)|\-|reviews|full|all|episode(s)?|film|movie|series)',
787 | '', i, flags=re.IGNORECASE) for i in gs]
788 | if not gs_parsed:
789 | reg = re.compile(r"watch(\s[a-zA-Z0-9_\s\-\(\)]*)*\|.*",
790 | re.IGNORECASE) # match something like Watch Niram | Amazon Prime
791 | for mv in g_s:
792 | match = reg.match(mv)
793 | if match:
794 | gs_parsed.append(match.group(1))
795 | user = msg.from_user.id if msg.from_user else 0
796 | movielist = []
797 | gs_parsed = list(dict.fromkeys(gs_parsed)) # removing duplicates https://stackoverflow.com/a/7961425
798 | if len(gs_parsed) > 3:
799 | gs_parsed = gs_parsed[:3]
800 | if gs_parsed:
801 | for mov in gs_parsed:
802 | imdb_s = await get_poster(mov.strip(), bulk=True) # searching each keyword in imdb
803 | if imdb_s:
804 | movielist += [movie.get('title') for movie in imdb_s]
805 | movielist += [(re.sub(r'(\-|\(|\)|_)', '', i, flags=re.IGNORECASE)).strip() for i in gs_parsed]
806 | movielist = list(dict.fromkeys(movielist)) # removing duplicates
807 | if not movielist:
808 | k = await msg.reply("I couldn't find anything related to that. Check your spelling")
809 | await asyncio.sleep(8)
810 | await k.delete()
811 | return
812 | SPELL_CHECK[msg.id] = movielist
813 | btn = [[
814 | InlineKeyboardButton(
815 | text=movie.strip(),
816 | callback_data=f"spolling#{user}#{k}",
817 | )
818 | ] for k, movie in enumerate(movielist)]
819 | btn.append([InlineKeyboardButton(text="Close", callback_data=f'spolling#{user}#close_spellcheck')])
820 | await msg.reply("I couldn't find anything related to that\nDid you mean any one of these?",
821 | reply_markup=InlineKeyboardMarkup(btn))
822 |
823 |
824 | async def manual_filters(client, message, text=False):
825 | group_id = message.chat.id
826 | name = text or message.text
827 | reply_id = message.reply_to_message.id if message.reply_to_message else message.id
828 | keywords = await get_filters(group_id)
829 | for keyword in reversed(sorted(keywords, key=len)):
830 | pattern = r"( |^|[^\w])" + re.escape(keyword) + r"( |$|[^\w])"
831 | if re.search(pattern, name, flags=re.IGNORECASE):
832 | reply_text, btn, alert, fileid = await find_filter(group_id, keyword)
833 |
834 | if reply_text:
835 | reply_text = reply_text.replace("\\n", "\n").replace("\\t", "\t")
836 |
837 | if btn is not None:
838 | try:
839 | if fileid == "None":
840 | if btn == "[]":
841 | await client.send_message(
842 | group_id,
843 | reply_text,
844 | disable_web_page_preview=True,
845 | reply_to_message_id=reply_id)
846 | else:
847 | button = eval(btn)
848 | await client.send_message(
849 | group_id,
850 | reply_text,
851 | disable_web_page_preview=True,
852 | reply_markup=InlineKeyboardMarkup(button),
853 | reply_to_message_id=reply_id
854 | )
855 | elif btn == "[]":
856 | await client.send_cached_media(
857 | group_id,
858 | fileid,
859 | caption=reply_text or "",
860 | reply_to_message_id=reply_id
861 | )
862 | else:
863 | button = eval(btn)
864 | await message.reply_cached_media(
865 | fileid,
866 | caption=reply_text or "",
867 | reply_markup=InlineKeyboardMarkup(button),
868 | reply_to_message_id=reply_id
869 | )
870 | except Exception as e:
871 | logger.exception(e)
872 | break
873 | else:
874 | return False
875 |
876 |
--------------------------------------------------------------------------------
/plugins/route.py:
--------------------------------------------------------------------------------
1 | #rymme
2 |
3 |
4 |
5 |
6 |
7 |
8 | from aiohttp import web
9 |
10 | routes = web.RouteTableDef()
11 |
12 | @routes.get("/", allow_head=True)
13 | async def root_route_handler(request):
14 | return web.json_response("BOT IS RUNNING -Telegram@LazyDeveloper")
15 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | git+https://github.com/Joelkb/cinemagoer
2 | pyrogram>=2.0.30
3 | tgcrypto
4 | pymongo[srv]==3.12.3
5 | motor==2.5.1
6 | marshmallow==3.14.1
7 | umongo==3.0.1
8 | requests
9 | bs4
10 | heroku3
11 | pynewtonmath
12 | pytz
13 | aiohttp
14 |
--------------------------------------------------------------------------------
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.10.8
2 |
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | if [ -z $UPSTREAM_REPO ]
2 | then
3 | echo "Cloning main Repository"
4 | git clone https://github.com/LazyDeveloperr/LazyPrincessV2 /LazyPrincessV2
5 | else
6 | echo "Cloning Custom Repo from $UPSTREAM_REPO "
7 | git clone $UPSTREAM_REPO /LazyPrincessV2
8 | fi
9 | cd /LazyPrincessV2
10 | pip3 install -U -r requirements.txt
11 | echo "Starting Bot...."
12 | python3 bot.py
13 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from pyrogram.errors import InputUserDeactivated, UserNotParticipant, FloodWait, UserIsBlocked, PeerIdInvalid
3 | from info import *
4 | from imdb import Cinemagoer
5 | import asyncio
6 | from pyrogram.types import Message, InlineKeyboardButton
7 | from pyrogram import enums
8 | from typing import Union
9 | import re
10 | import os
11 | from datetime import datetime
12 | from typing import List
13 | from database.users_chats_db import db
14 | from bs4 import BeautifulSoup
15 | import requests
16 | import aiohttp
17 |
18 | logger = logging.getLogger(__name__)
19 | logger.setLevel(logging.INFO)
20 |
21 | BTN_URL_REGEX = re.compile(
22 | r"(\[([^\[]+?)\]\((buttonurl|buttonalert):(?:/{0,2})(.+?)(:same)?\))"
23 | )
24 |
25 | imdb = Cinemagoer()
26 |
27 | BANNED = {}
28 | SMART_OPEN = '“'
29 | SMART_CLOSE = '”'
30 | START_CHAR = ('\'', '"', SMART_OPEN)
31 |
32 | # temp db for banned
33 | class temp(object):
34 | BANNED_USERS = []
35 | BANNED_CHATS = []
36 | ME = None
37 | CURRENT=int(os.environ.get("SKIP", 2))
38 | CANCEL = False
39 | MELCOW = {}
40 | U_NAME = None
41 | B_NAME = None
42 | SETTINGS = {}
43 |
44 | async def is_subscribed(bot, query):
45 | try:
46 | user = await bot.get_chat_member(AUTH_CHANNEL, query.from_user.id)
47 | except UserNotParticipant:
48 | pass
49 | except Exception as e:
50 | logger.exception(e)
51 | else:
52 | if user.status != 'kicked':
53 | return True
54 |
55 | return False
56 |
57 | async def get_poster(query, bulk=False, id=False, file=None):
58 | if not id:
59 | # https://t.me/GetTGLink/4183
60 | query = (query.strip()).lower()
61 | title = query
62 | year = re.findall(r'[1-2]\d{3}$', query, re.IGNORECASE)
63 | if year:
64 | year = list_to_str(year[:1])
65 | title = (query.replace(year, "")).strip()
66 | elif file is not None:
67 | year = re.findall(r'[1-2]\d{3}', file, re.IGNORECASE)
68 | if year:
69 | year = list_to_str(year[:1])
70 | else:
71 | year = None
72 | movieid = imdb.search_movie(title.lower(), results=10)
73 | if not movieid:
74 | return None
75 | if year:
76 | filtered=list(filter(lambda k: str(k.get('year')) == str(year), movieid))
77 | if not filtered:
78 | filtered = movieid
79 | else:
80 | filtered = movieid
81 | movieid=list(filter(lambda k: k.get('kind') in ['movie', 'tv series'], filtered))
82 | if not movieid:
83 | movieid = filtered
84 | if bulk:
85 | return movieid
86 | movieid = movieid[0].movieID
87 | else:
88 | movieid = query
89 | movie = imdb.get_movie(movieid)
90 | if movie.get("original air date"):
91 | date = movie["original air date"]
92 | elif movie.get("year"):
93 | date = movie.get("year")
94 | else:
95 | date = "N/A"
96 | plot = ""
97 | if not LONG_IMDB_DESCRIPTION:
98 | plot = movie.get('plot')
99 | if plot and len(plot) > 0:
100 | plot = plot[0]
101 | else:
102 | plot = movie.get('plot outline')
103 | if plot and len(plot) > 800:
104 | plot = plot[0:800] + "..."
105 |
106 | return {
107 | 'title': movie.get('title'),
108 | 'votes': movie.get('votes'),
109 | "aka": list_to_str(movie.get("akas")),
110 | "seasons": movie.get("number of seasons"),
111 | "box_office": movie.get('box office'),
112 | 'localized_title': movie.get('localized title'),
113 | 'kind': movie.get("kind"),
114 | "imdb_id": f"tt{movie.get('imdbID')}",
115 | "cast": list_to_str(movie.get("cast")),
116 | "runtime": list_to_str(movie.get("runtimes")),
117 | "countries": list_to_str(movie.get("countries")),
118 | "certificates": list_to_str(movie.get("certificates")),
119 | "languages": list_to_str(movie.get("languages")),
120 | "director": list_to_str(movie.get("director")),
121 | "writer":list_to_str(movie.get("writer")),
122 | "producer":list_to_str(movie.get("producer")),
123 | "composer":list_to_str(movie.get("composer")) ,
124 | "cinematographer":list_to_str(movie.get("cinematographer")),
125 | "music_team": list_to_str(movie.get("music department")),
126 | "distributors": list_to_str(movie.get("distributors")),
127 | 'release_date': date,
128 | 'year': movie.get('year'),
129 | 'genres': list_to_str(movie.get("genres")),
130 | 'poster': movie.get('full-size cover url'),
131 | 'plot': plot,
132 | 'rating': str(movie.get("rating")),
133 | 'url':f'https://www.imdb.com/title/tt{movieid}'
134 | }
135 | # https://github.com/odysseusmax/animated-lamp/blob/2ef4730eb2b5f0596ed6d03e7b05243d93e3415b/bot/utils/broadcast.py#L37
136 |
137 | async def broadcast_messages(user_id, message):
138 | try:
139 | await message.copy(chat_id=user_id)
140 | return True, "Success"
141 | except FloodWait as e:
142 | await asyncio.sleep(e.x)
143 | return await broadcast_messages(user_id, message)
144 | except InputUserDeactivated:
145 | await db.delete_user(int(user_id))
146 | logging.info(f"{user_id}-Removed from Database, since deleted account.")
147 | return False, "Deleted"
148 | except UserIsBlocked:
149 | logging.info(f"{user_id} -Blocked the bot.")
150 | return False, "Blocked"
151 | except PeerIdInvalid:
152 | await db.delete_user(int(user_id))
153 | logging.info(f"{user_id} - PeerIdInvalid")
154 | return False, "Error"
155 | except Exception as e:
156 | return False, "Error"
157 |
158 | async def search_gagala(text):
159 | usr_agent = {
160 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
161 | 'Chrome/61.0.3163.100 Safari/537.36'
162 | }
163 | text = text.replace(" ", '+')
164 | url = f'https://www.google.com/search?q={text}'
165 | response = requests.get(url, headers=usr_agent)
166 | response.raise_for_status()
167 | soup = BeautifulSoup(response.text, 'html.parser')
168 | titles = soup.find_all( 'h3' )
169 | return [title.getText() for title in titles]
170 |
171 |
172 | async def get_settings(group_id):
173 | settings = temp.SETTINGS.get(group_id)
174 | if not settings:
175 | settings = await db.get_settings(group_id)
176 | temp.SETTINGS[group_id] = settings
177 | return settings
178 |
179 | async def save_group_settings(group_id, key, value):
180 | current = await get_settings(group_id)
181 | current[key] = value
182 | temp.SETTINGS[group_id] = current
183 | await db.update_settings(group_id, current)
184 |
185 | def get_size(size):
186 | """Get size in readable format"""
187 |
188 | units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB"]
189 | size = float(size)
190 | i = 0
191 | while size >= 1024.0 and i < len(units):
192 | i += 1
193 | size /= 1024.0
194 | return "%.2f %s" % (size, units[i])
195 |
196 | def split_list(l, n):
197 | for i in range(0, len(l), n):
198 | yield l[i:i + n]
199 |
200 | def get_file_id(msg: Message):
201 | if msg.media:
202 | for message_type in (
203 | "photo",
204 | "animation",
205 | "audio",
206 | "document",
207 | "video",
208 | "video_note",
209 | "voice",
210 | "sticker"
211 | ):
212 | obj = getattr(msg, message_type)
213 | if obj:
214 | setattr(obj, "message_type", message_type)
215 | return obj
216 |
217 | def extract_user(message: Message) -> Union[int, str]:
218 | """extracts the user from a message"""
219 | # https://github.com/SpEcHiDe/PyroGramBot/blob/f30e2cca12002121bad1982f68cd0ff9814ce027/pyrobot/helper_functions/extract_user.py#L7
220 | user_id = None
221 | user_first_name = None
222 | if message.reply_to_message:
223 | user_id = message.reply_to_message.from_user.id
224 | user_first_name = message.reply_to_message.from_user.first_name
225 |
226 | elif len(message.command) > 1:
227 | if (
228 | len(message.entities) > 1 and
229 | message.entities[1].type == enums.MessageEntityType.TEXT_MENTION
230 | ):
231 |
232 | required_entity = message.entities[1]
233 | user_id = required_entity.user.id
234 | user_first_name = required_entity.user.first_name
235 | else:
236 | user_id = message.command[1]
237 | # don't want to make a request -_-
238 | user_first_name = user_id
239 | try:
240 | user_id = int(user_id)
241 | except ValueError:
242 | pass
243 | else:
244 | user_id = message.from_user.id
245 | user_first_name = message.from_user.first_name
246 | return (user_id, user_first_name)
247 |
248 | def list_to_str(k):
249 | if not k:
250 | return "N/A"
251 | elif len(k) == 1:
252 | return str(k[0])
253 | elif MAX_LIST_ELM:
254 | k = k[:int(MAX_LIST_ELM)]
255 | return ' '.join(f'{elem}, ' for elem in k)
256 | else:
257 | return ' '.join(f'{elem}, ' for elem in k)
258 |
259 | def last_online(from_user):
260 | time = ""
261 | if from_user.is_bot:
262 | time += "🤖 Bot :("
263 | elif from_user.status == enums.UserStatus.RECENTLY:
264 | time += "Recently"
265 | elif from_user.status == enums.UserStatus.LAST_WEEK:
266 | time += "Within the last week"
267 | elif from_user.status == enums.UserStatus.LAST_MONTH:
268 | time += "Within the last month"
269 | elif from_user.status == enums.UserStatus.LONG_AGO:
270 | time += "A long time ago :("
271 | elif from_user.status == enums.UserStatus.ONLINE:
272 | time += "Currently Online"
273 | elif from_user.status == enums.UserStatus.OFFLINE:
274 | time += from_user.last_online_date.strftime("%a, %d %b %Y, %H:%M:%S")
275 | return time
276 |
277 |
278 | def split_quotes(text: str) -> List:
279 | if not any(text.startswith(char) for char in START_CHAR):
280 | return text.split(None, 1)
281 | counter = 1 # ignore first char -> is some kind of quote
282 | while counter < len(text):
283 | if text[counter] == "\\":
284 | counter += 1
285 | elif text[counter] == text[0] or (text[0] == SMART_OPEN and text[counter] == SMART_CLOSE):
286 | break
287 | counter += 1
288 | else:
289 | return text.split(None, 1)
290 |
291 | # 1 to avoid starting quote, and counter is exclusive so avoids ending
292 | key = remove_escapes(text[1:counter].strip())
293 | # index will be in range, or `else` would have been executed and returned
294 | rest = text[counter + 1:].strip()
295 | if not key:
296 | key = text[0] + text[0]
297 | return list(filter(None, [key, rest]))
298 |
299 | def parser(text, keyword):
300 | if "buttonalert" in text:
301 | text = (text.replace("\n", "\\n").replace("\t", "\\t"))
302 | buttons = []
303 | note_data = ""
304 | prev = 0
305 | i = 0
306 | alerts = []
307 | for match in BTN_URL_REGEX.finditer(text):
308 | # Check if btnurl is escaped
309 | n_escapes = 0
310 | to_check = match.start(1) - 1
311 | while to_check > 0 and text[to_check] == "\\":
312 | n_escapes += 1
313 | to_check -= 1
314 |
315 | # if even, not escaped -> create button
316 | if n_escapes % 2 == 0:
317 | note_data += text[prev:match.start(1)]
318 | prev = match.end(1)
319 | if match.group(3) == "buttonalert":
320 | # create a thruple with button label, url, and newline status
321 | if bool(match.group(5)) and buttons:
322 | buttons[-1].append(InlineKeyboardButton(
323 | text=match.group(2),
324 | callback_data=f"alertmessage:{i}:{keyword}"
325 | ))
326 | else:
327 | buttons.append([InlineKeyboardButton(
328 | text=match.group(2),
329 | callback_data=f"alertmessage:{i}:{keyword}"
330 | )])
331 | i += 1
332 | alerts.append(match.group(4))
333 | elif bool(match.group(5)) and buttons:
334 | buttons[-1].append(InlineKeyboardButton(
335 | text=match.group(2),
336 | url=match.group(4).replace(" ", "")
337 | ))
338 | else:
339 | buttons.append([InlineKeyboardButton(
340 | text=match.group(2),
341 | url=match.group(4).replace(" ", "")
342 | )])
343 |
344 | else:
345 | note_data += text[prev:to_check]
346 | prev = match.start(1) - 1
347 | else:
348 | note_data += text[prev:]
349 |
350 | try:
351 | return note_data, buttons, alerts
352 | except:
353 | return note_data, buttons, None
354 |
355 | def remove_escapes(text: str) -> str:
356 | res = ""
357 | is_escaped = False
358 | for counter in range(len(text)):
359 | if is_escaped:
360 | res += text[counter]
361 | is_escaped = False
362 | elif text[counter] == "\\":
363 | is_escaped = True
364 | else:
365 | res += text[counter]
366 | return res
367 |
368 |
369 | def humanbytes(size):
370 | if not size:
371 | return ""
372 | power = 2**10
373 | n = 0
374 | Dic_powerN = {0: ' ', 1: 'Ki', 2: 'Mi', 3: 'Gi', 4: 'Ti'}
375 | while size > power:
376 | size /= power
377 | n += 1
378 | return str(round(size, 2)) + " " + Dic_powerN[n] + 'B'
379 |
380 | async def get_shortlink(link):
381 | https = link.split(":")[0]
382 | if "http" == https:
383 | https = "https"
384 | link = link.replace("http", https)
385 |
386 | url = f'https://api.shareus.in/shortLink'
387 | params = {'token': URL_SHORTNER_WEBSITE_API,
388 | 'link': link,
389 | 'format': 'json'
390 | }
391 |
392 | try:
393 | async with aiohttp.ClientSession() as session:
394 | async with session.get(url, params=params, raise_for_status=True, ssl=False) as response:
395 | data = await response.json(content_type='text/html')
396 | if data["status"] == "success":
397 | return data['shortlink']
398 | else:
399 | logger.error(f"Error: {data['message']}")
400 | return f'https://api.shareus.in/directLink?token={URL_SHORTNER_WEBSITE_API}&link={link}'
401 |
402 | except Exception as e:
403 | logger.error(e)
404 | return f'https://api.shareus.in/directLink?token={URL_SHORTNER_WEBSITE_API}&link={link}'
405 |
--------------------------------------------------------------------------------