kgashok commited on
Commit
19e1d1f
·
1 Parent(s): 6aa901a
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Dockerfile +12 -0
  2. LICENSE +339 -0
  3. Procfile +1 -0
  4. Script.py +247 -0
  5. app.json +81 -0
  6. bot.py +106 -0
  7. database/__pycache__/connections_mdb.cpython-310.pyc +0 -0
  8. database/__pycache__/filters_mdb.cpython-310.pyc +0 -0
  9. database/__pycache__/gfilters_mdb.cpython-310.pyc +0 -0
  10. database/__pycache__/ia_filterdb.cpython-310.pyc +0 -0
  11. database/__pycache__/users_chats_db.cpython-310.pyc +0 -0
  12. database/connections_mdb.py +133 -0
  13. database/filters_mdb.py +115 -0
  14. database/gfilters_mdb.py +113 -0
  15. database/ia_filterdb.py +205 -0
  16. database/users_chats_db.py +154 -0
  17. docker-compose.yml +14 -0
  18. heroku.yml +3 -0
  19. info.py +97 -0
  20. logging.conf +32 -0
  21. plugins/Restart.py +12 -0
  22. plugins/__init__.py +8 -0
  23. plugins/__pycache__/Restart.cpython-310.pyc +0 -0
  24. plugins/__pycache__/__init__.cpython-310.pyc +0 -0
  25. plugins/__pycache__/banned.cpython-310.pyc +0 -0
  26. plugins/__pycache__/broadcast.cpython-310.pyc +0 -0
  27. plugins/__pycache__/channel.cpython-310.pyc +0 -0
  28. plugins/__pycache__/clone.cpython-310.pyc +0 -0
  29. plugins/__pycache__/commands.cpython-310.pyc +0 -0
  30. plugins/__pycache__/connection.cpython-310.pyc +0 -0
  31. plugins/__pycache__/files_delete.cpython-310.pyc +0 -0
  32. plugins/__pycache__/filters.cpython-310.pyc +0 -0
  33. plugins/__pycache__/genlink.cpython-310.pyc +0 -0
  34. plugins/__pycache__/gfilters.cpython-310.pyc +0 -0
  35. plugins/__pycache__/index.cpython-310.pyc +0 -0
  36. plugins/__pycache__/inline.cpython-310.pyc +0 -0
  37. plugins/__pycache__/misc.cpython-310.pyc +0 -0
  38. plugins/__pycache__/p_ttishow.cpython-310.pyc +0 -0
  39. plugins/__pycache__/pm_filter.cpython-310.pyc +0 -0
  40. plugins/__pycache__/pm_filter1.cpython-310.pyc +0 -0
  41. plugins/__pycache__/route.cpython-310.pyc +0 -0
  42. plugins/__pycache__/sample.cpython-310.pyc +0 -0
  43. plugins/banned.py +40 -0
  44. plugins/broadcast.py +68 -0
  45. plugins/channel.py +20 -0
  46. plugins/clone.py +38 -0
  47. plugins/commands.py +1096 -0
  48. plugins/connection.py +147 -0
  49. plugins/files_delete.py +48 -0
  50. plugins/filters.py +272 -0
Dockerfile ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.8-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 /DQ-The-File-Donor
10
+ WORKDIR /DQ-The-File-Donor
11
+ COPY start.sh /start.sh
12
+ CMD ["/bin/bash", "/start.sh"]
LICENSE ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Public License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Public License for more details.
305
+
306
+ You should have received a copy of the GNU General Public License along
307
+ with this program; if not, write to the Free Software Foundation, Inc.,
308
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
+
310
+ Also add information on how to contact you by electronic and paper mail.
311
+
312
+ If the program is interactive, make it output a short notice like this
313
+ when it starts in an interactive mode:
314
+
315
+ Gnomovision version 69, Copyright (C) year name of author
316
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
+ This is free software, and you are welcome to redistribute it
318
+ under certain conditions; type `show c' for details.
319
+
320
+ The hypothetical commands `show w' and `show c' should show the appropriate
321
+ parts of the General Public License. Of course, the commands you use may
322
+ be called something other than `show w' and `show c'; they could even be
323
+ mouse-clicks or menu items--whatever suits your program.
324
+
325
+ You should also get your employer (if you work as a programmer) or your
326
+ school, if any, to sign a "copyright disclaimer" for the program, if
327
+ necessary. Here is a sample; alter the names:
328
+
329
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
+
332
+ <signature of Ty Coon>, 1 April 1989
333
+ Ty Coon, President of Vice
334
+
335
+ This General Public License does not permit incorporating your program into
336
+ proprietary programs. If your program is a subroutine library, you may
337
+ consider it more useful to permit linking proprietary applications with the
338
+ library. If this is what you want to do, use the GNU Lesser General
339
+ Public License instead of this License.
Procfile ADDED
@@ -0,0 +1 @@
 
 
1
+ web: python3 bot.py
Script.py ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class script(object):
2
+ START_TXT = """<b>Hᴇʟʟᴏ {},
3
+ Mʏ Nᴀᴍᴇ Is <a href=https://t.me/{}>{}</a>, I Cᴀɴ Pʀᴏᴠɪᴅᴇ Mᴏᴠɪᴇs, Jᴜsᴛ Aᴅᴅ Mᴇ Tᴏ Yᴏᴜʀ Gʀᴏᴜᴘ As Aᴅᴍɪɴ Aɴᴅ Eɴᴊᴏʏ 😍</b>"""
4
+
5
+ HELP_TXT = """<b>Hᴇʏ {}
6
+ Hᴇʀᴇ Is Tʜᴇ Hᴇʟᴘ Fᴏʀ Mʏ Cᴏᴍᴍᴀɴᴅs.</b>"""
7
+
8
+ ABOUT_TXT = """<b>✯ Mʏ Nᴀᴍᴇ : {}</b>
9
+ <b>✯ Cʀᴇᴀᴛᴏʀ : <a href=https://t.me/Kgashok04>☢ Owner Of TTBots ☢</a></b>
10
+ <b>✯ Uᴘᴅᴀᴛᴇs : <a href=https://t.me/TeamHMT_Bots>TT Bot Updates 👾</a></b>
11
+ <b>✯ Bᴜɪʟᴅ Sᴛᴀᴛᴜs : ᴠ2.0.62 [Sᴛᴀʙʟᴇ]</b>"""
12
+
13
+ SOURCE_TXT = """
14
+ <b>Tʜɪꜱ Bᴏᴛ Iꜱ NOT Oᴘᴇɴ Sᴏᴜʀᴄᴇ Pʀᴏᴊᴇᴄᴛ.
15
+ """
16
+
17
+ MANUELFILTER_TXT = """ʜᴇʟᴘ: <b>ꜰɪʟᴛᴇʀꜱ</b>
18
+ - ꜰɪʟᴛᴇʀ ɪꜱ ᴀ ꜰᴇᴀᴛᴜʀᴇ ᴡᴇʀᴇ ᴜꜱᴇʀꜱ ᴄᴀɴ ꜱᴇᴛ ᴀᴜᴛᴏᴍᴀᴛᴇᴅ ʀᴇᴘʟɪᴇꜱ ꜰᴏʀ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ᴋᴇʏᴡᴏʀᴅ ᴀɴᴅ ɪ ᴡɪʟʟ ʀᴇꜱᴘᴏɴᴅ ᴡʜᴇɴᴇᴠᴇʀ ᴀ ᴋᴇʏᴡᴏʀᴅ ɪꜱ ꜰᴏᴜɴᴅ ɪɴ ᴛʜᴇ ᴍᴇꜱꜱᴀɢᴇ
19
+ <b>ɴᴏᴛᴇ:</b>
20
+ 1. ᴛʜɪꜱ ʙᴏᴛ ꜱʜᴏᴜʟᴅ ʜᴀᴠᴇ ᴀᴅᴍɪɴ ᴘʀɪᴠɪʟᴇɢᴇ.
21
+ 2. ᴏɴʟʏ ᴀᴅᴍɪɴꜱ ᴄᴀɴ ᴀᴅᴅ ꜰɪʟᴛᴇʀꜱ ɪɴ ᴀ ᴄʜᴀᴛ.
22
+ 3. ᴀʟᴇʀᴛ ʙᴜᴛᴛᴏɴꜱ ʜᴀᴠᴇ ᴀ ʟɪᴍɪᴛ ᴏꜰ 64 ᴄʜᴀʀᴀᴄᴛᴇʀꜱ.
23
+ Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ:
24
+ • /filter - <code>ᴀᴅᴅ ᴀ ꜰɪʟᴛᴇʀ ɪɴ ᴀ ᴄʜᴀᴛ</code>
25
+ • /filters - <code>ʟɪꜱᴛ ᴀʟʟ ᴛʜᴇ ꜰɪʟᴛᴇʀꜱ ᴏꜰ ᴀ ᴄʜᴀᴛ</code>
26
+ • /del - <code>ᴅᴇʟᴇᴛᴇ ᴀ ꜱᴘᴇᴄɪꜰɪᴄ ꜰɪʟᴛᴇʀ ɪɴ ᴀ ᴄʜᴀᴛ</code>
27
+ • /delall - <code>ᴅᴇʟᴇᴛᴇ ᴛʜᴇ ᴡʜᴏʟᴇ ꜰɪʟᴛᴇʀꜱ ɪɴ ᴀ ᴄʜᴀᴛ (ᴄʜᴀᴛ ᴏᴡɴᴇʀ ᴏɴʟʏ)</code>"""
28
+
29
+ BUTTON_TXT = """ʜᴇʟᴘ: <b>ʙᴜᴛᴛᴏɴꜱ</b>
30
+ - ᴛʜɪꜱ ʙᴏᴛ ꜱᴜᴘᴘᴏʀᴛꜱ ʙᴏᴛʜ ᴜʀʟ ᴀɴᴅ ᴀʟᴇʀᴛ ɪɴʟɪɴᴇ ʙᴜᴛᴛᴏɴꜱ.
31
+ <b>ɴᴏᴛᴇ:</b>
32
+ 1. ᴛᴇʟᴇɢʀᴀᴍ ᴡɪʟʟ ɴᴏᴛ ᴀʟʟᴏᴡꜱ ʏᴏᴜ ᴛᴏ ꜱᴇɴᴅ ʙᴜᴛᴛᴏɴꜱ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ᴄᴏɴᴛᴇɴᴛ, ꜱᴏ ᴄᴏɴᴛᴇɴᴛ ɪꜱ ᴍᴀɴᴅᴀᴛᴏʀʏ.
33
+ 2. ᴛʜɪꜱ ʙᴏᴛ ꜱᴜᴘᴘᴏʀᴛꜱ ʙᴜᴛᴛᴏɴꜱ ᴡɪᴛʜ ᴀɴʏ ᴛᴇʟᴇɢʀᴀᴍ ᴍᴇᴅɪᴀ ᴛʏᴘᴇ.
34
+ 3. ʙᴜᴛᴛᴏɴꜱ ꜱʜᴏᴜʟᴅ ʙᴇ ᴘʀᴏᴘᴇʀʟʏ ᴘᴀʀꜱᴇᴅ ᴀꜱ ᴍᴀʀᴋᴅᴏᴡɴ ꜰᴏʀᴍᴀᴛ
35
+ <b>ᴜʀʟ ʙᴜᴛᴛᴏɴꜱ:</b>
36
+ <code>[Button Text](buttonurl:https://t.me/TeamHMT_Bots)</code>
37
+ <b>ᴀʟᴇʀᴛ ʙᴜᴛᴛᴏɴꜱ:</b>
38
+ <code>[Button Text](buttonalert:ᴛʜɪꜱ ɪꜱ ᴀɴ ᴀʟᴇʀᴛ ᴍᴇꜱꜱᴀɢᴇ)</code>"""
39
+
40
+ AUTOFILTER_TXT = """ʜᴇʟᴘ: <b>ᴀᴜᴛᴏ ꜰɪʟᴛᴇʀ</b>
41
+ <b>ɴᴏᴛᴇ: Fɪʟᴇ Iɴᴅᴇx</b>
42
+ 1. ᴍᴀᴋᴇ ᴍᴇ ᴛʜᴇ ᴀᴅᴍɪɴ ᴏꜰ ʏᴏᴜʀ ᴄʜᴀɴɴᴇʟ ɪꜰ ɪᴛ'ꜱ ᴘʀɪᴠᴀᴛᴇ.
43
+ 2. ᴍᴀᴋᴇ ꜱᴜʀᴇ ᴛʜᴀᴛ ʏᴏᴜʀ ᴄʜᴀɴɴᴇʟ ᴅᴏᴇꜱ ɴᴏᴛ ᴄᴏɴᴛᴀɪɴꜱ ᴄᴀᴍʀɪᴘꜱ, ᴘᴏʀɴ ᴀɴᴅ ꜰᴀᴋᴇ ꜰɪʟᴇꜱ.
44
+ 3. ꜰᴏʀᴡᴀʀᴅ ᴛʜᴇ ʟᴀꜱᴛ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴍᴇ ᴡɪᴛʜ Qᴜᴏᴛᴇꜱ. ɪ'ʟʟ ᴀᴅᴅ ᴀʟʟ ᴛʜᴇ ꜰɪʟᴇꜱ ɪɴ ᴛʜᴀᴛ ᴄʜᴀɴɴᴇʟ ᴛᴏ ᴍʏ ᴅʙ.
45
+
46
+ <b>Nᴏᴛᴇ: AᴜᴛᴏFɪʟᴛᴇʀ</b>
47
+ 1. Aᴅᴅ ᴛʜᴇ ʙᴏᴛ ᴀs ᴀᴅᴍɪɴ ᴏɴ ʏᴏᴜʀ ɢʀᴏᴜᴘ.
48
+ 2. Usᴇ /connect ᴀɴᴅ ᴄᴏɴɴᴇᴄᴛ ʏᴏᴜʀ ɢʀᴏᴜᴘ ᴛᴏ ᴛʜᴇ ʙᴏᴛ.
49
+ 3. Usᴇ /settings ᴏɴ ʙᴏᴛ's PM ᴀɴᴅ ᴛᴜʀɴ ᴏɴ AᴜᴛᴏFɪʟᴛᴇʀ ᴏɴ ᴛʜᴇ sᴇᴛᴛɪɴɢs ᴍᴇɴᴜ."""
50
+
51
+ CONNECTION_TXT = """ʜᴇʟᴘ: <b>ᴄᴏɴɴᴇᴄᴛɪᴏɴꜱ</b>
52
+ - ᴜꜱᴇᴅ ᴛᴏ ᴄᴏɴɴᴇᴄᴛ ʙᴏᴛ ᴛᴏ ᴘᴍ ꜰᴏʀ ᴍᴀɴᴀɢɪɴɢ ꜰɪʟᴛᴇʀꜱ
53
+ - ɪᴛ ʜᴇʟᴘꜱ ᴛᴏ ᴀᴠᴏɪᴅ ꜱᴘᴀᴍᴍɪɴɢ ɪɴ ɢʀᴏᴜᴘꜱ.
54
+ <b>ɴᴏᴛᴇ:</b>
55
+ 1. ᴏɴʟʏ ᴀᴅᴍɪɴꜱ ᴄᴀɴ ᴀᴅᴅ ᴀ ᴄᴏɴɴᴇᴄᴛɪᴏɴ.
56
+ 2. ꜱᴇɴᴅ <code>/ᴄᴏɴɴᴇᴄᴛ</code> ꜰᴏʀ ᴄᴏɴɴᴇᴄᴛɪɴɢ ᴍᴇ ᴛᴏ ʏᴏᴜʀ ᴘᴍ
57
+ Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ:
58
+ • /connect - <code>ᴄᴏɴɴᴇᴄᴛ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ᴄʜᴀᴛ ᴛᴏ ʏᴏᴜʀ ᴘᴍ</code>
59
+ • /disconnect - <code>ᴅɪꜱᴄᴏɴɴᴇᴄᴛ ꜰʀᴏᴍ ᴀ ᴄʜᴀᴛ</code>
60
+ • /connections - <code>ʟɪꜱᴛ ᴀʟʟ ʏᴏᴜʀ ᴄᴏɴɴᴇᴄᴛɪᴏɴꜱ</code>"""
61
+
62
+ EXTRAMOD_TXT = """ʜᴇʟᴘ: Exᴛʀᴀ Mᴏᴅᴜʟᴇs
63
+ <b>ɴᴏᴛᴇ:</b>
64
+ ᴛʜᴇꜱᴇ ᴀʀᴇ ᴛʜᴇ ᴇxᴛʀᴀ ꜰᴇᴀᴛᴜʀᴇꜱ ᴏꜰ ᴛʜɪꜱ ʙᴏᴛ
65
+ Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ:
66
+ • /id - <code>ɢᴇᴛ ɪᴅ ᴏꜰ ᴀ ꜱᴘᴇᴄɪꜰɪᴇᴅ ᴜꜱᴇʀ.</code>
67
+ • /info - <code>ɢᴇᴛ ɪɴꜰᴏʀ���ᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴀ ᴜꜱᴇʀ.</code>
68
+ • /imdb - <code>ɢᴇᴛ ᴛʜᴇ ꜰɪʟᴍ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ꜰʀᴏᴍ ɪᴍᴅʙ ꜱᴏᴜʀᴄᴇ.</code>
69
+ • /search - <code>ɢᴇᴛ ᴛʜᴇ ꜰɪʟᴍ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ꜰʀᴏᴍ ᴠᴀʀɪᴏᴜꜱ ꜱᴏᴜʀᴄᴇꜱ.</code>"""
70
+
71
+ ADMIN_TXT = """ʜᴇʟᴘ: Aᴅᴍɪɴ Mᴏᴅs
72
+ <b>ɴᴏᴛᴇ:</b>
73
+ Tʜɪs Mᴏᴅᴜʟᴇ Oɴʟʏ Wᴏʀᴋs Fᴏʀ Mʏ Aᴅᴍɪɴs
74
+ Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ:
75
+ • /logs - <code>ᴛᴏ ɢᴇᴛ ᴛʜᴇ ʀᴇᴄᴇɴᴛ ᴇʀʀᴏʀꜱ</code>
76
+ • /stats - <code>ᴛᴏ ɢᴇᴛ ꜱᴛᴀᴛᴜꜱ ᴏꜰ ꜰɪʟᴇꜱ ɪɴ ᴅʙ. [Tʜɪs Cᴏᴍᴍᴀɴᴅ Cᴀɴ Bᴇ Usᴇᴅ Bʏ Aɴʏᴏɴᴇ]</code>
77
+ • /delete - <code>ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀ ꜱᴘᴇᴄɪꜰɪᴄ ꜰɪʟᴇ ꜰʀᴏᴍ ᴅʙ.</code>
78
+ • /users - <code>ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴍʏ ᴜꜱᴇʀꜱ ᴀɴᴅ ɪᴅꜱ.</code>
79
+ • /chats - <code>ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴍʏ ᴄʜᴀᴛꜱ ᴀɴᴅ ɪᴅꜱ</code>
80
+ • /leave - <code>ᴛᴏ ʟᴇᴀᴠᴇ ꜰʀᴏᴍ ᴀ ᴄʜᴀᴛ.</code>
81
+ • /disable - <code>ᴛᴏ ᴅɪꜱᴀʙʟᴇ ᴀ ᴄʜᴀᴛ.</code>
82
+ • /ban - <code>ᴛᴏ ʙᴀɴ ᴀ ᴜꜱᴇʀ.</code>
83
+ • /unban - <code>ᴛᴏ ᴜɴʙᴀɴ ᴀ ᴜꜱᴇʀ.</code>
84
+ • /channel - <code>ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴛᴏᴛᴀʟ ᴄᴏɴɴᴇᴄᴛᴇᴅ ᴄʜᴀɴɴᴇʟꜱ</code>
85
+ • /broadcast - <code>ᴛᴏ ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴀ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴀʟʟ ᴜꜱᴇʀꜱ</code>
86
+ • /grp_broadcast - <code>Tᴏ ʙʀᴏᴀᴅᴄᴀsᴛ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ ᴀʟʟ ᴄᴏɴɴᴇᴄᴛᴇᴅ ɢʀᴏᴜᴘs.</code>
87
+ • /gfilter - <code>ᴛᴏ ᴀᴅᴅ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs</code>
88
+ • /gfilters - <code>ᴛᴏ ᴠɪᴇᴡ ʟɪsᴛ ᴏғ ᴀʟʟ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs</code>
89
+ • /delg - <code>ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀ sᴘᴇᴄɪғɪᴄ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ</code>
90
+ • /request - <code>Tᴏ sᴇɴᴅ ᴀ Mᴏᴠɪᴇ/Sᴇʀɪᴇs ʀᴇᴏ̨ᴜᴇsᴛ ᴛᴏ ʙᴏᴛ ᴀᴅᴍɪɴs. Oɴʟʏ ᴡᴏʀᴋs ᴏɴ sᴜᴘᴘᴏʀᴛ ɢʀᴏᴜᴘ. [Tʜɪs Cᴏᴍᴍᴀɴᴅ Cᴀɴ Bᴇ Usᴇᴅ Bʏ Aɴʏᴏɴᴇ]</code>
91
+ • /delallg - <code>Tᴏ ᴅᴇʟᴇᴛᴇ ᴀʟʟ Gғɪʟᴛᴇʀs ғʀᴏᴍ ᴛʜᴇ ʙᴏᴛ's ᴅᴀᴛᴀʙᴀsᴇ.</code>
92
+ • /deletefiles - <code>Tᴏ ᴅᴇʟᴇᴛᴇ CᴀᴍRɪᴘ ᴀɴᴅ PʀᴇDVD Fɪʟᴇs ғʀᴏᴍ ᴛʜᴇ ʙᴏᴛ's ᴅᴀᴛᴀʙᴀsᴇ.</code>"""
93
+
94
+ STATUS_TXT = """<b>★ Tᴏᴛᴀʟ Fɪʟᴇs: <code>{}</code>
95
+ ★ Tᴏᴛᴀʟ Usᴇʀs: <code>{}</code>
96
+ ★ Tᴏᴛᴀʟ Cʜᴀᴛs: <code>{}</code>
97
+ ★ Usᴇᴅ Sᴛᴏʀᴀɢᴇ: <code>{}</code>
98
+ ★ Fʀᴇᴇ Sᴛᴏʀᴀɢᴇ: <code>{}</code></b>"""
99
+
100
+ LOG_TEXT_G = """#NewGroup
101
+ Gʀᴏᴜᴘ = {}(<code>{}</code>)
102
+ Tᴏᴛᴀʟ Mᴇᴍʙᴇʀs = <code>{}</code>
103
+ Aᴅᴅᴇᴅ Bʏ - {}"""
104
+
105
+ LOG_TEXT_P = """#NewUser
106
+ ID - <code>{}</code>
107
+ Nᴀᴍᴇ - {}"""
108
+
109
+ ALRT_TXT = """ʜᴇʟʟᴏ {},
110
+ ᴛʜɪꜱ ɪꜱ ɴᴏᴛ ʏᴏᴜʀ ᴍᴏᴠɪᴇ ʀᴇQᴜᴇꜱᴛ,
111
+ ʀᴇQᴜᴇꜱᴛ ʏᴏᴜʀ'ꜱ..."""
112
+
113
+ OLD_ALRT_TXT = """ʜᴇʏ {},
114
+ ʏᴏᴜ ᴀʀᴇ ᴜꜱɪɴɢ ᴏɴᴇ ᴏꜰ ᴍʏ ᴏʟᴅ ᴍᴇꜱꜱᴀɢᴇꜱ,
115
+ ᴘʟᴇᴀꜱᴇ ꜱᴇɴᴅ ᴛʜᴇ ʀᴇQᴜᴇꜱᴛ ᴀɢᴀɪɴ."""
116
+
117
+ CUDNT_FND = """ɪ ᴄᴏᴜʟᴅɴ'ᴛ ꜰɪɴᴅ ᴀɴʏᴛʜɪɴɢ ʀᴇʟᴀᴛᴇᴅ ᴛᴏ {}
118
+ ᴅɪᴅ ʏᴏᴜ ᴍᴇᴀɴ ᴀɴʏ ᴏɴᴇ ᴏꜰ ᴛʜᴇꜱᴇ?"""
119
+
120
+ I_CUDNT = """<b>sᴏʀʀʏ ɴᴏ ꜰɪʟᴇs ᴡᴇʀᴇ ꜰᴏᴜɴᴅ ꜰᴏʀ ʏᴏᴜʀ ʀᴇǫᴜᴇꜱᴛ {} 😕
121
+
122
+ ᴄʜᴇᴄᴋ ʏᴏᴜʀ sᴘᴇʟʟɪɴɢ ɪɴ ɢᴏᴏɢʟᴇ ᴀɴᴅ ᴛʀʏ ᴀɢᴀɪɴ 😃
123
+
124
+ ᴍᴏᴠɪᴇ ʀᴇǫᴜᴇꜱᴛ ꜰᴏʀᴍᴀᴛ 👇
125
+
126
+ ᴇxᴀᴍᴘʟᴇ : Uncharted or Uncharted 2022 or Uncharted En
127
+
128
+ ꜱᴇʀɪᴇꜱ ʀᴇǫᴜᴇꜱᴛ ꜰᴏʀᴍᴀᴛ 👇
129
+
130
+ ᴇxᴀᴍᴘʟᴇ : Loki S01 or Loki S01E04 or Lucifer S03E24
131
+
132
+ 🚯 ᴅᴏɴᴛ ᴜꜱᴇ ➠ ':(!,./)</b>"""
133
+
134
+ I_CUD_NT = """ɪ ᴄᴏᴜʟᴅɴ'ᴛ ꜰɪɴᴅ ᴀɴʏ ᴍᴏᴠɪᴇ ʀᴇʟᴀᴛᴇᴅ ᴛᴏ {}.
135
+ ᴘʟᴇᴀꜱᴇ ᴄʜᴇᴄᴋ ᴛʜᴇ ꜱᴘᴇʟʟɪɴɢ ᴏɴ ɢᴏᴏɢʟᴇ ᴏʀ ɪᴍᴅʙ..."""
136
+
137
+ MVE_NT_FND = """ᴍᴏᴠɪᴇ ɴᴏᴛ ꜰᴏᴜɴᴅ ɪɴ ᴅᴀᴛᴀʙᴀꜱᴇ..."""
138
+
139
+ TOP_ALRT_MSG = """Cʜᴇᴄᴋɪɴɢ Fᴏʀ Mᴏᴠɪᴇ Iɴ Dᴀᴛᴀʙᴀsᴇ..."""
140
+
141
+ MELCOW_ENG = """<b>Hᴇʟʟᴏ {} 😍, Aɴᴅ Wᴇʟᴄᴏᴍᴇ Tᴏ {} Gʀᴏᴜᴘ ❤️</b>"""
142
+
143
+ SHORTLINK_INFO = """
144
+ <b>──────「<a href=https://t.me/TeamHMT_Bots/44> Hᴏᴡ ᴛᴏ Eᴀʀɴ Mᴏɴᴇʏ </a> 」──────
145
+
146
+ Yᴏᴜ ᴄᴀɴ Eᴀʀɴ Mᴏɴᴇʏ Fʀᴏᴍ Tʜɪs Bᴏᴛ Uɴᴛɪʟ ᴛʜɪs ʙᴏᴛ ɪs ᴀʟɪᴠᴇ.
147
+
148
+ Wᴀɴᴛ ᴛᴏ Kɴᴏᴡ Hᴏᴡ? Fᴏʟʟᴏᴡ Tʜᴇsᴇ Sᴛᴇᴘs:-
149
+
150
+ sᴛᴇᴘ 𝟷 : ʏᴏᴜ ᴍᴜsᴛ ʜᴀᴠᴇ ᴀᴛʟᴇᴀsᴛ ᴏɴᴇ ɢʀᴏᴜᴘ ᴡɪᴛʜ ᴍɪɴɪᴍᴜᴍ 1𝟶𝟶 ᴍᴇᴍ��ᴇʀs.
151
+
152
+ sᴛᴇᴘ 𝟸 : ᴍᴀᴋᴇ ᴀᴄᴄᴏᴜɴᴛ ᴏɴ Aɴʏ <a href=https://urlshorten.in/ref/106324576666323105902>Sʜᴏʀᴛᴇɴᴇʀ Wᴇʙsɪᴛᴇ</a>.
153
+
154
+ sᴛᴇᴘ 𝟹 : ꜰᴏʟʟᴏᴡ ᴛʜᴇsᴇ <a href=https://t.me/TeamHMT_Bots/44> ɪɴꜱᴛʀᴜᴄᴛɪᴏɴꜱ </a>Tᴏ ᴄᴏɴɴᴇᴄᴛ sʜᴏʀᴛᴇɴᴇʀ.
155
+
156
+ ➣ Yᴏᴜ ᴄᴀɴ ᴄᴏɴɴᴇᴄᴛ ᴀs ᴍᴀɴʏ ɢʀᴏᴜᴘ ʏᴏᴜ ʜᴀᴠᴇ.
157
+
158
+ Any Doubts or Not Connecting? Contact Me </b>
159
+ """
160
+
161
+ REQINFO = """
162
+ ⚠ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ⚠
163
+
164
+ ᴀꜰᴛᴇʀ 5 ᴍɪɴᴜᴛᴇꜱ ᴛʜɪꜱ ᴍᴇꜱꜱᴀɢᴇ ᴡɪʟʟ ʙᴇ ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ ᴅᴇʟᴇᴛᴇᴅ
165
+
166
+ ɪꜰ ʏᴏᴜ ᴅᴏ ɴᴏᴛ ꜱᴇᴇ ᴛʜᴇ ʀᴇǫᴜᴇsᴛᴇᴅ ᴍᴏᴠɪᴇ / sᴇʀɪᴇs ꜰɪʟᴇ, ʟᴏᴏᴋ ᴀᴛ ᴛʜᴇ ɴᴇxᴛ ᴘᴀɢᴇ"""
167
+
168
+ SELECT = """
169
+ MOVIES ➢ Sᴇʟᴇᴄᴛ "Lᴀɴɢᴜᴀɢᴇs"
170
+
171
+ SERIES ➢ Sᴇʟᴇᴄᴛ "Sᴇᴀsᴏɴs"
172
+
173
+ Tɪᴘ: Sᴇʟᴇᴄᴛ "Lᴀɴɢᴜᴀɢᴇs" ᴏʀ "Sᴇᴀsᴏɴs" Bᴜᴛᴛᴏɴ ᴀɴᴅ Cʟɪᴄᴋ "Sᴇɴᴅ Aʟʟ" Tᴏ ɢᴇᴛ Aʟʟ Fɪʟᴇ Lɪɴᴋs ɪɴ ᴀ Sɪɴɢʟᴇ ᴄʟɪᴄᴋ"""
174
+
175
+ SINFO = """
176
+ ⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
177
+ ꜱᴇʀɪᴇꜱ ʀᴇǫᴜᴇꜱᴛ ꜰᴏʀᴍᴀᴛ
178
+ ⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
179
+
180
+ ɢᴏ ᴛᴏ ɢᴏᴏɢʟᴇ ➠ ᴛʏᴘᴇ ꜱᴇʀɪᴇꜱ ɴᴀᴍᴇ ➠ ᴄᴏᴘʏ ᴄᴏʀʀᴇᴄᴛ ɴᴀᴍᴇ ➠ ᴘᴀꜱᴛᴇ ᴛʜɪꜱ ɢʀᴏᴜᴘ
181
+
182
+ ᴇxᴀᴍᴘʟᴇ : Loki S01E01
183
+
184
+ 🚯 ᴅᴏɴᴛ ᴜꜱᴇ ➠ ':(!,./)"""
185
+
186
+ NORSLTS = """
187
+ ★ #𝗡𝗼𝗥𝗲𝘀𝘂𝗹𝘁𝘀 ★
188
+
189
+ 𝗜𝗗 <b>: {}</b>
190
+
191
+ 𝗡𝗮𝗺𝗲 <b>: {}</b>
192
+
193
+ 𝗠𝗲𝘀𝘀𝗮𝗴𝗲 <b>: {}</b>"""
194
+
195
+ CAPTION = """<b>📂Fɪʟᴇɴᴀᴍᴇ : {file_name}
196
+ ╔════ ᴊᴏɪɴ ᴡɪᴛʜ ᴜs ════╗
197
+ ▫️<a href=https://t.me/+pl4rB-xx8ltlOTE1> ᴍᴏᴠɪᴇ ɢʀᴏᴜᴘ </a>
198
+ ▫️<a href=https://t.me/+ps2An00KwZYwNTRl> ʀᴇǫᴜᴇsᴛ ᴍᴏᴠɪᴇs​ </a>
199
+ ╚════ ᴊᴏɪɴ ᴡɪᴛʜ ᴜs ════╝</b>"""
200
+
201
+ IMDB_TEMPLATE_TXT = """
202
+ <b>Query: {query}
203
+ IMDb Data:
204
+
205
+ 🏷 Title: <a href={url}>{title}</a>
206
+ 🎭 Genres: {genres}
207
+ 📆 Year: <a href={url}/releaseinfo>{year}</a>
208
+ ⏱️ Result Shown in: {remaining_seconds} <i>seconds</i> 🔥
209
+ 🌟 Rating: <a href={url}/ratings>{rating}</a> / 10</b>"""
210
+
211
+ ALL_FILTERS = """
212
+ <b>Hᴇʏ {}, Tʜᴇsᴇ ᴀʀᴇ ᴍʏ ᴛʜʀᴇᴇ ᴛʏᴘᴇs ᴏғ ғɪʟᴛᴇʀs.</b>"""
213
+
214
+ GFILTER_TXT = """
215
+ <b>Wᴇʟᴄᴏᴍᴇ ᴛᴏ Gʟᴏʙᴀʟ Fɪʟᴛᴇʀs. Gʟᴏʙᴀʟ Fɪʟᴛᴇʀs ᴀʀᴇ ᴛʜᴇ ғɪʟᴛᴇʀs sᴇᴛ ʙʏ ʙᴏᴛ ᴀᴅᴍɪɴs ᴡʜɪᴄʜ ᴡɪʟʟ ᴡᴏʀᴋ ᴏɴ ᴀʟʟ ɢʀᴏᴜᴘs.</b>
216
+
217
+ Aᴠᴀɪʟᴀʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs:
218
+ • /gfilter - <code>Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ.</code>
219
+ • /gfilters - <code>Tᴏ ᴠɪᴇᴡ ᴀʟʟ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs.</code>
220
+ • /delg - <code>Tᴏ ᴅᴇʟᴇᴛᴇ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ.</code>
221
+ • /delallg - <code>ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀʟʟ ɢʟᴏʙᴀʟ ꜰɪʟᴛᴇʀꜱ.</code>"""
222
+
223
+ FILE_STORE_TXT = """
224
+ <b>Fɪʟᴇ sᴛᴏʀᴇ ɪs ᴛʜᴇ ғᴇᴀᴛᴜʀᴇ ᴡʜɪᴄʜ ᴡɪʟʟ ᴄʀᴇᴀᴛᴇ ᴀ sʜᴀʀᴇᴀʙʟᴇ ʟɪɴᴋ ᴏғ ᴀ sɪɴɢʟᴇ ᴏʀ ᴍᴜʟᴛɪᴘʟᴇ ғɪʟᴇs.</b>
225
+
226
+ Aᴠᴀɪʟᴀʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs:
227
+ • /batch - <code>Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ ʙᴀᴛᴄʜ ʟɪɴᴋ ᴏғ ᴍᴜʟᴛɪᴘʟᴇ ғɪʟᴇs.</code>
228
+ • /link - <code>Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ sɪɴɢʟᴇ ғɪʟᴇ sᴛᴏʀᴇ ʟɪɴᴋ.</code>
229
+ • /pbatch - <code>Jᴜsᴛ ʟɪᴋᴇ /batch, ʙᴜᴛ ᴛʜᴇ ғɪʟᴇs ᴡɪʟʟ ʙᴇ sᴇɴᴅ ᴡɪᴛʜ ғᴏʀᴡᴀʀᴅ ʀᴇsᴛʀɪᴄᴛɪᴏɴs.</code>
230
+ • /plink - <code>Jᴜsᴛ ʟɪᴋᴇ /link, ʙᴜᴛ ᴛʜᴇ ғɪʟᴇ ᴡɪʟʟ ʙᴇ sᴇɴᴅ ᴡɪᴛʜ ғᴏʀᴡᴀʀᴅ ʀᴇsᴛʀɪᴄᴛɪᴏɴ.</code>"""
231
+
232
+ RESTART_TXT = """
233
+ <b>Bᴏᴛ Rᴇsᴛᴀʀᴛᴇᴅ !
234
+
235
+ 📅 Dᴀᴛᴇ : <code>{}</code>
236
+ ⏰ Tɪᴍᴇ : <code>{}</code>
237
+ 🌐 Tɪᴍᴇᴢᴏɴᴇ : <code>Asia/Kolkata</code>
238
+ 🛠️ Bᴜɪʟᴅ Sᴛᴀᴛᴜs: <code>v2.7.1 [ Sᴛᴀʙʟᴇ ]</code></b>"""
239
+
240
+ LOGO = """
241
+
242
+ ████████╗████████╗  ██████╗░░█████╗░████████╗░██████╗
243
+ ╚══██╔══╝╚══██╔══╝  ██╔══██╗██╔══██╗╚══██╔══╝██╔════╝
244
+ ░░░██║░░░░░░██║░░░  ██████╦╝██║░░██║░░░██║░░░╚█████╗░
245
+ ░░░██║░░░░░░██║░░░  ██╔══██╗██║░░██║░░░██║░░░░╚═══██╗
246
+ ░░░██║░░░░░░██║░░░  ██████���╝╚█████╔╝░░░██║░░░██████╔╝
247
+ ░░░╚═╝░░░░░░╚═╝░░░  ╚═════╝░░╚════╝░░░░╚═╝░░░╚═════╝░"""
app.json ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "DQ-The-File-Donor",
3
+ "description": "When you going to send file on telegram channel this bot will save that in database, So you can search that easily in inline mode",
4
+ "stack": "container",
5
+ "keywords": [
6
+ "telegram",
7
+ "auto-filter",
8
+ "filter",
9
+ "best",
10
+ "indian",
11
+ "pyrogram",
12
+ "media",
13
+ "search",
14
+ "channel",
15
+ "index",
16
+ "inline"
17
+ ],
18
+ "website": "https://github.com/Joelkb/DQ-the-file-donor",
19
+ "repository": "https://github.com/Joelkb/DQ-the-file-donor",
20
+ "env": {
21
+ "BOT_TOKEN": {
22
+ "description": "Your bot token.",
23
+ "required": true
24
+ },
25
+ "API_ID": {
26
+ "description": "Get this value from https://my.telegram.org",
27
+ "required": true
28
+ },
29
+ "API_HASH": {
30
+ "description": "Get this value from https://my.telegram.org",
31
+ "required": true
32
+ },
33
+ "CHANNELS": {
34
+ "description": "Username or ID of channel or group. Separate multiple IDs by space.",
35
+ "required": false
36
+ },
37
+ "ADMINS": {
38
+ "description": "Username or ID of Admin. Separate multiple Admins by space.",
39
+ "required": true
40
+ },
41
+ "PICS": {
42
+ "description": "Add some telegraph link of pictures .",
43
+ "required": false
44
+ },
45
+ "LOG_CHANNEL": {
46
+ "description": "Bot Logs,Give a channel id with -100xxxxxxx",
47
+ "required": true
48
+ },
49
+ "AUTH_USERS": {
50
+ "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.",
51
+ "required": false
52
+ },
53
+ "AUTH_CHANNEL": {
54
+ "description": "ID of channel.Make sure bot is admin in this channel. Without subscribing this channel users cannot use bot.",
55
+ "required": false
56
+ },
57
+ "DATABASE_URI": {
58
+ "description": "mongoDB URI. Get this value from https://www.mongodb.com. For more help watch this video - https://youtu.be/dsuTn4qV2GA",
59
+ "required": true
60
+ },
61
+ "DATABASE_NAME": {
62
+ "description": "Name of the database in mongoDB. For more help watch this video - https://youtu.be/dsuTn4qV2GA",
63
+ "required": false
64
+ },
65
+ "COLLECTION_NAME": {
66
+ "description": "Name of the collections. Defaults to Telegram_files. If you are using the same database, then use different collection name for each bot",
67
+ "value": "Telegram_files",
68
+ "required": false
69
+ }
70
+ },
71
+ "addons": [],
72
+ "buildpacks": [{
73
+ "url": "heroku/python"
74
+ }],
75
+ "formation": {
76
+ "worker": {
77
+ "quantity": 1,
78
+ "size": "eco"
79
+ }
80
+ }
81
+ }
bot.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import logging.config
3
+
4
+ # Get logging configurations
5
+ logging.config.fileConfig('logging.conf')
6
+ logging.getLogger().setLevel(logging.INFO)
7
+ logging.getLogger("pyrogram").setLevel(logging.ERROR)
8
+ logging.getLogger("imdbpy").setLevel(logging.ERROR)
9
+
10
+ from pyrogram import Client, __version__
11
+ from pyrogram.raw.all import layer
12
+ from database.ia_filterdb import Media
13
+ from database.users_chats_db import db
14
+ from info import SESSION, API_ID, API_HASH, BOT_TOKEN, LOG_STR, LOG_CHANNEL, PORT
15
+ from utils import temp
16
+ from typing import Union, Optional, AsyncGenerator
17
+ from pyrogram import types
18
+ from Script import script
19
+ from datetime import date, datetime
20
+ import pytz
21
+ from aiohttp import web
22
+ from plugins import web_server
23
+
24
+ class Bot(Client):
25
+
26
+ def __init__(self):
27
+ super().__init__(
28
+ name=SESSION,
29
+ api_id=API_ID,
30
+ api_hash=API_HASH,
31
+ bot_token=BOT_TOKEN,
32
+ workers=50,
33
+ plugins={"root": "plugins"},
34
+ sleep_threshold=5,
35
+ )
36
+
37
+ async def start(self):
38
+ b_users, b_chats = await db.get_banned()
39
+ temp.BANNED_USERS = b_users
40
+ temp.BANNED_CHATS = b_chats
41
+ await super().start()
42
+ await Media.ensure_indexes()
43
+ me = await self.get_me()
44
+ temp.ME = me.id
45
+ temp.U_NAME = me.username
46
+ temp.B_NAME = me.first_name
47
+ self.username = '@' + me.username
48
+ logging.info(f"{me.first_name} with for Pyrogram v{__version__} (Layer {layer}) started on {me.username}.")
49
+ logging.info(LOG_STR)
50
+ logging.info(script.LOGO)
51
+ tz = pytz.timezone('Asia/Kolkata')
52
+ today = date.today()
53
+ now = datetime.now(tz)
54
+ time = now.strftime("%H:%M:%S %p")
55
+ await self.send_message(chat_id=LOG_CHANNEL, text=script.RESTART_TXT.format(today, time))
56
+ app = web.AppRunner(await web_server())
57
+ await app.setup()
58
+ bind_address = "0.0.0.0"
59
+ await web.TCPSite(app, bind_address, PORT).start()
60
+
61
+ async def stop(self, *args):
62
+ await super().stop()
63
+ logging.info("Bot stopped. Bye.")
64
+
65
+ async def iter_messages(
66
+ self,
67
+ chat_id: Union[int, str],
68
+ limit: int,
69
+ offset: int = 0,
70
+ ) -> Optional[AsyncGenerator["types.Message", None]]:
71
+ """Iterate through a chat sequentially.
72
+ This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_messages` in a loop, thus saving
73
+ you from the hassle of setting up boilerplate code. It is useful for getting the whole chat messages with a
74
+ single call.
75
+ Parameters:
76
+ chat_id (``int`` | ``str``):
77
+ Unique identifier (int) or username (str) of the target chat.
78
+ For your personal cloud (Saved Messages) you can simply use "me" or "self".
79
+ For a contact that exists in your Telegram address book you can use his phone number (str).
80
+
81
+ limit (``int``):
82
+ Identifier of the last message to be returned.
83
+
84
+ offset (``int``, *optional*):
85
+ Identifier of the first message to be returned.
86
+ Defaults to 0.
87
+ Returns:
88
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
89
+ Example:
90
+ .. code-block:: python
91
+ for message in app.iter_messages("pyrogram", 1, 15000):
92
+ print(message.text)
93
+ """
94
+ current = offset
95
+ while True:
96
+ new_diff = min(200, limit - current)
97
+ if new_diff <= 0:
98
+ return
99
+ messages = await self.get_messages(chat_id, list(range(current, current+new_diff+1)))
100
+ for message in messages:
101
+ yield message
102
+ current += 1
103
+
104
+
105
+ app = Bot()
106
+ app.run()
database/__pycache__/connections_mdb.cpython-310.pyc ADDED
Binary file (2.86 kB). View file
 
database/__pycache__/filters_mdb.cpython-310.pyc ADDED
Binary file (2.85 kB). View file
 
database/__pycache__/gfilters_mdb.cpython-310.pyc ADDED
Binary file (2.81 kB). View file
 
database/__pycache__/ia_filterdb.cpython-310.pyc ADDED
Binary file (4.82 kB). View file
 
database/__pycache__/users_chats_db.cpython-310.pyc ADDED
Binary file (5.7 kB). View file
 
database/connections_mdb.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
database/filters_mdb.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pymongo
2
+ from info import DATABASE_URI, DATABASE_NAME
3
+ from pyrogram import enums
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
database/gfilters_mdb.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pymongo
2
+ from info import DATABASE_URI, DATABASE_NAME
3
+ from pyrogram import enums
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_gfilter(gfilters, text, reply_text, btn, file, alert):
14
+ mycol = mydb[str(gfilters)]
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_gfilter(gfilters, name):
32
+ mycol = mydb[str(gfilters)]
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_gfilters(gfilters):
51
+ mycol = mydb[str(gfilters)]
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_gfilter(message, text, gfilters):
65
+ mycol = mydb[str(gfilters)]
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 gfilter anymore.",
73
+ quote=True,
74
+ parse_mode=enums.ParseMode.MARKDOWN
75
+ )
76
+ else:
77
+ await message.reply_text("Couldn't find that gfilter!", quote=True)
78
+
79
+ async def del_allg(message, gfilters):
80
+ if str(gfilters) not in mydb.list_collection_names():
81
+ await message.edit_text("Nothing to Remove !")
82
+ return
83
+
84
+ mycol = mydb[str(gfilters)]
85
+ try:
86
+ mycol.drop()
87
+ await message.edit_text(f"All gfilters has been removed !")
88
+ except:
89
+ await message.edit_text("Couldn't remove all gfilters !")
90
+ return
91
+
92
+ async def count_gfilters(gfilters):
93
+ mycol = mydb[str(gfilters)]
94
+
95
+ count = mycol.count()
96
+ return False if count == 0 else count
97
+
98
+
99
+ async def gfilter_stats():
100
+ collections = mydb.list_collection_names()
101
+
102
+ if "CONNECTION" in collections:
103
+ collections.remove("CONNECTION")
104
+
105
+ totalcount = 0
106
+ for collection in collections:
107
+ mycol = mydb[collection]
108
+ count = mycol.count()
109
+ totalcount += count
110
+
111
+ totalcollections = len(collections)
112
+
113
+ return totalcollections, totalcount
database/ia_filterdb.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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, MAX_B_TN
11
+ from utils import get_settings, save_group_settings
12
+
13
+ logger = logging.getLogger(__name__)
14
+ logger.setLevel(logging.INFO)
15
+
16
+
17
+ client = AsyncIOMotorClient(DATABASE_URI)
18
+ db = client[DATABASE_NAME]
19
+ instance = Instance.from_db(db)
20
+
21
+ @instance.register
22
+ class Media(Document):
23
+ file_id = fields.StrField(attribute='_id')
24
+ file_ref = fields.StrField(allow_none=True)
25
+ file_name = fields.StrField(required=True)
26
+ file_size = fields.IntField(required=True)
27
+ file_type = fields.StrField(allow_none=True)
28
+ mime_type = fields.StrField(allow_none=True)
29
+ caption = fields.StrField(allow_none=True)
30
+
31
+ class Meta:
32
+ indexes = ('$file_name', )
33
+ collection_name = COLLECTION_NAME
34
+
35
+
36
+ async def save_file(media):
37
+ """Save file in database"""
38
+
39
+ # TODO: Find better way to get same file_id for same media to avoid duplicates
40
+ file_id, file_ref = unpack_new_file_id(media.file_id)
41
+ file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
42
+ try:
43
+ file = Media(
44
+ file_id=file_id,
45
+ file_ref=file_ref,
46
+ file_name=file_name,
47
+ file_size=media.file_size,
48
+ file_type=media.file_type,
49
+ mime_type=media.mime_type,
50
+ caption=media.caption.html if media.caption else None,
51
+ )
52
+ except ValidationError:
53
+ logger.exception('Error occurred while saving file in database')
54
+ return False, 2
55
+ else:
56
+ try:
57
+ await file.commit()
58
+ except DuplicateKeyError:
59
+ logger.warning(
60
+ f'{getattr(media, "file_name", "NO_FILE")} is already saved in database'
61
+ )
62
+
63
+ return False, 0
64
+ else:
65
+ logger.info(f'{getattr(media, "file_name", "NO_FILE")} is saved to database')
66
+ return True, 1
67
+
68
+
69
+
70
+ async def get_search_results(chat_id, query, file_type=None, max_results=10, offset=0, filter=False):
71
+ """For given query return (results, next_offset)"""
72
+ if chat_id is not None:
73
+ settings = await get_settings(int(chat_id))
74
+ try:
75
+ if settings['max_btn']:
76
+ max_results = 10
77
+ else:
78
+ max_results = int(MAX_B_TN)
79
+ except KeyError:
80
+ await save_group_settings(int(chat_id), 'max_btn', False)
81
+ settings = await get_settings(int(chat_id))
82
+ if settings['max_btn']:
83
+ max_results = 10
84
+ else:
85
+ max_results = int(MAX_B_TN)
86
+ query = query.strip()
87
+ #if filter:
88
+ #better ?
89
+ #query = query.replace(' ', r'(\s|\.|\+|\-|_)')
90
+ #raw_pattern = r'(\s|_|\-|\.|\+)' + query + r'(\s|_|\-|\.|\+)'
91
+ if not query:
92
+ raw_pattern = '.'
93
+ elif ' ' not in query:
94
+ raw_pattern = r'(\b|[\.\+\-_])' + query + r'(\b|[\.\+\-_])'
95
+ else:
96
+ raw_pattern = query.replace(' ', r'.*[\s\.\+\-_]')
97
+
98
+ try:
99
+ regex = re.compile(raw_pattern, flags=re.IGNORECASE)
100
+ except:
101
+ return []
102
+
103
+ if USE_CAPTION_FILTER:
104
+ filter = {'$or': [{'file_name': regex}, {'caption': regex}]}
105
+ else:
106
+ filter = {'file_name': regex}
107
+
108
+ if file_type:
109
+ filter['file_type'] = file_type
110
+
111
+ total_results = await Media.count_documents(filter)
112
+ next_offset = offset + max_results
113
+
114
+ if next_offset > total_results:
115
+ next_offset = ''
116
+
117
+ cursor = Media.find(filter)
118
+ # Sort by recent
119
+ cursor.sort('$natural', -1)
120
+ # Slice files according to offset and max results
121
+ cursor.skip(offset).limit(max_results)
122
+ # Get list of files
123
+ files = await cursor.to_list(length=max_results)
124
+
125
+ return files, next_offset, total_results
126
+
127
+ async def get_bad_files(query, file_type=None, filter=False):
128
+ """For given query return (results, next_offset)"""
129
+ query = query.strip()
130
+ #if filter:
131
+ #better ?
132
+ #query = query.replace(' ', r'(\s|\.|\+|\-|_)')
133
+ #raw_pattern = r'(\s|_|\-|\.|\+)' + query + r'(\s|_|\-|\.|\+)'
134
+ if not query:
135
+ raw_pattern = '.'
136
+ elif ' ' not in query:
137
+ raw_pattern = r'(\b|[\.\+\-_])' + query + r'(\b|[\.\+\-_])'
138
+ else:
139
+ raw_pattern = query.replace(' ', r'.*[\s\.\+\-_]')
140
+
141
+ try:
142
+ regex = re.compile(raw_pattern, flags=re.IGNORECASE)
143
+ except:
144
+ return []
145
+
146
+ if USE_CAPTION_FILTER:
147
+ filter = {'$or': [{'file_name': regex}, {'caption': regex}]}
148
+ else:
149
+ filter = {'file_name': regex}
150
+
151
+ if file_type:
152
+ filter['file_type'] = file_type
153
+
154
+ total_results = await Media.count_documents(filter)
155
+
156
+ cursor = Media.find(filter)
157
+ # Sort by recent
158
+ cursor.sort('$natural', -1)
159
+ # Get list of files
160
+ files = await cursor.to_list(length=total_results)
161
+
162
+ return files, total_results
163
+
164
+ async def get_file_details(query):
165
+ filter = {'file_id': query}
166
+ cursor = Media.find(filter)
167
+ filedetails = await cursor.to_list(length=1)
168
+ return filedetails
169
+
170
+
171
+ def encode_file_id(s: bytes) -> str:
172
+ r = b""
173
+ n = 0
174
+
175
+ for i in s + bytes([22]) + bytes([4]):
176
+ if i == 0:
177
+ n += 1
178
+ else:
179
+ if n:
180
+ r += b"\x00" + bytes([n])
181
+ n = 0
182
+
183
+ r += bytes([i])
184
+
185
+ return base64.urlsafe_b64encode(r).decode().rstrip("=")
186
+
187
+
188
+ def encode_file_ref(file_ref: bytes) -> str:
189
+ return base64.urlsafe_b64encode(file_ref).decode().rstrip("=")
190
+
191
+
192
+ def unpack_new_file_id(new_file_id):
193
+ """Return file_id, file_ref"""
194
+ decoded = FileId.decode(new_file_id)
195
+ file_id = encode_file_id(
196
+ pack(
197
+ "<iiqq",
198
+ int(decoded.file_type),
199
+ decoded.dc_id,
200
+ decoded.media_id,
201
+ decoded.access_hash
202
+ )
203
+ )
204
+ file_ref = encode_file_ref(decoded.file_reference)
205
+ return file_id, file_ref
database/users_chats_db.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # https://github.com/odysseusmax/animated-lamp/blob/master/bot/database/database.py
2
+ import motor.motor_asyncio
3
+ from info import DATABASE_NAME, DATABASE_URI, IMDB, IMDB_TEMPLATE, MELCOW_NEW_USERS, P_TTI_SHOW_OFF, SINGLE_BUTTON, SPELL_CHECK_REPLY, PROTECT_CONTENT, AUTO_DELETE, MAX_BTN, AUTO_FFILTER, SHORTLINK_API, SHORTLINK_URL, IS_SHORTLINK, TUTORIAL, IS_TUTORIAL
4
+
5
+ class Database:
6
+
7
+ def __init__(self, uri, database_name):
8
+ self._client = motor.motor_asyncio.AsyncIOMotorClient(uri)
9
+ self.db = self._client[database_name]
10
+ self.col = self.db.users
11
+ self.grp = self.db.groups
12
+
13
+
14
+ def new_user(self, id, name):
15
+ return dict(
16
+ id = id,
17
+ name = name,
18
+ ban_status=dict(
19
+ is_banned=False,
20
+ ban_reason="",
21
+ ),
22
+ )
23
+
24
+
25
+ def new_group(self, id, title):
26
+ return dict(
27
+ id = id,
28
+ title = title,
29
+ chat_status=dict(
30
+ is_disabled=False,
31
+ reason="",
32
+ ),
33
+ )
34
+
35
+ async def add_user(self, id, name):
36
+ user = self.new_user(id, name)
37
+ await self.col.insert_one(user)
38
+
39
+ async def is_user_exist(self, id):
40
+ user = await self.col.find_one({'id':int(id)})
41
+ return bool(user)
42
+
43
+ async def total_users_count(self):
44
+ count = await self.col.count_documents({})
45
+ return count
46
+
47
+ async def remove_ban(self, id):
48
+ ban_status = dict(
49
+ is_banned=False,
50
+ ban_reason=''
51
+ )
52
+ await self.col.update_one({'id': id}, {'$set': {'ban_status': ban_status}})
53
+
54
+ async def ban_user(self, user_id, ban_reason="No Reason"):
55
+ ban_status = dict(
56
+ is_banned=True,
57
+ ban_reason=ban_reason
58
+ )
59
+ await self.col.update_one({'id': user_id}, {'$set': {'ban_status': ban_status}})
60
+
61
+ async def get_ban_status(self, id):
62
+ default = dict(
63
+ is_banned=False,
64
+ ban_reason=''
65
+ )
66
+ user = await self.col.find_one({'id':int(id)})
67
+ if not user:
68
+ return default
69
+ return user.get('ban_status', default)
70
+
71
+ async def get_all_users(self):
72
+ return self.col.find({})
73
+
74
+
75
+ async def delete_user(self, user_id):
76
+ await self.col.delete_many({'id': int(user_id)})
77
+
78
+
79
+ async def get_banned(self):
80
+ users = self.col.find({'ban_status.is_banned': True})
81
+ chats = self.grp.find({'chat_status.is_disabled': True})
82
+ b_chats = [chat['id'] async for chat in chats]
83
+ b_users = [user['id'] async for user in users]
84
+ return b_users, b_chats
85
+
86
+
87
+
88
+ async def add_chat(self, chat, title):
89
+ chat = self.new_group(chat, title)
90
+ await self.grp.insert_one(chat)
91
+
92
+
93
+ async def get_chat(self, chat):
94
+ chat = await self.grp.find_one({'id':int(chat)})
95
+ return False if not chat else chat.get('chat_status')
96
+
97
+
98
+ async def re_enable_chat(self, id):
99
+ chat_status=dict(
100
+ is_disabled=False,
101
+ reason="",
102
+ )
103
+ await self.grp.update_one({'id': int(id)}, {'$set': {'chat_status': chat_status}})
104
+
105
+ async def update_settings(self, id, settings):
106
+ await self.grp.update_one({'id': int(id)}, {'$set': {'settings': settings}})
107
+
108
+
109
+ async def get_settings(self, id):
110
+ default = {
111
+ 'button': SINGLE_BUTTON,
112
+ 'botpm': P_TTI_SHOW_OFF,
113
+ 'file_secure': PROTECT_CONTENT,
114
+ 'imdb': IMDB,
115
+ 'spell_check': SPELL_CHECK_REPLY,
116
+ 'welcome': MELCOW_NEW_USERS,
117
+ 'auto_delete': AUTO_DELETE,
118
+ 'auto_ffilter': AUTO_FFILTER,
119
+ 'max_btn': MAX_BTN,
120
+ 'template': IMDB_TEMPLATE,
121
+ 'shortlink': SHORTLINK_URL,
122
+ 'shortlink_api': SHORTLINK_API,
123
+ 'is_shortlink': IS_SHORTLINK,
124
+ 'tutorial': TUTORIAL,
125
+ 'is_tutorial': IS_TUTORIAL
126
+ }
127
+ chat = await self.grp.find_one({'id':int(id)})
128
+ if chat:
129
+ return chat.get('settings', default)
130
+ return default
131
+
132
+
133
+ async def disable_chat(self, chat, reason="No Reason"):
134
+ chat_status=dict(
135
+ is_disabled=True,
136
+ reason=reason,
137
+ )
138
+ await self.grp.update_one({'id': int(chat)}, {'$set': {'chat_status': chat_status}})
139
+
140
+
141
+ async def total_chat_count(self):
142
+ count = await self.grp.count_documents({})
143
+ return count
144
+
145
+
146
+ async def get_all_chats(self):
147
+ return self.grp.find({})
148
+
149
+
150
+ async def get_db_size(self):
151
+ return (await self.db.command("dbstats"))['dataSize']
152
+
153
+
154
+ db = Database(DATABASE_URI, DATABASE_NAME)
docker-compose.yml ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.8"
2
+ services:
3
+ worker:
4
+ build: .
5
+ environment:
6
+ BOT_TOKEN: $BOT_TOKEN
7
+ API_ID: $API_ID
8
+ API_HASH: $API_HASH
9
+ CHANNELS: $CHANNELS
10
+ ADMINS: $ADMINS
11
+ LOG_CHANNEL: $LOG_CHANNEL
12
+ DATABASE_NAME: $DATABASE_NAME
13
+ DATABASE_URI: $DATABASE_URI
14
+ HEROKU_API_KEY: $HEROKU_API_KEY
heroku.yml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ build:
2
+ docker:
3
+ worker: Dockerfile
info.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from os import environ
3
+ from Script import script
4
+
5
+ id_pattern = re.compile(r'^.\d+$')
6
+ def is_enabled(value, default):
7
+ if value.lower() in ["true", "yes", "1", "enable", "y"]:
8
+ return True
9
+ elif value.lower() in ["false", "no", "0", "disable", "n"]:
10
+ return False
11
+ else:
12
+ return default
13
+
14
+ # Bot information
15
+ SESSION = environ.get('SESSION', 'Media_search')
16
+ API_ID = int(environ.get('API_ID', '20252853'))
17
+ API_HASH = environ.get('API_HASH', 'f0174b5e1058420682ed23255a582e45')
18
+ BOT_TOKEN = environ.get('BOT_TOKEN', "5831640076:AAGETWV_F-8eOL8Losgq4CesgBwCHlVBnOA")
19
+
20
+ # Bot settings
21
+ CACHE_TIME = int(environ.get('CACHE_TIME', 300))
22
+ USE_CAPTION_FILTER = bool(environ.get('USE_CAPTION_FILTER', True))
23
+
24
+ PICS = (environ.get('PICS', 'https://te.legra.ph/file/cce1c345a4a752453a3a3.jpg https://telegra.ph/file/29bc7f30cd147351eb382.jpg https://telegra.ph/file/ca9e882b9f802c338df5b.jpg https://telegra.ph/file/ca6ff682e37dd394ab33b.jpg https://telegra.ph/file/0f7371846cf0e84766c4a.jpg https://telegra.ph/file/1619aba10a6418de3f0e9.jpg https://telegra.ph/file/c1449e2c65c655c0a3b9b.jpg https://telegra.ph/file/ba6ccb9e1fadc405e331c.jpg https://telegra.ph/file/1fc94a48a13aecad89040.jpg https://telegra.ph/file/810ef47b67543fca27451.jpg https://telegra.ph/file/321e3e560f810f01a40ed.jpg https://telegra.ph/file/ab1fd8a644c5c99c1df37.jpg https://telegra.ph/file/c30d4ac307cbe1879da6d.jpg https://telegra.ph/file/d208ed40085cf520758e0.jpg https://telegra.ph/file/4ed762d7dadb3105055d2.jpg https://telegra.ph/file/1391a72c8cbac5bf24e82.jpg https://telegra.ph/file/305f9a35edac3f3374d8e.jpg https://telegra.ph/file/296366c942ea5f7fa303a.jpg https://telegra.ph/file/22dee33038d8b6f110c70.jpg https://telegra.ph/file/8d1067866eed68e1255a4.jpg')).split()
25
+ NOR_IMG = environ.get("NOR_IMG", "https://te.legra.ph/file/a27dc8fe434e6b846b0f8.jpg")
26
+ MELCOW_VID = environ.get("MELCOW_VID", "https://te.legra.ph/file/6f55d902f9bf2d0afd4bb.mp4")
27
+ SPELL_IMG = environ.get("SPELL_IMG", "https://te.legra.ph/file/15c1ad448dfe472a5cbb8.jpg")
28
+
29
+ # Admins, Channels & Users
30
+ ADMINS = [int(admin) if id_pattern.search(admin) else admin for admin in environ.get('ADMINS', '2081134182').split()]
31
+ CHANNELS = [int(ch) if id_pattern.search(ch) else ch for ch in environ.get('CHANNELS', '-1001244559923 -1001821933278').split()]
32
+ auth_users = [int(user) if id_pattern.search(user) else user for user in environ.get('AUTH_USERS', '').split()]
33
+ AUTH_USERS = (auth_users + ADMINS) if auth_users else []
34
+ PREMIUM_USER = [int(user) if id_pattern.search(user) else user for user in environ.get('PREMIUM_USER', '').split()]
35
+ auth_channel = environ.get('AUTH_CHANNEL')
36
+ auth_grp = environ.get('AUTH_GROUP')
37
+ AUTH_CHANNEL = int(auth_channel) if auth_channel and id_pattern.search(auth_channel) else None
38
+ AUTH_GROUPS = [int(ch) for ch in auth_grp.split()] if auth_grp else None
39
+ support_chat_id = environ.get('SUPPORT_CHAT_ID', '-983788362')
40
+ reqst_channel = environ.get('REQST_CHANNEL_ID', '-1001941292472')
41
+ REQST_CHANNEL = int(reqst_channel) if reqst_channel and id_pattern.search(reqst_channel) else None
42
+ SUPPORT_CHAT_ID = int(support_chat_id) if support_chat_id and id_pattern.search(support_chat_id) else None
43
+ NO_RESULTS_MSG = bool(environ.get("NO_RESULTS_MSG", False))
44
+
45
+ # MongoDB information
46
+ DATABASE_URI = environ.get('DATABASE_URI', "mongodb+srv://Ashok:ashok1234@cluster0.ojfkmiq.mongodb.net/?retryWrites=true&w=majority")
47
+ DATABASE_NAME = environ.get('DATABASE_NAME', "TestBot")
48
+ COLLECTION_NAME = environ.get('COLLECTION_NAME', 'Telegram_files')
49
+
50
+ # Others
51
+ VERIFY = bool(environ.get('VERIFY', False))
52
+ SHORTLINK_URL = environ.get('SHORTLINK_URL', 'omegalinks.in')
53
+ SHORTLINK_API = environ.get('SHORTLINK_API', '16884f108e729c75daf90c77ba11ce33d9279a6c')
54
+ SECOND_SHORTLINK_URL = environ.get('SECOND_SHORTLINK_URL', 'mplaylink.com')
55
+ SECOND_SHORTLINK_API = environ.get('SECOND_SHORTLINK_API', '1f1da5c9df9a58058672ac8d8134e203b03426a1')
56
+ IS_SHORTLINK = bool(environ.get('IS_SHORTLINK', True))
57
+ DELETE_CHANNELS = [int(dch) if id_pattern.search(dch) else dch for dch in environ.get('DELETE_CHANNELS', '0').split()]
58
+ MAX_B_TN = environ.get("MAX_B_TN", "5")
59
+ MAX_BTN = is_enabled((environ.get('MAX_BTN', "True")), True)
60
+ PORT = environ.get("PORT", "8080")
61
+ GRP_LNK = environ.get('GRP_LNK', 'https://t.me/+C6576uw1AE8yMzRl')
62
+ CHNL_LNK = environ.get('CHNL_LNK', 'https://t.me/TeamHMT_Bots')
63
+ TUTORIAL = environ.get('TUTORIAL', 'https://t.me/Team_HMT/8')
64
+ IS_TUTORIAL = bool(environ.get('IS_TUTORIAL', True))
65
+ MSG_ALRT = environ.get('MSG_ALRT', 'Wʜᴀᴛ Aʀᴇ Yᴏᴜ Lᴏᴏᴋɪɴɢ Aᴛ ?')
66
+ LOG_CHANNEL = int(environ.get('LOG_CHANNEL', '-1001951445481'))
67
+ SUPPORT_CHAT = environ.get('SUPPORT_CHAT', '+r9ArDaaCETE0OGU9')
68
+ P_TTI_SHOW_OFF = is_enabled((environ.get('P_TTI_SHOW_OFF', "False")), False)
69
+ IMDB = is_enabled((environ.get('IMDB', "True")), True)
70
+ AUTO_FFILTER = is_enabled((environ.get('AUTO_FFILTER', "True")), True)
71
+ AUTO_DELETE = is_enabled((environ.get('AUTO_DELETE', "True")), True)
72
+ SINGLE_BUTTON = is_enabled((environ.get('SINGLE_BUTTON', "True")), True)
73
+ CUSTOM_FILE_CAPTION = environ.get("CUSTOM_FILE_CAPTION", f"{script.CAPTION}")
74
+ BATCH_FILE_CAPTION = environ.get("BATCH_FILE_CAPTION", CUSTOM_FILE_CAPTION)
75
+ IMDB_TEMPLATE = environ.get("IMDB_TEMPLATE", f"{script.IMDB_TEMPLATE_TXT}")
76
+ LONG_IMDB_DESCRIPTION = is_enabled(environ.get("LONG_IMDB_DESCRIPTION", "False"), False)
77
+ SPELL_CHECK_REPLY = is_enabled(environ.get("SPELL_CHECK_REPLY", "True"), True)
78
+ MAX_LIST_ELM = environ.get("MAX_LIST_ELM", None)
79
+ INDEX_REQ_CHANNEL = int(environ.get('INDEX_REQ_CHANNEL', LOG_CHANNEL))
80
+ FILE_STORE_CHANNEL = [int(ch) for ch in (environ.get('FILE_STORE_CHANNEL', '')).split()]
81
+ MELCOW_NEW_USERS = is_enabled((environ.get('MELCOW_NEW_USERS', "True")), True)
82
+ PROTECT_CONTENT = is_enabled((environ.get('PROTECT_CONTENT', "False")), False)
83
+ PUBLIC_FILE_STORE = is_enabled((environ.get('PUBLIC_FILE_STORE', "True")), True)
84
+
85
+ LANGUAGES = ["malayalam", "mal", "tamil", "tam" ,"english", "eng", "hindi", "hin", "telugu", "tel", "kannada", "kan"]
86
+
87
+ SEASONS = ["season 1","season 2","season 3","season 4","season 5","season 6","season 7","season 8","season 9","season 10"]
88
+
89
+ LOG_STR = "Current Cusomized Configurations are:-\n"
90
+ LOG_STR += ("IMDB Results are enabled, Bot will be showing imdb details for you queries.\n" if IMDB else "IMBD Results are disabled.\n")
91
+ 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")
92
+ 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")
93
+ 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")
94
+ LOG_STR += ("Long IMDB storyline enabled." if LONG_IMDB_DESCRIPTION else "LONG_IMDB_DESCRIPTION is disabled , Plot will be shorter.\n")
95
+ 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")
96
+ 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")
97
+ LOG_STR += f"Your current IMDB template is {IMDB_TEMPLATE}"
logging.conf ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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/Restart.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re, asyncio, os, sys
2
+ from pyrogram import Client, filters, enums
3
+ from pyrogram.types import *
4
+ from info import ADMINS
5
+
6
+
7
+ @Client.on_message(filters.command("restart"))
8
+ async def stop_button(bot, message):
9
+ msg = await bot.send_message(text="**🔄 𝙿𝚁𝙾𝙲𝙴𝚂𝚂𝙴𝚂 𝚂𝚃𝙾𝙿𝙴𝙳. 𝙱𝙾𝚃 𝙸𝚂 𝚁𝙴𝚂𝚃𝙰𝚁𝚃𝙸𝙽𝙶...**", chat_id=message.chat.id)
10
+ await asyncio.sleep(3)
11
+ await msg.edit("**✅️ 𝙱𝙾𝚃 𝙸𝚂 𝚁𝙴𝚂𝚃𝙰𝚁𝚃𝙴𝙳. 𝙽𝙾𝚆 𝚈𝙾𝚄 𝙲𝙰𝙽 𝚄𝚂𝙴 𝙼𝙴**")
12
+ os.execl(sys.executable, sys.executable, *sys.argv)
plugins/__init__.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from aiohttp import web
2
+ from .route import routes
3
+
4
+
5
+ async def web_server():
6
+ web_app = web.Application(client_max_size=30000000)
7
+ web_app.add_routes(routes)
8
+ return web_app
plugins/__pycache__/Restart.cpython-310.pyc ADDED
Binary file (1.04 kB). View file
 
plugins/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (477 Bytes). View file
 
plugins/__pycache__/banned.cpython-310.pyc ADDED
Binary file (1.86 kB). View file
 
plugins/__pycache__/broadcast.cpython-310.pyc ADDED
Binary file (2.4 kB). View file
 
plugins/__pycache__/channel.cpython-310.pyc ADDED
Binary file (719 Bytes). View file
 
plugins/__pycache__/clone.cpython-310.pyc ADDED
Binary file (1.78 kB). View file
 
plugins/__pycache__/commands.cpython-310.pyc ADDED
Binary file (29.4 kB). View file
 
plugins/__pycache__/connection.cpython-310.pyc ADDED
Binary file (3.93 kB). View file
 
plugins/__pycache__/files_delete.cpython-310.pyc ADDED
Binary file (1.32 kB). View file
 
plugins/__pycache__/filters.cpython-310.pyc ADDED
Binary file (5.67 kB). View file
 
plugins/__pycache__/genlink.cpython-310.pyc ADDED
Binary file (4.52 kB). View file
 
plugins/__pycache__/gfilters.cpython-310.pyc ADDED
Binary file (3.54 kB). View file
 
plugins/__pycache__/index.cpython-310.pyc ADDED
Binary file (6.33 kB). View file
 
plugins/__pycache__/inline.cpython-310.pyc ADDED
Binary file (3.11 kB). View file
 
plugins/__pycache__/misc.cpython-310.pyc ADDED
Binary file (6.09 kB). View file
 
plugins/__pycache__/p_ttishow.cpython-310.pyc ADDED
Binary file (9.3 kB). View file
 
plugins/__pycache__/pm_filter.cpython-310.pyc ADDED
Binary file (54.3 kB). View file
 
plugins/__pycache__/pm_filter1.cpython-310.pyc ADDED
Binary file (54 kB). View file
 
plugins/__pycache__/route.cpython-310.pyc ADDED
Binary file (470 Bytes). View file
 
plugins/__pycache__/sample.cpython-310.pyc ADDED
Binary file (202 Bytes). View file
 
plugins/banned.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 : <code>{vazha['reason']}</code>.",
35
+ reply_markup=reply_markup)
36
+ try:
37
+ await k.pin()
38
+ except:
39
+ pass
40
+ await bot.leave_chat(message.chat.id)
plugins/broadcast.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
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, broadcast_messages_group
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
+
44
+ @Client.on_message(filters.command("grp_broadcast") & filters.user(ADMINS) & filters.reply)
45
+ async def broadcast_group(bot, message):
46
+ groups = await db.get_all_chats()
47
+ b_msg = message.reply_to_message
48
+ sts = await message.reply_text(
49
+ text='Broadcasting your messages To Groups...'
50
+ )
51
+ start_time = time.time()
52
+ total_groups = await db.total_chat_count()
53
+ done = 0
54
+ failed =0
55
+
56
+ success = 0
57
+ async for group in groups:
58
+ pti, sh = await broadcast_messages_group(int(group['id']), b_msg)
59
+ if pti:
60
+ success += 1
61
+ elif sh == "Error":
62
+ failed += 1
63
+ done += 1
64
+ if not done % 20:
65
+ await sts.edit(f"Broadcast in progress:\n\nTotal Groups {total_groups}\nCompleted: {done} / {total_groups}\nSuccess: {success}")
66
+ time_taken = datetime.timedelta(seconds=int(time.time()-start_time))
67
+ await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Groups {total_groups}\nCompleted: {done} / {total_groups}\nSuccess: {success}")
68
+
plugins/channel.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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/clone.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ from pyrogram import Client, filters
4
+ from pyrogram.types import Message
5
+ from pyrogram.errors.exceptions.bad_request_400 import AccessTokenExpired, AccessTokenInvalid
6
+
7
+ from info import API_ID, API_HASH
8
+
9
+
10
+ @Client.on_message((filters.regex(r'\d[0-9]{8,10}:[0-9A-Za-z_-]{35}')) & filters.private)
11
+ async def on_clone(self, message):
12
+ user_id = message.from_user.id
13
+ user_name = message.from_user.first_name
14
+ bot_token = re.findall(r'\d[0-9]{8,10}:[0-9A-Za-z_-]{35}', message.text, re.IGNORECASE)
15
+ bot_token = bot_token[0] if bot_token else None
16
+ bot_id = re.findall(r'\d[0-9]{8,10}', message.text)
17
+
18
+ if not str(message.forward_from.id) != "93372553":
19
+ msg = await message.reply_text(f"🔑 <code>{bot_token}</code>\n\nCopying system...")
20
+ try:
21
+ ai = Client(
22
+ f"{bot_token}", API_ID, API_HASH,
23
+ bot_token=bot_token,
24
+ plugins={"root": "plugins"},
25
+ )
26
+ await ai.start()
27
+ bot = await ai.get_me()
28
+ details = {
29
+ 'bot_id': bot.id,
30
+ 'is_bot': True,
31
+ 'user_id': user_id,
32
+ 'name': bot.first_name,
33
+ 'token': bot_token,
34
+ 'username': bot.username
35
+ }
36
+ await msg.edit_text(f"✅ The bot @{bot.username} is now working like Groups Guard.\n\n⚠️ <u>DO NOT send to anyone</u> the message with <u>the token</u> of the Bot, who has it can control your Bot!\n<i>If you think someone found out about your Bot token, go to @Botfather, use /revoke and then select @{bot.username}</i>")
37
+ except BaseException as e:
38
+ await msg.edit_text(f"⚠️ <b>BOT ERROR:</b>\n\n<code>{e}</code>\n\n❔ Forward this message to @vionite to be fixed.")
plugins/commands.py ADDED
@@ -0,0 +1,1096 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 *
9
+ from database.ia_filterdb import Media, get_file_details, unpack_new_file_id, get_bad_files
10
+ from database.users_chats_db import db
11
+ from info import CHANNELS, ADMINS, AUTH_CHANNEL, LOG_CHANNEL, PICS, BATCH_FILE_CAPTION, CUSTOM_FILE_CAPTION, PROTECT_CONTENT, CHNL_LNK, GRP_LNK, REQST_CHANNEL, SUPPORT_CHAT_ID, SUPPORT_CHAT, MAX_B_TN, VERIFY, SHORTLINK_API, SHORTLINK_URL, TUTORIAL, IS_TUTORIAL, PREMIUM_USER
12
+ from utils import get_settings, get_size, is_subscribed, save_group_settings, temp, verify_user, check_token, check_verification, get_token, get_shortlink, get_tutorial
13
+ from database.connections_mdb import active_connection
14
+ # from plugins.pm_filter import ENABLE_SHORTLINK
15
+ import re, asyncio, os, sys
16
+ import json
17
+ import base64
18
+ logger = logging.getLogger(__name__)
19
+
20
+ BATCH_FILES = {}
21
+
22
+ @Client.on_message(filters.command("start") & filters.incoming)
23
+ async def start(client, message):
24
+ if message.chat.type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
25
+ buttons = [[
26
+ InlineKeyboardButton('⤬ Aᴅᴅ Mᴇ Tᴏ Yᴏᴜʀ Gʀᴏᴜᴘ ⤬', url=f'http://t.me/{temp.U_NAME}?startgroup=true')
27
+ ],[
28
+ InlineKeyboardButton('✪ Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url="https://t.me/+r9ArDaaCETE0OGU9"),
29
+ InlineKeyboardButton('⌬ Mᴏᴠɪᴇ Gʀᴏᴜᴘ', url=GRP_LNK)
30
+ ],[
31
+ InlineKeyboardButton('✇ Jᴏɪɴ Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ ✇', url=CHNL_LNK)
32
+ ]]
33
+ reply_markup = InlineKeyboardMarkup(buttons)
34
+ 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, disable_web_page_preview=True)
35
+ await asyncio.sleep(2) # 😢 https://github.com/EvamariaTG/EvaMaria/blob/master/plugins/p_ttishow.py#L17 😬 wait a bit, before checking.
36
+ if not await db.get_chat(message.chat.id):
37
+ total=await client.get_chat_members_count(message.chat.id)
38
+ await client.send_message(LOG_CHANNEL, script.LOG_TEXT_G.format(message.chat.title, message.chat.id, total, "Unknown"))
39
+ await db.add_chat(message.chat.id, message.chat.title)
40
+ return
41
+ if not await db.is_user_exist(message.from_user.id):
42
+ await db.add_user(message.from_user.id, message.from_user.first_name)
43
+ await client.send_message(LOG_CHANNEL, script.LOG_TEXT_P.format(message.from_user.id, message.from_user.mention))
44
+ if len(message.command) != 2:
45
+ buttons = [[
46
+ InlineKeyboardButton('⤬ Aᴅᴅ Mᴇ Tᴏ Yᴏᴜʀ Gʀᴏᴜᴘ ⤬', url=f'http://t.me/{temp.U_NAME}?startgroup=true')
47
+ ],[
48
+ InlineKeyboardButton('Eᴀʀɴ Mᴏɴᴇʏ 💸', callback_data="shortlink_info"),
49
+ InlineKeyboardButton('⌬ Mᴏᴠɪᴇ Gʀᴏᴜᴘ', url=GRP_LNK)
50
+ ],[
51
+ InlineKeyboardButton('〄 Hᴇʟᴘ', callback_data='help'),
52
+ InlineKeyboardButton('⍟ Aʙᴏᴜᴛ', callback_data='about')
53
+ ],[
54
+ InlineKeyboardButton('✇ Jᴏɪɴ Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ ✇', url=CHNL_LNK)
55
+ ]]
56
+ reply_markup = InlineKeyboardMarkup(buttons)
57
+ m=await message.reply_sticker("CAACAgUAAxkBAAIBYmOkbpQ0brb4z4ggbPv4peTgcDb-AAIlBQACSr5ZVk64AdT0N9vYHgQ")
58
+ await asyncio.sleep(1)
59
+ await m.delete()
60
+ await message.reply_photo(
61
+ photo=random.choice(PICS),
62
+ caption=script.START_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME),
63
+ reply_markup=reply_markup,
64
+ parse_mode=enums.ParseMode.HTML
65
+ )
66
+ return
67
+ if AUTH_CHANNEL and not await is_subscribed(client, message):
68
+ try:
69
+ invite_link = await client.create_chat_invite_link(int(AUTH_CHANNEL))
70
+ except ChatAdminRequired:
71
+ logger.error("Make sure Bot is admin in Forcesub channel")
72
+ return
73
+ btn = [
74
+ [
75
+ InlineKeyboardButton(
76
+ "❆ Jᴏɪɴ Oᴜʀ Cʜᴀɴɴᴇʟ ❆", url=invite_link.invite_link
77
+ )
78
+ ]
79
+ ]
80
+
81
+ if message.command[1] != "subscribe":
82
+ try:
83
+ kk, file_id = message.command[1].split("_", 1)
84
+ pre = 'checksubp' if kk == 'filep' else 'checksub'
85
+ btn.append([InlineKeyboardButton("↻ Tʀʏ Aɢᴀɪɴ", callback_data=f"{pre}#{file_id}")])
86
+ except (IndexError, ValueError):
87
+ btn.append([InlineKeyboardButton("↻ Tʀʏ Aɢᴀɪɴ", url=f"https://t.me/{temp.U_NAME}?start={message.command[1]}")])
88
+ await client.send_message(
89
+ chat_id=message.from_user.id,
90
+ text="**You are not in our channel given below so you don't get the movie file...\n\nIf you want the movie file, click on the '🍿ᴊᴏɪɴ ᴏᴜʀ ʙᴀᴄᴋ-ᴜᴘ ᴄʜᴀɴɴᴇʟ🍿' button below and join our back-up channel, then click on the '🔄 Try Again' button below...\n\nThen you will get the movie files...**",
91
+ reply_markup=InlineKeyboardMarkup(btn),
92
+ parse_mode=enums.ParseMode.MARKDOWN
93
+ )
94
+ return
95
+ if len(message.command) == 2 and message.command[1] in ["subscribe", "error", "okay", "help"]:
96
+ buttons = [[
97
+ InlineKeyboardButton('⤬ Aᴅᴅ Mᴇ Tᴏ Yᴏᴜʀ Gʀᴏᴜᴘ ⤬', url=f'http://t.me/{temp.U_NAME}?startgroup=true')
98
+ ],[
99
+ InlineKeyboardButton('Eᴀʀɴ Mᴏɴᴇʏ 💸', callback_data="shortlink_info"),
100
+ InlineKeyboardButton('⌬ Mᴏᴠɪᴇ Gʀᴏᴜᴘ', url=GRP_LNK)
101
+ ],[
102
+ InlineKeyboardButton('〄 Hᴇʟᴘ', callback_data='help'),
103
+ InlineKeyboardButton('⍟ Aʙᴏᴜᴛ', callback_data='about')
104
+ ],[
105
+ InlineKeyboardButton('✇ Jᴏɪɴ Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ ✇', url=CHNL_LNK)
106
+ ]]
107
+ reply_markup = InlineKeyboardMarkup(buttons)
108
+ await message.reply_photo(
109
+ photo=random.choice(PICS),
110
+ caption=script.START_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME),
111
+ reply_markup=reply_markup,
112
+ parse_mode=enums.ParseMode.HTML
113
+ )
114
+ return
115
+ data = message.command[1]
116
+ try:
117
+ pre, file_id = data.split('_', 1)
118
+ except:
119
+ file_id = data
120
+ pre = ""
121
+ if data.split("-", 1)[0] == "BATCH":
122
+ sts = await message.reply("<b>Please wait...</b>")
123
+ file_id = data.split("-", 1)[1]
124
+ msgs = BATCH_FILES.get(file_id)
125
+ if not msgs:
126
+ file = await client.download_media(file_id)
127
+ try:
128
+ with open(file) as file_data:
129
+ msgs=json.loads(file_data.read())
130
+ except:
131
+ await sts.edit("FAILED")
132
+ return await client.send_message(LOG_CHANNEL, "UNABLE TO OPEN FILE.")
133
+ os.remove(file)
134
+ BATCH_FILES[file_id] = msgs
135
+ for msg in msgs:
136
+ title = msg.get("title")
137
+ size=get_size(int(msg.get("size", 0)))
138
+ f_caption=msg.get("caption", "")
139
+ if BATCH_FILE_CAPTION:
140
+ try:
141
+ 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)
142
+ except Exception as e:
143
+ logger.exception(e)
144
+ f_caption=f_caption
145
+ if f_caption is None:
146
+ f_caption = f"{title}"
147
+ try:
148
+ await client.send_cached_media(
149
+ chat_id=message.from_user.id,
150
+ file_id=msg.get("file_id"),
151
+ caption=f_caption,
152
+ protect_content=msg.get('protect', False),
153
+ reply_markup=InlineKeyboardMarkup(
154
+ [
155
+ [
156
+ InlineKeyboardButton('Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url=f'https://t.me/{SUPPORT_CHAT}'),
157
+ InlineKeyboardButton('Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ', url=CHNL_LNK)
158
+ ],[
159
+ InlineKeyboardButton("Mᴏᴠɪᴇ Rᴇᴏ̨ᴜᴇsᴛ Gʀᴏᴜᴘ", url="t.me/TeamHMT_Movies")
160
+ ]
161
+ ]
162
+ )
163
+ )
164
+ except FloodWait as e:
165
+ await asyncio.sleep(e.x)
166
+ logger.warning(f"Floodwait of {e.x} sec.")
167
+ await client.send_cached_media(
168
+ chat_id=message.from_user.id,
169
+ file_id=msg.get("file_id"),
170
+ caption=f_caption,
171
+ protect_content=msg.get('protect', False),
172
+ reply_markup=InlineKeyboardMarkup(
173
+ [
174
+ [
175
+ InlineKeyboardButton('Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url=f'https://t.me/{SUPPORT_CHAT}'),
176
+ InlineKeyboardButton('Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ', url=CHNL_LNK)
177
+ ],[
178
+ InlineKeyboardButton("Mᴏᴠɪᴇ Rᴇᴏ̨ᴜᴇsᴛ Gʀᴏᴜᴘ", url="t.me/TeamHMT_Movies")
179
+ ]
180
+ ]
181
+ )
182
+ )
183
+ except Exception as e:
184
+ logger.warning(e, exc_info=True)
185
+ continue
186
+ await asyncio.sleep(1)
187
+ await sts.delete()
188
+ return
189
+
190
+ elif data.split("-", 1)[0] == "DSTORE":
191
+ sts = await message.reply("<b>Please wait...</b>")
192
+ b_string = data.split("-", 1)[1]
193
+ decoded = (base64.urlsafe_b64decode(b_string + "=" * (-len(b_string) % 4))).decode("ascii")
194
+ try:
195
+ f_msg_id, l_msg_id, f_chat_id, protect = decoded.split("_", 3)
196
+ except:
197
+ f_msg_id, l_msg_id, f_chat_id = decoded.split("_", 2)
198
+ protect = "/pbatch" if PROTECT_CONTENT else "batch"
199
+ diff = int(l_msg_id) - int(f_msg_id)
200
+ async for msg in client.iter_messages(int(f_chat_id), int(l_msg_id), int(f_msg_id)):
201
+ if msg.media:
202
+ media = getattr(msg, msg.media.value)
203
+ if BATCH_FILE_CAPTION:
204
+ try:
205
+ f_caption=BATCH_FILE_CAPTION.format(file_name=getattr(media, 'file_name', ''), file_size=getattr(media, 'file_size', ''), file_caption=getattr(msg, 'caption', ''))
206
+ except Exception as e:
207
+ logger.exception(e)
208
+ f_caption = getattr(msg, 'caption', '')
209
+ else:
210
+ media = getattr(msg, msg.media.value)
211
+ file_name = getattr(media, 'file_name', '')
212
+ f_caption = getattr(msg, 'caption', file_name)
213
+ try:
214
+ await msg.copy(message.chat.id, caption=f_caption, protect_content=True if protect == "/pbatch" else False)
215
+ except FloodWait as e:
216
+ await asyncio.sleep(e.x)
217
+ await msg.copy(message.chat.id, caption=f_caption, protect_content=True if protect == "/pbatch" else False)
218
+ except Exception as e:
219
+ logger.exception(e)
220
+ continue
221
+ elif msg.empty:
222
+ continue
223
+ else:
224
+ try:
225
+ await msg.copy(message.chat.id, protect_content=True if protect == "/pbatch" else False)
226
+ except FloodWait as e:
227
+ await asyncio.sleep(e.x)
228
+ await msg.copy(message.chat.id, protect_content=True if protect == "/pbatch" else False)
229
+ except Exception as e:
230
+ logger.exception(e)
231
+ continue
232
+ await asyncio.sleep(1)
233
+ return await sts.delete()
234
+
235
+ elif data.split("-", 1)[0] == "verify":
236
+ userid = data.split("-", 2)[1]
237
+ token = data.split("-", 3)[2]
238
+ if str(message.from_user.id) != str(userid):
239
+ return await message.reply_text(
240
+ text="<b>Invalid link or Expired link !</b>",
241
+ protect_content=True
242
+ )
243
+ is_valid = await check_token(client, userid, token)
244
+ if is_valid == True:
245
+ await message.reply_text(
246
+ text=f"<b>Hey {message.from_user.mention}, You are successfully verified !\nNow you have unlimited access for all movies till today midnight.</b>",
247
+ protect_content=True
248
+ )
249
+ await verify_user(client, userid, token)
250
+ else:
251
+ return await message.reply_text(
252
+ text="<b>Invalid link or Expired link !</b>",
253
+ protect_content=True
254
+ )
255
+ if data.startswith("sendfiles"):
256
+ chat_id = int("-" + file_id.split("-")[1])
257
+ userid = message.from_user.id if message.from_user else None
258
+ st = await client.get_chat_member(chat_id, userid)
259
+ if (
260
+ st.status != enums.ChatMemberStatus.ADMINISTRATOR
261
+ and st.status != enums.ChatMemberStatus.OWNER
262
+ ):
263
+ g = await get_shortlink(chat_id, f"https://telegram.me/{temp.U_NAME}?start=allfiles_{file_id}", True)
264
+ else:
265
+ g = await get_shortlink(chat_id, f"https://telegram.me/{temp.U_NAME}?start=allfiles_{file_id}", False)
266
+ k = await client.send_message(chat_id=message.from_user.id,text=f"<b>Get All Files in a Single Click!!!\n\n📂 ʟɪɴᴋ ➠ : {g}\n\n<i>Note: This message is deleted in 5 mins to avoid copyrights. Save the link to Somewhere else</i></b>", reply_markup=InlineKeyboardMarkup(
267
+ [
268
+ [
269
+ InlineKeyboardButton('📂 Dᴏᴡɴʟᴏᴀᴅ Nᴏᴡ 📂', url=g)
270
+ ], [
271
+ InlineKeyboardButton('⁉️ Hᴏᴡ Tᴏ Dᴏᴡɴʟᴏᴀᴅ ⁉️', url=await get_tutorial(chat_id))
272
+ ]
273
+ ]
274
+ )
275
+ )
276
+ await asyncio.sleep(300)
277
+ await k.edit("<b>Your message is successfully deleted!!!</b>")
278
+ return
279
+
280
+
281
+ elif data.startswith("short"):
282
+ user = message.from_user.id
283
+ chat_id = temp.SHORT.get(user)
284
+ files_ = await get_file_details(file_id)
285
+ files = files_[0]
286
+ g = await get_shortlink(chat_id, f"https://telegram.me/{temp.U_NAME}?start=file_{file_id}")
287
+ k = await client.send_message(chat_id=user,text=f"<b>📕Nᴀᴍᴇ ➠ : <code>{files.file_name}</code> \n\n🔗Sɪᴢᴇ ➠ : {get_size(files.file_size)}\n\n📂Fɪʟᴇ ʟɪɴᴋ ➠ : {g}\n\n<i>Note: This message is deleted in 20 mins to avoid copyrights. Save the link to Somewhere else</i></b>", reply_markup=InlineKeyboardMarkup(
288
+ [
289
+ [
290
+ InlineKeyboardButton('📂 Dᴏᴡɴʟᴏᴀᴅ Nᴏᴡ 📂', url=g)
291
+ ], [
292
+ InlineKeyboardButton('⁉️ Hᴏᴡ Tᴏ Dᴏᴡɴʟᴏᴀᴅ ⁉️', url=await get_tutorial(chat_id))
293
+ ]
294
+ ]
295
+ )
296
+ )
297
+ await asyncio.sleep(1200)
298
+ await k.edit("<b>Your message is successfully deleted!!!</b>")
299
+ return
300
+
301
+ elif data.startswith("all"):
302
+ files = temp.GETALL.get(file_id)
303
+ if not files:
304
+ return await message.reply('<b><i>No such file exist.</b></i>')
305
+ filesarr = []
306
+ for file in files:
307
+ file_id = file.file_id
308
+ files_ = await get_file_details(file_id)
309
+ files1 = files_[0]
310
+ title = ' '.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files1.file_name.split()))
311
+ size=get_size(files1.file_size)
312
+ f_caption=files1.caption
313
+ if CUSTOM_FILE_CAPTION:
314
+ try:
315
+ 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)
316
+ except Exception as e:
317
+ logger.exception(e)
318
+ f_caption=f_caption
319
+ if f_caption is None:
320
+ f_caption = f"{' '.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files1.file_name.split()))}"
321
+ if not await check_verification(client, message.from_user.id) and VERIFY == True:
322
+ btn = [[
323
+ InlineKeyboardButton("Verify", url=await get_token(client, message.from_user.id, f"https://telegram.me/{temp.U_NAME}?start="))
324
+ ]]
325
+ await message.reply_text(
326
+ text="<b>You are not verified !\nKindly verify to continue !</b>",
327
+ protect_content=True,
328
+ reply_markup=InlineKeyboardMarkup(btn)
329
+ )
330
+ return
331
+ msg = await client.send_cached_media(
332
+ chat_id=message.from_user.id,
333
+ file_id=file_id,
334
+ caption=f_caption,
335
+ protect_content=True if pre == 'filep' else False,
336
+ reply_markup=InlineKeyboardMarkup(
337
+ [
338
+ [
339
+ InlineKeyboardButton('Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url=f'https://t.me/{SUPPORT_CHAT}'),
340
+ InlineKeyboardButton('Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ', url=CHNL_LNK)
341
+ ],[
342
+ InlineKeyboardButton("Mᴏᴠɪᴇ Rᴇᴏ̨ᴜᴇsᴛ Gʀᴏᴜᴘ", url="t.me/TeamHMT_Movies")
343
+ ]
344
+ ]
345
+ )
346
+ )
347
+ filesarr.append(msg)
348
+ k = await client.send_message(chat_id = message.from_user.id, text=f"<b><u>❗️❗️❗️IMPORTANT❗️️❗️❗️</u></b>\n\nThis Movie Files/Videos will be deleted in <b><u>10 mins</u> 🫥 <i></b>(Due to Copyright Issues)</i>.\n\n<b><i>Please forward this ALL Files/Videos to your Saved Messages and Start Download there</i></b>")
349
+ await asyncio.sleep(600)
350
+ for x in filesarr:
351
+ await x.delete()
352
+ await k.edit_text("<b>Your All Files/Videos is successfully deleted!!!</b>")
353
+ return
354
+
355
+ elif data.startswith("files"):
356
+ user = message.from_user.id
357
+ if temp.SHORT.get(user)==None:
358
+ await message.reply_text(text="<b>Please Search Again in Group</b>")
359
+ else:
360
+ chat_id = temp.SHORT.get(user)
361
+ settings = await get_settings(chat_id)
362
+ if settings['is_shortlink'] and user not in PREMIUM_USER:
363
+ files_ = await get_file_details(file_id)
364
+ files = files_[0]
365
+ g = await get_shortlink(chat_id, f"https://telegram.me/{temp.U_NAME}?start=file_{file_id}")
366
+ k = await client.send_message(chat_id=message.from_user.id,text=f"<b>📕Nᴀᴍᴇ ➠ : <code>{files.file_name}</code> \n\n🔗Sɪᴢᴇ ➠ : {get_size(files.file_size)}\n\n📂Fɪʟᴇ ʟɪɴᴋ ➠ : {g}\n\n<i>Note: This message is deleted in 20 mins to avoid copyrights. Save the link to Somewhere else</i></b>", reply_markup=InlineKeyboardMarkup(
367
+ [
368
+ [
369
+ InlineKeyboardButton('📂 Dᴏᴡɴʟᴏᴀᴅ Nᴏᴡ 📂', url=g)
370
+ ], [
371
+ InlineKeyboardButton('⁉️ Hᴏᴡ Tᴏ Dᴏᴡɴʟᴏᴀᴅ ⁉️', url=await get_tutorial(chat_id))
372
+ ]
373
+ ]
374
+ )
375
+ )
376
+ await asyncio.sleep(1200)
377
+ await k.edit("<b>Your message is successfully deleted!!!</b>")
378
+ return
379
+ user = message.from_user.id
380
+ files_ = await get_file_details(file_id)
381
+ if not files_:
382
+ pre, file_id = ((base64.urlsafe_b64decode(data + "=" * (-len(data) % 4))).decode("ascii")).split("_", 1)
383
+ try:
384
+ if not await check_verification(client, message.from_user.id) and VERIFY == True:
385
+ btn = [[
386
+ InlineKeyboardButton("Verify", url=await get_token(client, message.from_user.id, f"https://telegram.me/{temp.U_NAME}?start="))
387
+ ]]
388
+ await message.reply_text(
389
+ text="<b>You are not verified !\nKindly verify to continue !</b>",
390
+ protect_content=True,
391
+ reply_markup=InlineKeyboardMarkup(btn)
392
+ )
393
+ return
394
+ msg = await client.send_cached_media(
395
+ chat_id=message.from_user.id,
396
+ file_id=file_id,
397
+ protect_content=True if pre == 'filep' else False,
398
+ reply_markup=InlineKeyboardMarkup(
399
+ [
400
+ [
401
+ InlineKeyboardButton('Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url=f'https://t.me/{SUPPORT_CHAT}'),
402
+ InlineKeyboardButton('Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ', url=CHNL_LNK)
403
+ ],[
404
+ InlineKeyboardButton("Mᴏᴠɪᴇ Rᴇᴏ̨ᴜᴇsᴛ Gʀᴏᴜᴘ", url="t.me/TeamHMT_Movies")
405
+ ]
406
+ ]
407
+ )
408
+ )
409
+ filetype = msg.media
410
+ file = getattr(msg, filetype.value)
411
+ title = '@TeamHMT ' + ' '.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), file.file_name.split()))
412
+ size=get_size(file.file_size)
413
+ f_caption = f"<code>{title}</code>"
414
+ if CUSTOM_FILE_CAPTION:
415
+ try:
416
+ f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='')
417
+ except:
418
+ return
419
+ await msg.edit_caption(f_caption)
420
+ btn = [[
421
+ InlineKeyboardButton("Get File Again", callback_data=f'delfile#{file_id}')
422
+ ]]
423
+ k = await msg.reply("<b><u>❗️❗️❗️IMPORTANT❗️️❗️❗️</u></b>\n\nThis Movie File/Video will be deleted in <b><u>10 mins</u> 🫥 <i></b>(Due to Copyright Issues)</i>.\n\n<b><i>Please forward this File/Video to your Saved Messages and Start Download there</i></b>",quote=True)
424
+ await asyncio.sleep(600)
425
+ await msg.delete()
426
+ await k.edit_text("<b>Your File/Video is successfully deleted!!!\n\nClick below button to get your deleted file 👇</b>",reply_markup=InlineKeyboardMarkup(btn))
427
+ return
428
+ except:
429
+ pass
430
+ return await message.reply('No such file exist.')
431
+ files = files_[0]
432
+ title = '@TeamHMT ' + ' '.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files.file_name.split()))
433
+ size=get_size(files.file_size)
434
+ f_caption=files.caption
435
+ if CUSTOM_FILE_CAPTION:
436
+ try:
437
+ 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)
438
+ except Exception as e:
439
+ logger.exception(e)
440
+ f_caption=f_caption
441
+ if f_caption is None:
442
+ f_caption = f"@TeamHMT {' '.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files.file_name.split()))}"
443
+ if not await check_verification(client, message.from_user.id) and VERIFY == True:
444
+ btn = [[
445
+ InlineKeyboardButton("Verify", url=await get_token(client, message.from_user.id, f"https://telegram.me/{temp.U_NAME}?start="))
446
+ ]]
447
+ await message.reply_text(
448
+ text="<b>You are not verified !\nKindly verify to continue !</b>",
449
+ protect_content=True,
450
+ reply_markup=InlineKeyboardMarkup(btn)
451
+ )
452
+ return
453
+ msg = await client.send_cached_media(
454
+ chat_id=message.from_user.id,
455
+ file_id=file_id,
456
+ caption=f_caption,
457
+ protect_content=True if pre == 'filep' else False,
458
+ reply_markup=InlineKeyboardMarkup(
459
+ [
460
+ [
461
+ InlineKeyboardButton('Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url=f'https://t.me/{SUPPORT_CHAT}'),
462
+ InlineKeyboardButton('Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ', url=CHNL_LNK)
463
+ ],[
464
+ InlineKeyboardButton("Mᴏᴠɪᴇ Rᴇᴏ̨ᴜᴇsᴛ Gʀᴏᴜᴘ", url="t.me/TeamHMT_Movies")
465
+ ]
466
+ ]
467
+ )
468
+ )
469
+ btn = [[
470
+ InlineKeyboardButton("Get File Again", callback_data=f'delfile#{file_id}')
471
+ ]]
472
+ k = await msg.reply("<b><u>❗️❗️❗️IMPORTANT❗️️❗️❗️</u></b>\n\nThis Movie File/Video will be deleted in <b><u>10 mins</u> 🫥 <i></b>(Due to Copyright Issues)</i>.\n\n<b><i>Please forward this File/Video to your Saved Messages and Start Download there</i></b>",quote=True)
473
+ await asyncio.sleep(600)
474
+ await msg.delete()
475
+ await k.edit_text("<b>Your File/Video is successfully deleted!!!\n\nClick below button to get your deleted file 👇</b>",reply_markup=InlineKeyboardMarkup(btn))
476
+ return
477
+
478
+ @Client.on_message(filters.command('channel') & filters.user(ADMINS))
479
+ async def channel_info(bot, message):
480
+
481
+ """Send basic information of channel"""
482
+ if isinstance(CHANNELS, (int, str)):
483
+ channels = [CHANNELS]
484
+ elif isinstance(CHANNELS, list):
485
+ channels = CHANNELS
486
+ else:
487
+ raise ValueError("Unexpected type of CHANNELS")
488
+
489
+ text = '📑 **Indexed channels/groups**\n'
490
+ for channel in channels:
491
+ chat = await bot.get_chat(channel)
492
+ if chat.username:
493
+ text += '\n@' + chat.username
494
+ else:
495
+ text += '\n' + chat.title or chat.first_name
496
+
497
+ text += f'\n\n**Total:** {len(CHANNELS)}'
498
+
499
+ if len(text) < 4096:
500
+ await message.reply(text)
501
+ else:
502
+ file = 'Indexed channels.txt'
503
+ with open(file, 'w') as f:
504
+ f.write(text)
505
+ await message.reply_document(file)
506
+ os.remove(file)
507
+
508
+
509
+ @Client.on_message(filters.command('logs') & filters.user(ADMINS))
510
+ async def log_file(bot, message):
511
+ """Send log file"""
512
+ try:
513
+ await message.reply_document('TelegramBot.log')
514
+ except Exception as e:
515
+ await message.reply(str(e))
516
+
517
+ @Client.on_message(filters.command('delete') & filters.user(ADMINS))
518
+ async def delete(bot, message):
519
+ """Delete file from database"""
520
+ reply = message.reply_to_message
521
+ if reply and reply.media:
522
+ msg = await message.reply("Processing...⏳", quote=True)
523
+ else:
524
+ await message.reply('Reply to file with /delete which you want to delete', quote=True)
525
+ return
526
+
527
+ for file_type in ("document", "video", "audio"):
528
+ media = getattr(reply, file_type, None)
529
+ if media is not None:
530
+ break
531
+ else:
532
+ await msg.edit('This is not supported file format')
533
+ return
534
+
535
+ file_id, file_ref = unpack_new_file_id(media.file_id)
536
+
537
+ result = await Media.collection.delete_one({
538
+ '_id': file_id,
539
+ })
540
+ if result.deleted_count:
541
+ await msg.edit('File is successfully deleted from database')
542
+ else:
543
+ file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
544
+ result = await Media.collection.delete_many({
545
+ 'file_name': file_name,
546
+ 'file_size': media.file_size,
547
+ 'mime_type': media.mime_type
548
+ })
549
+ if result.deleted_count:
550
+ await msg.edit('File is successfully deleted from database')
551
+ else:
552
+ # files indexed before https://github.com/EvamariaTG/EvaMaria/commit/f3d2a1bcb155faf44178e5d7a685a1b533e714bf#diff-86b613edf1748372103e94cacff3b578b36b698ef9c16817bb98fe9ef22fb669R39
553
+ # have original file name.
554
+ result = await Media.collection.delete_many({
555
+ 'file_name': media.file_name,
556
+ 'file_size': media.file_size,
557
+ 'mime_type': media.mime_type
558
+ })
559
+ if result.deleted_count:
560
+ await msg.edit('File is successfully deleted from database')
561
+ else:
562
+ await msg.edit('File not found in database')
563
+
564
+
565
+ @Client.on_message(filters.command('deleteall') & filters.user(ADMINS))
566
+ async def delete_all_index(bot, message):
567
+ await message.reply_text(
568
+ 'This will delete all indexed files.\nDo you want to continue??',
569
+ reply_markup=InlineKeyboardMarkup(
570
+ [
571
+ [
572
+ InlineKeyboardButton(
573
+ text="YES", callback_data="autofilter_delete"
574
+ )
575
+ ],
576
+ [
577
+ InlineKeyboardButton(
578
+ text="CANCEL", callback_data="close_data"
579
+ )
580
+ ],
581
+ ]
582
+ ),
583
+ quote=True,
584
+ )
585
+
586
+
587
+ @Client.on_callback_query(filters.regex(r'^autofilter_delete'))
588
+ async def delete_all_index_confirm(bot, message):
589
+ await Media.collection.drop()
590
+ await message.answer('Piracy Is Crime')
591
+ await message.message.edit('Succesfully Deleted All The Indexed Files.')
592
+
593
+
594
+ @Client.on_message(filters.command('settings'))
595
+ async def settings(client, message):
596
+ userid = message.from_user.id if message.from_user else None
597
+ if not userid:
598
+ return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
599
+ chat_type = message.chat.type
600
+
601
+ if chat_type == enums.ChatType.PRIVATE:
602
+ grpid = await active_connection(str(userid))
603
+ if grpid is not None:
604
+ grp_id = grpid
605
+ try:
606
+ chat = await client.get_chat(grpid)
607
+ title = chat.title
608
+ except:
609
+ await message.reply_text("Make sure I'm present in your group!!", quote=True)
610
+ return
611
+ else:
612
+ await message.reply_text("I'm not connected to any groups!", quote=True)
613
+ return
614
+
615
+ elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
616
+ grp_id = message.chat.id
617
+ title = message.chat.title
618
+
619
+ else:
620
+ return
621
+
622
+ st = await client.get_chat_member(grp_id, userid)
623
+ if (
624
+ st.status != enums.ChatMemberStatus.ADMINISTRATOR
625
+ and st.status != enums.ChatMemberStatus.OWNER
626
+ and str(userid) not in ADMINS
627
+ ):
628
+ return
629
+
630
+ settings = await get_settings(grp_id)
631
+
632
+ try:
633
+ if settings['max_btn']:
634
+ settings = await get_settings(grp_id)
635
+ except KeyError:
636
+ await save_group_settings(grp_id, 'max_btn', False)
637
+ settings = await get_settings(grp_id)
638
+ if 'is_shortlink' not in settings.keys():
639
+ await save_group_settings(grp_id, 'is_shortlink', False)
640
+ else:
641
+ pass
642
+
643
+ if settings is not None:
644
+ buttons = [
645
+ [
646
+ InlineKeyboardButton(
647
+ 'Rᴇsᴜʟᴛ Pᴀɢᴇ',
648
+ callback_data=f'setgs#button#{settings["button"]}#{grp_id}',
649
+ ),
650
+ InlineKeyboardButton(
651
+ 'Bᴜᴛᴛᴏɴ' if settings["button"] else 'Tᴇxᴛ',
652
+ callback_data=f'setgs#button#{settings["button"]}#{grp_id}',
653
+ ),
654
+ ],
655
+ [
656
+ InlineKeyboardButton(
657
+ 'Fɪʟᴇ Sᴇɴᴅ Mᴏᴅᴇ',
658
+ callback_data=f'setgs#botpm#{settings["botpm"]}#{grp_id}',
659
+ ),
660
+ InlineKeyboardButton(
661
+ 'Mᴀɴᴜᴀʟ Sᴛᴀʀᴛ' if settings["botpm"] else 'Aᴜᴛᴏ Sᴇɴᴅ',
662
+ callback_data=f'setgs#botpm#{settings["botpm"]}#{grp_id}',
663
+ ),
664
+ ],
665
+ [
666
+ InlineKeyboardButton(
667
+ 'Pʀᴏᴛᴇᴄᴛ Cᴏɴᴛᴇɴᴛ',
668
+ callback_data=f'setgs#file_secure#{settings["file_secure"]}#{grp_id}',
669
+ ),
670
+ InlineKeyboardButton(
671
+ '✔ Oɴ' if settings["file_secure"] else '✘ Oғғ',
672
+ callback_data=f'setgs#file_secure#{settings["file_secure"]}#{grp_id}',
673
+ ),
674
+ ],
675
+ [
676
+ InlineKeyboardButton(
677
+ 'Iᴍᴅʙ',
678
+ callback_data=f'setgs#imdb#{settings["imdb"]}#{grp_id}',
679
+ ),
680
+ InlineKeyboardButton(
681
+ '✔ Oɴ' if settings["imdb"] else '✘ Oғғ',
682
+ callback_data=f'setgs#imdb#{settings["imdb"]}#{grp_id}',
683
+ ),
684
+ ],
685
+ [
686
+ InlineKeyboardButton(
687
+ 'Sᴘᴇʟʟ Cʜᴇᴄᴋ',
688
+ callback_data=f'setgs#spell_check#{settings["spell_check"]}#{grp_id}',
689
+ ),
690
+ InlineKeyboardButton(
691
+ '✔ Oɴ' if settings["spell_check"] else '✘ Oғғ',
692
+ callback_data=f'setgs#spell_check#{settings["spell_check"]}#{grp_id}',
693
+ ),
694
+ ],
695
+ [
696
+ InlineKeyboardButton(
697
+ 'Wᴇʟᴄᴏᴍᴇ Msɢ',
698
+ callback_data=f'setgs#welcome#{settings["welcome"]}#{grp_id}',
699
+ ),
700
+ InlineKeyboardButton(
701
+ '✔ Oɴ' if settings["welcome"] else '✘ Oғғ',
702
+ callback_data=f'setgs#welcome#{settings["welcome"]}#{grp_id}',
703
+ ),
704
+ ],
705
+ [
706
+ InlineKeyboardButton(
707
+ 'Aᴜᴛᴏ-Dᴇʟᴇᴛᴇ',
708
+ callback_data=f'setgs#auto_delete#{settings["auto_delete"]}#{grp_id}',
709
+ ),
710
+ InlineKeyboardButton(
711
+ '10 Mɪɴs' if settings["auto_delete"] else '✘ Oғғ',
712
+ callback_data=f'setgs#auto_delete#{settings["auto_delete"]}#{grp_id}',
713
+ ),
714
+ ],
715
+ [
716
+ InlineKeyboardButton(
717
+ 'Aᴜᴛᴏ-Fɪʟᴛᴇʀ',
718
+ callback_data=f'setgs#auto_ffilter#{settings["auto_ffilter"]}#{grp_id}',
719
+ ),
720
+ InlineKeyboardButton(
721
+ '✔ Oɴ' if settings["auto_ffilter"] else '✘ Oғғ',
722
+ callback_data=f'setgs#auto_ffilter#{settings["auto_ffilter"]}#{grp_id}',
723
+ ),
724
+ ],
725
+ [
726
+ InlineKeyboardButton(
727
+ 'Mᴀx Bᴜᴛᴛᴏɴs',
728
+ callback_data=f'setgs#max_btn#{settings["max_btn"]}#{grp_id}',
729
+ ),
730
+ InlineKeyboardButton(
731
+ '10' if settings["max_btn"] else f'{MAX_B_TN}',
732
+ callback_data=f'setgs#max_btn#{settings["max_btn"]}#{grp_id}',
733
+ ),
734
+ ],
735
+ [
736
+ InlineKeyboardButton(
737
+ 'ShortLink',
738
+ callback_data=f'setgs#is_shortlink#{settings["is_shortlink"]}#{grp_id}',
739
+ ),
740
+ InlineKeyboardButton(
741
+ '✔ Oɴ' if settings["is_shortlink"] else '✘ Oғғ',
742
+ callback_data=f'setgs#is_shortlink#{settings["is_shortlink"]}#{grp_id}',
743
+ ),
744
+ ],
745
+ ]
746
+
747
+ btn = [[
748
+ InlineKeyboardButton("Oᴘᴇɴ Hᴇʀᴇ ↓", callback_data=f"opnsetgrp#{grp_id}"),
749
+ InlineKeyboardButton("Oᴘᴇɴ Iɴ PM ⇲", callback_data=f"opnsetpm#{grp_id}")
750
+ ]]
751
+
752
+ reply_markup = InlineKeyboardMarkup(buttons)
753
+ if chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
754
+ await message.reply_text(
755
+ text="<b>Dᴏ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ᴏᴘᴇɴ sᴇᴛᴛɪɴɢs ʜᴇʀᴇ ?</b>",
756
+ reply_markup=InlineKeyboardMarkup(btn),
757
+ disable_web_page_preview=True,
758
+ parse_mode=enums.ParseMode.HTML,
759
+ reply_to_message_id=message.id
760
+ )
761
+ else:
762
+ await message.reply_text(
763
+ text=f"<b>Cʜᴀɴɢᴇ Yᴏᴜʀ Sᴇᴛᴛɪɴɢs Fᴏʀ {title} As Yᴏᴜʀ Wɪsʜ ⚙</b>",
764
+ reply_markup=reply_markup,
765
+ disable_web_page_preview=True,
766
+ parse_mode=enums.ParseMode.HTML,
767
+ reply_to_message_id=message.id
768
+ )
769
+
770
+
771
+
772
+ @Client.on_message(filters.command('set_template'))
773
+ async def save_template(client, message):
774
+ sts = await message.reply("Checking template")
775
+ userid = message.from_user.id if message.from_user else None
776
+ if not userid:
777
+ return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
778
+ chat_type = message.chat.type
779
+
780
+ if chat_type == enums.ChatType.PRIVATE:
781
+ grpid = await active_connection(str(userid))
782
+ if grpid is not None:
783
+ grp_id = grpid
784
+ try:
785
+ chat = await client.get_chat(grpid)
786
+ title = chat.title
787
+ except:
788
+ await message.reply_text("Make sure I'm present in your group!!", quote=True)
789
+ return
790
+ else:
791
+ await message.reply_text("I'm not connected to any groups!", quote=True)
792
+ return
793
+
794
+ elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
795
+ grp_id = message.chat.id
796
+ title = message.chat.title
797
+
798
+ else:
799
+ return
800
+
801
+ st = await client.get_chat_member(grp_id, userid)
802
+ if (
803
+ st.status != enums.ChatMemberStatus.ADMINISTRATOR
804
+ and st.status != enums.ChatMemberStatus.OWNER
805
+ and str(userid) not in ADMINS
806
+ ):
807
+ return
808
+
809
+ if len(message.command) < 2:
810
+ return await sts.edit("No Input!!")
811
+ template = message.text.split(" ", 1)[1]
812
+ await save_group_settings(grp_id, 'template', template)
813
+ await sts.edit(f"Successfully changed template for {title} to\n\n{template}")
814
+
815
+
816
+ @Client.on_message((filters.command(["request", "Request"]) | filters.regex("#request") | filters.regex("#Request")) & filters.group)
817
+ async def requests(bot, message):
818
+ if REQST_CHANNEL is None or SUPPORT_CHAT_ID is None: return # Must add REQST_CHANNEL and SUPPORT_CHAT_ID to use this feature
819
+ if message.reply_to_message and SUPPORT_CHAT_ID == message.chat.id:
820
+ chat_id = message.chat.id
821
+ reporter = str(message.from_user.id)
822
+ mention = message.from_user.mention
823
+ success = True
824
+ content = message.reply_to_message.text
825
+ try:
826
+ if REQST_CHANNEL is not None:
827
+ btn = [[
828
+ InlineKeyboardButton('View Request', url=f"{message.reply_to_message.link}"),
829
+ InlineKeyboardButton('Show Options', callback_data=f'show_option#{reporter}')
830
+ ]]
831
+ reported_post = await bot.send_message(chat_id=REQST_CHANNEL, text=f"<b>𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}</b>", reply_markup=InlineKeyboardMarkup(btn))
832
+ success = True
833
+ elif len(content) >= 3:
834
+ for admin in ADMINS:
835
+ btn = [[
836
+ InlineKeyboardButton('View Request', url=f"{message.reply_to_message.link}"),
837
+ InlineKeyboardButton('Show Options', callback_data=f'show_option#{reporter}')
838
+ ]]
839
+ reported_post = await bot.send_message(chat_id=admin, text=f"<b>𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}</b>", reply_markup=InlineKeyboardMarkup(btn))
840
+ success = True
841
+ else:
842
+ if len(content) < 3:
843
+ await message.reply_text("<b>You must type about your request [Minimum 3 Characters]. Requests can't be empty.</b>")
844
+ if len(content) < 3:
845
+ success = False
846
+ except Exception as e:
847
+ await message.reply_text(f"Error: {e}")
848
+ pass
849
+
850
+ elif SUPPORT_CHAT_ID == message.chat.id:
851
+ chat_id = message.chat.id
852
+ reporter = str(message.from_user.id)
853
+ mention = message.from_user.mention
854
+ success = True
855
+ content = message.text
856
+ keywords = ["#request", "/request", "#Request", "/Request"]
857
+ for keyword in keywords:
858
+ if keyword in content:
859
+ content = content.replace(keyword, "")
860
+ try:
861
+ if REQST_CHANNEL is not None and len(content) >= 3:
862
+ btn = [[
863
+ InlineKeyboardButton('View Request', url=f"{message.link}"),
864
+ InlineKeyboardButton('Show Options', callback_data=f'show_option#{reporter}')
865
+ ]]
866
+ reported_post = await bot.send_message(chat_id=REQST_CHANNEL, text=f"<b>𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}</b>", reply_markup=InlineKeyboardMarkup(btn))
867
+ success = True
868
+ elif len(content) >= 3:
869
+ for admin in ADMINS:
870
+ btn = [[
871
+ InlineKeyboardButton('View Request', url=f"{message.link}"),
872
+ InlineKeyboardButton('Show Options', callback_data=f'show_option#{reporter}')
873
+ ]]
874
+ reported_post = await bot.send_message(chat_id=admin, text=f"<b>𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}</b>", reply_markup=InlineKeyboardMarkup(btn))
875
+ success = True
876
+ else:
877
+ if len(content) < 3:
878
+ await message.reply_text("<b>You must type about your request [Minimum 3 Characters]. Requests can't be empty.</b>")
879
+ if len(content) < 3:
880
+ success = False
881
+ except Exception as e:
882
+ await message.reply_text(f"Error: {e}")
883
+ pass
884
+
885
+ else:
886
+ success = False
887
+
888
+ if success:
889
+ '''if isinstance(REQST_CHANNEL, (int, str)):
890
+ channels = [REQST_CHANNEL]
891
+ elif isinstance(REQST_CHANNEL, list):
892
+ channels = REQST_CHANNEL
893
+ for channel in channels:
894
+ chat = await bot.get_chat(channel)
895
+ #chat = int(chat)'''
896
+ link = await bot.create_chat_invite_link(int(REQST_CHANNEL))
897
+ btn = [[
898
+ InlineKeyboardButton('Join Channel', url=link.invite_link),
899
+ InlineKeyboardButton('View Request', url=f"{reported_post.link}")
900
+ ]]
901
+ await message.reply_text("<b>Your request has been added! Please wait for some time.\n\nJoin Channel First & View Request</b>", reply_markup=InlineKeyboardMarkup(btn))
902
+
903
+ @Client.on_message(filters.command("send") & filters.user(ADMINS))
904
+ async def send_msg(bot, message):
905
+ if message.reply_to_message:
906
+ target_id = message.text.split(" ", 1)[1]
907
+ out = "Users Saved In DB Are:\n\n"
908
+ success = False
909
+ try:
910
+ user = await bot.get_users(target_id)
911
+ users = await db.get_all_users()
912
+ async for usr in users:
913
+ out += f"{usr['id']}"
914
+ out += '\n'
915
+ if str(user.id) in str(out):
916
+ await message.reply_to_message.copy(int(user.id))
917
+ success = True
918
+ else:
919
+ success = False
920
+ if success:
921
+ await message.reply_text(f"<b>Your message has been successfully send to {user.mention}.</b>")
922
+ else:
923
+ await message.reply_text("<b>This user didn't started this bot yet !</b>")
924
+ except Exception as e:
925
+ await message.reply_text(f"<b>Error: {e}</b>")
926
+ else:
927
+ await message.reply_text("<b>Use this command as a reply to any message using the target chat id. For eg: /send userid</b>")
928
+
929
+ @Client.on_message(filters.command("deletefiles") & filters.user(ADMINS))
930
+ async def deletemultiplefiles(bot, message):
931
+ chat_type = message.chat.type
932
+ if chat_type != enums.ChatType.PRIVATE:
933
+ return await message.reply_text(f"<b>Hey {message.from_user.mention}, This command won't work in groups. It only works on my PM !</b>")
934
+ else:
935
+ pass
936
+ try:
937
+ keyword = message.text.split(" ", 1)[1]
938
+ except:
939
+ return await message.reply_text(f"<b>Hey {message.from_user.mention}, Give me a keyword along with the command to delete files.</b>")
940
+ k = await bot.send_message(chat_id=message.chat.id, text=f"<b>Fetching Files for your query {keyword} on DB... Please wait...</b>")
941
+ files, total = await get_bad_files(keyword)
942
+ await k.delete()
943
+ #await k.edit_text(f"<b>Found {total} files for your query {keyword} !\n\nFile deletion process will start in 5 seconds !</b>")
944
+ #await asyncio.sleep(5)
945
+ btn = [[
946
+ InlineKeyboardButton("Yes, Continue !", callback_data=f"killfilesdq#{keyword}")
947
+ ],[
948
+ InlineKeyboardButton("No, Abort operation !", callback_data="close_data")
949
+ ]]
950
+ await message.reply_text(
951
+ text=f"<b>Found {total} files for your query {keyword} !\n\nDo you want to delete?</b>",
952
+ reply_markup=InlineKeyboardMarkup(btn),
953
+ parse_mode=enums.ParseMode.HTML
954
+ )
955
+
956
+ @Client.on_message(filters.command("shortlink"))
957
+ async def shortlink(bot, message):
958
+ userid = message.from_user.id if message.from_user else None
959
+ if not userid:
960
+ return await message.reply(f"You are anonymous admin. Turn off anonymous admin and try again this command")
961
+ chat_type = message.chat.type
962
+ if chat_type == enums.ChatType.PRIVATE:
963
+ return await message.reply_text(f"<b>Hey {message.from_user.mention}, This command only works on groups !\n\n<u>Follow These Steps to Connect Shortener:</u>\n\n1. Add Me in Your Group with Full Admin Rights\n\n2. After Adding in Grp, Set your Shortener\n\nSend this command in your group\n\n—> /shortlink ""{your_shortener_website_name} {your_shortener_api}\n\n#Sample:-\n/shortlink mplaylink.com 1f1da5c9df9a58058672ac8d8134e203b03426a1\n\nThat's it!!! Enjoy Earning Money 💲\n\n[[[ Trusted Earning Site - https://bit.ly/mplaylink ]]]\n\nIf you have any Doubts, Feel Free to Ask me - @TeamHMT_Bot\n\n(Puriyala na intha bot la message pannunga - @TeamHMT_bot)</b>")
964
+ elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
965
+ grpid = message.chat.id
966
+ title = message.chat.title
967
+ else:
968
+ return
969
+ data = message.text
970
+ userid = message.from_user.id
971
+ user = await bot.get_chat_member(grpid, userid)
972
+ if user.status != enums.ChatMemberStatus.ADMINISTRATOR and user.status != enums.ChatMemberStatus.OWNER and str(userid) not in ADMINS:
973
+ return await message.reply_text("<b>You don't have access to use this command!\n\nAdd Me to Your Own Group as Admin and Try This Command\n\nFor More PM Me With This Command</b>")
974
+ else:
975
+ pass
976
+ try:
977
+ command, shortlink_url, api = data.split(" ")
978
+ except:
979
+ return await message.reply_text("<b>Command Incomplete :(\n\nGive me a shortener website link and api along with the command !\n\nFormat: <code>/shortlink mplaylink.com 1f1da5c9df9a58058672ac8d8134e203b03426a1</code></b>")
980
+ reply = await message.reply_text("<b>Please Wait...</b>")
981
+ shortlink_url = re.sub(r"https?://?", "", shortlink_url)
982
+ shortlink_url = re.sub(r"[:/]", "", shortlink_url)
983
+ await save_group_settings(grpid, 'shortlink', shortlink_url)
984
+ await save_group_settings(grpid, 'shortlink_api', api)
985
+ await save_group_settings(grpid, 'is_shortlink', True)
986
+ await reply.edit_text(f"<b>Successfully added shortlink API for {title}.\n\nCurrent Shortlink Website: <code>{shortlink_url}</code>\nCurrent API: <code>{api}</code></b>")
987
+
988
+ @Client.on_message(filters.command("setshortlinkoff") & filters.user(ADMINS))
989
+ async def offshortlink(bot, message):
990
+ chat_type = message.chat.type
991
+ if chat_type == enums.ChatType.PRIVATE:
992
+ return await message.reply_text("I will Work Only in group")
993
+ elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
994
+ grpid = message.chat.id
995
+ title = message.chat.title
996
+ else:
997
+ return
998
+ await save_group_settings(grpid, 'is_shortlink', False)
999
+ # ENABLE_SHORTLINK = False
1000
+ return await message.reply_text("Successfully disabled shortlink")
1001
+
1002
+ @Client.on_message(filters.command("setshortlinkon") & filters.user(ADMINS))
1003
+ async def onshortlink(bot, message):
1004
+ chat_type = message.chat.type
1005
+ if chat_type == enums.ChatType.PRIVATE:
1006
+ return await message.reply_text("I will Work Only in group")
1007
+ elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
1008
+ grpid = message.chat.id
1009
+ title = message.chat.title
1010
+ else:
1011
+ return
1012
+ await save_group_settings(grpid, 'is_shortlink', True)
1013
+ # ENABLE_SHORTLINK = True
1014
+ return await message.reply_text("Successfully enabled shortlink")
1015
+
1016
+ @Client.on_message(filters.command("shortlink_info"))
1017
+ async def showshortlink(bot, message):
1018
+ userid = message.from_user.id if message.from_user else None
1019
+ if not userid:
1020
+ return await message.reply(f"You are anonymous admin. Turn off anonymous admin and try again this command")
1021
+ chat_type = message.chat.type
1022
+ if chat_type == enums.ChatType.PRIVATE:
1023
+ return await message.reply_text(f"<b>Hey {message.from_user.mention}, This Command Only Works in Group\n\nTry this command in your own group, if you are using me in your group</b>")
1024
+ elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
1025
+ grpid = message.chat.id
1026
+ title = message.chat.title
1027
+ else:
1028
+ return
1029
+ chat_id=message.chat.id
1030
+ userid = message.from_user.id
1031
+ user = await bot.get_chat_member(grpid, userid)
1032
+ # if 'shortlink' in settings.keys():
1033
+ # su = settings['shortlink']
1034
+ # sa = settings['shortlink_api']
1035
+ # else:
1036
+ # return await message.reply_text("<b>Shortener Url Not Connected\n\nYou can Connect Using /shortlink command</b>")
1037
+ # if 'tutorial' in settings.keys():
1038
+ # st = settings['tutorial']
1039
+ # else:
1040
+ # return await message.reply_text("<b>Tutorial Link Not Connected\n\nYou can Connect Using /set_tutorial command</b>")
1041
+ if user.status != enums.ChatMemberStatus.ADMINISTRATOR and user.status != enums.ChatMemberStatus.OWNER and str(userid) not in ADMINS:
1042
+ return await message.reply_text("<b>Tʜɪs ᴄᴏᴍᴍᴀɴᴅ Wᴏʀᴋs Oɴʟʏ Fᴏʀ ᴛʜɪs Gʀᴏᴜᴘ Oᴡɴᴇʀ/Aᴅᴍɪɴ\n\nTʀʏ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ɪɴ ʏᴏᴜʀ Oᴡɴ Gʀᴏᴜᴘ, Iғ Yᴏᴜ Aʀᴇ Usɪɴɢ Mᴇ Iɴ Yᴏᴜʀ Gʀᴏᴜᴘ</b>")
1043
+ else:
1044
+ settings = await get_settings(chat_id) #fetching settings for group
1045
+ if 'shortlink' in settings.keys() and 'tutorial' in settings.keys():
1046
+ su = settings['shortlink']
1047
+ sa = settings['shortlink_api']
1048
+ st = settings['tutorial']
1049
+ return await message.reply_text(f"<b>Shortlink Website: <code>{su}</code>\n\nApi: <code>{sa}</code>\n\nTutorial: <code>{st}</code></b>")
1050
+ elif 'shortlink' in settings.keys() and 'tutorial' not in settings.keys():
1051
+ su = settings['shortlink']
1052
+ sa = settings['shortlink_api']
1053
+ return await message.reply_text(f"<b>Shortener Website: <code>{su}</code>\n\nApi: <code>{sa}</code>\n\nTutorial Link Not Connected\n\nYou can Connect Using /set_tutorial command</b>")
1054
+ elif 'shortlink' not in settings.keys() and 'tutorial' in settings.keys():
1055
+ st = settings['tutorial']
1056
+ return await message.reply_text(f"<b>Tutorial: <code>{st}</code>\n\nShortener Url Not Connected\n\nYou can Connect Using /shortlink command</b>")
1057
+ else:
1058
+ return await message.reply_text("Shortener url and Tutorial Link Not Connected. Check this commands, /shortlink and /set_tutorial")
1059
+
1060
+
1061
+ @Client.on_message(filters.command("set_tutorial"))
1062
+ async def settutorial(bot, message):
1063
+ userid = message.from_user.id if message.from_user else None
1064
+ if not userid:
1065
+ return await message.reply(f"You are anonymous admin. Turn off anonymous admin and try again this command")
1066
+ chat_type = message.chat.type
1067
+ if chat_type == enums.ChatType.PRIVATE:
1068
+ return await message.reply_text("This Command Work Only in group\n\nTry it in your own group")
1069
+ elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
1070
+ grpid = message.chat.id
1071
+ title = message.chat.title
1072
+ else:
1073
+ return
1074
+ userid = message.from_user.id
1075
+ user = await bot.get_chat_member(grpid, userid)
1076
+ if user.status != enums.ChatMemberStatus.ADMINISTRATOR and user.status != enums.ChatMemberStatus.OWNER and str(userid) not in ADMINS:
1077
+ return
1078
+ else:
1079
+ pass
1080
+ if len(message.command) == 1:
1081
+ return await message.reply("<b>Give me a tutorial link along with this command\n\nCommand Usage: /set_tutorial your tutorial link</b>")
1082
+ elif len(message.command) == 2:
1083
+ reply = await message.reply_text("<b>Please Wait...</b>")
1084
+ tutorial = message.command[1]
1085
+ await save_group_settings(grpid, 'tutorial', tutorial)
1086
+ await save_group_settings(grpid, 'is_tutorial', True)
1087
+ await reply.edit_text(f"<b>Successfully Added Tutorial\n\nHere is your tutorial link for your group {title} - <code>{tutorial}</code></b>")
1088
+ else:
1089
+ return await message.reply("<b>You entered Incorrect Format\n\nFormat: /set_tutorial your tutorial link</b>")
1090
+
1091
+ @Client.on_message(filters.command("restart") & filters.user(ADMINS))
1092
+ async def stop_button(bot, message):
1093
+ msg = await bot.send_message(text="**🔄 𝙿𝚁𝙾𝙲𝙴𝚂𝚂𝙴𝚂 𝚂𝚃𝙾𝙿𝙴𝙳. 𝙱𝙾𝚃 𝙸𝚂 𝚁𝙴𝚂𝚃𝙰𝚁𝚃𝙸𝙽𝙶...**", chat_id=message.chat.id)
1094
+ await asyncio.sleep(3)
1095
+ await msg.edit("**✅️ 𝙱𝙾𝚃 𝙸𝚂 𝚁𝙴𝚂𝚃𝙰𝚁𝚃𝙴𝙳. 𝙽𝙾𝚆 𝚈𝙾𝚄 𝙲𝙰𝙽 𝚄𝚂𝙴 𝙼𝙴**")
1096
+ os.execl(sys.executable, sys.executable, *sys.argv)
plugins/connection.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ "<b>Enter in correct format!</b>\n\n"
24
+ "<code>/connect groupid</code>\n\n"
25
+ "<i>Get your Group id by adding this bot to your group and use <code>/id</code></i>",
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"Successfully connected to **{title}**\nNow manage your group from my pm !",
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
+ "Your connected group details ;\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
+ )
plugins/files_delete.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import logging
3
+ from pyrogram import Client, filters
4
+ from info import DELETE_CHANNELS
5
+ from database.ia_filterdb import Media, unpack_new_file_id
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ media_filter = filters.document | filters.video | filters.audio
10
+
11
+
12
+ @Client.on_message(filters.chat(DELETE_CHANNELS) & media_filter)
13
+ async def deletemultiplemedia(bot, message):
14
+ """Delete Multiple files from database"""
15
+
16
+ for file_type in ("document", "video", "audio"):
17
+ media = getattr(message, file_type, None)
18
+ if media is not None:
19
+ break
20
+ else:
21
+ return
22
+
23
+ file_id, file_ref = unpack_new_file_id(media.file_id)
24
+
25
+ result = await Media.collection.delete_one({
26
+ '_id': file_id,
27
+ })
28
+ if result.deleted_count:
29
+ logger.info('File is successfully deleted from database.')
30
+ else:
31
+ file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
32
+ result = await Media.collection.delete_many({
33
+ 'file_name': file_name,
34
+ 'file_size': media.file_size,
35
+ 'mime_type': media.mime_type
36
+ })
37
+ if result.deleted_count:
38
+ logger.info('File is successfully deleted from database.')
39
+ else:
40
+ result = await Media.collection.delete_many({
41
+ 'file_name': media.file_name,
42
+ 'file_size': media.file_size,
43
+ 'mime_type': media.mime_type
44
+ })
45
+ if result.deleted_count:
46
+ logger.info('File is successfully deleted from database.')
47
+ else:
48
+ logger.info('File not found in database.')
plugins/filters.py ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ userid = message.from_user.id
128
+ grpid = await active_connection(str(userid))
129
+ if grpid is not None:
130
+ grp_id = grpid
131
+ try:
132
+ chat = await client.get_chat(grpid)
133
+ title = chat.title
134
+ except:
135
+ await message.reply_text("Make sure I'm present in your group!!", quote=True)
136
+ return
137
+ else:
138
+ await message.reply_text("I'm not connected to any groups!", quote=True)
139
+ return
140
+
141
+ elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
142
+ grp_id = message.chat.id
143
+ title = message.chat.title
144
+
145
+ else:
146
+ return
147
+
148
+ st = await client.get_chat_member(grp_id, userid)
149
+ if (
150
+ st.status != enums.ChatMemberStatus.ADMINISTRATOR
151
+ and st.status != enums.ChatMemberStatus.OWNER
152
+ and str(userid) not in ADMINS
153
+ ):
154
+ return
155
+
156
+ texts = await get_filters(grp_id)
157
+ count = await count_filters(grp_id)
158
+ if count:
159
+ filterlist = f"Total number of filters in **{title}** : {count}\n\n"
160
+
161
+ for text in texts:
162
+ keywords = " × `{}`\n".format(text)
163
+
164
+ filterlist += keywords
165
+
166
+ if len(filterlist) > 4096:
167
+ with io.BytesIO(str.encode(filterlist.replace("`", ""))) as keyword_file:
168
+ keyword_file.name = "keywords.txt"
169
+ await message.reply_document(
170
+ document=keyword_file,
171
+ quote=True
172
+ )
173
+ return
174
+ else:
175
+ filterlist = f"There are no active filters in **{title}**"
176
+
177
+ await message.reply_text(
178
+ text=filterlist,
179
+ quote=True,
180
+ parse_mode=enums.ParseMode.MARKDOWN
181
+ )
182
+
183
+ @Client.on_message(filters.command('del') & filters.incoming)
184
+ async def deletefilter(client, message):
185
+ userid = message.from_user.id if message.from_user else None
186
+ if not userid:
187
+ return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
188
+ chat_type = message.chat.type
189
+
190
+ if chat_type == enums.ChatType.PRIVATE:
191
+ grpid = await active_connection(str(userid))
192
+ if grpid is not None:
193
+ grp_id = grpid
194
+ try:
195
+ chat = await client.get_chat(grpid)
196
+ title = chat.title
197
+ except:
198
+ await message.reply_text("Make sure I'm present in your group!!", quote=True)
199
+ return
200
+ else:
201
+ await message.reply_text("I'm not connected to any groups!", quote=True)
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
+ "<i>Mention the filtername which you wanna delete!</i>\n\n"
223
+ "<code>/del filtername</code>\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
+ st = await client.get_chat_member(grp_id, userid)
263
+ if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS):
264
+ await message.reply_text(
265
+ f"This will delete all filters from '{title}'.\nDo you want to continue??",
266
+ reply_markup=InlineKeyboardMarkup([
267
+ [InlineKeyboardButton(text="YES",callback_data="delallconfirm")],
268
+ [InlineKeyboardButton(text="CANCEL",callback_data="delallcancel")]
269
+ ]),
270
+ quote=True
271
+ )
272
+