commit
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- Dockerfile +12 -0
- LICENSE +339 -0
- Procfile +1 -0
- Script.py +247 -0
- app.json +81 -0
- bot.py +106 -0
- database/__pycache__/connections_mdb.cpython-310.pyc +0 -0
- database/__pycache__/filters_mdb.cpython-310.pyc +0 -0
- database/__pycache__/gfilters_mdb.cpython-310.pyc +0 -0
- database/__pycache__/ia_filterdb.cpython-310.pyc +0 -0
- database/__pycache__/users_chats_db.cpython-310.pyc +0 -0
- database/connections_mdb.py +133 -0
- database/filters_mdb.py +115 -0
- database/gfilters_mdb.py +113 -0
- database/ia_filterdb.py +205 -0
- database/users_chats_db.py +154 -0
- docker-compose.yml +14 -0
- heroku.yml +3 -0
- info.py +97 -0
- logging.conf +32 -0
- plugins/Restart.py +12 -0
- plugins/__init__.py +8 -0
- plugins/__pycache__/Restart.cpython-310.pyc +0 -0
- plugins/__pycache__/__init__.cpython-310.pyc +0 -0
- plugins/__pycache__/banned.cpython-310.pyc +0 -0
- plugins/__pycache__/broadcast.cpython-310.pyc +0 -0
- plugins/__pycache__/channel.cpython-310.pyc +0 -0
- plugins/__pycache__/clone.cpython-310.pyc +0 -0
- plugins/__pycache__/commands.cpython-310.pyc +0 -0
- plugins/__pycache__/connection.cpython-310.pyc +0 -0
- plugins/__pycache__/files_delete.cpython-310.pyc +0 -0
- plugins/__pycache__/filters.cpython-310.pyc +0 -0
- plugins/__pycache__/genlink.cpython-310.pyc +0 -0
- plugins/__pycache__/gfilters.cpython-310.pyc +0 -0
- plugins/__pycache__/index.cpython-310.pyc +0 -0
- plugins/__pycache__/inline.cpython-310.pyc +0 -0
- plugins/__pycache__/misc.cpython-310.pyc +0 -0
- plugins/__pycache__/p_ttishow.cpython-310.pyc +0 -0
- plugins/__pycache__/pm_filter.cpython-310.pyc +0 -0
- plugins/__pycache__/pm_filter1.cpython-310.pyc +0 -0
- plugins/__pycache__/route.cpython-310.pyc +0 -0
- plugins/__pycache__/sample.cpython-310.pyc +0 -0
- plugins/banned.py +40 -0
- plugins/broadcast.py +68 -0
- plugins/channel.py +20 -0
- plugins/clone.py +38 -0
- plugins/commands.py +1096 -0
- plugins/connection.py +147 -0
- plugins/files_delete.py +48 -0
- 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 |
+
|