taslim19 commited on
Commit
de1ee14
·
1 Parent(s): 0ed0019

uploading: by drag

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assest/about.jpg filter=lfs diff=lfs merge=lfs -text
.github/workflows/pylint.yml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: pyLint
2
+ on: push
3
+ jobs:
4
+ PEP8:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@v2
8
+ - name: Setup Python
9
+ uses: actions/setup-python@v1
10
+ with:
11
+ python-version: 3.10.x
12
+ - name: Install Python lint libraries
13
+ run: |
14
+ pip install autopep8 autoflake isort black
15
+ - name: Check for showstoppers
16
+ run: autopep8 --verbose --in-place --recursive --aggressive --aggressive .
17
+ - name: Remove unused imports and variables
18
+ run: autoflake --in-place --recursive --remove-all-unused-imports --remove-unused-variables --ignore-init-module-imports .
19
+ - name: lint with isort and black
20
+ run: |
21
+ isort .
22
+ black --fast .
23
+ # commit changes
24
+ - uses: stefanzweifel/git-auto-commit-action@v4
25
+ with:
26
+ commit_message: 'pyLint: auto-fixes'
27
+ commit_options: '--no-verify'
28
+ repository: .
29
+ commit_user_name: kaif-00z
30
+ commit_user_email: 88398455+kaif-00z@users.noreply.github.com
31
+ commit_author: kaif-00z <88398455+kaif-00z@users.noreply.github.com>
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .env
2
+ __pycache__/
3
+ test.py
.sample.env ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Mandatory Environment Variable
2
+
3
+ BOT_TOKEN=
4
+ MAIN_CHANNEL=-1001111
5
+ LOG_CHANNEL=-1001111
6
+ CLOUD_CHANNEL=-1001111
7
+ MONGO_SRV=
8
+ OWNER=1872074304
9
+ BACKUP_CHANNEL=-1001111
10
+
11
+ # Optional Environment Variable
12
+
13
+ API_ID=
14
+ API_HASH=
15
+ FORCESUB_CHANNEL_LINK=
16
+ FORCESUB_CHANNEL=
17
+ SESSION=
18
+ SEND_SCHEDULE=
19
+ THUMBNAIL=
20
+ CRF=
Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10.4-slim-buster
2
+
3
+ WORKDIR /usr/src/app
4
+ RUN chmod 777 /usr/src/app
5
+
6
+ RUN apt-get -qq update && apt-get -qq install -y git wget pv jq python3-dev mediainfo gcc aria2 libsm6 libxext6 libfontconfig1 libxrender1 libgl1-mesa-glx ffmpeg
7
+
8
+ COPY . .
9
+ RUN pip3 install --no-cache-dir -r requirements.txt
10
+
11
+ CMD ["bash","run.sh"]
LICENSE ADDED
@@ -0,0 +1,674 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ To protect your rights, we need to prevent others from denying you
30
+ these rights or asking you to surrender the rights. Therefore, you have
31
+ certain responsibilities if you distribute copies of the software, or if
32
+ you modify it: responsibilities to respect the freedom of others.
33
+
34
+ For example, if you distribute copies of such a program, whether
35
+ gratis or for a fee, you must pass on to the recipients the same
36
+ freedoms that you received. You must make sure that they, too, receive
37
+ or can get the source code. And you must show them these terms so they
38
+ know their rights.
39
+
40
+ Developers that use the GNU GPL protect your rights with two steps:
41
+ (1) assert copyright on the software, and (2) offer you this License
42
+ giving you legal permission to copy, distribute and/or modify it.
43
+
44
+ For the developers' and authors' protection, the GPL clearly explains
45
+ that there is no warranty for this free software. For both users' and
46
+ authors' sake, the GPL requires that modified versions be marked as
47
+ changed, so that their problems will not be attributed erroneously to
48
+ authors of previous versions.
49
+
50
+ Some devices are designed to deny users access to install or run
51
+ modified versions of the software inside them, although the manufacturer
52
+ can do so. This is fundamentally incompatible with the aim of
53
+ protecting users' freedom to change the software. The systematic
54
+ pattern of such abuse occurs in the area of products for individuals to
55
+ use, which is precisely where it is most unacceptable. Therefore, we
56
+ have designed this version of the GPL to prohibit the practice for those
57
+ products. If such problems arise substantially in other domains, we
58
+ stand ready to extend this provision to those domains in future versions
59
+ of the GPL, as needed to protect the freedom of users.
60
+
61
+ Finally, every program is threatened constantly by software patents.
62
+ States should not allow patents to restrict development and use of
63
+ software on general-purpose computers, but in those that do, we wish to
64
+ avoid the special danger that patents applied to a free program could
65
+ make it effectively proprietary. To prevent this, the GPL assures that
66
+ patents cannot be used to render the program non-free.
67
+
68
+ The precise terms and conditions for copying, distribution and
69
+ modification follow.
70
+
71
+ TERMS AND CONDITIONS
72
+
73
+ 0. Definitions.
74
+
75
+ "This License" refers to version 3 of the GNU General Public License.
76
+
77
+ "Copyright" also means copyright-like laws that apply to other kinds of
78
+ works, such as semiconductor masks.
79
+
80
+ "The Program" refers to any copyrightable work licensed under this
81
+ License. Each licensee is addressed as "you". "Licensees" and
82
+ "recipients" may be individuals or organizations.
83
+
84
+ To "modify" a work means to copy from or adapt all or part of the work
85
+ in a fashion requiring copyright permission, other than the making of an
86
+ exact copy. The resulting work is called a "modified version" of the
87
+ earlier work or a work "based on" the earlier work.
88
+
89
+ A "covered work" means either the unmodified Program or a work based
90
+ on the Program.
91
+
92
+ To "propagate" a work means to do anything with it that, without
93
+ permission, would make you directly or secondarily liable for
94
+ infringement under applicable copyright law, except executing it on a
95
+ computer or modifying a private copy. Propagation includes copying,
96
+ distribution (with or without modification), making available to the
97
+ public, and in some countries other activities as well.
98
+
99
+ To "convey" a work means any kind of propagation that enables other
100
+ parties to make or receive copies. Mere interaction with a user through
101
+ a computer network, with no transfer of a copy, is not conveying.
102
+
103
+ An interactive user interface displays "Appropriate Legal Notices"
104
+ to the extent that it includes a convenient and prominently visible
105
+ feature that (1) displays an appropriate copyright notice, and (2)
106
+ tells the user that there is no warranty for the work (except to the
107
+ extent that warranties are provided), that licensees may convey the
108
+ work under this License, and how to view a copy of this License. If
109
+ the interface presents a list of user commands or options, such as a
110
+ menu, a prominent item in the list meets this criterion.
111
+
112
+ 1. Source Code.
113
+
114
+ The "source code" for a work means the preferred form of the work
115
+ for making modifications to it. "Object code" means any non-source
116
+ form of a work.
117
+
118
+ A "Standard Interface" means an interface that either is an official
119
+ standard defined by a recognized standards body, or, in the case of
120
+ interfaces specified for a particular programming language, one that
121
+ is widely used among developers working in that language.
122
+
123
+ The "System Libraries" of an executable work include anything, other
124
+ than the work as a whole, that (a) is included in the normal form of
125
+ packaging a Major Component, but which is not part of that Major
126
+ Component, and (b) serves only to enable use of the work with that
127
+ Major Component, or to implement a Standard Interface for which an
128
+ implementation is available to the public in source code form. A
129
+ "Major Component", in this context, means a major essential component
130
+ (kernel, window system, and so on) of the specific operating system
131
+ (if any) on which the executable work runs, or a compiler used to
132
+ produce the work, or an object code interpreter used to run it.
133
+
134
+ The "Corresponding Source" for a work in object code form means all
135
+ the source code needed to generate, install, and (for an executable
136
+ work) run the object code and to modify the work, including scripts to
137
+ control those activities. However, it does not include the work's
138
+ System Libraries, or general-purpose tools or generally available free
139
+ programs which are used unmodified in performing those activities but
140
+ which are not part of the work. For example, Corresponding Source
141
+ includes interface definition files associated with source files for
142
+ the work, and the source code for shared libraries and dynamically
143
+ linked subprograms that the work is specifically designed to require,
144
+ such as by intimate data communication or control flow between those
145
+ subprograms and other parts of the work.
146
+
147
+ The Corresponding Source need not include anything that users
148
+ can regenerate automatically from other parts of the Corresponding
149
+ Source.
150
+
151
+ The Corresponding Source for a work in source code form is that
152
+ same work.
153
+
154
+ 2. Basic Permissions.
155
+
156
+ All rights granted under this License are granted for the term of
157
+ copyright on the Program, and are irrevocable provided the stated
158
+ conditions are met. This License explicitly affirms your unlimited
159
+ permission to run the unmodified Program. The output from running a
160
+ covered work is covered by this License only if the output, given its
161
+ content, constitutes a covered work. This License acknowledges your
162
+ rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+ You may make, run and propagate covered works that you do not
165
+ convey, without conditions so long as your license otherwise remains
166
+ in force. You may convey covered works to others for the sole purpose
167
+ of having them make modifications exclusively for you, or provide you
168
+ with facilities for running those works, provided that you comply with
169
+ the terms of this License in conveying all material for which you do
170
+ not control copyright. Those thus making or running the covered works
171
+ for you must do so exclusively on your behalf, under your direction
172
+ and control, on terms that prohibit them from making any copies of
173
+ your copyrighted material outside their relationship with you.
174
+
175
+ Conveying under any other circumstances is permitted solely under
176
+ the conditions stated below. Sublicensing is not allowed; section 10
177
+ makes it unnecessary.
178
+
179
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+ No covered work shall be deemed part of an effective technological
182
+ measure under any applicable law fulfilling obligations under article
183
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+ similar laws prohibiting or restricting circumvention of such
185
+ measures.
186
+
187
+ When you convey a covered work, you waive any legal power to forbid
188
+ circumvention of technological measures to the extent such circumvention
189
+ is effected by exercising rights under this License with respect to
190
+ the covered work, and you disclaim any intention to limit operation or
191
+ modification of the work as a means of enforcing, against the work's
192
+ users, your or third parties' legal rights to forbid circumvention of
193
+ technological measures.
194
+
195
+ 4. Conveying Verbatim Copies.
196
+
197
+ You may convey verbatim copies of the Program's source code as you
198
+ receive it, in any medium, provided that you conspicuously and
199
+ appropriately publish on each copy an appropriate copyright notice;
200
+ keep intact all notices stating that this License and any
201
+ non-permissive terms added in accord with section 7 apply to the code;
202
+ keep intact all notices of the absence of any warranty; and give all
203
+ recipients a copy of this License along with the Program.
204
+
205
+ You may charge any price or no price for each copy that you convey,
206
+ and you may offer support or warranty protection for a fee.
207
+
208
+ 5. Conveying Modified Source Versions.
209
+
210
+ You may convey a work based on the Program, or the modifications to
211
+ produce it from the Program, in the form of source code under the
212
+ terms of section 4, provided that you also meet all of these conditions:
213
+
214
+ a) The work must carry prominent notices stating that you modified
215
+ it, and giving a relevant date.
216
+
217
+ b) The work must carry prominent notices stating that it is
218
+ released under this License and any conditions added under section
219
+ 7. This requirement modifies the requirement in section 4 to
220
+ "keep intact all notices".
221
+
222
+ c) You must license the entire work, as a whole, under this
223
+ License to anyone who comes into possession of a copy. This
224
+ License will therefore apply, along with any applicable section 7
225
+ additional terms, to the whole of the work, and all its parts,
226
+ regardless of how they are packaged. This License gives no
227
+ permission to license the work in any other way, but it does not
228
+ invalidate such permission if you have separately received it.
229
+
230
+ d) If the work has interactive user interfaces, each must display
231
+ Appropriate Legal Notices; however, if the Program has interactive
232
+ interfaces that do not display Appropriate Legal Notices, your
233
+ work need not make them do so.
234
+
235
+ A compilation of a covered work with other separate and independent
236
+ works, which are not by their nature extensions of the covered work,
237
+ and which are not combined with it such as to form a larger program,
238
+ in or on a volume of a storage or distribution medium, is called an
239
+ "aggregate" if the compilation and its resulting copyright are not
240
+ used to limit the access or legal rights of the compilation's users
241
+ beyond what the individual works permit. Inclusion of a covered work
242
+ in an aggregate does not cause this License to apply to the other
243
+ parts of the aggregate.
244
+
245
+ 6. Conveying Non-Source Forms.
246
+
247
+ You may convey a covered work in object code form under the terms
248
+ of sections 4 and 5, provided that you also convey the
249
+ machine-readable Corresponding Source under the terms of this License,
250
+ in one of these ways:
251
+
252
+ a) Convey the object code in, or embodied in, a physical product
253
+ (including a physical distribution medium), accompanied by the
254
+ Corresponding Source fixed on a durable physical medium
255
+ customarily used for software interchange.
256
+
257
+ b) Convey the object code in, or embodied in, a physical product
258
+ (including a physical distribution medium), accompanied by a
259
+ written offer, valid for at least three years and valid for as
260
+ long as you offer spare parts or customer support for that product
261
+ model, to give anyone who possesses the object code either (1) a
262
+ copy of the Corresponding Source for all the software in the
263
+ product that is covered by this License, on a durable physical
264
+ medium customarily used for software interchange, for a price no
265
+ more than your reasonable cost of physically performing this
266
+ conveying of source, or (2) access to copy the
267
+ Corresponding Source from a network server at no charge.
268
+
269
+ c) Convey individual copies of the object code with a copy of the
270
+ written offer to provide the Corresponding Source. This
271
+ alternative is allowed only occasionally and noncommercially, and
272
+ only if you received the object code with such an offer, in accord
273
+ with subsection 6b.
274
+
275
+ d) Convey the object code by offering access from a designated
276
+ place (gratis or for a charge), and offer equivalent access to the
277
+ Corresponding Source in the same way through the same place at no
278
+ further charge. You need not require recipients to copy the
279
+ Corresponding Source along with the object code. If the place to
280
+ copy the object code is a network server, the Corresponding Source
281
+ may be on a different server (operated by you or a third party)
282
+ that supports equivalent copying facilities, provided you maintain
283
+ clear directions next to the object code saying where to find the
284
+ Corresponding Source. Regardless of what server hosts the
285
+ Corresponding Source, you remain obligated to ensure that it is
286
+ available for as long as needed to satisfy these requirements.
287
+
288
+ e) Convey the object code using peer-to-peer transmission, provided
289
+ you inform other peers where the object code and Corresponding
290
+ Source of the work are being offered to the general public at no
291
+ charge under subsection 6d.
292
+
293
+ A separable portion of the object code, whose source code is excluded
294
+ from the Corresponding Source as a System Library, need not be
295
+ included in conveying the object code work.
296
+
297
+ A "User Product" is either (1) a "consumer product", which means any
298
+ tangible personal property which is normally used for personal, family,
299
+ or household purposes, or (2) anything designed or sold for incorporation
300
+ into a dwelling. In determining whether a product is a consumer product,
301
+ doubtful cases shall be resolved in favor of coverage. For a particular
302
+ product received by a particular user, "normally used" refers to a
303
+ typical or common use of that class of product, regardless of the status
304
+ of the particular user or of the way in which the particular user
305
+ actually uses, or expects or is expected to use, the product. A product
306
+ is a consumer product regardless of whether the product has substantial
307
+ commercial, industrial or non-consumer uses, unless such uses represent
308
+ the only significant mode of use of the product.
309
+
310
+ "Installation Information" for a User Product means any methods,
311
+ procedures, authorization keys, or other information required to install
312
+ and execute modified versions of a covered work in that User Product from
313
+ a modified version of its Corresponding Source. The information must
314
+ suffice to ensure that the continued functioning of the modified object
315
+ code is in no case prevented or interfered with solely because
316
+ modification has been made.
317
+
318
+ If you convey an object code work under this section in, or with, or
319
+ specifically for use in, a User Product, and the conveying occurs as
320
+ part of a transaction in which the right of possession and use of the
321
+ User Product is transferred to the recipient in perpetuity or for a
322
+ fixed term (regardless of how the transaction is characterized), the
323
+ Corresponding Source conveyed under this section must be accompanied
324
+ by the Installation Information. But this requirement does not apply
325
+ if neither you nor any third party retains the ability to install
326
+ modified object code on the User Product (for example, the work has
327
+ been installed in ROM).
328
+
329
+ The requirement to provide Installation Information does not include a
330
+ requirement to continue to provide support service, warranty, or updates
331
+ for a work that has been modified or installed by the recipient, or for
332
+ the User Product in which it has been modified or installed. Access to a
333
+ network may be denied when the modification itself materially and
334
+ adversely affects the operation of the network or violates the rules and
335
+ protocols for communication across the network.
336
+
337
+ Corresponding Source conveyed, and Installation Information provided,
338
+ in accord with this section must be in a format that is publicly
339
+ documented (and with an implementation available to the public in
340
+ source code form), and must require no special password or key for
341
+ unpacking, reading or copying.
342
+
343
+ 7. Additional Terms.
344
+
345
+ "Additional permissions" are terms that supplement the terms of this
346
+ License by making exceptions from one or more of its conditions.
347
+ Additional permissions that are applicable to the entire Program shall
348
+ be treated as though they were included in this License, to the extent
349
+ that they are valid under applicable law. If additional permissions
350
+ apply only to part of the Program, that part may be used separately
351
+ under those permissions, but the entire Program remains governed by
352
+ this License without regard to the additional permissions.
353
+
354
+ When you convey a copy of a covered work, you may at your option
355
+ remove any additional permissions from that copy, or from any part of
356
+ it. (Additional permissions may be written to require their own
357
+ removal in certain cases when you modify the work.) You may place
358
+ additional permissions on material, added by you to a covered work,
359
+ for which you have or can give appropriate copyright permission.
360
+
361
+ Notwithstanding any other provision of this License, for material you
362
+ add to a covered work, you may (if authorized by the copyright holders of
363
+ that material) supplement the terms of this License with terms:
364
+
365
+ a) Disclaiming warranty or limiting liability differently from the
366
+ terms of sections 15 and 16 of this License; or
367
+
368
+ b) Requiring preservation of specified reasonable legal notices or
369
+ author attributions in that material or in the Appropriate Legal
370
+ Notices displayed by works containing it; or
371
+
372
+ c) Prohibiting misrepresentation of the origin of that material, or
373
+ requiring that modified versions of such material be marked in
374
+ reasonable ways as different from the original version; or
375
+
376
+ d) Limiting the use for publicity purposes of names of licensors or
377
+ authors of the material; or
378
+
379
+ e) Declining to grant rights under trademark law for use of some
380
+ trade names, trademarks, or service marks; or
381
+
382
+ f) Requiring indemnification of licensors and authors of that
383
+ material by anyone who conveys the material (or modified versions of
384
+ it) with contractual assumptions of liability to the recipient, for
385
+ any liability that these contractual assumptions directly impose on
386
+ those licensors and authors.
387
+
388
+ All other non-permissive additional terms are considered "further
389
+ restrictions" within the meaning of section 10. If the Program as you
390
+ received it, or any part of it, contains a notice stating that it is
391
+ governed by this License along with a term that is a further
392
+ restriction, you may remove that term. If a license document contains
393
+ a further restriction but permits relicensing or conveying under this
394
+ License, you may add to a covered work material governed by the terms
395
+ of that license document, provided that the further restriction does
396
+ not survive such relicensing or conveying.
397
+
398
+ If you add terms to a covered work in accord with this section, you
399
+ must place, in the relevant source files, a statement of the
400
+ additional terms that apply to those files, or a notice indicating
401
+ where to find the applicable terms.
402
+
403
+ Additional terms, permissive or non-permissive, may be stated in the
404
+ form of a separately written license, or stated as exceptions;
405
+ the above requirements apply either way.
406
+
407
+ 8. Termination.
408
+
409
+ You may not propagate or modify a covered work except as expressly
410
+ provided under this License. Any attempt otherwise to propagate or
411
+ modify it is void, and will automatically terminate your rights under
412
+ this License (including any patent licenses granted under the third
413
+ paragraph of section 11).
414
+
415
+ However, if you cease all violation of this License, then your
416
+ license from a particular copyright holder is reinstated (a)
417
+ provisionally, unless and until the copyright holder explicitly and
418
+ finally terminates your license, and (b) permanently, if the copyright
419
+ holder fails to notify you of the violation by some reasonable means
420
+ prior to 60 days after the cessation.
421
+
422
+ Moreover, your license from a particular copyright holder is
423
+ reinstated permanently if the copyright holder notifies you of the
424
+ violation by some reasonable means, this is the first time you have
425
+ received notice of violation of this License (for any work) from that
426
+ copyright holder, and you cure the violation prior to 30 days after
427
+ your receipt of the notice.
428
+
429
+ Termination of your rights under this section does not terminate the
430
+ licenses of parties who have received copies or rights from you under
431
+ this License. If your rights have been terminated and not permanently
432
+ reinstated, you do not qualify to receive new licenses for the same
433
+ material under section 10.
434
+
435
+ 9. Acceptance Not Required for Having Copies.
436
+
437
+ You are not required to accept this License in order to receive or
438
+ run a copy of the Program. Ancillary propagation of a covered work
439
+ occurring solely as a consequence of using peer-to-peer transmission
440
+ to receive a copy likewise does not require acceptance. However,
441
+ nothing other than this License grants you permission to propagate or
442
+ modify any covered work. These actions infringe copyright if you do
443
+ not accept this License. Therefore, by modifying or propagating a
444
+ covered work, you indicate your acceptance of this License to do so.
445
+
446
+ 10. Automatic Licensing of Downstream Recipients.
447
+
448
+ Each time you convey a covered work, the recipient automatically
449
+ receives a license from the original licensors, to run, modify and
450
+ propagate that work, subject to this License. You are not responsible
451
+ for enforcing compliance by third parties with this License.
452
+
453
+ An "entity transaction" is a transaction transferring control of an
454
+ organization, or substantially all assets of one, or subdividing an
455
+ organization, or merging organizations. If propagation of a covered
456
+ work results from an entity transaction, each party to that
457
+ transaction who receives a copy of the work also receives whatever
458
+ licenses to the work the party's predecessor in interest had or could
459
+ give under the previous paragraph, plus a right to possession of the
460
+ Corresponding Source of the work from the predecessor in interest, if
461
+ the predecessor has it or can get it with reasonable efforts.
462
+
463
+ You may not impose any further restrictions on the exercise of the
464
+ rights granted or affirmed under this License. For example, you may
465
+ not impose a license fee, royalty, or other charge for exercise of
466
+ rights granted under this License, and you may not initiate litigation
467
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
468
+ any patent claim is infringed by making, using, selling, offering for
469
+ sale, or importing the Program or any portion of it.
470
+
471
+ 11. Patents.
472
+
473
+ A "contributor" is a copyright holder who authorizes use under this
474
+ License of the Program or a work on which the Program is based. The
475
+ work thus licensed is called the contributor's "contributor version".
476
+
477
+ A contributor's "essential patent claims" are all patent claims
478
+ owned or controlled by the contributor, whether already acquired or
479
+ hereafter acquired, that would be infringed by some manner, permitted
480
+ by this License, of making, using, or selling its contributor version,
481
+ but do not include claims that would be infringed only as a
482
+ consequence of further modification of the contributor version. For
483
+ purposes of this definition, "control" includes the right to grant
484
+ patent sublicenses in a manner consistent with the requirements of
485
+ this License.
486
+
487
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+ patent license under the contributor's essential patent claims, to
489
+ make, use, sell, offer for sale, import and otherwise run, modify and
490
+ propagate the contents of its contributor version.
491
+
492
+ In the following three paragraphs, a "patent license" is any express
493
+ agreement or commitment, however denominated, not to enforce a patent
494
+ (such as an express permission to practice a patent or covenant not to
495
+ sue for patent infringement). To "grant" such a patent license to a
496
+ party means to make such an agreement or commitment not to enforce a
497
+ patent against the party.
498
+
499
+ If you convey a covered work, knowingly relying on a patent license,
500
+ and the Corresponding Source of the work is not available for anyone
501
+ to copy, free of charge and under the terms of this License, through a
502
+ publicly available network server or other readily accessible means,
503
+ then you must either (1) cause the Corresponding Source to be so
504
+ available, or (2) arrange to deprive yourself of the benefit of the
505
+ patent license for this particular work, or (3) arrange, in a manner
506
+ consistent with the requirements of this License, to extend the patent
507
+ license to downstream recipients. "Knowingly relying" means you have
508
+ actual knowledge that, but for the patent license, your conveying the
509
+ covered work in a country, or your recipient's use of the covered work
510
+ in a country, would infringe one or more identifiable patents in that
511
+ country that you have reason to believe are valid.
512
+
513
+ If, pursuant to or in connection with a single transaction or
514
+ arrangement, you convey, or propagate by procuring conveyance of, a
515
+ covered work, and grant a patent license to some of the parties
516
+ receiving the covered work authorizing them to use, propagate, modify
517
+ or convey a specific copy of the covered work, then the patent license
518
+ you grant is automatically extended to all recipients of the covered
519
+ work and works based on it.
520
+
521
+ A patent license is "discriminatory" if it does not include within
522
+ the scope of its coverage, prohibits the exercise of, or is
523
+ conditioned on the non-exercise of one or more of the rights that are
524
+ specifically granted under this License. You may not convey a covered
525
+ work if you are a party to an arrangement with a third party that is
526
+ in the business of distributing software, under which you make payment
527
+ to the third party based on the extent of your activity of conveying
528
+ the work, and under which the third party grants, to any of the
529
+ parties who would receive the covered work from you, a discriminatory
530
+ patent license (a) in connection with copies of the covered work
531
+ conveyed by you (or copies made from those copies), or (b) primarily
532
+ for and in connection with specific products or compilations that
533
+ contain the covered work, unless you entered into that arrangement,
534
+ or that patent license was granted, prior to 28 March 2007.
535
+
536
+ Nothing in this License shall be construed as excluding or limiting
537
+ any implied license or other defenses to infringement that may
538
+ otherwise be available to you under applicable patent law.
539
+
540
+ 12. No Surrender of Others' Freedom.
541
+
542
+ If conditions are imposed on you (whether by court order, agreement or
543
+ otherwise) that contradict the conditions of this License, they do not
544
+ excuse you from the conditions of this License. If you cannot convey a
545
+ covered work so as to satisfy simultaneously your obligations under this
546
+ License and any other pertinent obligations, then as a consequence you may
547
+ not convey it at all. For example, if you agree to terms that obligate you
548
+ to collect a royalty for further conveying from those to whom you convey
549
+ the Program, the only way you could satisfy both those terms and this
550
+ License would be to refrain entirely from conveying the Program.
551
+
552
+ 13. Use with the GNU Affero General Public License.
553
+
554
+ Notwithstanding any other provision of this License, you have
555
+ permission to link or combine any covered work with a work licensed
556
+ under version 3 of the GNU Affero General Public License into a single
557
+ combined work, and to convey the resulting work. The terms of this
558
+ License will continue to apply to the part which is the covered work,
559
+ but the special requirements of the GNU Affero General Public License,
560
+ section 13, concerning interaction through a network will apply to the
561
+ combination as such.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU General Public License from time to time. Such new versions will
567
+ be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
622
+
623
+ How to Apply These Terms to Your New Programs
624
+
625
+ If you develop a new program, and you want it to be of the greatest
626
+ possible use to the public, the best way to achieve this is to make it
627
+ free software which everyone can redistribute and change under these terms.
628
+
629
+ To do so, attach the following notices to the program. It is safest
630
+ to attach them to the start of each source file to most effectively
631
+ state the exclusion of warranty; and each file should have at least
632
+ the "copyright" line and a pointer to where the full notice is found.
633
+
634
+ <one line to give the program's name and a brief idea of what it does.>
635
+ Copyright (C) <year> <name of author>
636
+
637
+ This program is free software: you can redistribute it and/or modify
638
+ it under the terms of the GNU General Public License as published by
639
+ the Free Software Foundation, either version 3 of the License, or
640
+ (at your option) any later version.
641
+
642
+ This program is distributed in the hope that it will be useful,
643
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
+ GNU General Public License for more details.
646
+
647
+ You should have received a copy of the GNU General Public License
648
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
649
+
650
+ Also add information on how to contact you by electronic and paper mail.
651
+
652
+ If the program does terminal interaction, make it output a short
653
+ notice like this when it starts in an interactive mode:
654
+
655
+ <program> Copyright (C) <year> <name of author>
656
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+ This is free software, and you are welcome to redistribute it
658
+ under certain conditions; type `show c' for details.
659
+
660
+ The hypothetical commands `show w' and `show c' should show the appropriate
661
+ parts of the General Public License. Of course, your program's commands
662
+ might be different; for a GUI interface, you would use an "about box".
663
+
664
+ You should also get your employer (if you work as a programmer) or school,
665
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+ For more information on this, and how to apply and follow the GNU GPL, see
667
+ <https://www.gnu.org/licenses/>.
668
+
669
+ The GNU General Public License does not permit incorporating your program
670
+ into proprietary programs. If your program is a subroutine library, you
671
+ may consider it more useful to permit linking proprietary applications with
672
+ the library. If this is what you want to do, use the GNU Lesser General
673
+ Public License instead of this License. But first, please read
674
+ <https://www.gnu.org/licenses/why-not-lgpl.html>.
app.json ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "AutoAnimeBot",
3
+ "description": "Upload Ongoing Animes In Negligible Size... Automatically",
4
+ "logo": "https://graph.org/file/ad1b25807b81cdf1dff65.jpg",
5
+ "keywords": ["Telegram","python", "anime","Compressor","Encoder", "ongoing"],
6
+ "repository": "https://github.com/kaif-00z/AutoAnimeBot",
7
+ "success_url": "https://t.me/BotsBakery",
8
+ "stack": "container",
9
+ "env": {
10
+ "API_ID": {
11
+ "description": "You api id, from my.telegram.org",
12
+ "value": ""
13
+ },
14
+
15
+ "API_HASH": {
16
+ "description": "You api hash, from my.telegram.org",
17
+ "value": ""
18
+ },
19
+
20
+ "BOT_TOKEN": {
21
+ "description": "Make a bot from @BotFather, and enter it's api token here.",
22
+ "value": ""
23
+ },
24
+
25
+ "SESSION": {
26
+ "description": "Telethon Session String",
27
+ "value": "",
28
+ "required": false
29
+ },
30
+
31
+ "OWNER": {
32
+ "description": "Get ur Id Of Telegram nd Paste Here.",
33
+ "value": ""
34
+ },
35
+
36
+ "MONGO_SRV": {
37
+ "description": "Mongo SRV from mongo db.",
38
+ "value": ""
39
+ },
40
+
41
+ "MAIN_CHANNEL": {
42
+ "description": "ID of Your Main Channel.",
43
+ "value": ""
44
+ },
45
+
46
+ "BACKUP_CHANNEL": {
47
+ "description": "If You Want Button Upload On Main Channel Don't Forget To Add Backup Channel becoz anime will be save in backup channel",
48
+ "value": ""
49
+ },
50
+
51
+ "LOG_CHANNEL": {
52
+ "description": "Channel ID Where You Can Check Status Of Tasks.",
53
+ "value": ""
54
+ },
55
+
56
+ "CLOUD_CHANNEL": {
57
+ "description": "Channel ID Where Bot Will Upload Samples And Screen Shots.",
58
+ "value": ""
59
+ },
60
+
61
+ "FORCESUB_CHANNEL": {
62
+ "description": "Channel ID For ForceSub",
63
+ "value": "",
64
+ "required": false
65
+ },
66
+
67
+ "FORCESUB_CHANNEL_LINK": {
68
+ "description": "Channel Link Of ForceSub",
69
+ "value": "",
70
+ "required": false
71
+ },
72
+
73
+ "SEND_SCHEDULE": {
74
+ "description": "Keep it True If You Want Anime Airing Time Else False.",
75
+ "value": "True",
76
+ "required": false
77
+ },
78
+
79
+ "RESTART_EVERDAY": {
80
+ "description": "If You Are In Heroku Then Keep it False.",
81
+ "value": "False",
82
+ "required": false
83
+ },
84
+
85
+ "THUMBNAIL": {
86
+ "description": "Put Link of any picture.",
87
+ "value": "https://graph.org/file/ad1b25807b81cdf1dff65.jpg",
88
+ "required": false
89
+ },
90
+ "CRF": {
91
+ "description": "Less CRF == High Quality, More Size , More CRF == Low Quality, Less Size, CRF Range = 20-51",
92
+ "value": "27",
93
+ "required": false
94
+ }
95
+ }
96
+ }
assest/about.jpg ADDED

Git LFS Details

  • SHA256: 97b42076c833c12d96cec010b122585704a0a05b7362666c62c323df63fdaa39
  • Pointer size: 131 Bytes
  • Size of remote file: 105 kB
assest/poster_not_found.jpg ADDED
auto_env_gen.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import random
3
+ import sys
4
+ from traceback import format_exc
5
+
6
+ from telethon import TelegramClient
7
+ from telethon.sessions import StringSession
8
+ from telethon.tl.functions.channels import CreateChannelRequest
9
+ from telethon.tl.functions.contacts import UnblockRequest
10
+
11
+ DATA = {}
12
+ ENV = """
13
+ API_ID={}
14
+ API_HASH={}
15
+ BOT_TOKEN={}
16
+ SESSION={}
17
+ MAIN_CHANNEL={}
18
+ LOG_CHANNEL={}
19
+ CLOUD_CHANNEL={}
20
+ BACKUP_CHANNEL={}
21
+ MONGO_SRV={}
22
+ OWNER={}
23
+ FORCESUB_CHANNEL={}
24
+ FORCESUB_CHANNEL_LINK={}
25
+ """
26
+
27
+
28
+ async def generate_session_string():
29
+ api_id = int(input("Enter your API_ID: "))
30
+ api_hash = input("Enter your API_HASH: ")
31
+ if api_id and api_hash:
32
+ async with TelegramClient(StringSession(), api_id, api_hash) as client:
33
+ DATA["api_id"] = api_id
34
+ DATA["api_hash"] = api_hash
35
+ DATA["session"] = str(client.session.save())
36
+ return (str(client.session.save()), api_id, api_hash)
37
+ print("API_ID and HASH Not Found!")
38
+ sys.exit(1)
39
+
40
+
41
+ def get_mongo():
42
+ srv = input("Enter your Mongo SRV: ")
43
+ if srv.strip():
44
+ DATA["mongo_srv"] = srv
45
+ return True
46
+ DATA["mongo_srv"] = ""
47
+ return False
48
+
49
+
50
+ def get_forcesub():
51
+ fsub_id = input(
52
+ "Enter ID of Channel Where You Want ForceSub\nNOTE: Bot Is Admin In That Channel: "
53
+ )
54
+ fsub_link = input("Enter Invite Link From Which Subs Will Join The FSUB Channel: ")
55
+ if fsub_id and fsub_link:
56
+ DATA["fsub_id"] = fsub_id
57
+ DATA["fsub_link"] = fsub_link
58
+ return True
59
+ DATA["fsub_link"] = ""
60
+ DATA["fsub_id"] = ""
61
+ return False
62
+
63
+
64
+ async def create_channel(client, title):
65
+ try:
66
+ r = await client(
67
+ CreateChannelRequest(
68
+ title=title,
69
+ about="Made By https://github.com/kaif-00z/AutoAnimeBot",
70
+ megagroup=False,
71
+ )
72
+ )
73
+
74
+ created_chat_id = r.chats[0].id
75
+ return f"-100{created_chat_id}"
76
+ except BaseException:
77
+ print("Unable to Create Channel...")
78
+ sys.exit(1)
79
+
80
+
81
+ def generate_env():
82
+ txt = ENV.format(
83
+ DATA["api_id"],
84
+ DATA["api_hash"],
85
+ DATA["bot_token"],
86
+ DATA["session"],
87
+ DATA["Ongoing Anime 2024"],
88
+ DATA["Ongoing Anime Logs"],
89
+ DATA["Ongoing Anime Samples And SS"],
90
+ DATA["Ongoing Anime Backup"],
91
+ DATA["mongo_srv"],
92
+ DATA["owner_id"],
93
+ DATA["fsub_id"],
94
+ DATA["fsub_link"],
95
+ )
96
+ with open(".env", "w") as f:
97
+ f.write(txt.strip())
98
+ print("Succesfully Generated .env File Don't Forget To Save It! For Future Uses.")
99
+
100
+
101
+ async def auto_maker():
102
+ string_session, api_id, api_hash = await generate_session_string()
103
+ print(string_session)
104
+ async with TelegramClient(
105
+ StringSession(string_session), api_id, api_hash
106
+ ) as client:
107
+ print("Creating Bot Account...")
108
+ who = await client.get_me()
109
+ DATA["owner_id"] = who.id
110
+ name = who.first_name + "'s Auto Anime Bot"
111
+ if who.username:
112
+ username = who.username + "_anime_bot"
113
+ else:
114
+ username = "ongoing_anime_" + (str(who.id))[5:] + "_bot"
115
+ bf = "@BotFather"
116
+ await client(UnblockRequest(bf))
117
+ await client.send_message(bf, "/cancel")
118
+ await asyncio.sleep(1)
119
+ await client.send_message(bf, "/newbot")
120
+ await asyncio.sleep(1)
121
+ isdone = (await client.get_messages(bf, limit=1))[0].text
122
+ if isdone.startswith("That I cannot do.") or "20 bots" in isdone:
123
+ print(
124
+ "You Already Made 20 Bots In Your Current Account. You Have To Deleted One Bot To Run This Script."
125
+ )
126
+ sys.exit(1)
127
+ await client.send_message(bf, name)
128
+ await asyncio.sleep(1)
129
+ isdone = (await client.get_messages(bf, limit=1))[0].text
130
+ if not isdone.startswith("Good."):
131
+ print(
132
+ "Please make a Bot from @BotFather and add it's token in BOT_TOKEN, as an env var and restart me."
133
+ )
134
+ sys.exit(1)
135
+ await client.send_message(bf, username)
136
+ await asyncio.sleep(1)
137
+ isdone = (await client.get_messages(bf, limit=1))[0].text
138
+ await client.send_read_acknowledge("botfather")
139
+ if isdone.startswith("Sorry,"):
140
+ ran = random.randint(1, 100)
141
+ username = "ongoing_anime_" + (str(who.id))[6:] + str(ran) + "_bot"
142
+ await client.send_message(bf, username)
143
+ await asyncio.sleep(1)
144
+ isdone = (await client.get_messages(bf, limit=1))[0].text
145
+ if isdone.startswith("Done!"):
146
+ bot_token = isdone.split("`")[1]
147
+ DATA["bot_token"] = bot_token
148
+ print("Succesfully Created Bot Account...")
149
+ print("Creating Channels...")
150
+ for ch_name in [
151
+ "Ongoing Anime Logs",
152
+ "Ongoing Anime 2024",
153
+ "Ongoing Anime Samples And SS",
154
+ "Ongoing Anime Backup",
155
+ ]:
156
+ try:
157
+ chat_id = await create_channel(client, ch_name)
158
+ await asyncio.sleep(3)
159
+ await client.edit_admin(
160
+ int(chat_id),
161
+ username,
162
+ post_messages=True,
163
+ edit_messages=True,
164
+ delete_messages=True,
165
+ ban_users=True,
166
+ pin_messages=True,
167
+ add_admins=True,
168
+ )
169
+ DATA[ch_name] = chat_id
170
+ except BaseException:
171
+ print("Error While Creating Channel And Promoting Bot..")
172
+ print(format_exc())
173
+ sys.exit(1)
174
+ print("Succesfully Created Channel...")
175
+ print("Now If You Wana Skip Upcoming Inputs You Can Just Press Enter!!")
176
+ db = get_mongo()
177
+ if not db:
178
+ print("Generating .env Without Mongo SRV. Now You Have To Add it Manually!")
179
+ fsub = get_forcesub()
180
+ if not fsub:
181
+ print(
182
+ "Generating .env Without FSUB Configs. Now You May Have To Add it Manually!"
183
+ )
184
+ print("NOTE: Fsub config is optional!!!")
185
+ generate_env()
186
+
187
+
188
+ asyncio.run(auto_maker())
bot.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2024 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ from traceback import format_exc
20
+
21
+ from telethon import Button, events
22
+
23
+ from core.bot import Bot
24
+ from core.executors import Executors
25
+ from database import DataBase
26
+ from functions.info import AnimeInfo
27
+ from functions.schedule import ScheduleTasks, Var
28
+ from functions.tools import Tools, asyncio
29
+ from functions.utils import AdminUtils
30
+ from libs.ariawarp import Torrent
31
+ from libs.logger import LOGS, Reporter
32
+ from libs.subsplease import SubsPlease
33
+
34
+ tools = Tools()
35
+ tools.init_dir()
36
+ bot = Bot()
37
+ dB = DataBase()
38
+ subsplease = SubsPlease(dB)
39
+ torrent = Torrent()
40
+ schedule = ScheduleTasks(bot)
41
+ admin = AdminUtils(dB, bot)
42
+
43
+
44
+ @bot.on(
45
+ events.NewMessage(
46
+ incoming=True, pattern="^/start ?(.*)", func=lambda e: e.is_private
47
+ )
48
+ )
49
+ async def _start(event):
50
+ xnx = await event.reply("`Please Wait...`")
51
+ msg_id = event.pattern_match.group(1)
52
+ await dB.add_broadcast_user(event.sender_id)
53
+ if Var.FORCESUB_CHANNEL and Var.FORCESUB_CHANNEL_LINK:
54
+ is_user_joined = await bot.is_joined(Var.FORCESUB_CHANNEL, event.sender_id)
55
+ if is_user_joined:
56
+ pass
57
+ else:
58
+ return await xnx.edit(
59
+ f"**Please Join The Following Channel To Use This Bot 🫡**",
60
+ buttons=[
61
+ [Button.url("🚀 JOIN CHANNEL", url=Var.FORCESUB_CHANNEL_LINK)],
62
+ [
63
+ Button.url(
64
+ "♻️ REFRESH",
65
+ url=f"https://t.me/{((await bot.get_me()).username)}?start={msg_id}",
66
+ )
67
+ ],
68
+ ],
69
+ )
70
+ if msg_id:
71
+ if msg_id.isdigit():
72
+ msg = await bot.get_messages(Var.BACKUP_CHANNEL, ids=int(msg_id))
73
+ await event.reply(msg)
74
+ else:
75
+ items = await dB.get_store_items(msg_id)
76
+ if items:
77
+ for id in items:
78
+ msg = await bot.get_messages(Var.CLOUD_CHANNEL, ids=id)
79
+ await event.reply(file=[i for i in msg])
80
+ else:
81
+ if event.sender_id == Var.OWNER:
82
+ return await xnx.edit(
83
+ "** < ADMIN PANEL > **",
84
+ buttons=admin.admin_panel(),
85
+ )
86
+ await event.reply(
87
+ f"**Enjoy Ongoing Anime's Best Encode 24/7 🫡**",
88
+ buttons=[
89
+ [
90
+ Button.url("👨‍💻 DEV", url="t.me/kaif_00z"),
91
+ Button.url(
92
+ "💖 OPEN SOURCE",
93
+ url="https://github.com/kaif-00z/AutoAnimeBot/",
94
+ ),
95
+ ]
96
+ ],
97
+ )
98
+ await xnx.delete()
99
+
100
+
101
+ @bot.on(
102
+ events.NewMessage(incoming=True, pattern="^/about", func=lambda e: e.is_private)
103
+ )
104
+ async def _(e):
105
+ await admin._about(e)
106
+
107
+
108
+ @bot.on(events.callbackquery.CallbackQuery(data="slog"))
109
+ async def _(e):
110
+ await admin._logs(e)
111
+
112
+
113
+ @bot.on(events.callbackquery.CallbackQuery(data="sret"))
114
+ async def _(e):
115
+ await admin._restart(e, schedule)
116
+
117
+
118
+ @bot.on(events.callbackquery.CallbackQuery(data="entg"))
119
+ async def _(e):
120
+ await admin._encode_t(e)
121
+
122
+
123
+ @bot.on(events.callbackquery.CallbackQuery(data="butg"))
124
+ async def _(e):
125
+ await admin._btn_t(e)
126
+
127
+
128
+ @bot.on(events.callbackquery.CallbackQuery(data="scul"))
129
+ async def _(e):
130
+ await admin._sep_c_t(e)
131
+
132
+
133
+ @bot.on(events.callbackquery.CallbackQuery(data="cast"))
134
+ async def _(e):
135
+ await admin.broadcast_bt(e)
136
+
137
+
138
+ @bot.on(events.callbackquery.CallbackQuery(data="bek"))
139
+ async def _(e):
140
+ await e.edit(buttons=admin.admin_panel())
141
+
142
+
143
+ async def anime(data):
144
+ try:
145
+ torr = [data.get("480p"), data.get("720p"), data.get("1080p")]
146
+ anime_info = AnimeInfo(torr[0].title)
147
+ poster = await tools._poster(bot, anime_info)
148
+ if await dB.is_separate_channel_upload():
149
+ chat_info = await tools.get_chat_info(bot, anime_info, dB)
150
+ await poster.edit(
151
+ buttons=[
152
+ [
153
+ Button.url(
154
+ f"EPISODE {anime_info.data.get('episode_number', '')}".strip(),
155
+ url=chat_info["invite_link"],
156
+ )
157
+ ]
158
+ ]
159
+ )
160
+ poster = await tools._poster(bot, anime_info, chat_info["chat_id"])
161
+ btn = [[]]
162
+ original_upload = await dB.is_original_upload()
163
+ button_upload = await dB.is_button_upload()
164
+ for i in torr:
165
+ try:
166
+ filename = f"downloads/{i.title}"
167
+ reporter = Reporter(bot, i.title)
168
+ await reporter.alert_new_file_founded()
169
+ await torrent.download_magnet(i.link, "./downloads/")
170
+ exe = Executors(
171
+ bot,
172
+ dB,
173
+ {
174
+ "original_upload": original_upload,
175
+ "button_upload": button_upload,
176
+ },
177
+ filename,
178
+ AnimeInfo(i.title),
179
+ reporter,
180
+ )
181
+ result, _btn = await exe.execute()
182
+ if result:
183
+ if _btn:
184
+ if len(btn[0]) == 2:
185
+ btn.append([_btn])
186
+ else:
187
+ btn[0].append(_btn)
188
+ await poster.edit(buttons=btn)
189
+ asyncio.ensure_future(exe.further_work())
190
+ continue
191
+ await reporter.report_error(_btn, log=True)
192
+ await reporter.msg.delete()
193
+ except BaseException:
194
+ await reporter.report_error(str(format_exc()), log=True)
195
+ await reporter.msg.delete()
196
+ except BaseException:
197
+ LOGS.error(str(format_exc()))
198
+
199
+
200
+ try:
201
+ bot.loop.run_until_complete(subsplease.on_new_anime(anime))
202
+ bot.run()
203
+ except KeyboardInterrupt:
204
+ subsplease._exit()
core/bot.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+ # little bit inspired from pyUltroid.BaseClient
19
+
20
+ import asyncio
21
+ import sys
22
+ from logging import Logger
23
+ from traceback import format_exc
24
+
25
+ from pyrogram import Client, utils
26
+ from telethon import TelegramClient
27
+ from telethon.errors import (
28
+ AccessTokenExpiredError,
29
+ AccessTokenInvalidError,
30
+ ApiIdInvalidError,
31
+ AuthKeyDuplicatedError,
32
+ )
33
+ from telethon.errors.rpcerrorlist import UserNotParticipantError
34
+ from telethon.sessions import StringSession
35
+ from telethon.tl.functions.channels import (
36
+ CreateChannelRequest,
37
+ EditPhotoRequest,
38
+ GetParticipantRequest,
39
+ )
40
+ from telethon.tl.functions.messages import ExportChatInviteRequest
41
+
42
+ from functions.config import Var
43
+ from libs.logger import LOGS, TelethonLogger
44
+
45
+
46
+ class Bot(TelegramClient):
47
+ def __init__(
48
+ self,
49
+ api_id=None,
50
+ api_hash=None,
51
+ bot_token=None,
52
+ logger: Logger = LOGS,
53
+ log_attempt=True,
54
+ exit_on_error=True,
55
+ *args,
56
+ **kwargs,
57
+ ):
58
+ self._handle_error = exit_on_error
59
+ self._log_at = log_attempt
60
+ self.logger = logger
61
+ kwargs["api_id"] = api_id or Var.API_ID
62
+ kwargs["api_hash"] = api_hash or Var.API_HASH
63
+ kwargs["base_logger"] = TelethonLogger
64
+ utils.MIN_CHANNEL_ID = -1009147483647
65
+ super().__init__(None, **kwargs)
66
+ self.pyro_client = Client(
67
+ name="pekka",
68
+ api_id=kwargs["api_id"],
69
+ api_hash=kwargs["api_hash"],
70
+ bot_token=bot_token or Var.BOT_TOKEN,
71
+ in_memory=True,
72
+ )
73
+ self.user_client = None
74
+ if Var.SESSION:
75
+ self.user_client = TelegramClient(
76
+ StringSession(Var.SESSION), kwargs["api_id"], kwargs["api_hash"]
77
+ )
78
+ self.run_in_loop(self.start_client(bot_token=bot_token or Var.BOT_TOKEN))
79
+
80
+ def __repr__(self):
81
+ return "<AutoAnimeBot.Client :\n bot: {}\n>".format(self._bot)
82
+
83
+ async def start_client(self, **kwargs):
84
+ """function to start client"""
85
+ if self._log_at:
86
+ self.logger.info("Trying to login.")
87
+ try:
88
+ await self.start(**kwargs)
89
+ if self.user_client:
90
+ await self.user_client.start()
91
+ await self.pyro_client.start()
92
+ except ApiIdInvalidError:
93
+ self.logger.critical("API ID and API_HASH combination does not match!")
94
+ sys.exit(1)
95
+ except (AuthKeyDuplicatedError, EOFError):
96
+ if self._handle_error:
97
+ self.logger.critical("String session expired. Create new!")
98
+ sys.exit(1)
99
+ self.logger.critical("String session expired.")
100
+ except (AccessTokenExpiredError, AccessTokenInvalidError):
101
+ self.logger.critical(
102
+ "Bot token is expired or invalid. Create new from @Botfather and add in BOT_TOKEN env variable!"
103
+ )
104
+ sys.exit(1)
105
+ self.me = await self.get_me()
106
+ if self.me.bot:
107
+ me = f"@{self.me.username}"
108
+ if self._log_at:
109
+ self.logger.info(f"Logged in as {me}")
110
+ if self.user_client:
111
+ user_me = await self.user_client.get_me()
112
+ self.logger.info(f"Logged in as @{user_me.username}")
113
+ self._bot = await self.is_bot()
114
+
115
+ async def upload_anime(self, file, caption, thumb=None, is_button=False):
116
+ if not self.pyro_client.is_connected:
117
+ try:
118
+ await self.pyro_client.connect()
119
+ except ConnectionError:
120
+ pass
121
+ post = await self.pyro_client.send_document(
122
+ Var.BACKUP_CHANNEL if is_button else Var.MAIN_CHANNEL,
123
+ file,
124
+ caption=f"`{caption}`",
125
+ force_document=True,
126
+ thumb=thumb or "thumb.jpg",
127
+ )
128
+ return post
129
+
130
+ async def upload_poster(self, file, caption, channel_id=None):
131
+ post = await self.send_file(
132
+ channel_id if channel_id else Var.MAIN_CHANNEL,
133
+ file=file,
134
+ caption=caption or "",
135
+ )
136
+ return post
137
+
138
+ async def is_joined(self, channel_id, user_id):
139
+ try:
140
+ await self(GetParticipantRequest(channel=channel_id, participant=user_id))
141
+ return True
142
+ except UserNotParticipantError:
143
+ return False
144
+
145
+ async def create_channel(self, title: str, logo=None):
146
+ try:
147
+ r = await self.user_client(
148
+ CreateChannelRequest(
149
+ title=title,
150
+ about="Powered By github.com/kaif-00z/AutoAnimeBot",
151
+ megagroup=False,
152
+ )
153
+ )
154
+ created_chat_id = r.chats[0].id
155
+ chat_id = int(f"-100{created_chat_id}")
156
+ await asyncio.sleep(2)
157
+ await self.user_client.edit_admin(
158
+ int(chat_id),
159
+ f"{((await self.get_me()).username)}",
160
+ post_messages=True,
161
+ edit_messages=True,
162
+ delete_messages=True,
163
+ ban_users=True,
164
+ pin_messages=True,
165
+ add_admins=True,
166
+ )
167
+ if logo:
168
+ try:
169
+ await self.user_client(
170
+ EditPhotoRequest(
171
+ chat_id, (await self.user_client.upload_file(logo))
172
+ )
173
+ )
174
+ except BaseException:
175
+ pass
176
+ return chat_id
177
+ except BaseException:
178
+ LOGS.error(format_exc())
179
+
180
+ async def generate_invite_link(self, channel_id):
181
+ try:
182
+ data = await self.user_client(
183
+ ExportChatInviteRequest(
184
+ peer=channel_id,
185
+ title=f"Generated By Ongoing Anime Bot",
186
+ request_needed=False,
187
+ usage_limit=None,
188
+ )
189
+ )
190
+ return data.link
191
+ except BaseException:
192
+ LOGS.error(format_exc())
193
+
194
+ def run_in_loop(self, function):
195
+ return self.loop.run_until_complete(function)
196
+
197
+ def run(self):
198
+ self.run_until_disconnected()
199
+
200
+ def add_handler(self, func, *args, **kwargs):
201
+ if func in [_[0] for _ in self.list_event_handlers()]:
202
+ return
203
+ self.add_event_handler(func, *args, **kwargs)
core/executors.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ import asyncio
20
+ import os
21
+ import secrets
22
+ import shutil
23
+ from glob import glob
24
+ from traceback import format_exc
25
+
26
+ from telethon import Button
27
+
28
+ from core.bot import LOGS, Bot, Var
29
+ from database import DataBase
30
+ from functions.info import AnimeInfo
31
+ from functions.tools import Tools
32
+ from libs.logger import Reporter
33
+
34
+
35
+ class Executors:
36
+ def __init__(
37
+ self,
38
+ bot: Bot,
39
+ dB: DataBase,
40
+ configurations: dict,
41
+ input_file: str,
42
+ info: AnimeInfo,
43
+ reporter: Reporter,
44
+ ):
45
+ self.is_original = configurations.get("original_upload")
46
+ self.is_button = configurations.get("button_upload")
47
+ self.anime_info = info
48
+ self.bot = bot
49
+ self.input_file = input_file
50
+ self.tools = Tools()
51
+ self.db = dB
52
+ self.reporter = reporter
53
+ self.msg_id = None
54
+ self.output_file = None
55
+
56
+ async def execute(self):
57
+ try:
58
+ rename = await self.anime_info.rename(self.is_original)
59
+ self.output_file = f"encode/{rename}"
60
+ thumb = await self.tools.cover_dl((await self.anime_info.get_poster()))
61
+ if self.is_original:
62
+ await self.reporter.started_renaming()
63
+ succ, out = await self.tools.rename_file(
64
+ self.input_file, self.output_file
65
+ )
66
+ if not succ:
67
+ return False, out
68
+ else:
69
+ _log_msg = await self.reporter.started_compressing()
70
+ succ, _new_msg = await self.tools.compress(
71
+ self.input_file, self.output_file, _log_msg
72
+ )
73
+ if not succ:
74
+ return False, _new_msg
75
+ self.reporter.msg = _new_msg
76
+ await self.reporter.started_uploading()
77
+ if self.is_button:
78
+ msg = await self.bot.upload_anime(
79
+ self.output_file, rename, thumb or "thumb.jpg", is_button=True
80
+ )
81
+ btn = Button.url(
82
+ f"{self.anime_info.data.get('video_resolution')}",
83
+ url=f"https://t.me/{((await self.bot.get_me()).username)}?start={msg.id}",
84
+ )
85
+ self.msg_id = msg.id
86
+ return True, btn
87
+ msg = await self.bot.upload_anime(
88
+ self.output_file, rename, thumb or "thumb.jpg"
89
+ )
90
+ self.msg_id = msg.id
91
+ return True, []
92
+ except BaseException:
93
+ await self.reporter.report_error(str(format_exc()), log=True)
94
+ return False, str(format_exc())
95
+
96
+ def run_further_work(self):
97
+ asyncio.run(self.further_work())
98
+
99
+ async def further_work(self):
100
+ try:
101
+ if self.msg_id:
102
+ await self.reporter.started_gen_ss()
103
+ msg = await self.bot.get_messages(
104
+ Var.BACKUP_CHANNEL if self.is_button else Var.MAIN_CHANNEL,
105
+ ids=self.msg_id,
106
+ )
107
+ btn = [
108
+ [],
109
+ ]
110
+ link_info = await self.tools.mediainfo(self.output_file, self.bot)
111
+ if link_info:
112
+ btn.append(
113
+ [
114
+ Button.url(
115
+ "📜 MediaInfo",
116
+ url=link_info,
117
+ )
118
+ ]
119
+ )
120
+ await msg.edit(buttons=btn)
121
+ _hash = secrets.token_hex(nbytes=7)
122
+ ss_path, sp_path = await self.tools.gen_ss_sam(_hash, self.output_file)
123
+ if ss_path and sp_path:
124
+ ss = await self.bot.send_message(
125
+ Var.CLOUD_CHANNEL,
126
+ file=glob(f"{ss_path}/*") or ["assest/poster_not_found.jpg"],
127
+ )
128
+ sp = await self.bot.send_message(
129
+ Var.CLOUD_CHANNEL,
130
+ file=sp_path,
131
+ thumb="thumb.jpg",
132
+ force_document=True,
133
+ )
134
+ await self.db.store_items(_hash, [[i.id for i in ss], [sp.id]])
135
+ btn.append(
136
+ [
137
+ Button.url(
138
+ "📺 Sample & ScreenShots",
139
+ url=f"https://t.me/{((await self.bot.get_me()).username)}?start={_hash}",
140
+ )
141
+ ]
142
+ )
143
+ await msg.edit(buttons=btn)
144
+ await self.reporter.all_done()
145
+ try:
146
+ shutil.rmtree(_hash)
147
+ os.remove(sp_path)
148
+ os.remove(self.input_file)
149
+ os.remove(self.output_file)
150
+ except BaseException:
151
+ LOGS.error(str(format_exc()))
152
+ except BaseException:
153
+ await self.reporter.report_error(str(format_exc()), log=True)
database/__init__.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ import sys
20
+ from traceback import format_exc
21
+
22
+ from motor.motor_asyncio import AsyncIOMotorClient
23
+
24
+ from functions.config import Var
25
+ from libs.logger import LOGS
26
+
27
+
28
+ class DataBase:
29
+ def __init__(self):
30
+ try:
31
+ LOGS.info("Trying To Connect With MongoDB")
32
+ self.client = AsyncIOMotorClient(Var.MONGO_SRV)
33
+ self.file_info_db = self.client["ONGOINGANIME"]["fileInfo"]
34
+ self.channel_info_db = self.client["ONGOINGANIME"]["animeChannelInfo"]
35
+ self.opts_db = self.client["ONGOINGANIME"]["opts"]
36
+ self.file_store_db = self.client["ONGOINGANIME"]["fileStore"]
37
+ self.broadcast_db = self.client["ONGOINGANIME"]["broadcastInfo"]
38
+ LOGS.info("Successfully Connected With MongoDB")
39
+ except Exception as error:
40
+ LOGS.exception(format_exc())
41
+ LOGS.critical(str(error))
42
+ sys.exit(1)
43
+
44
+ async def add_anime(self, uid):
45
+ data = await self.file_info_db.find_one({"_id": uid})
46
+ if not data:
47
+ await self.file_info_db.insert_one({"_id": uid})
48
+
49
+ async def toggle_separate_channel_upload(self):
50
+ data = await self.opts_db.find_one({"_id": "SEPARATE_CHANNEL_UPLOAD"})
51
+ if (data or {}).get("switch"):
52
+ _data = False
53
+ else:
54
+ _data = True
55
+ await self.opts_db.update_one(
56
+ {"_id": "SEPARATE_CHANNEL_UPLOAD"}, {"$set": {"switch": _data}}, upsert=True
57
+ )
58
+
59
+ async def is_separate_channel_upload(self):
60
+ data = await self.opts_db.find_one({"_id": "SEPARATE_CHANNEL_UPLOAD"})
61
+ return (data or {}).get("switch") or False
62
+
63
+ async def toggle_original_upload(self):
64
+ data = await self.opts_db.find_one({"_id": "OG_UPLOAD"})
65
+ if (data or {}).get("switch"):
66
+ _data = False
67
+ else:
68
+ _data = True
69
+ await self.opts_db.update_one(
70
+ {"_id": "OG_UPLOAD"}, {"$set": {"switch": _data}}, upsert=True
71
+ )
72
+
73
+ async def is_original_upload(self):
74
+ data = await self.opts_db.find_one({"_id": "OG_UPLOAD"})
75
+ return (data or {}).get("switch") or False
76
+
77
+ async def toggle_button_upload(self):
78
+ data = await self.opts_db.find_one({"_id": "BUTTON_UPLOAD"})
79
+ if data and (data or {}).get("switch"):
80
+ _data = False
81
+ else:
82
+ _data = True
83
+ await self.opts_db.update_one(
84
+ {"_id": "BUTTON_UPLOAD"}, {"$set": {"switch": _data}}, upsert=True
85
+ )
86
+
87
+ async def is_button_upload(self):
88
+ data = await self.opts_db.find_one({"_id": "BUTTON_UPLOAD"})
89
+ return (data or {}).get("switch") or False
90
+
91
+ async def is_anime_uploaded(self, uid):
92
+ data = await self.file_info_db.find_one({"_id": uid})
93
+ if data:
94
+ return True
95
+ return False
96
+
97
+ async def add_anime_channel_info(self, title, _data):
98
+ await self.channel_info_db.update_one(
99
+ {"_id": title}, {"$set": {"data": _data}}, upsert=True
100
+ )
101
+
102
+ async def get_anime_channel_info(self, title):
103
+ data = await self.channel_info_db.find_one({"_id": title})
104
+ if (data or {}).get(title):
105
+ return data["data"]
106
+ return {}
107
+
108
+ async def store_items(self, _hash, _list):
109
+ # in case
110
+ await self.file_store_db.update_one(
111
+ {"_id": _hash}, {"$set": {"data": _list}}, upsert=True
112
+ )
113
+
114
+ async def get_store_items(self, _hash):
115
+ data = await self.file_store_db.find_one({"_id": _hash})
116
+ if (data or {}).get("data"):
117
+ return data["data"]
118
+ return []
119
+
120
+ async def add_broadcast_user(self, user_id):
121
+ data = await self.broadcast_db.find_one({"_id": user_id})
122
+ if not data:
123
+ await self.broadcast_db.insert_one({"_id": user_id})
124
+
125
+ async def get_broadcast_user(self):
126
+ data = self.broadcast_db.find()
127
+ return [i["_id"] for i in (await data.to_list(length=None))]
functions/config.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ from decouple import config
20
+
21
+
22
+ class Var:
23
+ # Version
24
+
25
+ __version__ = "v0.0.8"
26
+
27
+ # Telegram Credentials
28
+
29
+ API_ID = config("API_ID", default=6, cast=int)
30
+ API_HASH = config("API_HASH", default="eb06d4abfb49dc3eeb1aeb98ae0f581e")
31
+ BOT_TOKEN = config("BOT_TOKEN", default=None)
32
+ SESSION = config("SESSION", default=None)
33
+
34
+ # Database Credentials
35
+
36
+ MONGO_SRV = config("MONGO_SRV", default=None)
37
+
38
+ # Channels Ids
39
+
40
+ BACKUP_CHANNEL = config("BACKUP_CHANNEL", default=0, cast=int)
41
+ MAIN_CHANNEL = config("MAIN_CHANNEL", cast=int)
42
+ LOG_CHANNEL = config("LOG_CHANNEL", cast=int)
43
+ CLOUD_CHANNEL = config("CLOUD_CHANNEL", cast=int)
44
+ FORCESUB_CHANNEL = config("FORCESUB_CHANNEL", default=0, cast=int)
45
+ OWNER = config("OWNER", default=0, cast=int)
46
+
47
+ # Other Configs
48
+
49
+ THUMB = config(
50
+ "THUMBNAIL", default="https://graph.org/file/ad1b25807b81cdf1dff65.jpg"
51
+ )
52
+ FFMPEG = config("FFMPEG", default="ffmpeg")
53
+ CRF = config("CRF", default="27")
54
+ SEND_SCHEDULE = config("SEND_SCHEDULE", default=False, cast=bool)
55
+ RESTART_EVERDAY = config("RESTART_EVERDAY", default=True, cast=bool)
56
+ LOG_ON_MAIN = config("LOG_ON_MAIN", default=False, cast=bool)
57
+ FORCESUB_CHANNEL_LINK = config("FORCESUB_CHANNEL_LINK", default="", cast=str)
58
+
59
+ # Dev Configs
60
+
61
+ DEV_MODE = config("DEV_MODE", default=False, cast=bool)
functions/info.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ from traceback import format_exc
20
+
21
+ import anitopy
22
+
23
+ from libs.kitsu import RawAnimeInfo
24
+ from libs.logger import LOGS
25
+
26
+
27
+ class AnimeInfo:
28
+ def __init__(self, name):
29
+ self.kitsu = RawAnimeInfo()
30
+ self.CAPTION = """
31
+ **{}
32
+ ━━━━━━━━━━━━━━━
33
+ ‣ Language:** `Japanese [ESub]`
34
+ **‣ Quality:** `480p|720p|1080p`
35
+ **‣ Season:** `{}`
36
+ **‣ Episode:** `{}`
37
+ **━━━━━━━━━━━━━━━**
38
+ """
39
+ self.proper_name = self.get_proper_name_for_func(name)
40
+ self.name = name
41
+ self.data = anitopy.parse(name)
42
+
43
+ async def get_english(self):
44
+ anime_name = self.data.get("anime_title")
45
+ try:
46
+ anime = (await self.kitsu.search(self.proper_name)) or {}
47
+ return anime.get("english_title") or anime_name
48
+ except BaseException:
49
+ LOGS.error(str(format_exc()))
50
+ return anime_name.strip()
51
+
52
+ async def get_poster(self):
53
+ try:
54
+ if self.proper_name:
55
+ anime_poster = await self.kitsu.search(self.proper_name)
56
+ return anime_poster.get("poster_img") or None
57
+ except BaseException:
58
+ LOGS.error(str(format_exc()))
59
+
60
+ async def get_cover(self):
61
+ try:
62
+ if self.proper_name:
63
+ anime_poster = await self.kitsu.search(self.proper_name)
64
+ if anime_poster.get("anilist_id"):
65
+ return anime_poster.get("anilist_poster")
66
+ return None
67
+ except BaseException:
68
+ LOGS.error(str(format_exc()))
69
+
70
+ async def get_caption(self):
71
+ try:
72
+ if self.proper_name or self.data:
73
+ return self.CAPTION.format(
74
+ (await self.get_english()),
75
+ str(self.data.get("anime_season") or 1).zfill(2),
76
+ (
77
+ str(self.data.get("episode_number")).zfill(2)
78
+ if self.data.get("episode_number")
79
+ else "N/A"
80
+ ),
81
+ )
82
+ except BaseException:
83
+ LOGS.error(str(format_exc()))
84
+ return ""
85
+
86
+ async def rename(self, original=False):
87
+ try:
88
+ anime_name = self.data.get("anime_title")
89
+ if anime_name and self.data.get("episode_number"):
90
+ return (
91
+ f"[S{self.data.get('anime_season') or 1}-{self.data.get('episode_number') or ''}] {(await self.get_english())} [{self.data.get('video_resolution')}].mkv".replace(
92
+ "‘", ""
93
+ )
94
+ .replace("’", "")
95
+ .strip()
96
+ )
97
+ if anime_name:
98
+ return (
99
+ f"{(await self.get_english())} [{self.data.get('video_resolution')}].mkv".replace(
100
+ "‘", ""
101
+ )
102
+ .replace("’", "")
103
+ .strip()
104
+ )
105
+ return self.name
106
+ except Exception as error:
107
+ LOGS.error(str(error))
108
+ LOGS.exception(format_exc())
109
+ return self.name
110
+
111
+ def get_proper_name_for_func(self, name):
112
+ try:
113
+ data = anitopy.parse(name)
114
+ anime_name = data.get("anime_title")
115
+ if anime_name and data.get("episode_number"):
116
+ return (
117
+ f"{anime_name} S{data.get('anime_season')} {data.get('episode_title')}"
118
+ if data.get("anime_season") and data.get("episode_title")
119
+ else (
120
+ f"{anime_name} S{data.get('anime_season')}"
121
+ if data.get("anime_season")
122
+ else anime_name
123
+ )
124
+ )
125
+ return anime_name
126
+ except Exception as error:
127
+ LOGS.error(str(error))
128
+ LOGS.exception(format_exc())
functions/schedule.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+
20
+ import json
21
+ import os
22
+ import sys
23
+
24
+ from apscheduler.schedulers.asyncio import AsyncIOScheduler
25
+
26
+ from functions.config import Var
27
+ from functions.info import AnimeInfo
28
+ from functions.tools import Tools
29
+ from libs.logger import LOGS, TelegramClient
30
+
31
+
32
+ class ScheduleTasks:
33
+ def __init__(self, bot: TelegramClient):
34
+ self.tools = Tools()
35
+ self.bot = bot
36
+ if Var.SEND_SCHEDULE or Var.RESTART_EVERDAY:
37
+ self.sch = AsyncIOScheduler(timezone="Asia/Kolkata")
38
+ if Var.SEND_SCHEDULE:
39
+ self.sch.add_job(
40
+ self.anime_timing, "cron", hour=0, minute=30
41
+ ) # 12:30 AM IST
42
+ if Var.RESTART_EVERDAY:
43
+ self.sch.add_job(self.restart, "cron", hour=2, minute=1) # 2:01 AM IST
44
+ self.sch.start()
45
+
46
+ async def anime_timing(self):
47
+ try:
48
+ _res = await self.tools.async_searcher(
49
+ "https://subsplease.org/api/?f=schedule&h=true&tz=Asia/Kolkata"
50
+ )
51
+ xx = json.loads(_res)
52
+ xxx = xx["schedule"]
53
+ text = "**📆 Anime AirTime Today** `[IST]`\n\n"
54
+ for i in xxx:
55
+ info = AnimeInfo(i["title"])
56
+ text += f'`[{i["time"]}]` - [{(await info.get_english())}](https://subsplease.org/shows/{i["page"]})\n'
57
+ mssg = await self.bot.send_message(Var.MAIN_CHANNEL, text)
58
+ await mssg.pin(notify=True)
59
+ except Exception as error:
60
+ LOGS.error(str(error))
61
+
62
+ def restart(self):
63
+ os.execl(sys.executable, sys.executable, "bot.py")
functions/tools.py ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ import asyncio
20
+ import json
21
+ import math
22
+ import os
23
+ import re
24
+ import shutil
25
+ import subprocess
26
+ import time
27
+ from traceback import format_exc
28
+
29
+ import aiofiles
30
+ import aiohttp
31
+ import requests
32
+ from html_telegraph_poster import TelegraphPoster
33
+ from telethon.errors.rpcerrorlist import MessageNotModifiedError
34
+
35
+ from functions.config import Var
36
+ from libs.logger import LOGS
37
+
38
+
39
+ class Tools:
40
+ def __init__(self):
41
+ if Var.DEV_MODE:
42
+ self.ffmpeg_threads = int(os.cpu_count() or 0) + 2
43
+ else:
44
+ self.ffmpeg_threads = 2
45
+
46
+ async def async_searcher(
47
+ self,
48
+ url: str,
49
+ post: bool = None,
50
+ headers: dict = None,
51
+ params: dict = None,
52
+ json: dict = None,
53
+ data: dict = None,
54
+ ssl=None,
55
+ re_json: bool = False,
56
+ re_content: bool = False,
57
+ real: bool = False,
58
+ *args,
59
+ **kwargs,
60
+ ):
61
+ async with aiohttp.ClientSession(headers=headers) as client:
62
+ if post:
63
+ data = await client.post(
64
+ url, json=json, data=data, ssl=ssl, *args, **kwargs
65
+ )
66
+ else:
67
+ data = await client.get(url, params=params, ssl=ssl, *args, **kwargs)
68
+ if re_json:
69
+ return await data.json()
70
+ if re_content:
71
+ return await data.read()
72
+ if real:
73
+ return data
74
+ return await data.text()
75
+
76
+ async def cover_dl(self, link):
77
+ try:
78
+ if not link:
79
+ return None
80
+ image = await self.async_searcher(link, re_content=True)
81
+ fn = f"thumbs/{link.split('/')[-1]}"
82
+ if not fn.endswith((".jpg" or ".png")):
83
+ fn += ".jpg"
84
+ async with aiofiles.open(fn, "wb") as file:
85
+ await file.write(image)
86
+ return fn
87
+ except Exception as error:
88
+ LOGS.exception(format_exc())
89
+ LOGS.error(str(error))
90
+
91
+ async def mediainfo(self, file, bot):
92
+ try:
93
+ process = await asyncio.create_subprocess_shell(
94
+ f"mediainfo '''{file}''' --Output=HTML",
95
+ stdout=asyncio.subprocess.PIPE,
96
+ stderr=asyncio.subprocess.PIPE,
97
+ )
98
+ stdout, stderr = await process.communicate()
99
+ out = stdout.decode()
100
+ client = TelegraphPoster(use_api=True)
101
+ client.create_api_token("Mediainfo")
102
+ page = client.post(
103
+ title="Mediainfo",
104
+ author=((await bot.get_me()).first_name),
105
+ author_url=f"https://t.me/{((await bot.get_me()).username)}",
106
+ text=out,
107
+ )
108
+ return page.get("url")
109
+ except Exception as error:
110
+ LOGS.exception(format_exc())
111
+ LOGS.error(str(error))
112
+
113
+ async def _poster(self, bot, anime_info, channel_id=None):
114
+ thumb = await self.cover_dl((await anime_info.get_cover()))
115
+ caption = await anime_info.get_caption()
116
+ return await bot.upload_poster(
117
+ thumb or "assest/poster_not_found.jpg",
118
+ caption,
119
+ channel_id if channel_id else None,
120
+ )
121
+
122
+ async def get_chat_info(self, bot, anime_info, dB):
123
+ try:
124
+ chat_info = await dB.get_anime_channel_info(anime_info.proper_name)
125
+ if not chat_info:
126
+ chat_id = await bot.create_channel(
127
+ (await anime_info.get_english()),
128
+ (await self.cover_dl((await anime_info.get_poster()))),
129
+ )
130
+ invite_link = await bot.generate_invite_link(chat_id)
131
+ chat_info = {"chat_id": chat_id, "invite_link": invite_link}
132
+ await dB.add_anime_channel_info(anime_info.proper_name, chat_info)
133
+ return chat_info
134
+ except BaseException:
135
+ LOGS.error(str(format_exc()))
136
+
137
+ def init_dir(self):
138
+ if not os.path.exists("thumb.jpg"):
139
+ content = requests.get(Var.THUMB).content
140
+ with open("thumb.jpg", "wb") as f:
141
+ f.write(content)
142
+ if not os.path.isdir("encode/"):
143
+ os.mkdir("encode/")
144
+ if not os.path.isdir("thumbs/"):
145
+ os.mkdir("thumbs/")
146
+ if not os.path.isdir("downloads/"):
147
+ os.mkdir("downloads/")
148
+
149
+ def hbs(self, size):
150
+ if not size:
151
+ return ""
152
+ power = 2**10
153
+ raised_to_pow = 0
154
+ dict_power_n = {0: "B", 1: "K", 2: "M", 3: "G", 4: "T", 5: "P"}
155
+ while size > power:
156
+ size /= power
157
+ raised_to_pow += 1
158
+ return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B"
159
+
160
+ def ts(self, milliseconds: int) -> str:
161
+ seconds, milliseconds = divmod(int(milliseconds), 1000)
162
+ minutes, seconds = divmod(seconds, 60)
163
+ hours, minutes = divmod(minutes, 60)
164
+ days, hours = divmod(hours, 24)
165
+ tmp = (
166
+ ((str(days) + "d:") if days else "")
167
+ + ((str(hours) + "h:") if hours else "")
168
+ + ((str(minutes) + "m:") if minutes else "")
169
+ + ((str(seconds) + "s:") if seconds else "")
170
+ + ((str(milliseconds) + "ms:") if milliseconds else "")
171
+ )
172
+ return tmp[:-1]
173
+
174
+ async def rename_file(self, dl, out):
175
+ try:
176
+ os.rename(dl, out)
177
+ except BaseException:
178
+ return False, format_exc()
179
+ return True, out
180
+
181
+ async def bash_(self, cmd, run_code=0):
182
+ process = await asyncio.create_subprocess_shell(
183
+ cmd,
184
+ stdout=asyncio.subprocess.PIPE,
185
+ stderr=asyncio.subprocess.PIPE,
186
+ )
187
+ stdout, stderr = await process.communicate()
188
+ err = stderr.decode().strip() or None
189
+ out = stdout.decode().strip()
190
+ if not run_code and err:
191
+ if match := re.match("\\/bin\\/sh: (.*): ?(\\w+): not found", err):
192
+ return out, f"{match.group(2).upper()}_NOT_FOUND"
193
+ return out, err
194
+
195
+ async def frame_counts(self, dl):
196
+ _x, _y = await self.bash_(
197
+ f'mediainfo --fullscan """{dl}""" | grep "Frame count"'
198
+ )
199
+ if _y and _y.endswith("NOT_FOUND"):
200
+ LOGS.error(f"ERROR: `{_y}`")
201
+ return False
202
+ return _x.split(":")[1].split("\n")[0]
203
+
204
+ async def compress(self, dl, out, log_msg):
205
+ total_frames = await self.frame_counts(dl)
206
+ if not total_frames:
207
+ return False, "Unable to Count The Frames!"
208
+ _progress = f"progress-{time.time()}.txt"
209
+ cmd = f'''{Var.FFMPEG} -hide_banner -loglevel quiet -progress """{_progress}""" -i """{dl}""" -metadata "Encoded By"="https://github.com/kaif-00z/AutoAnimeBot/" -preset ultrafast -c:v libx265 -crf {Var.CRF} -map 0:v -c:a aac -map 0:a -c:s copy -map 0:s? -threads {self.ffmpeg_threads} """{out}""" -y'''
210
+ process = await asyncio.create_subprocess_shell(
211
+ cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
212
+ )
213
+ d_time = time.time()
214
+ while process.returncode != 0:
215
+ await asyncio.sleep(5)
216
+ with open(_progress, "r+") as fil:
217
+ text = fil.read()
218
+ frames = re.findall("frame=(\\d+)", text)
219
+ size = re.findall("total_size=(\\d+)", text)
220
+ speed = 0
221
+ if not os.path.exists(out) or os.path.getsize(out) == 0:
222
+ return False, "Unable To Encode This Video!"
223
+ if len(frames):
224
+ elapse = int(frames[-1])
225
+ if len(size):
226
+ size = int(size[-1])
227
+ per = elapse * 100 / int(total_frames)
228
+ time_diff = time.time() - int(d_time)
229
+ speed = round(elapse / time_diff, 2)
230
+ if int(speed) != 0:
231
+ some_eta = ((int(total_frames) - elapse) / speed) * 1000
232
+ text = f"**Successfully Downloaded The Anime**\n\n **File Name:** ```{dl.split('/')[-1]}```\n\n**STATUS:** \n"
233
+ progress_str = "`[{0}{1}] {2}%\n\n`".format(
234
+ "".join("●" for _ in range(math.floor(per / 5))),
235
+ "".join("" for _ in range(20 - math.floor(per / 5))),
236
+ round(per, 2),
237
+ )
238
+ e_size = f"{self.hbs(size)} of ~{self.hbs((size / per) * 100)}"
239
+ eta = f"~{self.ts(some_eta)}"
240
+ try:
241
+ _new_log_msg = await log_msg.edit(
242
+ text
243
+ + progress_str
244
+ + "`"
245
+ + e_size
246
+ + "`"
247
+ + "\n\n`"
248
+ + eta
249
+ + "`"
250
+ )
251
+ except MessageNotModifiedError:
252
+ pass
253
+ try:
254
+ os.remove(_progress)
255
+ except BaseException:
256
+ pass
257
+ return True, _new_log_msg
258
+
259
+ async def genss(self, file):
260
+ process = subprocess.Popen(
261
+ # just for better codefactor rating :)
262
+ [shutil.which("mediainfo"), file, "--Output=JSON"],
263
+ stdout=subprocess.PIPE,
264
+ stderr=subprocess.STDOUT,
265
+ )
266
+ stdout, stderr = process.communicate()
267
+ out = stdout.decode().strip()
268
+ z = json.loads(out)
269
+ p = z["media"]["track"][0]["Duration"]
270
+ return int(p.split(".")[-2])
271
+
272
+ def stdr(self, seconds: int) -> str:
273
+ minutes, seconds = divmod(seconds, 60)
274
+ hours, minutes = divmod(minutes, 60)
275
+ if len(str(minutes)) == 1:
276
+ minutes = "0" + str(minutes)
277
+ if len(str(hours)) == 1:
278
+ hours = "0" + str(hours)
279
+ if len(str(seconds)) == 1:
280
+ seconds = "0" + str(seconds)
281
+ dur = (
282
+ ((str(hours) + ":") if hours else "00:")
283
+ + ((str(minutes) + ":") if minutes else "00:")
284
+ + ((str(seconds)) if seconds else "")
285
+ )
286
+ return dur
287
+
288
+ async def duration_s(self, file):
289
+ tsec = await self.genss(file)
290
+ x = round(tsec / 5)
291
+ y = round(tsec / 5 + 30)
292
+ pin = self.stdr(x)
293
+ if y < tsec:
294
+ pon = self.stdr(y)
295
+ else:
296
+ pon = self.stdr(tsec)
297
+ return pin, pon
298
+
299
+ async def gen_ss_sam(self, _hash, filename):
300
+ try:
301
+ ss_path, sp_path = None, None
302
+ os.mkdir(_hash)
303
+ tsec = await self.genss(filename)
304
+ fps = 10 / tsec
305
+ ncmd = f"ffmpeg -i '{filename}' -vf fps={fps} -vframes 10 '{_hash}/pic%01d.png'"
306
+ process = await asyncio.create_subprocess_shell(
307
+ ncmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
308
+ )
309
+ await process.communicate()
310
+ ss, dd = await self.duration_s(filename)
311
+ __ = filename.split(".mkv")[-2]
312
+ out = __ + "_sample.mkv"
313
+ _ncmd = f'ffmpeg -i """{filename}""" -preset ultrafast -ss {ss} -to {dd} -c:v libx265 -crf 27 -map 0:v -c:a aac -map 0:a -c:s copy -map 0:s? """{out}""" -y'
314
+ process = await asyncio.create_subprocess_shell(
315
+ _ncmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
316
+ )
317
+ stdout, stderr = await process.communicate()
318
+ er = stderr.decode().strip()
319
+ try:
320
+ if er:
321
+ if not os.path.exists(out) or os.path.getsize(out) == 0:
322
+ LOGS.error(str(er))
323
+ return (ss_path, sp_path)
324
+ except BaseException:
325
+ pass
326
+ return _hash, out
327
+ except Exception as error:
328
+ LOGS.error(str(error))
329
+ LOGS.exception(format_exc())
functions/utils.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ import platform
20
+ from datetime import datetime as dt
21
+
22
+ from pyrogram import __version__ as _p_v
23
+ from telethon import Button
24
+ from telethon import __version__ as _t_v
25
+ from telethon import events
26
+
27
+ from core.bot import Bot, Var, asyncio
28
+ from database import DataBase
29
+ from functions.tools import Tools
30
+
31
+ ABOUT = """
32
+ **⏱ Uptime** : `{}`
33
+ **💡 Version** : `{}`
34
+ **👥 Users** : `{}`
35
+ **🗃️ Documents** : `{}`
36
+
37
+ • **🐍 Python**: `{}`
38
+ • **✈️ Telethon**: `{}`
39
+ • **🏔️ Pyrogram**: `{}`
40
+ • **💻 Server**: `{}`
41
+ • **📖 Source Code** : {}
42
+
43
+ ~ **Developer** __@Kaif_00z __
44
+ """
45
+
46
+
47
+ class AdminUtils:
48
+ def __init__(self, dB: DataBase, bot: Bot):
49
+ self.db = dB
50
+ self.bot = bot
51
+ self.tools = Tools()
52
+ self.python_version = platform.python_version()
53
+ self.system = f"{platform.system()}-{platform.release()}"
54
+ self.telethon_version = _t_v
55
+ self.pyrogram_version = _p_v
56
+ self.started_at = dt.now()
57
+
58
+ def admin_panel(self):
59
+ btn = [
60
+ [
61
+ Button.inline("📜 LOGS", data="slog"),
62
+ Button.inline("♻️ Restart", data="sret"),
63
+ ],
64
+ [
65
+ Button.inline("🎞️ Encode [Toogle]", data="entg"),
66
+ ],
67
+ [Button.inline("🔘 Button Upload [Toogle]", data="butg")],
68
+ [Button.inline("🗃️ Separate Channel Upload [Toogle]", data="scul")],
69
+ [Button.inline("🔊 Broadcast", data="cast")],
70
+ ]
71
+ return btn
72
+
73
+ def back_btn(self):
74
+ return [[Button.inline("🔙", data="bek")]]
75
+
76
+ async def _logs(self, e):
77
+ await e.delete()
78
+ await e.reply(
79
+ file="AutoAnimeBot.log", thumb="thumb.jpg", buttons=self.back_btn()
80
+ )
81
+
82
+ async def _restart(self, e, schedule):
83
+ await e.reply("`Restarting...`")
84
+ schedule.restart()
85
+
86
+ async def _encode_t(self, e):
87
+ if await self.db.is_original_upload():
88
+ await self.db.toggle_original_upload()
89
+ return await e.edit(
90
+ "`Successfully On The Compression`", buttons=self.back_btn()
91
+ )
92
+ await self.db.toggle_original_upload()
93
+ return await e.edit(
94
+ "`Successfully Off The Compression`", buttons=self.back_btn()
95
+ )
96
+
97
+ async def _btn_t(self, e):
98
+ if await self.db.is_separate_channel_upload():
99
+ return await e.edit(
100
+ "`You Can't On/Off The Button Upload When Seprate Channel Is Enabled`",
101
+ buttons=self.back_btn(),
102
+ )
103
+ if await self.db.is_button_upload():
104
+ await self.db.toggle_button_upload()
105
+ return await e.edit(
106
+ "`Successfully Off The Button Upload`", buttons=self.back_btn()
107
+ )
108
+ await self.db.toggle_button_upload()
109
+ return await e.edit("`Successfully On The Upload`", buttons=self.back_btn())
110
+
111
+ async def _sep_c_t(self, e):
112
+ if Var.SESSION:
113
+ if await self.db.is_button_upload():
114
+ if await self.db.is_separate_channel_upload():
115
+ await self.db.toggle_separate_channel_upload()
116
+ return await e.edit(
117
+ "`Successfully Off The Separate Channel Upload`",
118
+ buttons=self.back_btn(),
119
+ )
120
+ await self.db.toggle_separate_channel_upload()
121
+ return await e.edit(
122
+ "`Successfully On The Separate Channel Upload`",
123
+ buttons=self.back_btn(),
124
+ )
125
+ else:
126
+ return await e.edit(
127
+ "`To Use The Separate Channel Upload First You Have To Enable Button Upload`",
128
+ buttons=self.back_btn(),
129
+ )
130
+ else:
131
+ return await e.edit(
132
+ "`To Use The Separate Channel Upload First You Have To Add SESSION Variable in The Bot",
133
+ buttons=self.back_btn(),
134
+ )
135
+
136
+ async def broadcast_bt(self, e):
137
+ users = await self.db.get_broadcast_user()
138
+ await e.edit("**Please Use This Feature Responsibly ⚠️**")
139
+ await e.reply(
140
+ f"**Send a single Message To Broadcast 😉**\n\n**There are** `{len(users)}` **Users Currently Using Me👉🏻**.\n\nSend /cancel to Cancel Process."
141
+ )
142
+ async with e.client.conversation(e.sender_id) as cv:
143
+ reply = cv.wait_event(events.NewMessage(from_users=e.sender_id))
144
+ repl = await reply
145
+ await e.delete()
146
+ if repl.text and repl.text.startswith("/cancel"):
147
+ return await repl.reply("`Broadcast Cancelled`")
148
+ sent = await repl.reply("`🗣️ Broadcasting Your Post...`")
149
+ done, er = 0, 0
150
+ for user in users:
151
+ try:
152
+ if repl.poll:
153
+ await repl.forward_to(int(user))
154
+ else:
155
+ await e.client.send_message(int(user), repl.message)
156
+ await asyncio.sleep(0.2)
157
+ done += 1
158
+ except BaseException as ex:
159
+ er += 1
160
+ print(ex)
161
+ await sent.edit(
162
+ f"**Broadcast Completed To** `{done}` **Users.**\n**Error in** `{er}` **Users.**"
163
+ )
164
+
165
+ async def _about(self, e):
166
+ total_docs = await self.db.file_store_db.count_documents({})
167
+ total_users = await self.db.broadcast_db.count_documents({})
168
+ text = ABOUT.format(
169
+ self.tools.ts(int((dt.now() - self.started_at).seconds) * 1000),
170
+ Var.__version__,
171
+ total_users,
172
+ total_docs,
173
+ self.python_version,
174
+ self.telethon_version,
175
+ self.pyrogram_version,
176
+ self.system,
177
+ "[OngoingAnimeBot](https://github.com/Kaif-00z/AutoAnimeBot)",
178
+ )
179
+ await e.reply(text, file="assest/about.jpg", link_preview=False)
heroku.yml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ build:
2
+ docker:
3
+ worker: Dockerfile
4
+ run:
5
+ worker: bash run.sh
libs/ariawarp.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ import asyncio
20
+
21
+
22
+ class Torrent:
23
+ def __init__(self) -> None:
24
+ self.cmd = """aria2c '''{link}''' -x 10 -j 10 --seed-time=0 -d '{path}'"""
25
+
26
+ async def bash(self, cmd):
27
+ process = await asyncio.create_subprocess_shell(
28
+ cmd,
29
+ stdout=asyncio.subprocess.PIPE,
30
+ stderr=asyncio.subprocess.PIPE,
31
+ )
32
+ stdout, stderr = await process.communicate()
33
+ err = stderr.decode().strip() or None
34
+ out = stdout.decode().strip()
35
+ return out, err
36
+
37
+ async def download_magnet(self, link: str, path: str):
38
+ await self.bash(self.cmd.format(link=link, path=path))
libs/kitsu.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ import aiohttp
20
+ from AnilistPython import Anilist
21
+
22
+
23
+ class RawAnimeInfo:
24
+ def __init__(self):
25
+ self.anilist = Anilist()
26
+
27
+ async def search(self, query: str):
28
+ raw_data = ((await self.searcher(query)) or {}).get("data") or {}
29
+ try:
30
+ _raw_data = await self.search_anilist(raw_data.get("id"))
31
+ except BaseException:
32
+ _raw_data = {}
33
+ if not raw_data:
34
+ data = {} # self.alt_anilist(query)
35
+ return data
36
+ data = {}
37
+ data["anime_id"] = raw_data.get("id")
38
+ data["english_title"] = raw_data.get("attributes", {}).get("titles", {}).get(
39
+ "en"
40
+ ) or raw_data.get("attributes", {}).get("titles", {}).get("en_jp")
41
+ data["japanese_title"] = (
42
+ raw_data.get("attributes", {}).get("titles", {}).get("ja_jp")
43
+ )
44
+ data["description"] = raw_data.get("attributes", {}).get("description")
45
+ data["total_eps"] = raw_data.get("attributes", {}).get("episodeCount") or "N/A"
46
+ data["poster_img"] = (
47
+ raw_data.get("attributes", {}).get("posterImage", {}).get("original")
48
+ )
49
+ # anilist score will be better i guess
50
+ # data["score"] = raw_data.get("attributes", {}).get("averageRating") or "N/A"
51
+ data["type"] = raw_data.get("attributes", {}).get("showType") or "TV"
52
+ data["runtime"] = raw_data.get("attributes", {}).get("episodeLength") or 24
53
+ return {**(data if data else {}), **(_raw_data if _raw_data else {})}
54
+
55
+ async def searcher(
56
+ self,
57
+ query: str,
58
+ ):
59
+ async with aiohttp.ClientSession() as client:
60
+ try:
61
+ data = await client.get(
62
+ f"https://kitsu.io/api/edge/anime?filter%5Btext%5D={query.replace(' ', '%20')}"
63
+ )
64
+ links = (await data.json())["data"]
65
+ for index in range(len(links)):
66
+ res_data = await self.re_searcher(links[index]["links"]["self"])
67
+ if res_data["data"]["attributes"]["status"] == "tba":
68
+ continue
69
+ if "current" != res_data["data"]["attributes"]["status"]:
70
+ if (
71
+ res_data["data"]["attributes"]["endDate"]
72
+ or res_data["data"]["attributes"]["startDate"]
73
+ ):
74
+ if "2025" not in (
75
+ res_data["data"]["attributes"]["endDate"] or ""
76
+ ):
77
+ if all(
78
+ year
79
+ not in (
80
+ res_data["data"]["attributes"]["startDate"]
81
+ or ""
82
+ )
83
+ for year in ["2024", "2025"]
84
+ ):
85
+ continue
86
+ return res_data
87
+ except BaseException:
88
+ raise ValueError("Kitsu: Search Link Not Found")
89
+
90
+ async def re_searcher(self, link: str):
91
+ if not link:
92
+ raise ValueError("Kitsu: Link Not Found")
93
+ async with aiohttp.ClientSession() as client:
94
+ try:
95
+ data = await client.get(link)
96
+ return await data.json()
97
+ except BaseException:
98
+ raise ValueError("Kitsu: Link Not Found")
99
+
100
+ async def search_anilist(self, kitsu_id):
101
+ if not kitsu_id:
102
+ raise ValueError("Kitsu: ID Not Found")
103
+ async with aiohttp.ClientSession() as client:
104
+ try:
105
+ _data = {}
106
+ res = await client.get(
107
+ f"https://kitsu.io/api/edge/anime/{kitsu_id}/mappings"
108
+ )
109
+ data = (await res.json())["data"]
110
+ for maps in data:
111
+ if (
112
+ maps.get("attributes", {}).get("externalSite")
113
+ == "anilist/anime"
114
+ ):
115
+ _data["anilist_id"] = maps.get("attributes", {}).get(
116
+ "externalId"
117
+ )
118
+ _data["anilist_poster"] = (
119
+ f"https://img.anili.st/media/{_data['anilist_id']}"
120
+ )
121
+ __data = self.anilist_result(_data["anilist_id"])
122
+ return {**_data, **__data}
123
+ except BaseException:
124
+ raise ValueError("Kitsu: Mapping Failed")
125
+
126
+ def anilist_result(self, anilist_id):
127
+ try:
128
+ data = self.anilist.get_anime_with_id(anilist_id)
129
+ return {
130
+ "genres": data.get("genres"),
131
+ "next_airing_ep": data.get("next_airing_ep"),
132
+ "season": data.get("season"),
133
+ "starting_time": data.get("starting_time"),
134
+ "ending_time": data.get("ending_time"),
135
+ "score": data.get("average_score") or "N/A",
136
+ }
137
+ except BaseException:
138
+ return {}
139
+
140
+ def alt_anilist(self, anime_name):
141
+ data = self.anilist.get_anime(anime_name)
142
+ _id = self.anilist.get_anime_id(anime_name)
143
+ return {
144
+ "anilist_id": _id,
145
+ "genres": data.get("genres"),
146
+ "next_airing_ep": data.get("next_airing_ep") or {},
147
+ "season": data.get("season"),
148
+ "starting_time": data.get("starting_time"),
149
+ "ending_time": data.get("ending_time"),
150
+ "score": data.get("average_score") or "N/A",
151
+ "english_title": data.get("name_english"),
152
+ "japanese_title": data.get("name_romaji"),
153
+ "description": data.get("desc"),
154
+ "total_eps": data.get("airing_episodes") or "N/A",
155
+ "poster_img": data.get("banner_image"),
156
+ "type": data.get("airing_format") or "TV",
157
+ "runtime": 24,
158
+ "anilist_poster": f"https://img.anili.st/media/{_id}",
159
+ }
libs/logger.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ import asyncio
20
+ import logging
21
+ from traceback import format_exc
22
+
23
+ from telethon import TelegramClient
24
+ from telethon.errors.rpcerrorlist import FloodWaitError
25
+
26
+ from functions.config import Var
27
+
28
+ logging.basicConfig(
29
+ format="%(asctime)s || %(name)s [%(levelname)s] : %(message)s",
30
+ handlers=[
31
+ logging.FileHandler("AutoAnimeBot.log", mode="w", encoding="utf-8"),
32
+ logging.StreamHandler(),
33
+ ],
34
+ level=logging.INFO,
35
+ datefmt="%m/%d/%Y, %H:%M:%S",
36
+ )
37
+ LOGS = logging.getLogger("AutoAnimeBot")
38
+ TelethonLogger = logging.getLogger("Telethon")
39
+ TelethonLogger.setLevel(logging.INFO)
40
+
41
+ LOGS.info(
42
+ f"""
43
+ Auto Anime Bot
44
+ ©️ t.me/kAiF_00z (github.com/kaif-00z)
45
+ {Var.__version__} (original)
46
+ (2023-25)
47
+ [All Rigth Reserved]
48
+
49
+ """
50
+ )
51
+
52
+
53
+ class Reporter:
54
+ def __init__(self, client: TelegramClient, file_name: str):
55
+ self.client: TelegramClient = client
56
+ self.file_name = file_name
57
+ self.msg = None
58
+
59
+ async def alert_new_file_founded(self):
60
+ await self.awake()
61
+ msg = await self.client.send_message(
62
+ Var.MAIN_CHANNEL if Var.LOG_ON_MAIN else Var.LOG_CHANNEL,
63
+ f"**New Anime Released**\n\n **File Name:** ```{self.file_name}```\n\n**STATUS:** `Downloading...`",
64
+ )
65
+ self.msg = msg
66
+
67
+ async def started_compressing(self):
68
+ self.msg = await self.msg.edit(
69
+ f"**Successfully Downloaded The Anime**\n\n **File Name:** ```{self.file_name}```\n\n**STATUS:** `Encoding...`",
70
+ )
71
+ return self.msg
72
+
73
+ async def started_renaming(self):
74
+ self.msg = await self.msg.edit(
75
+ f"**Successfully Downloaded The Anime**\n\n **File Name:** ```{self.file_name}```\n\n**STATUS:** `Renaming...`",
76
+ )
77
+
78
+ async def started_uploading(self):
79
+ self.msg = await self.msg.edit(
80
+ f"**Successfully Encoded The Anime**\n\n **File Name:** ```{self.file_name}```\n\n**STATUS:** `Uploading...`"
81
+ )
82
+
83
+ async def started_gen_ss(self):
84
+ self.msg = await self.msg.edit(
85
+ f"**Successfully Uploaded The Anime**\n\n **File Name:** ```{self.file_name}```\n\n**STATUS:** `Generating Sample And Screen Shot...`"
86
+ )
87
+
88
+ async def all_done(self):
89
+ try:
90
+ self.msg = await self.msg.edit(
91
+ f"**Successfully Completed All Task Related To The Anime**\n\n **File Name:** ```{self.file_name}```\n\n**STATUS:** `DONE`"
92
+ )
93
+ except BaseException:
94
+ pass # ValueError Sometimes From telethon
95
+ if Var.LOG_ON_MAIN:
96
+ await self.msg.delete()
97
+
98
+ async def awake(self): # in case
99
+ if not self.client.is_connected():
100
+ await self.client.connect()
101
+
102
+ async def report_error(self, msg, log=False):
103
+ txt = f"[ERROR] {msg}"
104
+ if log:
105
+ LOGS.error(txt[0])
106
+ try:
107
+ await self.client.send_message(Var.LOG_CHANNEL, f"```{txt[:4096]}```")
108
+ except FloodWaitError as fwerr:
109
+ await self.client.disconnect()
110
+ LOGS.info("Sleeping Becoz Of Floodwait...")
111
+ await asyncio.sleep(fwerr.seconds + 10)
112
+ await self.client.connect()
113
+ except ConnectionError:
114
+ await self.client.connect()
115
+ except Exception as err:
116
+ LOGS.exception(format_exc())
117
+ LOGS.error(str(err))
libs/subsplease.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is part of the AutoAnime distribution.
2
+ # Copyright (c) 2025 Kaif_00z
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # General Public License for more details.
12
+ #
13
+ # License can be found in <
14
+ # https://github.com/kaif-00z/AutoAnimeBot/blob/main/LICENSE > .
15
+
16
+ # if you are using this following code then don't forgot to give proper
17
+ # credit to t.me/kAiF_00z (github.com/kaif-00z)
18
+
19
+ import asyncio
20
+ import hashlib
21
+ import shutil
22
+ import sys
23
+ from itertools import count
24
+ from traceback import format_exc
25
+
26
+ import anitopy
27
+ from feedparser import parse
28
+
29
+ from database import LOGS, DataBase
30
+
31
+
32
+ class SubsPlease:
33
+ def __init__(self, dB: DataBase):
34
+ self.db = dB
35
+
36
+ def digest(self, string: str):
37
+ return hashlib.sha256(string.encode()).hexdigest()
38
+
39
+ def _exit(self):
40
+ LOGS.info("Stopping The Bot...")
41
+ try:
42
+ [shutil.rmtree(fold) for fold in ["downloads", "thumbs", "encode"]]
43
+ except BaseException:
44
+ LOGS.error(format_exc())
45
+ sys.exit(0)
46
+
47
+ def rss_feed_data(self):
48
+ try:
49
+ return (
50
+ parse("https://subsplease.org/rss/?r=1080"),
51
+ parse("https://subsplease.org/rss/?r=720"),
52
+ parse("https://subsplease.org/rss/?r=sd"),
53
+ )
54
+ except KeyboardInterrupt:
55
+ self._exit()
56
+ except BaseException:
57
+ LOGS.error(format_exc())
58
+ return None, None, None
59
+
60
+ async def feed_optimizer(self):
61
+ d1080, d720, d480 = self.rss_feed_data()
62
+ if not d1080 or not d720 or not d480:
63
+ return None
64
+ for i in range(2, -1, -1):
65
+ try:
66
+ f1080, f720, f480 = d1080.entries[i], d720.entries[i], d480.entries[i]
67
+ a1080, a720, a480 = (
68
+ (anitopy.parse(f1080.title)).get("anime_title"),
69
+ (anitopy.parse(f720.title)).get("anime_title"),
70
+ (anitopy.parse(f480.title)).get("anime_title"),
71
+ )
72
+ if a1080 == a720 == a480:
73
+ if (
74
+ "[Batch]" in f1080.title
75
+ or "[Batch]" in f720.title
76
+ or "[Batch]" in f480.title
77
+ ):
78
+ continue
79
+ uid = self.digest(f1080.title + f720.title + f480.title)
80
+ if not await self.db.is_anime_uploaded(uid):
81
+ return {"uid": uid, "1080p": f1080, "720p": f720, "480p": f480}
82
+ except BaseException:
83
+ LOGS.error(format_exc())
84
+ return None
85
+
86
+ async def on_new_anime(self, function):
87
+ for i in count():
88
+ data = await self.feed_optimizer()
89
+ if data:
90
+ await function(data)
91
+ await self.db.add_anime(data.get("uid"))
92
+ await asyncio.sleep(5)
ongoing-anime ADDED
@@ -0,0 +1 @@
 
 
1
+ Subproject commit 0ed0019f35e7aaabcc0c7903f4ba329b6edb5869
pkg.sh ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ sudo apt install -y mediainfo ffmpeg wget gcc python3-pip python3 aria2
2
+ pip3 install -U -r requirements.txt
requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ python-decouple
2
+ motor[srv]==3.2.0
3
+ dnspython
4
+ lxml_html_clean
5
+ aiohttp
6
+ aiofiles
7
+ apscheduler==3.10.1
8
+ feedparser
9
+ https://github.com/New-dev0/Telethon/archive/platy.zip
10
+ pyrofork==2.2.11
11
+ tgcrypto
12
+ AnilistPython==0.1.3
13
+ anitopy
14
+ git+https://github.com/kaif-00z/html-telegraph-poster
15
+ pytz
run.sh ADDED
@@ -0,0 +1 @@
 
 
1
+ python3 bot.py