Commited backup
59
fajox1/famods/CodeBase64.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: CodeBase64
|
||||
# Description: Encode and decode base64
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/CodeBase64.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import base64
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class CodeBase64(loader.Module):
|
||||
"""Encode and decode base64"""
|
||||
|
||||
strings = {
|
||||
"name": "CodeBase64",
|
||||
|
||||
"only_base64": "<b><emoji document_id=5019523782004441717>🚫</emoji> Only <code>base64</code></b>",
|
||||
|
||||
"enc_txt": "<b><emoji document_id=6334316848741352906>⌨️</emoji> You encoded text into base64:</b>\n<code>{}</code>",
|
||||
"de_txt": "<b><emoji document_id=6334316848741352906>⌨️</emoji> You decoded text from base64:</b>\n<code>{}</code>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def cbase64(self, message):
|
||||
"""Кодирование в base64"""
|
||||
enc_bytes = base64.b64encode(utils.get_args_raw(message).encode('utf-8'))
|
||||
enc_text = enc_bytes.decode('utf-8') # Декодируем байты в строку
|
||||
|
||||
await utils.answer(message, self.strings["enc_txt"].format(enc_text))
|
||||
|
||||
@loader.command()
|
||||
async def dbase64(self, message):
|
||||
"""Декодирование из base64"""
|
||||
try:
|
||||
de_bytes = base64.b64decode(utils.get_args_raw(message))
|
||||
except:
|
||||
return await utils.answer(message, self.strings['only_base64'])
|
||||
de_text = de_bytes.decode('utf-8') # Декодируем байты в строку
|
||||
|
||||
await utils.answer(message, self.strings["de_txt"].format(de_text))
|
||||
674
fajox1/famods/LICENSE
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
35
fajox1/famods/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
<div align="center">
|
||||
|
||||
# 💻 FAmods
|
||||
|
||||
<i>Модули для юзербота Hikka</i>
|
||||
|
||||
## ⬇️ Установка
|
||||
|
||||
### Обычная установка в Hikka
|
||||
<pre><code>.dlmod https://raw.githubusercontent.com/FajoX1/FAmods/main/<b><i>{название_модуля}</i></b>.py</code></pre>
|
||||
<hr>
|
||||
|
||||
### Установка репозитория
|
||||
> <i>Установить репозиторий</i>
|
||||
<pre><code>.addrepo https://github.com/FajoX1/FAmods/raw/main</code></pre>
|
||||
> <i>Установка модуля</i>
|
||||
<pre><code>.dlmod <b><i>{название_модуля}</i></b></code></pre>
|
||||
|
||||
<div align="center">
|
||||
|
||||
## 📝 Лицензия
|
||||
|
||||
</div>
|
||||
|
||||
> <i>Все файлы этого репозитория находятся под лицензией <b>GNU AGPLv3.</b></i><br>
|
||||
> <b>https://www.gnu.org/licenses/agpl-3.0.html</b>
|
||||
|
||||
## ❓ Нашёл баг?
|
||||
> <b><a href="https://t.me/vecax">Писать сюда</a></b>
|
||||
|
||||
<hr>
|
||||
|
||||
### ✈️ <a href="https://t.me/FAmods">Канал</a> | <a href="https://t.me/FAmods_Chat">Чат</a> | <a href="https://t.me/vecax">Разработчик</a>
|
||||
|
||||
</div>
|
||||
137
fajox1/famods/anonsms.py
Normal file
@@ -0,0 +1,137 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: AnonSMS
|
||||
# Description: Анонимное сообщение
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/anonsms.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import time
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
from ..inline.types import InlineCall, BotInlineMessage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class AnonSMS(loader.Module):
|
||||
"""Анонимное сообщение"""
|
||||
|
||||
strings = {
|
||||
"name": "AnonSMS",
|
||||
|
||||
"enter_message": "<b>📩 Отправьте сообщение</b>",
|
||||
|
||||
"new_anon_msg": "<b>📨 Вам пришло новое анонимное сообщение:</b>",
|
||||
"opening_settings": "<b><emoji document_id=5327902038720257153>🔄</emoji> Открываю настройки...</b>",
|
||||
|
||||
"only_one": "<b>❌ Отправлять сообщение можно раз в {} секунд!</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"start_text",
|
||||
"<b>👋 Привет!\nТы можешь написать мне анонимное сообщение</b>",
|
||||
lambda: "Текст после перехода по ссылке",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"sent_text",
|
||||
"<b>✅ Сообщение отправлено</b>",
|
||||
lambda: "Текст пользователю после отправки сообщения",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"error_send_text",
|
||||
"<b>❌ Не удалось отправить сообщение</b>",
|
||||
lambda: "Текст пользователю если не удалось отправить сообщение",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"floodwait",
|
||||
15,
|
||||
lambda: "Раз в сколько секунд можно отправить сообщение",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
async def _check_message_rate(self, user_id: int) -> bool:
|
||||
if user_id in self.last_message_time:
|
||||
last_time = self.last_message_time[user_id]
|
||||
|
||||
if time.time() - last_time < self.config['floodwait']:
|
||||
return False
|
||||
|
||||
self.last_message_time[user_id] = time.time()
|
||||
return True
|
||||
|
||||
@loader.command()
|
||||
async def getanonlink(self, message):
|
||||
"""Получить ссылку на получение анонимного сообщения"""
|
||||
|
||||
await utils.answer(message, f"<emoji document_id=5271604874419647061>🔗</emoji> <b>Твоя ссылка для получение анонимного смс:\n<code>https://t.me/{self.inline.bot_username}?start=anonsms</code></b>")
|
||||
|
||||
@loader.command()
|
||||
async def anonsettings(self, message):
|
||||
"""Настроят модуль"""
|
||||
|
||||
await utils.answer(message, self.strings['opening_settings'])
|
||||
await self.invoke("config", "AnonSMS", message.peer_id)
|
||||
await message.delete()
|
||||
|
||||
@loader.inline_everyone
|
||||
@loader.callback_handler()
|
||||
async def anon_sms(self, call: InlineCall):
|
||||
if call.data == "anon_cancel":
|
||||
self.inline.ss(call.from_user.id, False)
|
||||
await self.inline.bot.delete_message(
|
||||
call.message.chat.id,
|
||||
call.message.message_id,
|
||||
)
|
||||
return
|
||||
|
||||
if call.data != "leave_anonsms":
|
||||
return
|
||||
|
||||
self.inline.ss(call.from_user.id, "send_anonsms")
|
||||
await self.inline.bot.edit_message_text(
|
||||
chat_id=call.message.chat.id,
|
||||
message_id=call.message.message_id,
|
||||
text=self.strings['enter_message'],
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True,
|
||||
reply_markup=self.inline.generate_markup(
|
||||
{"text": "🚫 Отменить", "data": "anon_cancel"}
|
||||
),
|
||||
)
|
||||
|
||||
async def aiogram_watcher(self, message: BotInlineMessage):
|
||||
if message.text == "/start anonsms":
|
||||
return await message.answer(
|
||||
self.config["start_text"],
|
||||
reply_markup=self.inline.generate_markup(
|
||||
{"text": "✍️ Написать", "data": "leave_anonsms"}
|
||||
),
|
||||
)
|
||||
if self.inline.gs(message.from_user.id) == "send_anonsms":
|
||||
if not await self._check_message_rate(message.from_user.id):
|
||||
await message.answer(self.strings['only_one'].format(self.config['floodwait']))
|
||||
return
|
||||
try:
|
||||
await self.inline.bot.send_message(self._tg_id, self.strings['new_anon_msg'])
|
||||
await message.send_copy(self._tg_id)
|
||||
except:
|
||||
return await message.answer(self.config['error_send_text'])
|
||||
return await message.answer(self.config["sent_text"])
|
||||
BIN
fajox1/famods/assets/banners/CodeBase64.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
BIN
fajox1/famods/assets/banners/anonsms.png
Normal file
|
After Width: | Height: | Size: 583 KiB |
BIN
fajox1/famods/assets/banners/autogh.png
Normal file
|
After Width: | Height: | Size: 621 KiB |
BIN
fajox1/famods/assets/banners/avachanger.png
Normal file
|
After Width: | Height: | Size: 587 KiB |
BIN
fajox1/famods/assets/banners/banforaskmod.png
Normal file
|
After Width: | Height: | Size: 581 KiB |
BIN
fajox1/famods/assets/banners/bigmac.png
Normal file
|
After Width: | Height: | Size: 613 KiB |
BIN
fajox1/famods/assets/banners/checkhost.png
Normal file
|
After Width: | Height: | Size: 648 KiB |
BIN
fajox1/famods/assets/banners/chmodslist.png
Normal file
|
After Width: | Height: | Size: 588 KiB |
BIN
fajox1/famods/assets/banners/cryptoqr.png
Normal file
|
After Width: | Height: | Size: 589 KiB |
BIN
fajox1/famods/assets/banners/edmes.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
BIN
fajox1/famods/assets/banners/epsilion.png
Normal file
|
After Width: | Height: | Size: 624 KiB |
BIN
fajox1/famods/assets/banners/evalaliases.png
Normal file
|
After Width: | Height: | Size: 582 KiB |
BIN
fajox1/famods/assets/banners/executor.png
Normal file
|
After Width: | Height: | Size: 585 KiB |
BIN
fajox1/famods/assets/banners/fabrika.png
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
fajox1/famods/assets/banners/fabusiness.png
Normal file
|
After Width: | Height: | Size: 584 KiB |
BIN
fajox1/famods/assets/banners/faker.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
fajox1/famods/assets/banners/famod.png
Normal file
|
After Width: | Height: | Size: 591 KiB |
BIN
fajox1/famods/assets/banners/freegpt.png
Normal file
|
After Width: | Height: | Size: 587 KiB |
BIN
fajox1/famods/assets/banners/fun.png
Normal file
|
After Width: | Height: | Size: 155 KiB |
BIN
fajox1/famods/assets/banners/gemini.png
Normal file
|
After Width: | Height: | Size: 588 KiB |
BIN
fajox1/famods/assets/banners/gigachat.png
Normal file
|
After Width: | Height: | Size: 584 KiB |
BIN
fajox1/famods/assets/banners/giveaways.png
Normal file
|
After Width: | Height: | Size: 591 KiB |
BIN
fajox1/famods/assets/banners/grokai.png
Normal file
|
After Width: | Height: | Size: 588 KiB |
BIN
fajox1/famods/assets/banners/gsearch.png
Normal file
|
After Width: | Height: | Size: 634 KiB |
BIN
fajox1/famods/assets/banners/hbotcommand.png
Normal file
|
After Width: | Height: | Size: 626 KiB |
BIN
fajox1/famods/assets/banners/hetalib.png
Normal file
|
After Width: | Height: | Size: 634 KiB |
BIN
fajox1/famods/assets/banners/hetsu.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
fajox1/famods/assets/banners/infoip.png
Normal file
|
After Width: | Height: | Size: 632 KiB |
BIN
fajox1/famods/assets/banners/phoneinfo.png
Normal file
|
After Width: | Height: | Size: 635 KiB |
BIN
fajox1/famods/assets/banners/picme.png
Normal file
|
After Width: | Height: | Size: 585 KiB |
BIN
fajox1/famods/assets/banners/pricefreedom.png
Normal file
|
After Width: | Height: | Size: 642 KiB |
BIN
fajox1/famods/assets/banners/proxy.png
Normal file
|
After Width: | Height: | Size: 588 KiB |
BIN
fajox1/famods/assets/banners/removebg.png
Normal file
|
After Width: | Height: | Size: 638 KiB |
BIN
fajox1/famods/assets/banners/requirements.png
Normal file
|
After Width: | Height: | Size: 626 KiB |
BIN
fajox1/famods/assets/banners/spotify4ik.png
Normal file
|
After Width: | Height: | Size: 585 KiB |
BIN
fajox1/famods/assets/banners/stats.png
Normal file
|
After Width: | Height: | Size: 167 KiB |
BIN
fajox1/famods/assets/banners/telegrapher.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
fajox1/famods/assets/banners/timer.png
Normal file
|
After Width: | Height: | Size: 159 KiB |
BIN
fajox1/famods/assets/banners/tondns.png
Normal file
|
After Width: | Height: | Size: 169 KiB |
BIN
fajox1/famods/assets/banners/tonscan.png
Normal file
|
After Width: | Height: | Size: 175 KiB |
BIN
fajox1/famods/assets/banners/vaper.png
Normal file
|
After Width: | Height: | Size: 591 KiB |
BIN
fajox1/famods/assets/banners/wakatime.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
fajox1/famods/assets/banners/xrocket.png
Normal file
|
After Width: | Height: | Size: 594 KiB |
BIN
fajox1/famods/assets/banners/ytsearch.png
Normal file
|
After Width: | Height: | Size: 634 KiB |
BIN
fajox1/famods/assets/buckshot-roulette-buckshot.gif
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
fajox1/famods/assets/buckshot-roulette-dealer.gif
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
fajox1/famods/assets/buckshot-roulette.gif
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
fajox1/famods/assets/buckshotroulette-shotgun.gif
Normal file
|
After Width: | Height: | Size: 7.4 MiB |
BIN
fajox1/famods/assets/famods_banner.png
Normal file
|
After Width: | Height: | Size: 672 KiB |
166
fajox1/famods/assets/musicdl.py
Normal file
@@ -0,0 +1,166 @@
|
||||
# █ █ ▀ █▄▀ ▄▀█ █▀█ ▀
|
||||
# █▀█ █ █ █ █▀█ █▀▄ █
|
||||
# © Copyright 2022
|
||||
# https://t.me/hikariatama
|
||||
#
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
import asyncio
|
||||
import io
|
||||
import logging
|
||||
import typing
|
||||
|
||||
import requests
|
||||
from telethon.errors.rpcerrorlist import BotResponseTimeoutError
|
||||
from telethon.events import MessageEdited, StopPropagation
|
||||
from telethon.tl.types import Document
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
|
||||
class MusicDLLib(loader.Library):
|
||||
developer = "@hikariatama"
|
||||
version = (1, 0, 19)
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.LibraryConfig(
|
||||
loader.ConfigValue(
|
||||
"timeout",
|
||||
40,
|
||||
"Timeout for downloading",
|
||||
validator=loader.validators.Integer(minimum=5),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"retries",
|
||||
3,
|
||||
"Number of retries for downloading",
|
||||
validator=loader.validators.Integer(minimum=0),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"lossless_priority",
|
||||
False,
|
||||
"If True, lossless music will be downloaded first",
|
||||
validator=loader.validators.Boolean(),
|
||||
),
|
||||
)
|
||||
|
||||
async def _dl(self, bot: str, full_name: str):
|
||||
try:
|
||||
return (await self._client.inline_query(bot, full_name))[0].document
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
async def _legacy(self, full_name: str):
|
||||
document = await self._dl("@vkm4bot", full_name)
|
||||
document = (
|
||||
await self._dl("@spotifysavebot", full_name) if not document else document
|
||||
)
|
||||
document = await self._dl("@lybot", full_name) if not document else document
|
||||
return document
|
||||
|
||||
async def dl(
|
||||
self,
|
||||
full_name: str,
|
||||
only_document: bool = False,
|
||||
retries: int = 0,
|
||||
) -> typing.Union[Document, str]:
|
||||
try:
|
||||
if not self.config["lossless_priority"]:
|
||||
document = await self._legacy(full_name)
|
||||
|
||||
if self.config["lossless_priority"] or not document:
|
||||
try:
|
||||
q = await self._client.inline_query("@losslessrobot", full_name)
|
||||
except BotResponseTimeoutError:
|
||||
if retries >= self.config["retries"]:
|
||||
raise Exception("Failed to download")
|
||||
|
||||
await asyncio.sleep(3)
|
||||
return await self.dl(full_name, only_document, retries + 1)
|
||||
|
||||
result = q.result.results[0]
|
||||
if not getattr(
|
||||
getattr(result, "send_message", None), "reply_markup", None
|
||||
):
|
||||
document = result.document
|
||||
if text := getattr(
|
||||
getattr(result, "send_message", None), "message", None
|
||||
):
|
||||
if "FLAC" in text:
|
||||
document.is_flac = True
|
||||
else:
|
||||
m = await q[0].click("me")
|
||||
|
||||
dl_event = asyncio.Event()
|
||||
document = None
|
||||
|
||||
@self._client.on(MessageEdited(chats=utils.get_chat_id(m)))
|
||||
async def handler(event: MessageEdited):
|
||||
nonlocal document
|
||||
try:
|
||||
if (
|
||||
event.message.id == m.id
|
||||
and (
|
||||
not getattr(event.message, "reply_markup", None)
|
||||
or all(
|
||||
button.text
|
||||
!= "Подождите, трек скоро скачается."
|
||||
for button in utils.array_sum(
|
||||
[
|
||||
row.buttons
|
||||
for row in event.message.reply_markup.rows
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
and event.message.document
|
||||
):
|
||||
document = event.message.document
|
||||
if text := getattr(event.message, "message", None):
|
||||
if "FLAC" in text:
|
||||
document.is_flac = True
|
||||
dl_event.set()
|
||||
|
||||
raise StopPropagation
|
||||
except StopPropagation:
|
||||
raise
|
||||
except Exception:
|
||||
logging.exception("Failed to download")
|
||||
|
||||
try:
|
||||
await asyncio.wait_for(
|
||||
dl_event.wait(),
|
||||
timeout=self.config["timeout"],
|
||||
)
|
||||
except Exception:
|
||||
await m.delete()
|
||||
document = None
|
||||
else:
|
||||
await m.delete()
|
||||
except Exception:
|
||||
logging.debug("Can't download", exc_info=True)
|
||||
document = None
|
||||
|
||||
if not document:
|
||||
document = await self._legacy(full_name)
|
||||
|
||||
if not document:
|
||||
return None
|
||||
|
||||
if only_document:
|
||||
return document
|
||||
|
||||
file = io.BytesIO(await self._client.download_file(document, bytes))
|
||||
file.name = "audio.mp3"
|
||||
|
||||
try:
|
||||
skynet = await utils.run_sync(
|
||||
requests.post,
|
||||
"https://siasky.net/skynet/skyfile",
|
||||
files={"file": file},
|
||||
)
|
||||
except ConnectionError:
|
||||
return None
|
||||
|
||||
return f"https://siasky.net/{skynet.json()['skylink']}"
|
||||
BIN
fajox1/famods/assets/photo_2025-03-26_17-03-56.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
fajox1/famods/assets/start.jpg
Normal file
|
After Width: | Height: | Size: 512 KiB |
120
fajox1/famods/autogh.py
Normal file
@@ -0,0 +1,120 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: AutoGH
|
||||
# Description: Авто-коммиты в Github
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/autogh.png?raw=true
|
||||
# requires: PyGithub
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from github import Github
|
||||
from datetime import datetime
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class AutoGH(loader.Module):
|
||||
"""Авто-коммиты в Github"""
|
||||
|
||||
strings = {
|
||||
"name": "AutoGH",
|
||||
|
||||
"no_cfg": "<b><emoji document_id=5854929766146118183>🚫</emoji> Нету {}! Вставьте его в config через <code>{}cfg AutoGH</code></b>",
|
||||
|
||||
"autocommit_on": "<b><emoji document_id=4985961065012527769>🖥</emoji> Авто-коммит включен!</b>",
|
||||
"autocommit_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Авто-коммит выключен!</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"API_TOKEN",
|
||||
None,
|
||||
lambda: "Github API Token. Создать токен можно в https://github.com/settings/tokens/new",
|
||||
validator=loader.validators.Hidden(loader.validators.String()),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"REPO",
|
||||
None,
|
||||
lambda: "Репозиторий для авто-коммитов. Пример: FajoX1/FAmods",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"file_name",
|
||||
"autocommit.txt",
|
||||
lambda: "Файл для авто-коммита",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"commit_name",
|
||||
"AutoCommit",
|
||||
lambda: "Название коммита",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"time_autocommit",
|
||||
3600,
|
||||
lambda: "Через сколько секунд сделать следущий коммит",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"log",
|
||||
True,
|
||||
lambda: "Логи о том что сделали/не получилось сделать коммит",
|
||||
validator=loader.validators.Boolean(),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
asyncio.create_task(self._autocommit())
|
||||
|
||||
async def _autocommit(self):
|
||||
while True:
|
||||
if self.db.get(self.name, "autocommit", False):
|
||||
try:
|
||||
g = Github(self.config['API_TOKEN'])
|
||||
repo = g.get_repo(self.config['REPO'])
|
||||
file_content = f'Commit at {datetime.now()}'
|
||||
try:
|
||||
contents = repo.get_contents(self.config['file_name'])
|
||||
sha = contents.sha
|
||||
repo.update_file(self.config['file_name'], self.config['commit_name'], file_content, sha)
|
||||
except:
|
||||
repo.create_file(self.config['file_name'], self.config['commit_name'], file_content)
|
||||
if self.config['log']:
|
||||
logger.info("Auto commited")
|
||||
except Exception as e:
|
||||
if self.config['log']:
|
||||
logger.error(f"Can't commit:\n{e}")
|
||||
|
||||
await asyncio.sleep(self.config['time_autocommit'])
|
||||
|
||||
@loader.command()
|
||||
async def autocommit(self, message):
|
||||
"""Включить/выключить автоматический коммит"""
|
||||
|
||||
if not self.config['API_TOKEN']:
|
||||
return await utils.answer(message, self.strings['no_cfg'].format("токена github", self.get_prefix()))
|
||||
|
||||
if not self.config['REPO']:
|
||||
return await utils.answer(message, self.strings['no_cfg'].format("названия репозитория", self.get_prefix()))
|
||||
|
||||
if self.db.get(self.name, "autocommit", False):
|
||||
self.db.set(self.name, "autocommit", False)
|
||||
return await utils.answer(message, self.strings["autocommit_off"])
|
||||
|
||||
self.db.set(self.name, "autocommit", True)
|
||||
|
||||
await utils.answer(message, self.strings["autocommit_on"])
|
||||
96
fajox1/famods/avachanger.py
Normal file
@@ -0,0 +1,96 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: AvaChanger
|
||||
# Description: Смена аватарки по времени
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/avachanger.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import asyncio
|
||||
import tempfile
|
||||
|
||||
import logging
|
||||
|
||||
from telethon.tl.functions.photos import UploadProfilePhotoRequest
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class AvaChanger(loader.Module):
|
||||
"""Смена аватарки по времени"""
|
||||
|
||||
strings = {
|
||||
"name": "AvaChanger",
|
||||
|
||||
"no_args": "<emoji document_id=5440381017384822513>❌</emoji> <b>Нужно <code>{}avatarl [сколько раз] [сколько ждать перед сменой каждой аватарки]</code></b>",
|
||||
"no_reply": "<emoji document_id=5440381017384822513>❌</emoji> <b>Нужно ответить на сообщение с фоткой</b>",
|
||||
|
||||
"changing_avatars": "<emoji document_id=5328274090262275771>🔄</emoji> <b>Меняю аватарки...</b>\n<i>⏳ Это займёт {} секунд</i>",
|
||||
|
||||
"was_off": "<emoji document_id=5440381017384822513>❌</emoji> <b>Смена аватарки была выключена!</b>",
|
||||
|
||||
"off": "<b><emoji document_id=5212932275376759608>✅</emoji> Выключил смену аватарки</b>",
|
||||
"completed": "<b><emoji document_id=5212932275376759608>✅</emoji> Готово. Сменил аватарку {} раз за {} секунд/</b>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def avatarl(self, message):
|
||||
"""Смена аватарки по времени"""
|
||||
|
||||
args = utils.get_args_raw(message)
|
||||
|
||||
try:
|
||||
counts, time_c = args.split(" ")
|
||||
counts = int(counts)
|
||||
time_c = int(time_c)
|
||||
except:
|
||||
return await utils.answer(message, self.strings['no_args'].format(self.get_prefix()))
|
||||
|
||||
r = await message.get_reply_message()
|
||||
|
||||
if not r:
|
||||
return await utils.answer(message, self.strings['no_reply'])
|
||||
|
||||
m = await utils.answer(message, self.strings['changing_avatars'].format((time_c * counts)))
|
||||
|
||||
self.m = m
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
file_path = os.path.join(temp_dir, os.path.basename("avatar.jpg"))
|
||||
|
||||
await message.client.download_media(r.media.photo, file_path)
|
||||
|
||||
for i in range(counts):
|
||||
if not self.m:
|
||||
return
|
||||
await self.client(UploadProfilePhotoRequest(file=await self.client.upload_file(file_path)))
|
||||
await asyncio.sleep(time_c)
|
||||
|
||||
self.m = None
|
||||
|
||||
await utils.answer(message, self.strings['completed'].format(counts, (time_c * counts)))
|
||||
|
||||
@loader.command()
|
||||
async def avatarl_stop(self, message):
|
||||
"""Выключить смену аватарки по времени"""
|
||||
|
||||
m = self.m
|
||||
self.m = None
|
||||
|
||||
await utils.answer(m, self.strings['was_off'])
|
||||
await utils.answer(message, self.strings['off'])
|
||||
113
fajox1/famods/banforaskmod.py
Normal file
@@ -0,0 +1,113 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: BanForAskMod
|
||||
# Description: Бан за просьбу дать модулей
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/banforaskmod.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import re
|
||||
import asyncio
|
||||
|
||||
import logging
|
||||
|
||||
from telethon.tl.types import ChatBannedRights
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class BanForAskMod(loader.Module):
|
||||
"""Бан за просьбу дать модулей"""
|
||||
|
||||
strings = {
|
||||
"name": "BanForAskMod",
|
||||
|
||||
"cannot_ban": "<emoji document_id=5440381017384822513>❌</emoji> <b>Не могу забанить пользователя</b>",
|
||||
|
||||
"opening_settings": "<emoji document_id=5334885140147479028>🔄</emoji> <b>Открываю настройку...</b>",
|
||||
}
|
||||
|
||||
|
||||
BANNED_RIGHTS = {
|
||||
"view_messages": False,
|
||||
"send_messages": False,
|
||||
"send_media": False,
|
||||
"send_stickers": False,
|
||||
"send_gifs": False,
|
||||
"send_games": False,
|
||||
"send_inline": False,
|
||||
"send_polls": False,
|
||||
"change_info": False,
|
||||
"invite_users": False,
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"status",
|
||||
False,
|
||||
lambda: "Включить/Выключить бан",
|
||||
validator=loader.validators.Boolean()
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"chats",
|
||||
[],
|
||||
lambda: "Айди чатов где будет работать модуль. Пример: 42348439320",
|
||||
validator=loader.validators.Series(loader.validators.TelegramID())
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"text",
|
||||
"<b>👨⚖️ {user} забанен!\nПричина:</b> <i>Просьба дать модулей</i>",
|
||||
lambda: "Текст бана пользователя",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def bfmsettings(self, message):
|
||||
"""Открыть настройку модуля"""
|
||||
|
||||
m = await utils.answer(message, self.strings['opening_settings'])
|
||||
|
||||
await self.invoke("config", "banforaskmod", message.peer_id)
|
||||
|
||||
await message.delete()
|
||||
|
||||
async def watcher(self, event):
|
||||
if not self.config['status']:
|
||||
return
|
||||
|
||||
chat_id = utils.get_chat_id(event)
|
||||
|
||||
if str(chat_id) not in map(str, [str(c).replace("-100", "") for c in self.config['chats']]):
|
||||
return
|
||||
|
||||
pattern = r'(?:дай(?:те)?(?:\s+моду[лл][еь]?[йя]?| моду[лл][еь]?[йя]?)|моду[лл][еь]?[йя]?\s+дай(?:те)?)'
|
||||
|
||||
match = re.search(pattern, event.raw_text.lower())
|
||||
if not match:
|
||||
return
|
||||
|
||||
try:
|
||||
await self._client.edit_permissions(
|
||||
chat_id,
|
||||
event.from_id,
|
||||
until_date=0,
|
||||
**self.BANNED_RIGHTS,
|
||||
)
|
||||
await utils.answer(event, self.config['text'].format(user=f"<a href='tg://user?id={event.from_id}'>{event.sender.first_name + (event.sender.last_name if event.sender.last_name else '')}</a>"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
await utils.answer(event, self.strings['cannot_ban'])
|
||||
119
fajox1/famods/bigmac.py
Normal file
@@ -0,0 +1,119 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: BigMac
|
||||
# Description: Авто-фарм в @BigMacMetreBot
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/bigmac.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import hikkatl
|
||||
|
||||
import re
|
||||
import random
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class BigMac(loader.Module):
|
||||
"""Авто-фарм в @BigMacMetreBot"""
|
||||
|
||||
strings = {
|
||||
"name": "BigMac",
|
||||
|
||||
"checking_profile": "<b><emoji document_id=5424885441100782420>👀</emoji> Смотрю профиль...</b>",
|
||||
"getting_top": "<b><emoji document_id=5424885441100782420>👀</emoji> Смотрю статистику...</b>",
|
||||
|
||||
"e_on": "<emoji document_id=5239948040575393823>🍔</emoji> <b>Авто-фарм включен!</b>",
|
||||
"e_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Авто-фарм выключен!</b>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
async def _eat(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@BigMacMetreBot") as conv:
|
||||
msg = await conv.send_message("/bigmac")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _getprofme(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@BigMacMetreBot") as conv:
|
||||
msg = await conv.send_message("/profile")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
return f"""<b>{r.text}</b>"""
|
||||
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _gettop(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@BigMacMetreBot") as conv:
|
||||
msg = await conv.send_message("/top")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
return f"<b>{r.text}</b>"
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
@loader.command()
|
||||
async def bigmacs(self, message):
|
||||
"""Включить/выключить авто-фарм"""
|
||||
|
||||
if self.db.get(self.name, "eat_bigmac", False):
|
||||
self.db.set(self.name, "eat_bigmac", False)
|
||||
return await utils.answer(message, self.strings["e_off"])
|
||||
|
||||
self.db.set(self.name, "eat_bigmac", True)
|
||||
|
||||
await utils.answer(message, self.strings["e_on"])
|
||||
|
||||
await self._eat()
|
||||
|
||||
@loader.command()
|
||||
async def bp(self, message):
|
||||
"""Посмотреть свой профиль"""
|
||||
|
||||
await utils.answer(message, self.strings["checking_profile"])
|
||||
|
||||
await utils.answer(message, await self._getprofme())
|
||||
|
||||
@loader.command()
|
||||
async def btop(self, message):
|
||||
"""Посмотреть топ"""
|
||||
|
||||
await utils.answer(message, self.strings["getting_top"])
|
||||
|
||||
await utils.answer(message, await self._gettop())
|
||||
|
||||
@loader.loop(interval=60*60, autostart=True)
|
||||
async def loop(self):
|
||||
if self.db.get(self.name, "eat_bigmac", False):
|
||||
await self._eat()
|
||||
await asyncio.sleep(random.randint(65, 90))
|
||||
351
fajox1/famods/checkhost.py
Normal file
@@ -0,0 +1,351 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: CheckHost
|
||||
# Description: Проверка доступности веб-сайтов, серверов, хостов и IP-адресов с разных геолокаций и тд.
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/checkhost.png?raw=true
|
||||
# requires: aiohttp
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class CheckHost(loader.Module):
|
||||
"""Проверка доступности веб-сайтов, серверов, хостов и IP-адресов с разных геолокаций и тд."""
|
||||
|
||||
strings = {
|
||||
"name": "CheckHost",
|
||||
|
||||
"no_url": "<emoji document_id=5440381017384822513>❌</emoji> <b>Нужно <code>{}{} [адрес]</code></b>",
|
||||
|
||||
"checking_http": "<emoji document_id=6332573220868196043>🕓</emoji> <b>Проверяю доступность...</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"limit",
|
||||
True,
|
||||
lambda: "Включить/Выключить лимит геолокаций в проверке.",
|
||||
validator=loader.validators.Boolean(),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"limit_geo",
|
||||
10,
|
||||
lambda: "Лимит геолокаций.",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def chhttp(self, message):
|
||||
"""Проверить доступность"""
|
||||
|
||||
query = utils.get_args_raw(message)
|
||||
|
||||
if not query:
|
||||
return await utils.answer(message, self.strings['no_url'].format(self.get_prefix(), 'chhttp'))
|
||||
|
||||
await utils.answer(message, self.strings['checking_http'])
|
||||
|
||||
url_cr = f"https://check-host.net/check-http?host={query}"
|
||||
|
||||
if self.config['limit']:
|
||||
url_cr += f"&max_nodes={self.config['limit_geo']}"
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
cr = await session.get(url_cr, headers={'Accept': 'application/json'})
|
||||
create = await cr.json()
|
||||
await asyncio.sleep(10)
|
||||
res = await session.get(f"https://check-host.net/check-result/{create['request_id']}", headers={'Accept': 'application/json'})
|
||||
response = await res.json()
|
||||
|
||||
txt = f"""<b>
|
||||
🌐 Проверка доступности
|
||||
|
||||
📡 IP: <code>{list(response.items())[0][1][0][4]}</code>
|
||||
🔗 Адрес: {query}
|
||||
|
||||
🛜 Доступность
|
||||
</b>
|
||||
"""
|
||||
|
||||
k = 0
|
||||
|
||||
for inf in create['nodes'].items():
|
||||
if self.config['limit']:
|
||||
if k == self.config['limit_geo']:
|
||||
break
|
||||
country = inf[1][1]
|
||||
country_code = inf[1][0]
|
||||
try:
|
||||
txt += self.flags[country_code] + " "
|
||||
except:
|
||||
pass
|
||||
city = inf[1][2]
|
||||
ip = inf[1][3]
|
||||
|
||||
response_code = list(response.items())[k][1][0][3]
|
||||
responsee = list(response.items())[k][1][0][2]
|
||||
response_seconds = list(response.items())[k][1][0][1]
|
||||
|
||||
txt += f"""<b>{country} ({city}) (<code>{ip}</code>)</b>
|
||||
<i>Response code: {response_code} ({responsee}) {response_seconds} сек.</i>
|
||||
"""
|
||||
|
||||
k += 1
|
||||
|
||||
txt += f"\n<b><a href={create['permanent_link']}>🖥 Ссылка на результат в check-host.net</a></b>"
|
||||
|
||||
return await utils.answer(message, txt)
|
||||
|
||||
flags = {
|
||||
"ad": "🇦🇩", # Андорра
|
||||
"ae": "🇦🇪", # ОАЭ
|
||||
"af": "🇦🇫", # Афганистан
|
||||
"ag": "🇦🇬", # Антигуа и Барбуда
|
||||
"ai": "🇦🇮", # Ангилья
|
||||
"al": "🇦🇱", # Албания
|
||||
"am": "🇦🇲", # Армения
|
||||
"ao": "🇦🇴", # Ангола
|
||||
"aq": "🇦🇶", # Антарктика
|
||||
"ar": "🇦🇷", # Аргентина
|
||||
"at": "🇦🇹", # Австрия
|
||||
"au": "🇦🇺", # Австралия
|
||||
"aw": "🇦🇼", # Аруба
|
||||
"ax": "🇦🇽", # Аландские острова
|
||||
"az": "🇦🇿", # Азербайджан
|
||||
"ba": "🇧🇦", # Босния и Герцеговина
|
||||
"bb": "🇧🇧", # Барбадос
|
||||
"bd": "🇧🇩", # Бангладеш
|
||||
"be": "🇧🇪", # Бельгия
|
||||
"bf": "🇧🇫", # Буркина-Фасо
|
||||
"bg": "🇧🇬", # Болгария
|
||||
"bh": "🇧🇭", # Бахрейн
|
||||
"bi": "🇧🇮", # Бурунди
|
||||
"bj": "🇧🇯", # Бенин
|
||||
"bl": "🇧🇱", # Сен-Бартельми
|
||||
"bm": "🇧🇲", # Бермудские острова
|
||||
"bn": "🇧🇳", # Бруней
|
||||
"bo": "🇧🇴", # Боливия
|
||||
"bq": "🇧🇶", # Бонэйр, Синт-Эстатиус и Саба
|
||||
"br": "🇧🇷", # Бразилия
|
||||
"bs": "🇧🇸", # Багамы
|
||||
"bt": "🇧🇹", # Бутан
|
||||
"bv": "🇧🇻", # остров Буве
|
||||
"bw": "🇧🇼", # Ботсвана
|
||||
"by": "🇧🇾", # Беларусь
|
||||
"bz": "🇧🇿", # Белиз
|
||||
"ca": "🇨🇦", # Канада
|
||||
"cc": "🇨🇨", # Кокосовые (Килинг) острова
|
||||
"cd": "🇨🇩", # Конго - Киншаса
|
||||
"cf": "🇨🇫", # Центральноафриканская Республика
|
||||
"cg": "🇨🇬", # Конго - Браззавиль
|
||||
"ch": "🇨🇭", # Швейцария
|
||||
"ci": "🇨🇮", # Кот-д’Ивуар
|
||||
"ck": "🇨🇰", # Острова Кука
|
||||
"cl": "🇨🇱", # Чили
|
||||
"cm": "🇨🇲", # Камерун
|
||||
"cn": "🇨🇳", # Китай
|
||||
"co": "🇨🇴", # Колумбия
|
||||
"cr": "🇨🇷", # Коста-Рика
|
||||
"cu": "🇨🇺", # Куба
|
||||
"cv": "🇨🇻", # Кабо-Верде
|
||||
"cw": "🇨🇼", # Кюрасао
|
||||
"cx": "🇨🇽", # остров Рождества
|
||||
"cy": "🇨🇾", # Кипр
|
||||
"cz": "🇨🇿", # Чехия
|
||||
"de": "🇩🇪", # Германия
|
||||
"dj": "🇩🇯", # Джибути
|
||||
"dk": "🇩🇰", # Дания
|
||||
"dm": "🇩🇲", # Доминика
|
||||
"do": "🇩🇴", # Доминиканская Республика
|
||||
"dz": "🇩🇿", # Алжир
|
||||
"ec": "🇪🇨", # Эквадор
|
||||
"ee": "🇪🇪", # Эстония
|
||||
"eg": "🇪🇬", # Египет
|
||||
"eh": "🇪🇭", # Западная Сахара
|
||||
"er": "🇪🇷", # Эритрея
|
||||
"es": "🇪🇸", # Испания
|
||||
"et": "🇪🇹", # Эфиопия
|
||||
"fi": "🇫🇮", # Финляндия
|
||||
"fj": "🇫🇯", # Фиджи
|
||||
"fk": "🇫🇰", # Фолклендские острова
|
||||
"fm": "🇫🇲", # Микронезия
|
||||
"fo": "🇫🇴", # Фарерские острова
|
||||
"fr": "🇫🇷", # Франция
|
||||
"ga": "🇬🇦", # Габон
|
||||
"gb": "🇬🇧", # Великобритания
|
||||
"gd": "🇬🇩", # Гренада
|
||||
"ge": "🇬🇪", # Грузия
|
||||
"gf": "🇬🇫", # Французская Гвиана
|
||||
"gg": "🇬🇬", # Гернси
|
||||
"gh": "🇬🇭", # Гана
|
||||
"gi": "🇬🇮", # Гибралтар
|
||||
"gl": "🇬🇱", # Гренландия
|
||||
"gm": "🇬🇲", # Гамбия
|
||||
"gn": "🇬🇳", # Гвинея
|
||||
"gp": "🇬🇵", # Гваделупа
|
||||
"gq": "🇬🇶", # Экваториальная Гвинея
|
||||
"gr": "🇬🇷", # Греция
|
||||
"gs": "🇬🇸", # Южная Георгия и Южные Сандвичевы острова
|
||||
"gt": "🇬🇹", # Гватемала
|
||||
"gu": "🇬🇺", # Гуам
|
||||
"gw": "🇬🇼", # Гвинея-Бисау
|
||||
"gy": "🇬🇾", # Гайана
|
||||
"hk": "🇭🇰", # Гонконг
|
||||
"hm": "🇭🇲", # остров Херд и острова Макдональд
|
||||
"hn": "🇭🇳", # Гондурас
|
||||
"hr": "🇭🇷", # Хорватия
|
||||
"ht": "🇭🇹", # Гаити
|
||||
"hu": "🇭🇺", # Венгрия
|
||||
"id": "🇮🇩", # Индонезия
|
||||
"ie": "🇮🇪", # Ирландия
|
||||
"il": "🇮🇱", # Израиль
|
||||
"im": "🇮🇲", # остров Мэн
|
||||
"in": "🇮🇳", # Индия
|
||||
"io": "🇮🇴", # Британская территория в Индийском океане
|
||||
"iq": "🇮🇶", # Ирак
|
||||
"ir": "🇮🇷", # Иран
|
||||
"is": "🇮🇸", # Исландия
|
||||
"it": "🇮🇹", # Италия
|
||||
"je": "🇯🇪", # Джерси
|
||||
"jm": "🇯🇲", # Ямайка
|
||||
"jo": "🇯🇴", # Иордания
|
||||
"jp": "🇯🇵", # Япония
|
||||
"ke": "🇰🇪", # Кения
|
||||
"kg": "🇰🇬", # Киргизия
|
||||
"kh": "🇰🇭", # Камбоджа
|
||||
"ki": "🇰🇮", # Кирибати
|
||||
"km": "🇰🇲", # Коморы
|
||||
"kn": "🇰🇳", # Сент-Китс и Невис
|
||||
"kp": "🇰🇵", # Корейская Народно-Демократическая Республика
|
||||
"kr": "🇰🇷", # Республика Корея
|
||||
"kw": "🇰🇼", # Кувейт
|
||||
"ky": "🇰🇾", # Каймановы острова
|
||||
"kz": "🇰🇿", # Казахстан
|
||||
"la": "🇱🇦", # Лаос
|
||||
"lb": "🇱🇧", # Ливан
|
||||
"lc": "🇱🇨", # Сент-Люсия
|
||||
"li": "🇱🇮", # Лихтенштейн
|
||||
"lk": "🇱🇰", # Шри-Ланка
|
||||
"lr": "🇱🇷", # Либерия
|
||||
"ls": "🇱🇸", # Лесото
|
||||
"lt": "🇱🇹", # Литва
|
||||
"lu": "🇱🇺", # Люксембург
|
||||
"lv": "🇱🇻", # Латвия
|
||||
"ly": "🇱🇾", # Ливия
|
||||
"my": "🇲🇾",
|
||||
"md": "🇲🇩",
|
||||
"mv": "🇲🇻",
|
||||
"mw": "🇲🇼",
|
||||
"mx": "🇲🇽",
|
||||
"my": "🇲🇾",
|
||||
"mz": "🇲🇿",
|
||||
"na": "🇳🇦",
|
||||
"nc": "🇳🇨",
|
||||
"ne": "🇳🇪",
|
||||
"nf": "🇳🇫",
|
||||
"ng": "🇳🇬",
|
||||
"ni": "🇳🇮",
|
||||
"nl": "🇳🇱",
|
||||
"no": "🇳🇴",
|
||||
"np": "🇳🇵",
|
||||
"nr": "🇳🇷",
|
||||
"nu": "🇳🇺",
|
||||
"nz": "🇳🇿",
|
||||
"om": "🇴🇲",
|
||||
"pa": "🇵🇦",
|
||||
"pe": "🇵🇪",
|
||||
"pf": "🇵🇫",
|
||||
"pg": "🇵🇬",
|
||||
"ph": "🇵🇭",
|
||||
"pk": "🇵🇰",
|
||||
"pl": "🇵🇱",
|
||||
"pm": "🇵🇲",
|
||||
"pn": "🇵🇳",
|
||||
"pr": "🇵🇷",
|
||||
"ps": "🇵🇸",
|
||||
"pt": "🇵🇹",
|
||||
"pw": "🇵🇼",
|
||||
"py": "🇵🇾",
|
||||
"qa": "🇶🇦",
|
||||
"re": "🇷🇪",
|
||||
"ro": "🇷🇴",
|
||||
"rs": "🇷🇸",
|
||||
"ru": "🇷🇺",
|
||||
"rw": "🇷🇼",
|
||||
"sa": "🇸🇦",
|
||||
"sb": "🇸🇧",
|
||||
"sc": "🇸🇨",
|
||||
"sd": "🇸🇩",
|
||||
"se": "🇸🇪",
|
||||
"sg": "🇸🇬",
|
||||
"sh": "🇸🇭",
|
||||
"si": "🇸🇮",
|
||||
"sj": "🇸🇯",
|
||||
"sk": "🇸🇰",
|
||||
"sl": "🇸🇱",
|
||||
"sm": "🇸🇲",
|
||||
"sn": "🇸🇳",
|
||||
"so": "🇸🇴",
|
||||
"sr": "🇸🇷",
|
||||
"ss": "🇸🇸",
|
||||
"st": "🇸🇹",
|
||||
"sv": "🇸🇻",
|
||||
"sx": "🇸🇽",
|
||||
"sy": "🇸🇾",
|
||||
"sz": "🇸🇿",
|
||||
"tc": "🇹🇨",
|
||||
"td": "🇹🇩",
|
||||
"tf": "🇹🇫",
|
||||
"tg": "🇹🇬",
|
||||
"th": "🇹🇭",
|
||||
"tj": "🇹🇯",
|
||||
"tk": "🇹🇰",
|
||||
"tl": "🇹🇱",
|
||||
"tm": "🇹🇲",
|
||||
"tn": "🇹🇳",
|
||||
"to": "🇹🇴",
|
||||
"tr": "🇹🇷",
|
||||
"tt": "🇹🇹",
|
||||
"tv": "🇹🇻",
|
||||
"tw": "🇹🇼",
|
||||
"tz": "🇹🇿",
|
||||
"ua": "🇺🇦",
|
||||
"ug": "🇺🇬",
|
||||
"um": "🇺🇲",
|
||||
"us": "🇺🇸",
|
||||
"va": "🇻🇦",
|
||||
"vc": "🇻🇨",
|
||||
"ve": "🇻🇪",
|
||||
"vg": "🇻🇬",
|
||||
"vi": "🇻🇮",
|
||||
"vn": "🇻🇳",
|
||||
"vu": "🇻🇺",
|
||||
"wf": "🇼🇫",
|
||||
"ws": "🇼🇸",
|
||||
"xk": "🇽🇰",
|
||||
"ye": "🇾🇪",
|
||||
"yt": "🇾🇹",
|
||||
"za": "🇿🇦",
|
||||
"zm": "🇿🇲",
|
||||
"zw": "🇿🇼",
|
||||
}
|
||||
86
fajox1/famods/chmodslist.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: CHmodsList
|
||||
# Description: Список каналов с модулями (идея: @codrago)
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/chmodslist.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class CHmodsList(loader.Module):
|
||||
"""Список каналов с модулями (идея: @codrago)"""
|
||||
|
||||
strings = {
|
||||
"name": "CHmodsList",
|
||||
|
||||
"opening_config": "<b><emoji document_id=5327902038720257153>🔄</emoji> Открываю настройки...</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"header_text",
|
||||
"<emoji document_id=5188377234380954537>🌘</emoji> Список каналов с модулями",
|
||||
lambda: "Заголовок текста с каналами модулей",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"channels",
|
||||
[
|
||||
"<emoji document_id=5370547013815376328>😶🌫️</emoji> @hikarimods",
|
||||
"<emoji document_id=5373141891321699086>😎</emoji> @famods",
|
||||
"<emoji document_id=5445096582238181549>🦋</emoji> @morisummermods",
|
||||
"<emoji document_id=5449380056201697322>💚</emoji> @nalinormods",
|
||||
"<emoji document_id=5373026167722876724>🤩</emoji> @AstroModules",
|
||||
"<emoji document_id=5366217837104872614>⭐️</emoji> @shadow_modules",
|
||||
"<emoji document_id=5249042457731024510>💪</emoji> @vsecoder_m",
|
||||
"<emoji document_id=5371037748188683677>☺️</emoji> @mm_mods",
|
||||
"<emoji document_id=5370856741086960948>😈</emoji> @apodiktum_modules",
|
||||
"<emoji document_id=5370947515220761242>😇</emoji> @wilsonmods",
|
||||
"<emoji document_id=5467406098367521267>👑</emoji> @DorotoroMods",
|
||||
"<emoji document_id=5469986291380657759>✌️</emoji> @HikkaFTGmods",
|
||||
"<emoji document_id=5413703918947413540>🐈⬛</emoji> @nercymods",
|
||||
"<emoji document_id=5472091323571903308>🎈</emoji> @hikka_mods",
|
||||
"<emoji document_id=5298799263013151249>😐</emoji> @sqlmerr_m",
|
||||
"<emoji document_id=5296274178725396201>🥰</emoji> @AuroraModules",
|
||||
"<emoji document_id=5429400349377051725>😄</emoji> @BHikkaMods",
|
||||
"<emoji document_id=5355149418620272518>🌟</emoji> @BchModules",
|
||||
],
|
||||
lambda: "Список каналов с модулями",
|
||||
validator=loader.validators.Series()
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def chsettings(self, message):
|
||||
"""Изменить список каналов с модулями"""
|
||||
|
||||
await utils.answer(message, self.strings['opening_config'])
|
||||
|
||||
await self.invoke("config", "chmodslist", message.peer_id)
|
||||
|
||||
await message.delete()
|
||||
|
||||
@loader.command()
|
||||
async def chmods(self, message):
|
||||
"""Посмотреть список каналов с модулями"""
|
||||
|
||||
await utils.answer(message, "<b>{}</b>\n\n<b>{}</b>".format(self.config['header_text'], '\n'.join(self.config['channels'])))
|
||||
53
fajox1/famods/cryptoqr.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: CryptoQR
|
||||
# Description: Создание QR код в стиле CryptoBot
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/cryptoqr.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import hikkatl
|
||||
import asyncio
|
||||
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class CryptoQR(loader.Module):
|
||||
"""Создание QR код в стиле CryptoBot"""
|
||||
|
||||
strings = {
|
||||
"name": "CryptoQR",
|
||||
|
||||
"no_args": "<emoji document_id=5440381017384822513>❌</emoji> <b>Нужно <code>{}cqr [текст/ссылка]</code></b>",
|
||||
|
||||
"creating": "<emoji document_id=5451732530048802485>⏳</emoji> <b>Создаю QRcode...</b>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def cqr(self, message):
|
||||
"""Создать QRcode"""
|
||||
|
||||
q = utils.get_args_raw(message)
|
||||
if not q:
|
||||
return await utils.answer(message, self.strings['no_args'].format(self.get_prefix()))
|
||||
|
||||
m = await utils.answer(message, self.strings['creating'])
|
||||
|
||||
await self.client.send_file(m.peer_id, f"https://qr.crypt.bot/?url={q}", force_document=True, caption=f"<emoji document_id=5431376038628171216>💻</emoji> <b>Текст:</b> <code>{q}</code>")
|
||||
await m.delete()
|
||||
57
fajox1/famods/edmes.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Edmes
|
||||
# Description: Редактирует сообщение с заданим текстом.
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/edmes.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Edmes(loader.Module):
|
||||
"""Редактирует сообщение с заданим текстом."""
|
||||
|
||||
strings = {
|
||||
"name": "Edmes",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"edit_texts",
|
||||
['👋 Привет', '👨 Я', '✏️ Редактирую', '📋 Текст', '❌ Конец.'],
|
||||
lambda: "Текст который будет при редактировании сообщения\nПример: ['👋 Привет', '👨 Я', '✏️ Редактирую', '📋 Текст', '❌ Конец.']",
|
||||
validator=loader.validators.Series()
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"wait_to_edit",
|
||||
1.2,
|
||||
lambda: "Сколько будет ждать секунд перед редактиророванием сообщения.",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def edmsg(self, message):
|
||||
"""Редактировать"""
|
||||
|
||||
for txt in self.config["edit_texts"]:
|
||||
await utils.answer(message, txt)
|
||||
await asyncio.sleep(self.config["wait_to_edit"])
|
||||
262
fajox1/famods/epsilion.py
Normal file
@@ -0,0 +1,262 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Epsilion
|
||||
# Description: Авто-фарм в @EpsilionWarBot
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/epsilion.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import hikkatl
|
||||
|
||||
import re
|
||||
import random
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Epsilion(loader.Module):
|
||||
"""Авто-фарм в @EpsilionWarBot"""
|
||||
|
||||
strings = {
|
||||
"name": "Epsilion",
|
||||
|
||||
"checking_profile": "<b><emoji document_id=5424885441100782420>👀</emoji> Смотрю профиль...</b>",
|
||||
|
||||
"b_on": "<b><emoji document_id=5429633836684157942>⚡️</emoji> Авто-фарм включен!</b>",
|
||||
"b_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Авто-фарм выключен!</b>",
|
||||
|
||||
"bonus_on": "<b><emoji document_id=5429633836684157942>⚡️</emoji> Авто ежедневный бонус включен!</b>",
|
||||
"bonus_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Авто ежедневный бонус выключен!</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"location",
|
||||
"☘️ Фермерские угодья",
|
||||
lambda: "Локация в которую ты по стандарту будешь отправляться. Пример: ☘️ Фермерские угодья",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"start_message",
|
||||
"💖 Ваше здоровье полностью восстановлено",
|
||||
lambda: "Сообщение от бота после которого начинается бой",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
if self.db.get(self.name, "battle", False):
|
||||
asyncio.create_task(self._battle())
|
||||
|
||||
async def _check_hp(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@EpsilionWarBot") as conv:
|
||||
msg = await conv.send_message("/equip")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
matches = re.search(r'\((\d+)/(\d+)\)', r.text)
|
||||
if matches and self.db.get(self.name, "battle", False):
|
||||
current_hp = int(matches.group(1))
|
||||
max_hp = int(matches.group(2))
|
||||
|
||||
above_50_percent = (current_hp / max_hp) > 0.5
|
||||
full_health = current_hp == max_hp
|
||||
|
||||
await asyncio.sleep(3.66767665323)
|
||||
|
||||
if above_50_percent:
|
||||
if "💖 Ваше здоровье восстановлено на 50%" in self.config['start_message']:
|
||||
return asyncio.create_task(self._battle())
|
||||
|
||||
if full_health:
|
||||
if "💖 Ваше здоровье полностью восстановлено" in self.config['start_message']:
|
||||
return asyncio.create_task(self._battle())
|
||||
return
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _change_location(self, conv, location):
|
||||
if location == "default":
|
||||
location = self.config['location']
|
||||
while True:
|
||||
try:
|
||||
msg = await self._client.send_message(776510403, "🗺 Карта")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
await asyncio.sleep(4.4324232432)
|
||||
msg = await self._client.send_message(776510403, location)
|
||||
r = await conv.get_response()
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _battle(self):
|
||||
self.cont = True
|
||||
while self.cont:
|
||||
try:
|
||||
async with self._client.conversation("@EpsilionWarBot") as conv:
|
||||
msg = await conv.send_message("⚔️ Найти врагов")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
cavella = False
|
||||
cavella = True if not r.text == "🔭 Начался поиск противника" else False
|
||||
if "Недостаточно здоровья для сражений" in r.text:
|
||||
return
|
||||
if cavella:
|
||||
await self._change_location(conv, "default")
|
||||
msg = await conv.send_message("⚔️ Найти врагов")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
while self.cont:
|
||||
r = await conv.get_response()
|
||||
if "сбежать" in r.text:
|
||||
await conv.send_message("В зону охоты")
|
||||
self.cont = False
|
||||
await asyncio.sleep(2.82323318089)
|
||||
asyncio.create_task(self._check_hp())
|
||||
return
|
||||
if "Хотел встретить врага, но" in r.text:
|
||||
r = await conv.get_response()
|
||||
pr = []
|
||||
for b in r.reply_markup.rows:
|
||||
for bu in b.buttons:
|
||||
if all(x not in bu.text for x in ["Сбежать", "Пропустить", "(", ")", "[", "]"]):
|
||||
pr.append(bu.text)
|
||||
msg = await conv.send_message(random.choice(pr))
|
||||
r = await conv.get_response()
|
||||
if not "блокировать?" in r.text:
|
||||
if "Тебе не повезло" in r.text:
|
||||
await conv.send_message("💀 Принять участь")
|
||||
if "Ты победил" in r.text:
|
||||
await conv.send_message("✅ Забрать нaграду")
|
||||
if "сбежать" in r.text:
|
||||
await conv.send_message("В зону охоты")
|
||||
else:
|
||||
await conv.send_message("В город")
|
||||
self.cont = False
|
||||
await asyncio.sleep(3.3222444435)
|
||||
asyncio.create_task(self._check_hp())
|
||||
return
|
||||
await asyncio.sleep(3.54354353)
|
||||
pr = []
|
||||
for b in r.reply_markup.rows:
|
||||
for bu in b.buttons:
|
||||
if all(x not in bu.text for x in ["Сбежать", "Пропустить", "(", ")", "[", "]"]):
|
||||
pr.append(bu.text)
|
||||
msg = await conv.send_message(random.choice(pr))
|
||||
r = await conv.get_response()
|
||||
if "сбежать" in r.text:
|
||||
await conv.send_message("В зону охоты")
|
||||
self.cont = False
|
||||
await asyncio.sleep(2.82323318089)
|
||||
asyncio.create_task(self._check_hp())
|
||||
return
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _bonus(self):
|
||||
self.cont = True
|
||||
while self.cont:
|
||||
try:
|
||||
async with self._client.conversation("@EpsilionWarBot") as conv:
|
||||
msg = await conv.send_message("📟 Меню")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
msg = await self._client.send_message(776510403, "🎁 Награды")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
msg = await self._client.send_message(776510403, "🧁 Ежедневная награда")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _getprofme(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@EpsilionWarBot") as conv:
|
||||
msg = await conv.send_message("/equip")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
return f"<b>📁 Профиль</b>\n\n{r.text}"
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
@loader.command()
|
||||
async def eps(self, message):
|
||||
"""Включить/выключить авто-фарм"""
|
||||
|
||||
if self.db.get(self.name, "battle", False):
|
||||
self.cont = False
|
||||
self.db.set(self.name, "battle", False)
|
||||
return await utils.answer(message, self.strings["b_off"])
|
||||
|
||||
self.db.set(self.name, "battle", True)
|
||||
|
||||
await utils.answer(message, self.strings["b_on"])
|
||||
|
||||
await self._battle()
|
||||
|
||||
@loader.command()
|
||||
async def epb(self, message):
|
||||
"""Включить/выключить авто ежедневный бонус"""
|
||||
|
||||
if self.db.get(self.name, "everyday_bonus", False):
|
||||
self.db.set(self.name, "everyday_bonus", False)
|
||||
return await utils.answer(message, self.strings["bonus_off"])
|
||||
|
||||
self.db.set(self.name, "everyday_bonus", True)
|
||||
|
||||
await utils.answer(message, self.strings["bonus_on"])
|
||||
|
||||
await self._bonus()
|
||||
|
||||
@loader.command()
|
||||
async def epp(self, message):
|
||||
"""Посмотреть свой профиль"""
|
||||
|
||||
await utils.answer(message, self.strings["checking_profile"])
|
||||
|
||||
await utils.answer(message, await self._getprofme())
|
||||
|
||||
@loader.loop(interval=60*60*24, autostart=True)
|
||||
async def loop(self):
|
||||
if self.db.get(self.name, "everyday_bonus", False):
|
||||
await self._bonus()
|
||||
await asyncio.sleep(random.randint(65, 90))
|
||||
|
||||
async def watcher(self, event):
|
||||
chat = utils.get_chat_id(event)
|
||||
|
||||
if chat != 776510403:
|
||||
return
|
||||
|
||||
if event.raw_text == self.config['start_message']:
|
||||
if self.db.get(self.name, "battle", False):
|
||||
await asyncio.sleep(random.randint(3, 5))
|
||||
asyncio.create_task(await self._battle())
|
||||
127
fajox1/famods/evalaliases.py
Normal file
@@ -0,0 +1,127 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: EvalAliases
|
||||
# Description: Алиаси для eval
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/evalaliases.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import hikkatl
|
||||
|
||||
import re
|
||||
import random
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class EvalAliases(loader.Module):
|
||||
"""Алиаси для eval"""
|
||||
|
||||
strings = {
|
||||
"name": "EvalAliases",
|
||||
|
||||
"no_args": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нужно </b><code>{}{} {}</code>",
|
||||
|
||||
"already_created": "<emoji document_id=5854929766146118183>❌</emoji> <b>Алиас <code>{}</code> уже существует!</b>",
|
||||
"alias_created": """<emoji document_id=5429633836684157942>⚡️</emoji> <b>Алиас <code>{}</code> создан!</b>
|
||||
|
||||
<i>Используй его с помощью <code>{}v{}</code></i>""",
|
||||
|
||||
"alias_not_found": "<emoji document_id=5854929766146118183>❌</emoji> <b>Алиас <code>{}</code> не найден!</b>",
|
||||
"alias_deleted": "<emoji document_id=5854929766146118183>❌</emoji> <b>Алиас <code>{}</code> удален!</b>",
|
||||
|
||||
"no_aliases": "<emoji document_id=5854929766146118183>❌</emoji> <b>Вы ещё не создали алиасов!</b>",
|
||||
"aliases": """<emoji document_id=4985626654563894116>🖥</emoji> <b>Список алиасов</b>
|
||||
|
||||
{}""",
|
||||
}
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def addea(self, message):
|
||||
"""Добавить алиас"""
|
||||
|
||||
args = utils.get_args_raw(message)
|
||||
try:
|
||||
name, code = args.split(" ")
|
||||
except:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "addea", "[имя] [код]"))
|
||||
|
||||
aliases = self.db.get(self.name, "aliases", [])
|
||||
|
||||
if any(alias['name'] == name for alias in aliases):
|
||||
return await utils.answer(message, self.strings["already_created"].format(name))
|
||||
|
||||
aliases.append({"name": name, "code": code})
|
||||
|
||||
self.db.set(self.name, "aliases", aliases)
|
||||
|
||||
await utils.answer(message, self.strings["alias_created"].format(name, self.get_prefix(), name))
|
||||
|
||||
@loader.command()
|
||||
async def removea(self, message):
|
||||
"""Удалить алиас"""
|
||||
|
||||
name = utils.get_args_raw(message)
|
||||
if not name:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "removea", "[имя]"))
|
||||
|
||||
aliases = self.db.get(self.name, "aliases", [])
|
||||
|
||||
alias_to_remove = next((alias for alias in aliases if alias['name'] == name), None)
|
||||
if not alias_to_remove:
|
||||
return await utils.answer(message, self.strings["alias_not_found"].format(name))
|
||||
|
||||
aliases.remove(alias_to_remove)
|
||||
|
||||
self.db.set(self.name, "aliases", aliases)
|
||||
|
||||
await utils.answer(message, self.strings["alias_deleted"].format(name))
|
||||
|
||||
@loader.command()
|
||||
async def getea(self, message):
|
||||
"""Получить список алиасов для Eval"""
|
||||
|
||||
aliases = self.db.get(self.name, "aliases", [])
|
||||
|
||||
if not aliases:
|
||||
return await utils.answer(message, self.strings["no_aliases"])
|
||||
|
||||
aliases_list = ""
|
||||
for alias in aliases:
|
||||
aliases_list += f"<emoji document_id=4974259868996207180>▫️</emoji> <code>{self.get_prefix()}v{alias['name']}</code>"
|
||||
|
||||
await utils.answer(message, self.strings["aliases"].format(aliases_list))
|
||||
|
||||
async def watcher(self, event):
|
||||
try:
|
||||
if event.from_id != self.tg_id:
|
||||
return
|
||||
except:
|
||||
return
|
||||
if f"{self.get_prefix()}v" not in event.raw_text:
|
||||
return
|
||||
alias_name = event.raw_text.split(f"{self.get_prefix()}v")[1]
|
||||
logger.info(alias_name)
|
||||
aliases = self.db.get(self.name, "aliases", [])
|
||||
|
||||
alias = next((alias for alias in aliases if alias['name'] == alias_name), None)
|
||||
if not alias:
|
||||
return
|
||||
|
||||
await event.delete()
|
||||
await self.invoke("e", alias['code'], event.peer_id)
|
||||
136
fajox1/famods/executor.py
Normal file
@@ -0,0 +1,136 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Executor
|
||||
# Description: Выполнение python кода
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/executor.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
import html
|
||||
import time
|
||||
import html
|
||||
import telethon
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from meval import meval
|
||||
from io import StringIO
|
||||
|
||||
from .. import loader, utils
|
||||
from ..log import HikkaException
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Executor(loader.Module):
|
||||
"""Выполнение python кода"""
|
||||
|
||||
strings = {
|
||||
"name": "Executor",
|
||||
|
||||
"no_code": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть </b><code>{}exec [python код]</code>",
|
||||
|
||||
"executing": "<b><emoji document_id=5332600281970517875>🔄</emoji> Выполняю код...</b>"
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"hide_phone",
|
||||
False,
|
||||
lambda: "Скрывает твой номер телефона при выводе",
|
||||
validator=loader.validators.Boolean()
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
async def cexecute(self, code, message, reply):
|
||||
client = self.client
|
||||
me = await client.get_me()
|
||||
reply = await message.get_reply_message()
|
||||
functions = {
|
||||
"message": message,
|
||||
"client": self._client,
|
||||
"reply": reply,
|
||||
"r": reply,
|
||||
"event": message,
|
||||
"chat": message.to_id,
|
||||
"me": me,
|
||||
"hikkatl": telethon,
|
||||
"telethon": telethon,
|
||||
"utils": utils,
|
||||
"loader": loader,
|
||||
"f": telethon.tl.functions,
|
||||
"c": self._client,
|
||||
"m": message,
|
||||
"lookup": self.lookup,
|
||||
"self": self,
|
||||
"db": self.db,
|
||||
}
|
||||
result = sys.stdout = StringIO()
|
||||
try:
|
||||
res = await meval(
|
||||
code,
|
||||
globals(),
|
||||
**functions,
|
||||
)
|
||||
except:
|
||||
return traceback.format_exc().strip(), None, True
|
||||
return result.getvalue().strip(), res, False
|
||||
|
||||
@loader.command()
|
||||
async def execcmd(self, message):
|
||||
"""Выполнить python код"""
|
||||
|
||||
code = utils.get_args_raw(message)
|
||||
if not code:
|
||||
return await utils.answer(message, self.strings["no_code"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings["executing"])
|
||||
|
||||
reply = await message.get_reply_message()
|
||||
|
||||
start_time = time.perf_counter()
|
||||
result, res, cerr = await self.cexecute(code, message, reply)
|
||||
stop_time = time.perf_counter()
|
||||
|
||||
me = await self.client.get_me()
|
||||
|
||||
result = str(result)
|
||||
res = str(res)
|
||||
|
||||
if self.config['hide_phone']:
|
||||
t_h = "never gonna give you up"
|
||||
|
||||
if result:
|
||||
result = result.replace("+"+me.phone, t_h).replace(me.phone, t_h)
|
||||
if res:
|
||||
res = res.replace("+"+me.phone, t_h).replace(me.phone, t_h)
|
||||
|
||||
if result:
|
||||
result = f"""{'<emoji document_id=6334758581832779720>✅</emoji> Результат' if not cerr else '<emoji document_id=5440381017384822513>🚫</emoji> Ошибка'}:
|
||||
<pre><code class="language-python">{html.escape(result)}</code></pre>
|
||||
"""
|
||||
if res or res == 0 or res == False and res is not None:
|
||||
result += f"""<emoji document_id=6334778871258286021>💾</emoji> Код вернул:
|
||||
<pre><code class="language-python">{res}</code></pre>
|
||||
"""
|
||||
|
||||
return await utils.answer(message, f"""<b>
|
||||
<emoji document_id=5431376038628171216>💻</emoji> Код:
|
||||
<pre><code class="language-python">{html.escape(code)}</code></pre>
|
||||
{result}
|
||||
<emoji document_id=5451732530048802485>⏳</emoji> Выполнен за {round(stop_time - start_time, 5)} секунд</b>""")
|
||||
266
fajox1/famods/fabrika.py
Normal file
@@ -0,0 +1,266 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Fabrika
|
||||
# Description: Авто-фарм в @fabrika
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/fabrika.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import hikkatl
|
||||
|
||||
import random
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Fabrika(loader.Module):
|
||||
"""Авто-фарм в @fabrika"""
|
||||
|
||||
strings = {
|
||||
"name": "Fabrika",
|
||||
|
||||
"checking_profile": "<b><emoji document_id=5424885441100782420>👀</emoji> Смотрю профиль...</b>",
|
||||
|
||||
"searching_team": "<b><emoji document_id=5424885441100782420>👀</emoji> Поиск команды...</b>",
|
||||
"searching_id": "<b><emoji document_id=5424885441100782420>👀</emoji> Поиск пользователя...</b>",
|
||||
|
||||
"no_usid": "<emoji document_id=5019523782004441717>🚫</emoji> <b>Нужно <code>{}{} [айди]</code></b>",
|
||||
|
||||
"no_found_us": "<emoji document_id=5019523782004441717>🚫</emoji> <b>Пользователь не найден!</b>",
|
||||
|
||||
"rw_on": "<b><emoji document_id=5429633836684157942>⚡️</emoji> Отправка рабочих включена!</b>",
|
||||
"rw_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Отправка рабочих выключена!</b>",
|
||||
|
||||
"team_on": "<b><emoji document_id=5429633836684157942>⚡️</emoji> Командная работа включена!</b>",
|
||||
"team_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Командная работа выключена!</b>",
|
||||
|
||||
"bonus_on": "<b><emoji document_id=5852779353330421386>🎁</emoji> Авто-бонус включен!</b>",
|
||||
"bonus_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Авто-бонус выключен!</b>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
if self.db.get(self.name, "slaves_w", False):
|
||||
asyncio.create_task(self._slavesw())
|
||||
|
||||
if self.db.get(self.name, "team", False):
|
||||
asyncio.create_task(self._teamw())
|
||||
|
||||
async def _slavesw(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@fabrika") as conv:
|
||||
msg = await conv.send_message("/factory")
|
||||
r = await conv.get_response()
|
||||
await r.click(1)
|
||||
r = await conv.get_edit()
|
||||
await r.click(0)
|
||||
await r.delete()
|
||||
await msg.delete()
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _teamw(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@fabrika") as conv:
|
||||
msg = await conv.send_message("/start")
|
||||
r = await conv.get_response()
|
||||
await r.click(5)
|
||||
r = await conv.get_edit()
|
||||
await asyncio.sleep(2.61)
|
||||
await r.click(3)
|
||||
r = await conv.get_edit()
|
||||
await asyncio.sleep(3.61)
|
||||
await r.click(0)
|
||||
await r.delete()
|
||||
await msg.delete()
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _takebonus(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@fabrika") as conv:
|
||||
msg = await conv.send_message("/city")
|
||||
r = await conv.get_response()
|
||||
await r.click(1)
|
||||
r = await conv.get_edit()
|
||||
await r.click(0)
|
||||
await r.delete()
|
||||
await msg.delete()
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _getidfb(self, query):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@fabrika") as conv:
|
||||
msg = await conv.send_message("/market")
|
||||
r = await conv.get_response()
|
||||
await r.click(0)
|
||||
msg = await conv.send_message(query)
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
await msg.delete()
|
||||
if r.text != "Пользователь не найден":
|
||||
return f"📁 {r.text}\n\n<b><a href='https://t.me/fabrika?start=su_{r.reply_markup.rows[5].buttons[0].query[4:]}'>🔗 Ссылка</a></b>"
|
||||
return f"🚫 <b>{r.text}</b>"
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _getteamfb(self, query):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@fabrika") as conv:
|
||||
msg = await conv.send_message(f"/start team_{query}")
|
||||
r = await conv.get_response()
|
||||
await r.delete()
|
||||
await msg.delete()
|
||||
if r.text != "Команда не найдена" and r.text != "Неверный формат":
|
||||
return f"{r.text}\n\n<b><a href='https://t.me/fabrika?start=team_{query}'>🔗 Ссылка</a></b>"
|
||||
return f"🚫 <b>{r.text}</b>"
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _getprofme(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@fabrika") as conv:
|
||||
msg = await conv.send_message("/profile")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
return f"📁 {r.text}\n\n<b><a href='https://t.me/fabrika?start=su_{r.reply_markup.rows[4].buttons[0].query[4:]}'>🔗 Ссылка</a></b>"
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
@loader.command()
|
||||
async def fbrw(self, message):
|
||||
"""Включить/выключить автоматически давать работу работникам"""
|
||||
|
||||
if self.db.get(self.name, "slaves_w", False):
|
||||
self.db.set(self.name, "slaves_w", False)
|
||||
return await utils.answer(message, self.strings["rw_off"])
|
||||
|
||||
self.db.set(self.name, "slaves_w", True)
|
||||
|
||||
await utils.answer(message, self.strings["rw_on"])
|
||||
|
||||
await self._slavesw()
|
||||
|
||||
@loader.command()
|
||||
async def fbbonus(self, message):
|
||||
"""Включить/выключить автоматическое получать бонус"""
|
||||
|
||||
if self.db.get(self.name, "autobonus", False):
|
||||
self.db.set(self.name, "autobonus", False)
|
||||
return await utils.answer(message, self.strings["bonus_off"])
|
||||
|
||||
self.db.set(self.name, "autobonus", True)
|
||||
|
||||
await utils.answer(message, self.strings["bonus_on"])
|
||||
|
||||
await self._takebonus()
|
||||
|
||||
@loader.command()
|
||||
async def fbteam(self, message):
|
||||
"""Включить/выключить автоматически отправлятся на комадную работу"""
|
||||
|
||||
if self.db.get(self.name, "team", False):
|
||||
self.db.set(self.name, "team", False)
|
||||
return await utils.answer(message, self.strings["team_off"])
|
||||
|
||||
self.db.set(self.name, "team", True)
|
||||
|
||||
await utils.answer(message, self.strings["team_on"])
|
||||
|
||||
await self._teamw()
|
||||
|
||||
@loader.command()
|
||||
async def sprof(self, message):
|
||||
"""Посмотреть свой профиль"""
|
||||
|
||||
await utils.answer(message, self.strings["checking_profile"])
|
||||
|
||||
await utils.answer(message, await self._getprofme())
|
||||
|
||||
@loader.command()
|
||||
async def sidtg(self, message):
|
||||
"""Посмотреть профиль пользователя через айди в тг"""
|
||||
|
||||
query = utils.get_args_raw(message)
|
||||
|
||||
if not query:
|
||||
return await utils.answer(message, self.strings['no_usid'].format(self.get_prefix(), 'sidtg'))
|
||||
|
||||
await utils.answer(message, self.strings["searching_id"])
|
||||
|
||||
try:
|
||||
q = await self._client.inline_query("@fabrika", f"sup_{query}")
|
||||
await utils.answer(message, f"<b>📁 {q.result.results[0].send_message.message}\n\n<a href='{q.result.results[0].send_message.reply_markup.rows[1].buttons[0].url}'>🔗 Ссылка</a></b>")
|
||||
except (IndexError, AttributeError):
|
||||
return await utils.answer(message, self.strings['no_found_us'])
|
||||
|
||||
@loader.command()
|
||||
async def sidfb(self, message):
|
||||
"""Посмотреть профиль пользователя через айди в боте"""
|
||||
|
||||
query = utils.get_args_raw(message)
|
||||
|
||||
if not query:
|
||||
return await utils.answer(message, self.strings['no_usid'].format(self.get_prefix(), 'sidfb'))
|
||||
|
||||
await utils.answer(message, self.strings["searching_id"])
|
||||
|
||||
await utils.answer(message, await self._getidfb(query))
|
||||
|
||||
@loader.command()
|
||||
async def steamfb(self, message):
|
||||
"""Посмотреть команду через айди"""
|
||||
|
||||
query = utils.get_args_raw(message)
|
||||
|
||||
if not query:
|
||||
return await utils.answer(message, self.strings['no_usid'].format(self.get_prefix(), 'steamfb'))
|
||||
|
||||
await utils.answer(message, self.strings["searching_team"])
|
||||
|
||||
await utils.answer(message, await self._getteamfb(query))
|
||||
|
||||
@loader.loop(interval=60*60*24, autostart=True)
|
||||
async def loop(self):
|
||||
if self.db.get(self.name, "autobonus", False):
|
||||
await self._takebonus()
|
||||
await asyncio.sleep(random.randint(65, 90))
|
||||
|
||||
async def watcher(self, event):
|
||||
chat = utils.get_chat_id(event)
|
||||
|
||||
if chat != 6520131495:
|
||||
return
|
||||
|
||||
if all(keyword in event.raw_text for keyword in ["Ваши рабоч", "законч", "работу"]):
|
||||
if self.db.get(self.name, "slaves_w", False):
|
||||
await self._slavesw()
|
||||
if "Командная работа завершена!" in event.raw_text:
|
||||
if self.db.get(self.name, "team", False):
|
||||
await self._teamw()
|
||||
144
fajox1/famods/fabusiness.py
Normal file
@@ -0,0 +1,144 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: FAbusiness
|
||||
# Description: Бесплатный Telegram business
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/fabusiness.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import time
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from telethon.tl.types import Message, PeerUser
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class FAbusiness(loader.Module):
|
||||
"""Бесплатный Telegram business"""
|
||||
|
||||
strings = {
|
||||
"name": "FAbusiness",
|
||||
|
||||
"loading_cfg": "<b><emoji document_id=5334904192622403796>🔄</emoji> Открываю настройку...</b>",
|
||||
|
||||
"business_on": "<b><emoji document_id=5431376038628171216>💻</emoji> FAbusiness включен!</b>",
|
||||
"business_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> FAbusiness выключен!</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"not_here",
|
||||
False,
|
||||
lambda: "Ты на месте?",
|
||||
validator=loader.validators.Boolean()
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"hello_text",
|
||||
"<b>👋 Привет</b>",
|
||||
lambda: "Текст приветствия",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"not_here_text",
|
||||
"<b>❌ Нет на месте</b>",
|
||||
lambda: "Текст если вас нету на месте",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
self.last_message_time = {}
|
||||
|
||||
async def _check_message_rate(self, user_id: int) -> bool:
|
||||
if user_id in self.last_message_time:
|
||||
last_time = self.last_message_time[user_id]
|
||||
|
||||
if time.time() - last_time < 30:
|
||||
return False
|
||||
|
||||
self.last_message_time[user_id] = time.time()
|
||||
return True
|
||||
|
||||
@loader.command()
|
||||
async def business(self, message):
|
||||
"""Включить/выключить FAbusiness"""
|
||||
|
||||
if self.db.get(self.name, "business", False):
|
||||
self.db.set(self.name, "business", False)
|
||||
return await utils.answer(message, self.strings["business_off"])
|
||||
|
||||
self.db.set(self.name, "business", True)
|
||||
|
||||
await utils.answer(message, self.strings["business_on"])
|
||||
|
||||
@loader.command()
|
||||
async def bsettings(self, message):
|
||||
"""Настройка FAbusiness"""
|
||||
|
||||
msg = await utils.answer(message, self.strings['loading_cfg'])
|
||||
|
||||
await self.invoke("config", "FAbusiness", message.peer_id)
|
||||
|
||||
await msg.delete()
|
||||
|
||||
async def watcher(self, event):
|
||||
if (
|
||||
getattr(event, "out", False)
|
||||
or not isinstance(event, Message)
|
||||
or not isinstance(event.peer_id, PeerUser)
|
||||
or not self.db.get(self.name, "business")
|
||||
or utils.get_chat_id(event)
|
||||
in {
|
||||
1271266957, # @replies
|
||||
777000, # Telegram Notifications
|
||||
self._tg_id, # Self
|
||||
}
|
||||
):
|
||||
return
|
||||
|
||||
try:
|
||||
if (
|
||||
event.sender.bot
|
||||
or event.sender.support
|
||||
or event.sender.contact
|
||||
):
|
||||
return
|
||||
except:
|
||||
pass
|
||||
|
||||
said_users = self.db.get(self.name, "said_users")
|
||||
|
||||
if not said_users:
|
||||
said_users = []
|
||||
|
||||
if not self.config['not_here']:
|
||||
if event.from_id not in said_users:
|
||||
said_users.append(event.from_id)
|
||||
self.db.set(self.name, "said_users", said_users)
|
||||
else:
|
||||
return
|
||||
|
||||
else:
|
||||
if not await self._check_message_rate(event.from_id):
|
||||
return
|
||||
|
||||
if self.config['not_here']:
|
||||
text = self.config['not_here_text']
|
||||
else:
|
||||
text = self.config['hello_text']
|
||||
|
||||
await utils.answer(event, text)
|
||||
77
fajox1/famods/faker.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Faker
|
||||
# Description: Генерация фейк информации
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/faker.png?raw=true
|
||||
# requires: faker
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import faker
|
||||
import random
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Faker(loader.Module):
|
||||
"""Генерация фейк информации"""
|
||||
|
||||
strings = {
|
||||
"name": "Faker",
|
||||
|
||||
"loading": "<b><emoji document_id=5332600281970517875>🔄</emoji> Генерирую информацию...</b>"
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
async def _gen_fake(self):
|
||||
|
||||
fake = faker.Faker()
|
||||
|
||||
name = fake.first_name()
|
||||
surname = fake.last_name()
|
||||
age = random.randint(18, 63)
|
||||
|
||||
country = fake.country()
|
||||
address = fake.address()
|
||||
post_code = fake.zipcode()
|
||||
|
||||
email = fake.email()
|
||||
phone_number = fake.phone_number()
|
||||
|
||||
return f"""<b>
|
||||
🔰 Сгенерированная фейк информация:
|
||||
|
||||
📄 Имя: <code>{name}</code>
|
||||
📄 Фамилия: <code>{surname}</code>
|
||||
💈 Возраст: <code>{age}</code>
|
||||
|
||||
🗺 Страна: <code>{country}</code>
|
||||
🏠 Адрес: <code>{address}</code>
|
||||
📮 Пост-код: <code>{post_code}</code>
|
||||
|
||||
📧 Е-мейл: <code>{email}</code>
|
||||
☎ Номер телефона: <code>{phone_number}</code>
|
||||
</b>"""
|
||||
|
||||
@loader.command()
|
||||
async def gfake(self, message):
|
||||
"""Сгенерировать фейк информацию"""
|
||||
|
||||
await utils.answer(message, self.strings["loading"])
|
||||
|
||||
await utils.answer(message, await self._gen_fake())
|
||||
201
fajox1/famods/famod.py
Normal file
@@ -0,0 +1,201 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: FAmod
|
||||
# Description: Управление вещами, связанными с @FAmods_Bot
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/famod.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import re
|
||||
import shlex
|
||||
import hikkatl
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Famod(loader.Module):
|
||||
"""Управление вещами, связанными с @FAmods_Bot"""
|
||||
|
||||
strings = {
|
||||
"name": "Famod",
|
||||
|
||||
"no_q": "<emoji document_id=5440381017384822513>❌</emoji> <b>Нужно <code>{}{} [запрос]</code></b>",
|
||||
|
||||
"searching_module": "<emoji document_id=5334904192622403796>🔄</emoji> <b>Поиск модуля...</b>",
|
||||
"getting_stats": "<emoji document_id=5328302454226298081>🔄</emoji> <b>Получение статистики...</b>",
|
||||
|
||||
"no_found": "<emoji document_id=5440381017384822513>❌</emoji> <b>Не нашёл такой модуль</b>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
async def _install(self, call, text, url_name):
|
||||
link = f"https://raw.githubusercontent.com/FajoX1/FAmods/main/{url_name}.py"
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(link) as response:
|
||||
code = await response.text()
|
||||
|
||||
requires_comments = re.findall(r'#\s*requires:\s*(.*)', code)
|
||||
all_requires = ''.join(requires_comments).strip()
|
||||
|
||||
if all_requires:
|
||||
requirements_list = shlex.split(all_requires)
|
||||
process = await asyncio.create_subprocess_exec('pip', 'install', *requirements_list)
|
||||
await process.wait()
|
||||
|
||||
loader_m = self.lookup("loader")
|
||||
|
||||
await loader_m.download_and_install(link, None)
|
||||
|
||||
await call.edit(
|
||||
text,
|
||||
reply_markup={
|
||||
"text": (
|
||||
"✅ Установлен"
|
||||
),
|
||||
"data": "empty",
|
||||
}
|
||||
)
|
||||
|
||||
async def _get_stats(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@FAmods_Bot") as conv:
|
||||
msg = await conv.send_message("/stats")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
text = r.text
|
||||
text = text.replace("📊", "<emoji document_id=5431577498364158238>📊</emoji>")
|
||||
text = text.replace("💻", "<emoji document_id=5431376038628171216>💻</emoji>")
|
||||
text = text.replace("🧑💻", "<emoji document_id=5190458330719461749>🧑💻</emoji>")
|
||||
return text
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
@loader.command()
|
||||
async def fmstats(self, message):
|
||||
"""Просмотр статистики"""
|
||||
|
||||
await utils.answer(message, self.strings['getting_stats'])
|
||||
|
||||
stats = await self._get_stats()
|
||||
|
||||
await utils.answer(message, stats)
|
||||
|
||||
@loader.command()
|
||||
async def fmsearch(self, message):
|
||||
"""Поиск модуля"""
|
||||
|
||||
query = utils.get_args_raw(message)
|
||||
|
||||
if not query:
|
||||
return await utils.answer(message, self.strings['no_q'].format(self.get_prefix(), 'fmsearch'))
|
||||
|
||||
await utils.answer(message, self.strings['searching_module'])
|
||||
|
||||
try:
|
||||
q = await self._client.inline_query("@FAmods_Bot", query)
|
||||
result = q.result.results[0]
|
||||
|
||||
text = result.send_message.message
|
||||
|
||||
url_name = str(result.send_message.reply_markup.rows[0].buttons[0].data).split(":")[1]
|
||||
|
||||
except (IndexError, AttributeError):
|
||||
return await utils.answer(message, self.strings['no_found'])
|
||||
|
||||
module_name = text.split(' ')[2]
|
||||
|
||||
text = text.replace(text.split('\n')[0], '<b>' + text.split('\n')[0] + '</b>')
|
||||
text = text.replace("(source)", f"(<a href='https://raw.githubusercontent.com/FajoX1/FAmods/main/{url_name}.py'>source</a>)")
|
||||
text = text.replace(text.split('\n')[1], '<i>' + text.split('\n')[1] + '</i>')
|
||||
text = text.replace(module_name, '<code>' + module_name + '</code>')
|
||||
|
||||
keyboard = [
|
||||
[
|
||||
{
|
||||
"text": "⬇️ Установить",
|
||||
"callback": self._install,
|
||||
"args": (text, url_name),
|
||||
}
|
||||
],
|
||||
]
|
||||
|
||||
await self.inline.form(
|
||||
text=text,
|
||||
message=message,
|
||||
reply_markup=keyboard,
|
||||
force_me=True,
|
||||
)
|
||||
|
||||
@loader.inline_handler(thumb_url="https://cdn-0.emojis.wiki/emoji-pics/apple/magnifying-glass-tilted-right-apple.png")
|
||||
async def famods(self, query):
|
||||
"""Поиск модулей"""
|
||||
|
||||
if not query.args:
|
||||
return [
|
||||
{
|
||||
"title": "Поиск модулей",
|
||||
"description": "Введите запрос для поиска модулей",
|
||||
"message": "🔎 Введи запрос к поиску",
|
||||
"thumb": "https://cdn-0.emojis.wiki/emoji-pics/apple/magnifying-glass-tilted-right-apple.png",
|
||||
}
|
||||
]
|
||||
|
||||
q = await self._client.inline_query("@FAmods_Bot", query.args)
|
||||
mods = q.result.results
|
||||
|
||||
modules = []
|
||||
|
||||
for mod in mods:
|
||||
text = mod.send_message.message
|
||||
|
||||
url_name = str(mod.send_message.reply_markup.rows[0].buttons[0].data).split(":")[1]
|
||||
|
||||
module_name = text.split(' ')[2]
|
||||
module_description = text.split('ℹ️')[1].strip()
|
||||
|
||||
text = text.replace(text.split('\n')[0], '<b>' + text.split('\n')[0] + '</b>')
|
||||
text = text.replace("(source)", f"(<a href='https://raw.githubusercontent.com/FajoX1/FAmods/main/{url_name}.py'>source</a>)")
|
||||
text = text.replace(text.split('\n')[1], '<i>' + text.split('\n')[1] + '</i>')
|
||||
text = text.replace(module_name, '<code>' + module_name + '</code>')
|
||||
|
||||
modules.append({
|
||||
"name": module_name,
|
||||
"description": module_description,
|
||||
"url_name": url_name,
|
||||
"text": text,
|
||||
})
|
||||
|
||||
return [
|
||||
{
|
||||
"title": module['name'],
|
||||
"description": module['description'],
|
||||
"message": self.inline.sanitise_text(
|
||||
module['text']
|
||||
),
|
||||
"thumb": "https://cdn-0.emojis.wiki/emoji-pics/apple/laptop-apple.png",
|
||||
"reply_markup": {
|
||||
"text": "⬇️ Установить",
|
||||
"callback": self._install,
|
||||
"args": (module['text'], module['url_name']),
|
||||
}
|
||||
}
|
||||
for module in modules
|
||||
]
|
||||
69
fajox1/famods/famods_socket.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: FAmodsSocket
|
||||
# Description: Установка модулей через @FAmods_Bot
|
||||
# meta developer: @FAmods
|
||||
# requires: BeautifulSoup4
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import re
|
||||
import shlex
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class FAmodsSocket(loader.Module):
|
||||
"""Установка модулей через @FAmods_Bot"""
|
||||
|
||||
strings = {"name": "FAmodsSocket"}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
async def watcher(self, message):
|
||||
chat = utils.get_chat_id(message)
|
||||
|
||||
if chat != 7283754755:
|
||||
return
|
||||
|
||||
if not message.text.startswith('<a href="https://raw.githubusercontent.com/FajoX1/FAmods/main/'):
|
||||
return
|
||||
|
||||
soup = BeautifulSoup(message.text, 'html.parser')
|
||||
link = soup.a['href']
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(link) as response:
|
||||
code = await response.text()
|
||||
|
||||
requires_comments = re.findall(r'#\s*requires:\s*(.*)', code)
|
||||
all_requires = ''.join(requires_comments).strip()
|
||||
|
||||
if all_requires:
|
||||
await message.delete()
|
||||
requirements_list = shlex.split(all_requires)
|
||||
process = await asyncio.create_subprocess_exec('pip', 'install', *requirements_list)
|
||||
await process.wait()
|
||||
|
||||
loader_m = self.lookup("loader")
|
||||
|
||||
await loader_m.download_and_install(link, None)
|
||||
|
||||
if not all_requires:
|
||||
await message.delete()
|
||||
139
fajox1/famods/freegpt.py
Normal file
@@ -0,0 +1,139 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: FreeGPT
|
||||
# Description: Бесплатный ChatGPT. БЕЗ API. БЕЗ БОТОВ.
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/freegpt.png?raw=true
|
||||
# requires: g4f[all]
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from g4f.client import Client
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class FreeGPT(loader.Module):
|
||||
"""Бесплатный ChatGPT. БЕЗ API. БЕЗ БОТОВ."""
|
||||
|
||||
strings = {
|
||||
"name": "FreeGPT",
|
||||
|
||||
"no_args": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нужно </b><code>{}{} {}</code>",
|
||||
|
||||
"asking_chatgpt": """<emoji document_id=5334675996714999970>🔄</emoji> <b>Спрашиваю ChatGPT...</b>
|
||||
|
||||
<i><emoji document_id=5370869711888194012>👾</emoji> Вы также можете получать ответы в реальном времены с помощью stream_answer в {prefix}cfg FreeGPT</i>""",
|
||||
"creating_image": "<emoji document_id=5334675996714999970>🔄</emoji> <b>Генерирую изображение...</b>",
|
||||
|
||||
"answer_text": """<emoji document_id=5818813162815753343>👨💻</emoji> <b>Вопрос:</b> {question}
|
||||
|
||||
<emoji document_id=5372981976804366741>🤖</emoji> <b>Ответ:</b> {answer}
|
||||
|
||||
<emoji document_id=5424753383741346604>🖥</emoji> <b>Модель</b>: <code>{model}</code>""",
|
||||
|
||||
"photo_caption": """<emoji document_id=5375074927252621134>🖼</emoji> <b>Промпт:</b> <code>{prompt}</code>
|
||||
|
||||
<emoji document_id=5424753383741346604>🖥</emoji> <b>Модель</b>: <code>{model}</code>""",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"model",
|
||||
"gpt-4o",
|
||||
lambda: "Модель ChatGPT",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"image_model",
|
||||
"flux",
|
||||
lambda: "Модель для генерации изображений",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"role",
|
||||
"user",
|
||||
lambda: "Кто ты для ChatGPT?",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"stream_answer",
|
||||
False,
|
||||
lambda: "Ответ в реальном времени",
|
||||
validator=loader.validators.Boolean()
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"stream_answer_delay",
|
||||
1.162131238129,
|
||||
lambda: "Задержка обновлений в реальном времени",
|
||||
),
|
||||
)
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def gf(self, message):
|
||||
"""Задать вопрос к ChatGPT"""
|
||||
q = utils.get_args_raw(message)
|
||||
if not q:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "gf", "[вопрос]"))
|
||||
|
||||
if not self.config['stream_answer']:
|
||||
await utils.answer(message, self.strings['asking_chatgpt'].format(prefix=self.get_prefix()))
|
||||
|
||||
client = Client()
|
||||
response = client.chat.completions.create(
|
||||
model=self.config['model'],
|
||||
messages=[{"role": self.config['role'], "content": q}],
|
||||
stream=False,
|
||||
)
|
||||
|
||||
return await utils.answer(message, self.strings['answer_text'].format(question=q, answer=response.choices[0].message.content.replace("Generated by BLACKBOX.AI, try unlimited chat https://www.blackbox.ai", "").strip(), model=self.config['model']))
|
||||
|
||||
await utils.answer(message, self.strings['answer_text'].format(question=q, answer="<code>Загрузка...</code>", model=self.config['model']))
|
||||
|
||||
client = Client()
|
||||
response = client.chat.completions.create(
|
||||
model=self.config['model'],
|
||||
messages=[{"role": self.config['role'], "content": q}],
|
||||
stream=self.config['stream_answer'],
|
||||
)
|
||||
|
||||
response_text = ""
|
||||
|
||||
for chunk in response:
|
||||
if chunk.choices[0].delta.content:
|
||||
response_text += chunk.choices[0].delta.content
|
||||
await utils.answer(message, self.strings['answer_text'].format(question=q, answer=response_text+"...".replace("Generated by BLACKBOX.AI, try unlimited chat https://www.blackbox.ai", "").strip(), model=self.config['model']))
|
||||
await asyncio.sleep(self.config['stream_answer_delay'])
|
||||
|
||||
return await utils.answer(message, self.strings['answer_text'].format(question=q, answer=response_text.replace("Generated by BLACKBOX.AI, try unlimited chat https://www.blackbox.ai", "").strip(), model=self.config['model']))
|
||||
|
||||
@loader.command()
|
||||
async def gfi(self, message):
|
||||
"""Сгенерировать картинку"""
|
||||
prompt = utils.get_args_raw(message)
|
||||
if not prompt:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "gfi", "[промпт]"))
|
||||
|
||||
m = await utils.answer(message, self.strings['creating_image'])
|
||||
|
||||
client = Client()
|
||||
response = client.images.generate(
|
||||
model=self.config['image_model'],
|
||||
prompt=prompt.replace(" ", "+"),
|
||||
)
|
||||
|
||||
await self.client.send_file(m.peer_id, response.data[0].url, force_document=True, caption=self.strings['photo_caption'].format(prompt=prompt, model=self.config['image_model']))
|
||||
await m.delete()
|
||||
45
fajox1/famods/full.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
wakatime
|
||||
CodeBase64
|
||||
stats
|
||||
faker
|
||||
edmes
|
||||
fun
|
||||
fabrika
|
||||
tonscan
|
||||
telegrapher
|
||||
timer
|
||||
tondns
|
||||
gsearch
|
||||
infoip
|
||||
removebg
|
||||
hetalib
|
||||
phoneinfo
|
||||
checkhost
|
||||
pricefreedom
|
||||
ytsearch
|
||||
autogh
|
||||
epsilion
|
||||
requirements
|
||||
hbotcommand
|
||||
chmodslist
|
||||
xrocket
|
||||
anonsms
|
||||
banforaskmod
|
||||
avachanger
|
||||
giveaways
|
||||
fabusiness
|
||||
famods_socket
|
||||
famod
|
||||
proxy
|
||||
gemini
|
||||
executor
|
||||
cryptoqr
|
||||
vaper
|
||||
freegpt
|
||||
grokai
|
||||
gigachat
|
||||
bigmac
|
||||
evalaliases
|
||||
spotify4ik
|
||||
picme
|
||||
hetsu
|
||||
136
fajox1/famods/fun.py
Normal file
@@ -0,0 +1,136 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Fun
|
||||
# Description: Module for fun
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/fun.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import random
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Fun(loader.Module):
|
||||
"""Module for fun..."""
|
||||
|
||||
strings = {
|
||||
"name": "Fun",
|
||||
|
||||
"no_us": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть .hacku [юзернейм/ник чела]</b>",
|
||||
"no_typing_text": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть .ftype [текст]</b>",
|
||||
|
||||
"hacku_process": "<emoji document_id=6334357625160861194>💻</emoji> <b>Взлом {} в процессе... {}%</b>",
|
||||
"hackedu": "<emoji document_id=5854762571659218443>✅</emoji> <b>{} успешно взломан!</b>",
|
||||
"collecting_info": "<b><emoji document_id=6334778871258286021>💾</emoji> Сохранение информации о {}... {}%</b>",
|
||||
"collected_info": "<emoji document_id=5854762571659218443>✅</emoji> <b>Успешно нашёл и сохранил всю информацию о {}</b>",
|
||||
|
||||
"hackp_process": "<emoji document_id=5370872220149099318>👮♀️</emoji> <b>Взлом пентагона в процессе... {}%</b>",
|
||||
"hackedp": "🟢 <b>Пентагон успешно взломан!</b>",
|
||||
"founding_nlo": "<b><emoji document_id=5371018382181145040>👽</emoji> Поиск секретных данных об НЛО ... {}%</b>",
|
||||
"dino_founded": "<emoji document_id=5460873384390830669>🦖</emoji> <b>Найдены данные о существовании динозавров на земле!</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"TYPING_SYMBOL",
|
||||
"_",
|
||||
lambda: "Печатающий символ в .ftype",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"WAITING_TIME",
|
||||
0.05,
|
||||
lambda: "Сколько секунд будет ждать перед печатю каждой буквы в .ftype",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def hacku(self, message):
|
||||
"""Взлом пользователя"""
|
||||
|
||||
us = utils.get_args_raw(message)
|
||||
if not us:
|
||||
return await utils.answer(message, self.strings["no_us"])
|
||||
|
||||
perc = 0
|
||||
|
||||
while(perc < 100):
|
||||
await utils.answer(message, self.strings["hacku_process"].format(us, perc))
|
||||
perc += random.randint(1, 3)
|
||||
await asyncio.sleep(0.3)
|
||||
|
||||
await utils.answer(message, self.strings["hackedu"].format(us))
|
||||
|
||||
await asyncio.sleep(3)
|
||||
|
||||
perc = 0
|
||||
|
||||
while(perc < 100):
|
||||
await utils.answer(message, self.strings["collecting_info"].format(us, perc))
|
||||
perc += random.randint(1, 5)
|
||||
await asyncio.sleep(0.33)
|
||||
|
||||
await utils.answer(message, self.strings["collected_info"].format(us))
|
||||
|
||||
@loader.command()
|
||||
async def hackp(self, message):
|
||||
"""Взлом пентагона"""
|
||||
perc = 0
|
||||
|
||||
while(perc < 100):
|
||||
await utils.answer(message, self.strings["hackp_process"].format(perc))
|
||||
perc += random.randint(1, 3)
|
||||
await asyncio.sleep(0.3)
|
||||
|
||||
await utils.answer(message, self.strings["hackedp"])
|
||||
|
||||
await asyncio.sleep(3)
|
||||
|
||||
perc = 0
|
||||
|
||||
while(perc < 100):
|
||||
await utils.answer(message, self.strings["founding_nlo"].format(perc))
|
||||
perc += random.randint(1, 5)
|
||||
await asyncio.sleep(0.33)
|
||||
|
||||
await utils.answer(message, self.strings["dino_founded"])
|
||||
|
||||
@loader.command()
|
||||
async def ftype(self, message):
|
||||
"""Печатать текст"""
|
||||
orig_text = utils.get_args_raw(message)
|
||||
if not orig_text:
|
||||
return await utils.answer(message, self.strings["no_typing_text"])
|
||||
|
||||
text = orig_text
|
||||
|
||||
tbp = ""
|
||||
typing_symbol = self.config["TYPING_SYMBOL"]
|
||||
waiting_seconds = self.config["WAITING_TIME"]
|
||||
|
||||
while(tbp != orig_text):
|
||||
await utils.answer(message, tbp + typing_symbol)
|
||||
await asyncio.sleep(waiting_seconds)
|
||||
|
||||
tbp = tbp + text[0]
|
||||
text = text[1:]
|
||||
|
||||
await utils.answer(message, tbp)
|
||||
await asyncio.sleep(waiting_seconds)
|
||||
91
fajox1/famods/gemini.py
Normal file
@@ -0,0 +1,91 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Gemini
|
||||
# Description: Взаимодействие с AI Gemini
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/gemini.png?raw=true
|
||||
# requires: aiohttp openai
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Gemini(loader.Module):
|
||||
"""Взаимодействие с AI Gemini"""
|
||||
|
||||
strings = {
|
||||
"name": "Gemini",
|
||||
|
||||
"no_args": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нужно </b><code>{}{} {}</code>",
|
||||
"no_token": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нету токена! Вставь его в </b><code>{}cfg gemini</code>",
|
||||
|
||||
"asking_gemini": "<emoji document_id=5332518162195816960>🔄</emoji> <b>Спрашиваю Gemini...</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"api_key",
|
||||
None,
|
||||
lambda: "Токен Gemini AI. Получить токен: https://aistudio.google.com/app/apikey",
|
||||
validator=loader.validators.Hidden(loader.validators.String())
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"answer_text",
|
||||
"""[👤](tg://emoji?id=5879770735999717115) **Вопрос:** {question}
|
||||
|
||||
[🤖](tg://emoji?id=5372981976804366741) **Ответ:** {answer}""",
|
||||
lambda: "Текст вывода",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def gemini(self, message):
|
||||
"""Задать вопрос к Gemini"""
|
||||
q = utils.get_args_raw(message)
|
||||
if not q:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "gemini", "[вопрос]"))
|
||||
|
||||
if not self.config['api_key']:
|
||||
return await utils.answer(message, self.strings["no_token"].format(self.get_prefix()))
|
||||
|
||||
m = await utils.answer(message, self.strings['asking_gemini'])
|
||||
|
||||
# Не тупите, ЭТО НЕ CHATGPT, это Gemini.
|
||||
# Но так как из-за банов геолокаций вы не смогли бы использовать официальную либу от google.
|
||||
|
||||
client = OpenAI(
|
||||
api_key=self.config['api_key'],
|
||||
base_url="https://gemini-openai.vercel.app/v1" # Для работы с Gemini а не с ChatGPT
|
||||
)
|
||||
|
||||
chat_completion = client.chat.completions.create(
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": q,
|
||||
}
|
||||
],
|
||||
model="gpt-3.5-turbo",
|
||||
)
|
||||
|
||||
return await m.edit(self.config['answer_text'].format(question=q, answer=chat_completion.choices[0].message.content), parse_mode="markdown")
|
||||
82
fajox1/famods/gigachat.py
Normal file
@@ -0,0 +1,82 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: GigaChat
|
||||
# Description: GigaChat AI. БЕЗ АПИ
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/gigachat.png?raw=true
|
||||
# requires: aiohttp
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import hikkatl
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class GigaChat(loader.Module):
|
||||
"""GigaChat AI. БЕЗ АПИ"""
|
||||
|
||||
strings = {
|
||||
"name": "GigaChat",
|
||||
|
||||
"no_args": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нужно </b><code>{}{} {}</code>",
|
||||
|
||||
"asking_gg": "<emoji document_id=5325787248363314644>🔄</emoji> <b>Спрашиваю GigaChat...</b>",
|
||||
|
||||
"answer": """<emoji document_id=5357555931745893459>🗿</emoji> <b>Ответ:</b> {answer}
|
||||
|
||||
<emoji document_id=5785419053354979106>❔</emoji> <b>Вопрос:</b> {question}""",
|
||||
}
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
self.ggbot = "@GigaChat_Bot"
|
||||
|
||||
try:
|
||||
async with self._client.conversation(self.ggbot) as conv:
|
||||
msg = await conv.send_message("/start")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
except:
|
||||
pass
|
||||
|
||||
async def _ask_ai(self, q):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation(self.ggbot) as conv:
|
||||
msg = await conv.send_message(q)
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
return r.text
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
@loader.command()
|
||||
async def ggchat(self, message):
|
||||
"""Задать вопрос к GigaChat"""
|
||||
q = utils.get_args_raw(message)
|
||||
if not q:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "ggchat", "[вопрос]"))
|
||||
|
||||
await utils.answer(message, self.strings['asking_gg'])
|
||||
|
||||
return await utils.answer(
|
||||
message,
|
||||
self.strings['answer'].format(
|
||||
question=q,
|
||||
answer=await self._ask_ai(q))
|
||||
)
|
||||
85
fajox1/famods/giveaways.py
Normal file
@@ -0,0 +1,85 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Giveaways
|
||||
# Description: Авто-участие в розыгрышах Telegram Premium (Hikka 1.6.4+)
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/giveaways.png?raw=true
|
||||
# scope: hikka_min 1.6.4
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from telethon.tl.types import MessageMediaGiveaway
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
from telethon.tl.functions.channels import JoinChannelRequest
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Giveaways(loader.Module):
|
||||
"""Авто-участие в розыгрышах Telegram Premium"""
|
||||
|
||||
strings = {
|
||||
"name": "Giveaways",
|
||||
|
||||
"giveaways_on": "<b><emoji document_id=5852779353330421386>🎁</emoji> Авто-участие включено!</b>",
|
||||
"giveaways_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Авто-участие выключено!</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"log",
|
||||
True,
|
||||
lambda: "Писать в логи о участии в новом розыгрыше",
|
||||
validator=loader.validators.Boolean()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def gwtg(self, message):
|
||||
"""Включить/выключить автоматическое участие в розыгрышах Telegram Premium"""
|
||||
|
||||
if self.db.get(self.name, "giveaways_status", False):
|
||||
self.db.set(self.name, "giveaways_status", False)
|
||||
return await utils.answer(message, self.strings["giveaways_off"])
|
||||
|
||||
self.db.set(self.name, "giveaways_status", True)
|
||||
|
||||
await utils.answer(message, self.strings["giveaways_on"])
|
||||
|
||||
async def watcher(self, event):
|
||||
try:
|
||||
if not isinstance(event.media, MessageMediaGiveaway):
|
||||
return
|
||||
except:
|
||||
return
|
||||
|
||||
if not self.db.get(self.name, "giveaways_status"):
|
||||
return
|
||||
|
||||
for c_id in event.media.channels:
|
||||
try:
|
||||
channel = await self.client.get_entity(c_id)
|
||||
await self.client(JoinChannelRequest(channel))
|
||||
await asyncio.sleep(2.343982493248932)
|
||||
except:
|
||||
return
|
||||
|
||||
if self.config['log']:
|
||||
logging.info("Joined to new giveaway")
|
||||
97
fajox1/famods/grokai.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: GrokAI
|
||||
# Description: Взаимодействие с Grok AI
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/grokai.png?raw=true
|
||||
# requires: aiohttp openai
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class GrokAI(loader.Module):
|
||||
"""Взаимодействие с Grok AI"""
|
||||
|
||||
strings = {
|
||||
"name": "GrokAI",
|
||||
|
||||
"no_args": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нужно </b><code>{}{} {}</code>",
|
||||
"no_token": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нету токена! Вставь его в </b><code>{}cfg grokai</code>",
|
||||
|
||||
"asking_grok": "<emoji document_id=5325787248363314644>🔄</emoji> <b>Спрашиваю Grok...</b>",
|
||||
|
||||
"answer": """<emoji document_id=5355148941878900494>🌐</emoji> <b>Ответ:</b> {answer}
|
||||
|
||||
<emoji document_id=5785419053354979106>❔</emoji> <b>Вопрос:</b> {question}""",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"api_key",
|
||||
None,
|
||||
lambda: "Токен GrokAI. Получить токен: https://console.x.ai",
|
||||
validator=loader.validators.Hidden(loader.validators.String())
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"model",
|
||||
"grok-beta",
|
||||
lambda: "Модель Grok AI",
|
||||
),
|
||||
)
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def grok(self, message):
|
||||
"""Задать вопрос к Grok"""
|
||||
q = utils.get_args_raw(message)
|
||||
if not q:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "grok", "[вопрос]"))
|
||||
|
||||
if not self.config['api_key']:
|
||||
return await utils.answer(message, self.strings["no_token"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['asking_grok'])
|
||||
|
||||
# Не тупите, ЭТО НЕ CHATGPT, это ГРОК от илона маска.
|
||||
# В документации для грока использовалась либа опенаи, так что меня заставили её юзануть ><
|
||||
|
||||
client = OpenAI(
|
||||
api_key=self.config['api_key'],
|
||||
base_url="https://api.x.ai/v1" # вот теперь это точно грок
|
||||
)
|
||||
|
||||
chat_completion = client.chat.completions.create(
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": q,
|
||||
}
|
||||
],
|
||||
model=self.config['model'],
|
||||
)
|
||||
|
||||
return await utils.answer(
|
||||
message,
|
||||
self.strings['answer'].format(
|
||||
question=q,
|
||||
answer=chat_completion.choices[0].message.content)
|
||||
)
|
||||
136
fajox1/famods/gsearch.py
Normal file
@@ -0,0 +1,136 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Gsearch
|
||||
# Description: Поиск в Google
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/gsearch.png?raw=true
|
||||
# requires: aiohttp google BeautifulSoup4
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import time
|
||||
import asyncio
|
||||
import logging
|
||||
import aiohttp
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from googlesearch import search
|
||||
from urllib.parse import unquote
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Gsearch(loader.Module):
|
||||
"""Поиск в Google"""
|
||||
|
||||
strings = {
|
||||
"name": "Gsearch",
|
||||
|
||||
"no_q": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть </b><code>{}gsearch [запрос]</code>",
|
||||
"no_result": "<b>😕 Ничего не нашёл по этому запросу</b>",
|
||||
|
||||
"searching": "<emoji document_id=5326015457155620929>🔄</emoji> <b>Поиск в google.com...</b>",
|
||||
"searched": """<b>
|
||||
<emoji document_id=5308054573938647180>🔎</emoji> Результаты поиска
|
||||
|
||||
<emoji document_id=5188311512791393083>🔎</emoji> Запрос:</b> <code>{}</code>
|
||||
{}
|
||||
|
||||
<i>{} результатов за {} сек</i>
|
||||
</b>""",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"results",
|
||||
5,
|
||||
lambda: "Количество результатов",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"safe_search",
|
||||
False,
|
||||
lambda: "Безопастный поиск",
|
||||
validator=loader.validators.Boolean(),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"lang",
|
||||
"ru",
|
||||
lambda: "Язык результатов",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"emoji",
|
||||
"<emoji document_id=5098187078693290864>▪️</emoji>",
|
||||
lambda: "Эмодзи в результатах поиска",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"user_agent",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
|
||||
lambda: "Ваш User-Agent"
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"show_title",
|
||||
True,
|
||||
lambda: "Заголовки в результате",
|
||||
validator=loader.validators.Boolean()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def gsearch(self, message):
|
||||
"""Поиск в Google"""
|
||||
|
||||
q = utils.get_args_raw(message)
|
||||
if not q:
|
||||
return await utils.answer(message, self.strings["no_q"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['searching'])
|
||||
|
||||
safe_s = "off"
|
||||
|
||||
if self.config["safe_search"]:
|
||||
safe_s = "on"
|
||||
|
||||
count_s = 0
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
searched_result = ""
|
||||
|
||||
emojii = self.config["emoji"]
|
||||
|
||||
for url in search(q, stop=self.config["results"], lang=self.config["safe_search"], safe=safe_s):
|
||||
if self.config['show_title']:
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url, headers={"User-Agent": self.config['user_agent']}) as response:
|
||||
html = await response.read()
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
title = soup.find('title').text
|
||||
searched_result += f"\n{emojii} <i><a href='{unquote(url)}'>{title}</a></i>"
|
||||
except:
|
||||
searched_result += f"\n{emojii} <i>{unquote(url)}</i>"
|
||||
else:
|
||||
searched_result += f"\n{emojii} <i>{unquote(url)}</i>"
|
||||
count_s += 1
|
||||
|
||||
end_time = time.time()
|
||||
execution_time = end_time - start_time
|
||||
|
||||
if count_s == 0:
|
||||
return await utils.answer(message, self.strings['no_result'])
|
||||
|
||||
return await utils.answer(message, self.strings['searched'].format(q, searched_result, count_s, execution_time))
|
||||
105
fajox1/famods/hbotcommand.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: HbotCommand
|
||||
# Description: Дополнительная команда для твоего inline бота
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/hbotcommand.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import re
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from aiogram import types
|
||||
from .. import loader, utils
|
||||
from ..inline.types import BotInlineMessage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class HbotCommand(loader.Module):
|
||||
"""Дополнительная команда для твоего inline бота"""
|
||||
|
||||
strings = {
|
||||
"name": "HbotCommand",
|
||||
|
||||
"loading_cfg": "<b><emoji document_id=5334904192622403796>🔄</emoji> Открываю настройку...</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"command_text",
|
||||
"<b>Этот текст можно изменить в .cfg HbotCommand</b>",
|
||||
lambda: "Текст сообщения",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"command_image",
|
||||
"https://2.bp.blogspot.com/-wkYFtsM9jf8/XD9CK8-u-rI/AAAAAAAAArI/OWAfpxubCXA4H7sG72YPDEqR8I_yR7AeACKgBGAs/w4096-h2304-c/shooting-star-sunset-anime-horizon-30-4k.jpg",
|
||||
lambda: "Картинка сообщения",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"command_button",
|
||||
"""FAmods, https://t.me/famods""",
|
||||
lambda: "Кнопки сообщения",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"command_name",
|
||||
"/famods",
|
||||
lambda: "Команда для кастомного сообщения",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"command_work",
|
||||
True,
|
||||
lambda: "Кастомное сообщение",
|
||||
validator=loader.validators.Boolean()
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def busername(self, message):
|
||||
"""Посмотреть юзернейм бота"""
|
||||
|
||||
await utils.answer(message, f"<b><emoji document_id=5785175271011259591>🌀</emoji> Username бота: @{self.inline.bot_username}</b>")
|
||||
|
||||
@loader.command()
|
||||
async def bcsettings(self, message):
|
||||
"""Настройка команды бота"""
|
||||
|
||||
msg = await utils.answer(message, self.strings['loading_cfg'])
|
||||
|
||||
await self.invoke("config", "HbotCommand", message.peer_id)
|
||||
|
||||
await msg.delete()
|
||||
|
||||
async def aiogram_watcher(self, message: BotInlineMessage):
|
||||
if self.config['command_work'] and message.text == self.config['command_name']:
|
||||
markup = None
|
||||
if self.config['command_button']:
|
||||
markup = types.InlineKeyboardMarkup()
|
||||
pattern = r'(\w+),\s(https?://\S+)'
|
||||
matches = re.findall(pattern, self.config['command_button'])
|
||||
if matches:
|
||||
title, url = matches[0]
|
||||
button = types.InlineKeyboardButton(text=title, url=url)
|
||||
markup.add(button)
|
||||
|
||||
if self.config['command_image']:
|
||||
return await message.answer_photo(photo=self.config['command_image'], caption=self.config['command_text'], reply_markup=markup)
|
||||
|
||||
await message.answer(
|
||||
self.config['command_text'],
|
||||
reply_markup=markup
|
||||
)
|
||||
135
fajox1/famods/hetalib.py
Normal file
@@ -0,0 +1,135 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: HetaLib
|
||||
# Description: Модуль для работы с heta
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/hetalib.png?raw=true
|
||||
# requires: heta==1.0.2 requests
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import heta
|
||||
import asyncio
|
||||
import requests
|
||||
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class HetaLib(loader.Module):
|
||||
"""Модуль для работы с heta"""
|
||||
|
||||
strings = {
|
||||
"name": "HetaLib",
|
||||
|
||||
"no_q": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть <code>{}hsearch [запрос]</code></b>",
|
||||
"no_hh": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть <code>{}decode_hhash [хэш]</code></b>",
|
||||
"no_repo": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть <code>{}mods_repo [ссылка_на_репозиторий]</code></b>",
|
||||
|
||||
"invalid_hh": "<b>😕 Неверный хэш</b>",
|
||||
"invalid_repo": "<b>😕 Неверный репозиторий модулей</b>",
|
||||
"no_modules_in_repo": "<b>😕 Нету модулей в репозитории</b>",
|
||||
|
||||
"searching": "<emoji document_id=5307710821936145414>🔄</emoji> <b>Поиск модулей...</b>",
|
||||
"receiving_modules": "<emoji document_id=5325792861885570739>🔄</emoji> <b>Получаю модули...</b>",
|
||||
"decoding": "<emoji document_id=5307981757063110606>🔄</emoji> <b>Декодирую хэш...</b>",
|
||||
}
|
||||
|
||||
app_name = "famods Hetalib"
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"search_limit_result",
|
||||
5,
|
||||
lambda: "Максимум результатов поиска будет при поиске модулей.",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def hsearch(self, message):
|
||||
"""Поиск модуля в heta"""
|
||||
|
||||
q = utils.get_args_raw(message)
|
||||
if not q:
|
||||
return await utils.answer(message, self.strings["no_q"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['searching'])
|
||||
|
||||
smods = heta.search(query=q, limit=self.config["search_limit_result"], app_name=self.app_name)
|
||||
|
||||
mtext = f"""<b>⛩ Heta search ⛩
|
||||
|
||||
<emoji document_id=5188311512791393083>🔎</emoji> Запрос: </b><code>{q}</code>
|
||||
|
||||
"""
|
||||
|
||||
for mod in smods:
|
||||
mtext += f"""<b>🖥 {mod['module']['name']} (<a href="{mod['module']['link']}">source</a>) by {mod['module']['dev']}
|
||||
ℹ️ </b><i>{mod['module']['cls_doc']}</i><b>
|
||||
<code>{self.get_prefix()}dlh {mod['module']['hash']}</code>
|
||||
——
|
||||
</b>"""
|
||||
|
||||
await utils.answer(message, mtext)
|
||||
|
||||
@loader.command()
|
||||
async def decode_hhash(self, message):
|
||||
"""Декодировать heta hash"""
|
||||
|
||||
hhash = utils.get_args_raw(message)
|
||||
if not hhash:
|
||||
return await utils.answer(message, self.strings["no_hh"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['decoding'])
|
||||
|
||||
try:
|
||||
hh_info = heta.decode_hash(mhash=hhash, app_name=self.app_name)
|
||||
except requests.exceptions.JSONDecodeError:
|
||||
return await utils.answer(message, self.strings['invalid_hh'])
|
||||
|
||||
await utils.answer(message, f"""<b>
|
||||
🖥 {hh_info['name']} (<a href="{hh_info['link']}">source</a>)
|
||||
<code>{self.get_prefix()}dlh {hhash}</code>
|
||||
</b>""")
|
||||
|
||||
@loader.command()
|
||||
async def mods_repo(self, message):
|
||||
"""Получить модули с репозитория"""
|
||||
|
||||
rep = utils.get_args_raw(message)
|
||||
if not rep:
|
||||
return await utils.answer(message, self.strings["no_repo"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['receiving_modules'])
|
||||
|
||||
try:
|
||||
mods = heta.repo.get_modules(repo=rep)
|
||||
except requests.exceptions.MissingSchema:
|
||||
return await utils.answer(message, self.strings['invalid_repo'])
|
||||
if mods == "no modules":
|
||||
return await utils.answer(message, self.strings['no_modules_in_repo'])
|
||||
|
||||
mdsrepo = f"""
|
||||
<b>🖥 Модули из <a href="{rep}">этого</a> репозитория</b>
|
||||
|
||||
"""
|
||||
|
||||
for mod in mods:
|
||||
mdsrepo += f"<i>{mod['name']}</i> (<i><a href='{mod['link']}'>ссылка</a></i>)\n"
|
||||
|
||||
await utils.answer(message, mdsrepo)
|
||||
207
fajox1/famods/hetsu.py
Normal file
@@ -0,0 +1,207 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Hetsu
|
||||
# Description: Search and install modules easily.
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/hetsu.png?raw=true
|
||||
# requires: aiohttp
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import re
|
||||
import asyncio
|
||||
import aiohttp
|
||||
|
||||
import logging
|
||||
|
||||
from telethon import types, functions
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Hetsu(loader.Module):
|
||||
"""Search and install modules easily."""
|
||||
|
||||
strings = {
|
||||
"name": "Hetsu",
|
||||
|
||||
"no_q": "<emoji document_id=5854929766146118183>❌</emoji> <b>You need to write <code>{}hetsu [query]</code></b>",
|
||||
"inline_no_q": "<emoji document_id=5854929766146118183>❌</emoji> <b>Enter query.</b>",
|
||||
|
||||
"no_modules": "<b>❌ No modules founded.</b>",
|
||||
|
||||
"searching": """<emoji document_id=5404630946563515782>🔍</emoji> <b>Hetsu searching...</b>
|
||||
|
||||
<i><emoji document_id=6028117381690167734>🛡</emoji> Searching above 900+ modules. All modules are safety and clearly moderated.</i>""",
|
||||
|
||||
"module": """<b><emoji document_id=5843843420468024653>⭐️</emoji> Module <code>{module_name}</code></b> {developer}
|
||||
|
||||
<emoji document_id=5843862283964390528>🔖</emoji> <b>Ratio:</b> <code>{ratio}</code>
|
||||
<emoji document_id=5874960879434338403>🔎</emoji> <b>Query:</b> {query}
|
||||
|
||||
<emoji document_id=5879785854284599288>ℹ️</emoji> <b>Description:</b> <i>{description}</i>
|
||||
|
||||
<emoji document_id=5967816500415827773>💻</emoji> <b>Source code:</b> <a href="{link}">click</a>
|
||||
|
||||
<emoji document_id=5899757765743615694>⬇️</emoji> <code>{prefix}dlm {link}</code>""",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"limit",
|
||||
5,
|
||||
lambda: "Max results of modules.",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def hetsucmd(self, message):
|
||||
"""Search module"""
|
||||
|
||||
q = utils.get_args_raw(message)
|
||||
if not q:
|
||||
return await utils.answer(message, self.strings["no_q"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['searching'])
|
||||
|
||||
q_default = q
|
||||
|
||||
if not bool(re.fullmatch(r"[A-Za-z\s\d\W]+", q)):
|
||||
q = await self._client(
|
||||
functions.messages.TranslateTextRequest(
|
||||
peer=False,
|
||||
id=False,
|
||||
text=[
|
||||
types.TextWithEntities(
|
||||
q_default,
|
||||
[],
|
||||
)
|
||||
],
|
||||
to_lang="en",
|
||||
)
|
||||
)
|
||||
|
||||
q = q.result[0].text
|
||||
|
||||
logger.info(q)
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
"https://hetsu.fajox.one/api/search",
|
||||
params={
|
||||
"q": q,
|
||||
"limit": 1,
|
||||
}
|
||||
) as response:
|
||||
modules = (await response.json())['results']
|
||||
|
||||
if not modules:
|
||||
return await utils.answer(message, self.strings['no_modules'])
|
||||
|
||||
module = modules[0]
|
||||
|
||||
module_text = self.strings['module'].format(
|
||||
module_name=module['name'],
|
||||
developer=f"<b>by <code>{module['developer']}</code></b>" if module['developer'] else "",
|
||||
ratio=module['ratio'],
|
||||
query=q_default,
|
||||
description=module['description'] if module['description'] else "No description.",
|
||||
link=module['link'],
|
||||
prefix=self.get_prefix()
|
||||
)
|
||||
|
||||
if module['banner']:
|
||||
return await utils.answer_file(
|
||||
message,
|
||||
module['banner'],
|
||||
caption=module_text,
|
||||
)
|
||||
else:
|
||||
return await utils.answer(
|
||||
message,
|
||||
module_text
|
||||
)
|
||||
|
||||
@loader.inline_handler()
|
||||
async def hetsu(self, query):
|
||||
"""Search module"""
|
||||
|
||||
q = query.args
|
||||
|
||||
if not q:
|
||||
return {
|
||||
"title": "No query",
|
||||
"description": "Enter query for search module",
|
||||
"thumb": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/Flat_cross_icon.svg/1024px-Flat_cross_icon.svg.png",
|
||||
"message": self.strings['inline_no_q'],
|
||||
}
|
||||
|
||||
q_default = q
|
||||
|
||||
if not bool(re.fullmatch(r"[A-Za-z\s\d\W]+", q)):
|
||||
q = await self._client(
|
||||
functions.messages.TranslateTextRequest(
|
||||
peer=False,
|
||||
id=False,
|
||||
text=[
|
||||
types.TextWithEntities(
|
||||
q,
|
||||
[],
|
||||
)
|
||||
],
|
||||
to_lang="en",
|
||||
)
|
||||
)
|
||||
|
||||
q = str(q)
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
"https://hetsu.fajox.one/api/search",
|
||||
params={
|
||||
"q": q,
|
||||
"limit": self.config['limit'],
|
||||
}
|
||||
) as response:
|
||||
modules = (await response.json())['results']
|
||||
|
||||
if not modules:
|
||||
return {
|
||||
"title": "No modules",
|
||||
"description": "No modules founded with this query.",
|
||||
"thumb": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/Flat_cross_icon.svg/1024px-Flat_cross_icon.svg.png",
|
||||
"message": self.strings['no_modules'],
|
||||
}
|
||||
|
||||
answer = []
|
||||
|
||||
for module in modules:
|
||||
answer.append({
|
||||
"title": module['name'],
|
||||
"description": module['description'] if module['description'] else "No description.",
|
||||
"thumb": "https://img.icons8.com/m_outlined/512/FFFFFF/info.png",
|
||||
"message": self.strings['module'].format(
|
||||
module_name=module['name'],
|
||||
developer=f"<b>by <code>{module['developer']}</code></b>" if module['developer'] else "",
|
||||
ratio=module['ratio'],
|
||||
query=q_default,
|
||||
description=module['description'] if module['description'] else "No description.",
|
||||
link=module['link'],
|
||||
prefix=self.get_prefix()
|
||||
),
|
||||
})
|
||||
|
||||
return answer
|
||||
95
fajox1/famods/infoip.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: InfoIP
|
||||
# Description: Информация об IP адресе
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/infoip.png?raw=true
|
||||
# requires: ipinfo
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import ipinfo
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class InfoIP(loader.Module):
|
||||
"""Информация об IP адресе"""
|
||||
|
||||
strings = {
|
||||
"name": "InfoIP",
|
||||
|
||||
"no_ip": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть .ipi [айпи]</b>",
|
||||
"no_token": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нету токена! Поставь его в <code>{}cfg InfoIP</code></b>",
|
||||
"invalid_token": "<b>😕 Неверный токен</b>",
|
||||
"invalid_ip": "<b>😕 Неверный IP</b>",
|
||||
|
||||
"searching_info": "<emoji document_id=5326015457155620929>🔄</emoji> <b>Получаю информацию...</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"api_token",
|
||||
None,
|
||||
lambda: "Токен для работы с API. Взять можно на сайте https://ipinfo.io/account/token",
|
||||
validator=loader.validators.Hidden(loader.validators.String()),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def ipi(self, message):
|
||||
"""Информация об IP"""
|
||||
|
||||
ip = utils.get_args_raw(message)
|
||||
if not ip:
|
||||
return await utils.answer(message, self.strings["no_ip"])
|
||||
|
||||
if not self.config["api_token"]:
|
||||
return await utils.answer(message, self.strings["no_token"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['searching_info'])
|
||||
|
||||
access_token = self.config["api_token"]
|
||||
handler = ipinfo.getHandler(access_token)
|
||||
|
||||
try:
|
||||
info = handler.getDetails(ip)
|
||||
except ipinfo.error.APIError:
|
||||
return await utils.answer(message, self.strings['invalid_token'])
|
||||
except ValueError:
|
||||
return await utils.answer(message, self.strings['invalid_ip'])
|
||||
|
||||
return await utils.answer(message, f"""<b>
|
||||
🌐 Информация об IP
|
||||
|
||||
<emoji document_id=6334617384782923882>📟</emoji> IP: <code>{info.ip}</code>
|
||||
|
||||
⛰ Регион: <code>{info.region}</code>
|
||||
🏙 Город: <code>{info.city}</code>
|
||||
🗺 Страна: {info.country_flag['emoji']} <code>{info.country_name} ({info.country})</code>
|
||||
🗺 Континент: <code>{info.continent['name']} ({info.continent['code']})</code>
|
||||
🧾 Пост-код: <code>{info.postal}</code>
|
||||
|
||||
🏛 Организация: <code>{info.org}</code>
|
||||
|
||||
🪙 Валюта: <code>{info.country_currency['code']} ({info.country_currency['symbol']})</code>
|
||||
|
||||
🏕 Место: <code>{info.loc}</code>
|
||||
<emoji document_id=6334427547228440889>🕒</emoji> Часовой пояс: <code>{info.timezone}</code>
|
||||
</b>""")
|
||||
183
fajox1/famods/phoneinfo.py
Normal file
@@ -0,0 +1,183 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: PhoneInfo
|
||||
# Description: Информация о телефоне
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/phoneinfo.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import time
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class PhoneInfo(loader.Module):
|
||||
"""Информация о телефоне"""
|
||||
|
||||
strings = {
|
||||
"name": "PhoneInfo",
|
||||
|
||||
"no_phone": "<emoji document_id=5440381017384822513>❌</emoji> <b>Нужно <code>{}{} [название телефона]</code></b>",
|
||||
|
||||
"searching": "<emoji document_id=5334904192622403796>🔄</emoji> <b>Поиск телефона...</b>",
|
||||
"searching_info": "<emoji document_id=5334904192622403796>🔄</emoji> <b>Поиск информации о телефоне...</b>",
|
||||
|
||||
"no_found": "<emoji document_id=5440381017384822513>❌</emoji> <b>Не нашёл такой телефон</b>",
|
||||
|
||||
"cameras_txt": "<emoji document_id=5787632606484893320>📷</emoji> Cameras:",
|
||||
"software_txt": "<emoji document_id=6334742097748298141>🖥</emoji> Software:",
|
||||
"hardware_txt": "<emoji document_id=6334778871258286021>💾</emoji> Hardware:",
|
||||
}
|
||||
|
||||
cameras_t = "Cameras:"
|
||||
software_t = "Software:"
|
||||
hardware_t = "Hardware:"
|
||||
|
||||
opt_bt = "\nspecs prepared with ❤️ by @gsmarbot"
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"search_limit",
|
||||
5,
|
||||
lambda: "Лимит результатов в поиске",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
async def _get_phone_info(self, query):
|
||||
try:
|
||||
q = await self._client.inline_query("@gsmarbot", query)
|
||||
result = q.result.results[1]
|
||||
|
||||
message = result.send_message.message
|
||||
message = message.replace(self.opt_bt, "")
|
||||
message = message.replace(self.cameras_t, self.strings['cameras_txt'])
|
||||
message = message.replace(self.software_t, self.strings['software_txt'])
|
||||
message = message.replace(self.hardware_t, self.strings['hardware_txt'])
|
||||
|
||||
url = result.send_message.reply_markup.rows[0].buttons[0].url
|
||||
|
||||
return {'info': message, 'link': url}
|
||||
except (IndexError, AttributeError):
|
||||
return {'info': "no found"}
|
||||
|
||||
async def _get_phones(self, query):
|
||||
try:
|
||||
q = await self._client.inline_query("@gsmarbot", query)
|
||||
q.result.results[1]
|
||||
|
||||
results = q.result.results
|
||||
|
||||
limit = self.config["search_limit"]
|
||||
|
||||
c_res = 0
|
||||
|
||||
resultss = []
|
||||
|
||||
for result in results:
|
||||
|
||||
if c_res == limit:
|
||||
break
|
||||
|
||||
resultss.append({"name": result.send_message.message.split('\n')[0], "link": result.send_message.reply_markup.rows[0].buttons[0].url})
|
||||
|
||||
c_res += 1
|
||||
|
||||
return {'result': resultss, 'count_result_res': c_res}
|
||||
except (IndexError, AttributeError):
|
||||
return {"result": "no found"}
|
||||
|
||||
@loader.command()
|
||||
async def pnsearch(self, message):
|
||||
"""Поиск телефона"""
|
||||
|
||||
query = utils.get_args_raw(message)
|
||||
|
||||
if not query:
|
||||
return await utils.answer(message, self.strings['no_phone'].format(self.get_prefix(), 'pnsearch'))
|
||||
|
||||
await utils.answer(message, self.strings['searching'])
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
phones = await self._get_phones(query)
|
||||
|
||||
if phones['result'] == "no found":
|
||||
return await utils.answer(message, self.strings['no_found'])
|
||||
|
||||
txt = f"""<b>
|
||||
<emoji document_id=5407025283456835913>📱</emoji> Результаты поиска
|
||||
|
||||
<emoji document_id=5188311512791393083>🔎</emoji> Запрос: <code>{query}</code>
|
||||
|
||||
</b>"""
|
||||
|
||||
for phone in phones['result']:
|
||||
txt += f"<b>📱 {phone['name']}\n🔗 {phone['link']}</b>\n\n"
|
||||
|
||||
end_time = time.time()
|
||||
execution_time = end_time - start_time
|
||||
|
||||
txt += f"<i>{phones['count_result_res']} результатов за {execution_time} сек</i>"
|
||||
|
||||
return await utils.answer(message, txt)
|
||||
|
||||
@loader.command()
|
||||
async def pninfo(self, message):
|
||||
"""Получить информацию о телефоне"""
|
||||
|
||||
query = utils.get_args_raw(message)
|
||||
|
||||
if not query:
|
||||
return await utils.answer(message, self.strings['no_phone'].format(self.get_prefix(), 'pninfo'))
|
||||
|
||||
await utils.answer(message, self.strings['searching_info'])
|
||||
|
||||
info = await self._get_phone_info(query)
|
||||
|
||||
if info['info'] == "no found":
|
||||
return await utils.answer(message, self.strings['no_found'])
|
||||
|
||||
txt = f"""<b>
|
||||
<emoji document_id=5407025283456835913>📱</emoji> Информация о телефоне
|
||||
|
||||
<emoji document_id=5188311512791393083>🔎</emoji> Запрос: <code>{query}</code>
|
||||
|
||||
<emoji document_id=5406809207947142040>📲</emoji> {info['info']}
|
||||
</b>"""
|
||||
|
||||
keyboard = [
|
||||
[
|
||||
{
|
||||
"text": "Полная информация о телефоне",
|
||||
"url": info['link'],
|
||||
}
|
||||
],
|
||||
]
|
||||
|
||||
# try:
|
||||
await self.inline.form(
|
||||
text=txt,
|
||||
message=message,
|
||||
reply_markup=keyboard,
|
||||
force_me=True,
|
||||
)
|
||||
# except Exception as e:
|
||||
# txt += f"<b><a href='{link}'><emoji document_id=6334638004920911460>ℹ️</emoji> Полная информация о телефоне</a></b>"
|
||||
# return await utils.answer(message, txt)
|
||||
83
fajox1/famods/picme.py
Normal file
@@ -0,0 +1,83 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: PicMe
|
||||
# Description: Кринж модуль
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/picme.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import hikkatl
|
||||
|
||||
import random
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class PicMe(loader.Module):
|
||||
"""Кринж модуль"""
|
||||
|
||||
strings = {
|
||||
"name": "PicMe",
|
||||
|
||||
"p_on": "<b><emoji document_id=5373189724372474575>😘</emoji> Режим пикми включен!</b>",
|
||||
"p_off": "<b><emoji document_id=5370881342659631698>😢</emoji> Режим пикми выключен!</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"emojies",
|
||||
["😊", "😂", "🎉", "👍", "🔥", "❤️", "🥳", "😎"],
|
||||
lambda: "Эмодзы для вставки в текст",
|
||||
validator=loader.validators.Series()
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"signs",
|
||||
["!", "!!"],
|
||||
lambda: "Знаки для вставки в текст",
|
||||
validator=loader.validators.Series()
|
||||
),
|
||||
)
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def picme(self, message):
|
||||
"""Включить/выключить режим пикми"""
|
||||
|
||||
if self.db.get(self.name, "picme", False):
|
||||
self.db.set(self.name, "picme", False)
|
||||
return await utils.answer(message, self.strings["p_off"])
|
||||
|
||||
self.db.set(self.name, "picme", True)
|
||||
|
||||
await utils.answer(message, self.strings["p_on"])
|
||||
|
||||
async def watcher(self, event):
|
||||
try:
|
||||
if event.from_id != self.tg_id:
|
||||
return
|
||||
except:
|
||||
return
|
||||
if not self.db.get(self.name, "picme", False):
|
||||
return
|
||||
|
||||
words = event.raw_text.split()
|
||||
modified_text = " ".join(
|
||||
word + (f" {random.choice(self.config['emojies'])}" if random.random() > 0.5 else "")
|
||||
for word in words
|
||||
)
|
||||
await event.edit(text=modified_text+random.choice(self.config['signs']))
|
||||
150
fajox1/famods/pricefreedom.py
Normal file
@@ -0,0 +1,150 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: PriceFreedom
|
||||
# Description: Автоматизированная работа с @rabstvo_game_bot
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/pricefreedom.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import hikkatl
|
||||
|
||||
import re
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class PriceFreedom(loader.Module):
|
||||
"""Автоматизированная работа с @rabstvo_game_bot"""
|
||||
|
||||
strings = {
|
||||
"name": "PriceFreedom",
|
||||
|
||||
"checking_profile": "<b><emoji document_id=5424885441100782420>👀</emoji> Смотрю профиль...</b>",
|
||||
"searching_us": "<b><emoji document_id=5424885441100782420>👀</emoji> Поиск пользователя...</b>",
|
||||
|
||||
"no_usid": "<emoji document_id=5019523782004441717>🚫</emoji> <b>Нужно <code>{}{} [айди]</code></b>",
|
||||
|
||||
"promo_on": "<b><emoji document_id=5852779353330421386>🎁</emoji> Авто-промо включен!</b>\n\n<i>Что бы получать промокоды вы должны быть подписаним <a href='{}'>здесь</a>.</i>",
|
||||
"promo_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Авто-промо выключен!</b>",
|
||||
}
|
||||
|
||||
promo_channel = "https://t.me/+1eLPUMl51a5mOWQy"
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
# while True:
|
||||
# try:
|
||||
# async with self._client.conversation("@rabstvo_game_bot") as conv:
|
||||
# msg = await conv.send_message("/start 44088")
|
||||
# r = await conv.get_response()
|
||||
# await msg.delete()
|
||||
# await r.delete()
|
||||
# break
|
||||
# except hikkatl.errors.common.AlreadyInConversationError:
|
||||
# await asyncio.sleep(5.67)
|
||||
# except Exception:
|
||||
# break
|
||||
|
||||
async def _active_promo(self, prom):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@rabstvo_game_bot") as conv:
|
||||
msg = await conv.send_message(f"/start {prom}")
|
||||
r = await conv.get_response()
|
||||
await r.delete()
|
||||
r = await conv.get_response()
|
||||
await r.delete()
|
||||
await msg.delete()
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _spfus_s(self, query):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@rabstvo_game_bot") as conv:
|
||||
msg = await conv.send_message(f"/start {query}")
|
||||
r = await conv.get_response()
|
||||
await r.delete()
|
||||
await msg.delete()
|
||||
o = await conv.get_response()
|
||||
await o.delete()
|
||||
if not "Зарабатывает:" in r.text:
|
||||
return f"🚫 <b>Пользователь не найден!</b>"
|
||||
return f"<b>👾 Информация о игроке\n\n{r.text}</b>\n\n<b><a href='https://t.me/rabstvo_game_bot?start={query}'>🔗 Ссылка</a></b>"
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _getprofme(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@rabstvo_game_bot") as conv:
|
||||
msg = await conv.send_message("🫅 Профиль")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
|
||||
pattern = r'#(\w+).*?Баланс:'
|
||||
result = re.search(pattern, r.text, re.DOTALL)
|
||||
my_id = result.group(1)
|
||||
|
||||
return f"<b>📁 Ваши данные\n\n{r.text}\n\n<a href='https://t.me/rabstvo_game_bot?start={my_id}'>🔗 Ссылка</a></b>"
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
@loader.command()
|
||||
async def pfpromo(self, message):
|
||||
"""Включить/выключить автоматически активирование промокода"""
|
||||
|
||||
if self.db.get(self.name, "promo_s", False):
|
||||
self.db.set(self.name, "promo_s", False)
|
||||
return await utils.answer(message, self.strings["promo_off"])
|
||||
|
||||
self.db.set(self.name, "promo_s", True)
|
||||
|
||||
await utils.answer(message, self.strings["promo_on"].format(self.promo_channel))
|
||||
|
||||
@loader.command()
|
||||
async def spfus(self, message):
|
||||
"""Посмотреть профиль пользователя"""
|
||||
|
||||
query = utils.get_args_raw(message)
|
||||
|
||||
if not query:
|
||||
return await utils.answer(message, self.strings['no_usid'].format(self.get_prefix(), 'spfus'))
|
||||
|
||||
await utils.answer(message, self.strings["searching_us"])
|
||||
|
||||
await utils.answer(message, await self._spfus_s(query))
|
||||
|
||||
@loader.command()
|
||||
async def spfme(self, message):
|
||||
"""Посмотреть свой профиль"""
|
||||
|
||||
await utils.answer(message, self.strings["checking_profile"])
|
||||
|
||||
await utils.answer(message, await self._getprofme())
|
||||
|
||||
async def watcher(self, event):
|
||||
chat = utils.get_chat_id(event)
|
||||
|
||||
if chat != 1726199153:
|
||||
return
|
||||
|
||||
if all(keyword in event.raw_text for keyword in ["ПРОМОКОД", "Активируй"]):
|
||||
if self.db.get(self.name, "promo_s", False):
|
||||
await self._active_promo(event.reply_markup.rows[0].buttons[0].url.split("?start=")[1])
|
||||
139
fajox1/famods/proxy.py
Normal file
@@ -0,0 +1,139 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Proxy
|
||||
# Description: Работа с прокси
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/proxy.png?raw=true
|
||||
# requires: aiohttp
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import random
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Proxy(loader.Module):
|
||||
"""Работа с прокси"""
|
||||
|
||||
strings = {
|
||||
"name": "Proxy",
|
||||
|
||||
"not_work_proxy": "<emoji document_id=5854929766146118183>❌</emoji> <b>Прокси не работает</b>",
|
||||
"no_args": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нужно быть </b><code>{}{} {}</code>",
|
||||
"no_link": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нету ссылки на прокси! Вставь её в </b><code>{}cfg proxy</code>",
|
||||
"incorrect_protocol": "<b>😕 Неверный протокол или его нету в нашей базе!</b>",
|
||||
"update_link": "<b>😕 Истек срок работы ссылки! Обнови её в </b><code>{}cfg proxy</code>",
|
||||
|
||||
"searching_proxy": "<emoji document_id=5332518162195816960>🔄</emoji> <b>Ищю прокси...</b>",
|
||||
"checking_proxy": "<emoji document_id=5332518162195816960>🔄</emoji> <b>Проверяю прокси...</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"link",
|
||||
None,
|
||||
lambda: "Ссылка для получение прокси. Взять можно в https://advanced.name/ru/freeproxy",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"check_work",
|
||||
True,
|
||||
lambda: "Проверять работу прокси?",
|
||||
validator=loader.validators.Boolean(),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def gproxy(self, message):
|
||||
"""Получить рандомное прокси"""
|
||||
protocol = utils.get_args_raw(message)
|
||||
if not protocol:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "gproxy", "[протокол]"))
|
||||
|
||||
if not self.config["link"]:
|
||||
return await utils.answer(message, self.strings["no_link"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['searching_proxy'])
|
||||
|
||||
proxys_link = self.config["link"]
|
||||
|
||||
params = {"type": protocol}
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(proxys_link) as res:
|
||||
proxys_default = await res.text()
|
||||
if not proxys_default:
|
||||
return await utils.answer(message, self.strings['update_link'].format(self.get_prefix()))
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(proxys_link, params=params) as res:
|
||||
proxys = await res.text()
|
||||
|
||||
if proxys_default == proxys:
|
||||
return await utils.answer(message, self.strings['incorrect_protocol'])
|
||||
|
||||
proxys = proxys.split("\n")
|
||||
|
||||
while True:
|
||||
proxy = random.choice(proxys)
|
||||
proxy_ip = proxy.split(":")[0]
|
||||
proxy_port = proxy.split(":")[1]
|
||||
|
||||
if not self.config['check_work']:
|
||||
break
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get('http://example.com', proxy=f"{protocol}://{proxy_ip}:{proxy_port}", timeout=5) as res:
|
||||
if res.status == 200:
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
return await utils.answer(message, f"""<b>🌐 Рандомное прокси
|
||||
|
||||
💾 Протокол: <code>{protocol}</code>
|
||||
🖥 IP: <code>{proxy_ip}</code>
|
||||
📟 Порт: <code>{proxy_port}</code>
|
||||
|
||||
{'<emoji document_id=5215191209131123104>💎</emoji> Модуль проверяет работоспособность прокси!' if self.config['check_work'] else ''}</b>""")
|
||||
|
||||
@loader.command()
|
||||
async def wproxy(self, message):
|
||||
"""Проверить работу прокси"""
|
||||
try:
|
||||
protocol, ip_port = utils.get_args_raw(message).split(" ")
|
||||
ip_port = ip_port.split(":")
|
||||
ip = ip_port[0]
|
||||
port = ip_port[1]
|
||||
except:
|
||||
return await utils.answer(message, self.strings["no_args"].format(self.get_prefix(), "wproxy", "[протокол] [айпи:порт]"))
|
||||
|
||||
await utils.answer(message, self.strings['checking_proxy'])
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get('http://example.com', proxy=f"{protocol}://{ip}:{port}", timeout=5) as res:
|
||||
if res.status == 200:
|
||||
return await utils.answer(message, f"""<emoji document_id=6334758581832779720>✅</emoji> <b>Прокси работает!</b>""")
|
||||
else:
|
||||
return await utils.answer(message, self.strings['not_work_proxy'])
|
||||
except:
|
||||
return await utils.answer(message, self.strings['not_work_proxy'])
|
||||
109
fajox1/famods/removebg.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: RemoveBG
|
||||
# Description: Убрать фон из изображения
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/removebg.png?raw=true
|
||||
# requires: aiohttp
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import asyncio
|
||||
import tempfile
|
||||
import logging
|
||||
import aiohttp
|
||||
|
||||
from aiohttp import FormData
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class RemoveBG(loader.Module):
|
||||
"""Убрать фон из изображения"""
|
||||
|
||||
strings = {
|
||||
"name": "RemoveBG",
|
||||
|
||||
"must_be_forced": "<emoji document_id=5854929766146118183>❌</emoji> <b>Фото не должно быть сжатым!</b>",
|
||||
"no_photo": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нужно ответить на фото!</b>",
|
||||
"no_token": "<emoji document_id=5854929766146118183>❌</emoji> <b>Нету токена! Поставь его в <code>{}cfg RemoveBG</code></b>",
|
||||
"invalid_token": "<b>😕 Неверный токен</b>",
|
||||
"only_photo": "<b>😕 Удалять фон можно только с фото (.png, .jpg, .jpeg)</b>",
|
||||
|
||||
"removing_bg": "<emoji document_id=5326015457155620929>🔄</emoji> <b>Удаление фона...</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"api_token",
|
||||
None,
|
||||
lambda: "Токен для работы с API. Взять можно на сайте https://www.remove.bg/dashboard#api-key",
|
||||
validator=loader.validators.Hidden(loader.validators.String()),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def removebg(self, message):
|
||||
"""Убрать фон из изображения"""
|
||||
|
||||
reply = await message.get_reply_message()
|
||||
if not reply:
|
||||
return await utils.answer(message, self.strings("no_photo"))
|
||||
|
||||
try:
|
||||
if not any(ext in reply.file.name for ext in [".png", ".jpg", ".jpeg"]):
|
||||
return await utils.answer(message, self.strings['only_photo'])
|
||||
except TypeError:
|
||||
return await utils.answer(message, self.strings['must_be_forced'])
|
||||
|
||||
if not self.config["api_token"]:
|
||||
return await utils.answer(message, self.strings["no_token"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings['removing_bg'])
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
try:
|
||||
file_path = os.path.join(temp_dir, reply.file.name)
|
||||
await reply.download_media(file_path)
|
||||
except TypeError:
|
||||
return await utils.answer(message, self.strings['must_be_forced'])
|
||||
|
||||
access_token = self.config["api_token"]
|
||||
async with aiohttp.ClientSession() as session:
|
||||
form_data = FormData()
|
||||
form_data.add_field('image_file', open(file_path, 'rb'))
|
||||
form_data.add_field('size', 'auto')
|
||||
|
||||
async with session.post(
|
||||
'https://api.remove.bg/v1.0/removebg',
|
||||
headers={'X-Api-Key': access_token},
|
||||
data=form_data
|
||||
) as res:
|
||||
try:
|
||||
response_json = await res.json()
|
||||
if 'errors' in response_json and response_json['errors'][0]['title'] == "API Key invalid":
|
||||
return await utils.answer(message, self.strings['invalid_token'])
|
||||
except Exception as e:
|
||||
print(f"Error processing response: {e}")
|
||||
|
||||
file_name = f"famods-no-bg-{os.path.splitext(reply.file.name)[0]}.png"
|
||||
with open(os.path.join(temp_dir, file_name), 'wb') as out:
|
||||
out.write(await res.read())
|
||||
|
||||
await message.client.send_file(message.chat_id, os.path.join(temp_dir, file_name), force_document=True)
|
||||
await message.delete()
|
||||
206
fajox1/famods/requirements.py
Normal file
@@ -0,0 +1,206 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Requirements
|
||||
# Description: Работа с pip пакетами в модуле
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/requirements.png?raw=true
|
||||
# requires: heta
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import re
|
||||
import os
|
||||
import heta
|
||||
import shlex
|
||||
import asyncio
|
||||
import logging
|
||||
import tempfile
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Requirements(loader.Module):
|
||||
"""Работа с pip пакетами в модуле"""
|
||||
|
||||
strings = {
|
||||
"name": "Requirements",
|
||||
|
||||
"no_dep": "<emoji document_id=5440381017384822513>❌</emoji> <b>В модуле нету зависимостей</b>",
|
||||
"only_url_or_hash": "<emoji document_id=5440381017384822513>❌</emoji> <b>Только ссылка на модуль, или heta hash</b>",
|
||||
|
||||
"no_file_and_link": "<emoji document_id=5440381017384822513>❌</emoji> <b>Нужно ответить на файл или <code>{}{} [ссылка или heta hash]</code></b>",
|
||||
|
||||
"search_deps": "<emoji document_id=6332573220868196043>🕓</emoji> <b>Ищу зависимости...</b>",
|
||||
"install_deps": "<emoji document_id=6332573220868196043>🕓</emoji> <b>Установка зависимостей:</b>\n\n<code>{}</code>",
|
||||
"uninstall_deps": "<emoji document_id=6332573220868196043>🕓</emoji> <b>Удаление зависимостей:</b>\n\n<code>{}</code>",
|
||||
|
||||
"installed": "<emoji document_id=5021905410089550576>✅</emoji> <b>Успешно установил зависимости:</b>\n\n<code>{}</code>\n\n{}",
|
||||
"uninstalled": "<emoji document_id=5021905410089550576>✅</emoji> <b>Успешно удалил зависимости:</b>\n\n<code>{}</code>",
|
||||
|
||||
"requirements": "<emoji document_id=5294080842006538030>⚙️</emoji> <b>Зависимости:</b>\n\n<code>{}</code>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"auto_dlm",
|
||||
False,
|
||||
lambda: "Автоматическая загрузка модуля после установки зависимостей",
|
||||
validator=loader.validators.Boolean()
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def dldeps(self, message):
|
||||
"""Установить pip пакеты с модуля"""
|
||||
|
||||
link = utils.get_args_raw(message)
|
||||
|
||||
r = await message.get_reply_message()
|
||||
|
||||
if not link and not r:
|
||||
return await utils.answer(message, self.strings['no_file_and_link'].format(self.get_prefix(), "dldeps"))
|
||||
|
||||
await utils.answer(message, self.strings['search_deps'])
|
||||
|
||||
_heta = False
|
||||
|
||||
if link:
|
||||
try:
|
||||
code = heta.module.get_code(link)
|
||||
except:
|
||||
try:
|
||||
m = heta.decode_hash(link)
|
||||
code = heta.module.get_code(m['link'])
|
||||
_heta = True
|
||||
except:
|
||||
return await utils.answer(message, self.strings['only_url_or_hash'])
|
||||
else:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
file_path = os.path.join(temp_dir, r.file.name)
|
||||
await r.download_media(file_path)
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
code = f.read()
|
||||
|
||||
requires_comments = re.findall(r'#\s*requires:\s*(.*)', code)
|
||||
|
||||
all_requires = ''.join(requires_comments).strip()
|
||||
|
||||
if not all_requires:
|
||||
return await utils.answer(message, self.strings['no_dep'])
|
||||
|
||||
await utils.answer(message, self.strings['install_deps'].format(all_requires.replace(" ", "\n")))
|
||||
|
||||
requirements_list = shlex.split(all_requires)
|
||||
|
||||
process = await asyncio.create_subprocess_exec('pip', 'install', *requirements_list)
|
||||
await process.wait()
|
||||
|
||||
await utils.answer(message, self.strings['installed'].format(all_requires.replace(" ", "\n"), ((f"<b><emoji document_id=6334353510582191829>⬇️</emoji> Установите модуль:\n<code>{self.get_prefix()}{'dlh' if _heta else 'dlmod'} {link}</code></b>" if link else f"<b><emoji document_id=6334353510582191829>⬇️</emoji> Установите модуль через <code>{self.get_prefix()}lm</code> (с ответом на файл модуля)</b>") if not self.config['auto_dlm'] else "")))
|
||||
|
||||
if not self.config['auto_dlm']:
|
||||
return
|
||||
|
||||
if _heta:
|
||||
return await self.invoke("dlh", link, message.peer_id)
|
||||
if link:
|
||||
return await self.invoke("dlmod", link, message.peer_id)
|
||||
else:
|
||||
rr = await r.reply("ㅤ")
|
||||
return await self.invoke("loadmod", message=rr, edit=True)
|
||||
|
||||
@loader.command()
|
||||
async def uldeps(self, message):
|
||||
"""Удалить pip пакеты с модуля"""
|
||||
|
||||
link = utils.get_args_raw(message)
|
||||
|
||||
r = await message.get_reply_message()
|
||||
|
||||
if not link and not r:
|
||||
return await utils.answer(message, self.strings['no_file_and_link'].format(self.get_prefix(), "uldeps"))
|
||||
|
||||
await utils.answer(message, self.strings['search_deps'])
|
||||
|
||||
if link:
|
||||
try:
|
||||
code = heta.module.get_code(link)
|
||||
except:
|
||||
try:
|
||||
m = heta.decode_hash(link)
|
||||
code = heta.module.get_code(m['link'])
|
||||
except:
|
||||
return await utils.answer(message, self.strings['only_url_or_hash'])
|
||||
else:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
file_path = os.path.join(temp_dir, r.file.name)
|
||||
await r.download_media(file_path)
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
code = f.read()
|
||||
|
||||
requires_comments = re.findall(r'#\s*requires:\s*(.*)', code)
|
||||
|
||||
all_requires = ''.join(requires_comments).strip()
|
||||
|
||||
if not all_requires:
|
||||
return await utils.answer(message, self.strings['no_dep'])
|
||||
|
||||
await utils.answer(message, self.strings['uninstall_deps'].format(all_requires.replace(" ", "\n")))
|
||||
|
||||
requirements_list = shlex.split(all_requires)
|
||||
|
||||
process = await asyncio.create_subprocess_exec('pip', 'uninstall', *requirements_list, '-y')
|
||||
await process.wait()
|
||||
|
||||
return await utils.answer(message, self.strings['uninstalled'].format(all_requires.replace(" ", "\n")))
|
||||
|
||||
@loader.command()
|
||||
async def deps(self, message):
|
||||
"""Посмотреть pip пакеты с модуля"""
|
||||
|
||||
link = utils.get_args_raw(message)
|
||||
|
||||
r = await message.get_reply_message()
|
||||
|
||||
if not link and not r:
|
||||
return await utils.answer(message, self.strings['no_file_and_link'].format(self.get_prefix(), "deps"))
|
||||
|
||||
await utils.answer(message, self.strings['search_deps'])
|
||||
|
||||
if link:
|
||||
try:
|
||||
code = heta.module.get_code(link)
|
||||
except:
|
||||
try:
|
||||
m = heta.decode_hash(link)
|
||||
code = heta.module.get_code(m['link'])
|
||||
except:
|
||||
return await utils.answer(message, self.strings['only_url_or_hash'])
|
||||
else:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
file_path = os.path.join(temp_dir, r.file.name)
|
||||
await r.download_media(file_path)
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
code = f.read()
|
||||
|
||||
requires_comments = re.findall(r'#\s*requires:\s*(.*)', code)
|
||||
|
||||
all_requires = ''.join(requires_comments).strip()
|
||||
|
||||
if not all_requires:
|
||||
return await utils.answer(message, self.strings['no_dep'])
|
||||
|
||||
return await utils.answer(message, self.strings['requirements'].format(all_requires.replace(" ", "\n"), f"<b><emoji document_id=6334353510582191829>⬇️</emoji> Модуль: <code>{link}</code>"))
|
||||
771
fajox1/famods/spotify4ik.py
Normal file
@@ -0,0 +1,771 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Spotify4ik
|
||||
# Description: Слушай музыку в Spotify
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/spotify4ik.png?raw=true
|
||||
# requires: spotipy yt-dlp aiohttp
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import asyncio
|
||||
import logging
|
||||
import tempfile
|
||||
import aiohttp
|
||||
|
||||
import yt_dlp
|
||||
import spotipy
|
||||
|
||||
from telethon import types
|
||||
from telethon.tl.types import ChatAdminRights
|
||||
from telethon.tl.functions.channels import EditTitleRequest, EditAdminRequest
|
||||
from telethon.tl.functions.account import UpdateProfileRequest
|
||||
|
||||
from aiogram.types import InputFile
|
||||
from aiogram.types.inline_keyboard import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Spotify4ik(loader.Module):
|
||||
"""Слушай музыку в Spotify"""
|
||||
|
||||
strings = {
|
||||
"name": "Spotify4ik",
|
||||
|
||||
"go_auth_link": """<b><emoji document_id=5271604874419647061>🔗</emoji> Ссылка для авторизации создана!
|
||||
|
||||
🔐 Перейди по <a href='{}'>этой ссылке</a>.
|
||||
|
||||
✏️ Потом введи: <code>{}spcode свой_auth_token</code></b>""",
|
||||
|
||||
"need_client_tokens": """<emoji document_id=5472308992514464048>🔐</emoji> <b>Создай приложение по <a href="https://developer.spotify.com/dashboard">этой ссылке</a></b>
|
||||
|
||||
<emoji document_id=5467890025217661107>‼️</emoji> <b>Важно:</b> redirect_url приложения должен быть <code>https://sp.fajox.one</code>
|
||||
|
||||
<b><emoji document_id=5330115548900501467>🔑</emoji> Заполни <code>client_id</code> и <code>client_secret</code> в <code>{}cfg Spotify4ik</code></b>
|
||||
|
||||
<b><emoji document_id=5431376038628171216>💻</emoji> И снова напиши <code>{}spauth</code></b>""",
|
||||
|
||||
"no_auth_token": "<emoji document_id=5854929766146118183>❌</emoji> <b>Авторизуйся в свой аккаунт через <code>{}spauth</code></b>",
|
||||
"no_song_playing": "<emoji document_id=5854929766146118183>❌</emoji> <b>Сейчас ничего не играет.</b>",
|
||||
"no_code": "<emoji document_id=5854929766146118183>❌</emoji> <b>Должно быть <code>{}spcode код_авторизации</code></b>",
|
||||
"code_installed": """<b><emoji document_id=5330115548900501467>🔑</emoji> Код авторизации установлен!</b>
|
||||
|
||||
<emoji document_id=5870794890006237381>🎶</emoji> <b>Наслаждайся музыкой!</b>""",
|
||||
|
||||
"auth_error": "<emoji document_id=5854929766146118183>❌</emoji> <b>Ошибка авторизации:</b> <code>{}</code>",
|
||||
"unexpected_error": "<emoji document_id=5854929766146118183>❌</emoji> <b>Произошла ошибка:</b> <code>{}</code>",
|
||||
|
||||
"track_pause": "<b><emoji document_id=6334755820168808080>⏸️</emoji> Трек поставлен на паузу.</b>",
|
||||
"track_play": "<b><emoji document_id=5938473438468378529>🎶</emoji> Играю...</b>",
|
||||
|
||||
"track_loading": "<emoji document_id=5334768819548200731>💻</emoji> <b>Загружаю трек...</b>",
|
||||
|
||||
"music_bio_disabled": "<b><emoji document_id=5188621441926438751>🎵</emoji> Стрим музыки в био выключен</b>",
|
||||
"music_bio_enabled": "<b><emoji document_id=5188621441926438751>🎵</emoji> Стрим музыки в био включен</b>",
|
||||
|
||||
"track_skipped": "<b><emoji document_id=5188621441926438751>🎵</emoji> Следующий трек...</b>",
|
||||
|
||||
"track_repeat": "<b><emoji document_id=6334550748365325938>🔁</emoji> Трек будет повторяться.</b>",
|
||||
"track_norepeat": "<b><emoji document_id=6334550748365325938>🔁</emoji> Трек не будет повторяться.</b>",
|
||||
|
||||
"track_liked": f"<b><emoji document_id=5287454910059654880>❤️</emoji> Трек добавлен в избранное!</b>",
|
||||
|
||||
"channel_music_bio_disabled": "<b><emoji document_id=5188621441926438751>🎵</emoji> Стрим музыки в био канале выключен!</b>",
|
||||
|
||||
"channel_music_bio_enabled": """<b><emoji document_id=5188621441926438751>🎵</emoji> Стрим музыки в био канале включен!</b>
|
||||
|
||||
<b><emoji document_id=5787544344906959608>ℹ️</emoji> Инструкция:</b>
|
||||
1. Создай публичный канал (название любое)
|
||||
2. Добавь канал в профиль
|
||||
3. Добавь <code>@username</code> канала в config (<code>.cfg Spotify4ik</code> → <code>channel</code>)
|
||||
4. Готово"""
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"client_id",
|
||||
None,
|
||||
lambda: "Айди приложения, Получить: https://developer.spotify.com/dashboard",
|
||||
validator=loader.validators.Hidden(loader.validators.String()),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"client_secret",
|
||||
None,
|
||||
lambda: "Секретный ключ приложения, Получить: https://developer.spotify.com/dashboard",
|
||||
validator=loader.validators.Hidden(loader.validators.String()),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"auth_token",
|
||||
None,
|
||||
lambda: "Токен для авторизации",
|
||||
validator=loader.validators.Hidden(loader.validators.String()),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"refresh_token",
|
||||
None,
|
||||
lambda: "Токен для обновления",
|
||||
validator=loader.validators.Hidden(loader.validators.String()),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"bio_text",
|
||||
"🎵 {track_name} - {artist_name}",
|
||||
lambda: "Текст био с текущим треком",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"scopes",
|
||||
(
|
||||
"user-read-playback-state playlist-read-private playlist-read-collaborative"
|
||||
" app-remote-control user-modify-playback-state user-library-modify"
|
||||
" user-library-read"
|
||||
),
|
||||
lambda: "Список разрешений",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"use_ytdl",
|
||||
False,
|
||||
lambda: "Для загрузки файла песни использовать yt-dl",
|
||||
validator=loader.validators.Boolean(),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"channel",
|
||||
None,
|
||||
lambda: "Канал для показа текущей музыки в био"
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"stream_upload_track",
|
||||
False,
|
||||
lambda: "Загрузка трека в био канал для стриминга",
|
||||
validator=loader.validators.Boolean(),
|
||||
)
|
||||
)
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
self.current_track = ""
|
||||
|
||||
self.musicdl = await self.import_lib(
|
||||
"https://famods.fajox.one/assets/musicdl.py",
|
||||
suspend_on_error=True,
|
||||
)
|
||||
|
||||
async def _create_stream_messages(self, channel):
|
||||
await self.client(
|
||||
EditAdminRequest(
|
||||
channel=channel,
|
||||
user_id=self.inline.bot_username,
|
||||
admin_rights=ChatAdminRights(
|
||||
change_info=True,
|
||||
post_messages=True,
|
||||
edit_messages=True,
|
||||
delete_messages=True
|
||||
),
|
||||
rank="spot"
|
||||
)
|
||||
)
|
||||
|
||||
audio_path = await self.musicdl.dl("The Lost Soul Down - NBSPLV", only_document=True)
|
||||
|
||||
if self.config['stream_upload_track']:
|
||||
first_message = await self.client.send_file(
|
||||
channel,
|
||||
audio_path,
|
||||
caption="first_message",
|
||||
attributes=[
|
||||
types.DocumentAttributeAudio(
|
||||
duration=0,
|
||||
title="famods",
|
||||
performer=""
|
||||
)
|
||||
],
|
||||
thumb="https://github.com/fajox1/famods/raw/main/assets/photo_2025-03-26_17-03-56.jpg"
|
||||
)
|
||||
else:
|
||||
first_message = await self.client.send_message(
|
||||
channel,
|
||||
"first_message",
|
||||
)
|
||||
display_message = await self.inline.bot.send_message(int("-100"+str(channel.id)), "display_message")
|
||||
|
||||
self.db.set(self.name, 'stream_upload_message', self.config['stream_upload_track'])
|
||||
|
||||
me = await self.client.get_me()
|
||||
me_mention = f"@{me.username}" if me.username else (f"@{me.usernames[0].username}" if me.usernames else me.first_name)
|
||||
|
||||
try:
|
||||
await self.inline.bot.set_chat_description(
|
||||
chat_id=int("-100"+str(channel.id)),
|
||||
description=f"Current track playing for the {me_mention}"
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
self.db.set(self.name, 'stream_channel_data', {
|
||||
"first_message": first_message.id,
|
||||
"display_message": display_message.message_id,
|
||||
"channel": self.config['channel']
|
||||
})
|
||||
|
||||
@loader.command()
|
||||
async def spauth(self, message):
|
||||
"""Войти в свой аккаунт"""
|
||||
if not self.config['client_id'] or not self.config['client_secret']:
|
||||
return await utils.answer(message, self.strings['need_client_tokens'].format(self.get_prefix(), self.get_prefix()))
|
||||
|
||||
sp_oauth = spotipy.oauth2.SpotifyOAuth(
|
||||
client_id=self.config['client_id'],
|
||||
client_secret=self.config['client_secret'],
|
||||
redirect_uri="https://sp.fajox.one",
|
||||
scope=self.config['scopes']
|
||||
)
|
||||
|
||||
auth_url = sp_oauth.get_authorize_url()
|
||||
|
||||
await utils.answer(message, self.strings['go_auth_link'].format(auth_url, self.get_prefix()))
|
||||
|
||||
@loader.command()
|
||||
async def spcode(self, message):
|
||||
"""Ввести код авторизации"""
|
||||
if not self.config['client_id'] or not self.config['client_secret']:
|
||||
return await utils.answer(message, self.strings['need_client_tokens'].format(self.get_prefix()))
|
||||
code = utils.get_args_raw(message)
|
||||
if not code:
|
||||
return await utils.answer(message, self.strings['no_code'].format(self.get_prefix()))
|
||||
|
||||
sp_oauth = spotipy.oauth2.SpotifyOAuth(
|
||||
client_id=self.config['client_id'],
|
||||
client_secret=self.config['client_secret'],
|
||||
redirect_uri="https://sp.fajox.one",
|
||||
scope=self.config['scopes']
|
||||
)
|
||||
token_info = sp_oauth.get_access_token(code)
|
||||
self.config['auth_token'] = token_info['access_token']
|
||||
self.config['refresh_token'] = token_info['refresh_token']
|
||||
|
||||
try:
|
||||
sp = spotipy.Spotify(auth=token_info['access_token'])
|
||||
current_playback = sp.current_playback()
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except Exception as e:
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
|
||||
await utils.answer(message, self.strings['code_installed'])
|
||||
|
||||
@loader.command()
|
||||
async def sppause(self, message):
|
||||
"""Поставить на паузу текущий трек"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
|
||||
try:
|
||||
sp.pause_playback()
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "Restriction violated" in str(e):
|
||||
return await utils.answer(message, self.strings['track_pause'])
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
await utils.answer(message, self.strings['track_pause'])
|
||||
|
||||
@loader.command()
|
||||
async def spplay(self, message):
|
||||
"""Воспроизвести текущий трек"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
|
||||
try:
|
||||
sp.start_playback()
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "Restriction violated" in str(e):
|
||||
return await utils.answer(message, self.strings['track_play'])
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
await utils.answer(message, self.strings['track_play'])
|
||||
|
||||
@loader.command()
|
||||
async def spbegin(self, message):
|
||||
"""Включить текущий трек с начала"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
|
||||
try:
|
||||
current_playback = sp.current_playback()
|
||||
if not current_playback or not current_playback.get('item'):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
|
||||
track_uri = current_playback['item']['uri']
|
||||
sp.start_playback(uris=[track_uri])
|
||||
sp.seek_track(0)
|
||||
await utils.answer(message, self.strings['track_play'])
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
|
||||
@loader.command()
|
||||
async def spback(self, message):
|
||||
"""Включить предыдущий трек"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
|
||||
try:
|
||||
sp.previous_track()
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
|
||||
await utils.answer(message, self.strings['track_play'])
|
||||
|
||||
@loader.command()
|
||||
async def spnext(self, message):
|
||||
"""Включить следующий трек"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
|
||||
try:
|
||||
sp.next_track()
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "Restriction violated" in str(e):
|
||||
return await utils.answer(message, self.strings['track_play'])
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
await utils.answer(message, self.strings['track_skipped'])
|
||||
|
||||
@loader.command()
|
||||
async def spbio(self, message):
|
||||
"""Включить/выключить стрим текущего трека в био"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
if self.db.get(self.name, "bio_change", False):
|
||||
self.db.set(self.name, 'bio_change', False)
|
||||
return await utils.answer(message, self.strings['music_bio_disabled'])
|
||||
|
||||
self.db.set(self.name, 'bio_change', True)
|
||||
await utils.answer(message, self.strings['music_bio_enabled'])
|
||||
|
||||
@loader.command()
|
||||
async def spbiochannel(self, message):
|
||||
"""Включить/выключить стрим текущего трека в канале в био"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
if self.db.get(self.name, "channel_bio_change", False):
|
||||
self.db.set(self.name, 'channel_bio_change', False)
|
||||
return await utils.answer(message, self.strings['channel_music_bio_disabled'])
|
||||
|
||||
self.db.set(self.name, 'channel_bio_change', True)
|
||||
await utils.answer(message, self.strings['channel_music_bio_enabled'])
|
||||
|
||||
@loader.command()
|
||||
async def splike(self, message):
|
||||
"""Лайкнуть текущий трек"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
|
||||
try:
|
||||
current_playback = sp.current_playback()
|
||||
if not current_playback or not current_playback.get('item'):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
|
||||
track_id = current_playback['item']['id']
|
||||
sp.current_user_saved_tracks_add([track_id])
|
||||
await utils.answer(message, self.strings['track_liked'])
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
|
||||
@loader.command()
|
||||
async def sprepeat(self, message):
|
||||
"""Повторить текущий трек"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
|
||||
try:
|
||||
current_playback = sp.current_playback()
|
||||
if not current_playback or not current_playback.get('item'):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
|
||||
sp.repeat("track")
|
||||
await utils.answer(message, self.strings['track_repeat'])
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
|
||||
@loader.command()
|
||||
async def spnorepeat(self, message):
|
||||
"""Перестать повторять текущий трек"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
|
||||
try:
|
||||
current_playback = sp.current_playback()
|
||||
if not current_playback or not current_playback.get('item'):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
|
||||
sp.repeat("no")
|
||||
await utils.answer(message, self.strings['track_norepeat'])
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
|
||||
@loader.command()
|
||||
async def spnow(self, message):
|
||||
"""Текущий трек"""
|
||||
if not self.config['auth_token']:
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
|
||||
try:
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
current_playback = sp.current_playback()
|
||||
|
||||
if not current_playback or not current_playback.get('item'):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
|
||||
await utils.answer(message, self.strings['track_loading'])
|
||||
|
||||
track = current_playback['item']
|
||||
track_name = track.get('name', 'Unknown Track')
|
||||
artist_name = track['artists'][0].get('name', 'Unknown Artist')
|
||||
album_name = track['album'].get('name', 'Unknown Album')
|
||||
duration_ms = track.get('duration_ms', 0)
|
||||
progress_ms = current_playback.get('progress_ms', 0)
|
||||
is_playing = current_playback.get('is_playing', False)
|
||||
|
||||
duration_min, duration_sec = divmod(duration_ms // 1000, 60)
|
||||
progress_min, progress_sec = divmod(progress_ms // 1000, 60)
|
||||
|
||||
playlist = current_playback.get('context', {}).get('uri', '').split(':')[-1] if current_playback.get('context') else None
|
||||
device_name = current_playback.get('device', {}).get('name', 'Unknown Device')+" "+current_playback.get('device', {}).get('type', '')
|
||||
device_type = current_playback.get('device', {}).get('type', 'unknown')
|
||||
|
||||
user_profile = sp.current_user()
|
||||
user_name = user_profile['display_name']
|
||||
user_id = user_profile['id']
|
||||
|
||||
track_url = track['external_urls']['spotify']
|
||||
user_url = f"https://open.spotify.com/user/{user_id}"
|
||||
playlist_url = f"https://open.spotify.com/playlist/{playlist}" if playlist else None
|
||||
|
||||
track_info = (
|
||||
f"<b>🎧 Now Playing</b>\n\n"
|
||||
f"<b><emoji document_id=5188705588925702510>🎶</emoji> {track_name} - <code>{artist_name}</code>\n"
|
||||
f"<b><emoji document_id=5870794890006237381>💿</emoji> Album:</b> <code>{album_name}</code>\n\n"
|
||||
f"<b><emoji document_id=6007938409857815902>🎧</emoji> Device:</b> <code>{device_name}</code>\n"
|
||||
+ (("<b><emoji document_id=5872863028428410654>❤️</emoji> From favorite tracks</b>\n" if "playlist/collection" in playlist_url else
|
||||
f"<b><emoji document_id=5944809881029578897>📑</emoji> From Playlist:</b> <a href='{playlist_url}'>View</a>\n") if playlist else "")
|
||||
+ f"\n<b><emoji document_id=5902449142575141204>🔗</emoji> Track URL:</b> <a href='{track_url}'>Open in Spotify</a>"
|
||||
)
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
if self.config['use_ytdl']:
|
||||
audio_path = os.path.join(temp_dir, f"{artist_name} - {track_name}.mp3")
|
||||
|
||||
ydl_opts = {
|
||||
"format": "bestaudio/best[ext=mp3]",
|
||||
"outtmpl": audio_path,
|
||||
"noplaylist": True,
|
||||
}
|
||||
|
||||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||
ydl.download([f"ytsearch1:{track_name} - {artist_name}"])
|
||||
|
||||
else:
|
||||
audio_path = await self.musicdl.dl(f"{artist_name} - {track_name}", only_document=True)
|
||||
|
||||
album_art_url = track['album']['images'][0]['url']
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(album_art_url) as response:
|
||||
art_path = os.path.join(temp_dir, "cover.jpg")
|
||||
with open(art_path, "wb") as f:
|
||||
f.write(await response.read())
|
||||
|
||||
await self._client.send_file(
|
||||
message.chat_id,
|
||||
audio_path,
|
||||
caption=track_info,
|
||||
attributes=[
|
||||
types.DocumentAttributeAudio(
|
||||
duration=duration_ms//1000,
|
||||
title=track_name,
|
||||
performer=artist_name
|
||||
)
|
||||
],
|
||||
thumb=art_path,
|
||||
reply_to=message.reply_to_msg_id if message.is_reply else getattr(message, "top_id", None)
|
||||
)
|
||||
|
||||
await message.delete()
|
||||
|
||||
except spotipy.oauth2.SpotifyOauthError as e:
|
||||
return await utils.answer(message, self.strings['auth_error'].format(str(e)))
|
||||
except spotipy.exceptions.SpotifyException as e:
|
||||
if "The access token expired" in str(e):
|
||||
return await utils.answer(message, self.strings['no_auth_token'].format(self.get_prefix()))
|
||||
if "NO_ACTIVE_DEVICE" in str(e):
|
||||
return await utils.answer(message, self.strings['no_song_playing'])
|
||||
return await utils.answer(message, self.strings['unexpected_error'].format(str(e)))
|
||||
|
||||
@loader.loop(interval=60*40, autostart=True)
|
||||
async def loop_token(self):
|
||||
if not self.config['auth_token']:
|
||||
return
|
||||
|
||||
try:
|
||||
sp_oauth = spotipy.oauth2.SpotifyOAuth(
|
||||
client_id=self.config['client_id'],
|
||||
client_secret=self.config['client_secret'],
|
||||
redirect_uri="https://sp.fajox.one",
|
||||
scope=self.config['scopes']
|
||||
)
|
||||
|
||||
token_info = sp_oauth.refresh_access_token(self.config['refresh_token'])
|
||||
self.config['auth_token'] = token_info['access_token']
|
||||
self.config['refresh_token'] = token_info['refresh_token']
|
||||
except Exception as e:
|
||||
pass
|
||||
# logger.error(f"Failed to refresh Spotify token: {str(e)}", exc_info=True)
|
||||
|
||||
@loader.loop(interval=70, autostart=True)
|
||||
async def loop(self):
|
||||
if not self.config['auth_token']:
|
||||
return
|
||||
|
||||
if not self.db.get(self.name, "channel_bio_change", False):
|
||||
return
|
||||
if not self.config['channel']:
|
||||
return
|
||||
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
current_playback = sp.current_playback()
|
||||
|
||||
if not current_playback or not current_playback.get('item'):
|
||||
return
|
||||
|
||||
track = current_playback['item']
|
||||
track_name = track.get('name', 'Unknown Track')
|
||||
artist_name = track['artists'][0].get('name', 'Unknown Artist')
|
||||
|
||||
current_track = f"{track_name} - {artist_name}"
|
||||
last_track = self.db.get(self.name, "last_track", False)
|
||||
if last_track == current_track:
|
||||
return
|
||||
|
||||
self.db.set(self.name, 'last_track', f"{track_name} - {artist_name}")
|
||||
|
||||
channel = await self.client.get_entity(self.config['channel'])
|
||||
|
||||
stream_channel_data = self.db.get(self.name, "stream_channel_data", False)
|
||||
stream_upload_message = self.db.get(self.name, "stream_upload_message", True)
|
||||
|
||||
if not stream_channel_data or self.config['channel'] != stream_channel_data['channel'] or self.config['stream_upload_track'] != stream_upload_message:
|
||||
await self._create_stream_messages(channel)
|
||||
await asyncio.sleep(3)
|
||||
|
||||
stream_channel_data = self.db.get(self.name, "stream_channel_data", False)
|
||||
|
||||
artist_link = track['artists'][0]['external_urls']['spotify']
|
||||
album_name = track['album'].get('name', 'Unknown Album')
|
||||
track_url = track['external_urls']['spotify']
|
||||
duration_ms = track.get('duration_ms', 0)
|
||||
playlist = current_playback.get('context', {}).get('uri', '').split(':')[-1] if current_playback.get('context') else None
|
||||
device_name = current_playback.get('device', {}).get('name', 'Unknown Device')+" "+current_playback.get('device', {}).get('type', '')
|
||||
playlist_url = f"https://open.spotify.com/playlist/{playlist}" if playlist else None
|
||||
|
||||
keyboard = InlineKeyboardMarkup()
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text="Open in Spotify",
|
||||
url=track_url
|
||||
)
|
||||
)
|
||||
|
||||
now_play_text = f"""
|
||||
<b><emoji document_id=5188705588925702510>🎶</emoji> {track_name} - <code>{artist_name}</code>
|
||||
<b><emoji document_id=5870794890006237381>💿</emoji> Album:</b> <code>{album_name}</code>
|
||||
|
||||
<b><emoji document_id=6007938409857815902>🎧</emoji> Device:</b> <code>{device_name}</code>
|
||||
"""+ (("<b><emoji document_id=5872863028428410654>❤️</emoji> From favorite tracks</b>\n" if "playlist/collection" in playlist_url else
|
||||
f"<b><emoji document_id=5944809881029578897>📑</emoji> From Playlist:</b> <a href='{playlist_url}'>View</a>\n") if playlist else "")
|
||||
|
||||
if self.config['stream_upload_track']:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
if self.config['use_ytdl']:
|
||||
audio_path = os.path.join(temp_dir, f"{artist_name} - {track_name}.mp3")
|
||||
|
||||
ydl_opts = {
|
||||
"format": "bestaudio/best[ext=mp3]",
|
||||
"outtmpl": audio_path,
|
||||
"noplaylist": True,
|
||||
}
|
||||
|
||||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||
ydl.download([f"ytsearch1:{track_name} - {artist_name}"])
|
||||
|
||||
else:
|
||||
audio_path = await self.musicdl.dl(f"{artist_name} - {track_name}", only_document=True)
|
||||
|
||||
album_art_url = track['album']['images'][0]['url']
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(album_art_url) as response:
|
||||
art_path = os.path.join(temp_dir, "cover.jpg")
|
||||
with open(art_path, "wb") as f:
|
||||
f.write(await response.read())
|
||||
|
||||
await self.inline.bot.set_chat_photo(
|
||||
chat_id=int("-100"+str(channel.id)),
|
||||
photo=InputFile(art_path)
|
||||
)
|
||||
|
||||
await self.client.edit_message(
|
||||
entity=channel.username,
|
||||
message=stream_channel_data['first_message'],
|
||||
file=audio_path,
|
||||
attributes=[
|
||||
types.DocumentAttributeAudio(
|
||||
duration=duration_ms//1000,
|
||||
title=track_name,
|
||||
performer=artist_name
|
||||
)
|
||||
],
|
||||
thumb=art_path,
|
||||
text=now_play_text
|
||||
)
|
||||
|
||||
else:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
album_art_url = track['album']['images'][0]['url']
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(album_art_url) as response:
|
||||
art_path = os.path.join(temp_dir, "cover.jpg")
|
||||
with open(art_path, "wb") as f:
|
||||
f.write(await response.read())
|
||||
|
||||
await self.inline.bot.set_chat_photo(
|
||||
chat_id=int("-100"+str(channel.id)),
|
||||
photo=InputFile(art_path)
|
||||
)
|
||||
await self.client.edit_message(
|
||||
entity=channel.username,
|
||||
message=stream_channel_data['first_message'],
|
||||
text="<b>🎧 Now Playing</b>\n"+now_play_text
|
||||
)
|
||||
|
||||
try:
|
||||
await self.inline.bot.edit_message_reply_markup(
|
||||
chat_id=int("-100"+str(channel.id)),
|
||||
message_id=stream_channel_data['first_message'],
|
||||
reply_markup=keyboard
|
||||
)
|
||||
except:
|
||||
await self._create_stream_messages(channel)
|
||||
await asyncio.sleep(2.3342)
|
||||
try:
|
||||
await self.client.edit_message(
|
||||
entity=channel,
|
||||
message=stream_channel_data['display_message'],
|
||||
text=f"<emoji document_id=5346074681004801565>📱</emoji> <a href='{artist_link}'>{artist_name}</a>",
|
||||
link_preview=False
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
await asyncio.sleep(1.3342)
|
||||
|
||||
try:
|
||||
await self.inline.bot.set_chat_title(
|
||||
chat_id=int("-100"+str(channel.id)),
|
||||
title=f"🎧 {track_name}"
|
||||
)
|
||||
|
||||
messages = await self.client.get_messages(
|
||||
entity=channel,
|
||||
limit=2
|
||||
)
|
||||
for message in messages:
|
||||
await message.delete()
|
||||
except:
|
||||
return
|
||||
|
||||
@loader.loop(interval=90, autostart=True)
|
||||
async def loop_bio(self):
|
||||
if self.db.get(self.name, "bio_change", False):
|
||||
return
|
||||
sp = spotipy.Spotify(auth=self.config['auth_token'])
|
||||
try:
|
||||
current_playback = sp.current_playback()
|
||||
if current_playback and current_playback.get('item'):
|
||||
track = current_playback['item']
|
||||
track_name = track.get('name', 'Unknown Track')
|
||||
artist_name = track['artists'][0].get('name', 'Unknown Artist')
|
||||
bio = self.config['bio_text'].format(track_name=track_name, artist_name=artist_name)
|
||||
await self._client(UpdateProfileRequest(about=bio[:70]))
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating bio: {e}")
|
||||
75
fajox1/famods/stats.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Stats
|
||||
# Description: Показывает статистику твоего аккаунта
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/stats.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Stats(loader.Module):
|
||||
"""Показывает статистику твоего аккаунта"""
|
||||
|
||||
strings = {
|
||||
"name": "Stats",
|
||||
|
||||
"loading_stats": "<b><emoji document_id=5326015457155620929>🔄</emoji> Загрузка статистики...</b>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def stats(self, message):
|
||||
"""Получить статистику"""
|
||||
|
||||
await utils.answer(message, self.strings['loading_stats'])
|
||||
u_chat = 0
|
||||
b_chat = 0
|
||||
c_chat = 0
|
||||
ch_chat = 0
|
||||
all_chats = 0
|
||||
|
||||
async for dialog in self._client.iter_dialogs():
|
||||
all_chats += 1
|
||||
if dialog.is_user:
|
||||
if dialog.entity.bot:
|
||||
b_chat += 1
|
||||
elif not dialog.entity.bot:
|
||||
u_chat += 1
|
||||
elif dialog.is_group:
|
||||
c_chat += 1
|
||||
elif dialog.is_channel:
|
||||
if dialog.entity.megagroup or dialog.entity.gigagroup:
|
||||
if dialog.entity.megagroup:
|
||||
c_chat += 1
|
||||
elif dialog.entity.gigagroup:
|
||||
c_chat += 1
|
||||
elif not dialog.entity.megagroup and not dialog.entity.gigagroup:
|
||||
ch_chat += 1
|
||||
await utils.answer(message,
|
||||
f"""<b><emoji document_id=5431577498364158238>📊</emoji> Твоя статистика
|
||||
|
||||
<emoji document_id=5884510167986343350>💬</emoji> Всего чатов: <code>{all_chats}</code>
|
||||
|
||||
<emoji document_id=5258011929993026890>👤</emoji> <code>{u_chat}</code> личных чатов
|
||||
<emoji document_id=5258513401784573443>👥</emoji> <code>{c_chat}</code> групп
|
||||
<emoji document_id=5852471614628696454>📢</emoji> <code>{ch_chat}</code> каналов
|
||||
<emoji document_id=5258093637450866522>🤖</emoji> <code>{b_chat}</code> ботов</b>""")
|
||||
155
fajox1/famods/telegrapher.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Telegrapher
|
||||
# Description: Создание статей и другое связанное с telegra.ph
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/telegrapher.png?raw=true
|
||||
# requires: aiohttp telegraph
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from telegraph import Telegraph
|
||||
|
||||
from telethon import types
|
||||
from telethon.tl.types import DocumentAttributeFilename
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Telegrapher(loader.Module):
|
||||
"""Создание статей и другое связанное с telegra.ph"""
|
||||
|
||||
strings = {
|
||||
"name": "Telegrapher",
|
||||
|
||||
"waiting": "<b><emoji document_id=6334391057186293707>🕑</emoji> Создаю страницу на telegra.ph...</b>",
|
||||
"waiting_up": "<b><emoji document_id=6334391057186293707>🕑</emoji> Загружаю файл на telegra.ph...</b>",
|
||||
|
||||
"article_ready": """<b>
|
||||
<emoji document_id=6334758581832779720>✅</emoji> Твоя статья в Telegra.ph создана!
|
||||
|
||||
<emoji document_id=5271604874419647061>🔗</emoji> Ссылка: {}
|
||||
|
||||
<emoji document_id=6334638004920911460>ℹ️</emoji> </b><i>Редактировать заголовок/контент/автора на странице можно в <code>{}cfg telegrapher</code></i>
|
||||
""",
|
||||
"upload_ready": """<b>
|
||||
<emoji document_id=6334353510582191829>⬇️</emoji> Файл загружен!
|
||||
|
||||
<emoji document_id=5271604874419647061>🔗</emoji> Ссылка: {}
|
||||
</b>""",
|
||||
"upload_error": "<emoji document_id=5019523782004441717>❌</emoji> <b>Ошибка при выгрузке файла на telegra.ph!</b>",
|
||||
|
||||
"media_type_invalid": "<emoji document_id=5019523782004441717>❌</emoji> <b>Ответь на фото или видео/гиф</b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"TITLE",
|
||||
"FAmods telegrapher",
|
||||
lambda: "Заголовок статьи",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"CONTENT",
|
||||
"Редактировать заголовок/контент/автора на странице можно в .cfg telegrapher",
|
||||
lambda: "Контент статьи (можно использовать html-разметку)",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"author_name",
|
||||
"famods",
|
||||
lambda: "Автор статьи",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"author_short_name",
|
||||
"famods",
|
||||
lambda: "Короткое имя автора статьи (нужно для авторизации в telegraph api)",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def tghpost(self, message):
|
||||
"""Выложить статью в telegra.ph"""
|
||||
|
||||
await utils.answer(message, self.strings['waiting'])
|
||||
|
||||
telegraph_api = Telegraph()
|
||||
telegraph_api.create_account(short_name=self.config["author_short_name"], author_name=self.config["author_name"])
|
||||
response = telegraph_api.create_page(
|
||||
title=self.config["TITLE"],
|
||||
html_content=self.config["CONTENT"],
|
||||
author_name=self.config["author_name"],
|
||||
)
|
||||
|
||||
return await utils.answer(message, self.strings['article_ready'].format(f"https://telegra.ph/{response['path']}", self.get_prefix()))
|
||||
|
||||
@loader.command()
|
||||
async def tghup(self, message):
|
||||
"""Выложить медиа в telegra.ph"""
|
||||
reply_message = await message.get_reply_message()
|
||||
|
||||
if not reply_message or not reply_message.media:
|
||||
await utils.answer(message, self.strings['media_type_invalid'])
|
||||
return
|
||||
|
||||
await utils.answer(message, self.strings['waiting_up'])
|
||||
|
||||
media_data = await self.check_media_type(reply_message.media)
|
||||
|
||||
if not media_data:
|
||||
await utils.answer(message, self.strings['media_type_invalid'])
|
||||
return
|
||||
|
||||
file_content = await message.client.download_media(media_data, bytes)
|
||||
telegraph_upload_url = "https://telegra.ph/upload"
|
||||
form = aiohttp.FormData()
|
||||
form.add_field('file', file_content, filename='file')
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(telegraph_upload_url, data=form) as response:
|
||||
uploaded_data = await response.json()
|
||||
telegraph_link = "https://telegra.ph" + uploaded_data[0]["src"]
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return await utils.answer(message, self.strings['upload_error'])
|
||||
|
||||
await utils.answer(message, self.strings['upload_ready'].format(telegraph_link))
|
||||
|
||||
async def check_media_type(self, media):
|
||||
if not media:
|
||||
return False
|
||||
|
||||
if isinstance(media, types.MessageMediaPhoto):
|
||||
media_data = media.photo
|
||||
elif isinstance(media, types.MessageMediaDocument):
|
||||
document = media.document
|
||||
|
||||
if any(
|
||||
isinstance(attribute, types.DocumentAttributeAudio)
|
||||
for attribute in document.attributes
|
||||
):
|
||||
return False
|
||||
|
||||
if DocumentAttributeFilename(file_name="AnimatedSticker.tgs") in document.attributes:
|
||||
return False
|
||||
|
||||
media_data = document
|
||||
else:
|
||||
return False
|
||||
|
||||
return media_data
|
||||
1
fajox1/famods/test.txt
Normal file
@@ -0,0 +1 @@
|
||||
test
|
||||
136
fajox1/famods/timer.py
Normal file
@@ -0,0 +1,136 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Timer
|
||||
# Description: Показывает сколько времени осталось
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/timer.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import pytz
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Timer(loader.Module):
|
||||
"""Показывает сколько времени осталось"""
|
||||
|
||||
strings = {
|
||||
"name": "Timer",
|
||||
|
||||
"no_date": "<b><emoji document_id=5019523782004441717>❌</emoji> Добавь сначала дату в <code>{}cfg timer</code></b>",
|
||||
|
||||
"invalid_date": "<b><emoji document_id=5019523782004441717>❌</emoji> Неверный формат даты и времени в конфиге.</b>",
|
||||
"invalid_timezone": "<b><emoji document_id=5019523782004441717>❌</emoji> Неверный часовой пояс.</b>"
|
||||
}
|
||||
|
||||
time_units = [
|
||||
('год', 'года', 'лет'),
|
||||
('день', 'дня', 'дней'),
|
||||
('час', 'часа', 'часов'),
|
||||
('минута', 'минуты', 'минут'),
|
||||
('секунда', 'секунды', 'секунд')
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"text",
|
||||
"<b>🕑 Осталось до этого ещё {time}</b>",
|
||||
lambda: "Текст который будет отображаться с датой. (Можно использовать HTML-разметку) Пример: 🕑 Осталось до этого ещё {time}",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"text_already",
|
||||
"<b>✅ Это уже случилось {time} назад</b>",
|
||||
lambda: "Текст который будет если событие уже случилось. Пример: ✅ Это уже случилось {time} назад",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"date",
|
||||
None,
|
||||
lambda: "Дата до которой нужно считать. Пример: 25.04.2025 17:05",
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"timezone",
|
||||
"auto",
|
||||
lambda: "Часовой пояс, по стандарту автоматически. Пример: Europe/Moscow",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def stime(self, message):
|
||||
"""Посмотреть сколько осталось времени"""
|
||||
|
||||
if not self.config["date"]:
|
||||
return await utils.answer(message, self.strings['no_date'].format(self.get_prefix()))
|
||||
|
||||
date_time_str = self.config['date']
|
||||
timezone = self.config.get('timezone', 'auto')
|
||||
|
||||
try:
|
||||
date_str, time_str = date_time_str.split(' ')
|
||||
except ValueError:
|
||||
return await utils.answer(message, self.strings['invalid_date'])
|
||||
|
||||
day, month, year = map(int, date_str.split("."))
|
||||
hour, minute = map(int, time_str.split(":"))
|
||||
|
||||
now = datetime.now()
|
||||
|
||||
if timezone == 'auto':
|
||||
event_time = datetime(year, month, day, hour, minute)
|
||||
else:
|
||||
try:
|
||||
user_timezone = pytz.timezone(timezone)
|
||||
event_time = user_timezone.localize(datetime(year, month, day, hour, minute), is_dst=None)
|
||||
except pytz.UnknownTimeZoneError:
|
||||
return await utils.answer(message, self.strings['invalid_timezone'])
|
||||
|
||||
if timezone != 'auto':
|
||||
now = now.astimezone(user_timezone)
|
||||
|
||||
was_t = now > event_time if timezone == 'auto' else now > event_time.astimezone(user_timezone)
|
||||
|
||||
time_to_event = abs(now - event_time if timezone == 'auto' else now - event_time.astimezone(user_timezone))
|
||||
days = time_to_event.days
|
||||
|
||||
years = days // 365
|
||||
days %= 365
|
||||
|
||||
hours, remainder = divmod(time_to_event.seconds, 3600)
|
||||
minutes, seconds = divmod(remainder, 60)
|
||||
|
||||
time_values = [years, days, hours, minutes, seconds]
|
||||
time_to = ""
|
||||
|
||||
for value, (singular, genitive, plural) in zip(time_values, self.time_units):
|
||||
if value > 0:
|
||||
form = singular if value == 1 else genitive if 1 < value < 5 else plural
|
||||
time_to += f"{value} {form} "
|
||||
time_to = time_to.rstrip()
|
||||
|
||||
if time_to and not was_t:
|
||||
return await utils.answer(
|
||||
message,
|
||||
self.config["text"].format(time=time_to),
|
||||
)
|
||||
|
||||
return await utils.answer(
|
||||
message,
|
||||
self.config["text_already"].format(time=time_to),
|
||||
)
|
||||
110
fajox1/famods/tondns.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: TonDNS
|
||||
# Description: Модуль для работы с TON DNS
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/tondns.png?raw=true
|
||||
# requires: aiohttp
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class TonDNS(loader.Module):
|
||||
"""Модуль для работы с Ton DNS"""
|
||||
|
||||
strings = {
|
||||
"name": "TonDNS",
|
||||
|
||||
"waiting": "<b><emoji document_id=6334391057186293707>🕑</emoji> Собираю информацию...</b>",
|
||||
"waiting_shot": "<b><emoji document_id=6334391057186293707>📸</emoji> Делаю скриншот TON DNS сайта...</b>",
|
||||
|
||||
"shot_ton_dns": "<b>💎 Скриншот TON DNS сайта <code>{}</code></b>",
|
||||
|
||||
"ton_shot_link": "https://mini.s-shot.ru/1920x1080/JPEG/1024/Z100/?{}",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def itondns(self, message):
|
||||
"""Информация о TON DNS"""
|
||||
address = utils.get_args_raw(message)
|
||||
|
||||
if not address:
|
||||
return await utils.answer(message, f"<emoji document_id=5019523782004441717>❌</emoji> <b>Должно быть</b> <code>{self.get_prefix()}itondns тон_домен</code>")
|
||||
|
||||
await utils.answer(message, self.strings["waiting"])
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(f"https://tonapi.io/v2/dns/{address}") as res:
|
||||
response = await res.json()
|
||||
|
||||
try:
|
||||
response['error']
|
||||
if "can't decode address" in response['error']:
|
||||
return await utils.answer(message, f"<b>❌ Это не адрес кошелька!</b>")
|
||||
|
||||
return await utils.answer(message, f"""<b>❌ Ошибка!\n\n
|
||||
<code>{response['error']}</code>
|
||||
</b>""")
|
||||
except:
|
||||
pass
|
||||
|
||||
await utils.answer(message, f"""<b>
|
||||
<emoji document_id=5854713299794398583>💎</emoji> Ton DNS
|
||||
|
||||
Имя: <code>{response['name']}</code>
|
||||
Адрес: <code>{response['item']['address']}</code>
|
||||
|
||||
⌛️ Истекает: <i>{datetime.fromtimestamp(response['expiring_at'])}</i>
|
||||
|
||||
🧑💻 Владелец
|
||||
Адресс: <code>{response['item']['owner']['address']}</code>
|
||||
|
||||
🌐 DNS адрес: <code>{response['item']['dns']}</code>
|
||||
|
||||
<a href="https://tonscan.org/address/{address}">Tonscan</a> • <a href="{response['item']['previews'][2]['url']}">Image</a> • <a href="https://tonscan.org/address/{address}#source">Contract</a>
|
||||
</b>""")
|
||||
|
||||
@loader.command()
|
||||
async def tonshot(self, message):
|
||||
"""Скриншот TON DNS сайта"""
|
||||
address = utils.get_args_raw(message)
|
||||
|
||||
if not address:
|
||||
return await utils.answer(message, f"<emoji document_id=5019523782004441717>❌</emoji> <b>Должно быть</b> <code>.tonshot тон_домен</code>")
|
||||
|
||||
await utils.answer(message, self.strings["waiting_shot"])
|
||||
|
||||
address = address.replace("https://", "")
|
||||
address = address.replace("http://", "")
|
||||
|
||||
ton_dns = address
|
||||
|
||||
address += f"-s.cam"
|
||||
|
||||
try:
|
||||
await message.client.send_file(message.chat_id, self.strings['ton_shot_link'].format(address), caption=self.strings['shot_ton_dns'].format(ton_dns))
|
||||
await message.delete()
|
||||
except:
|
||||
address = address.replace("-s.cam", ".run")
|
||||
await message.client.send_file(message.chat_id, self.strings['ton_shot_link'].format(address), caption=self.strings['shot_ton_dns'].format(ton_dns))
|
||||
await message.delete()
|
||||
301
fajox1/famods/tonscan.py
Normal file
@@ -0,0 +1,301 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Tonscan
|
||||
# Description: Информация о TON адресе
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/tonscan.png?raw=true
|
||||
# requires: aiohttp
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Tonscan(loader.Module):
|
||||
"""Информация о TON адресе"""
|
||||
|
||||
strings = {
|
||||
"name": "Tonscan",
|
||||
|
||||
"waiting": "<b><emoji document_id=6334391057186293707>🕑</emoji> Собираю информацию...</b>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
@loader.command()
|
||||
async def tonwallet(self, message):
|
||||
"""Информация о TON кошельке"""
|
||||
address = utils.get_args_raw(message)
|
||||
|
||||
if not address:
|
||||
return await utils.answer(message, f"<emoji document_id=5019523782004441717>❌</emoji> <b>Должно быть</b> <code>.tonwallet адрес_кошелька</code>")
|
||||
|
||||
await utils.answer(message, self.strings["waiting"])
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(f"https://tonapi.io/v2/accounts/{address}") as res:
|
||||
response = await res.json()
|
||||
|
||||
try:
|
||||
response['icon']
|
||||
ava = f"""<a href="{response['icon']}">Аватарка</a> • """
|
||||
except:
|
||||
ava = ""
|
||||
|
||||
try:
|
||||
response['name']
|
||||
name = f"\nИмя: <code>{response['name']}</code>\n"
|
||||
except:
|
||||
name = ""
|
||||
|
||||
try:
|
||||
response['error']
|
||||
if "can't decode address" in response['error']:
|
||||
return await utils.answer(message, f"<b>❌ Это не адрес кошелька!</b>")
|
||||
|
||||
return await utils.answer(message, f"""<b>❌ Ошибка!\n\n
|
||||
```json
|
||||
{response['error']}
|
||||
```</b>""")
|
||||
except:
|
||||
pass
|
||||
|
||||
scam = "Нет"
|
||||
|
||||
try:
|
||||
if response['is_scam'] == "True":
|
||||
scam = "Да"
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
contract = f"Контракт: <code>{response['interfaces'][0]}</code>\n"
|
||||
except:
|
||||
contract = ""
|
||||
|
||||
try:
|
||||
last_activity = f"\nПоследння активность: </b><i>{datetime.fromtimestamp(response['last_activity'])}</i><b>"
|
||||
except:
|
||||
last_activity = ""
|
||||
|
||||
await utils.answer(message, f"""<b>
|
||||
<emoji document_id=5854713299794398583>💎</emoji> Ton wallet
|
||||
{name}
|
||||
Адрес: <code>{address}</code>
|
||||
Баланс: <code>{response['balance']} TON</code>
|
||||
|
||||
Скам: </b><i>{scam}</i><b>
|
||||
Статус: </b><i>{response['status']}</i><b>{last_activity}
|
||||
{contract}
|
||||
<a href="https://tonscan.org/address/{address}">Tonscan</a> • {ava}<a href="https://tonscan.org/address/{address}#transactions">История</a> • <a href="https://tonscan.org/address/{address}#nfts">NFT</a> • <a href="https://tonscan.org/address/{address}#tokens">jettons</a> • <a href="https://tonscan.org/address/{address}#source">Contract</a>
|
||||
</b>""")
|
||||
|
||||
@loader.command()
|
||||
async def tonjetton(self, message):
|
||||
"""Информация о TON токене"""
|
||||
address = utils.get_args_raw(message)
|
||||
|
||||
if not address:
|
||||
return await utils.answer(message, f"<emoji document_id=5019523782004441717>❌</emoji> <b>Должно быть</b> <code>.tonjetton адрес_токена</code>")
|
||||
|
||||
await utils.answer(message, self.strings["waiting"])
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(f"https://tonapi.io/v2/jettons/{address}") as res:
|
||||
response = await res.json()
|
||||
|
||||
try:
|
||||
response['error']
|
||||
return await utils.answer(message, f"""<b>❌ Ошибка!\n\n
|
||||
```json
|
||||
{response['error']}
|
||||
```</b>""")
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
response['metadata']['description']
|
||||
descr = f"\n</b><i>{response['metadata']['description']}</i><b>\n"
|
||||
except:
|
||||
descr = ""
|
||||
|
||||
try:
|
||||
response['metadata']['social']
|
||||
|
||||
socials = """Ссылки:
|
||||
"""
|
||||
for s in response['metadata']['social']:
|
||||
socials += s + "\n"
|
||||
socials += "\n"
|
||||
except:
|
||||
socials = ""
|
||||
|
||||
await utils.answer(message, f"""<b>
|
||||
<emoji document_id=5854713299794398583>💎</emoji> Ton jetton
|
||||
|
||||
Имя: <code>{response['metadata']['name']}</code>
|
||||
Символ: <code>{response['metadata']['symbol']}</code>
|
||||
{descr}
|
||||
Адрес: <code>{address}</code>
|
||||
Общее предложение: <code>{response['total_supply']} TON</code>
|
||||
|
||||
Количество держателей: <code>{response['holders_count']}</code>
|
||||
|
||||
{socials}<a href="https://tonscan.org/jetton/{address}">Tonscan</a> • <a href="{response['metadata']['image']}">Лого</a> • <a href="https://tonscan.org/jetton/{address}#transactions">История</a> • <a href="https://tonscan.org/jetton/{address}#holders">Топ держателей</a> • <a href="https://tonscan.org/jetton/{address}#source">Contract</a>
|
||||
</b>""")
|
||||
|
||||
@loader.command()
|
||||
async def tonnftcol(self, message):
|
||||
"""Информация о TON NFT коллекции"""
|
||||
address = utils.get_args_raw(message)
|
||||
|
||||
if not address:
|
||||
return await utils.answer(message, f"<emoji document_id=5019523782004441717>❌</emoji> <b>Должно быть</b> <code>.tonnftcol адрес_коллекции</code>")
|
||||
|
||||
await utils.answer(message, self.strings["waiting"])
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(f"https://tonapi.io/v2/nfts/collections/{address}") as res:
|
||||
response = await res.json()
|
||||
|
||||
try:
|
||||
response['error']
|
||||
return await utils.answer(message, f"""<b>❌ Ошибка!\n\n
|
||||
```json
|
||||
{response['error']}
|
||||
```</b>""")
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
response['metadata']['description']
|
||||
descr = f"\n</b><i>{response['metadata']['description']}</i><b>\n"
|
||||
except:
|
||||
descr = ""
|
||||
|
||||
try:
|
||||
response['metadata']['external_link']
|
||||
external_link = f"\nВнешняя ссылка: {response['metadata']['external_link']}\n"
|
||||
except:
|
||||
external_link = ""
|
||||
|
||||
try:
|
||||
response['metadata']['social_links']
|
||||
|
||||
socials = """Ссылки:
|
||||
"""
|
||||
for s in response['metadata']['social']:
|
||||
socials += s + "\n"
|
||||
socials += "\n"
|
||||
except:
|
||||
socials = ""
|
||||
|
||||
try:
|
||||
response['metadata']['approved_by']
|
||||
|
||||
approved_by = """Одобрено:
|
||||
"""
|
||||
for s in response['metadata']['approved_by']:
|
||||
approved_by += s + "\n"
|
||||
approved_by += "\n"
|
||||
except:
|
||||
approved_by = ""
|
||||
|
||||
await utils.answer(message, f"""<b>
|
||||
<emoji document_id=5854713299794398583>💎</emoji> Ton NFT collection
|
||||
|
||||
Имя: <code>{response['metadata']['name']}</code>
|
||||
Адрес: <code>{address}</code>
|
||||
{descr}
|
||||
{external_link}
|
||||
{approved_by}{socials}<a href="https://tonscan.org/nft/{address}">Tonscan</a> • <a href="https://tonscan.org/nft/{address}">Коллекция</a> • <a href="{response['metadata']['image']}">Лого</a> • <a href="{response['metadata']['cover_image']}">Баннер</a>
|
||||
</b>""")
|
||||
|
||||
@loader.command()
|
||||
async def tonnft(self, message):
|
||||
"""Информация о TON NFT"""
|
||||
address = utils.get_args_raw(message)
|
||||
|
||||
if not address:
|
||||
return await utils.answer(message, f"<emoji document_id=5019523782004441717>❌</emoji> <b>Должно быть</b> <code>.tonnft адрес_nft</code>")
|
||||
|
||||
await utils.answer(message, self.strings["waiting"])
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(f"https://tonapi.io/v2/nfts/{address}") as res:
|
||||
response = await res.json()
|
||||
|
||||
try:
|
||||
response['error']
|
||||
return await utils.answer(message, f"""<b>❌ Ошибка!\n\n
|
||||
```json
|
||||
{response['error']}
|
||||
```</b>""")
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
response['metadata']['description']
|
||||
descr = f"\n</b><i>{response['metadata']['description']}</i><b>\n"
|
||||
except:
|
||||
descr = ""
|
||||
|
||||
try:
|
||||
response['collection']['name']
|
||||
coll = f"\nКолекция: <code>{response['collection']['name']}</code>\n"
|
||||
except:
|
||||
coll = ""
|
||||
|
||||
try:
|
||||
response['metadata']['external_link']
|
||||
external_link = f"\nВнешняя ссылка: {response['metadata']['external_link']}\n"
|
||||
except:
|
||||
external_link = ""
|
||||
|
||||
try:
|
||||
response['metadata']['social_links']
|
||||
|
||||
socials = """Ссылки:
|
||||
"""
|
||||
for s in response['metadata']['social']:
|
||||
socials += s + "\n"
|
||||
socials += "\n"
|
||||
except:
|
||||
socials = ""
|
||||
|
||||
try:
|
||||
response['metadata']['approved_by']
|
||||
|
||||
approved_by = """Одобрено:
|
||||
"""
|
||||
for s in response['metadata']['approved_by']:
|
||||
approved_by += s + "\n"
|
||||
approved_by += "\n"
|
||||
except:
|
||||
approved_by = ""
|
||||
|
||||
await utils.answer(message, f"""<b>
|
||||
<emoji document_id=5854713299794398583>💎</emoji> Ton NFT
|
||||
{coll}
|
||||
Имя: <code>{response['metadata']['name']}</code>
|
||||
Адрес: <code>{address}</code>
|
||||
{descr}
|
||||
{external_link}
|
||||
{approved_by}{socials}<a href="https://tonscan.org/nft/{address}">Tonscan</a> • <a href="{response['metadata']['image']}">NFT фото</a>
|
||||
</b>""")
|
||||
135
fajox1/famods/vaper.py
Normal file
@@ -0,0 +1,135 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Vaper
|
||||
# Description: Авто-фарм в @vapeusebot
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/vaper.png?raw=true
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import hikkatl
|
||||
|
||||
import re
|
||||
import random
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Vaper(loader.Module):
|
||||
"""Авто-фарм в @vapeusebot"""
|
||||
|
||||
strings = {
|
||||
"name": "Vaper",
|
||||
|
||||
"checking_profile": "<b><emoji document_id=5424885441100782420>👀</emoji> Смотрю профиль...</b>",
|
||||
"getting_top": "<b><emoji document_id=5424885441100782420>👀</emoji> Смотрю статистику...</b>",
|
||||
|
||||
"v_on": "<b><emoji document_id=5429633836684157942>⚡️</emoji> Авто-фарм включен!</b>",
|
||||
"v_off": "<b><emoji document_id=5854929766146118183>🚫</emoji> Авто-фарм выключен!</b>",
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
if self.db.get(self.name, "vape", False):
|
||||
asyncio.create_task(self._vape())
|
||||
|
||||
async def _vape(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@vapeusebot") as conv:
|
||||
msg = await conv.send_message("/vape")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _getprofme(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@vapeusebot") as conv:
|
||||
msg = await conv.send_message("/vape")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
match = re.search(r'Всего затягов: (\d+)', r.text)
|
||||
total_puffs = int(match.group(1))
|
||||
await asyncio.sleep(2.4211112)
|
||||
msg = await conv.send_message("/ref")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
match = re.search(r'рефералов: (\d+)', r.text)
|
||||
referrals = int(match.group(1))
|
||||
return f"""<b><emoji document_id=5433653135799228968>📁</emoji> Профиль
|
||||
|
||||
🌫 Затяжек: <code>{total_puffs}</code>
|
||||
👥 Приглашено: <code>{referrals}</code>
|
||||
|
||||
<emoji document_id=5271604874419647061>🔗</emoji> Реферальная ссылка: <code>http://t.me/vapeusebot?start=ref_{self.tg_id}</code></b>"""
|
||||
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
async def _gettop(self):
|
||||
while True:
|
||||
try:
|
||||
async with self._client.conversation("@vapeusebot") as conv:
|
||||
msg = await conv.send_message("/global_top")
|
||||
r = await conv.get_response()
|
||||
await msg.delete()
|
||||
await r.delete()
|
||||
return r.text.replace("<i>/vape</i>", "<code>/vape</code>")
|
||||
break
|
||||
except hikkatl.errors.common.AlreadyInConversationError:
|
||||
await asyncio.sleep(5.67)
|
||||
|
||||
@loader.command()
|
||||
async def vape(self, message):
|
||||
"""Включить/выключить авто-фарм"""
|
||||
|
||||
if self.db.get(self.name, "vape", False):
|
||||
self.db.set(self.name, "vape", False)
|
||||
return await utils.answer(message, self.strings["v_off"])
|
||||
|
||||
self.db.set(self.name, "vape", True)
|
||||
|
||||
await utils.answer(message, self.strings["v_on"])
|
||||
|
||||
await self._vape()
|
||||
|
||||
@loader.command()
|
||||
async def vp(self, message):
|
||||
"""Посмотреть свой профиль"""
|
||||
|
||||
await utils.answer(message, self.strings["checking_profile"])
|
||||
|
||||
await utils.answer(message, await self._getprofme())
|
||||
|
||||
@loader.command()
|
||||
async def vtop(self, message):
|
||||
"""Посмотреть топ"""
|
||||
|
||||
await utils.answer(message, self.strings["getting_top"])
|
||||
|
||||
await utils.answer(message, await self._gettop())
|
||||
|
||||
@loader.loop(interval=60*60, autostart=True)
|
||||
async def loop(self):
|
||||
if self.db.get(self.name, "vape", False):
|
||||
await self._vape()
|
||||
await asyncio.sleep(random.randint(65, 90))
|
||||
13
fajox1/famods/vercel.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"headers": [
|
||||
{
|
||||
"source": "/(.*)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "text/plain; charset=utf-8"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
109
fajox1/famods/wakatime.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# █▀▀ ▄▀█ █▀▄▀█ █▀█ █▀▄ █▀
|
||||
# █▀░ █▀█ █░▀░█ █▄█ █▄▀ ▄█
|
||||
|
||||
# https://t.me/famods
|
||||
|
||||
# 🔒 Licensed under the GNU AGPLv3
|
||||
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Name: Wakatime
|
||||
# Description: Показывает твою Wakatime статистику
|
||||
# meta developer: @FAmods
|
||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/wakatime.png?raw=true
|
||||
# requires: httpx
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import httpx
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@loader.tds
|
||||
class Wakatime(loader.Module):
|
||||
"""Показывает твою Wakatime статистику"""
|
||||
|
||||
strings = {
|
||||
"name": "Wakatime",
|
||||
|
||||
"loading": "<emoji document_id=6334391057186293707>🕑</emoji> <b>Загрузка статистики...</b>",
|
||||
"no_token": "<emoji document_id=5210952531676504517>🚫</emoji> <b>Wakatime токен не поставлен! Поставь его в <code>{}cfg wakatime</code></b>",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"WAKATIME_TOKEN",
|
||||
None,
|
||||
lambda: "Твой wakatime токен. Получить токен: https://wakatime.com/settings/account",
|
||||
validator=loader.validators.Hidden(loader.validators.String()),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.db = db
|
||||
self._client = client
|
||||
|
||||
async def _get_data(self, endpoint, token):
|
||||
url = f"https://wakatime.com/api/v1/users/current/{endpoint}?api_key={token}"
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(url)
|
||||
return response
|
||||
|
||||
async def get_waka(self, token):
|
||||
endpoints = ["status_bar/today", "stats/all_time", "stats/all_time", "all_time_since_today"]
|
||||
|
||||
responses = await asyncio.gather(*(self._get_data(endpoint, token) for endpoint in endpoints))
|
||||
data_today, data_all_time, data_stats_s, data_all_time_since_today = [response.json() for response in responses]
|
||||
|
||||
all_time = data_all_time_since_today["data"]["text"]
|
||||
username = data_all_time["data"]["username"]
|
||||
if not username:
|
||||
username = "Нету"
|
||||
try:
|
||||
languages = data_all_time["data"]["languages"]
|
||||
except:
|
||||
languages = []
|
||||
today = data_today["data"]["categories"]
|
||||
try:
|
||||
os = data_all_time["data"]["operating_systems"]
|
||||
except:
|
||||
pass
|
||||
OS = ", ".join([f"<code>{stat['name']}</code>" for stat in os if stat["text"] != "0 secs"])
|
||||
editor = data_all_time["data"]["editors"]
|
||||
EDITOR = ", ".join([f"<code>{stat['name']}</code> " for stat in editor if stat["text"] != "0 secs"])
|
||||
try:
|
||||
LANG = "\n".join([f"▫️ <b>{stat['name']}</b>: <i>{stat['text']}</i>" for stat in languages if stat["text"] != "0 secs"])
|
||||
except:
|
||||
LANG = ""
|
||||
TODAY = "\n".join([f"{stat['text']}" for stat in today if stat["text"] != "0 secs"])
|
||||
|
||||
return f"""<b><emoji document_id=5190458330719461749>🧑💻</emoji> Юзернейм: <code>{username}</code>
|
||||
|
||||
<emoji document_id=6334391057186293707>🕑</emoji> За всё время: <code>{all_time}</code>
|
||||
📃 Сегодня: <code>{TODAY}</code>
|
||||
|
||||
<emoji document_id=6334742097748298141>🖥</emoji> ОС:</b> <i>{OS}</i>
|
||||
<emoji document_id=5807454683714817955>💻</emoji> <b>Редактор:</b> <i>{EDITOR}</i>
|
||||
|
||||
<b>💈 Языки программирования</b>
|
||||
|
||||
{LANG}\n"""
|
||||
|
||||
@loader.command()
|
||||
async def waka(self, message):
|
||||
"""Посмотреть свою статистику в Wakatime"""
|
||||
token = self.config["WAKATIME_TOKEN"]
|
||||
|
||||
if token is None:
|
||||
return await utils.answer(message, self.strings["no_token"].format(self.get_prefix()))
|
||||
|
||||
await utils.answer(message, self.strings["loading"])
|
||||
|
||||
waka_text = await self.get_waka(token)
|
||||
|
||||
await utils.answer(message, waka_text)
|
||||