mirror of
https://github.com/yasirarism/MissKatyPyro.git
synced 2025-12-29 17:44:50 +00:00
Rilis Pertama
This commit is contained in:
commit
6142c2a5e5
71 changed files with 9610 additions and 0 deletions
26
.github/workflows/notify.yml
vendored
Normal file
26
.github/workflows/notify.yml
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
name: Notify on Telegram
|
||||
|
||||
on:
|
||||
fork:
|
||||
push:
|
||||
release:
|
||||
issue_comment:
|
||||
types: created
|
||||
watch:
|
||||
types: started
|
||||
pull_request_review_comment:
|
||||
types: created
|
||||
pull_request:
|
||||
types: [opened, closed, reopened]
|
||||
issues:
|
||||
types: [opened, pinned, closed, reopened]
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Notify the commit on Telegram.
|
||||
uses: EverythingSuckz/github-telegram-notify@main
|
||||
with:
|
||||
bot_token: '${{ secrets.BOT_TOKEN }}'
|
||||
chat_id: '${{ secrets.CHAT_ID }}'
|
||||
32
.github/workflows/pylint.yml
vendored
Normal file
32
.github/workflows/pylint.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
name: PyLint
|
||||
|
||||
on: [pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
Pylint_Fix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install Python lint libraries
|
||||
run: |
|
||||
pip install autoflake black
|
||||
- name: Remove unused imports and variables
|
||||
run: |
|
||||
autoflake --in-place --recursive --exclude "__main__.py" --remove-all-unused-imports --remove-unused-variables --ignore-init-module-imports .
|
||||
- name: lint with black
|
||||
run: |
|
||||
black --exclude "__main__.py" --line-length 250 --target-version py310 .
|
||||
# commit changes
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: 'reformating: code'
|
||||
commit_options: '--no-verify'
|
||||
repository: .
|
||||
commit_user_name: yasirarism
|
||||
commit_user_email: mail@yasir.eu.org
|
||||
commit_author: yasirarism <mail@yasir.eu.org>
|
||||
BIN
Calistoga-Regular.ttf
Normal file
BIN
Calistoga-Regular.ttf
Normal file
Binary file not shown.
12
Dockerfile
Normal file
12
Dockerfile
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# * @author Yasir Aris M <yasiramunandar@gmail.com>
|
||||
# * @date 2022-12-01 09:12:27
|
||||
# * @lastModified 2022-12-01 09:27:31
|
||||
# * @projectName MissKatyPyro
|
||||
# * Copyright ©YasirPedia All rights reserved
|
||||
|
||||
# Base Docker
|
||||
FROM yasirarism/misskaty-docker:latest
|
||||
|
||||
COPY . .
|
||||
# Set CMD Bot
|
||||
CMD ["python3", "-m", "misskaty"]
|
||||
339
LICENSE
Normal file
339
LICENSE
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) 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
|
||||
this service 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 make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. 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.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
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
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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 a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE 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.
|
||||
|
||||
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
|
||||
convey 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 2 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision 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, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This 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.
|
||||
64
README.md
Normal file
64
README.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<h1 align="center">
|
||||
<b>MissKaty Bot based on Pyrogram</b>
|
||||
</h1>
|
||||
|
||||
## NOTES
|
||||
This repo has many bugs and i dont have time to fix it. If you can help me, please open pull request (PR).
|
||||
|
||||
## Demo
|
||||
You can check demo this repo in this bot [MissKatyPyro](https://t.me/MissKatyRoBot)
|
||||
|
||||
## Features
|
||||
I'm forget about it, try asking doraemon maybe know.. :)
|
||||
|
||||
## Variables
|
||||
|
||||
### Required Variables
|
||||
* `BOT_TOKEN`: Create a bot using [@BotFather](https://telegram.dog/BotFather), and get the Telegram API token.
|
||||
* `API_ID`: Get this value from [telegram.org](https://my.telegram.org/apps)
|
||||
* `API_HASH`: Get this value from [telegram.org](https://my.telegram.org/apps)
|
||||
* `ADMINS`: Username or ID of Admin. Separate multiple Admins by space
|
||||
* `DATABASE_URI`: [mongoDB](https://www.mongodb.com) URI. Get this value from [mongoDB](https://www.mongodb.com). For more help watch this [video](https://youtu.be/1G1XwEOnxxo)
|
||||
* `DATABASE_NAME`: Name of the database in [mongoDB](https://www.mongodb.com). For more help watch this [video](https://youtu.be/1G1XwEOnxxo)
|
||||
* `LOG_CHANNEL` : A channel to log the activities of bot. Make sure bot is an admin in the channel.
|
||||
### Optional Variables
|
||||
Check by yourself for optional vars.
|
||||
|
||||
## Deploy (Must Use Docker to Run This Bot)
|
||||
|
||||
- Start Docker daemon (Skip if already running):
|
||||
```
|
||||
sudo dockerd
|
||||
```
|
||||
- Build Docker image:
|
||||
```
|
||||
sudo docker build . -t misskaty
|
||||
```
|
||||
- Run the image:
|
||||
```
|
||||
sudo docker run misskaty
|
||||
```
|
||||
- To stop the image:
|
||||
```
|
||||
sudo docker ps
|
||||
```
|
||||
```
|
||||
sudo docker stop id
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
|
||||
## Thanks to
|
||||
- Thanks To Allah Swt.
|
||||
- Thanks To Dan For His Awesome [Library](https://github.com/pyrogram/pyrogram).
|
||||
- Thanks To [The Hamker Cat](https://github.com/TheHamkerCat) For Some Code.
|
||||
- Thanks To [Team Yukki](https://github.com/TeamYukki) For Some Code.
|
||||
- Thanks To [Wrench](https://github.com/EverythingSuckz) For Some Code.
|
||||
- And All People Who Help Me In My Life...
|
||||
If your code used in this repo and want to give credit please open issue..
|
||||
|
||||
## Disclaimer
|
||||
[](https://www.gnu.org/licenses/agpl-3.0.en.html#header)
|
||||
Licensed under [GNU AGPL 2.0.](https://github.com/yasirarism/MissKatyPyro/blob/master/LICENSE)
|
||||
Selling The Codes To Other People For Money Is *Strictly Prohibited*. God always sees you.
|
||||
7
config.env.sample
Normal file
7
config.env.sample
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
API_HASH=
|
||||
DATABASE_NAME=
|
||||
API_ID=
|
||||
SUPPORT_CHAT=YasirPediaChannel
|
||||
DATABASE_URI=mongodb+srv://
|
||||
BOT_TOKEN=
|
||||
LOG_CHANNEL=-
|
||||
12
database/__init__.py
Normal file
12
database/__init__.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
"""
|
||||
* @author yasir <yasiramunandar@gmail.com>
|
||||
* @date 2022-09-06 10:12:09
|
||||
* @lastModified 2022-12-01 09:34:27
|
||||
* @projectName MissKatyPyro
|
||||
* Copyright @YasirPedia All rights reserved
|
||||
"""
|
||||
from motor.motor_asyncio import AsyncIOMotorClient as MongoClient
|
||||
from misskaty.vars import DATABASE_URI
|
||||
|
||||
mongo = MongoClient(DATABASE_URI)
|
||||
dbname = mongo.MissKatyDB
|
||||
31
database/afk_db.py
Normal file
31
database/afk_db.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
from database import dbname
|
||||
|
||||
usersdb = dbname.users
|
||||
|
||||
|
||||
async def is_afk(user_id: int) -> bool:
|
||||
user = await usersdb.find_one({"user_id": user_id})
|
||||
return (True, user["reason"]) if user else (False, {})
|
||||
|
||||
|
||||
async def add_afk(user_id: int, mode):
|
||||
await usersdb.update_one({"user_id": user_id}, {"$set": {
|
||||
"reason": mode
|
||||
}},
|
||||
upsert=True)
|
||||
|
||||
|
||||
async def remove_afk(user_id: int):
|
||||
user = await usersdb.find_one({"user_id": user_id})
|
||||
if user:
|
||||
return await usersdb.delete_one({"user_id": user_id})
|
||||
|
||||
|
||||
async def get_afk_users() -> list:
|
||||
users = usersdb.find({"user_id": {"$gt": 0}})
|
||||
if not users:
|
||||
return []
|
||||
users_list = []
|
||||
for user in await users.to_list(length=1000000000):
|
||||
users_list.append(user)
|
||||
return users_list
|
||||
66
database/karma_db.py
Normal file
66
database/karma_db.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
from typing import Dict, Union
|
||||
from misskaty.helper.functions import int_to_alpha
|
||||
from database import dbname
|
||||
|
||||
karmadb = dbname.karma
|
||||
|
||||
|
||||
async def get_karmas_count() -> dict:
|
||||
chats_count = 0
|
||||
karmas_count = 0
|
||||
async for chat in karmadb.find({"chat_id": {"$lt": 0}}):
|
||||
for i in chat["karma"]:
|
||||
karma_ = chat["karma"][i]["karma"]
|
||||
if karma_ > 0:
|
||||
karmas_count += karma_
|
||||
chats_count += 1
|
||||
return {"chats_count": chats_count, "karmas_count": karmas_count}
|
||||
|
||||
|
||||
async def user_global_karma(user_id) -> int:
|
||||
total_karma = 0
|
||||
async for chat in karmadb.find({"chat_id": {"$lt": 0}}):
|
||||
karma = await get_karma(chat["chat_id"], await int_to_alpha(user_id))
|
||||
if karma and (int(karma["karma"]) > 0):
|
||||
total_karma += int(karma["karma"])
|
||||
return total_karma
|
||||
|
||||
|
||||
async def get_karmas(chat_id: int) -> Dict[str, int]:
|
||||
karma = await karmadb.find_one({"chat_id": chat_id})
|
||||
return karma["karma"] if karma else {}
|
||||
|
||||
|
||||
async def get_karma(chat_id: int, name: str) -> Union[bool, dict]:
|
||||
name = name.lower().strip()
|
||||
karmas = await get_karmas(chat_id)
|
||||
if name in karmas:
|
||||
return karmas[name]
|
||||
|
||||
|
||||
async def update_karma(chat_id: int, name: str, karma: dict):
|
||||
name = name.lower().strip()
|
||||
karmas = await get_karmas(chat_id)
|
||||
karmas[name] = karma
|
||||
await karmadb.update_one(
|
||||
{"chat_id": chat_id}, {"$set": {"karma": karmas}}, upsert=True
|
||||
)
|
||||
|
||||
|
||||
async def is_karma_on(chat_id: int) -> bool:
|
||||
chat = await karmadb.find_one({"chat_id_toggle": chat_id})
|
||||
return bool(chat)
|
||||
|
||||
|
||||
async def karma_on(chat_id: int):
|
||||
is_karma = await is_karma_on(chat_id)
|
||||
if is_karma:
|
||||
return
|
||||
return await karmadb.delete_one({"chat_id_toggle": chat_id})
|
||||
|
||||
|
||||
async def karma_off(chat_id: int):
|
||||
is_karma = await is_karma_on(chat_id)
|
||||
if not is_karma:
|
||||
return
|
||||
return await karmadb.insert_one({"chat_id_toggle": chat_id})
|
||||
105
database/users_chats_db.py
Normal file
105
database/users_chats_db.py
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import motor.motor_asyncio
|
||||
from misskaty.vars import DATABASE_NAME, DATABASE_URI
|
||||
|
||||
|
||||
class Database:
|
||||
def __init__(self, uri, database_name):
|
||||
self._client = motor.motor_asyncio.AsyncIOMotorClient(uri)
|
||||
self.db = self._client[database_name]
|
||||
self.col = self.db.users
|
||||
self.grp = self.db.groups
|
||||
|
||||
def new_user(self, id, name):
|
||||
return dict(
|
||||
id=id,
|
||||
name=name,
|
||||
ban_status=dict(
|
||||
is_banned=False,
|
||||
ban_reason="",
|
||||
),
|
||||
)
|
||||
|
||||
def new_group(self, id, title):
|
||||
return dict(
|
||||
id=id,
|
||||
title=title,
|
||||
chat_status=dict(
|
||||
is_disabled=False,
|
||||
reason="",
|
||||
),
|
||||
)
|
||||
|
||||
async def add_user(self, id, name):
|
||||
user = self.new_user(id, name)
|
||||
await self.col.insert_one(user)
|
||||
|
||||
async def is_user_exist(self, id):
|
||||
user = await self.col.find_one({"id": int(id)})
|
||||
return bool(user)
|
||||
|
||||
async def total_users_count(self):
|
||||
return await self.col.count_documents({})
|
||||
|
||||
async def remove_ban(self, id):
|
||||
ban_status = dict(is_banned=False, ban_reason="")
|
||||
await self.col.update_one({"id": id}, {"$set": {"ban_status": ban_status}})
|
||||
|
||||
async def ban_user(self, user_id, ban_reason="No Reason"):
|
||||
ban_status = dict(is_banned=True, ban_reason=ban_reason)
|
||||
await self.col.update_one({"id": user_id}, {"$set": {"ban_status": ban_status}})
|
||||
|
||||
async def get_ban_status(self, id):
|
||||
default = dict(is_banned=False, ban_reason="")
|
||||
user = await self.col.find_one({"id": int(id)})
|
||||
return user.get("ban_status", default) if user else default
|
||||
|
||||
async def get_all_users(self):
|
||||
return self.col.find({})
|
||||
|
||||
async def delete_user(self, user_id):
|
||||
await self.col.delete_many({"id": int(user_id)})
|
||||
|
||||
async def get_banned(self):
|
||||
users = self.col.find({"ban_status.is_banned": True})
|
||||
chats = self.grp.find({"chat_status.is_disabled": True})
|
||||
b_chats = [chat["id"] async for chat in chats]
|
||||
b_users = [user["id"] async for user in users]
|
||||
return b_users, b_chats
|
||||
|
||||
async def add_chat(self, chat, title):
|
||||
chat = self.new_group(chat, title)
|
||||
await self.grp.insert_one(chat)
|
||||
|
||||
async def get_chat(self, chat):
|
||||
chat = await self.grp.find_one({"id": int(chat)})
|
||||
return chat.get("chat_status") if chat else False
|
||||
|
||||
async def re_enable_chat(self, id):
|
||||
chat_status = dict(
|
||||
is_disabled=False,
|
||||
reason="",
|
||||
)
|
||||
await self.grp.update_one(
|
||||
{"id": int(id)}, {"$set": {"chat_status": chat_status}}
|
||||
)
|
||||
|
||||
async def disable_chat(self, chat, reason="No Reason"):
|
||||
chat_status = dict(
|
||||
is_disabled=True,
|
||||
reason=reason,
|
||||
)
|
||||
await self.grp.update_one(
|
||||
{"id": int(chat)}, {"$set": {"chat_status": chat_status}}
|
||||
)
|
||||
|
||||
async def total_chat_count(self):
|
||||
return await self.grp.count_documents({})
|
||||
|
||||
async def get_all_chats(self):
|
||||
return self.grp.find({})
|
||||
|
||||
async def get_db_size(self):
|
||||
return (await self.db.command("dbstats"))["dataSize"]
|
||||
|
||||
|
||||
db = Database(DATABASE_URI, DATABASE_NAME)
|
||||
53
database/warn_db.py
Normal file
53
database/warn_db.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
from typing import Dict, Union
|
||||
from database import dbname
|
||||
|
||||
warnsdb = dbname.warn
|
||||
|
||||
|
||||
async def get_warns_count() -> dict:
|
||||
chats_count = 0
|
||||
warns_count = 0
|
||||
async for chat in warnsdb.find({"chat_id": {"$lt": 0}}):
|
||||
for user in chat["warns"]:
|
||||
warns_count += chat["warns"][user]["warns"]
|
||||
chats_count += 1
|
||||
return {"chats_count": chats_count, "warns_count": warns_count}
|
||||
|
||||
|
||||
async def get_warns(chat_id: int) -> Dict[str, int]:
|
||||
warns = await warnsdb.find_one({"chat_id": chat_id})
|
||||
return warns["warns"] if warns else {}
|
||||
|
||||
|
||||
async def get_warn(chat_id: int, name: str) -> Union[bool, dict]:
|
||||
name = name.lower().strip()
|
||||
warns = await get_warns(chat_id)
|
||||
if name in warns:
|
||||
return warns[name]
|
||||
|
||||
|
||||
async def add_warn(chat_id: int, name: str, warn: dict):
|
||||
name = name.lower().strip()
|
||||
warns = await get_warns(chat_id)
|
||||
warns[name] = warn
|
||||
|
||||
await warnsdb.update_one({"chat_id": chat_id}, {"$set": {
|
||||
"warns": warns
|
||||
}},
|
||||
upsert=True)
|
||||
|
||||
|
||||
async def remove_warns(chat_id: int, name: str) -> bool:
|
||||
warnsd = await get_warns(chat_id)
|
||||
name = name.lower().strip()
|
||||
if name in warnsd:
|
||||
del warnsd[name]
|
||||
await warnsdb.update_one(
|
||||
{"chat_id": chat_id},
|
||||
{"$set": {
|
||||
"warns": warnsd
|
||||
}},
|
||||
upsert=True,
|
||||
)
|
||||
return True
|
||||
return False
|
||||
BIN
img/bg.png
Normal file
BIN
img/bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
img/profilepic.png
Normal file
BIN
img/profilepic.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
32
logging.conf
Normal file
32
logging.conf
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
[loggers]
|
||||
keys=root
|
||||
|
||||
[handlers]
|
||||
keys=consoleHandler,fileHandler
|
||||
|
||||
[formatters]
|
||||
keys=consoleFormatter,fileFormatter
|
||||
|
||||
[logger_root]
|
||||
level=DEBUG
|
||||
handlers=consoleHandler,fileHandler
|
||||
|
||||
[handler_consoleHandler]
|
||||
class=StreamHandler
|
||||
level=INFO
|
||||
formatter=consoleFormatter
|
||||
args=(sys.stdout,)
|
||||
|
||||
[handler_fileHandler]
|
||||
class=FileHandler
|
||||
level=ERROR
|
||||
formatter=fileFormatter
|
||||
args=('MissKatyLogs.txt','w',)
|
||||
|
||||
[formatter_consoleFormatter]
|
||||
format=%(asctime)s - %(lineno)d - %(name)s - %(module)s - %(levelname)s - %(message)s
|
||||
datefmt=%I:%M:%S %p
|
||||
|
||||
[formatter_fileFormatter]
|
||||
format=[%(asctime)s:%(name)s:%(lineno)d:%(levelname)s] %(message)s
|
||||
datefmt=%m/%d/%Y %I:%M:%S %p
|
||||
31
misskaty/__init__.py
Normal file
31
misskaty/__init__.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import logging
|
||||
import time
|
||||
import logging.config
|
||||
|
||||
# Get logging
|
||||
logging.config.fileConfig("logging.conf")
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
logging.getLogger("pyrogram").setLevel(logging.ERROR)
|
||||
from pyrogram import Client
|
||||
from misskaty.vars import API_ID, API_HASH, BOT_TOKEN, USER_SESSION
|
||||
|
||||
MOD_LOAD = []
|
||||
MOD_NOLOAD = []
|
||||
HELPABLE = {}
|
||||
|
||||
botStartTime = time.time()
|
||||
|
||||
# Pyrogram Bot Client
|
||||
app = Client(
|
||||
name="MissKatyBot",
|
||||
api_id=API_ID,
|
||||
api_hash=API_HASH,
|
||||
bot_token=BOT_TOKEN,
|
||||
sleep_threshold=5,
|
||||
)
|
||||
|
||||
# Pyrogram UserBot Client
|
||||
user = Client(
|
||||
name="YasirUBot",
|
||||
session_string=USER_SESSION,
|
||||
)
|
||||
342
misskaty/__main__.py
Normal file
342
misskaty/__main__.py
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
"""
|
||||
* @author yasir <yasiramunandar@gmail.com>
|
||||
* @date 2022-12-01 09:12:27
|
||||
* @lastModified 2022-12-01 09:33:16
|
||||
* @projectName MissKatyPyro
|
||||
* Copyright @YasirPedia All rights reserved
|
||||
"""
|
||||
import asyncio, importlib, re, logging
|
||||
from misskaty import app, user, HELPABLE
|
||||
from misskaty.plugins import ALL_MODULES
|
||||
from misskaty.helper import paginate_modules
|
||||
from misskaty.helper.tools import bot_sys_stats
|
||||
from database.users_chats_db import db
|
||||
from misskaty.vars import LOG_CHANNEL
|
||||
from utils import temp
|
||||
from logging import info as log_info
|
||||
from pyrogram.raw.all import layer
|
||||
from pyrogram import idle, __version__, filters
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
|
||||
# Run Bot
|
||||
async def start_bot():
|
||||
global HELPABLE
|
||||
|
||||
for module in ALL_MODULES:
|
||||
imported_module = importlib.import_module(f"misskaty.plugins.{module}")
|
||||
if hasattr(imported_module, "__MODULE__") and imported_module.__MODULE__:
|
||||
imported_module.__MODULE__ = imported_module.__MODULE__
|
||||
if hasattr(imported_module, "__HELP__") and imported_module.__HELP__:
|
||||
HELPABLE[imported_module.__MODULE__.lower()] = imported_module
|
||||
bot_modules = ""
|
||||
j = 1
|
||||
for i in ALL_MODULES:
|
||||
if j == 4:
|
||||
bot_modules += "|{:<15}|\n".format(i)
|
||||
j = 0
|
||||
else:
|
||||
bot_modules += "|{:<15}".format(i)
|
||||
j += 1
|
||||
await app.start()
|
||||
await user.start()
|
||||
me = await app.get_me()
|
||||
ubot = await user.get_me()
|
||||
log_info("+===============================================================+")
|
||||
log_info("| MissKatyPyro |")
|
||||
log_info("+===============+===============+===============+===============+")
|
||||
log_info(bot_modules)
|
||||
log_info("+===============+===============+===============+===============+")
|
||||
log_info(f"[INFO]: BOT STARTED AS @{me.username}!")
|
||||
|
||||
try:
|
||||
log_info("[INFO]: SENDING ONLINE STATUS")
|
||||
await app.send_message(
|
||||
617426792,
|
||||
f"USERBOT AND BOT STARTED with Pyrogram v{__version__}..\nUserBot: {ubot.first_name}\nBot: {me.first_name}\n\nwith Pyrogram v{__version__} (Layer {layer}) started on @{me.username}.",
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
await idle()
|
||||
await app.stop()
|
||||
await user.stop()
|
||||
print("[INFO]: Bye!")
|
||||
|
||||
|
||||
home_keyboard_pm = InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(text="Commands ❓", callback_data="bot_commands"),
|
||||
InlineKeyboardButton(
|
||||
text="Github Repo 🛠",
|
||||
url="https://github.com/yasirarism/MissKatyPyro",
|
||||
),
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="System Stats 🖥",
|
||||
callback_data="stats_callback",
|
||||
),
|
||||
InlineKeyboardButton(text="Dev 👨", url="https://t.me/YasirArisM"),
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="Add Me To Your Group 🎉",
|
||||
url="http://t.me/MissKatyRoBot?startgroup=new",
|
||||
)
|
||||
],
|
||||
]
|
||||
)
|
||||
|
||||
home_text_pm = f"Hey there! My name is MissKatyRoBot. I have many useful features for you, feel free to add me to your group.\n\nIf you want give coffee to my owner you can send /donate command for more info."
|
||||
|
||||
keyboard = InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(text="Help ❓", url="t.me/MissKatyRoBot?start=help"),
|
||||
InlineKeyboardButton(
|
||||
text="Github Repo <20>",
|
||||
url="https://github.com/yasirarism/MissKatyPyro",
|
||||
),
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="System Stats 💻",
|
||||
callback_data="stats_callback",
|
||||
),
|
||||
InlineKeyboardButton(text="Dev 👨", url="https://t.me/YasirArisM"),
|
||||
],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(filters.command("start"))
|
||||
async def start(_, message):
|
||||
if message.chat.type.value != "private":
|
||||
if not await db.get_chat(message.chat.id):
|
||||
total = await app.get_chat_members_count(message.chat.id)
|
||||
await app.send_message(
|
||||
LOG_CHANNEL,
|
||||
f"#NewGroup\nGroup = {message.chat.title}(<code>{message.chat.id}</code>)\nMembers Count = <code>{total}</code>\nAdded by - Unknown",
|
||||
)
|
||||
|
||||
await db.add_chat(message.chat.id, message.chat.title)
|
||||
nama = (
|
||||
message.from_user.mention
|
||||
if message.from_user
|
||||
else message.sender_chat.title
|
||||
)
|
||||
return await message.reply_photo(
|
||||
photo="https://telegra.ph/file/90e9a448bc2f8b055b762.jpg",
|
||||
caption=f"Hi {nama}, Pm Me For More Info About Me.",
|
||||
reply_markup=keyboard,
|
||||
)
|
||||
if not await db.is_user_exist(message.from_user.id):
|
||||
await db.add_user(message.from_user.id, message.from_user.first_name)
|
||||
await app.send_message(
|
||||
LOG_CHANNEL,
|
||||
f"#NewUser\nID - <code>{message.from_user.id}</code>\nName - {message.from_user.mention}",
|
||||
)
|
||||
|
||||
if len(message.text.split()) > 1:
|
||||
name = (message.text.split(None, 1)[1]).lower()
|
||||
if "_" in name:
|
||||
module = name.split("_", 1)[1]
|
||||
text = (
|
||||
f"Here is the help for **{HELPABLE[module].__MODULE__}**:\n"
|
||||
+ HELPABLE[module].__HELP__
|
||||
)
|
||||
await message.reply(text, disable_web_page_preview=True)
|
||||
elif name == "help":
|
||||
text, keyb = await help_parser(message.from_user.first_name)
|
||||
await message.reply(
|
||||
text,
|
||||
reply_markup=keyb,
|
||||
)
|
||||
else:
|
||||
await message.reply_photo(
|
||||
photo="https://telegra.ph/file/90e9a448bc2f8b055b762.jpg",
|
||||
caption=home_text_pm,
|
||||
reply_markup=home_keyboard_pm,
|
||||
)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("bot_commands"))
|
||||
async def commands_callbacc(_, CallbackQuery):
|
||||
text, keyboard = await help_parser(CallbackQuery.from_user.mention)
|
||||
await app.send_message(
|
||||
CallbackQuery.message.chat.id,
|
||||
text=text,
|
||||
reply_markup=keyboard,
|
||||
)
|
||||
|
||||
await CallbackQuery.message.delete()
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("stats_callback"))
|
||||
async def stats_callbacc(_, CallbackQuery):
|
||||
text = await bot_sys_stats()
|
||||
await app.answer_callback_query(CallbackQuery.id, text, show_alert=True)
|
||||
|
||||
|
||||
@app.on_message(filters.command("help"))
|
||||
async def help_command(_, message):
|
||||
if message.chat.type.value != "private":
|
||||
if not await db.get_chat(message.chat.id):
|
||||
total = await app.get_chat_members_count(message.chat.id)
|
||||
await app.send_message(
|
||||
LOG_CHANNEL,
|
||||
f"#NewGroup\nGroup = {message.chat.title}(<code>{message.chat.id}</code>)\nMembers Count = <code>{total}</code>\nAdded by - Unknown",
|
||||
)
|
||||
|
||||
await db.add_chat(message.chat.id, message.chat.title)
|
||||
if len(message.command) >= 2:
|
||||
name = (message.text.split(None, 1)[1]).replace(" ", "_").lower()
|
||||
if str(name) in HELPABLE:
|
||||
key = InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="Click here",
|
||||
url=f"t.me/MissKatyRoBot?start=help_{name}",
|
||||
)
|
||||
],
|
||||
]
|
||||
)
|
||||
await message.reply(
|
||||
f"Click on the below button to get help about {name}",
|
||||
reply_markup=key,
|
||||
)
|
||||
else:
|
||||
await message.reply("PM Me For More Details.", reply_markup=keyboard)
|
||||
else:
|
||||
await message.reply("Pm Me For More Details.", reply_markup=keyboard)
|
||||
else:
|
||||
if not await db.is_user_exist(message.from_user.id):
|
||||
await db.add_user(message.from_user.id, message.from_user.first_name)
|
||||
await app.send_message(
|
||||
LOG_CHANNEL,
|
||||
f"#NewUser\nID - <code>{message.from_user.id}</code>\nName - {message.from_user.mention}",
|
||||
)
|
||||
|
||||
if len(message.command) >= 2:
|
||||
name = (message.text.split(None, 1)[1]).replace(" ", "_").lower()
|
||||
if str(name) in HELPABLE:
|
||||
text = (
|
||||
f"Here is the help for **{HELPABLE[name].__MODULE__}**:\n"
|
||||
+ HELPABLE[name].__HELP__
|
||||
)
|
||||
await message.reply(text, disable_web_page_preview=True)
|
||||
else:
|
||||
text, help_keyboard = await help_parser(message.from_user.first_name)
|
||||
await message.reply(
|
||||
text,
|
||||
reply_markup=help_keyboard,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
else:
|
||||
text, help_keyboard = await help_parser(message.from_user.first_name)
|
||||
await message.reply(
|
||||
text, reply_markup=help_keyboard, disable_web_page_preview=True
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
async def help_parser(name, keyboard=None):
|
||||
if not keyboard:
|
||||
keyboard = InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help"))
|
||||
return (
|
||||
"""Hello {first_name}, My name is {bot_name}.
|
||||
I'm a bot with some useful features.
|
||||
You can choose an option below, by clicking a button.
|
||||
|
||||
If you want give coffee to my owner you can send /donate command for more info.
|
||||
""".format(
|
||||
first_name=name,
|
||||
bot_name="MissKaty",
|
||||
),
|
||||
keyboard,
|
||||
)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"help_(.*?)"))
|
||||
async def help_button(client, query):
|
||||
home_match = re.match(r"help_home\((.+?)\)", query.data)
|
||||
mod_match = re.match(r"help_module\((.+?)\)", query.data)
|
||||
prev_match = re.match(r"help_prev\((.+?)\)", query.data)
|
||||
next_match = re.match(r"help_next\((.+?)\)", query.data)
|
||||
back_match = re.match(r"help_back", query.data)
|
||||
create_match = re.match(r"help_create", query.data)
|
||||
top_text = f"""
|
||||
Hello {query.from_user.first_name}, My name is MissKaty.
|
||||
I'm a bot with some usefule features.
|
||||
You can choose an option below, by clicking a button below.
|
||||
|
||||
General command are:
|
||||
- /start: Start the bot
|
||||
- /help: Give this message
|
||||
"""
|
||||
if mod_match:
|
||||
module = mod_match[1].replace(" ", "_")
|
||||
text = f"Here is the help for **{HELPABLE[module].__MODULE__}**:\n{HELPABLE[module].__HELP__}"
|
||||
|
||||
await query.message.edit(
|
||||
text=text,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton("back", callback_data="help_back")]]
|
||||
),
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
elif home_match:
|
||||
await app.send_message(
|
||||
query.from_user.id,
|
||||
text=home_text_pm,
|
||||
reply_markup=home_keyboard_pm,
|
||||
)
|
||||
await query.message.delete()
|
||||
elif prev_match:
|
||||
curr_page = int(prev_match[1])
|
||||
await query.message.edit(
|
||||
text=top_text,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
paginate_modules(curr_page - 1, HELPABLE, "help")
|
||||
),
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
elif next_match:
|
||||
next_page = int(next_match[1])
|
||||
await query.message.edit(
|
||||
text=top_text,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
paginate_modules(next_page + 1, HELPABLE, "help")
|
||||
),
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
elif back_match:
|
||||
await query.message.edit(
|
||||
text=top_text,
|
||||
reply_markup=InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help")),
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
elif create_match:
|
||||
text, keyboard = await help_parser(query)
|
||||
await query.message.edit(
|
||||
text=text,
|
||||
reply_markup=keyboard,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
return await client.answer_callback_query(query.id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
loop.run_until_complete(start_bot())
|
||||
except KeyboardInterrupt:
|
||||
logging.info("----------------------- Service Stopped -----------------------")
|
||||
59
misskaty/core/decorator/errors.py
Normal file
59
misskaty/core/decorator/errors.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import traceback, asyncio
|
||||
from functools import wraps
|
||||
from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
|
||||
from misskaty.vars import LOG_CHANNEL
|
||||
from misskaty import app
|
||||
|
||||
|
||||
def asyncify(func):
|
||||
async def inner(*args, **kwargs):
|
||||
loop = asyncio.get_running_loop()
|
||||
func_out = await loop.run_in_executor(None, func, *args, **kwargs)
|
||||
return func_out
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
def split_limits(text):
|
||||
if len(text) < 2048:
|
||||
return [text]
|
||||
|
||||
lines = text.splitlines(True)
|
||||
small_msg = ""
|
||||
result = []
|
||||
for line in lines:
|
||||
if len(small_msg) + len(line) < 2048:
|
||||
small_msg += line
|
||||
else:
|
||||
result.append(small_msg)
|
||||
small_msg = line
|
||||
result.append(small_msg)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def capture_err(func):
|
||||
@wraps(func)
|
||||
async def capture(client, message, *args, **kwargs):
|
||||
try:
|
||||
return await func(client, message, *args, **kwargs)
|
||||
except ChatWriteForbidden:
|
||||
await app.leave_chat(message.chat.id)
|
||||
return
|
||||
except Exception as err:
|
||||
exc = traceback.format_exc()
|
||||
error_feedback = split_limits(
|
||||
"**ERROR** | `{}` | `{}`\n\n```{}```\n\n```{}```\n".format(
|
||||
message.from_user.id if message.from_user else 0,
|
||||
message.chat.id if message.chat else 0,
|
||||
message.text or message.caption,
|
||||
exc,
|
||||
)
|
||||
)
|
||||
|
||||
for x in error_feedback:
|
||||
await app.send_message(LOG_CHANNEL, x)
|
||||
await message.reply(x)
|
||||
raise err
|
||||
|
||||
return capture
|
||||
109
misskaty/core/decorator/permissions.py
Normal file
109
misskaty/core/decorator/permissions.py
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
from functools import wraps
|
||||
from traceback import format_exc as err
|
||||
from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
|
||||
from pyrogram.types import Message
|
||||
from pyrogram import enums
|
||||
from misskaty import app
|
||||
from misskaty.vars import SUDO
|
||||
from time import time
|
||||
|
||||
|
||||
async def member_permissions(chat_id: int, user_id: int):
|
||||
perms = []
|
||||
try:
|
||||
member = await app.get_chat_member(chat_id, user_id)
|
||||
perijinan = member.privileges
|
||||
except Exception:
|
||||
return []
|
||||
if member.status != enums.ChatMemberStatus.MEMBER:
|
||||
if perijinan.can_post_messages:
|
||||
perms.append("can_post_messages")
|
||||
if perijinan.can_edit_messages:
|
||||
perms.append("can_edit_messages")
|
||||
if perijinan.can_delete_messages:
|
||||
perms.append("can_delete_messages")
|
||||
if perijinan.can_restrict_members:
|
||||
perms.append("can_restrict_members")
|
||||
if perijinan.can_promote_members:
|
||||
perms.append("can_promote_members")
|
||||
if perijinan.can_change_info:
|
||||
perms.append("can_change_info")
|
||||
if perijinan.can_invite_users:
|
||||
perms.append("can_invite_users")
|
||||
if perijinan.can_pin_messages:
|
||||
perms.append("can_pin_messages")
|
||||
if perijinan.can_manage_video_chats:
|
||||
perms.append("can_manage_video_chats")
|
||||
return perms
|
||||
|
||||
|
||||
admins_in_chat = {}
|
||||
|
||||
|
||||
async def list_admins(chat_id: int):
|
||||
global admins_in_chat
|
||||
if chat_id in admins_in_chat:
|
||||
interval = time() - admins_in_chat[chat_id]["last_updated_at"]
|
||||
if interval < 3600:
|
||||
return admins_in_chat[chat_id]["data"]
|
||||
|
||||
admins_in_chat[chat_id] = {
|
||||
"last_updated_at": time(),
|
||||
"data": [member.user.id async for member in app.get_chat_members(chat_id, filter=enums.ChatMembersFilter.ADMINISTRATORS)],
|
||||
}
|
||||
return admins_in_chat[chat_id]["data"]
|
||||
|
||||
|
||||
async def authorised(func, subFunc2, client, message, *args, **kwargs):
|
||||
chatID = message.chat.id
|
||||
try:
|
||||
await func(client, message, *args, **kwargs)
|
||||
except ChatWriteForbidden:
|
||||
await app.leave_chat(chatID)
|
||||
except Exception as e:
|
||||
try:
|
||||
await message.reply_text(str(e.MESSAGE))
|
||||
except AttributeError:
|
||||
await message.reply_text(str(e))
|
||||
e = err()
|
||||
print(e)
|
||||
return subFunc2
|
||||
|
||||
|
||||
async def unauthorised(message: Message, permission, subFunc2):
|
||||
chatID = message.chat.id
|
||||
text = "You don't have the required permission to perform this action." + f"\n**Permission:** __{permission}__"
|
||||
try:
|
||||
await message.reply_text(text)
|
||||
except ChatWriteForbidden:
|
||||
await app.leave_chat(chatID)
|
||||
return subFunc2
|
||||
|
||||
|
||||
def adminsOnly(permission):
|
||||
def subFunc(func):
|
||||
@wraps(func)
|
||||
async def subFunc2(client, message: Message, *args, **kwargs):
|
||||
chatID = message.chat.id
|
||||
if not message.from_user:
|
||||
# For anonymous admins
|
||||
if message.sender_chat and message.sender_chat.id == message.chat.id:
|
||||
return await authorised(
|
||||
func,
|
||||
subFunc2,
|
||||
client,
|
||||
message,
|
||||
*args,
|
||||
**kwargs,
|
||||
)
|
||||
return await unauthorised(message, permission, subFunc2)
|
||||
# For admins and sudo users
|
||||
userID = message.from_user.id
|
||||
permissions = await member_permissions(chatID, userID)
|
||||
if userID not in SUDO and permission not in permissions:
|
||||
return await unauthorised(message, permission, subFunc2)
|
||||
return await authorised(func, subFunc2, client, message, *args, **kwargs)
|
||||
|
||||
return subFunc2
|
||||
|
||||
return subFunc
|
||||
26
misskaty/core/keyboard.py
Normal file
26
misskaty/core/keyboard.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
from pykeyboard import InlineKeyboard
|
||||
from pyrogram.types import InlineKeyboardButton as Ikb
|
||||
|
||||
from misskaty.helper.functions import get_urls_from_text as is_url
|
||||
|
||||
|
||||
def keyboard(buttons_list, row_width: int = 2):
|
||||
"""
|
||||
Buttons builder, pass buttons in a list and it will
|
||||
return pyrogram.types.IKB object
|
||||
Ex: keyboard([["click here", "https://google.com"]])
|
||||
if theres, a url, it will make url button, else callback button
|
||||
"""
|
||||
buttons = InlineKeyboard(row_width=row_width)
|
||||
data = [Ikb(text=str(i[0]), url=str(i[1])) if is_url(i[1]) else Ikb(text=str(i[0]), callback_data=str(i[1])) for i in buttons_list]
|
||||
|
||||
buttons.add(*data)
|
||||
return buttons
|
||||
|
||||
|
||||
def ikb(data: dict, row_width: int = 2):
|
||||
"""
|
||||
Converts a dict to pyrogram buttons
|
||||
Ex: dict_to_keyboard({"click here": "this is callback data"})
|
||||
"""
|
||||
return keyboard(data.items(), row_width=row_width)
|
||||
1
misskaty/helper/__init__.py
Normal file
1
misskaty/helper/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .misc import paginate_modules
|
||||
61
misskaty/helper/ffmpeg_helper.py
Normal file
61
misskaty/helper/ffmpeg_helper.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import asyncio
|
||||
import os
|
||||
import time
|
||||
from pyrogram.types import InputMediaPhoto
|
||||
from misskaty.plugins.dev import shell_exec
|
||||
from pyrogram.errors import FloodWait
|
||||
|
||||
|
||||
def hhmmss(seconds):
|
||||
return time.strftime("%H:%M:%S", time.gmtime(seconds))
|
||||
|
||||
|
||||
async def take_ss(video_file):
|
||||
out_put_file_name = f"genss{str(time.time())}.png"
|
||||
cmd = f"ssmedia '{video_file}' -t -w 1340 -g 4x4 --ffmpeg-name mediaextract --quality 100 --end-delay-percent 20 --metadata-font-size 30 --timestamp-font-size 20 -o {out_put_file_name}"
|
||||
await shell_exec(cmd)
|
||||
return out_put_file_name if os.path.lexists(out_put_file_name) else None
|
||||
|
||||
|
||||
async def ssgen_link(video, output_directory, ttl):
|
||||
out_put_file_name = f"{output_directory}/{str(time.time())}.png"
|
||||
cmd = [
|
||||
"mediaextract",
|
||||
"-ss",
|
||||
str(ttl),
|
||||
"-i",
|
||||
video,
|
||||
"-vframes",
|
||||
"1",
|
||||
"-f",
|
||||
"image2",
|
||||
out_put_file_name,
|
||||
]
|
||||
process = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
||||
|
||||
stdout, stderr = await process.communicate()
|
||||
stderr.decode().strip()
|
||||
stdout.decode().strip()
|
||||
return out_put_file_name if os.path.isfile(out_put_file_name) else None
|
||||
|
||||
|
||||
async def genss_link(msg, video_link, output_directory, min_duration, no_of_photos):
|
||||
metadata = (await shell_exec(f"ffprobe -i {video_link} -show_entries format=duration -v quiet -of csv='p=0'"))[0]
|
||||
duration = round(float(metadata))
|
||||
if duration > min_duration:
|
||||
images = []
|
||||
ttl_step = duration // no_of_photos
|
||||
current_ttl = ttl_step
|
||||
for looper in range(no_of_photos):
|
||||
ss_img = await ssgen_link(video_link, output_directory, current_ttl)
|
||||
images.append(InputMediaPhoto(media=ss_img, caption=f"Screenshot at {hhmmss(current_ttl)}"))
|
||||
try:
|
||||
await msg.edit(f"📸 <b>Take Screenshoot:</b>\n<code>{looper+1} of {no_of_photos} screenshot generated..</code>")
|
||||
except FloodWait as e:
|
||||
await asyncio.sleep(e.value)
|
||||
await msg.edit(f"📸 <b>Take Screenshoot:</b>\n<code>{looper+1} of {no_of_photos} screenshot generated..</code>")
|
||||
current_ttl = current_ttl + ttl_step
|
||||
await asyncio.sleep(2)
|
||||
return images
|
||||
else:
|
||||
return None
|
||||
82
misskaty/helper/files.py
Normal file
82
misskaty/helper/files.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
"""
|
||||
MIT License
|
||||
Copyright (c) 2021 TheHamkerCat
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
import math
|
||||
import os
|
||||
|
||||
from PIL import Image
|
||||
from pyrogram import Client, raw
|
||||
from pyrogram.file_id import FileId
|
||||
|
||||
STICKER_DIMENSIONS = (512, 512)
|
||||
|
||||
|
||||
async def resize_file_to_sticker_size(file_path: str) -> str:
|
||||
im = Image.open(file_path)
|
||||
if (im.width, im.height) < STICKER_DIMENSIONS:
|
||||
size1 = im.width
|
||||
size2 = im.height
|
||||
if im.width > im.height:
|
||||
scale = STICKER_DIMENSIONS[0] / size1
|
||||
size1new = STICKER_DIMENSIONS[0]
|
||||
size2new = size2 * scale
|
||||
else:
|
||||
scale = STICKER_DIMENSIONS[1] / size2
|
||||
size1new = size1 * scale
|
||||
size2new = STICKER_DIMENSIONS[1]
|
||||
size1new = math.floor(size1new)
|
||||
size2new = math.floor(size2new)
|
||||
sizenew = (size1new, size2new)
|
||||
im = im.resize(sizenew)
|
||||
else:
|
||||
im.thumbnail(STICKER_DIMENSIONS)
|
||||
try:
|
||||
os.remove(file_path)
|
||||
return f"{file_path}.png"
|
||||
finally:
|
||||
im.save(file_path)
|
||||
|
||||
|
||||
async def upload_document(client: Client, file_path: str, chat_id: int) -> raw.base.InputDocument:
|
||||
media = await client.send(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await client.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaUploadedDocument(
|
||||
mime_type=client.guess_mime_type(file_path) or "application/zip",
|
||||
file=await client.save_file(file_path),
|
||||
attributes=[raw.types.DocumentAttributeFilename(file_name=os.path.basename(file_path))],
|
||||
),
|
||||
)
|
||||
)
|
||||
return raw.types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference,
|
||||
)
|
||||
|
||||
|
||||
async def get_document_from_file_id(
|
||||
file_id: str,
|
||||
) -> raw.base.InputDocument:
|
||||
decoded = FileId.decode(file_id)
|
||||
return raw.types.InputDocument(
|
||||
id=decoded.media_id,
|
||||
access_hash=decoded.access_hash,
|
||||
file_reference=decoded.file_reference,
|
||||
)
|
||||
109
misskaty/helper/functions.py
Normal file
109
misskaty/helper/functions.py
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
from pyrogram import enums
|
||||
from datetime import datetime, timedelta
|
||||
from string import ascii_lowercase
|
||||
from re import findall
|
||||
|
||||
|
||||
def get_urls_from_text(text: str) -> bool:
|
||||
regex = r"""(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]
|
||||
[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(
|
||||
\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\
|
||||
()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".strip()
|
||||
return [x[0] for x in findall(regex, text)]
|
||||
|
||||
|
||||
async def alpha_to_int(user_id_alphabet: str) -> int:
|
||||
alphabet = list(ascii_lowercase)[:10]
|
||||
user_id = ""
|
||||
for i in user_id_alphabet:
|
||||
index = alphabet.index(i)
|
||||
user_id += str(index)
|
||||
return int(user_id)
|
||||
|
||||
|
||||
async def int_to_alpha(user_id: int) -> str:
|
||||
alphabet = list(ascii_lowercase)[:10]
|
||||
user_id = str(user_id)
|
||||
return "".join(alphabet[int(i)] for i in user_id)
|
||||
|
||||
|
||||
async def extract_userid(message, text: str):
|
||||
"""
|
||||
NOT TO BE USED OUTSIDE THIS FILE
|
||||
"""
|
||||
|
||||
def is_int(text: str):
|
||||
try:
|
||||
int(text)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
text = text.strip()
|
||||
|
||||
if is_int(text):
|
||||
return int(text)
|
||||
|
||||
entities = message.entities
|
||||
app = message._client
|
||||
if len(entities) < 2:
|
||||
return (await app.get_users(text)).id
|
||||
entity = entities[1]
|
||||
if entity.type == enums.MessageEntityType.MENTION:
|
||||
return (await app.get_users(text)).id
|
||||
if entity.type == enums.MessageEntityType.MENTION:
|
||||
return entity.user.id
|
||||
return None
|
||||
|
||||
|
||||
async def extract_user_and_reason(message, sender_chat=False):
|
||||
args = message.text.strip().split()
|
||||
text = message.text
|
||||
user = None
|
||||
reason = None
|
||||
if message.reply_to_message:
|
||||
reply = message.reply_to_message
|
||||
# if reply to a message and no reason is given
|
||||
if reply.from_user:
|
||||
id_ = reply.from_user.id
|
||||
|
||||
elif reply.sender_chat and reply.sender_chat != message.chat.id and sender_chat:
|
||||
id_ = reply.sender_chat.id
|
||||
else:
|
||||
return None, None
|
||||
reason = None if len(args) < 2 else text.split(None, 1)[1]
|
||||
return id_, reason
|
||||
|
||||
# if not reply to a message and no reason is given
|
||||
if len(args) == 2:
|
||||
user = text.split(None, 1)[1]
|
||||
return await extract_userid(message, user), None
|
||||
|
||||
# if reason is given
|
||||
if len(args) > 2:
|
||||
user, reason = text.split(None, 2)[1:]
|
||||
return await extract_userid(message, user), reason
|
||||
|
||||
return user, reason
|
||||
|
||||
|
||||
async def extract_user(message):
|
||||
return (await extract_user_and_reason(message))[0]
|
||||
|
||||
|
||||
async def time_converter(message, time_value: str) -> int:
|
||||
unit = ["m", "h", "d"] # m == minutes | h == hours | d == days
|
||||
check_unit = "".join(list(filter(time_value[-1].lower().endswith, unit)))
|
||||
currunt_time = datetime.now()
|
||||
time_digit = time_value[:-1]
|
||||
if not time_digit.isdigit():
|
||||
return await message.reply_text("Incorrect time specified")
|
||||
if check_unit == "m":
|
||||
temp_time = currunt_time + timedelta(minutes=int(time_digit))
|
||||
elif check_unit == "h":
|
||||
temp_time = currunt_time + timedelta(hours=int(time_digit))
|
||||
elif check_unit == "d":
|
||||
temp_time = currunt_time + timedelta(days=int(time_digit))
|
||||
else:
|
||||
return await message.reply_text("Incorrect time specified.")
|
||||
return int(datetime.timestamp(temp_time))
|
||||
78
misskaty/helper/http.py
Normal file
78
misskaty/helper/http.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
MIT License
|
||||
Copyright (c) 2021 TheHamkerCat
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
import httpx
|
||||
from asyncio import gather
|
||||
from aiohttp import ClientSession
|
||||
|
||||
# Aiohttp Async Client
|
||||
session = ClientSession()
|
||||
|
||||
# HTTPx Async Client
|
||||
http = httpx.AsyncClient(
|
||||
http2=True,
|
||||
timeout=httpx.Timeout(40),
|
||||
)
|
||||
|
||||
|
||||
async def get(url: str, *args, **kwargs):
|
||||
async with session.get(url, *args, **kwargs) as resp:
|
||||
try:
|
||||
data = await resp.json()
|
||||
except Exception:
|
||||
data = await resp.text()
|
||||
return data
|
||||
|
||||
|
||||
async def head(url: str, *args, **kwargs):
|
||||
async with session.head(url, *args, **kwargs) as resp:
|
||||
try:
|
||||
data = await resp.json()
|
||||
except Exception:
|
||||
data = await resp.text()
|
||||
return data
|
||||
|
||||
|
||||
async def post(url: str, *args, **kwargs):
|
||||
async with session.post(url, *args, **kwargs) as resp:
|
||||
try:
|
||||
data = await resp.json()
|
||||
except Exception:
|
||||
data = await resp.text()
|
||||
return data
|
||||
|
||||
|
||||
async def multiget(url: str, times: int, *args, **kwargs):
|
||||
return await gather(*[get(url, *args, **kwargs) for _ in range(times)])
|
||||
|
||||
|
||||
async def multihead(url: str, times: int, *args, **kwargs):
|
||||
return await gather(*[head(url, *args, **kwargs) for _ in range(times)])
|
||||
|
||||
|
||||
async def multipost(url: str, times: int, *args, **kwargs):
|
||||
return await gather(*[post(url, *args, **kwargs) for _ in range(times)])
|
||||
|
||||
|
||||
async def resp_get(url: str, *args, **kwargs):
|
||||
return await session.get(url, *args, **kwargs)
|
||||
|
||||
|
||||
async def resp_post(url: str, *args, **kwargs):
|
||||
return await session.post(url, *args, **kwargs)
|
||||
54
misskaty/helper/human_read.py
Normal file
54
misskaty/helper/human_read.py
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
SIZE_UNITS = ["B", "KB", "MB", "GB", "TB", "PB"]
|
||||
|
||||
|
||||
def get_readable_file_size(size_in_bytes) -> str:
|
||||
if size_in_bytes is None:
|
||||
return "0B"
|
||||
index = 0
|
||||
while size_in_bytes >= 1024:
|
||||
size_in_bytes /= 1024
|
||||
index += 1
|
||||
try:
|
||||
return f"{round(size_in_bytes, 2)}{SIZE_UNITS[index]}"
|
||||
except IndexError:
|
||||
return "File too large"
|
||||
|
||||
|
||||
def get_readable_time(seconds: int) -> str:
|
||||
result = ""
|
||||
(days, remainder) = divmod(seconds, 86400)
|
||||
days = int(days)
|
||||
if days != 0:
|
||||
result += f"{days} day "
|
||||
(hours, remainder) = divmod(remainder, 3600)
|
||||
hours = int(hours)
|
||||
if hours != 0:
|
||||
result += f"{hours} hour "
|
||||
(minutes, seconds) = divmod(remainder, 60)
|
||||
minutes = int(minutes)
|
||||
if minutes != 0:
|
||||
result += f"{minutes} minute "
|
||||
seconds = int(seconds)
|
||||
result += f"{seconds} second "
|
||||
return result
|
||||
|
||||
|
||||
def get_readable_time2(seconds: int) -> str:
|
||||
count = 0
|
||||
ping_time = ""
|
||||
time_list = []
|
||||
time_suffix_list = ["second", "minute", "hour", "day", "week", "month", "year"]
|
||||
while count < 4:
|
||||
count += 1
|
||||
remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
|
||||
if seconds == 0 and remainder == 0:
|
||||
break
|
||||
time_list.append(int(result))
|
||||
seconds = int(remainder)
|
||||
for i in range(len(time_list)):
|
||||
time_list[i] = str(time_list[i]) + time_suffix_list[i]
|
||||
if len(time_list) == 4:
|
||||
ping_time += f"{time_list.pop()}, "
|
||||
time_list.reverse()
|
||||
ping_time += ":".join(time_list)
|
||||
return ping_time
|
||||
67
misskaty/helper/media_helper.py
Normal file
67
misskaty/helper/media_helper.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import os
|
||||
import asyncio
|
||||
from html_telegraph_poster import TelegraphPoster
|
||||
from typing import Tuple
|
||||
import shlex
|
||||
|
||||
|
||||
def post_to_telegraph(a_title: str, content: str) -> str:
|
||||
"""Create a Telegram Post using HTML Content"""
|
||||
post_client = TelegraphPoster(use_api=True)
|
||||
auth_name = "MissKaty Bot"
|
||||
post_client.create_api_token(auth_name)
|
||||
post_page = post_client.post(
|
||||
title=a_title,
|
||||
author=auth_name,
|
||||
author_url="https://www.yasir.my.id",
|
||||
text=content,
|
||||
)
|
||||
return post_page["url"]
|
||||
|
||||
|
||||
async def run_subprocess(cmd):
|
||||
process = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
||||
return await process.communicate()
|
||||
|
||||
|
||||
async def get_media_info(file_link):
|
||||
ffprobe_cmd = [
|
||||
"ffprobe",
|
||||
"-headers",
|
||||
"IAM:''",
|
||||
"-i",
|
||||
file_link,
|
||||
"-v",
|
||||
"quiet",
|
||||
"-of",
|
||||
"json",
|
||||
"-show_streams",
|
||||
"-show_format",
|
||||
"-show_chapters",
|
||||
"-show_programs",
|
||||
]
|
||||
data, err = await run_subprocess(ffprobe_cmd)
|
||||
return data
|
||||
|
||||
|
||||
async def runcmd(cmd: str) -> Tuple[str, str, int, int]:
|
||||
"""run command in terminal"""
|
||||
args = shlex.split(cmd)
|
||||
process = await asyncio.create_subprocess_exec(*args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
||||
stdout, stderr = await process.communicate()
|
||||
return (
|
||||
stdout.decode("utf-8", "replace").strip(),
|
||||
stderr.decode("utf-8", "replace").strip(),
|
||||
process.returncode,
|
||||
process.pid,
|
||||
)
|
||||
|
||||
|
||||
# Solves ValueError: No closing quotation by removing ' or " in file name
|
||||
def safe_filename(path_):
|
||||
if path_ is None:
|
||||
return
|
||||
safename = path_.replace("'", "").replace('"', "")
|
||||
if safename != path_:
|
||||
os.rename(path_, safename)
|
||||
return safename
|
||||
82
misskaty/helper/misc.py
Normal file
82
misskaty/helper/misc.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
from math import ceil
|
||||
|
||||
from pyrogram.types import InlineKeyboardButton
|
||||
|
||||
from misskaty import MOD_LOAD, MOD_NOLOAD
|
||||
|
||||
|
||||
class EqInlineKeyboardButton(InlineKeyboardButton):
|
||||
def __eq__(self, other):
|
||||
return self.text == other.text
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.text < other.text
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.text > other.text
|
||||
|
||||
|
||||
def paginate_modules(page_n, module_dict, prefix, chat=None):
|
||||
modules = (
|
||||
sorted(
|
||||
[
|
||||
EqInlineKeyboardButton(
|
||||
x.__MODULE__,
|
||||
callback_data=f"{prefix}_module({chat},{x.__MODULE__.lower()})",
|
||||
)
|
||||
for x in module_dict.values()
|
||||
]
|
||||
)
|
||||
if chat
|
||||
else sorted(
|
||||
[
|
||||
EqInlineKeyboardButton(
|
||||
x.__MODULE__,
|
||||
callback_data=f"{prefix}_module({x.__MODULE__.lower()})",
|
||||
)
|
||||
for x in module_dict.values()
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
pairs = list(zip(modules[::3], modules[1::3], modules[2::3]))
|
||||
i = 0
|
||||
for m in pairs:
|
||||
for _ in m:
|
||||
i += 1
|
||||
if len(modules) - i == 1:
|
||||
pairs.append((modules[-1],))
|
||||
elif len(modules) - i == 2:
|
||||
pairs.append(
|
||||
(
|
||||
modules[-2],
|
||||
modules[-1],
|
||||
)
|
||||
)
|
||||
|
||||
COLUMN_SIZE = 4
|
||||
|
||||
max_num_pages = ceil(len(pairs) / COLUMN_SIZE)
|
||||
modulo_page = page_n % max_num_pages
|
||||
|
||||
# can only have a certain amount of buttons side by side
|
||||
if len(pairs) > COLUMN_SIZE:
|
||||
pairs = pairs[modulo_page * COLUMN_SIZE : COLUMN_SIZE * (modulo_page + 1)] + [
|
||||
(
|
||||
EqInlineKeyboardButton(
|
||||
"❮", callback_data=f"{prefix}_prev({modulo_page})"
|
||||
),
|
||||
EqInlineKeyboardButton(
|
||||
"Back", callback_data=f"{prefix}_home({modulo_page})"
|
||||
),
|
||||
EqInlineKeyboardButton(
|
||||
"❯", callback_data=f"{prefix}_next({modulo_page})"
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
return pairs
|
||||
|
||||
|
||||
def is_module_loaded(name):
|
||||
return (not MOD_LOAD or name in MOD_LOAD) and name not in MOD_NOLOAD
|
||||
75
misskaty/helper/pyro_progress.py
Normal file
75
misskaty/helper/pyro_progress.py
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# (c) Shrimadhav U K
|
||||
|
||||
import asyncio
|
||||
import math
|
||||
import time
|
||||
from pyrogram.errors import MessageNotModified, FloodWait
|
||||
|
||||
|
||||
async def progress_for_pyrogram(current, total, ud_type, message, start):
|
||||
"""generic progress display for Telegram Upload / Download status"""
|
||||
now = time.time()
|
||||
diff = now - start
|
||||
if round(diff % 10.00) == 0 or current == total:
|
||||
# if round(current / total * 100, 0) % 5 == 0:
|
||||
percentage = current * 100 / total
|
||||
elapsed_time = round(diff)
|
||||
if elapsed_time == 0:
|
||||
return
|
||||
speed = current / diff
|
||||
time_to_completion = round((total - current) / speed)
|
||||
estimated_total_time = elapsed_time + time_to_completion
|
||||
|
||||
elapsed_time = time_formatter(elapsed_time)
|
||||
estimated_total_time = time_formatter(estimated_total_time)
|
||||
|
||||
progress = "[{0}{1}] \nP: {2}%\n".format(
|
||||
"".join(["█" for _ in range(math.floor(percentage / 5))]),
|
||||
"".join(["░" for _ in range(20 - math.floor(percentage / 5))]),
|
||||
round(percentage, 2),
|
||||
)
|
||||
|
||||
tmp = progress + "{0} of {1}\nSpeed: {2}/s\nETA: {3}\n".format(
|
||||
humanbytes(current),
|
||||
humanbytes(total),
|
||||
humanbytes(speed),
|
||||
# elapsed_time if elapsed_time != "" else "0 s",
|
||||
estimated_total_time if estimated_total_time != "" else "0 s",
|
||||
)
|
||||
try:
|
||||
await message.edit(f"{ud_type}\n {tmp}")
|
||||
except FloodWait as e:
|
||||
await asyncio.sleep(e.value)
|
||||
await message.edit(f"{ud_type}\n {tmp}")
|
||||
except MessageNotModified:
|
||||
pass
|
||||
|
||||
|
||||
def humanbytes(size: int) -> str:
|
||||
"""converts bytes into human readable format"""
|
||||
# https://stackoverflow.com/a/49361727/4723940
|
||||
# 2**10 = 1024
|
||||
if not size:
|
||||
return ""
|
||||
power = 2**10
|
||||
number = 0
|
||||
dict_power_n = {0: " ", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}
|
||||
while size > power:
|
||||
size /= power
|
||||
number += 1
|
||||
return f"{str(round(size, 2))} {dict_power_n[number]}B"
|
||||
|
||||
|
||||
def time_formatter(seconds: int) -> str:
|
||||
result = ""
|
||||
v_m = 0
|
||||
remainder = seconds
|
||||
r_ange_s = {"days": (24 * 60 * 60), "hours": (60 * 60), "minutes": 60, "seconds": 1}
|
||||
for age, divisor in r_ange_s.items():
|
||||
v_m, remainder = divmod(remainder, divisor)
|
||||
v_m = int(v_m)
|
||||
if v_m != 0:
|
||||
result += f" {v_m} {age} "
|
||||
return result
|
||||
73
misskaty/helper/stickerset.py
Normal file
73
misskaty/helper/stickerset.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
"""
|
||||
MIT License
|
||||
Copyright (c) 2021 TheHamkerCat
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
from typing import List
|
||||
|
||||
from pyrogram import Client, errors, raw
|
||||
|
||||
|
||||
async def get_sticker_set_by_name(client: Client, name: str) -> raw.base.messages.StickerSet:
|
||||
try:
|
||||
return await client.invoke(
|
||||
raw.functions.messages.GetStickerSet(
|
||||
stickerset=raw.types.InputStickerSetShortName(short_name=name),
|
||||
hash=0,
|
||||
)
|
||||
)
|
||||
except errors.exceptions.not_acceptable_406.StickersetInvalid:
|
||||
return None
|
||||
|
||||
|
||||
# Known errors: (I don't see a reason to catch them as we, for sure, won't face them right now):
|
||||
# errors.exceptions.bad_request_400.PackShortNameInvalid -> pack name needs to end with _by_botname
|
||||
# errors.exceptions.bad_request_400.ShortnameOccupyFailed -> pack's name is already in use
|
||||
|
||||
|
||||
async def create_sticker_set(
|
||||
client: Client,
|
||||
owner: int,
|
||||
title: str,
|
||||
short_name: str,
|
||||
stickers: List[raw.base.InputStickerSetItem],
|
||||
) -> raw.base.messages.StickerSet:
|
||||
return await client.invoke(
|
||||
raw.functions.stickers.CreateStickerSet(
|
||||
user_id=await client.resolve_peer(owner),
|
||||
title=title,
|
||||
short_name=short_name,
|
||||
stickers=stickers,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def add_sticker_to_set(
|
||||
client: Client,
|
||||
stickerset: raw.base.messages.StickerSet,
|
||||
sticker: raw.base.InputStickerSetItem,
|
||||
) -> raw.base.messages.StickerSet:
|
||||
return await client.invoke(
|
||||
raw.functions.stickers.AddStickerToSet(
|
||||
stickerset=raw.types.InputStickerSetShortName(short_name=stickerset.set.short_name),
|
||||
sticker=sticker,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def create_sticker(sticker: raw.base.InputDocument, emoji: str) -> raw.base.InputStickerSetItem:
|
||||
return raw.types.InputStickerSetItem(document=sticker, emoji=emoji)
|
||||
18
misskaty/helper/time_gap.py
Normal file
18
misskaty/helper/time_gap.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import time
|
||||
|
||||
GAP = {}
|
||||
|
||||
|
||||
async def check_time_gap(user_id: int):
|
||||
"""A Function for checking user time gap!
|
||||
:parameter user_id Telegram User ID"""
|
||||
|
||||
if str(user_id) in GAP:
|
||||
current_time = time.time()
|
||||
previous_time = GAP[str(user_id)]
|
||||
if round(current_time - previous_time) < 10:
|
||||
return True, round(previous_time - current_time + 10)
|
||||
del GAP[str(user_id)]
|
||||
else:
|
||||
GAP[str(user_id)] = time.time()
|
||||
return False, None
|
||||
83
misskaty/helper/tools.py
Normal file
83
misskaty/helper/tools.py
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import random
|
||||
import string
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
from misskaty import botStartTime
|
||||
from misskaty.plugins import ALL_MODULES
|
||||
from misskaty.helper.human_read import get_readable_time
|
||||
from misskaty.helper.http import http
|
||||
from http.cookies import SimpleCookie
|
||||
|
||||
GENRES_EMOJI = {
|
||||
"Action": "👊",
|
||||
"Adventure": random.choice(["🪂", "🧗♀", "🌋"]),
|
||||
"Family": "👨",
|
||||
"Musical": "🎸",
|
||||
"Comedy": "🤣",
|
||||
"Drama": " 🎭",
|
||||
"Ecchi": random.choice(["💋", "🥵"]),
|
||||
"Fantasy": random.choice(["🧞", "🧞♂", "🧞♀", "🌗"]),
|
||||
"Hentai": "🔞",
|
||||
"History": "📜",
|
||||
"Horror": "☠",
|
||||
"Mahou Shoujo": "☯",
|
||||
"Mecha": "🤖",
|
||||
"Music": "🎸",
|
||||
"Mystery": "🔮",
|
||||
"Psychological": "♟",
|
||||
"Romance": "💞",
|
||||
"Sci-Fi": "🛸",
|
||||
"Slice of Life": random.choice(["☘", "🍁"]),
|
||||
"Sports": "⚽️",
|
||||
"Supernatural": "🫧",
|
||||
"Thriller": random.choice(["🥶", "🔪", "🤯"]),
|
||||
}
|
||||
|
||||
|
||||
async def bot_sys_stats():
|
||||
bot_uptime = int(time.time() - botStartTime)
|
||||
cpu = psutil.cpu_percent(interval=0.5)
|
||||
mem = psutil.virtual_memory().percent
|
||||
disk = psutil.disk_usage("/").percent
|
||||
process = psutil.Process(os.getpid())
|
||||
return f"""
|
||||
YasirArisM@MissKatyRoBot
|
||||
------------------
|
||||
UPTIME: {get_readable_time(bot_uptime)}
|
||||
BOT: {round(process.memory_info()[0] / 1024**2)} MB
|
||||
CPU: {cpu}%
|
||||
RAM: {mem}%
|
||||
DISK: {disk}%
|
||||
|
||||
TOTAL PLUGINS: {len(ALL_MODULES)}
|
||||
"""
|
||||
|
||||
|
||||
def get_random_string(length):
|
||||
# choose from all lowercase letter
|
||||
letters = string.ascii_lowercase
|
||||
return "".join(random.choice(letters) for _ in range(length))
|
||||
|
||||
|
||||
async def rentry(teks):
|
||||
# buat dapetin cookie
|
||||
cookie = SimpleCookie()
|
||||
kuki = (await http.get("https://rentry.co")).cookies
|
||||
cookie.load(kuki)
|
||||
kukidict = {key: value.value for key, value in cookie.items()}
|
||||
# headernya
|
||||
header = {"Referer": "https://rentry.co"}
|
||||
payload = {"csrfmiddlewaretoken": kukidict["csrftoken"], "text": teks}
|
||||
return (
|
||||
(
|
||||
await http.post(
|
||||
"https://rentry.co/api/new",
|
||||
data=payload,
|
||||
headers=header,
|
||||
cookies=kukidict,
|
||||
)
|
||||
)
|
||||
.json()
|
||||
.get("url")
|
||||
)
|
||||
42
misskaty/helper/ytdl_helper.py
Normal file
42
misskaty/helper/ytdl_helper.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import string
|
||||
import os
|
||||
import requests
|
||||
import time
|
||||
import random
|
||||
from misskaty.helper.human_read import get_readable_file_size
|
||||
|
||||
|
||||
def random_char(y):
|
||||
return "".join(random.choice(string.ascii_letters) for _ in range(y))
|
||||
|
||||
|
||||
def DetectFileSize(url):
|
||||
r = requests.get(url, allow_redirects=True, stream=True)
|
||||
return int(r.headers.get("content-length", 0))
|
||||
|
||||
|
||||
def DownLoadFile(url, file_name, chunk_size, client, ud_type, message_id, chat_id):
|
||||
if os.path.exists(file_name):
|
||||
os.remove(file_name)
|
||||
if not url:
|
||||
return file_name
|
||||
r = requests.get(url, allow_redirects=True, stream=True)
|
||||
# https://stackoverflow.com/a/47342052/4723940
|
||||
total_size = int(r.headers.get("content-length", 0))
|
||||
downloaded_size = 0
|
||||
with open(file_name, "wb") as fd:
|
||||
for chunk in r.iter_content(chunk_size=chunk_size):
|
||||
if chunk:
|
||||
fd.write(chunk)
|
||||
downloaded_size += chunk_size
|
||||
if client is not None and ((total_size // downloaded_size) % 5) == 0:
|
||||
time.sleep(0.3)
|
||||
try:
|
||||
client.edit_message_text(
|
||||
chat_id,
|
||||
message_id,
|
||||
text=f"{ud_type}: {get_readable_file_size(downloaded_size)} of {get_readable_file_size(total_size)}",
|
||||
)
|
||||
except:
|
||||
pass
|
||||
return file_name
|
||||
45
misskaty/plugins/__init__.py
Normal file
45
misskaty/plugins/__init__.py
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
"""
|
||||
* @author yasir <yasiramunandar@gmail.com>
|
||||
* @date 2022-12-01 09:12:27
|
||||
* @lastModified 2022-12-01 09:27:31
|
||||
* @projectName MissKatyPyro
|
||||
* Copyright ©YasirPedia All rights reserved
|
||||
"""
|
||||
import glob
|
||||
import importlib
|
||||
import sys
|
||||
from logging import info as log_info
|
||||
from os.path import basename, dirname, isfile
|
||||
from misskaty import MOD_LOAD, MOD_NOLOAD
|
||||
|
||||
|
||||
def __list_all_modules():
|
||||
# This generates a list of modules in this
|
||||
# folder for the * in __main__ to work.
|
||||
mod_paths = glob.glob(f"{dirname(__file__)}/*.py")
|
||||
all_modules = [
|
||||
basename(f)[:-3] for f in mod_paths if isfile(f) and f.endswith(".py")
|
||||
and not f.endswith("__init__.py") and not f.endswith("__main__.py")
|
||||
]
|
||||
|
||||
if MOD_LOAD or MOD_NOLOAD:
|
||||
to_load = MOD_LOAD
|
||||
if to_load:
|
||||
if not all(
|
||||
any(mod == module_name for module_name in all_modules)
|
||||
for mod in to_load):
|
||||
sys.exit()
|
||||
|
||||
else:
|
||||
to_load = all_modules
|
||||
|
||||
return [item for item in to_load
|
||||
if item not in MOD_NOLOAD] if MOD_NOLOAD else to_load
|
||||
|
||||
return all_modules
|
||||
|
||||
|
||||
log_info("[INFO]: IMPORTING PLUGINS")
|
||||
importlib.import_module("misskaty.plugins.__main__")
|
||||
ALL_MODULES = sorted(__list_all_modules())
|
||||
__all__ = ALL_MODULES + ["ALL_MODULES"]
|
||||
0
misskaty/plugins/__main__.py
Normal file
0
misskaty/plugins/__main__.py
Normal file
715
misskaty/plugins/admin.py
Normal file
715
misskaty/plugins/admin.py
Normal file
|
|
@ -0,0 +1,715 @@
|
|||
import logging
|
||||
import asyncio, re
|
||||
from misskaty import app
|
||||
from misskaty.helper.functions import (
|
||||
extract_user_and_reason,
|
||||
time_converter,
|
||||
extract_user,
|
||||
int_to_alpha,
|
||||
)
|
||||
from time import time
|
||||
from pyrogram import filters, enums
|
||||
from pyrogram.errors import FloodWait, ChatAdminRequired
|
||||
from pyrogram.types import ChatPermissions
|
||||
from misskaty.core.decorator.permissions import (
|
||||
adminsOnly,
|
||||
admins_in_chat,
|
||||
list_admins,
|
||||
member_permissions,
|
||||
)
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.core.keyboard import ikb
|
||||
from misskaty.vars import SUDO, COMMAND_HANDLER
|
||||
from database.warn_db import get_warn, remove_warns, add_warn
|
||||
|
||||
__MODULE__ = "Admin"
|
||||
__HELP__ = """
|
||||
/ban - Ban A User From A Group
|
||||
/dban - Delete the replied message banning its sender
|
||||
/tban - Ban A User For Specific Time
|
||||
/unban - Unban A User
|
||||
/listban - Ban a user from groups listed in a message
|
||||
/listunban - Unban a user from groups listed in a message
|
||||
/warn - Warn A User
|
||||
/dwarn - Delete the replied message warning its sender
|
||||
/rmwarns - Remove All Warning of A User
|
||||
/warns - Show Warning Of A User
|
||||
/kick - Kick A User
|
||||
/dkick - Delete the replied message kicking its sender
|
||||
/purge - Purge Messages
|
||||
/purge [n] - Purge "n" number of messages from replied message
|
||||
/del - Delete Replied Message
|
||||
/promote - Promote A Member
|
||||
/fullpromote - Promote A Member With All Rights
|
||||
/demote - Demote A Member
|
||||
/pin - Pin A Message
|
||||
/mute - Mute A User
|
||||
/tmute - Mute A User For Specific Time
|
||||
/unmute - Unmute A User
|
||||
/ban_ghosts - Ban Deleted Accounts
|
||||
/report | @admins | @admin - Report A Message To Admins.
|
||||
"""
|
||||
|
||||
|
||||
# Admin cache reload
|
||||
@app.on_chat_member_updated()
|
||||
async def admin_cache_func(_, cmu):
|
||||
if cmu.old_chat_member and cmu.old_chat_member.promoted_by:
|
||||
admins_in_chat[cmu.chat.id] = {
|
||||
"last_updated_at": time(),
|
||||
"data": [
|
||||
member.user.id
|
||||
async for member in app.get_chat_members(
|
||||
cmu.chat.id, filter=enums.ChatMembersFilter.ADMINISTRATORS
|
||||
)
|
||||
],
|
||||
}
|
||||
logging.info(f"Updated admin cache for {cmu.chat.id} [{cmu.chat.title}]")
|
||||
|
||||
|
||||
# Purge CMD
|
||||
@app.on_message(filters.command("purge", COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_delete_messages")
|
||||
async def purge(_, message):
|
||||
repliedmsg = message.reply_to_message
|
||||
await message.delete()
|
||||
|
||||
if not repliedmsg:
|
||||
return await message.reply_text("Reply to a message to purge from.")
|
||||
|
||||
cmd = message.command
|
||||
if len(cmd) > 1 and cmd[1].isdigit():
|
||||
purge_to = repliedmsg.id + int(cmd[1])
|
||||
if purge_to > message.id:
|
||||
purge_to = message.id
|
||||
else:
|
||||
purge_to = message.id
|
||||
|
||||
chat_id = message.chat.id
|
||||
message_ids = []
|
||||
del_total = 0
|
||||
|
||||
for message_id in range(
|
||||
repliedmsg.id,
|
||||
purge_to,
|
||||
):
|
||||
message_ids.append(message_id)
|
||||
|
||||
# Max message deletion limit is 100
|
||||
if len(message_ids) == 100:
|
||||
await app.delete_messages(
|
||||
chat_id=chat_id,
|
||||
message_ids=message_ids,
|
||||
revoke=True, # For both sides
|
||||
)
|
||||
del_total += len(message_ids)
|
||||
# To delete more than 100 messages, start again
|
||||
message_ids = []
|
||||
|
||||
# Delete if any messages left
|
||||
if len(message_ids) > 0:
|
||||
await app.delete_messages(
|
||||
chat_id=chat_id,
|
||||
message_ids=message_ids,
|
||||
revoke=True,
|
||||
)
|
||||
del_total += len(message_ids)
|
||||
await message.reply(f"Successfully deleted {del_total} messages..")
|
||||
|
||||
|
||||
# Kick members
|
||||
@app.on_message(filters.command(["kick", "dkick"], COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_restrict_members")
|
||||
async def kickFunc(_, message):
|
||||
user_id, reason = await extract_user_and_reason(message)
|
||||
if not user_id:
|
||||
return await message.reply_text("I can't find that user.")
|
||||
if user_id == 1507530289:
|
||||
return await message.reply_text("I can't kick myself, i can leave if you want.")
|
||||
if user_id in SUDO:
|
||||
return await message.reply_text("Wow, you wanna kick my owner?")
|
||||
if user_id in (await list_admins(message.chat.id)):
|
||||
return await message.reply_text("Lol, it's crazy if i can kick an admin.")
|
||||
mention = (await app.get_users(user_id)).mention
|
||||
msg = f"""
|
||||
**Kicked User:** {mention}
|
||||
**Kicked By:** {message.from_user.mention if message.from_user else 'Anon'}
|
||||
**Reason:** {reason or '-'}"""
|
||||
if message.command[0][0] == "d":
|
||||
await message.reply_to_message.delete()
|
||||
await message.chat.ban_member(user_id)
|
||||
await message.reply_text(msg)
|
||||
await asyncio.sleep(1)
|
||||
await message.chat.unban_member(user_id)
|
||||
|
||||
|
||||
# Ban/DBan/TBan User
|
||||
@app.on_message(
|
||||
filters.command(["ban", "dban", "tban"], COMMAND_HANDLER) & ~filters.private
|
||||
)
|
||||
@adminsOnly("can_restrict_members")
|
||||
async def banFunc(_, message):
|
||||
user_id, reason = await extract_user_and_reason(message, sender_chat=True)
|
||||
|
||||
if not user_id:
|
||||
return await message.reply_text("I can't find that user.")
|
||||
if user_id == 1507530289:
|
||||
return await message.reply_text("I can't ban myself, i can leave if you want.")
|
||||
if user_id in SUDO:
|
||||
return await message.reply_text("You Wanna Ban The Elevated One?, RECONSIDER!")
|
||||
if user_id in (await list_admins(message.chat.id)):
|
||||
return await message.reply_text(
|
||||
"I can't ban an admin, You know the rules, so do i."
|
||||
)
|
||||
|
||||
try:
|
||||
mention = (await app.get_users(user_id)).mention
|
||||
except IndexError:
|
||||
mention = (
|
||||
message.reply_to_message.sender_chat.title
|
||||
if message.reply_to_message
|
||||
else "Anon"
|
||||
)
|
||||
|
||||
msg = (
|
||||
f"**Banned User:** {mention}\n"
|
||||
f"**Banned By:** {message.from_user.mention if message.from_user else 'Anon'}\n"
|
||||
)
|
||||
if message.command[0][0] == "d":
|
||||
await message.reply_to_message.delete()
|
||||
if message.command[0] == "tban":
|
||||
split = reason.split(None, 1)
|
||||
time_value = split[0]
|
||||
temp_reason = split[1] if len(split) > 1 else ""
|
||||
temp_ban = await time_converter(message, time_value)
|
||||
msg += f"**Banned For:** {time_value}\n"
|
||||
if temp_reason:
|
||||
msg += f"**Reason:** {temp_reason}"
|
||||
try:
|
||||
if len(time_value[:-1]) < 3:
|
||||
await message.chat.ban_member(user_id, until_date=temp_ban)
|
||||
await message.reply_text(msg)
|
||||
else:
|
||||
await message.reply_text("You can't use more than 99")
|
||||
except AttributeError:
|
||||
pass
|
||||
return
|
||||
if reason:
|
||||
msg += f"**Reason:** {reason}"
|
||||
keyboard = ikb({"🚨 Unban 🚨": f"unban_{user_id}"})
|
||||
await message.chat.ban_member(user_id)
|
||||
await message.reply_text(msg, reply_markup=keyboard)
|
||||
|
||||
|
||||
# Unban members
|
||||
@app.on_message(filters.command("unban", COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_restrict_members")
|
||||
async def unban_func(_, message):
|
||||
# we don't need reasons for unban, also, we
|
||||
# don't need to get "text_mention" entity, because
|
||||
# normal users won't get text_mention if the user
|
||||
# they want to unban is not in the group.
|
||||
reply = message.reply_to_message
|
||||
|
||||
if reply and reply.sender_chat and reply.sender_chat != message.chat.id:
|
||||
return await message.reply_text("You cannot unban a channel")
|
||||
|
||||
if len(message.command) == 2:
|
||||
user = message.text.split(None, 1)[1]
|
||||
elif len(message.command) == 1 and reply:
|
||||
user = message.reply_to_message.from_user.id
|
||||
else:
|
||||
return await message.reply_text(
|
||||
"Provide a username or reply to a user's message to unban."
|
||||
)
|
||||
await message.chat.unban_member(user)
|
||||
umention = (await app.get_users(user)).mention
|
||||
await message.reply_text(f"Unbanned! {umention}")
|
||||
|
||||
|
||||
# Ban users listed in a message
|
||||
@app.on_message(
|
||||
filters.user(SUDO) & filters.command("listban", COMMAND_HANDLER) & ~filters.private
|
||||
)
|
||||
async def list_ban_(c, message):
|
||||
userid, msglink_reason = await extract_user_and_reason(message)
|
||||
if not userid or not msglink_reason:
|
||||
return await message.reply_text(
|
||||
"Provide a userid/username along with message link and reason to list-ban"
|
||||
)
|
||||
if len(msglink_reason.split(" ")) == 1: # message link included with the reason
|
||||
return await message.reply_text("You must provide a reason to list-ban")
|
||||
# seperate messge link from reason
|
||||
lreason = msglink_reason.split()
|
||||
messagelink, reason = lreason[0], " ".join(lreason[1:])
|
||||
|
||||
if not re.search(
|
||||
r"(https?://)?t(elegram)?\.me/\w+/\d+", messagelink
|
||||
): # validate link
|
||||
return await message.reply_text("Invalid message link provided")
|
||||
|
||||
if userid == 1507530289:
|
||||
return await message.reply_text("I can't ban myself.")
|
||||
if userid in SUDO:
|
||||
return await message.reply_text("You Wanna Ban The Elevated One?, RECONSIDER!")
|
||||
splitted = messagelink.split("/")
|
||||
uname, mid = splitted[-2], int(splitted[-1])
|
||||
m = await message.reply_text(
|
||||
"`Banning User from multiple groups. This may take some time`"
|
||||
)
|
||||
try:
|
||||
msgtext = (await app.get_messages(uname, mid)).text
|
||||
gusernames = re.findall("@\w+", msgtext)
|
||||
except:
|
||||
return await m.edit_text("Could not get group usernames")
|
||||
count = 0
|
||||
for username in gusernames:
|
||||
try:
|
||||
await app.ban_chat_member(username.strip("@"), userid)
|
||||
await asyncio.sleep(1)
|
||||
except FloodWait as e:
|
||||
await asyncio.sleep(e.value)
|
||||
except:
|
||||
continue
|
||||
count += 1
|
||||
mention = (await app.get_users(userid)).mention
|
||||
|
||||
msg = f"""
|
||||
**List-Banned User:** {mention}
|
||||
**Banned User ID:** `{userid}`
|
||||
**Admin:** {message.from_user.mention}
|
||||
**Affected chats:** `{count}`
|
||||
**Reason:** {reason}
|
||||
"""
|
||||
await m.edit_text(msg)
|
||||
|
||||
|
||||
# Unban users listed in a message
|
||||
@app.on_message(
|
||||
filters.user(SUDO)
|
||||
& filters.command("listunban", COMMAND_HANDLER)
|
||||
& ~filters.private
|
||||
)
|
||||
async def list_unban_(c, message):
|
||||
userid, msglink = await extract_user_and_reason(message)
|
||||
if not userid or not msglink:
|
||||
return await message.reply_text(
|
||||
"Provide a userid/username along with message link to list-unban"
|
||||
)
|
||||
|
||||
if not re.search(r"(https?://)?t(elegram)?\.me/\w+/\d+", msglink): # validate link
|
||||
return await message.reply_text("Invalid message link provided")
|
||||
|
||||
splitted = msglink.split("/")
|
||||
uname, mid = splitted[-2], int(splitted[-1])
|
||||
m = await message.reply_text(
|
||||
"`Unbanning User from multiple groups. \
|
||||
This may take some time`"
|
||||
)
|
||||
try:
|
||||
msgtext = (await app.get_messages(uname, mid)).text
|
||||
gusernames = re.findall("@\w+", msgtext)
|
||||
except:
|
||||
return await m.edit_text("Could not get the group usernames")
|
||||
count = 0
|
||||
for username in gusernames:
|
||||
try:
|
||||
await app.unban_chat_member(username.strip("@"), userid)
|
||||
await asyncio.sleep(1)
|
||||
except FloodWait as e:
|
||||
await asyncio.sleep(e.x)
|
||||
except:
|
||||
continue
|
||||
count += 1
|
||||
mention = (await app.get_users(userid)).mention
|
||||
msg = f"""
|
||||
**List-Unbanned User:** {mention}
|
||||
**Unbanned User ID:** `{userid}`
|
||||
**Admin:** {message.from_user.mention}
|
||||
**Affected chats:** `{count}`
|
||||
"""
|
||||
await m.edit_text(msg)
|
||||
|
||||
|
||||
# Delete messages
|
||||
@app.on_message(filters.command("del", COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_delete_messages")
|
||||
async def deleteFunc(_, message):
|
||||
if not message.reply_to_message:
|
||||
return await message.reply_text("Reply To A Message To Delete It")
|
||||
await message.reply_to_message.delete()
|
||||
await message.delete()
|
||||
|
||||
|
||||
# Promote Members
|
||||
@app.on_message(
|
||||
filters.command(["promote", "fullpromote"], COMMAND_HANDLER) & ~filters.private
|
||||
)
|
||||
@adminsOnly("can_promote_members")
|
||||
async def promoteFunc(_, message):
|
||||
user_id = await extract_user(message)
|
||||
umention = (await app.get_users(user_id)).mention
|
||||
if not user_id:
|
||||
return await message.reply_text("I can't find that user.")
|
||||
bot = await app.get_chat_member(message.chat.id, 1507530289)
|
||||
if user_id == 1507530289:
|
||||
return await message.reply_text("I can't promote myself.")
|
||||
if not bot.can_promote_members:
|
||||
return await message.reply_text("I don't have enough permissions")
|
||||
if message.command[0][0] == "f":
|
||||
await message.chat.promote_member(
|
||||
user_id=user_id,
|
||||
can_change_info=bot.can_change_info,
|
||||
can_invite_users=bot.can_invite_users,
|
||||
can_delete_messages=bot.can_delete_messages,
|
||||
can_restrict_members=bot.can_restrict_members,
|
||||
can_pin_messages=bot.can_pin_messages,
|
||||
can_promote_members=bot.can_promote_members,
|
||||
can_manage_chat=bot.can_manage_chat,
|
||||
can_manage_voice_chats=bot.can_manage_voice_chats,
|
||||
)
|
||||
return await message.reply_text(f"Fully Promoted! {umention}")
|
||||
|
||||
await message.chat.promote_member(
|
||||
user_id=user_id,
|
||||
can_change_info=False,
|
||||
can_invite_users=bot.can_invite_users,
|
||||
can_delete_messages=bot.can_delete_messages,
|
||||
can_restrict_members=False,
|
||||
can_pin_messages=False,
|
||||
can_promote_members=False,
|
||||
can_manage_chat=bot.can_manage_chat,
|
||||
can_manage_voice_chats=bot.can_manage_voice_chats,
|
||||
)
|
||||
await message.reply_text(f"Promoted! {umention}")
|
||||
|
||||
|
||||
# Demote Member
|
||||
@app.on_message(filters.command("demote", COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_promote_members")
|
||||
async def demote(_, message):
|
||||
user_id = await extract_user(message)
|
||||
if not user_id:
|
||||
return await message.reply_text("I can't find that user.")
|
||||
if user_id == 1507530289:
|
||||
return await message.reply_text("I can't demote myself.")
|
||||
if user_id in SUDO:
|
||||
return await message.reply_text("You wanna demote the elevated one?")
|
||||
await message.chat.promote_member(
|
||||
user_id=user_id,
|
||||
can_change_info=False,
|
||||
can_invite_users=False,
|
||||
can_delete_messages=False,
|
||||
can_restrict_members=False,
|
||||
can_pin_messages=False,
|
||||
can_promote_members=False,
|
||||
can_manage_chat=False,
|
||||
can_manage_voice_chats=False,
|
||||
)
|
||||
umention = (await app.get_users(user_id)).mention
|
||||
await message.reply_text(f"Demoted! {umention}")
|
||||
|
||||
|
||||
# Pin Messages
|
||||
@app.on_message(filters.command(["pin", "unpin"], COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_pin_messages")
|
||||
async def pin(_, message):
|
||||
if not message.reply_to_message:
|
||||
return await message.reply_text("Reply to a message to pin/unpin it.")
|
||||
r = message.reply_to_message
|
||||
try:
|
||||
if message.command[0][0] == "u":
|
||||
await r.unpin()
|
||||
return await message.reply_text(
|
||||
f"**Unpinned [this]({r.link}) message.**",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
await r.pin(disable_notification=True)
|
||||
await message.reply(
|
||||
f"**Pinned [this]({r.link}) message.**",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except ChatAdminRequired:
|
||||
await message.reply(
|
||||
"Please give me admin access to use this command.",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
|
||||
# Mute members
|
||||
@app.on_message(filters.command(["mute", "tmute"], COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_restrict_members")
|
||||
async def mute(_, message):
|
||||
user_id, reason = await extract_user_and_reason(message)
|
||||
if not user_id:
|
||||
return await message.reply_text("I can't find that user.")
|
||||
if user_id == 1507530289:
|
||||
return await message.reply_text("I can't mute myself.")
|
||||
if user_id in SUDO:
|
||||
return await message.reply_text("You wanna mute the elevated one?, RECONSIDER!")
|
||||
if user_id in (await list_admins(message.chat.id)):
|
||||
return await message.reply_text(
|
||||
"I can't mute an admin, You know the rules, so do i."
|
||||
)
|
||||
mention = (await app.get_users(user_id)).mention
|
||||
keyboard = ikb({"🚨 Unmute 🚨": f"unmute_{user_id}"})
|
||||
msg = (
|
||||
f"**Muted User:** {mention}\n"
|
||||
f"**Muted By:** {message.from_user.mention if message.from_user else 'Anon'}\n"
|
||||
)
|
||||
if message.command[0] == "tmute":
|
||||
split = reason.split(None, 1)
|
||||
time_value = split[0]
|
||||
temp_reason = split[1] if len(split) > 1 else ""
|
||||
temp_mute = await time_converter(message, time_value)
|
||||
msg += f"**Muted For:** {time_value}\n"
|
||||
if temp_reason:
|
||||
msg += f"**Reason:** {temp_reason}"
|
||||
try:
|
||||
if len(time_value[:-1]) < 3:
|
||||
await message.chat.restrict_member(
|
||||
user_id,
|
||||
permissions=ChatPermissions(),
|
||||
until_date=temp_mute,
|
||||
)
|
||||
await message.reply_text(msg, reply_markup=keyboard)
|
||||
else:
|
||||
await message.reply_text("You can't use more than 99")
|
||||
except AttributeError:
|
||||
pass
|
||||
return
|
||||
if reason:
|
||||
msg += f"**Reason:** {reason}"
|
||||
await message.chat.restrict_member(user_id, permissions=ChatPermissions())
|
||||
await message.reply_text(msg, reply_markup=keyboard)
|
||||
|
||||
|
||||
# Unmute members
|
||||
@app.on_message(filters.command("unmute", COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_restrict_members")
|
||||
async def unmute(_, message):
|
||||
user_id = await extract_user(message)
|
||||
if not user_id:
|
||||
return await message.reply_text("I can't find that user.")
|
||||
await message.chat.unban_member(user_id)
|
||||
umention = (await app.get_users(user_id)).mention
|
||||
await message.reply_text(f"Unmuted! {umention}")
|
||||
|
||||
|
||||
# Ban deleted accounts
|
||||
@app.on_message(filters.command("ban_ghosts", COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_restrict_members")
|
||||
async def ban_deleted_accounts(_, message):
|
||||
chat_id = message.chat.id
|
||||
deleted_users = []
|
||||
m = await message.reply("Finding ghosts...")
|
||||
|
||||
async for i in app.iter_chat_members(chat_id):
|
||||
if i.user.is_deleted:
|
||||
deleted_users.append(i.user.id)
|
||||
if deleted_users:
|
||||
banned_users = 0
|
||||
for deleted_user in deleted_users:
|
||||
try:
|
||||
await message.chat.ban_member(deleted_user)
|
||||
except Exception:
|
||||
pass
|
||||
banned_users += 1
|
||||
await m.edit(f"Banned {banned_users} Deleted Accounts")
|
||||
else:
|
||||
await m.edit("There are no deleted accounts in this chat")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["warn", "dwarn"], COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_restrict_members")
|
||||
async def warn_user(_, message):
|
||||
user_id, reason = await extract_user_and_reason(message)
|
||||
chat_id = message.chat.id
|
||||
if not user_id:
|
||||
return await message.reply_text("I can't find that user.")
|
||||
if user_id == 1507530289:
|
||||
return await message.reply_text("I can't warn myself, i can leave if you want.")
|
||||
if user_id in SUDO:
|
||||
return await message.reply_text("You Wanna Warn The Elevated One?, RECONSIDER!")
|
||||
if user_id in (await list_admins(chat_id)):
|
||||
return await message.reply_text(
|
||||
"I can't warn an admin, You know the rules, so do i."
|
||||
)
|
||||
user, warns = await asyncio.gather(
|
||||
app.get_users(user_id),
|
||||
get_warn(chat_id, await int_to_alpha(user_id)),
|
||||
)
|
||||
mention = user.mention
|
||||
keyboard = ikb({"🚨 Remove Warn 🚨": f"unwarn_{user_id}"})
|
||||
warns = warns["warns"] if warns else 0
|
||||
if message.command[0][0] == "d":
|
||||
await message.reply_to_message.delete()
|
||||
if warns >= 2:
|
||||
await message.chat.ban_member(user_id)
|
||||
await message.reply_text(f"Number of warns of {mention} exceeded, BANNED!")
|
||||
await remove_warns(chat_id, await int_to_alpha(user_id))
|
||||
else:
|
||||
warn = {"warns": warns + 1}
|
||||
msg = f"""
|
||||
**Warned User:** {mention}
|
||||
**Warned By:** {message.from_user.mention if message.from_user else 'Anon'}
|
||||
**Reason:** {reason or 'No Reason Provided.'}
|
||||
**Warns:** {warns + 1}/3"""
|
||||
await message.reply_text(msg, reply_markup=keyboard)
|
||||
await add_warn(chat_id, await int_to_alpha(user_id), warn)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("unwarn_"))
|
||||
async def remove_warning(_, cq):
|
||||
from_user = cq.from_user
|
||||
chat_id = cq.message.chat.id
|
||||
permissions = await member_permissions(chat_id, from_user.id)
|
||||
permission = "can_restrict_members"
|
||||
if permission not in permissions:
|
||||
return await cq.answer(
|
||||
"You don't have enough permissions to perform this action.\n"
|
||||
+ f"Permission needed: {permission}",
|
||||
show_alert=True,
|
||||
)
|
||||
user_id = cq.data.split("_")[1]
|
||||
warns = await get_warn(chat_id, await int_to_alpha(user_id))
|
||||
if warns:
|
||||
warns = warns["warns"]
|
||||
if not warns or warns == 0:
|
||||
return await cq.answer("User has no warnings.")
|
||||
warn = {"warns": warns - 1}
|
||||
await add_warn(chat_id, await int_to_alpha(user_id), warn)
|
||||
text = cq.message.text.markdown
|
||||
text = f"~~{text}~~\n\n"
|
||||
text += f"__Warn removed by {from_user.mention}__"
|
||||
await cq.message.edit(text)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("unmute_"))
|
||||
async def unmute_user(_, cq):
|
||||
from_user = cq.from_user
|
||||
chat_id = cq.message.chat.id
|
||||
permissions = await member_permissions(chat_id, from_user.id)
|
||||
permission = "can_restrict_members"
|
||||
if permission not in permissions:
|
||||
return await cq.answer(
|
||||
"You don't have enough permissions to perform this action.\n"
|
||||
+ f"Permission needed: {permission}",
|
||||
show_alert=True,
|
||||
)
|
||||
user_id = cq.data.split("_")[1]
|
||||
text = cq.message.text.markdown
|
||||
text = f"~~{text}~~\n\n"
|
||||
text += f"__Mute removed by {from_user.mention}__"
|
||||
await cq.message.chat.unban_member(user_id)
|
||||
await cq.message.edit(text)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("unban_"))
|
||||
async def unban_user(_, cq):
|
||||
from_user = cq.from_user
|
||||
chat_id = cq.message.chat.id
|
||||
permissions = await member_permissions(chat_id, from_user.id)
|
||||
permission = "can_restrict_members"
|
||||
if permission not in permissions:
|
||||
return await cq.answer(
|
||||
"You don't have enough permissions to perform this action.\n"
|
||||
+ f"Permission needed: {permission}",
|
||||
show_alert=True,
|
||||
)
|
||||
user_id = cq.data.split("_")[1]
|
||||
(await app.get_users(user_id)).mention
|
||||
text = cq.message.text.markdown
|
||||
text = f"~~{text}~~\n\n"
|
||||
text += f"__Banned removed by {from_user.mention}__"
|
||||
await cq.message.chat.unban_member(user_id)
|
||||
await cq.message.edit(text)
|
||||
|
||||
|
||||
# Remove Warn
|
||||
@app.on_message(filters.command("rmwarn", COMMAND_HANDLER) & ~filters.private)
|
||||
@adminsOnly("can_restrict_members")
|
||||
async def remove_warnings(_, message):
|
||||
if not message.reply_to_message:
|
||||
return await message.reply_text(
|
||||
"Reply to a message to remove a user's warnings."
|
||||
)
|
||||
user_id = message.reply_to_message.from_user.id
|
||||
mention = message.reply_to_message.from_user.mention
|
||||
chat_id = message.chat.id
|
||||
warns = await get_warn(chat_id, await int_to_alpha(user_id))
|
||||
if warns:
|
||||
warns = warns["warns"]
|
||||
if warns == 0 or not warns:
|
||||
await message.reply_text(f"{mention} have no warnings.")
|
||||
else:
|
||||
await remove_warns(chat_id, await int_to_alpha(user_id))
|
||||
await message.reply_text(f"Removed warnings of {mention}.")
|
||||
|
||||
|
||||
# Warns
|
||||
@app.on_message(filters.command("warns", COMMAND_HANDLER) & ~filters.private)
|
||||
@capture_err
|
||||
async def check_warns(_, message):
|
||||
user_id = await extract_user(message)
|
||||
if not user_id:
|
||||
return await message.reply_text("I can't find that user.")
|
||||
warns = await get_warn(message.chat.id, await int_to_alpha(user_id))
|
||||
mention = (await app.get_users(user_id)).mention
|
||||
if warns:
|
||||
warns = warns["warns"]
|
||||
else:
|
||||
return await message.reply_text(f"{mention} has no warnings.")
|
||||
return await message.reply_text(f"{mention} has {warns}/3 warnings.")
|
||||
|
||||
|
||||
# Report User in Group
|
||||
@app.on_message(
|
||||
(
|
||||
filters.command("report", COMMAND_HANDLER)
|
||||
| filters.command(["admins", "admin"], prefixes="@")
|
||||
)
|
||||
& ~filters.private
|
||||
)
|
||||
@capture_err
|
||||
async def report_user(_, message):
|
||||
if not message.reply_to_message:
|
||||
return await message.reply_text("Reply to a message to report that user.")
|
||||
reply = message.reply_to_message
|
||||
reply_id = reply.from_user.id if reply.from_user else reply.sender_chat.id
|
||||
user_id = message.from_user.id if message.from_user else message.sender_chat.id
|
||||
if reply_id == user_id:
|
||||
return await message.reply_text("Why are you reporting yourself ?")
|
||||
|
||||
list_of_admins = await list_admins(message.chat.id)
|
||||
linked_chat = (await app.get_chat(message.chat.id)).linked_chat
|
||||
if linked_chat is None:
|
||||
if reply_id in list_of_admins or reply_id == message.chat.id:
|
||||
return await message.reply_text(
|
||||
"Do you know that the user you are replying is an admin ?"
|
||||
)
|
||||
|
||||
elif (
|
||||
reply_id in list_of_admins
|
||||
or reply_id == message.chat.id
|
||||
or reply_id == linked_chat.id
|
||||
):
|
||||
return await message.reply_text(
|
||||
"Do you know that the user you are replying is an admin ?"
|
||||
)
|
||||
user_mention = (
|
||||
reply.from_user.mention if reply.from_user else reply.sender_chat.title
|
||||
)
|
||||
text = f"Reported {user_mention} to admins!"
|
||||
admin_data = [
|
||||
m
|
||||
async for m in app.get_chat_members(
|
||||
message.chat.id, filter=enums.ChatMembersFilter.ADMINISTRATORS
|
||||
)
|
||||
]
|
||||
for admin in admin_data:
|
||||
if admin.user.is_bot or admin.user.is_deleted:
|
||||
# return bots or deleted admins
|
||||
continue
|
||||
text += f"[\u2063](tg://user?id={admin.user.id})"
|
||||
await message.reply_to_message.reply_text(text)
|
||||
175
misskaty/plugins/afk.py
Normal file
175
misskaty/plugins/afk.py
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
# Sample menggunakan modul motor mongodb
|
||||
import time, asyncio
|
||||
from misskaty import app
|
||||
from pyrogram import filters
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from database.afk_db import remove_afk, is_afk, add_afk
|
||||
from misskaty.helper.human_read import get_readable_time2
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
|
||||
__MODULE__ = "AFK"
|
||||
__HELP__ = """/afk [Reason > Optional] - Tell others that you are AFK (Away From Keyboard), so that your boyfriend or girlfriend won't look for you 💔.
|
||||
Just type something in group to remove AFK Status."""
|
||||
|
||||
|
||||
# Handle set AFK Command
|
||||
@capture_err
|
||||
@app.on_message(filters.command(["afk"], COMMAND_HANDLER))
|
||||
async def active_afk(_, message):
|
||||
if message.sender_chat:
|
||||
return
|
||||
user_id = message.from_user.id
|
||||
verifier, reasondb = await is_afk(user_id)
|
||||
if verifier:
|
||||
await remove_afk(user_id)
|
||||
try:
|
||||
afktype = reasondb["type"]
|
||||
timeafk = reasondb["time"]
|
||||
data = reasondb["data"]
|
||||
reasonafk = reasondb["reason"]
|
||||
seenago = get_readable_time2((int(time.time() - timeafk)))
|
||||
if afktype == "text":
|
||||
return await message.reply_text(
|
||||
f"**{message.from_user.first_name}** is back online and was away for {seenago}",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
if afktype == "text_reason":
|
||||
return await message.reply_text(
|
||||
f"**{message.from_user.first_name}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
if afktype == "animation":
|
||||
return (
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{message.from_user.first_name}** is back online and was away for {seenago}",
|
||||
)
|
||||
if str(reasonafk) == "None"
|
||||
else await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{message.from_user.first_name}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}",
|
||||
)
|
||||
)
|
||||
|
||||
elif afktype == "photo":
|
||||
return (
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{user_id}.jpg",
|
||||
caption=f"**{message.from_user.first_name}** is back online and was away for {seenago}",
|
||||
)
|
||||
if str(reasonafk) == "None"
|
||||
else await message.reply_photo(
|
||||
photo=f"downloads/{user_id}.jpg",
|
||||
caption=f"**{message.from_user.first_name}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}",
|
||||
)
|
||||
)
|
||||
|
||||
except Exception:
|
||||
return await message.reply_text(
|
||||
f"**{message.from_user.first_name}** is back online.",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
if len(message.command) == 1 and not message.reply_to_message:
|
||||
details = {
|
||||
"type": "text",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": None,
|
||||
}
|
||||
elif len(message.command) > 1 and not message.reply_to_message:
|
||||
_reason = (message.text.split(None, 1)[1].strip())[:100]
|
||||
details = {
|
||||
"type": "text_reason",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": _reason,
|
||||
}
|
||||
elif len(message.command) == 1 and message.reply_to_message.animation:
|
||||
_data = message.reply_to_message.animation.file_id
|
||||
details = {
|
||||
"type": "animation",
|
||||
"time": time.time(),
|
||||
"data": _data,
|
||||
"reason": None,
|
||||
}
|
||||
elif len(message.command) > 1 and message.reply_to_message.animation:
|
||||
_data = message.reply_to_message.animation.file_id
|
||||
_reason = (message.text.split(None, 1)[1].strip())[:100]
|
||||
details = {
|
||||
"type": "animation",
|
||||
"time": time.time(),
|
||||
"data": _data,
|
||||
"reason": _reason,
|
||||
}
|
||||
elif len(message.command) == 1 and message.reply_to_message.photo:
|
||||
await app.download_media(message.reply_to_message, file_name=f"{user_id}.jpg")
|
||||
details = {
|
||||
"type": "photo",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": None,
|
||||
}
|
||||
elif len(message.command) > 1 and message.reply_to_message.photo:
|
||||
await app.download_media(message.reply_to_message, file_name=f"{user_id}.jpg")
|
||||
_reason = message.text.split(None, 1)[1].strip()
|
||||
details = {
|
||||
"type": "photo",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": _reason,
|
||||
}
|
||||
elif len(message.command) == 1 and message.reply_to_message.sticker:
|
||||
if message.reply_to_message.sticker.is_animated:
|
||||
details = {
|
||||
"type": "text",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": None,
|
||||
}
|
||||
else:
|
||||
await app.download_media(
|
||||
message.reply_to_message, file_name=f"{user_id}.jpg"
|
||||
)
|
||||
details = {
|
||||
"type": "photo",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": None,
|
||||
}
|
||||
elif len(message.command) > 1 and message.reply_to_message.sticker:
|
||||
_reason = (message.text.split(None, 1)[1].strip())[:100]
|
||||
if message.reply_to_message.sticker.is_animated:
|
||||
details = {
|
||||
"type": "text_reason",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": _reason,
|
||||
}
|
||||
else:
|
||||
await app.download_media(
|
||||
message.reply_to_message, file_name=f"{user_id}.jpg"
|
||||
)
|
||||
details = {
|
||||
"type": "photo",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": _reason,
|
||||
}
|
||||
else:
|
||||
details = {
|
||||
"type": "text",
|
||||
"time": time.time(),
|
||||
"data": None,
|
||||
"reason": None,
|
||||
}
|
||||
|
||||
await add_afk(user_id, details)
|
||||
pesan = await message.reply_text(
|
||||
f"{message.from_user.mention} [<code>{message.from_user.id}</code>] is now AFK! This message will be deleted in 10s."
|
||||
)
|
||||
await asyncio.sleep(10)
|
||||
await pesan.delete()
|
||||
try:
|
||||
await message.delete()
|
||||
except:
|
||||
pass
|
||||
44
misskaty/plugins/auto_approve.py
Normal file
44
misskaty/plugins/auto_approve.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
from misskaty import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from pyrogram.errors import UserIsBlocked, UserAlreadyParticipant
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
|
||||
|
||||
@capture_err
|
||||
@app.on_chat_join_request(filters.chat(-1001686184174))
|
||||
async def approve_join_chat(c, m):
|
||||
try:
|
||||
markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="Sudah", callback_data=f"approve_{m.chat.id}"), InlineKeyboardButton(text="Belum", callback_data=f"declined_{m.chat.id}")]])
|
||||
await c.send_message(
|
||||
m.from_user.id,
|
||||
"<b>PERMINTAAN JOIN CHANNEL YMOVIEZ REBORN</b>\n\nSebelum masuk ke channel ada tes kejujuran, apakah anda sudah membaca catatan di @YMovieZ_New? Jika sudah silahkan klik <b>Sudah</b>, jika kamu berbohong resiko kamu tanggung sendiri 😶🌫️.\n\nBot by @YasirPediaChannel",
|
||||
disable_web_page_preview=True,
|
||||
reply_markup=markup,
|
||||
)
|
||||
except UserIsBlocked:
|
||||
await m.decline()
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^approve"))
|
||||
async def approve_chat(c, q):
|
||||
i, chat = q.data.split("_")
|
||||
try:
|
||||
await q.message.edit("Yeayy, selamat kamu bisa bergabung di Channel YMovieZ Reborn...")
|
||||
await c.approve_chat_join_request(chat, q.from_user.id)
|
||||
except UserAlreadyParticipant:
|
||||
await q.message.edit("Kamu sudah di acc join grup, jadi ga perlu menekan button.")
|
||||
except Exception as err:
|
||||
await q.message.edit(err)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^declined"))
|
||||
async def decline_chat(c, q):
|
||||
i, chat = q.data.split("_")
|
||||
try:
|
||||
await q.message.edit("Yahh, kamu ditolak join channel. Biasakan rajin membaca yahhh..")
|
||||
await c.decline_chat_join_request(chat, q.from_user.id)
|
||||
except UserAlreadyParticipant:
|
||||
await q.message.edit("Kamu sudah di acc join grup, jadi ga perlu menekan button.")
|
||||
except Exception as err:
|
||||
await q.message.edit(err)
|
||||
93
misskaty/plugins/auto_forwarder.py
Normal file
93
misskaty/plugins/auto_forwarder.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# Code copy from https://github.com/AbirHasan2005/Forward-Client
|
||||
import logging
|
||||
from misskaty import user
|
||||
from pyrogram import filters
|
||||
from asyncio import sleep
|
||||
from pyrogram.types import Message
|
||||
from pyrogram.errors import FloodWait
|
||||
from misskaty.vars import (
|
||||
FORWARD_FILTERS,
|
||||
BLOCK_FILES_WITHOUT_EXTENSIONS,
|
||||
BLOCKED_EXTENSIONS,
|
||||
FORWARD_FROM_CHAT_ID,
|
||||
FORWARD_TO_CHAT_ID,
|
||||
MINIMUM_FILE_SIZE,
|
||||
)
|
||||
|
||||
|
||||
async def FilterMessage(message: Message):
|
||||
if (message.forward_from or message.forward_from_chat) and (
|
||||
"forwarded" not in FORWARD_FILTERS
|
||||
):
|
||||
return 400
|
||||
if (len(FORWARD_FILTERS) == 9) or (
|
||||
(message.video and ("video" in FORWARD_FILTERS))
|
||||
or (message.document and ("document" in FORWARD_FILTERS))
|
||||
or (message.photo and ("photo" in FORWARD_FILTERS))
|
||||
or (message.audio and ("audio" in FORWARD_FILTERS))
|
||||
or (message.text and ("text" in FORWARD_FILTERS))
|
||||
or (message.animation and ("gif" in FORWARD_FILTERS))
|
||||
or (message.poll and ("poll" in FORWARD_FILTERS))
|
||||
or (message.sticker and ("sticker" in FORWARD_FILTERS))
|
||||
):
|
||||
return 200
|
||||
else:
|
||||
return 400
|
||||
|
||||
|
||||
async def CheckBlockedExt(event: Message):
|
||||
media = event.document or event.video or event.audio or event.animation
|
||||
if (BLOCK_FILES_WITHOUT_EXTENSIONS is True) and ("." not in media.file_name):
|
||||
return True
|
||||
if (media is not None) and (media.file_name is not None):
|
||||
_file = media.file_name.rsplit(".", 1)
|
||||
if len(_file) == 2:
|
||||
return (
|
||||
_file[-1].lower() in BLOCKED_EXTENSIONS
|
||||
or _file[-1].upper() in BLOCKED_EXTENSIONS
|
||||
)
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
async def CheckFileSize(msg: Message):
|
||||
media = msg.video or msg.document or msg.audio or msg.photo or msg.animation
|
||||
return MINIMUM_FILE_SIZE is None or media.file_size >= int(MINIMUM_FILE_SIZE)
|
||||
|
||||
|
||||
async def ForwardMessage(client: user, msg: Message):
|
||||
try:
|
||||
## --- Check 1 --- ##
|
||||
can_forward = await FilterMessage(message=msg)
|
||||
if can_forward == 400:
|
||||
return 400
|
||||
## --- Check 2 --- ##
|
||||
has_blocked_ext = await CheckBlockedExt(event=msg)
|
||||
if has_blocked_ext is True:
|
||||
return 400
|
||||
## --- Check 3 --- ##
|
||||
file_size_passed = await CheckFileSize(msg=msg)
|
||||
if file_size_passed is False:
|
||||
return 400
|
||||
## --- Check 4 --- ##
|
||||
for i in range(len(FORWARD_TO_CHAT_ID)):
|
||||
try:
|
||||
await msg.copy(FORWARD_TO_CHAT_ID[i])
|
||||
except FloodWait as e:
|
||||
await sleep(e.value)
|
||||
logging.warning(f"#FloodWait: Stopped Forwarder for {e.x}s!")
|
||||
await ForwardMessage(client, msg)
|
||||
except Exception as err:
|
||||
logging.warning(
|
||||
f"#ERROR: {err}\n\nUnable to Forward Message to {str(FORWARD_TO_CHAT_ID[i])}, reason: <code>{err}</code>"
|
||||
)
|
||||
except Exception as err:
|
||||
logging.warning(f"#ERROR: {err}")
|
||||
|
||||
|
||||
@user.on_message((filters.text | filters.media) & filters.chat(FORWARD_FROM_CHAT_ID))
|
||||
async def forwardubot(client: user, message: Message):
|
||||
try_forward = await ForwardMessage(client, message)
|
||||
if try_forward == 400:
|
||||
return
|
||||
40
misskaty/plugins/banned.py
Normal file
40
misskaty/plugins/banned.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
from pyrogram import filters
|
||||
from utils import temp
|
||||
from pyrogram.types import Message
|
||||
from database.users_chats_db import db
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from misskaty.vars import SUPPORT_CHAT
|
||||
from misskaty import app
|
||||
|
||||
|
||||
async def banned_users(_, client, message: Message):
|
||||
return (message.from_user is not None or not message.sender_chat) and message.from_user.id in temp.BANNED_USERS
|
||||
|
||||
|
||||
banned_user = filters.create(banned_users)
|
||||
|
||||
|
||||
async def disabled_chat(_, client, message: Message):
|
||||
return message.chat.id in temp.BANNED_CHATS
|
||||
|
||||
|
||||
disabled_group = filters.create(disabled_chat)
|
||||
|
||||
|
||||
@app.on_message(filters.private & banned_user & filters.incoming)
|
||||
async def ban_reply(bot, message):
|
||||
ban = await db.get_ban_status(message.from_user.id)
|
||||
await message.reply(f'Sorry Dude, You are Banned to use Me. \nBan Reason: {ban["ban_reason"]}')
|
||||
|
||||
|
||||
@app.on_message(filters.group & disabled_group & filters.incoming)
|
||||
async def grp_bd(bot, message):
|
||||
buttons = [[InlineKeyboardButton("Support", url=f"https://t.me/{SUPPORT_CHAT}")]]
|
||||
reply_markup = InlineKeyboardMarkup(buttons)
|
||||
vazha = await db.get_chat(message.chat.id)
|
||||
k = await message.reply(text=f"CHAT NOT ALLOWED 🐞\n\nMy admins has restricted me from working here ! If you want to know more about it contact support..\nReason : <code>{vazha['reason']}</code>.", reply_markup=reply_markup)
|
||||
try:
|
||||
await k.pin()
|
||||
except:
|
||||
pass
|
||||
await bot.leave_chat(message.chat.id)
|
||||
44
misskaty/plugins/broadcast.py
Normal file
44
misskaty/plugins/broadcast.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
from pyrogram import filters
|
||||
import datetime
|
||||
import time
|
||||
from database.users_chats_db import db
|
||||
from misskaty.vars import SUDO
|
||||
from utils import broadcast_messages
|
||||
import asyncio
|
||||
from misskaty import app
|
||||
|
||||
|
||||
@app.on_message(filters.command("broadcast") & filters.user(SUDO) & filters.reply)
|
||||
async def broadcast(bot, message):
|
||||
users = await db.get_all_users()
|
||||
b_msg = message.reply_to_message
|
||||
sts = await message.reply_text(text="Broadcasting your messages...")
|
||||
start_time = time.time()
|
||||
total_users = await db.total_users_count()
|
||||
done = 0
|
||||
blocked = 0
|
||||
deleted = 0
|
||||
failed = 0
|
||||
|
||||
success = 0
|
||||
async for user in users:
|
||||
pti, sh = await broadcast_messages(int(user["id"]), b_msg)
|
||||
if pti:
|
||||
success += 1
|
||||
elif pti == False:
|
||||
if sh == "Bocked":
|
||||
blocked += 1
|
||||
elif sh == "Deleted":
|
||||
deleted += 1
|
||||
elif sh == "Error":
|
||||
failed += 1
|
||||
done += 1
|
||||
await asyncio.sleep(2)
|
||||
if not done % 20:
|
||||
await sts.edit(
|
||||
f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}"
|
||||
)
|
||||
time_taken = datetime.timedelta(seconds=int(time.time() - start_time))
|
||||
await sts.edit(
|
||||
f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}"
|
||||
)
|
||||
73
misskaty/plugins/bypass.py
Normal file
73
misskaty/plugins/bypass.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import re
|
||||
from misskaty.helper.http import http
|
||||
from misskaty import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from pyrogram.errors import MessageTooLong, EntitiesTooLong
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from misskaty.helper.tools import rentry
|
||||
from urllib.parse import unquote
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.helper.human_read import get_readable_file_size
|
||||
|
||||
LIST_LINK = """
|
||||
- Pling and all aliases.
|
||||
- Other link soon...
|
||||
"""
|
||||
|
||||
__MODULE__ = "Bypass"
|
||||
__HELP__ = f"""
|
||||
/directurl [Link] - Bypass URL.
|
||||
|
||||
Supported Link:
|
||||
{LIST_LINK}
|
||||
"""
|
||||
|
||||
|
||||
async def pling_bypass(url):
|
||||
try:
|
||||
id_url = re.search(r"https?://(store.kde.org|www.pling.com)\/p\/(\d+)", url)[2]
|
||||
link = f"https://www.pling.com/p/{id_url}/loadFiles"
|
||||
res = await http.get(link)
|
||||
json_dic_files = res.json().pop("files")
|
||||
msg = f"\n**Source Link** :\n`{url}`\n**Direct Link :**\n"
|
||||
msg += "\n".join(
|
||||
f'**→ [{i["name"]}]({unquote(i["url"])}) ({get_readable_file_size(int(i["size"]))})**'
|
||||
for i in json_dic_files
|
||||
)
|
||||
return msg
|
||||
except Exception as e:
|
||||
return e
|
||||
|
||||
|
||||
@app.on_message(filters.command(["directurl"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def bypass(_, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply(
|
||||
f"Gunakan perintah /{message.command[0]} untuk bypass url"
|
||||
)
|
||||
url = message.command[1]
|
||||
msg = await message.reply("Bypassing URL..", quote=True)
|
||||
mention = f"**Bypasser:** {message.from_user.mention} ({message.from_user.id})"
|
||||
if re.match(r"https?://(store.kde.org|www.pling.com)\/p\/(\d+)", url):
|
||||
data = await pling_bypass(url)
|
||||
try:
|
||||
await msg.edit(f"{data}\n\n{mention}")
|
||||
except (MessageTooLong, EntitiesTooLong):
|
||||
result = await rentry(data)
|
||||
markup = InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton("Open Link", url=result),
|
||||
InlineKeyboardButton("Raw Link", url=f"{result}/raw"),
|
||||
]
|
||||
]
|
||||
)
|
||||
await msg.edit(
|
||||
f"{result}\n\nBecause your bypassed url is too long, so your link will be pasted to rentry.\n{mention}",
|
||||
reply_markup=markup,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
else:
|
||||
await msg.edit("Unsupported link..")
|
||||
710
misskaty/plugins/code_tester.py
Normal file
710
misskaty/plugins/code_tester.py
Normal file
|
|
@ -0,0 +1,710 @@
|
|||
import aiohttp
|
||||
from pyrogram import enums, filters
|
||||
from pyrogram.errors import MessageTooLong
|
||||
from misskaty import app
|
||||
from misskaty.helper.tools import rentry
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
|
||||
__MODULE__ = "CodeTester"
|
||||
__HELP__ = """
|
||||
This feature allows you to run multiple programming languages through this bot via the Glot.io api. The following is a list of supported languages, for temporary commands only support with a "!" like the example below.
|
||||
|
||||
List of Supported Programming Languages:
|
||||
~> assembly
|
||||
~> ats
|
||||
~> bash
|
||||
~> c
|
||||
~> clojure
|
||||
~> cobol
|
||||
~> coffeescript
|
||||
~> cpp
|
||||
~> crystal
|
||||
~> csharp
|
||||
~> d
|
||||
~> elixir
|
||||
~> elm
|
||||
~> erlang
|
||||
~> fsharp
|
||||
~> go
|
||||
~> groovy
|
||||
~> haskell
|
||||
~> idris
|
||||
~> java
|
||||
~> javascript
|
||||
~> julia
|
||||
~> kotlin
|
||||
~> lua
|
||||
~> mercury
|
||||
~> nim
|
||||
~> nix
|
||||
~> ocaml
|
||||
~> perl
|
||||
~> php
|
||||
~> python
|
||||
~> raku
|
||||
~> ruby
|
||||
~> rust
|
||||
~> scala
|
||||
~> swift
|
||||
~> typescript
|
||||
|
||||
**Example:**
|
||||
~> `!python print("Hai aku MissKatyRoBot")`
|
||||
"""
|
||||
|
||||
|
||||
async def listcode():
|
||||
async with aiohttp.ClientSession() as session:
|
||||
r = await session.get("https://glot.io/api/run")
|
||||
return await r.json()
|
||||
|
||||
|
||||
async def glot(lang, langcode, code):
|
||||
async with aiohttp.ClientSession() as session:
|
||||
data = {"files": [{"name": f"misskaty.{langcode}", "content": code}]}
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": "Token b8a2b75a-a078-4089-869c-e53d448b1ebb",
|
||||
}
|
||||
r = await session.post(
|
||||
f"https://glot.io/api/run/{lang}/latest", headers=headers, json=data
|
||||
)
|
||||
return await r.json()
|
||||
|
||||
|
||||
@app.on_message(filters.command(["codelist"], COMMAND_HANDLER))
|
||||
async def list_lang(client, message):
|
||||
daftarlang = await listcode()
|
||||
list_ = "".join(f"~> {i['name']}\n" for i in daftarlang)
|
||||
return await message.reply(
|
||||
f"<b>List of Supported Programming Languages:</b>\n{list_}"
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["assembly"], "!"))
|
||||
@app.on_edited_message(filters.command(["assembly"], "!"))
|
||||
async def assembly(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "asm", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ats"], "!"))
|
||||
@app.on_edited_message(filters.command(["ats"], "!"))
|
||||
async def ats(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "dats", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["bash"], "!"))
|
||||
@app.on_edited_message(filters.command(["bash"], "!"))
|
||||
async def bash(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "sh", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["c"], "!"))
|
||||
@app.on_edited_message(filters.command(["c"], "!"))
|
||||
async def c(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "c", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["clojure"], "!"))
|
||||
@app.on_edited_message(filters.command(["clojure"], "!"))
|
||||
async def clojure(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "clj", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["cobol"], "!"))
|
||||
@app.on_edited_message(filters.command(["cobol"], "!"))
|
||||
async def cobol(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "cob", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["coffeescript"], "!"))
|
||||
@app.on_edited_message(filters.command(["coffeescript"], "!"))
|
||||
async def coffeescript(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "coffee", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["cpp"], "!"))
|
||||
@app.on_edited_message(filters.command(["cpp"], "!"))
|
||||
async def cpp(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "cpp", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["crystal"], "!"))
|
||||
@app.on_edited_message(filters.command(["crystal"], "!"))
|
||||
async def crystal(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "cr", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["csharp"], "!"))
|
||||
@app.on_edited_message(filters.command(["csharp"], "!"))
|
||||
async def csharp(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "cs", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["d"], "!"))
|
||||
@app.on_edited_message(filters.command(["d"], "!"))
|
||||
async def d(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "d", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["elixir"], "!"))
|
||||
@app.on_edited_message(filters.command(["elixir"], "!"))
|
||||
async def elixir(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "ex", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["elm"], "!"))
|
||||
@app.on_edited_message(filters.command(["elm"], "!"))
|
||||
async def elm(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "elm", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["erlang"], "!"))
|
||||
@app.on_edited_message(filters.command(["erlang"], "!"))
|
||||
async def erlang(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "erl", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["fsharp"], "!"))
|
||||
@app.on_edited_message(filters.command(["fsharp"], "!"))
|
||||
async def fsharp(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "fs", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["go"], "!"))
|
||||
@app.on_edited_message(filters.command(["go"], "!"))
|
||||
async def go(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "go", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["groovy"], "!"))
|
||||
@app.on_edited_message(filters.command(["groovy"], "!"))
|
||||
async def groovy(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "groovy", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["haskell"], "!"))
|
||||
@app.on_edited_message(filters.command(["haskell"], "!"))
|
||||
async def haskell(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "hs", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["idris"], "!"))
|
||||
@app.on_edited_message(filters.command(["idris"], "!"))
|
||||
async def idris(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "idr", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["java"], "!"))
|
||||
@app.on_edited_message(filters.command(["java"], "!"))
|
||||
async def java(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "java", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["javascript"], "!"))
|
||||
@app.on_edited_message(filters.command(["javascript"], "!"))
|
||||
async def javascript(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "js", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["julia"], "!"))
|
||||
@app.on_edited_message(filters.command(["julia"], "!"))
|
||||
async def julia(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "jl", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["kotlin"], "!"))
|
||||
@app.on_edited_message(filters.command(["kotlin"], "!"))
|
||||
async def kotlin(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "kt", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["lua"], "!"))
|
||||
@app.on_edited_message(filters.command(["lua"], "!"))
|
||||
async def lua(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "lua", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["mercury"], "!"))
|
||||
@app.on_edited_message(filters.command(["mercury"], "!"))
|
||||
async def mercury(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "m", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["nim"], "!"))
|
||||
@app.on_edited_message(filters.command(["nim"], "!"))
|
||||
async def nim(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "nim", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["nix"], "!"))
|
||||
@app.on_edited_message(filters.command(["nix"], "!"))
|
||||
async def nix(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "nix", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ocaml"], "!"))
|
||||
@app.on_edited_message(filters.command(["ocaml"], "!"))
|
||||
async def ocaml(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "ml", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["perl"], "!"))
|
||||
@app.on_edited_message(filters.command(["perl"], "!"))
|
||||
async def perl(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "pl", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["php"], "!"))
|
||||
@app.on_edited_message(filters.command(["php"], "!"))
|
||||
async def php(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "php", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["python"], "!"))
|
||||
@app.on_edited_message(filters.command(["python"], "!"))
|
||||
async def python(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "py", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["raku"], "!"))
|
||||
@app.on_edited_message(filters.command(["raku"], "!"))
|
||||
async def raku(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "raku", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ruby"], "!"))
|
||||
@app.on_edited_message(filters.command(["ruby"], "!"))
|
||||
async def ruby(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "rb", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["rust"], "!"))
|
||||
@app.on_edited_message(filters.command(["rust"], "!"))
|
||||
async def rust(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "rs", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["scala"], "!"))
|
||||
@app.on_edited_message(filters.command(["scala"], "!"))
|
||||
async def scala(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "scala", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["swift"], "!"))
|
||||
@app.on_edited_message(filters.command(["swift"], "!"))
|
||||
async def swift(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "swift", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["typescript"], "!"))
|
||||
@app.on_edited_message(filters.command(["typescript"], "!"))
|
||||
async def typescript(client, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Please enter the code you want to run.")
|
||||
res = await glot(message.command[0], "ts", message.text.split(None, 1)[1])
|
||||
hasil = res["stdout"] or res["stderr"]
|
||||
hasil = f"Result :\n{hasil}"
|
||||
try:
|
||||
return await message.reply(hasil, parse_mode=enums.ParseMode.DISABLED)
|
||||
except MessageTooLong:
|
||||
post = await rentry(hasil)
|
||||
return await message.reply(f"<b>View Result in Rentry:</b>\n{post}")
|
||||
except Exception as e:
|
||||
return await message.reply(e, parse_mode=enums.ParseMode.DISABLED)
|
||||
77
misskaty/plugins/copy_forward.py
Normal file
77
misskaty/plugins/copy_forward.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
from pyrogram import filters, enums
|
||||
from pyrogram.errors import UserIsBlocked, UserNotParticipant
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty import app
|
||||
|
||||
|
||||
@app.on_message(filters.command(["copy"], COMMAND_HANDLER))
|
||||
async def copy(client, message):
|
||||
if len(message.command) == 1:
|
||||
if not message.reply_to_message:
|
||||
return await message.reply("Silahkan balas pesan yang mau dicopy.")
|
||||
try:
|
||||
await message.reply_to_message.copy(message.from_user.id, caption_entities=message.reply_to_message.entities, reply_markup=message.reply_to_message.reply_markup)
|
||||
return await message.reply_text("Pesan berhasil dikirim..")
|
||||
except UserIsBlocked:
|
||||
return await message.reply("Silahkan PM Saya untuk mengcopy pesan ke chat pribadi..", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="💬 Chat Aku Yahh", url="https://t.me/MissKatyRoBot")]]))
|
||||
except Exception as e:
|
||||
return await message.reply(f"ERROR: {str(e)}")
|
||||
elif message.reply_to_message:
|
||||
try:
|
||||
idtujuan = message.command[1]
|
||||
userstat = await app.get_chat_member(-1001686184174, message.from_user.id)
|
||||
if (
|
||||
userstat.status
|
||||
not in [
|
||||
enums.ChatMemberStatus.ADMINISTRATOR,
|
||||
enums.ChatMemberStatus.OWNER,
|
||||
]
|
||||
and message.from_user.id != 2024984460
|
||||
):
|
||||
return await message.reply_text("🦉🦉🦉")
|
||||
await message.reply_to_message.copy(idtujuan, caption_entities=message.reply_to_message.entities, reply_markup=message.reply_to_message.reply_markup)
|
||||
return await message.reply_text("Pesan berhasil dikirim..")
|
||||
except UserNotParticipant:
|
||||
return await message.reply("Command ini hanya untuk admin YMoviezNew")
|
||||
except Exception as e:
|
||||
return await message.reply(f"ERROR: {e}")
|
||||
else:
|
||||
await message.reply("Silahkan balas pesan yang mau dicopy.")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["forward"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def forward(client, message):
|
||||
if len(message.command) == 1:
|
||||
if not message.reply_to_message:
|
||||
return await message.reply("Silahkan balas pesan yang mau dicopy.")
|
||||
try:
|
||||
await message.reply_to_message.forward(message.from_user.id)
|
||||
return await message.reply_text("Pesan berhasil dikirim..")
|
||||
except UserIsBlocked:
|
||||
return await message.reply("Silahkan PM Saya untuk memforward pesan ke chat pribadi..", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="💬 Chat Aku Yahh", url="https://t.me/MissKatyRoBot")]]))
|
||||
except Exception as e:
|
||||
return await message.reply(f"ERROR: {str(e)}")
|
||||
elif message.reply_to_message:
|
||||
try:
|
||||
idtujuan = message.command[1]
|
||||
userstat = await app.get_chat_member(-1001686184174, message.from_user.id)
|
||||
if (
|
||||
userstat.status
|
||||
not in [
|
||||
enums.ChatMemberStatus.ADMINISTRATOR,
|
||||
enums.ChatMemberStatus.OWNER,
|
||||
]
|
||||
and message.from_user.id != 2024984460
|
||||
):
|
||||
return await message.reply_text("🦉🦉🦉")
|
||||
await message.reply_to_message.forward(idtujuan)
|
||||
return await message.reply_text("Pesan berhasil dikirim..")
|
||||
except UserNotParticipant:
|
||||
return await message.reply("Comman ini hanya untuk admin YMoviezNew")
|
||||
except Exception as e:
|
||||
return await message.reply(f"ERROR: {e}")
|
||||
else:
|
||||
await message.reply("Silahkan balas pesan yang mau diforward.")
|
||||
220
misskaty/plugins/detect_afk.py
Normal file
220
misskaty/plugins/detect_afk.py
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
import re
|
||||
import time
|
||||
import asyncio
|
||||
from misskaty import app
|
||||
from pyrogram import filters, enums
|
||||
from database.afk_db import remove_afk, is_afk
|
||||
from misskaty.helper.human_read import get_readable_time2
|
||||
|
||||
# Detect user that AFK based on Yukki Repo
|
||||
@app.on_message(
|
||||
filters.group & ~filters.bot & ~filters.via_bot,
|
||||
group=1,
|
||||
)
|
||||
async def chat_watcher_func(_, message):
|
||||
if message.sender_chat:
|
||||
return
|
||||
userid = message.from_user.id
|
||||
user_name = message.from_user.first_name
|
||||
if message.entities:
|
||||
possible = ["/afk", f"/afk@MissKatyRoBot", "!afk"]
|
||||
message_text = message.text or message.caption
|
||||
for entity in message.entities:
|
||||
if entity.type == enums.MessageEntityType.BOT_COMMAND:
|
||||
if (message_text[0 : 0 + entity.length]).lower() in possible:
|
||||
return
|
||||
|
||||
msg = ""
|
||||
replied_user_id = 0
|
||||
|
||||
# Self AFK
|
||||
verifier, reasondb = await is_afk(userid)
|
||||
if verifier:
|
||||
await remove_afk(userid)
|
||||
try:
|
||||
afktype = reasondb["type"]
|
||||
timeafk = reasondb["time"]
|
||||
data = reasondb["data"]
|
||||
reasonafk = reasondb["reason"]
|
||||
seenago = get_readable_time2((int(time.time() - timeafk)))
|
||||
if afktype == "text":
|
||||
msg += f"**{user_name[:25]}** is back online and was away for {seenago}\n\n"
|
||||
if afktype == "text_reason":
|
||||
msg += f"**{user_name[:25]}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}\n\n"
|
||||
if afktype == "animation":
|
||||
if str(reasonafk) == "None":
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{user_name[:25]}** is back online and was away for {seenago}\n\n",
|
||||
)
|
||||
else:
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{user_name[:25]}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}\n\n",
|
||||
)
|
||||
if afktype == "photo":
|
||||
if str(reasonafk) == "None":
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{userid}.jpg",
|
||||
caption=f"**{user_name[:25]}** is back online and was away for {seenago}\n\n",
|
||||
)
|
||||
else:
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{userid}.jpg",
|
||||
caption=f"**{user_name[:25]}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}\n\n",
|
||||
)
|
||||
except:
|
||||
msg += f"**{user_name[:25]}** is back online.\n\n"
|
||||
|
||||
# Replied to a User which is AFK
|
||||
if message.reply_to_message:
|
||||
try:
|
||||
replied_first_name = message.reply_to_message.from_user.first_name
|
||||
replied_user_id = message.reply_to_message.from_user.id
|
||||
verifier, reasondb = await is_afk(replied_user_id)
|
||||
if verifier:
|
||||
try:
|
||||
afktype = reasondb["type"]
|
||||
timeafk = reasondb["time"]
|
||||
data = reasondb["data"]
|
||||
reasonafk = reasondb["reason"]
|
||||
seenago = get_readable_time2((int(time.time() - timeafk)))
|
||||
if afktype == "text":
|
||||
msg += f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n"
|
||||
if afktype == "text_reason":
|
||||
msg += f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n"
|
||||
if afktype == "animation":
|
||||
if str(reasonafk) == "None":
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n",
|
||||
)
|
||||
else:
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n",
|
||||
)
|
||||
if afktype == "photo":
|
||||
if str(reasonafk) == "None":
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{replied_user_id}.jpg",
|
||||
caption=f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n",
|
||||
)
|
||||
else:
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{replied_user_id}.jpg",
|
||||
caption=f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n",
|
||||
)
|
||||
except Exception:
|
||||
msg += f"**{replied_first_name}** is AFK\n\n"
|
||||
except:
|
||||
pass
|
||||
|
||||
# If username or mentioned user is AFK
|
||||
if message.entities:
|
||||
entity = message.entities
|
||||
j = 0
|
||||
for x in range(len(entity)):
|
||||
if (entity[j].type) == enums.MessageEntityType.MENTION:
|
||||
found = re.findall("@([_0-9a-zA-Z]+)", message.text)
|
||||
try:
|
||||
get_user = found[j]
|
||||
user = await app.get_users(get_user)
|
||||
if user.id == replied_user_id:
|
||||
j += 1
|
||||
continue
|
||||
except:
|
||||
j += 1
|
||||
continue
|
||||
verifier, reasondb = await is_afk(user.id)
|
||||
if verifier:
|
||||
try:
|
||||
afktype = reasondb["type"]
|
||||
timeafk = reasondb["time"]
|
||||
data = reasondb["data"]
|
||||
reasonafk = reasondb["reason"]
|
||||
seenago = get_readable_time2((int(time.time() - timeafk)))
|
||||
if afktype == "text":
|
||||
msg += f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n"
|
||||
if afktype == "text_reason":
|
||||
msg += f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n"
|
||||
if afktype == "animation":
|
||||
if str(reasonafk) == "None":
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n",
|
||||
)
|
||||
else:
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason**: {reasonafk}\n\n",
|
||||
)
|
||||
if afktype == "photo":
|
||||
if str(reasonafk) == "None":
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{user.id}.jpg",
|
||||
caption=f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n",
|
||||
)
|
||||
else:
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{user.id}.jpg",
|
||||
caption=f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n",
|
||||
)
|
||||
except:
|
||||
msg += f"**{user.first_name[:25]}** is AFK\n\n"
|
||||
elif (entity[j].type) == enums.MessageEntityType.TEXT_MENTION:
|
||||
try:
|
||||
user_id = entity[j].user.id
|
||||
if user_id == replied_user_id:
|
||||
j += 1
|
||||
continue
|
||||
first_name = entity[j].user.first_name
|
||||
except:
|
||||
j += 1
|
||||
continue
|
||||
verifier, reasondb = await is_afk(user_id)
|
||||
if verifier:
|
||||
try:
|
||||
afktype = reasondb["type"]
|
||||
timeafk = reasondb["time"]
|
||||
data = reasondb["data"]
|
||||
reasonafk = reasondb["reason"]
|
||||
seenago = get_readable_time2((int(time.time() - timeafk)))
|
||||
if afktype == "text":
|
||||
msg += (
|
||||
f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n"
|
||||
)
|
||||
if afktype == "text_reason":
|
||||
msg += f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n"
|
||||
if afktype == "animation":
|
||||
if str(reasonafk) == "None":
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n",
|
||||
)
|
||||
else:
|
||||
await message.reply_animation(
|
||||
data,
|
||||
caption=f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n",
|
||||
)
|
||||
if afktype == "photo":
|
||||
if str(reasonafk) == "None":
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{user_id}.jpg",
|
||||
caption=f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n",
|
||||
)
|
||||
else:
|
||||
await message.reply_photo(
|
||||
photo=f"downloads/{user_id}.jpg",
|
||||
caption=f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n",
|
||||
)
|
||||
except:
|
||||
msg += f"**{first_name[:25]}** is AFK\n\n"
|
||||
j += 1
|
||||
if msg != "":
|
||||
try:
|
||||
pesan = await message.reply_text(msg, disable_web_page_preview=True)
|
||||
await asyncio.sleep(20)
|
||||
await pesan.delete()
|
||||
except:
|
||||
return
|
||||
144
misskaty/plugins/dev.py
Normal file
144
misskaty/plugins/dev.py
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
import io
|
||||
import sys
|
||||
import os
|
||||
import traceback
|
||||
import asyncio
|
||||
from pyrogram import filters, enums
|
||||
from misskaty.vars import COMMAND_HANDLER, SUDO
|
||||
from misskaty import app
|
||||
|
||||
__MODULE__ = "DevCommand"
|
||||
__HELP__ = """
|
||||
**For Owner Bot Only.**
|
||||
/run [args] - Run eval CMD
|
||||
/shell [args] - Run Exec/Terminal CMD
|
||||
/download [link/reply_to_telegram_file] - Download file from Telegram
|
||||
|
||||
**For Public Use**
|
||||
/json - Send structure message Telegram in JSON using Pyrogram Style.
|
||||
"""
|
||||
|
||||
|
||||
@app.on_message(filters.command(["logs"]) & filters.user(SUDO))
|
||||
async def log_file(bot, message):
|
||||
"""Send log file"""
|
||||
try:
|
||||
await message.reply_document("MissKatyLogs.txt", caption="Log Bot MissKatyPyro")
|
||||
except Exception as e:
|
||||
await message.reply(str(e))
|
||||
|
||||
|
||||
@app.on_message(filters.command(["donate"], COMMAND_HANDLER))
|
||||
async def donate(_, message):
|
||||
await message.reply_photo(
|
||||
"AgACAgQAAxkBAAECsVNjbMvjxbN4gRafvNBH-Kv-Zqml8wACzq4xG95tbVPDeZ_UusonbAAIAQADAgADeQAHHgQ",
|
||||
caption=f"Hai {message.from_user.mention}, jika kamu merasa bot ini berguna bisa melakukan donasi dengan scan kode QRIS diatas untuk kebutuhan server dan lainnya. Terimakasih..",
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.command(["balas"], COMMAND_HANDLER) & filters.user(SUDO) & filters.reply
|
||||
)
|
||||
async def balas(c, m):
|
||||
pesan = m.text.split(" ", 1)
|
||||
await m.delete()
|
||||
await m.reply(pesan[1], reply_to_message_id=m.reply_to_message.id)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["neofetch"], COMMAND_HANDLER) & filters.user(SUDO))
|
||||
async def neofetch(c, m):
|
||||
neofetch = (await shell_exec("neofetch --stdout"))[0]
|
||||
await m.reply(f"<code>{neofetch}</code>")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["shell", "sh"], COMMAND_HANDLER) & filters.user(SUDO))
|
||||
@app.on_edited_message(
|
||||
filters.command(["shell", "sh"], COMMAND_HANDLER) & filters.user(SUDO)
|
||||
)
|
||||
async def shell(client, message):
|
||||
cmd = message.text.split(" ", 1)
|
||||
if len(cmd) == 1:
|
||||
return await message.reply("No command to execute was given.")
|
||||
shell = (await shell_exec(cmd[1]))[0]
|
||||
if len(shell) > 3000:
|
||||
with open("shell_output.txt", "w") as file:
|
||||
file.write(shell)
|
||||
with open("shell_output.txt", "rb") as doc:
|
||||
await message.reply_document(document=doc, file_name=doc.name)
|
||||
try:
|
||||
os.remove("shell_output.txt")
|
||||
except:
|
||||
pass
|
||||
elif len(shell) != 0:
|
||||
await message.reply(shell, parse_mode=enums.ParseMode.HTML)
|
||||
else:
|
||||
await message.reply("No Reply")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ev", "run"]) & filters.user(SUDO))
|
||||
@app.on_edited_message(filters.command(["ev", "run"]) & filters.user(SUDO))
|
||||
async def evaluation_cmd_t(client, message):
|
||||
status_message = await message.reply("__Processing eval pyrogram...__")
|
||||
try:
|
||||
cmd = message.text.split(" ", maxsplit=1)[1]
|
||||
except IndexError:
|
||||
return await status_message.edit("__No evaluate message!__")
|
||||
old_stderr = sys.stderr
|
||||
old_stdout = sys.stdout
|
||||
redirected_output = sys.stdout = io.StringIO()
|
||||
redirected_error = sys.stderr = io.StringIO()
|
||||
stdout, stderr, exc = None, None, None
|
||||
|
||||
try:
|
||||
await aexec(cmd, client, message)
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
|
||||
stdout = redirected_output.getvalue()
|
||||
stderr = redirected_error.getvalue()
|
||||
sys.stdout = old_stdout
|
||||
sys.stderr = old_stderr
|
||||
|
||||
evaluation = ""
|
||||
if exc:
|
||||
evaluation = exc
|
||||
elif stderr:
|
||||
evaluation = stderr
|
||||
elif stdout:
|
||||
evaluation = stdout
|
||||
else:
|
||||
evaluation = "Success"
|
||||
|
||||
final_output = f"**EVAL**:\n`{cmd}`\n\n**OUTPUT**:\n`{evaluation.strip()}`\n"
|
||||
|
||||
if len(final_output) > 4096:
|
||||
with open("MissKatyEval.txt", "w+", encoding="utf8") as out_file:
|
||||
out_file.write(final_output)
|
||||
await status_message.reply_document(
|
||||
document="MissKatyEval.txt",
|
||||
caption=cmd[: 4096 // 4 - 1],
|
||||
disable_notification=True,
|
||||
)
|
||||
os.remove("MissKatyEval.txt")
|
||||
await status_message.delete()
|
||||
else:
|
||||
await status_message.edit(final_output, parse_mode=enums.ParseMode.MARKDOWN)
|
||||
|
||||
|
||||
async def aexec(code, client, message):
|
||||
exec(
|
||||
"async def __aexec(client, message): "
|
||||
+ "".join(f"\n {l_}" for l_ in code.split("\n"))
|
||||
)
|
||||
return await locals()["__aexec"](client, message)
|
||||
|
||||
|
||||
async def shell_exec(code, treat=True):
|
||||
process = await asyncio.create_subprocess_shell(
|
||||
code, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT
|
||||
)
|
||||
|
||||
stdout = (await process.communicate())[0]
|
||||
if treat:
|
||||
stdout = stdout.decode().strip()
|
||||
return stdout, process
|
||||
198
misskaty/plugins/download_upload.py
Normal file
198
misskaty/plugins/download_upload.py
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
import time
|
||||
import asyncio
|
||||
import math
|
||||
import os
|
||||
import logging
|
||||
import aiohttp
|
||||
import json
|
||||
from misskaty.helper.http import http
|
||||
from bs4 import BeautifulSoup
|
||||
from misskaty import app
|
||||
from pySmartDL import SmartDL
|
||||
from datetime import datetime
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.vars import COMMAND_HANDLER, SUDO
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from misskaty.helper.pyro_progress import (
|
||||
progress_for_pyrogram,
|
||||
humanbytes,
|
||||
)
|
||||
|
||||
__MODULE__ = "Download/Upload"
|
||||
__HELP__ = """
|
||||
/download [url] - Download file from URL (Sudo Only)
|
||||
/download [reply_to_TG_File] - Download TG File
|
||||
/tiktokdl [link] - Download TikTok Video
|
||||
/fbdl [link] - Download Facebook Video
|
||||
/anon [link] - Upload files to Anonfiles
|
||||
/ytdown [link] - Download YouTube dengan YT-DLP
|
||||
"""
|
||||
|
||||
|
||||
@app.on_message(filters.command(["anon"], COMMAND_HANDLER))
|
||||
async def upload(bot, message):
|
||||
if not message.reply_to_message:
|
||||
return await message.reply("Please reply to media file.")
|
||||
if message.reply_to_message is not None:
|
||||
vid = [message.reply_to_message.video, message.reply_to_message.document]
|
||||
for v in vid:
|
||||
if v is not None:
|
||||
break
|
||||
m = await message.reply("Download your file to my Server...")
|
||||
now = time.time()
|
||||
fileku = await message.reply_to_message.download(
|
||||
progress=progress_for_pyrogram,
|
||||
progress_args=("Trying to download, please wait..", m, now),
|
||||
)
|
||||
try:
|
||||
files = {"file": open(fileku, "rb")}
|
||||
await m.edit("Uploading to Anonfile, Please Wait||")
|
||||
callapi = await http.post("https://api.anonfiles.com/upload", files=files)
|
||||
text = callapi.json()
|
||||
output = f'<u>File Uploaded to Anonfile</u>\n\n📂 File Name: {text["data"]["file"]["metadata"]["name"]}\n\n📦 File Size: {text["data"]["file"]["metadata"]["size"]["readable"]}\n\n📥 Download Link: {text["data"]["file"]["url"]["full"]}'
|
||||
|
||||
btn = InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"📥 Download 📥", url=f"{text['data']['file']['url']['full']}"
|
||||
)
|
||||
]
|
||||
]
|
||||
)
|
||||
await m.edit(output, reply_markup=btn)
|
||||
except Exception as e:
|
||||
await bot.send_message(message.chat.id, text=f"Something Went Wrong!\n\n{e}")
|
||||
os.remove(sed)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["download"], COMMAND_HANDLER) & filters.user(SUDO))
|
||||
@capture_err
|
||||
async def download(client, message):
|
||||
pesan = await message.reply_text("Processing...", quote=True)
|
||||
if message.reply_to_message is not None:
|
||||
start_t = datetime.now()
|
||||
c_time = time.time()
|
||||
the_real_download_location = await client.download_media(
|
||||
message=message.reply_to_message,
|
||||
progress=progress_for_pyrogram,
|
||||
progress_args=("trying to download, sabar yakk..", pesan, c_time),
|
||||
)
|
||||
end_t = datetime.now()
|
||||
ms = (end_t - start_t).seconds
|
||||
await pesan.edit(
|
||||
f"Downloaded to <code>{the_real_download_location}</code> in <u>{ms}</u> seconds."
|
||||
)
|
||||
elif len(message.command) > 1:
|
||||
start_t = datetime.now()
|
||||
the_url_parts = " ".join(message.command[1:])
|
||||
url = the_url_parts.strip()
|
||||
custom_file_name = os.path.basename(url)
|
||||
if "|" in the_url_parts:
|
||||
url, custom_file_name = the_url_parts.split("|")
|
||||
url = url.strip()
|
||||
custom_file_name = custom_file_name.strip()
|
||||
download_file_path = os.path.join("downloads/", custom_file_name)
|
||||
downloader = SmartDL(url, download_file_path, progress_bar=False)
|
||||
downloader.start(blocking=False)
|
||||
c_time = time.time()
|
||||
while not downloader.isFinished():
|
||||
total_length = downloader.filesize or None
|
||||
downloaded = downloader.get_dl_size()
|
||||
display_message = ""
|
||||
now = time.time()
|
||||
diff = now - c_time
|
||||
percentage = downloader.get_progress() * 100
|
||||
speed = downloader.get_speed()
|
||||
round(diff) * 1000
|
||||
progress_str = "[{0}{1}]\nProgress: {2}%".format(
|
||||
"".join(["█" for _ in range(math.floor(percentage / 5))]),
|
||||
"".join(["░" for _ in range(20 - math.floor(percentage / 5))]),
|
||||
round(percentage, 2),
|
||||
)
|
||||
|
||||
estimated_total_time = downloader.get_eta(human=True)
|
||||
try:
|
||||
current_message = "trying to download...\n"
|
||||
current_message += f"URL: <code>{url}</code>\n"
|
||||
current_message += f"File Name: <code>{custom_file_name}</code>\n"
|
||||
current_message += f"Speed: {speed}\n"
|
||||
current_message += f"{progress_str}\n"
|
||||
current_message += (
|
||||
f"{humanbytes(downloaded)} of {humanbytes(total_length)}\n"
|
||||
)
|
||||
current_message += f"ETA: {estimated_total_time}"
|
||||
if round(diff % 10.00) == 0 and current_message != display_message:
|
||||
await pesan.edit(
|
||||
disable_web_page_preview=True, text=current_message
|
||||
)
|
||||
display_message = current_message
|
||||
await asyncio.sleep(10)
|
||||
except Exception as e:
|
||||
logging.info(str(e))
|
||||
if os.path.exists(download_file_path):
|
||||
end_t = datetime.now()
|
||||
ms = (end_t - start_t).seconds
|
||||
await pesan.edit(
|
||||
f"Downloaded to <code>{download_file_path}</code> in {ms} seconds"
|
||||
)
|
||||
else:
|
||||
await pesan.edit(
|
||||
"Reply to a Telegram Media, to download it to my local server."
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["tiktokdl"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def tiktokdl(client, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply(
|
||||
f"Use command /{message.command[0]} [link] to download tiktok video."
|
||||
)
|
||||
link = message.command[1]
|
||||
msg = await message.reply("Trying download...")
|
||||
try:
|
||||
r = (await http.get(f"https://api.hayo.my.id/api/tiktok/4?url={link}")).json()
|
||||
await message.reply_video(
|
||||
r["linkori"],
|
||||
caption=f"<b>Title:</b> <code>{r['name']}</code>\n\nUploaded for {message.from_user.mention} [<code>{message.from_user.id}</code>]",
|
||||
)
|
||||
await msg.delete()
|
||||
except Exception as e:
|
||||
await message.reply(f"Failed to download tiktok video..\n\n<b>Reason:</b> {e}")
|
||||
await msg.delete()
|
||||
|
||||
|
||||
@app.on_message(filters.command(["fbdl"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def fbdl(client, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply(
|
||||
f"Use command /{message.command[0]} [link] to download Facebook video."
|
||||
)
|
||||
link = message.command[1]
|
||||
msg = await message.reply("Trying download...")
|
||||
try:
|
||||
resjson = (await http.get(f"https://yasirapi.eu.org/fbdl?link={link}")).json()
|
||||
try:
|
||||
url = resjson["result"]["links"]["hd"].replace("&", "&")
|
||||
except:
|
||||
url = resjson["result"]["links"]["sd"].replace("&", "&")
|
||||
obj = SmartDL(url, progress_bar=False)
|
||||
obj.start()
|
||||
path = obj.get_dest()
|
||||
await message.reply_video(
|
||||
path,
|
||||
caption=f"<code>{os.path.basename(path)}</code>\n\nUploaded for {message.from_user.mention} [<code>{message.from_user.id}</code>]",
|
||||
)
|
||||
await msg.delete()
|
||||
try:
|
||||
os.remove(path)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
await message.reply(
|
||||
f"Failed to download Facebook video..\n\n<b>Reason:</b> {e}"
|
||||
)
|
||||
await msg.delete()
|
||||
199
misskaty/plugins/filter_request.py
Normal file
199
misskaty/plugins/filter_request.py
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
import re
|
||||
import random
|
||||
from misskaty import app
|
||||
from pyrogram import enums, filters
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from pyrogram.errors import UserNotParticipant, PeerIdInvalid
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.helper.time_gap import check_time_gap
|
||||
|
||||
chat = [-1001128045651, -1001255283935, -1001455886928]
|
||||
REQUEST_DB = {}
|
||||
|
||||
|
||||
@app.on_message(filters.regex(r"alamu'?ala[iy]ku+m", re.I) & filters.chat(chat))
|
||||
async def start(_, message):
|
||||
await message.reply_text(text=f"Wa'alaikumsalam {message.from_user.mention} 😇")
|
||||
|
||||
|
||||
@app.on_message(filters.regex(r"#request|#req", re.I) & (filters.text | filters.photo) & filters.chat(-1001255283935) & ~filters.channel)
|
||||
@capture_err
|
||||
async def request_user(client, message):
|
||||
if message.sender_chat:
|
||||
return await message.reply(f"{message.from_user.mention} mohon gunakan akun asli saat request.")
|
||||
is_in_gap, sleep_time = await check_time_gap(message.from_user.id)
|
||||
if is_in_gap:
|
||||
return await message.reply("Sabar dikit napa.. 🙄")
|
||||
markup = InlineKeyboardMarkup(
|
||||
[
|
||||
[InlineKeyboardButton(text="💬 Lihat Pesan", url=f"https://t.me/c/1255283935/{message.id}")],
|
||||
[InlineKeyboardButton(text="🚫 Tolak", callback_data=f"rejectreq_{message.id}_{message.chat.id}"), InlineKeyboardButton(text="✅ Done", callback_data=f"donereq_{message.id}_{message.chat.id}")],
|
||||
[InlineKeyboardButton(text="⚠️ Tidak Tersedia", callback_data=f"unavailablereq_{message.id}_{message.chat.id}")],
|
||||
[InlineKeyboardButton(text="🔍 Sudah Ada", callback_data=f"dahada_{message.id}_{message.chat.id}")],
|
||||
]
|
||||
)
|
||||
try:
|
||||
user_id = message.from_user.id
|
||||
if user_id in REQUEST_DB:
|
||||
REQUEST_DB[user_id] += 1
|
||||
else:
|
||||
REQUEST_DB[user_id] = 1
|
||||
if REQUEST_DB[user_id] > 3:
|
||||
return await message.reply(f"Mohon maaf {message.from_user.mention}, maksimal request hanya 3x perhari. Kalo mau tambah 5k per request 😝😝.")
|
||||
if message.text:
|
||||
forward = await client.send_message(-1001575525902, f"Request by <a href='tg://user?id={message.from_user.id}'>{message.from_user.first_name}</a> (#id{message.from_user.id})\n\n{message.text}", reply_markup=markup)
|
||||
markup2 = InlineKeyboardMarkup([[InlineKeyboardButton(text="⏳ Cek Status Request", url=f"https://t.me/c/1575525902/{forward.id}")]])
|
||||
if message.photo:
|
||||
forward = await client.send_photo(
|
||||
-1001575525902, message.photo.file_id, caption=f"Request by <a href='tg://user?id={message.from_user.id}'>{message.from_user.first_name}</a> (#id{message.from_user.id})\n\n{message.caption}", reply_markup=markup
|
||||
)
|
||||
markup2 = InlineKeyboardMarkup([[InlineKeyboardButton(text="⏳ Cek Status Request", url=f"https://t.me/c/1575525902/{forward.id}")]])
|
||||
await message.reply_text(text=f"Hai {message.from_user.mention}, request kamu sudah dikirim yaa. Harap bersabar mungkin admin juga punya kesibukan lain.\n\n<b>Sisa Request:</b> {3 - REQUEST_DB[user_id]}x", quote=True, reply_markup=markup2)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
async def clear_reqdict():
|
||||
REQUEST_DB.clear()
|
||||
|
||||
|
||||
# @app.on_message(filters.regex(r"makasi|thank|terimakasih|terima kasih|mksh", re.I) & filters.chat(chat))
|
||||
async def start(_, message):
|
||||
pesan = [
|
||||
f"Sama-sama {message.from_user.first_name}",
|
||||
f"You're Welcome {message.from_user.first_name}",
|
||||
"Oke..",
|
||||
"Yoi..",
|
||||
"Terimakasih Kembali..",
|
||||
"Sami-Sami...",
|
||||
"Sama-sama, senang bisa membantu..",
|
||||
f"Yups, Sama-sama {message.from_user.first_name}",
|
||||
"Okayyy...",
|
||||
]
|
||||
await message.reply_text(text=random.choice(pesan))
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^donereq"))
|
||||
async def _callbackreq(c, q):
|
||||
try:
|
||||
user = await c.get_chat_member(-1001201566570, q.from_user.id)
|
||||
if user.status in [enums.ChatMemberStatus.ADMINISTRATOR, enums.ChatMemberStatus.OWNER]:
|
||||
i, msg_id, chat_id = q.data.split("_")
|
||||
await c.send_message(
|
||||
chat_id=chat_id,
|
||||
text="#Done\nDone ✅, Selamat menonton. Jika request tidak bisa dilihat digrup silahkan join channel melalui link private yang ada di @YMovieZ_New ...",
|
||||
reply_to_message_id=int(msg_id),
|
||||
)
|
||||
|
||||
if q.message.caption:
|
||||
await q.message.edit_text(f"<b>COMPLETED</b>\n\n<s>{q.message.caption}</s>", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="✅ Request Completed", callback_data="reqcompl")]]))
|
||||
else:
|
||||
await q.message.edit_text(f"<b>COMPLETED</b>\n\n<s>{q.message.text}</s>", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="✅ Request Completed", callback_data="reqcompl")]]))
|
||||
await q.answer("Request berhasil diselesaikan ✅")
|
||||
else:
|
||||
await q.answer("Apa motivasi kamu menekan tombol ini?", show_alert=True)
|
||||
except UserNotParticipant:
|
||||
return await q.answer("Apa motivasi kamu menekan tombol ini?", show_alert=True, cache_time=10)
|
||||
except PeerIdInvalid:
|
||||
return await q.answer("Silahkan kirim pesan digrup supaya bot bisa merespon.", show_alert=True, cache_time=10)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^dahada"))
|
||||
async def _callbackreqada(c, q):
|
||||
try:
|
||||
user = await c.get_chat_member(-1001201566570, q.from_user.id)
|
||||
if user.status in [enums.ChatMemberStatus.ADMINISTRATOR, enums.ChatMemberStatus.OWNER]:
|
||||
i, msg_id, chat_id = q.data.split("_")
|
||||
await c.send_message(
|
||||
chat_id=chat_id,
|
||||
text="#SudahAda\nFilm/series yang direquest sudah ada sebelumnya. Biasakan mencari terlebih dahulu..",
|
||||
reply_to_message_id=int(msg_id),
|
||||
)
|
||||
|
||||
if q.message.caption:
|
||||
await q.message.edit_text(f"<b>#AlreadyAvailable</b>\n\n<s>{q.message.caption}</s>", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="🔍 Request Sudah Ada", callback_data="reqavailable")]]))
|
||||
else:
|
||||
await q.message.edit_text(f"<b>Already Available</b>\n\n<s>{q.message.text}</s>", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="🔍 Request Sudah Ada", callback_data="reqavailable")]]))
|
||||
await q.answer("Done ✔️")
|
||||
else:
|
||||
await q.answer("Apa motivasi kamu menekan tombol ini?", show_alert=True)
|
||||
except UserNotParticipant:
|
||||
return await q.answer("Apa motivasi kamu menekan tombol ini?", show_alert=True, cache_time=10)
|
||||
except PeerIdInvalid:
|
||||
return await q.answer("Silahkan kirim pesan digrup supaya bot bisa merespon.", show_alert=True, cache_time=10)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^rejectreq"))
|
||||
async def _callbackreject(c, q):
|
||||
try:
|
||||
user = await c.get_chat_member(-1001201566570, q.from_user.id)
|
||||
if user.status in [enums.ChatMemberStatus.ADMINISTRATOR, enums.ChatMemberStatus.OWNER]:
|
||||
i, msg_id, chat_id = q.data.split("_")
|
||||
await c.send_message(
|
||||
chat_id=chat_id,
|
||||
text="Mohon maaf, request kamu ditolak karena tidak sesuai rules. Harap baca rules grup no.6 yaa 🙃.",
|
||||
reply_to_message_id=int(msg_id),
|
||||
)
|
||||
|
||||
if q.message.caption:
|
||||
await q.message.edit_text(f"<b>REJECTED</b>\n\n<s>{q.message.caption}</s>", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="🚫 Request Rejected", callback_data="reqreject")]]))
|
||||
else:
|
||||
await q.message.edit_text(f"<b>REJECTED</b>\n\n<s>{q.message.text}</s>", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="🚫 Request Rejected", callback_data="reqreject")]]))
|
||||
await q.answer("Request berhasil ditolak 🚫")
|
||||
else:
|
||||
await q.answer("Apa motivasi kamu menekan tombol ini?", show_alert=True)
|
||||
except UserNotParticipant:
|
||||
await q.answer("Apa motivasi kamu menekan tombol ini?", show_alert=True, cache_time=10)
|
||||
except PeerIdInvalid:
|
||||
return await q.answer("Silahkan kirim pesan digrup supaya bot bisa merespon.", show_alert=True, cache_time=10)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^unavailablereq"))
|
||||
async def _callbackunav(c, q):
|
||||
try:
|
||||
user = await c.get_chat_member(-1001201566570, q.from_user.id)
|
||||
if user.status in [enums.ChatMemberStatus.ADMINISTRATOR, enums.ChatMemberStatus.OWNER]:
|
||||
i, msg_id, chat_id = q.data.split("_")
|
||||
await c.send_message(
|
||||
chat_id=chat_id,
|
||||
text="Mohon maaf, request kamu tidak tersedia. Silahkan baca beberapa alasannya di channel @YMovieZ_New",
|
||||
reply_to_message_id=int(msg_id),
|
||||
)
|
||||
|
||||
if q.message.caption:
|
||||
await q.message.edit_text(f"<b>UNAVAILABLE</b>\n\n<s>{q.message.caption}</s>", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="⚠️ Request Unavailable", callback_data="requnav")]]))
|
||||
else:
|
||||
await q.message.edit_text(f"<b>UNAVAILABLE</b>\n\n<s>{q.message.text}</s>", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="⚠️ Request Unavailable", callback_data="requnav")]]))
|
||||
await q.answer("Request tidak tersedia, mungkin belum rilis atau memang tidak tersedia versi digital.")
|
||||
else:
|
||||
await q.answer("Apa motivasi kamu menekan tombol ini?", show_alert=True, cache_time=1000)
|
||||
except UserNotParticipant:
|
||||
await q.answer("Apa motivasi kamu menekan tombol ini?", show_alert=True, cache_time=10)
|
||||
except PeerIdInvalid:
|
||||
return await q.answer("Silahkan kirim pesan digrup supaya bot bisa merespon.", show_alert=True, cache_time=10)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^reqcompl$"))
|
||||
async def _callbackaft_done(c, q):
|
||||
await q.answer("Request ini sudah terselesaikan 🥳, silahkan cek di channel atau grup yaa..", show_alert=True, cache_time=1000)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^reqreject$"))
|
||||
async def _callbackaft_rej(c, q):
|
||||
await q.answer("Request ini ditolak 💔, silahkan cek rules grup yaa.", show_alert=True, cache_time=1000)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^requnav$"))
|
||||
async def _callbackaft_unav(c, q):
|
||||
await q.answer("Request ini tidak tersedia ☹️, mungkin filmnya belum rilis atau memang tidak tersedia versi digital.", show_alert=True, cache_time=1000)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^reqavailable$"))
|
||||
async def _callbackaft_dahada(c, q):
|
||||
await q.answer("Request ini sudah ada, silahkan cari 🔍 di channelnya yaa 😉..", show_alert=True)
|
||||
|
||||
|
||||
scheduler = AsyncIOScheduler(timezone="Asia/Jakarta")
|
||||
scheduler.add_job(clear_reqdict, trigger="cron", hour=7, minute=0)
|
||||
scheduler.start()
|
||||
142
misskaty/plugins/genss.py
Normal file
142
misskaty/plugins/genss.py
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
# the logging things
|
||||
import logging
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
import os, time, traceback
|
||||
from asyncio import sleep, gather
|
||||
from shutil import rmtree
|
||||
from pyrogram import filters, enums
|
||||
from pyrogram.errors import FloodWait
|
||||
from misskaty import app
|
||||
from misskaty.helper.ffmpeg_helper import take_ss, genss_link
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from misskaty.helper.pyro_progress import progress_for_pyrogram
|
||||
|
||||
__MODULE__ = "MediaTool"
|
||||
__HELP__ = """"
|
||||
/genss [reply to video] - Generate Screenshot From Video.
|
||||
/genss_link [link] - Generate Screenshot Video From URL. (Unstable)
|
||||
/mediainfo [link/reply to TG Video] - Get Mediainfo From File.
|
||||
"""
|
||||
|
||||
|
||||
@app.on_message(filters.command(["genss"], COMMAND_HANDLER))
|
||||
async def genss(client, message):
|
||||
if message.reply_to_message is not None:
|
||||
process = await message.reply_text("`Processing, please wait..`")
|
||||
c_time = time.time()
|
||||
the_real_download_location = await client.download_media(
|
||||
message=message.reply_to_message,
|
||||
progress=progress_for_pyrogram,
|
||||
progress_args=("Trying to download, please wait..", process, c_time),
|
||||
)
|
||||
if the_real_download_location is not None:
|
||||
try:
|
||||
await client.edit_message_text(
|
||||
text=f"File video berhasil didownload dengan path <code>{the_real_download_location}</code>.",
|
||||
chat_id=message.chat.id,
|
||||
message_id=process.id,
|
||||
)
|
||||
await sleep(2)
|
||||
images = await take_ss(the_real_download_location)
|
||||
await client.edit_message_text(
|
||||
text="Mencoba mengupload, hasil generate screenshot..",
|
||||
chat_id=message.chat.id,
|
||||
message_id=process.id,
|
||||
)
|
||||
await client.send_chat_action(
|
||||
chat_id=message.chat.id, action=enums.ChatAction.UPLOAD_PHOTO
|
||||
)
|
||||
|
||||
try:
|
||||
await gather(
|
||||
*[
|
||||
message.reply_document(
|
||||
images, reply_to_message_id=message.id
|
||||
),
|
||||
message.reply_photo(images, reply_to_message_id=message.id),
|
||||
]
|
||||
)
|
||||
except FloodWait as e:
|
||||
await sleep(e.value)
|
||||
await gather(
|
||||
*[
|
||||
message.reply_document(
|
||||
images, reply_to_message_id=message.id
|
||||
),
|
||||
message.reply_photo(images, reply_to_message_id=message.id),
|
||||
]
|
||||
)
|
||||
await message.reply(
|
||||
f"☑️ Uploaded [1] screenshoot.\n\n{message.from_user.first_name} (<code>{message.from_user.id}</code>)\n#️⃣ #ssgen #id{message.from_user.id}\n\nSS Generate by @MissKatyRoBot",
|
||||
reply_to_message_id=message.id,
|
||||
)
|
||||
await process.delete()
|
||||
try:
|
||||
os.remove(images)
|
||||
os.remove(the_real_download_location)
|
||||
except:
|
||||
pass
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await message.reply(f"Gagal generate screenshot.\n\n{exc}")
|
||||
try:
|
||||
os.remove(images)
|
||||
os.remove(the_real_download_location)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
await message.reply("Reply to a Telegram media to get screenshots..")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["genss_link"], COMMAND_HANDLER))
|
||||
async def genss_link(client, message):
|
||||
try:
|
||||
link = message.text.split(" ")[1]
|
||||
if link.startswith("https://file.yasirweb.my.id"):
|
||||
link = link.replace(
|
||||
"https://file.yasirweb.my.id", "https://file.yasiraris.workers.dev"
|
||||
)
|
||||
if link.startswith("https://link.yasirweb.my.id"):
|
||||
link = link.replace(
|
||||
"https://link.yasirweb.my.id", "https://yasirrobot.herokuapp.com"
|
||||
)
|
||||
process = await message.reply_text("`Processing, please wait..`")
|
||||
tmp_directory_for_each_user = f"./MissKaty_Genss/{str(message.from_user.id)}"
|
||||
if not os.path.isdir(tmp_directory_for_each_user):
|
||||
os.makedirs(tmp_directory_for_each_user)
|
||||
images = await genss_link(process, link, tmp_directory_for_each_user, 5, 8)
|
||||
await sleep(2)
|
||||
await client.edit_message_text(
|
||||
text="Mencoba mengupload, hasil generate screenshot..",
|
||||
chat_id=message.chat.id,
|
||||
message_id=process.id,
|
||||
)
|
||||
await client.send_chat_action(
|
||||
chat_id=message.chat.id, action=enums.ChatAction.UPLOAD_PHOTO
|
||||
)
|
||||
try:
|
||||
await message.reply_media_group(images, reply_to_message_id=message.id)
|
||||
except FloodWait as e:
|
||||
await sleep(e.value)
|
||||
await message.reply_media_group(images, reply_to_message_id=message.id)
|
||||
await message.reply(
|
||||
f"☑️ Uploaded [8] screenshoot.\n\nGenerated by @MissKatyRoBot.",
|
||||
reply_to_message_id=message.id,
|
||||
)
|
||||
await process.delete()
|
||||
try:
|
||||
rmtree(tmp_directory_for_each_user)
|
||||
except:
|
||||
pass
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await message.reply(f"Gagal generate screenshot.\n\n{exc}")
|
||||
try:
|
||||
rmtree(tmp_directory_for_each_user)
|
||||
except:
|
||||
pass
|
||||
347
misskaty/plugins/grup_tools.py
Normal file
347
misskaty/plugins/grup_tools.py
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
from datetime import datetime, timedelta
|
||||
import time
|
||||
import os
|
||||
import logging
|
||||
from misskaty.helper.http import http
|
||||
from pyrogram import enums, filters
|
||||
from pyrogram.types import ChatMemberUpdated, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from pyrogram.errors import ChatSendMediaForbidden, MessageTooLong, RPCError, SlowmodeWait
|
||||
from misskaty import app
|
||||
from misskaty.core.decorator.errors import capture_err, asyncify
|
||||
from PIL import Image, ImageChops, ImageDraw, ImageFont
|
||||
import textwrap
|
||||
from database.users_chats_db import db
|
||||
from utils import temp
|
||||
from pyrogram.errors import ChatAdminRequired
|
||||
from misskaty.vars import SUDO, LOG_CHANNEL, SUPPORT_CHAT, COMMAND_HANDLER
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def circle(pfp, size=(215, 215)):
|
||||
pfp = pfp.resize(size, Image.ANTIALIAS).convert("RGBA")
|
||||
bigsize = (pfp.size[0] * 3, pfp.size[1] * 3)
|
||||
mask = Image.new("L", bigsize, 0)
|
||||
draw = ImageDraw.Draw(mask)
|
||||
draw.ellipse((0, 0) + bigsize, fill=255)
|
||||
mask = mask.resize(pfp.size, Image.ANTIALIAS)
|
||||
mask = ImageChops.darker(mask, pfp.split()[-1])
|
||||
pfp.putalpha(mask)
|
||||
return pfp
|
||||
|
||||
|
||||
def draw_multiple_line_text(image, text, font, text_start_height):
|
||||
"""
|
||||
From unutbu on [python PIL draw multiline text on image](https://stackoverflow.com/a/7698300/395857)
|
||||
"""
|
||||
draw = ImageDraw.Draw(image)
|
||||
image_width, image_height = image.size
|
||||
y_text = text_start_height
|
||||
lines = textwrap.wrap(text, width=50)
|
||||
for line in lines:
|
||||
line_width, line_height = font.getsize(line)
|
||||
draw.text(((image_width - line_width) / 2, y_text), line, font=font, fill="black")
|
||||
y_text += line_height
|
||||
|
||||
|
||||
@asyncify
|
||||
def welcomepic(pic, user, chat, count, id):
|
||||
background = Image.open("img/bg.png") # <- Background Image (Should be PNG)
|
||||
background = background.resize((1024, 500), Image.ANTIALIAS)
|
||||
pfp = Image.open(pic).convert("RGBA")
|
||||
pfp = circle(pfp)
|
||||
pfp = pfp.resize((265, 265)) # Resizes the Profilepicture so it fits perfectly in the circle
|
||||
font = ImageFont.truetype("Calistoga-Regular.ttf", 37) # <- Text Font of the Member Count. Change the text size for your preference
|
||||
member_text = f"User#{count}, Selamat Datang {user}" # <- Text under the Profilepicture with the Membercount
|
||||
draw_multiple_line_text(background, member_text, font, 395)
|
||||
draw_multiple_line_text(background, chat, font, 47)
|
||||
ImageDraw.Draw(background).text((530, 460), "Generated by @MissKatyRoBot", font=ImageFont.truetype("Calistoga-Regular.ttf", 28), size=20, align="right")
|
||||
background.paste(pfp, (379, 123), pfp) # Pastes the Profilepicture on the Background Image
|
||||
background.save(f"downloads/welcome#{id}.png") # Saves the finished Image in the folder with the filename
|
||||
return f"downloads/welcome#{id}.png"
|
||||
|
||||
|
||||
@app.on_chat_member_updated(filters.group & filters.chat(-1001128045651))
|
||||
async def member_has_joined(c: app, member: ChatMemberUpdated):
|
||||
if not member.new_chat_member or member.new_chat_member.status in {"banned", "left", "restricted"} or member.old_chat_member:
|
||||
return
|
||||
user = member.new_chat_member.user if member.new_chat_member else member.from_user
|
||||
if user.id in SUDO:
|
||||
await c.send_message(
|
||||
member.chat.id,
|
||||
"Waw, owner ku yang keren baru saja bergabung ke grup!",
|
||||
)
|
||||
return
|
||||
elif user.is_bot:
|
||||
return # ignore bots
|
||||
else:
|
||||
if (temp.MELCOW).get(f"welcome-{member.chat.id}") is not None:
|
||||
try:
|
||||
await (temp.MELCOW[f"welcome-{member.chat.id}"]).delete()
|
||||
except:
|
||||
pass
|
||||
mention = f"<a href='tg://user?id={user.id}'>{user.first_name}</a>"
|
||||
joined_date = datetime.fromtimestamp(time.time()).strftime("%Y.%m.%d %H:%M:%S")
|
||||
first_name = f"{user.first_name} {user.last_name}" if user.last_name else user.first_name
|
||||
id = user.id
|
||||
dc = user.dc_id or "Member tanpa PP"
|
||||
count = await app.get_chat_members_count(member.chat.id)
|
||||
try:
|
||||
pic = await app.download_media(user.photo.big_file_id, file_name=f"pp{user.id}.png")
|
||||
except AttributeError:
|
||||
pic = "img/profilepic.png"
|
||||
welcomeimg = await welcomepic(pic, user.first_name, member.chat.title, count, user.id)
|
||||
temp.MELCOW[f"welcome-{member.chat.id}"] = await c.send_photo(
|
||||
member.chat.id,
|
||||
photo=welcomeimg,
|
||||
caption=f"Hai {mention}, Selamat datang digrup {member.chat.title} harap baca rules di pinned message terlebih dahulu.\n\n<b>Nama :<b> <code>{first_name}</code>\n<b>ID :<b> <code>{id}</code>\n<b>DC ID :<b> <code>{dc}</code>\n<b>Tanggal Join :<b> <code>{joined_date}</code>",
|
||||
)
|
||||
userspammer = ""
|
||||
# Spamwatch Detection
|
||||
try:
|
||||
headers = {"Authorization": "Bearer XvfzE4AUNXkzCy0DnIVpFDlxZi79lt6EnwKgBj8Quuzms0OSdHvf1k6zSeyzZ_lz"}
|
||||
apispamwatch = (await http.get(f"https://api.spamwat.ch/banlist/{user.id}", headers=headers)).json()
|
||||
if not apispamwatch.get("error"):
|
||||
await app.ban_chat_member(member.chat.id, user.id, datetime.now() + timedelta(seconds=30))
|
||||
userspammer += f"<b>#SpamWatch Federation Ban</b>\nUser {mention} [<code>{user.id}</code>] has been kicked because <code>{apispamwatch.get('reason')}</code>.\n"
|
||||
except Exception as err:
|
||||
LOGGER.error(f"ERROR in Spamwatch Detection. {err}")
|
||||
# Combot API Detection
|
||||
try:
|
||||
apicombot = (await http.get(f"https://api.cas.chat/check?user_id={user.id}")).json()
|
||||
if apicombot.get("ok") == "true":
|
||||
await app.ban_chat_member(member.chat.id, user.id, datetime.now() + timedelta(seconds=30))
|
||||
userspammer += f"<b>#CAS Federation Ban</b>\nUser {mention} [<code>{user.id}</code>] detected as spambot and has been kicked. Powered by <a href='https://api.cas.chat/check?user_id={user.id}'>Combot AntiSpam.</a>"
|
||||
except Exception as err:
|
||||
LOGGER.error(f"ERROR in Combot API Detection. {err}")
|
||||
if userspammer != "":
|
||||
await c.send_message(member.chat.id, userspammer)
|
||||
try:
|
||||
os.remove(f"downloads/welcome#{user.id}.png")
|
||||
os.remove(f"downloads/pp{user.id}.png")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@app.on_message(filters.new_chat_members & filters.group)
|
||||
async def save_group(bot, message):
|
||||
r_j_check = [u.id for u in message.new_chat_members]
|
||||
if temp.ME in r_j_check:
|
||||
if not await db.get_chat(message.chat.id):
|
||||
total = await bot.get_chat_members_count(message.chat.id)
|
||||
r_j = message.from_user.mention if message.from_user else "Anonymous"
|
||||
await bot.send_message(
|
||||
LOG_CHANNEL,
|
||||
f"#NewGroup\nGroup = {message.chat.title}(<code>{message.chat.id}</code>)\nMembers Count = <code>{total}</code>\nAdded by - {r_j}",
|
||||
)
|
||||
|
||||
await db.add_chat(message.chat.id, message.chat.title)
|
||||
if message.chat.id in temp.BANNED_CHATS:
|
||||
# Inspired from a boat of a banana tree
|
||||
buttons = [[InlineKeyboardButton("Support", url=f"https://t.me/{SUPPORT_CHAT}")]]
|
||||
reply_markup = InlineKeyboardMarkup(buttons)
|
||||
k = await message.reply(
|
||||
text="<b>CHAT NOT ALLOWED 🐞\n\nMy admins has restricted me from working here ! If you want to know more about it contact support..</b>",
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
|
||||
try:
|
||||
await k.pin()
|
||||
except:
|
||||
pass
|
||||
await bot.leave_chat(message.chat.id)
|
||||
return
|
||||
buttons = [[InlineKeyboardButton("ℹ️ Help", url=f"https://t.me/{temp.U_NAME}?start=help"), InlineKeyboardButton("📢 Updates", url="https://t.me/YasirPediaChannel")]]
|
||||
reply_markup = InlineKeyboardMarkup(buttons)
|
||||
await message.reply_text(text=f"<b>Terimakasih sudah menambahkan saya di {message.chat.title} ❣️\n\nJika ada kendala atau saran bisa kontak ke saya.</b>", reply_markup=reply_markup)
|
||||
else:
|
||||
for u in message.new_chat_members:
|
||||
count = await app.get_chat_members_count(message.chat.id)
|
||||
try:
|
||||
pic = await app.download_media(u.photo.big_file_id, file_name=f"pp{u.id}.png")
|
||||
except AttributeError:
|
||||
pic = "img/profilepic.png"
|
||||
welcomeimg = await welcomepic(pic, u.first_name, message.chat.title, count, u.id)
|
||||
if (temp.MELCOW).get(f"welcome-{message.chat.id}") is not None:
|
||||
try:
|
||||
await (temp.MELCOW[f"welcome-{message.chat.id}"]).delete()
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
temp.MELCOW[f"welcome-{message.chat.id}"] = await app.send_photo(
|
||||
message.chat.id,
|
||||
photo=welcomeimg,
|
||||
caption=f"Hai {u.mention}, Selamat datang digrup {message.chat.title}.",
|
||||
)
|
||||
except (ChatSendMediaForbidden, SlowmodeWait):
|
||||
await app.leave_chat(message.chat.id)
|
||||
try:
|
||||
os.remove(f"downloads/welcome#{u.id}.png")
|
||||
os.remove(f"downloads/pp{u.id}.png")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@app.on_message(filters.command("leave") & filters.user(SUDO))
|
||||
async def leave_a_chat(bot, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Give me a chat id")
|
||||
chat = message.command[1]
|
||||
try:
|
||||
chat = int(chat)
|
||||
except:
|
||||
chat = chat
|
||||
try:
|
||||
buttons = [[InlineKeyboardButton("Support", url=f"https://t.me/{SUPPORT_CHAT}")]]
|
||||
reply_markup = InlineKeyboardMarkup(buttons)
|
||||
await bot.send_message(
|
||||
chat_id=chat,
|
||||
text="<b>Hai kawan, \nOwner aku bilang saya harus pergi! Jika kamu ingin menambahkan bot ini lagi silahkan kontak owner bot ini.</b>",
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
await bot.leave_chat(chat)
|
||||
except Exception as e:
|
||||
await message.reply(f"Error - {e}")
|
||||
await bot.leave_chat(chat)
|
||||
|
||||
|
||||
@app.on_message(filters.command("disable") & filters.user(SUDO))
|
||||
async def disable_chat(bot, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Give me a chat id")
|
||||
r = message.text.split(None)
|
||||
if len(r) > 2:
|
||||
reason = message.text.split(None, 2)[2]
|
||||
chat = message.text.split(None, 2)[1]
|
||||
else:
|
||||
chat = message.command[1]
|
||||
reason = "No reason Provided"
|
||||
try:
|
||||
chat_ = int(chat)
|
||||
except:
|
||||
return await message.reply("Give Me A Valid Chat ID")
|
||||
cha_t = await db.get_chat(chat_)
|
||||
if not cha_t:
|
||||
return await message.reply("Chat Not Found In DB")
|
||||
if cha_t["is_disabled"]:
|
||||
return await message.reply(f"This chat is already disabled:\nReason-<code> {cha_t['reason']} </code>")
|
||||
await db.disable_chat(chat_, reason)
|
||||
temp.BANNED_CHATS.append(chat_)
|
||||
await message.reply("Chat Succesfully Disabled")
|
||||
try:
|
||||
buttons = [[InlineKeyboardButton("Support", url=f"https://t.me/{SUPPORT_CHAT}")]]
|
||||
reply_markup = InlineKeyboardMarkup(buttons)
|
||||
await bot.send_message(chat_id=chat_, text=f"<b>Hello Friends, \nMy admin has told me to leave from group so i go! If you wanna add me again contact my support group.</b> \nReason : <code>{reason}</code>", reply_markup=reply_markup)
|
||||
await bot.leave_chat(chat_)
|
||||
except Exception as e:
|
||||
await message.reply(f"Error - {e}")
|
||||
|
||||
|
||||
@app.on_message(filters.command("enable") & filters.user(SUDO))
|
||||
async def re_enable_chat(bot, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Give me a chat id")
|
||||
chat = message.command[1]
|
||||
try:
|
||||
chat_ = int(chat)
|
||||
except:
|
||||
return await message.reply("Give Me A Valid Chat ID")
|
||||
sts = await db.get_chat(int(chat))
|
||||
if not sts:
|
||||
return await message.reply("Chat Not Found In DB !")
|
||||
if not sts.get("is_disabled"):
|
||||
return await message.reply("This chat is not yet disabled.")
|
||||
await db.re_enable_chat(chat_)
|
||||
temp.BANNED_CHATS.remove(chat_)
|
||||
await message.reply("Chat Succesfully re-enabled")
|
||||
|
||||
|
||||
# a function for trespassing into others groups, Inspired by a Vazha
|
||||
# Not to be used , But Just to showcase his vazhatharam.
|
||||
# @app.on_message(filters.command('invite') & filters.user(SUDO))
|
||||
async def gen_invite(bot, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Give me a chat id")
|
||||
chat = message.command[1]
|
||||
try:
|
||||
chat = int(chat)
|
||||
except:
|
||||
return await message.reply("Give Me A Valid Chat ID")
|
||||
try:
|
||||
link = await bot.create_chat_invite_link(chat)
|
||||
except ChatAdminRequired:
|
||||
return await message.reply("Invite Link Generation Failed, Iam Not Having Sufficient Rights")
|
||||
except Exception as e:
|
||||
return await message.reply(f"Error {e}")
|
||||
await message.reply(f"Here is your Invite Link {link.invite_link}")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["adminlist", "adminlist@MissKatyRoBot"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def adminlist(_, message):
|
||||
if message.chat.type == enums.ChatType.PRIVATE:
|
||||
return await message.reply("Perintah ini hanya untuk grup")
|
||||
try:
|
||||
administrators = []
|
||||
async for m in app.get_chat_members(message.chat.id, filter=enums.ChatMembersFilter.ADMINISTRATORS):
|
||||
administrators.append(f"{m.user.first_name}")
|
||||
|
||||
res = "".join(f"~ {i}\n" for i in administrators)
|
||||
return await message.reply(f"Daftar Admin di <b>{message.chat.title}</b> ({message.chat.id}):\n~ {res}")
|
||||
except Exception as e:
|
||||
await message.reply(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["kickme"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def kickme(_, message):
|
||||
reason = None
|
||||
if len(message.text.split()) >= 2:
|
||||
reason = message.text.split(None, 1)[1]
|
||||
try:
|
||||
await message.ban_member(message.from_user.id)
|
||||
txt = f"Pengguna {message.from_user.mention} menendang dirinya sendiri. Mungkin dia sedang frustasi 😕"
|
||||
txt += f"\n<b>Alasan</b>: {reason}" if reason else ""
|
||||
await message.reply_text(txt)
|
||||
await message.unban_member(message.from_user.id)
|
||||
except RPCError as ef:
|
||||
await message.reply_text(f"Sepertinya ada error, silahkan report ke owner saya. \nERROR: {str(ef)}")
|
||||
return
|
||||
|
||||
|
||||
@app.on_message(filters.command("users") & filters.user(SUDO))
|
||||
async def list_users(bot, message):
|
||||
# https://t.me/GetTGLink/4184
|
||||
raju = await message.reply("Getting List Of Users")
|
||||
users = await db.get_all_users()
|
||||
out = "Users Saved In DB Are:\n\n"
|
||||
async for user in users:
|
||||
out += f"<a href=tg://user?id={user['id']}>{user['name']}</a>"
|
||||
if user["ban_status"]["is_banned"]:
|
||||
out += "( Banned User )"
|
||||
out += "\n"
|
||||
try:
|
||||
await raju.edit_text(out)
|
||||
except MessageTooLong:
|
||||
with open("users.txt", "w+") as outfile:
|
||||
outfile.write(out)
|
||||
await message.reply_document("users.txt", caption="List Of Users")
|
||||
|
||||
|
||||
@app.on_message(filters.command("chats") & filters.user(SUDO))
|
||||
async def list_chats(bot, message):
|
||||
raju = await message.reply("Getting List Of chats")
|
||||
chats = await db.get_all_chats()
|
||||
out = "Chats Saved In DB Are:\n\n"
|
||||
async for chat in chats:
|
||||
out += f"**Title:** `{chat['title']}`\n**- ID:** `{chat['id']}`"
|
||||
if chat["chat_status"]["is_disabled"]:
|
||||
out += "( Disabled Chat )"
|
||||
out += "\n"
|
||||
try:
|
||||
await raju.edit_text(out)
|
||||
except MessageTooLong:
|
||||
with open("chats.txt", "w+") as outfile:
|
||||
outfile.write(out)
|
||||
await message.reply_document("chats.txt", caption="List Of Chats")
|
||||
233
misskaty/plugins/inkick_user.py
Normal file
233
misskaty/plugins/inkick_user.py
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
import time
|
||||
from asyncio import sleep
|
||||
from misskaty import app
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from pyrogram import enums, filters
|
||||
from pyrogram.errors import FloodWait
|
||||
from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
|
||||
from pyrogram.errors.exceptions.bad_request_400 import (
|
||||
ChatAdminRequired,
|
||||
UserAdminInvalid,
|
||||
)
|
||||
|
||||
__MODULE__ = "Inkick"
|
||||
__HELP__ = """"
|
||||
/instatus - View member status in group.
|
||||
/dkick - Remove deleted account from group.
|
||||
"""
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.incoming & ~filters.private & filters.command(["inkick"], COMMAND_HANDLER)
|
||||
)
|
||||
async def inkick(_, message):
|
||||
user = await app.get_chat_member(message.chat.id, message.from_user.id)
|
||||
if user.status.value in ("administrator", "owner"):
|
||||
if len(message.command) > 1:
|
||||
input_str = message.command
|
||||
sent_message = await message.reply_text(
|
||||
"🚮**Sedang membersihkan user, mungkin butuh waktu beberapa saat...**"
|
||||
)
|
||||
count = 0
|
||||
async for member in app.get_chat_members(message.chat.id):
|
||||
if member.user.is_bot:
|
||||
continue
|
||||
if (
|
||||
member.user.status.value in input_str
|
||||
and member.status.value not in ("administrator", "owner")
|
||||
):
|
||||
try:
|
||||
await message.chat.ban_member(member.user.id)
|
||||
count += 1
|
||||
await sleep(1)
|
||||
await message.chat.unban_member(member.user.id)
|
||||
except (ChatAdminRequired, UserAdminInvalid):
|
||||
await sent_message.edit(
|
||||
"❗**Oh tidaakk, saya bukan admin disini**\n__Saya pergi dari sini, tambahkan aku kembali dengan perijinan banned pengguna.__"
|
||||
)
|
||||
await app.leave_chat(message.chat.id)
|
||||
break
|
||||
except FloodWait as e:
|
||||
await sleep(e.value)
|
||||
try:
|
||||
await sent_message.edit(
|
||||
f"✔️ **Berhasil menendang {count} pengguna berdasarkan argumen.**"
|
||||
)
|
||||
|
||||
except ChatWriteForbidden:
|
||||
await app.leave_chat(message.chat.id)
|
||||
else:
|
||||
await message.reply_text(
|
||||
"❗ **Arguments Required**\n__See /help in personal message for more information.__"
|
||||
)
|
||||
else:
|
||||
sent_message = await message.reply_text(
|
||||
"❗ **You have to be the group creator to do that.**"
|
||||
)
|
||||
await sleep(5)
|
||||
await sent_message.delete()
|
||||
|
||||
|
||||
# Kick User Without Username
|
||||
@app.on_message(
|
||||
filters.incoming & ~filters.private & filters.command(["uname"], COMMAND_HANDLER)
|
||||
)
|
||||
async def uname(_, message):
|
||||
user = await app.get_chat_member(message.chat.id, message.from_user.id)
|
||||
if user.status.value in ("administrator", "owner"):
|
||||
sent_message = await message.reply_text(
|
||||
"🚮**Sedang membersihkan user, mungkin butuh waktu beberapa saat...**"
|
||||
)
|
||||
count = 0
|
||||
async for member in app.get_chat_members(message.chat.id):
|
||||
if not member.user.username and member.status.value not in (
|
||||
"administrator",
|
||||
"owner",
|
||||
):
|
||||
try:
|
||||
await message.chat.ban_member(member.user.id)
|
||||
count += 1
|
||||
await sleep(1)
|
||||
await message.chat.unban_member(member.user.id)
|
||||
except (ChatAdminRequired, UserAdminInvalid):
|
||||
await sent_message.edit(
|
||||
"❗**Oh tidaakk, saya bukan admin disini**\n__Saya pergi dari sini, tambahkan aku kembali dengan perijinan banned pengguna.__"
|
||||
)
|
||||
await app.leave_chat(message.chat.id)
|
||||
break
|
||||
except FloodWait as e:
|
||||
await sleep(e.value)
|
||||
try:
|
||||
await sent_message.edit(
|
||||
f"✔️ **Berhasil menendang {count} pengguna berdasarkan argumen.**"
|
||||
)
|
||||
|
||||
except ChatWriteForbidden:
|
||||
await app.leave_chat(message.chat.id)
|
||||
else:
|
||||
sent_message = await message.reply_text(
|
||||
"❗ **You have to be the group creator to do that.**"
|
||||
)
|
||||
await sleep(5)
|
||||
await sent_message.delete()
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.incoming & ~filters.private & filters.command(["dkick"], COMMAND_HANDLER)
|
||||
)
|
||||
async def dkick(client, message):
|
||||
user = await app.get_chat_member(message.chat.id, message.from_user.id)
|
||||
if user.status.value in ("administrator", "owner"):
|
||||
sent_message = await message.reply_text(
|
||||
"🚮**Sedang membersihkan user, mungkin butuh waktu beberapa saat...**"
|
||||
)
|
||||
count = 0
|
||||
async for member in app.get_chat_members(message.chat.id):
|
||||
if member.user.is_deleted and member.status.value not in (
|
||||
"administrator",
|
||||
"owner",
|
||||
):
|
||||
try:
|
||||
await message.chat.ban_member(member.user.id)
|
||||
count += 1
|
||||
await sleep(1)
|
||||
await message.chat.unban_member(member.user.id)
|
||||
except (ChatAdminRequired, UserAdminInvalid):
|
||||
await sent_message.edit(
|
||||
"❗**Oh tidaakk, saya bukan admin disini**\n__Saya pergi dari sini, tambahkan aku kembali dengan perijinan banned pengguna.__"
|
||||
)
|
||||
await app.leave_chat(message.chat.id)
|
||||
break
|
||||
except FloodWait as e:
|
||||
await sleep(e.value)
|
||||
try:
|
||||
await sent_message.edit(f"✔️ **Berhasil menendang {count} akun terhapus.**")
|
||||
except ChatWriteForbidden:
|
||||
await app.leave_chat(message.chat.id)
|
||||
else:
|
||||
sent_message = await message.reply_text(
|
||||
"❗ **Kamu harus jadi admin atau owner grup untuk melakukan tindakan ini.**"
|
||||
)
|
||||
await sleep(5)
|
||||
await sent_message.delete()
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.incoming & ~filters.private & filters.command(["instatus"], COMMAND_HANDLER)
|
||||
)
|
||||
async def instatus(client, message):
|
||||
start_time = time.perf_counter()
|
||||
user = await app.get_chat_member(message.chat.id, message.from_user.id)
|
||||
count = await app.get_chat_members_count(message.chat.id)
|
||||
if user.status in (
|
||||
enums.ChatMemberStatus.ADMINISTRATOR,
|
||||
enums.ChatMemberStatus.OWNER,
|
||||
):
|
||||
sent_message = await message.reply_text(
|
||||
"**Sedang mengumpulkan informasi pengguna...**"
|
||||
)
|
||||
recently = 0
|
||||
within_week = 0
|
||||
within_month = 0
|
||||
long_time_ago = 0
|
||||
deleted_acc = 0
|
||||
premium_acc = 0
|
||||
no_username = 0
|
||||
restricted = 0
|
||||
banned = 0
|
||||
uncached = 0
|
||||
bot = 0
|
||||
async for ban in app.get_chat_members(
|
||||
message.chat.id, filter=enums.ChatMembersFilter.BANNED
|
||||
):
|
||||
banned += 1
|
||||
async for restr in app.get_chat_members(
|
||||
message.chat.id, filter=enums.ChatMembersFilter.RESTRICTED
|
||||
):
|
||||
restricted += 1
|
||||
async for member in app.get_chat_members(message.chat.id):
|
||||
user = member.user
|
||||
if user.is_deleted:
|
||||
deleted_acc += 1
|
||||
elif user.is_bot:
|
||||
bot += 1
|
||||
elif user.is_premium:
|
||||
premium_acc += 1
|
||||
elif not user.username:
|
||||
no_username += 1
|
||||
elif user.status.value == "recently":
|
||||
recently += 1
|
||||
elif user.status.value == "last_week":
|
||||
within_week += 1
|
||||
elif user.status.value == "last_month":
|
||||
within_month += 1
|
||||
elif user.status.value == "long_ago":
|
||||
long_time_ago += 1
|
||||
else:
|
||||
uncached += 1
|
||||
end_time = time.perf_counter()
|
||||
timelog = "{:.2f}".format(end_time - start_time)
|
||||
await sent_message.edit(
|
||||
"<b>💠 {}\n👥 {} Anggota\n——————\n👁🗨 Informasi Status Anggota\n——————\n</b>🕒 <code>recently</code>: {}\n🕒 <code>last_week</code>: {}\n🕒 <code>last_month</code>: {}\n🕒 <code>long_ago</code>: {}\n🉑 Tanpa Username: {}\n🤐 Dibatasi: {}\n🚫 Diblokir: {}\n👻 Deleted Account (<code>/dkick</code>): {}\n🤖 Bot: {}\n⭐️ Premium User: {}\n👽 UnCached: {}\n\n⏱ Waktu eksekusi {} detik.".format(
|
||||
message.chat.title,
|
||||
count,
|
||||
recently,
|
||||
within_week,
|
||||
within_month,
|
||||
long_time_ago,
|
||||
no_username,
|
||||
restricted,
|
||||
banned,
|
||||
deleted_acc,
|
||||
bot,
|
||||
premium_acc,
|
||||
uncached,
|
||||
timelog,
|
||||
)
|
||||
)
|
||||
else:
|
||||
sent_message = await message.reply_text(
|
||||
"❗ **Kamu harus jadi admin atau owner grup untuk melakukan tindakan ini.**"
|
||||
)
|
||||
await sleep(5)
|
||||
await sent_message.delete()
|
||||
607
misskaty/plugins/inline_search.py
Normal file
607
misskaty/plugins/inline_search.py
Normal file
|
|
@ -0,0 +1,607 @@
|
|||
import json, traceback
|
||||
from sys import version as pyver, platform
|
||||
from misskaty import app, user
|
||||
from motor import version as mongover
|
||||
from misskaty.plugins.misc_tools import get_content
|
||||
from pyrogram import __version__ as pyrover
|
||||
from misskaty.helper.http import http
|
||||
from misskaty.helper.tools import GENRES_EMOJI
|
||||
from pyrogram import filters, enums
|
||||
from bs4 import BeautifulSoup
|
||||
from utils import demoji
|
||||
from pykeyboard import InlineKeyboard
|
||||
from deep_translator import GoogleTranslator
|
||||
from pyrogram.types import (
|
||||
InlineKeyboardButton,
|
||||
InlineKeyboardMarkup,
|
||||
InlineQuery,
|
||||
InlineQueryResultArticle,
|
||||
InputTextMessageContent,
|
||||
InlineQueryResultPhoto,
|
||||
)
|
||||
|
||||
__MODULE__ = "InlineFeature"
|
||||
__HELP__ = """
|
||||
To use this feature, just type bot username with following args below.
|
||||
~ imdb [query] - Search movie details in IMDb.com.
|
||||
~ pypi [query] - Search package from Pypi.
|
||||
~ git [query] - Search in Git.
|
||||
~ google [query] - Search in Google.
|
||||
"""
|
||||
|
||||
keywords_list = ["imdb", "pypi", "git", "google", "secretmsg"]
|
||||
|
||||
PRVT_MSGS = {}
|
||||
|
||||
|
||||
@app.on_inline_query()
|
||||
async def inline_menu(_, inline_query: InlineQuery):
|
||||
if inline_query.query.strip().lower().strip() == "":
|
||||
buttons = InlineKeyboard(row_width=2)
|
||||
buttons.add(
|
||||
*[
|
||||
(InlineKeyboardButton(text=i, switch_inline_query_current_chat=i))
|
||||
for i in keywords_list
|
||||
]
|
||||
)
|
||||
|
||||
btn = InlineKeyboard(row_width=2)
|
||||
bot_state = "Alive" if await app.get_me() else "Dead"
|
||||
ubot_state = "Alive" if await user.get_me() else "Dead"
|
||||
btn.add(
|
||||
InlineKeyboardButton("Stats", callback_data="stats_callback"),
|
||||
InlineKeyboardButton("Go Inline!", switch_inline_query_current_chat=""),
|
||||
)
|
||||
|
||||
msg = f"""
|
||||
**[MissKaty✨](https://github.com/yasirarism):**
|
||||
**MainBot:** `{bot_state}`
|
||||
**UserBot:** `{ubot_state}`
|
||||
**Python:** `{pyver.split()[0]}`
|
||||
**Pyrogram:** `{pyrover}`
|
||||
**MongoDB:** `{mongover}`
|
||||
**Platform:** `{platform}`
|
||||
**Profiles:** {(await app.get_me()).username} | {(await user.get_me()).first_name}
|
||||
"""
|
||||
answerss = [
|
||||
InlineQueryResultArticle(
|
||||
title="Inline Commands",
|
||||
description="Help Related To Inline Usage.",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"Click A Button To Get Started."
|
||||
),
|
||||
thumb_url="https://hamker.me/cy00x5x.png",
|
||||
reply_markup=buttons,
|
||||
),
|
||||
InlineQueryResultArticle(
|
||||
title="Github Repo",
|
||||
description="Github Repo of This Bot.",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"<b>Github Repo @MissKatyRoBot</b>\n\nhttps://github.com/yasirarism/MissKatyPyro"
|
||||
),
|
||||
thumb_url="https://hamker.me/gjc9fo3.png",
|
||||
),
|
||||
InlineQueryResultArticle(
|
||||
title="Alive",
|
||||
description="Check Bot's Stats",
|
||||
thumb_url="https://yt3.ggpht.com/ytc/AMLnZu-zbtIsllERaGYY8Aecww3uWUASPMjLUUEt7ecu=s900-c-k-c0x00ffffff-no-rj",
|
||||
input_message_content=InputTextMessageContent(
|
||||
msg, disable_web_page_preview=True
|
||||
),
|
||||
reply_markup=btn,
|
||||
),
|
||||
]
|
||||
await inline_query.answer(results=answerss)
|
||||
elif inline_query.query.strip().lower().split()[0] == "google":
|
||||
if len(inline_query.query.strip().lower().split()) < 2:
|
||||
return await inline_query.answer(
|
||||
results=[],
|
||||
switch_pm_text="Google Search | google [QUERY]",
|
||||
switch_pm_parameter="inline",
|
||||
)
|
||||
judul = inline_query.query.split(None, 1)[1].strip()
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/61.0.3163.100 Safari/537.36"
|
||||
}
|
||||
search_results = await http.get(
|
||||
f"https://www.google.com/search?q={judul}&num=20", headers=headers
|
||||
)
|
||||
soup = BeautifulSoup(search_results.text, "lxml")
|
||||
data = []
|
||||
for result in soup.select(".tF2Cxc"):
|
||||
title = result.select_one(".DKV0Md").text
|
||||
link = result.select_one(".yuRUbf a")["href"]
|
||||
try:
|
||||
snippet = result.select_one("#rso .lyLwlc").text
|
||||
except:
|
||||
snippet = "-"
|
||||
message_text = f"<a href='{link}'>{title}</a>\n"
|
||||
message_text += f"Deskription: {snippet}"
|
||||
data.append(
|
||||
InlineQueryResultArticle(
|
||||
title=f"{title}",
|
||||
input_message_content=InputTextMessageContent(
|
||||
message_text=message_text,
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
disable_web_page_preview=False,
|
||||
),
|
||||
url=link,
|
||||
description=snippet,
|
||||
thumb_url="https://te.legra.ph/file/ed8ea62ae636793000bb4.jpg",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(text="Open Website", url=link)]]
|
||||
),
|
||||
)
|
||||
)
|
||||
await inline_query.answer(
|
||||
results=data,
|
||||
is_gallery=False,
|
||||
is_personal=False,
|
||||
next_offset="",
|
||||
switch_pm_text=f"Found {len(data)} results",
|
||||
switch_pm_parameter="google",
|
||||
)
|
||||
elif inline_query.query.strip().lower().split()[0] == "secretmsg":
|
||||
if len(inline_query.query.strip().lower().split()) < 3:
|
||||
return await inline_query.answer(
|
||||
results=[],
|
||||
switch_pm_text="SecretMsg | secretmsg [USERNAME/ID] [MESSAGE]",
|
||||
switch_pm_parameter="inline",
|
||||
)
|
||||
_id = inline_query.query.split()[1]
|
||||
msg = inline_query.query.split(None, 2)[2].strip()
|
||||
|
||||
if not msg or not msg.endswith(":"):
|
||||
inline_query.stop_propagation()
|
||||
|
||||
try:
|
||||
penerima = await app.get_users(_id.strip())
|
||||
except Exception: # pylint: disable=broad-except
|
||||
inline_query.stop_propagation()
|
||||
return
|
||||
|
||||
PRVT_MSGS[inline_query.id] = (
|
||||
penerima.id,
|
||||
penerima.first_name,
|
||||
inline_query.from_user.id,
|
||||
msg.strip(": "),
|
||||
)
|
||||
prvte_msg = InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"Show Message 🔐", callback_data=f"prvtmsg({inline_query.id})"
|
||||
)
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"Destroy☠️ this msg",
|
||||
callback_data=f"destroy({inline_query.id})",
|
||||
)
|
||||
],
|
||||
]
|
||||
)
|
||||
mention = (
|
||||
f"@{penerima.username}"
|
||||
if penerima.username
|
||||
else f"<a href='tg://user?id={penerima.id}'>{penerima.first_name}</a>"
|
||||
)
|
||||
|
||||
msg_c = (
|
||||
f"🔒 A <b>private message</b> to {mention} [<code>{penerima.id}</code>], "
|
||||
)
|
||||
msg_c += "Only he/she can open it."
|
||||
results = [
|
||||
InlineQueryResultArticle(
|
||||
title=f"A Private Msg to {penerima.first_name}",
|
||||
input_message_content=InputTextMessageContent(msg_c),
|
||||
description="Only he/she can open it",
|
||||
thumb_url="https://te.legra.ph/file/16133ab3297b3f73c8da5.png",
|
||||
reply_markup=prvte_msg,
|
||||
)
|
||||
]
|
||||
await inline_query.answer(results=results, cache_time=3)
|
||||
elif inline_query.query.strip().lower().split()[0] == "git":
|
||||
if len(inline_query.query.strip().lower().split()) < 2:
|
||||
return await inline_query.answer(
|
||||
results=[],
|
||||
switch_pm_text="Github Search | git [QUERY]",
|
||||
switch_pm_parameter="inline",
|
||||
)
|
||||
query = inline_query.query.split(None, 1)[1].strip()
|
||||
search_results = await http.get(
|
||||
f"https://api.github.com/search/repositories?q={query}"
|
||||
)
|
||||
srch_results = json.loads(search_results.text)
|
||||
item = srch_results.get("items")
|
||||
data = []
|
||||
for sraeo in item:
|
||||
title = sraeo.get("full_name")
|
||||
link = sraeo.get("html_url")
|
||||
deskripsi = sraeo.get("description")
|
||||
lang = sraeo.get("language")
|
||||
message_text = f"🔗: {sraeo.get('html_url')}\n│\n└─🍴Forks: {sraeo.get('forks')} ┃┃ 🌟Stars: {sraeo.get('stargazers_count')}\n\n"
|
||||
message_text += f"<b>Description:</b> {deskripsi}\n"
|
||||
message_text += f"<b>Language:</b> {lang}"
|
||||
data.append(
|
||||
InlineQueryResultArticle(
|
||||
title=f"{title}",
|
||||
input_message_content=InputTextMessageContent(
|
||||
message_text=message_text,
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
disable_web_page_preview=False,
|
||||
),
|
||||
url=link,
|
||||
description=deskripsi,
|
||||
thumb_url="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(text="Open Github Link", url=link)]]
|
||||
),
|
||||
)
|
||||
)
|
||||
await inline_query.answer(
|
||||
results=data,
|
||||
is_gallery=False,
|
||||
is_personal=False,
|
||||
next_offset="",
|
||||
switch_pm_text=f"Found {len(data)} results",
|
||||
switch_pm_parameter="github",
|
||||
)
|
||||
elif inline_query.query.strip().lower().split()[0] == "pypi":
|
||||
if len(inline_query.query.strip().lower().split()) < 2:
|
||||
return await inline_query.answer(
|
||||
results=[],
|
||||
switch_pm_text="Pypi Search | pypi [QUERY]",
|
||||
switch_pm_parameter="inline",
|
||||
)
|
||||
query = inline_query.query.split(None, 1)[1].strip()
|
||||
search_results = await http.get(
|
||||
f"https://api.hayo.my.id/api/pypi?package={query}"
|
||||
)
|
||||
srch_results = json.loads(search_results.text)
|
||||
data = []
|
||||
for sraeo in srch_results:
|
||||
title = sraeo.get("title")
|
||||
link = sraeo.get("link")
|
||||
deskripsi = sraeo.get("desc")
|
||||
version = sraeo.get("version")
|
||||
message_text = f"<a href='{link}'>{title} {version}</a>\n"
|
||||
message_text += f"Description: {deskripsi}\n"
|
||||
data.append(
|
||||
InlineQueryResultArticle(
|
||||
title=f"{title}",
|
||||
input_message_content=InputTextMessageContent(
|
||||
message_text=message_text,
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
disable_web_page_preview=False,
|
||||
),
|
||||
url=link,
|
||||
description=deskripsi,
|
||||
thumb_url="https://raw.githubusercontent.com/github/explore/666de02829613e0244e9441b114edb85781e972c/topics/pip/pip.png",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(text="Open Link", url=link)]]
|
||||
),
|
||||
)
|
||||
)
|
||||
await inline_query.answer(
|
||||
results=data,
|
||||
is_gallery=False,
|
||||
is_personal=False,
|
||||
next_offset="",
|
||||
switch_pm_text=f"Found {len(data)} results",
|
||||
switch_pm_parameter="pypi",
|
||||
)
|
||||
elif inline_query.query.strip().lower().split()[0] == "yt":
|
||||
if len(inline_query.query.strip().lower().split()) < 2:
|
||||
return await inline_query.answer(
|
||||
results=[],
|
||||
switch_pm_text="YouTube Search | yt [QUERY]",
|
||||
switch_pm_parameter="inline",
|
||||
)
|
||||
judul = inline_query.query.split(None, 1)[1].strip()
|
||||
search_results = await http.get(
|
||||
f"https://api.abir-hasan.tk/youtube?query={judul}"
|
||||
)
|
||||
srch_results = json.loads(search_results.text)
|
||||
asroe = srch_results.get("results")
|
||||
oorse = []
|
||||
for sraeo in asroe:
|
||||
title = sraeo.get("title")
|
||||
link = sraeo.get("link")
|
||||
view = sraeo.get("viewCount").get("text")
|
||||
thumb = sraeo.get("thumbnails")[0].get("url")
|
||||
durasi = sraeo.get("accessibility").get("duration")
|
||||
publishTime = sraeo.get("publishedTime")
|
||||
try:
|
||||
deskripsi = "".join(
|
||||
f"{i['text']} " for i in sraeo.get("descriptionSnippet")
|
||||
)
|
||||
except:
|
||||
deskripsi = "-"
|
||||
message_text = f"<a href='{link}'>{title}</a>\n"
|
||||
message_text += f"Description: {deskripsi}\n"
|
||||
message_text += f"Total View: {view}\n"
|
||||
message_text += f"Duration: {durasi}\n"
|
||||
message_text += f"Published Time: {publishTime}"
|
||||
oorse.append(
|
||||
InlineQueryResultArticle(
|
||||
title=f"{title}",
|
||||
input_message_content=InputTextMessageContent(
|
||||
message_text=message_text,
|
||||
parse_mode=enums.ParseMode.HTML,
|
||||
disable_web_page_preview=False,
|
||||
),
|
||||
url=link,
|
||||
description=deskripsi,
|
||||
thumb_url=thumb,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(text="Watch Video 📹", url=link)]]
|
||||
),
|
||||
)
|
||||
)
|
||||
await inline_query.answer(
|
||||
results=oorse,
|
||||
is_gallery=False,
|
||||
is_personal=False,
|
||||
next_offset="",
|
||||
switch_pm_text=f"Found {len(asroe)} results",
|
||||
switch_pm_parameter="yt",
|
||||
)
|
||||
elif inline_query.query.strip().lower().split()[0] == "imdb":
|
||||
if len(inline_query.query.strip().lower().split()) < 2:
|
||||
return await inline_query.answer(
|
||||
results=[],
|
||||
switch_pm_text="IMDB Search | imdb [QUERY]",
|
||||
switch_pm_parameter="inline",
|
||||
)
|
||||
movie_name = inline_query.query.split(None, 1)[1].strip()
|
||||
search_results = await http.get(
|
||||
f"https://yasirapi.eu.org/imdb-search?q={movie_name}"
|
||||
)
|
||||
res = json.loads(search_results.text).get("result")
|
||||
oorse = []
|
||||
for midb in res:
|
||||
title = midb.get("l", "")
|
||||
description = midb.get("q", "")
|
||||
stars = midb.get("s", "")
|
||||
imdb_url = f"https://imdb.com/title/{midb.get('id')}"
|
||||
year = f"({midb.get('y')})" if midb.get("y") else ""
|
||||
image_url = (
|
||||
midb.get("i").get("imageUrl").replace(".jpg", "._V1_UX360.jpg")
|
||||
if midb.get("i")
|
||||
else "https://te.legra.ph/file/e263d10ff4f4426a7c664.jpg"
|
||||
)
|
||||
caption = f"<a href='{image_url}'>🎬</a>"
|
||||
caption += f"<a href='{imdb_url}'>{title} {year}</a>"
|
||||
oorse.append(
|
||||
InlineQueryResultPhoto(
|
||||
title=f"{title} {year}",
|
||||
caption=caption,
|
||||
description=f" {description} | {stars}",
|
||||
photo_url=image_url,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="Get IMDB details",
|
||||
callback_data=f"imdbinl_{inline_query.from_user.id}_{midb.get('id')}",
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
)
|
||||
resfo = json.loads(search_results.text).get("q")
|
||||
await inline_query.answer(
|
||||
results=oorse,
|
||||
is_gallery=False,
|
||||
is_personal=False,
|
||||
next_offset="",
|
||||
switch_pm_text=f"Found {len(oorse)} results for {resfo}",
|
||||
switch_pm_parameter="imdb",
|
||||
)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"prvtmsg\((.+)\)"))
|
||||
async def prvt_msg(_, c_q):
|
||||
msg_id = str(c_q.matches[0].group(1))
|
||||
|
||||
if msg_id not in PRVT_MSGS:
|
||||
await c_q.answer("Message now outdated !", show_alert=True)
|
||||
return
|
||||
|
||||
user_id, flname, sender_id, msg = PRVT_MSGS[msg_id]
|
||||
|
||||
if c_q.from_user.id in [user_id, sender_id]:
|
||||
await c_q.answer(msg, show_alert=True)
|
||||
else:
|
||||
await c_q.answer(f"Only {flname} can see this Private Msg!", show_alert=True)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"destroy\((.+)\)"))
|
||||
async def destroy_msg(_, c_q):
|
||||
msg_id = str(c_q.matches[0].group(1))
|
||||
|
||||
if msg_id not in PRVT_MSGS:
|
||||
await c_q.answer("Message now outdated !", show_alert=True)
|
||||
return
|
||||
|
||||
user_id, flname, sender_id, msg = PRVT_MSGS[msg_id]
|
||||
|
||||
if c_q.from_user.id in [user_id, sender_id]:
|
||||
del PRVT_MSGS[msg_id]
|
||||
by = "receiver" if c_q.from_user.id == user_id else "sender"
|
||||
await c_q.edit_message_text(f"This secret message is ☠️destroyed☠️ by msg {by}")
|
||||
else:
|
||||
await c_q.answer(f"Only {flname} can see this Private Msg!", show_alert=True)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("^imdbinl_"))
|
||||
async def imdb_inl(_, query):
|
||||
i, user, movie = query.data.split("_")
|
||||
if user == f"{query.from_user.id}":
|
||||
await query.edit_message_caption("⏳ <i>Permintaan kamu sedang diproses.. </i>")
|
||||
try:
|
||||
url = f"https://www.imdb.com/title/{movie}/"
|
||||
resp = await get_content(url)
|
||||
sop = BeautifulSoup(resp, "lxml")
|
||||
r_json = json.loads(
|
||||
sop.find("script", attrs={"type": "application/ld+json"}).contents[0]
|
||||
)
|
||||
res_str = ""
|
||||
type = f"<code>{r_json['@type']}</code>" if r_json.get("@type") else ""
|
||||
if r_json.get("name"):
|
||||
try:
|
||||
tahun = (
|
||||
sop.select('ul[data-testid="hero-title-block__metadata"]')[0]
|
||||
.find(class_="sc-8c396aa2-2 itZqyK")
|
||||
.text
|
||||
)
|
||||
except:
|
||||
tahun = "-"
|
||||
res_str += f"<b>📹 Judul:</b> <a href='{url}'>{r_json['name']} [{tahun}]</a> (<code>{type}</code>)\n"
|
||||
if r_json.get("alternateName"):
|
||||
res_str += (
|
||||
f"<b>📢 AKA:</b> <code>{r_json.get('alternateName')}</code>\n\n"
|
||||
)
|
||||
else:
|
||||
res_str += "\n"
|
||||
if sop.select('li[data-testid="title-techspec_runtime"]'):
|
||||
durasi = (
|
||||
sop.select('li[data-testid="title-techspec_runtime"]')[0]
|
||||
.find(class_="ipc-metadata-list-item__content-container")
|
||||
.text
|
||||
)
|
||||
res_str += f"<b>Durasi:</b> <code>{GoogleTranslator('auto', 'id').translate(durasi)}</code>\n"
|
||||
if r_json.get("contentRating"):
|
||||
res_str += f"<b>Kategori:</b> <code>{r_json['contentRating']}</code> \n"
|
||||
if r_json.get("aggregateRating"):
|
||||
res_str += f"<b>Peringkat:</b> <code>{r_json['aggregateRating']['ratingValue']}⭐️ dari {r_json['aggregateRating']['ratingCount']} pengguna</code> \n"
|
||||
if sop.select('li[data-testid="title-details-releasedate"]'):
|
||||
rilis = (
|
||||
sop.select('li[data-testid="title-details-releasedate"]')[0]
|
||||
.find(
|
||||
class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link"
|
||||
)
|
||||
.text
|
||||
)
|
||||
rilis_url = sop.select('li[data-testid="title-details-releasedate"]')[
|
||||
0
|
||||
].find(
|
||||
class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link"
|
||||
)[
|
||||
"href"
|
||||
]
|
||||
res_str += f"<b>Rilis:</b> <a href='https://www.imdb.com{rilis_url}'>{rilis}</a>\n"
|
||||
if r_json.get("genre"):
|
||||
genre = "".join(
|
||||
f"{GENRES_EMOJI[i]} #{i.replace('-', '_').replace(' ', '_')}, "
|
||||
if i in GENRES_EMOJI
|
||||
else f"#{i.replace('-', '_').replace(' ', '_')}, "
|
||||
for i in r_json["genre"]
|
||||
)
|
||||
|
||||
genre = genre[:-2]
|
||||
res_str += f"<b>Genre:</b> {genre}\n"
|
||||
if sop.select('li[data-testid="title-details-origin"]'):
|
||||
country = "".join(
|
||||
f"{demoji(country.text)} #{country.text.replace(' ', '_').replace('-', '_')}, "
|
||||
for country in sop.select('li[data-testid="title-details-origin"]')[
|
||||
0
|
||||
].findAll(
|
||||
class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link"
|
||||
)
|
||||
)
|
||||
country = country[:-2]
|
||||
res_str += f"<b>Negara:</b> {country}\n"
|
||||
if sop.select('li[data-testid="title-details-languages"]'):
|
||||
language = "".join(
|
||||
f"#{lang.text.replace(' ', '_').replace('-', '_')}, "
|
||||
for lang in sop.select('li[data-testid="title-details-languages"]')[
|
||||
0
|
||||
].findAll(
|
||||
class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link"
|
||||
)
|
||||
)
|
||||
language = language[:-2]
|
||||
res_str += f"<b>Bahasa:</b> {language}\n"
|
||||
res_str += "\n<b>🙎 Info Cast:</b>\n"
|
||||
if r_json.get("director"):
|
||||
director = ""
|
||||
for i in r_json["director"]:
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
director += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
director = director[:-2]
|
||||
res_str += f"<b>Sutradara:</b> {director}\n"
|
||||
if r_json.get("creator"):
|
||||
creator = ""
|
||||
for i in r_json["creator"]:
|
||||
if i["@type"] == "Person":
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
creator += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
creator = creator[:-2]
|
||||
res_str += f"<b>Penulis:</b> {creator}\n"
|
||||
if r_json.get("actor"):
|
||||
actors = ""
|
||||
for i in r_json["actor"]:
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
actors += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
actors = actors[:-2]
|
||||
res_str += f"<b>Pemeran:</b> {actors}\n\n"
|
||||
if r_json.get("description"):
|
||||
summary = GoogleTranslator("auto", "id").translate(
|
||||
r_json.get("description")
|
||||
)
|
||||
res_str += f"<b>📜 Plot: </b> <code>{summary}</code>\n\n"
|
||||
if r_json.get("keywords"):
|
||||
keywords = r_json["keywords"].split(",")
|
||||
key_ = ""
|
||||
for i in keywords:
|
||||
i = i.replace(" ", "_").replace("-", "_")
|
||||
key_ += f"#{i}, "
|
||||
key_ = key_[:-2]
|
||||
res_str += f"<b>🔥 Kata Kunci:</b> {key_} \n"
|
||||
if sop.select('li[data-testid="award_information"]'):
|
||||
awards = (
|
||||
sop.select('li[data-testid="award_information"]')[0]
|
||||
.find(class_="ipc-metadata-list-item__list-content-item")
|
||||
.text
|
||||
)
|
||||
res_str += f"<b>🏆 Penghargaan:</b> <code>{GoogleTranslator('auto', 'id').translate(awards)}</code>\n\n"
|
||||
else:
|
||||
res_str += "\n"
|
||||
res_str += "<b>©️ IMDb by</b> @MissKatyRoBot"
|
||||
if r_json.get("trailer"):
|
||||
trailer_url = r_json["trailer"]["url"]
|
||||
markup = InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"🎬 Open IMDB",
|
||||
url=f"https://www.imdb.com{r_json['url']}",
|
||||
),
|
||||
InlineKeyboardButton("▶️ Trailer", url=trailer_url),
|
||||
]
|
||||
]
|
||||
)
|
||||
else:
|
||||
markup = InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"🎬 Open IMDB",
|
||||
url=f"https://www.imdb.com{r_json['url']}",
|
||||
)
|
||||
]
|
||||
]
|
||||
)
|
||||
await query.edit_message_caption(res_str, reply_markup=markup)
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await query.edit_message_caption(f"<b>ERROR:</b>\n<code>{exc}</code>")
|
||||
else:
|
||||
await query.answer("⚠️ Akses Ditolak!", True)
|
||||
25
misskaty/plugins/json.py
Normal file
25
misskaty/plugins/json.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import os
|
||||
from pyrogram import filters
|
||||
from misskaty import app
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
|
||||
|
||||
# View Structure Telegram Message As JSON
|
||||
@app.on_message(filters.command(["json"], COMMAND_HANDLER))
|
||||
async def jsonify(_, message):
|
||||
the_real_message = None
|
||||
reply_to_id = None
|
||||
|
||||
the_real_message = message.reply_to_message or message
|
||||
try:
|
||||
await message.reply_text(f"<code>{the_real_message}</code>")
|
||||
except Exception as e:
|
||||
with open("json.text", "w+", encoding="utf8") as out_file:
|
||||
out_file.write(str(the_real_message))
|
||||
await message.reply_document(
|
||||
document="json.text",
|
||||
caption=f"<code>{str(e)}</code>",
|
||||
disable_notification=True,
|
||||
reply_to_message_id=reply_to_id,
|
||||
)
|
||||
os.remove("json.text")
|
||||
201
misskaty/plugins/karma.py
Normal file
201
misskaty/plugins/karma.py
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
import re
|
||||
from pyrogram import filters
|
||||
from misskaty import app
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.core.decorator.permissions import adminsOnly
|
||||
from misskaty.helper.functions import alpha_to_int, int_to_alpha
|
||||
from database.karma_db import (
|
||||
get_karma,
|
||||
get_karmas,
|
||||
is_karma_on,
|
||||
karma_off,
|
||||
karma_on,
|
||||
update_karma,
|
||||
)
|
||||
|
||||
__MODULE__ = "Karma"
|
||||
__HELP__ = """
|
||||
Give reputation to other people in group.
|
||||
|
||||
/karma_toggle [enable/disable] - Enable/Disable Karma.
|
||||
/karma - View all karma from member group.
|
||||
"""
|
||||
|
||||
karma_positive_group = 3
|
||||
karma_negative_group = 4
|
||||
|
||||
regex_upvote = (
|
||||
r"^(\+|\+\+|\+1|thx|tnx|ty|thank you|thanx|thanks|pro|cool|good|makasih|👍|\+\+ .+)$"
|
||||
)
|
||||
regex_downvote = r"^(-|--|-1|👎|-- .+)$"
|
||||
|
||||
n = "\n"
|
||||
w = " "
|
||||
|
||||
bold = lambda x: f"**{x}:** "
|
||||
bold_ul = lambda x: f"**--{x}:**-- "
|
||||
|
||||
mono = lambda x: f"`{x}`{n}"
|
||||
|
||||
|
||||
def section(
|
||||
title: str,
|
||||
body: dict,
|
||||
indent: int = 2,
|
||||
underline: bool = False,
|
||||
) -> str:
|
||||
text = (bold_ul(title) + n) if underline else bold(title) + n
|
||||
|
||||
for key, value in body.items():
|
||||
text += (
|
||||
indent * w
|
||||
+ bold(key)
|
||||
+ ((value[0] + n) if isinstance(value, list) else mono(value))
|
||||
)
|
||||
return text
|
||||
|
||||
|
||||
async def get_user_id_and_usernames(client) -> dict:
|
||||
with client.storage.lock, client.storage.conn:
|
||||
users = client.storage.conn.execute(
|
||||
'SELECT * FROM peers WHERE type in ("user", "bot") AND username NOT null'
|
||||
).fetchall()
|
||||
return {user[0]: user[3] for user in users}
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.text
|
||||
& filters.group
|
||||
& filters.incoming
|
||||
& filters.reply
|
||||
& filters.regex(regex_upvote, re.IGNORECASE)
|
||||
& ~filters.via_bot
|
||||
& ~filters.bot,
|
||||
group=karma_positive_group,
|
||||
)
|
||||
@capture_err
|
||||
async def upvote(_, message):
|
||||
if not await is_karma_on(message.chat.id):
|
||||
return
|
||||
if not message.reply_to_message.from_user:
|
||||
return
|
||||
if not message.from_user:
|
||||
return
|
||||
if message.reply_to_message.from_user.id == message.from_user.id:
|
||||
return
|
||||
chat_id = message.chat.id
|
||||
user_id = message.reply_to_message.from_user.id
|
||||
user_mention = message.reply_to_message.from_user.mention
|
||||
current_karma = await get_karma(chat_id, await int_to_alpha(user_id))
|
||||
if current_karma:
|
||||
current_karma = current_karma["karma"]
|
||||
karma = current_karma + 1
|
||||
else:
|
||||
karma = 1
|
||||
new_karma = {"karma": karma}
|
||||
await update_karma(chat_id, await int_to_alpha(user_id), new_karma)
|
||||
await message.reply_text(
|
||||
f"Incremented Karma of {user_mention} By 1 \nTotal Points: {karma}"
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.text
|
||||
& filters.group
|
||||
& filters.incoming
|
||||
& filters.reply
|
||||
& filters.regex(regex_downvote, re.IGNORECASE)
|
||||
& ~filters.via_bot
|
||||
& ~filters.bot,
|
||||
group=karma_negative_group,
|
||||
)
|
||||
@capture_err
|
||||
async def downvote(_, message):
|
||||
if not await is_karma_on(message.chat.id):
|
||||
return
|
||||
if not message.reply_to_message.from_user:
|
||||
return
|
||||
if not message.from_user:
|
||||
return
|
||||
if message.reply_to_message.from_user.id == message.from_user.id:
|
||||
return
|
||||
|
||||
chat_id = message.chat.id
|
||||
user_id = message.reply_to_message.from_user.id
|
||||
user_mention = message.reply_to_message.from_user.mention
|
||||
current_karma = await get_karma(chat_id, await int_to_alpha(user_id))
|
||||
if current_karma:
|
||||
current_karma = current_karma["karma"]
|
||||
karma = current_karma - 1
|
||||
else:
|
||||
karma = 1
|
||||
new_karma = {"karma": karma}
|
||||
await update_karma(chat_id, await int_to_alpha(user_id), new_karma)
|
||||
await message.reply_text(
|
||||
f"Decremented Karma Of {user_mention} By 1 \nTotal Points: {karma}"
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(filters.command("karma") & filters.group)
|
||||
@capture_err
|
||||
async def command_karma(_, message):
|
||||
chat_id = message.chat.id
|
||||
if not message.reply_to_message:
|
||||
m = await message.reply_text("Analyzing Karma...")
|
||||
karma = await get_karmas(chat_id)
|
||||
if not karma:
|
||||
return await m.edit("No karma in DB for this chat.")
|
||||
msg = f"Karma list of {message.chat.title}"
|
||||
limit = 0
|
||||
karma_dicc = {}
|
||||
for i in karma:
|
||||
user_id = await alpha_to_int(i)
|
||||
user_karma = karma[i]["karma"]
|
||||
karma_dicc[str(user_id)] = user_karma
|
||||
karma_arranged = dict(
|
||||
sorted(
|
||||
karma_dicc.items(),
|
||||
key=lambda item: item[1],
|
||||
reverse=True,
|
||||
)
|
||||
)
|
||||
if not karma_dicc:
|
||||
return await m.edit("No karma in DB for this chat.")
|
||||
userdb = await get_user_id_and_usernames(app)
|
||||
karma = {}
|
||||
for user_idd, karma_count in karma_arranged.items():
|
||||
if limit > 15:
|
||||
break
|
||||
if int(user_idd) not in list(userdb.keys()):
|
||||
continue
|
||||
username = userdb[int(user_idd)]
|
||||
karma[f"@{username}"] = [f"**{str(karma_count)}**"]
|
||||
limit += 1
|
||||
await m.edit(section(msg, karma))
|
||||
else:
|
||||
if not message.reply_to_message.from_user:
|
||||
return await message.reply("Anon user hash no karma.")
|
||||
|
||||
user_id = message.reply_to_message.from_user.id
|
||||
karma = await get_karma(chat_id, await int_to_alpha(user_id))
|
||||
karma = karma["karma"] if karma else 0
|
||||
await message.reply_text(f"**Total Points**: __{karma}__")
|
||||
|
||||
|
||||
@app.on_message(filters.command("karma_toggle") & ~filters.private)
|
||||
@adminsOnly
|
||||
async def captcha_state(_, message):
|
||||
usage = "**Usage:**\n/karma_toggle [ENABLE|DISABLE]"
|
||||
if len(message.command) != 2:
|
||||
return await message.reply_text(usage)
|
||||
chat_id = message.chat.id
|
||||
state = message.text.split(None, 1)[1].strip()
|
||||
state = state.lower()
|
||||
if state == "enable":
|
||||
await karma_on(chat_id)
|
||||
await message.reply_text("Enabled karma system.")
|
||||
elif state == "disable":
|
||||
await karma_off(chat_id)
|
||||
await message.reply_text("Disabled karma system.")
|
||||
else:
|
||||
await message.reply_text(usage)
|
||||
81
misskaty/plugins/mediainfo.py
Normal file
81
misskaty/plugins/mediainfo.py
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import io
|
||||
from os import remove as osremove
|
||||
import time
|
||||
import subprocess
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from utils import get_file_id
|
||||
from misskaty import app
|
||||
from misskaty.helper.media_helper import post_to_telegraph, runcmd
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.helper.pyro_progress import (
|
||||
progress_for_pyrogram,
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["mediainfo", "mediainfo@MissKatyRoBot"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def mediainfo(client, message):
|
||||
if message.reply_to_message and message.reply_to_message.media:
|
||||
process = await message.reply_text("`Sedang memproses, lama waktu tergantung ukuran file kamu...`", quote=True)
|
||||
file_info = get_file_id(message.reply_to_message)
|
||||
if file_info is None:
|
||||
await process.edit_text("Balas ke format media yang valid")
|
||||
return
|
||||
c_time = time.time()
|
||||
# file_path = safe_filename(await reply.download())
|
||||
file_path = await client.download_media(
|
||||
message=message.reply_to_message,
|
||||
progress=progress_for_pyrogram,
|
||||
progress_args=("trying to download, sabar yakk..", process, c_time),
|
||||
)
|
||||
output_ = await runcmd(f'mediainfo "{file_path}"')
|
||||
out = output_[0] if len(output_) != 0 else None
|
||||
body_text = f"""
|
||||
<img src='https://telegra.ph/file/72c99bbc89bbe4e178cc9.jpg' />
|
||||
<h2>JSON</h2>
|
||||
<pre>{file_info}.type</pre>
|
||||
<br>
|
||||
<h2>DETAILS</h2>
|
||||
<pre>{out or 'Not Supported'}</pre>
|
||||
"""
|
||||
title = "MissKaty Bot Mediainfo"
|
||||
text_ = file_info.message_type
|
||||
link = post_to_telegraph(title, body_text)
|
||||
markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=text_, url=link)]])
|
||||
await message.reply("ℹ️ <b>MEDIA INFO</b>", reply_markup=markup, quote=True)
|
||||
await process.delete()
|
||||
try:
|
||||
osremove(file_path)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
link = message.text.split(" ", maxsplit=1)[1]
|
||||
if link.startswith("https://file.yasirweb.my.id"):
|
||||
link = link.replace("https://file.yasirweb.my.id", "https://file.yasiraris.workers.dev")
|
||||
if link.startswith("https://link.yasirweb.my.id"):
|
||||
link = link.replace("https://link.yasirweb.my.id", "https://yasirrobot.herokuapp.com")
|
||||
process = await message.reply_text("`Mohon tunggu sejenak...`")
|
||||
try:
|
||||
output = subprocess.check_output(["mediainfo", f"{link}"]).decode("utf-8")
|
||||
except Exception:
|
||||
return await process.edit("Sepertinya link yang kamu kirim tidak valid, pastikan direct link dan bisa di download.")
|
||||
title = "MissKaty Bot Mediainfo"
|
||||
body_text = f"""
|
||||
<img src='https://telegra.ph/file/72c99bbc89bbe4e178cc9.jpg' />
|
||||
<pre>{output}</pre>
|
||||
"""
|
||||
tgraph = post_to_telegraph(title, body_text)
|
||||
# siteurl = "https://spaceb.in/api/v1/documents/"
|
||||
# response = await http.post(siteurl, data={"content": output, "extension": 'txt'} )
|
||||
# response = response.json()
|
||||
# spacebin = "https://spaceb.in/"+response['payload']['id']
|
||||
markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="💬 Telegraph", url=tgraph)]])
|
||||
with io.BytesIO(str.encode(output)) as out_file:
|
||||
out_file.name = "MissKaty_Mediainfo.txt"
|
||||
await message.reply_document(out_file, caption=f"Hasil mediainfo anda..\n\n<b>Request by:</b> {message.from_user.mention}", reply_markup=markup)
|
||||
await process.delete()
|
||||
except IndexError:
|
||||
return await message.reply_text("Gunakan command /mediainfo [link], atau reply telegram media dengan /mediainfo.")
|
||||
154
misskaty/plugins/memify.py
Normal file
154
misskaty/plugins/memify.py
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
import textwrap
|
||||
from os import remove as hapus
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty import app
|
||||
from pyrogram import filters
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from PIL import Image, ImageFont, ImageDraw
|
||||
|
||||
|
||||
async def draw_meme_text(image_path, text):
|
||||
img = Image.open(image_path)
|
||||
hapus(image_path)
|
||||
i_width, i_height = img.size
|
||||
m_font = ImageFont.truetype("Calistoga-Regular.ttf", int((70 / 640) * i_width))
|
||||
if ";" in text:
|
||||
upper_text, lower_text = text.split(";")
|
||||
else:
|
||||
upper_text = text
|
||||
lower_text = ""
|
||||
draw = ImageDraw.Draw(img)
|
||||
current_h, pad = 10, 5
|
||||
if upper_text:
|
||||
for u_text in textwrap.wrap(upper_text, width=15):
|
||||
u_width, u_height = draw.textsize(u_text, font=m_font)
|
||||
|
||||
draw.text(
|
||||
xy=(((i_width - u_width) / 2) - 1, int((current_h / 640) * i_width)),
|
||||
text=u_text,
|
||||
font=m_font,
|
||||
fill=(0, 0, 0),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
draw.text(
|
||||
xy=(((i_width - u_width) / 2) + 1, int((current_h / 640) * i_width)),
|
||||
text=u_text,
|
||||
font=m_font,
|
||||
fill=(0, 0, 0),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
draw.text(
|
||||
xy=((i_width - u_width) / 2, int(((current_h / 640) * i_width)) - 1),
|
||||
text=u_text,
|
||||
font=m_font,
|
||||
fill=(0, 0, 0),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
draw.text(
|
||||
xy=(((i_width - u_width) / 2), int(((current_h / 640) * i_width)) + 1),
|
||||
text=u_text,
|
||||
font=m_font,
|
||||
fill=(0, 0, 0),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
|
||||
draw.text(
|
||||
xy=((i_width - u_width) / 2, int((current_h / 640) * i_width)),
|
||||
text=u_text,
|
||||
font=m_font,
|
||||
fill=(255, 255, 255),
|
||||
)
|
||||
current_h += u_height + pad
|
||||
if lower_text:
|
||||
for l_text in textwrap.wrap(lower_text, width=15):
|
||||
u_width, u_height = draw.textsize(l_text, font=m_font)
|
||||
|
||||
draw.text(
|
||||
xy=(
|
||||
((i_width - u_width) / 2) - 1,
|
||||
i_height - u_height - int((20 / 640) * i_width),
|
||||
),
|
||||
text=l_text,
|
||||
font=m_font,
|
||||
fill=(0, 0, 0),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
draw.text(
|
||||
xy=(
|
||||
((i_width - u_width) / 2) + 1,
|
||||
i_height - u_height - int((20 / 640) * i_width),
|
||||
),
|
||||
text=l_text,
|
||||
font=m_font,
|
||||
fill=(0, 0, 0),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
draw.text(
|
||||
xy=(
|
||||
(i_width - u_width) / 2,
|
||||
(i_height - u_height - int((20 / 640) * i_width)) - 1,
|
||||
),
|
||||
text=l_text,
|
||||
font=m_font,
|
||||
fill=(0, 0, 0),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
draw.text(
|
||||
xy=(
|
||||
(i_width - u_width) / 2,
|
||||
(i_height - u_height - int((20 / 640) * i_width)) + 1,
|
||||
),
|
||||
text=l_text,
|
||||
font=m_font,
|
||||
fill=(0, 0, 0),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
|
||||
draw.text(
|
||||
xy=(
|
||||
(i_width - u_width) / 2,
|
||||
i_height - u_height - int((20 / 640) * i_width),
|
||||
),
|
||||
text=l_text,
|
||||
font=m_font,
|
||||
fill=(255, 255, 255),
|
||||
stroke_width=3,
|
||||
stroke_fill="black",
|
||||
)
|
||||
current_h += u_height + pad
|
||||
|
||||
webp_file = "memify.webp"
|
||||
img.save(webp_file, "WebP")
|
||||
return webp_file
|
||||
|
||||
|
||||
@app.on_message(filters.command(["mmf"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def memify(client, message):
|
||||
if message.reply_to_message and (
|
||||
message.reply_to_message.sticker or message.reply_to_message.photo
|
||||
):
|
||||
try:
|
||||
file = await message.reply_to_message.download()
|
||||
res = await draw_meme_text(file, message.text.split(None, 1)[1].strip())
|
||||
await message.reply_sticker(res)
|
||||
try:
|
||||
hapus(res)
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
await message.reply(
|
||||
"Gunakan command <b>/mmf <text></b> dengan reply ke sticker, pisahkan dengan ; untuk membuat posisi text dibawah."
|
||||
)
|
||||
else:
|
||||
await message.reply(
|
||||
"Gunakan command <b>/mmf <text></b> dengan reply ke sticker, pisahkan dengan ; untuk membuat posisi text dibawah."
|
||||
)
|
||||
645
misskaty/plugins/misc_tools.py
Normal file
645
misskaty/plugins/misc_tools.py
Normal file
|
|
@ -0,0 +1,645 @@
|
|||
import os, re
|
||||
import aiohttp
|
||||
from bs4 import BeautifulSoup
|
||||
import json
|
||||
import traceback
|
||||
from pyrogram import Client, filters
|
||||
from deep_translator import GoogleTranslator
|
||||
from gtts import gTTS
|
||||
from pyrogram.errors import MediaEmpty, MessageNotModified, PhotoInvalidDimensions, UserNotParticipant, WebpageMediaEmpty, MessageTooLong
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from utils import extract_user, get_file_id, demoji
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pykeyboard import InlineKeyboard
|
||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.helper.tools import rentry, GENRES_EMOJI
|
||||
from misskaty.helper.http import http
|
||||
from misskaty import app
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.ERROR)
|
||||
|
||||
__MODULE__ = "Misc"
|
||||
__HELP__ = """
|
||||
/sof [query] - Search your problem in StackOverflow.
|
||||
/google [query] - Search using Google Search.
|
||||
(/tr, /trans, /translate) [lang code] - Translate text using Google Translate.
|
||||
/tts - Convert Text to Voice.
|
||||
/imdb [query] - Find Movie Details From IMDB.com in Indonesian Language.
|
||||
/imdb_en [query] - Find Movie Details From IMDB.com in English Language.
|
||||
"""
|
||||
|
||||
|
||||
def remove_html_tags(text):
|
||||
"""Remove html tags from a string"""
|
||||
import re
|
||||
|
||||
clean = re.compile("<.*?>")
|
||||
return re.sub(clean, "", text)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["sof"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def stackoverflow(client, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Give a query to search in StackOverflow!")
|
||||
r = (await http.get(f"https://api.stackexchange.com/2.3/search/excerpts?order=asc&sort=relevance&q={message.command[1]}&accepted=True&migrated=False¬ice=False&wiki=False&site=stackoverflow")).json()
|
||||
hasil = ""
|
||||
for count, data in enumerate(r["items"], start=1):
|
||||
question = data["question_id"]
|
||||
title = data["title"]
|
||||
snippet = remove_html_tags(data["excerpt"])[:80].replace("\n", "").replace(" ", "") if len(remove_html_tags(data["excerpt"])) > 80 else remove_html_tags(data["excerpt"]).replace("\n", "").replace(" ", "")
|
||||
hasil += f"{count}. <a href='https://stackoverflow.com/questions/{question}'>{title}</a>\n<code>{snippet}</code>\n"
|
||||
try:
|
||||
await message.reply(hasil)
|
||||
except MessageTooLong:
|
||||
url = await rentry(hasil)
|
||||
await r.edit(f"Your text pasted to rentry because has long text:\n{url}")
|
||||
except Exception as e:
|
||||
await message.reply(e)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["google"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def gsearch(client, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Give a query to search in Google!")
|
||||
query = message.text.split(" ", maxsplit=1)[1]
|
||||
msg = await message.reply_text(f"**Googling** for `{query}` ...")
|
||||
try:
|
||||
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/61.0.3163.100 Safari/537.36"}
|
||||
html = await http.get(f"https://www.google.com/search?q={query}&gl=id&hl=id&num=17", headers=headers)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
|
||||
# collect data
|
||||
data = []
|
||||
|
||||
for result in soup.select(".tF2Cxc"):
|
||||
title = result.select_one(".DKV0Md").text
|
||||
link = result.select_one(".yuRUbf a")["href"]
|
||||
try:
|
||||
snippet = result.select_one("#rso .lyLwlc").text
|
||||
except:
|
||||
snippet = "-"
|
||||
|
||||
# appending data to an array
|
||||
data.append(
|
||||
{
|
||||
"title": title,
|
||||
"link": link,
|
||||
"snippet": snippet,
|
||||
}
|
||||
)
|
||||
arr = json.dumps(data, indent=2, ensure_ascii=False)
|
||||
parse = json.loads(arr)
|
||||
total = len(parse)
|
||||
res = "".join(f"<a href='{i['link']}'>{i['title']}</a>\n{i['snippet']}\n\n" for i in parse)
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
return await msg.edit(exc)
|
||||
await msg.edit(text=f"<b>Ada {total} Hasil Pencarian dari {query}:</b>\n{res}<b>Scraped by @MissKatyRoBot</b>", disable_web_page_preview=True)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["tr", "trans", "translate"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def translate(client, message):
|
||||
if message.reply_to_message and (message.reply_to_message.text or message.reply_to_message.caption):
|
||||
target_lang = "id" if len(message.command) == 1 else message.text.split()[1]
|
||||
text = message.reply_to_message.text or message.reply_to_message.caption
|
||||
else:
|
||||
if len(message.command) == 1:
|
||||
return await message.reply_text(
|
||||
"Berikan Kode bahasa yang valid.\n[Available options](https://telegra.ph/Lang-Codes-11-08).\n<b>Usage:</b> <code>/tr en</code>",
|
||||
)
|
||||
target_lang = message.text.split(None, 2)[1]
|
||||
text = message.text.split(None, 2)[2]
|
||||
msg = await message.reply("Menerjemahkan...")
|
||||
try:
|
||||
tekstr = (await http.get(f"https://script.google.com/macros/s/AKfycbyhNk6uVgrtJLEFRUT6y5B2pxETQugCZ9pKvu01-bE1gKkDRsw/exec?q={text}&target={target_lang}")).json()["text"]
|
||||
except Exception as err:
|
||||
return await msg.edit(f"Error: <code>{str(err)}</code>")
|
||||
try:
|
||||
await msg.edit(f"<code>{tekstr}</code>")
|
||||
except MessageTooLong:
|
||||
url = await rentry(tekstr.text)
|
||||
await msg.edit(f"Your translated text pasted to rentry because has long text:\n{url}")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["tts"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def tts(_, message):
|
||||
if message.reply_to_message and (message.reply_to_message.text or message.reply_to_message.caption):
|
||||
if len(message.text.split()) == 1:
|
||||
target_lang = "id"
|
||||
else:
|
||||
target_lang = message.text.split()[1]
|
||||
text = message.reply_to_message.text or message.reply_to_message.caption
|
||||
else:
|
||||
if len(message.text.split()) <= 2:
|
||||
await message.reply_text(
|
||||
"Berikan Kode bahasa yang valid.\n[Available options](https://telegra.ph/Lang-Codes-11-08).\n<b>Usage:</b> <code>/tts en <text></code>",
|
||||
)
|
||||
return
|
||||
target_lang = message.text.split(None, 2)[1]
|
||||
text = message.text.split(None, 2)[2]
|
||||
msg = await message.reply("Converting to voice...")
|
||||
try:
|
||||
tts = gTTS(text, lang=target_lang)
|
||||
tts.save(f"tts_{message.from_user.id}.mp3")
|
||||
except ValueError as err:
|
||||
await msg.edit(f"Error: <code>{str(err)}</code>")
|
||||
return
|
||||
await msg.delete()
|
||||
await msg.reply_audio(f"tts_{message.from_user.id}.mp3")
|
||||
try:
|
||||
os.remove(f"tts_{message.from_user.id}.mp3")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@app.on_message(filters.command(["tosticker", "tosticker@MissKatyRoBot"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def tostick(client, message):
|
||||
try:
|
||||
if not message.reply_to_message or not message.reply_to_message.photo:
|
||||
return await message.reply_text("Reply ke foto untuk mengubah ke sticker")
|
||||
sticker = await client.download_media(message.reply_to_message.photo.file_id, f"tostick_{message.from_user.id}.webp")
|
||||
await message.reply_sticker(sticker)
|
||||
os.remove(sticker)
|
||||
except Exception as e:
|
||||
await message.reply_text(str(e))
|
||||
|
||||
|
||||
@app.on_message(filters.command(["toimage", "toimage@MissKatyRoBot"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def topho(client, message):
|
||||
try:
|
||||
if not message.reply_to_message or not message.reply_to_message.sticker:
|
||||
return await message.reply_text("Reply ke sticker untuk mengubah ke foto")
|
||||
if message.reply_to_message.sticker.is_animated:
|
||||
return await message.reply_text("Ini sticker animasi, command ini hanya untuk sticker biasa.")
|
||||
photo = await client.download_media(message.reply_to_message.sticker.file_id, f"tostick_{message.from_user.id}.jpg")
|
||||
await message.reply_photo(photo=photo, caption="Sticker -> Image\n@MissKatyRoBot")
|
||||
|
||||
os.remove(photo)
|
||||
except Exception as e:
|
||||
await message.reply_text(str(e))
|
||||
|
||||
|
||||
@app.on_message(filters.command(["id", "id@MissKatyRoBot"], COMMAND_HANDLER))
|
||||
async def showid(client, message):
|
||||
chat_type = message.chat.type
|
||||
if chat_type == "private":
|
||||
user_id = message.chat.id
|
||||
first = message.from_user.first_name
|
||||
last = message.from_user.last_name or ""
|
||||
username = message.from_user.username
|
||||
dc_id = message.from_user.dc_id or ""
|
||||
await message.reply_text(f"<b>➲ First Name:</b> {first}\n<b>➲ Last Name:</b> {last}\n<b>➲ Username:</b> {username}\n<b>➲ Telegram ID:</b> <code>{user_id}</code>\n<b>➲ Data Centre:</b> <code>{dc_id}</code>", quote=True)
|
||||
|
||||
elif chat_type in ["group", "supergroup"]:
|
||||
_id = ""
|
||||
_id += "<b>➲ Chat ID</b>: " f"<code>{message.chat.id}</code>\n"
|
||||
if message.reply_to_message:
|
||||
_id += (
|
||||
"<b>➲ User ID</b>: "
|
||||
f"<code>{message.from_user.id if message.from_user else 'Anonymous'}</code>\n"
|
||||
"<b>➲ Replied User ID</b>: "
|
||||
f"<code>{message.reply_to_message.from_user.id if message.reply_to_message.from_user else 'Anonymous'}</code>\n"
|
||||
)
|
||||
file_info = get_file_id(message.reply_to_message)
|
||||
else:
|
||||
_id += "<b>➲ User ID</b>: " f"<code>{message.from_user.id if message.from_user else 'Anonymous'}</code>\n"
|
||||
file_info = get_file_id(message)
|
||||
if file_info:
|
||||
_id += f"<b>{file_info.message_type}</b>: " f"<code>{file_info.file_id}</code>\n"
|
||||
await message.reply_text(_id, quote=True)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["info"], COMMAND_HANDLER))
|
||||
async def who_is(client, message):
|
||||
# https://github.com/SpEcHiDe/PyroGramBot/blob/master/pyrobot/plugins/admemes/whois.py#L19
|
||||
status_message = await message.reply_text("`Fetching user info...`")
|
||||
await status_message.edit("`Processing user info...`")
|
||||
from_user = None
|
||||
from_user_id, _ = extract_user(message)
|
||||
try:
|
||||
from_user = await client.get_users(from_user_id)
|
||||
except Exception as error:
|
||||
await status_message.edit(str(error))
|
||||
return
|
||||
if from_user is None:
|
||||
return await status_message.edit("no valid user_id / message specified")
|
||||
message_out_str = ""
|
||||
message_out_str += f"<b>➲First Name:</b> {from_user.first_name}\n"
|
||||
last_name = from_user.last_name or "<b>None</b>"
|
||||
message_out_str += f"<b>➲Last Name:</b> {last_name}\n"
|
||||
message_out_str += f"<b>➲Telegram ID:</b> <code>{from_user.id}</code>\n"
|
||||
username = from_user.username or "<b>None</b>"
|
||||
dc_id = from_user.dc_id or "[User Doesnt Have A Valid DP]"
|
||||
message_out_str += f"<b>➲Data Centre:</b> <code>{dc_id}</code>\n"
|
||||
message_out_str += f"<b>➲User Name:</b> @{username}\n"
|
||||
message_out_str += f"<b>➲User 𝖫𝗂𝗇𝗄:</b> <a href='tg://user?id={from_user.id}'><b>Click Here</b></a>\n"
|
||||
if message.chat.type in (("supergroup", "channel")):
|
||||
try:
|
||||
chat_member_p = await message.chat.get_member(from_user.id)
|
||||
joined_date = datetime.fromtimestamp(chat_member_p.joined_date or time.time()).strftime("%Y.%m.%d %H:%M:%S")
|
||||
message_out_str += "<b>➲Joined this Chat on:</b> <code>" f"{joined_date}" "</code>\n"
|
||||
except UserNotParticipant:
|
||||
pass
|
||||
if chat_photo := from_user.photo:
|
||||
local_user_photo = await client.download_media(message=chat_photo.big_file_id)
|
||||
buttons = [[InlineKeyboardButton("🔐 Close", callback_data="close_data")]]
|
||||
reply_markup = InlineKeyboardMarkup(buttons)
|
||||
await message.reply_photo(photo=local_user_photo, quote=True, reply_markup=reply_markup, caption=message_out_str, disable_notification=True)
|
||||
os.remove(local_user_photo)
|
||||
else:
|
||||
buttons = [[InlineKeyboardButton("🔐 Close", callback_data="close_data")]]
|
||||
reply_markup = InlineKeyboardMarkup(buttons)
|
||||
await message.reply_text(text=message_out_str, reply_markup=reply_markup, quote=True, disable_notification=True)
|
||||
await status_message.delete()
|
||||
|
||||
|
||||
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10"}
|
||||
|
||||
|
||||
async def get_content(url):
|
||||
async with aiohttp.ClientSession() as session:
|
||||
r = await session.get(url, headers=headers)
|
||||
return await r.read()
|
||||
|
||||
|
||||
async def mdlapi(title):
|
||||
link = f"https://kuryana.vercel.app/search/q/{title}"
|
||||
async with aiohttp.ClientSession() as ses:
|
||||
async with ses.get(link) as result:
|
||||
return await result.json()
|
||||
|
||||
|
||||
@app.on_message(filters.command(["mdl"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def mdlsearch(client, message):
|
||||
if " " in message.text:
|
||||
r, title = message.text.split(None, 1)
|
||||
k = await message.reply("Sedang mencari di Database MyDramaList.. 😴")
|
||||
movies = await mdlapi(title)
|
||||
res = movies["results"]["dramas"]
|
||||
if not movies:
|
||||
return await k.edit("Tidak ada hasil ditemukan.. 😕")
|
||||
btn = [
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text=f"{movie.get('title')} ({movie.get('year')})",
|
||||
callback_data=f"mdls_{message.from_user.id}_{message.id}_{movie['slug']}",
|
||||
)
|
||||
]
|
||||
for movie in res
|
||||
]
|
||||
await k.edit(f"Ditemukan {len(movies)} query dari <code>{title}</code>", reply_markup=InlineKeyboardMarkup(btn))
|
||||
else:
|
||||
await message.reply("Berikan aku nama drama yang ingin dicari. 🤷🏻♂️")
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("^mdls"))
|
||||
@capture_err
|
||||
async def mdl_callback(bot: Client, query: CallbackQuery):
|
||||
i, user, msg_id, slug = query.data.split("_")
|
||||
if user == f"{query.from_user.id}":
|
||||
await query.message.edit_text("Permintaan kamu sedang diproses.. ")
|
||||
result = ""
|
||||
try:
|
||||
res = (await http.get(f"https://kuryana.vercel.app/id/{slug}")).json()
|
||||
result += f"<b>Title:</b> <a href='{res['data']['link']}'>{res['data']['title']}</a>\n"
|
||||
result += f"<b>AKA:</b> <code>{res['data']['others']['also_known_as']}</code>\n\n"
|
||||
result += f"<b>Rating:</b> <code>{res['data']['details']['score']}</code>\n"
|
||||
result += f"<b>Content Rating:</b> <code>{res['data']['details']['content_rating']}</code>\n"
|
||||
result += f"<b>Type:</b> <code>{res['data']['details']['type']}</code>\n"
|
||||
result += f"<b>Country:</b> <code>{res['data']['details']['country']}</code>\n"
|
||||
if res["data"]["details"]["type"] == "Movie":
|
||||
result += f"<b>Release Date:</b> <code>{res['data']['details']['release_date']}</code>\n"
|
||||
elif res["data"]["details"]["type"] == "Drama":
|
||||
result += f"<b>Episode:</b> {res['data']['details']['episodes']}\n"
|
||||
result += f"<b>Aired:</b> <code>{res['data']['details']['aired']}</code>\n"
|
||||
try:
|
||||
result += f"<b>Aired on:</b> <code>{res['data']['details']['aired_on']}</code>\n"
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
result += f"<b>Original Network:</b> <code>{res['data']['details']['original_network']}</code>\n"
|
||||
except:
|
||||
pass
|
||||
result += f"<b>Duration:</b> <code>{res['data']['details']['duration']}</code>\n"
|
||||
result += f"<b>Genre:</b> <code>{res['data']['others']['genres']}</code>\n\n"
|
||||
result += f"<b>Synopsis:</b> <code>{res['data']['synopsis']}</code>\n"
|
||||
result += f"<b>Tags:</b> <code>{res['data']['others']['tags']}</code>\n"
|
||||
btn = InlineKeyboardMarkup([[InlineKeyboardButton("🎬 Open MyDramaList", url=res["data"]["link"])]])
|
||||
await query.message.edit_text(result, reply_markup=btn)
|
||||
except Exception as e:
|
||||
await query.message.edit_text(f"<b>ERROR:</b>\n<code>{e}</code>")
|
||||
else:
|
||||
await query.answer("Tombol ini bukan untukmu", show_alert=True)
|
||||
|
||||
|
||||
# IMDB Versi Indonesia v1
|
||||
@app.on_message(filters.command(["imdb"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def imdb1_search(client, message):
|
||||
BTN = []
|
||||
if message.sender_chat:
|
||||
return await message.reply("Mohon maaf fitur tidak tersedia untuk akun channel, harap ganti ke akun biasa..")
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Berikan aku nama series atau movie yang ingin dicari. 🤷🏻♂️", quote=True)
|
||||
r, judul = message.text.split(None, 1)
|
||||
k = await message.reply("🔎 Sedang mencari di Database IMDB..", quote=True)
|
||||
msg = ""
|
||||
buttons = InlineKeyboard(row_width=4)
|
||||
try:
|
||||
r = await get_content(f"https://yasirapi.eu.org/imdb-search?q={judul}")
|
||||
res = json.loads(r).get("result")
|
||||
if not res:
|
||||
return await k.edit("Tidak ada hasil ditemukan.. 😕")
|
||||
msg += f"Ditemukan {len(res)} query dari <code>{judul}</code> ~ {message.from_user.mention}\n\n"
|
||||
for count, movie in enumerate(res, start=1):
|
||||
title = movie.get("l")
|
||||
year = f"({movie.get('y')})" if movie.get("y") else ""
|
||||
type = movie.get("q").replace("feature", "movie").capitalize()
|
||||
movieID = re.findall(r"tt(\d+)", movie.get("id"))[0]
|
||||
msg += f"{count}. {title} {year} ~ {type}\n"
|
||||
BTN.append(InlineKeyboardButton(text=count, callback_data=f"imdbid#{message.from_user.id}#{movieID}"))
|
||||
buttons.add(*BTN)
|
||||
await k.edit(msg, reply_markup=buttons)
|
||||
except Exception as err:
|
||||
await k.edit(f"Ooppss, gagal mendapatkan daftar judul di IMDb.\n\nERROR: {err}")
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("^imdbid"))
|
||||
async def imdbcb_backup(bot: Client, query: CallbackQuery):
|
||||
usr = query.message.reply_to_message
|
||||
i, userid, movie = query.data.split("#")
|
||||
if query.from_user.id != int(userid):
|
||||
return await query.answer("⚠️ Akses Ditolak!", True)
|
||||
try:
|
||||
await query.message.edit_text("Permintaan kamu sedang diproses.. ")
|
||||
url = f"https://www.imdb.com/title/tt{movie}/"
|
||||
resp = await get_content(url)
|
||||
sop = BeautifulSoup(resp, "lxml")
|
||||
r_json = json.loads(sop.find("script", attrs={"type": "application/ld+json"}).contents[0])
|
||||
res_str = ""
|
||||
type = f"<code>{r_json['@type']}</code>" if r_json.get("@type") else ""
|
||||
if r_json.get("name"):
|
||||
try:
|
||||
tahun = sop.select('ul[data-testid="hero-title-block__metadata"]')[0].find(class_="sc-8c396aa2-2 itZqyK").text
|
||||
except:
|
||||
tahun = "-"
|
||||
res_str += f"<b>📹 Judul:</b> <a href='{url}'>{r_json['name']} [{tahun}]</a> (<code>{type}</code>)\n"
|
||||
if r_json.get("alternateName"):
|
||||
res_str += f"<b>📢 AKA:</b> <code>{r_json.get('alternateName')}</code>\n\n"
|
||||
else:
|
||||
res_str += "\n"
|
||||
if sop.select('li[data-testid="title-techspec_runtime"]'):
|
||||
durasi = sop.select('li[data-testid="title-techspec_runtime"]')[0].find(class_="ipc-metadata-list-item__content-container").text
|
||||
res_str += f"<b>Durasi:</b> <code>{GoogleTranslator('auto', 'id').translate(durasi)}</code>\n"
|
||||
if r_json.get("contentRating"):
|
||||
res_str += f"<b>Kategori:</b> <code>{r_json['contentRating']}</code> \n"
|
||||
if r_json.get("aggregateRating"):
|
||||
res_str += f"<b>Peringkat:</b> <code>{r_json['aggregateRating']['ratingValue']}⭐️ dari {r_json['aggregateRating']['ratingCount']} pengguna</code> \n"
|
||||
if sop.select('li[data-testid="title-details-releasedate"]'):
|
||||
rilis = sop.select('li[data-testid="title-details-releasedate"]')[0].find(class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link").text
|
||||
rilis_url = sop.select('li[data-testid="title-details-releasedate"]')[0].find(class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link")["href"]
|
||||
res_str += f"<b>Rilis:</b> <a href='https://www.imdb.com{rilis_url}'>{rilis}</a>\n"
|
||||
if r_json.get("genre"):
|
||||
genre = "".join(f"{GENRES_EMOJI[i]} #{i.replace('-', '_').replace(' ', '_')}, " if i in GENRES_EMOJI else f"#{i.replace('-', '_').replace(' ', '_')}, " for i in r_json["genre"])
|
||||
|
||||
genre = genre[:-2]
|
||||
res_str += f"<b>Genre:</b> {genre}\n"
|
||||
if sop.select('li[data-testid="title-details-origin"]'):
|
||||
country = "".join(
|
||||
f"{demoji(country.text)} #{country.text.replace(' ', '_').replace('-', '_')}, "
|
||||
for country in sop.select('li[data-testid="title-details-origin"]')[0].findAll(class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link")
|
||||
)
|
||||
country = country[:-2]
|
||||
res_str += f"<b>Negara:</b> {country}\n"
|
||||
if sop.select('li[data-testid="title-details-languages"]'):
|
||||
language = "".join(
|
||||
f"#{lang.text.replace(' ', '_').replace('-', '_')}, " for lang in sop.select('li[data-testid="title-details-languages"]')[0].findAll(class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link")
|
||||
)
|
||||
language = language[:-2]
|
||||
res_str += f"<b>Bahasa:</b> {language}\n"
|
||||
res_str += "\n<b>🙎 Info Cast:</b>\n"
|
||||
if r_json.get("director"):
|
||||
director = ""
|
||||
for i in r_json["director"]:
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
director += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
director = director[:-2]
|
||||
res_str += f"<b>Sutradara:</b> {director}\n"
|
||||
if r_json.get("creator"):
|
||||
creator = ""
|
||||
for i in r_json["creator"]:
|
||||
if i["@type"] == "Person":
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
creator += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
creator = creator[:-2]
|
||||
res_str += f"<b>Penulis:</b> {creator}\n"
|
||||
if r_json.get("actor"):
|
||||
actors = ""
|
||||
for i in r_json["actor"]:
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
actors += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
actors = actors[:-2]
|
||||
res_str += f"<b>Pemeran:</b> {actors}\n\n"
|
||||
if r_json.get("description"):
|
||||
summary = GoogleTranslator("auto", "id").translate(r_json.get("description"))
|
||||
res_str += f"<b>📜 Plot: </b> <code>{summary}</code>\n\n"
|
||||
if r_json.get("keywords"):
|
||||
keywords = r_json["keywords"].split(",")
|
||||
key_ = ""
|
||||
for i in keywords:
|
||||
i = i.replace(" ", "_").replace("-", "_")
|
||||
key_ += f"#{i}, "
|
||||
key_ = key_[:-2]
|
||||
res_str += f"<b>🔥 Kata Kunci:</b> {key_} \n"
|
||||
if sop.select('li[data-testid="award_information"]'):
|
||||
awards = sop.select('li[data-testid="award_information"]')[0].find(class_="ipc-metadata-list-item__list-content-item").text
|
||||
res_str += f"<b>🏆 Penghargaan:</b> <code>{GoogleTranslator('auto', 'id').translate(awards)}</code>\n\n"
|
||||
else:
|
||||
res_str += "\n"
|
||||
res_str += "<b>©️ IMDb by</b> @MissKatyRoBot"
|
||||
if r_json.get("trailer"):
|
||||
trailer_url = r_json["trailer"]["url"]
|
||||
markup = InlineKeyboardMarkup([[InlineKeyboardButton("🎬 Open IMDB", url=f"https://www.imdb.com{r_json['url']}"), InlineKeyboardButton("▶️ Trailer", url=trailer_url)]])
|
||||
else:
|
||||
markup = InlineKeyboardMarkup([[InlineKeyboardButton("🎬 Open IMDB", url=f"https://www.imdb.com{r_json['url']}")]])
|
||||
if thumb := r_json.get("image"):
|
||||
try:
|
||||
await query.message.reply_photo(photo=thumb, quote=True, caption=res_str, reply_to_message_id=usr.id, reply_markup=markup)
|
||||
except (MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty):
|
||||
poster = thumb.replace(".jpg", "._V1_UX360.jpg")
|
||||
await query.message.reply_photo(photo=poster, caption=res_str, reply_to_message_id=usr.id, reply_markup=markup)
|
||||
except Exception:
|
||||
await query.message.reply(res_str, reply_markup=markup, disable_web_page_preview=False, reply_to_message_id=usr.id)
|
||||
await query.message.delete()
|
||||
else:
|
||||
await query.message.edit(res_str, reply_markup=markup, disable_web_page_preview=False)
|
||||
await query.answer()
|
||||
except MessageNotModified:
|
||||
pass
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await query.message.edit_text(f"<b>ERROR:</b>\n<code>{exc}</code>")
|
||||
|
||||
|
||||
# IMDB Versi English
|
||||
@app.on_message(filters.command(["imdb_en"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def imdb_en_search(client, message):
|
||||
BTN = []
|
||||
if message.sender_chat:
|
||||
return await message.reply("This feature not available for channel.")
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Give movie name or series. Ex: <code>/imdb_en soul</code>. 🤷🏻♂️", quote=True)
|
||||
r, title = message.text.split(None, 1)
|
||||
k = await message.reply("Searching Movie/Series in IMDB Database.. 😴", quote=True)
|
||||
msg = ""
|
||||
buttons = InlineKeyboard(row_width=4)
|
||||
try:
|
||||
r = await get_content(f"https://yasirapi.eu.org/imdb-search?q={title}")
|
||||
res = json.loads(r).get("result")
|
||||
if not res:
|
||||
return await k.edit("Sad, No Result.. 😕")
|
||||
msg = f"Found {len(res)} result from <code>{title}</code> ~ {message.from_user.mention}\n\n"
|
||||
for count, movie in enumerate(res, start=1):
|
||||
titles = movie.get("l")
|
||||
year = f"({movie.get('y')})" if movie.get("y") else ""
|
||||
type = movie.get("qid").replace("feature", "movie").capitalize()
|
||||
movieID = re.findall(r"tt(\d+)", movie.get("id"))[0]
|
||||
msg += f"{count}. {titles} {year} ~ {type}\n"
|
||||
BTN.append(InlineKeyboardButton(text=count, callback_data=f"imdben#{message.from_user.id}#{movieID}"))
|
||||
buttons.add(*BTN)
|
||||
await k.edit(msg, reply_markup=buttons)
|
||||
except Exception as err:
|
||||
await k.edit(f"Ooppss, failed get movie list from IMDb.\n\nERROR: {err}")
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex("^imdben"))
|
||||
@capture_err
|
||||
async def imdb_en_callback(bot: Client, query: CallbackQuery):
|
||||
usr = query.message.reply_to_message
|
||||
i, userid, movie = query.data.split("#")
|
||||
if query.from_user.id != int(userid):
|
||||
return await query.answer("⚠️ Access Denied!", True)
|
||||
await query.message.edit_text("<i>⏳ Processing your request..</i>")
|
||||
try:
|
||||
url = f"https://www.imdb.com/title/tt{movie}/"
|
||||
resp = await get_content(url)
|
||||
sop = BeautifulSoup(resp, "lxml")
|
||||
r_json = json.loads(sop.find("script", attrs={"type": "application/ld+json"}).contents[0])
|
||||
res_str = ""
|
||||
type = f"<code>{r_json['@type']}</code>" if r_json.get("@type") else ""
|
||||
if r_json.get("name"):
|
||||
try:
|
||||
tahun = sop.select('ul[data-testid="hero-title-block__metadata"]')[0].find(class_="sc-8c396aa2-2 itZqyK").text
|
||||
except:
|
||||
tahun = "-"
|
||||
res_str += f"<b>📹 Title:</b> <a href='{url}'>{r_json['name']} [{tahun}]</a> (<code>{type}</code>)\n"
|
||||
if r_json.get("alternateName"):
|
||||
res_str += f"<b>📢 AKA:</b> <code>{r_json.get('alternateName')}</code>\n\n"
|
||||
else:
|
||||
res_str += "\n"
|
||||
if sop.select('li[data-testid="title-techspec_runtime"]'):
|
||||
durasi = sop.select('li[data-testid="title-techspec_runtime"]')[0].find(class_="ipc-metadata-list-item__content-container").text
|
||||
res_str += f"<b>Duration:</b> <code>{durasi}</code>\n"
|
||||
if r_json.get("contentRating"):
|
||||
res_str += f"<b>Category:</b> <code>{r_json['contentRating']}</code> \n"
|
||||
if r_json.get("aggregateRating"):
|
||||
res_str += f"<b>Rating:</b> <code>{r_json['aggregateRating']['ratingValue']}⭐️ from {r_json['aggregateRating']['ratingCount']} user</code> \n"
|
||||
if sop.select('li[data-testid="title-details-releasedate"]'):
|
||||
rilis = sop.select('li[data-testid="title-details-releasedate"]')[0].find(class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link").text
|
||||
rilis_url = sop.select('li[data-testid="title-details-releasedate"]')[0].find(class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link")["href"]
|
||||
res_str += f"<b>Release Data:</b> <a href='https://www.imdb.com{rilis_url}'>{rilis}</a>\n"
|
||||
if r_json.get("genre"):
|
||||
genre = "".join(f"{GENRES_EMOJI[i]} #{i.replace('-', '_').replace(' ', '_')}, " if i in GENRES_EMOJI else f"#{i.replace('-', '_').replace(' ', '_')}, " for i in r_json["genre"])
|
||||
|
||||
genre = genre[:-2]
|
||||
res_str += f"<b>Genre:</b> {genre}\n"
|
||||
if sop.select('li[data-testid="title-details-origin"]'):
|
||||
country = "".join(
|
||||
f"{demoji(country.text)} #{country.text.replace(' ', '_').replace('-', '_')}, "
|
||||
for country in sop.select('li[data-testid="title-details-origin"]')[0].findAll(class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link")
|
||||
)
|
||||
country = country[:-2]
|
||||
res_str += f"<b>Country:</b> {country}\n"
|
||||
if sop.select('li[data-testid="title-details-languages"]'):
|
||||
language = "".join(
|
||||
f"#{lang.text.replace(' ', '_').replace('-', '_')}, " for lang in sop.select('li[data-testid="title-details-languages"]')[0].findAll(class_="ipc-metadata-list-item__list-content-item ipc-metadata-list-item__list-content-item--link")
|
||||
)
|
||||
language = language[:-2]
|
||||
res_str += f"<b>Language:</b> {language}\n"
|
||||
res_str += "\n<b>🙎 Cast Info:</b>\n"
|
||||
if r_json.get("director"):
|
||||
director = ""
|
||||
for i in r_json["director"]:
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
director += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
director = director[:-2]
|
||||
res_str += f"<b>Director:</b> {director}\n"
|
||||
if r_json.get("creator"):
|
||||
creator = ""
|
||||
for i in r_json["creator"]:
|
||||
if i["@type"] == "Person":
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
creator += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
creator = creator[:-2]
|
||||
res_str += f"<b>Penulis:</b> {creator}\n"
|
||||
if r_json.get("actor"):
|
||||
actors = ""
|
||||
for i in r_json["actor"]:
|
||||
name = i["name"]
|
||||
url = i["url"]
|
||||
actors += f"<a href='https://www.imdb.com{url}'>{name}</a>, "
|
||||
actors = actors[:-2]
|
||||
res_str += f"<b>Stars:</b> {actors}\n\n"
|
||||
if r_json.get("description"):
|
||||
res_str += f"<b>📜 Summary: </b> <code>{r_json['description'].replace(' ', ' ')}</code>\n\n"
|
||||
if r_json.get("keywords"):
|
||||
keywords = r_json["keywords"].split(",")
|
||||
key_ = ""
|
||||
for i in keywords:
|
||||
i = i.replace(" ", "_").replace("-", "_")
|
||||
key_ += f"#{i}, "
|
||||
key_ = key_[:-2]
|
||||
res_str += f"<b>🔥 Keywords:</b> {key_} \n"
|
||||
if sop.select('li[data-testid="award_information"]'):
|
||||
awards = sop.select('li[data-testid="award_information"]')[0].find(class_="ipc-metadata-list-item__list-content-item").text
|
||||
res_str += f"<b>🏆 Awards:</b> <code>{awards}</code>\n\n"
|
||||
else:
|
||||
res_str += "\n"
|
||||
res_str += "<b>©️ IMDb by</b> @MissKatyRoBot"
|
||||
if r_json.get("trailer"):
|
||||
trailer_url = r_json["trailer"]["url"]
|
||||
markup = InlineKeyboardMarkup([[InlineKeyboardButton("🎬 Open IMDB", url=f"https://www.imdb.com{r_json['url']}"), InlineKeyboardButton("▶️ Trailer", url=trailer_url)]])
|
||||
else:
|
||||
markup = InlineKeyboardMarkup([[InlineKeyboardButton("🎬 Open IMDB", url=f"https://www.imdb.com{r_json['url']}")]])
|
||||
if thumb := r_json.get("image"):
|
||||
try:
|
||||
await query.message.reply_photo(photo=thumb, quote=True, caption=res_str, reply_to_message_id=usr.id, reply_markup=markup)
|
||||
except (MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty):
|
||||
poster = thumb.replace(".jpg", "._V1_UX360.jpg")
|
||||
await query.message.reply_photo(photo=poster, caption=res_str, reply_to_message_id=usr.id, reply_markup=markup)
|
||||
except Exception:
|
||||
await query.message.reply(res_str, reply_markup=markup, disable_web_page_preview=False, reply_to_message_id=usr.id)
|
||||
await query.message.delete()
|
||||
else:
|
||||
await query.message.edit(res_str, reply_markup=markup, disable_web_page_preview=False)
|
||||
await query.answer()
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await query.message.edit_text(f"<b>ERROR:</b>\n<code>{exc}</code>")
|
||||
213
misskaty/plugins/nightmode.py
Normal file
213
misskaty/plugins/nightmode.py
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
# Auto Close and Open Group, I dont have time to add Database Support
|
||||
from pyrogram.types import ChatPermissions
|
||||
from pyrogram import Client, __version__, filters
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
import pytz
|
||||
import traceback
|
||||
from misskaty import app
|
||||
from datetime import datetime
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery
|
||||
from misskaty.vars import LOG_CHANNEL
|
||||
|
||||
|
||||
# Check calculate how long it will take to Ramadhan
|
||||
def puasa():
|
||||
now = datetime.now(pytz.timezone("Asia/Jakarta"))
|
||||
tahun = now.strftime("%Y")
|
||||
bulan = now.strftime("%m")
|
||||
tgl = now.strftime("%d")
|
||||
jam = now.strftime("%H")
|
||||
menit = now.strftime("%M")
|
||||
detik = now.strftime("%S")
|
||||
x = datetime(int(tahun), int(bulan), int(tgl), int(jam), int(menit), int(detik))
|
||||
y = datetime(2022, 4, 2, 0, 0, 0)
|
||||
return y - x
|
||||
|
||||
|
||||
async def job_close():
|
||||
now = datetime.now(pytz.timezone("Asia/Jakarta"))
|
||||
days = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
|
||||
month = [
|
||||
"Unknown",
|
||||
"Januari",
|
||||
"Februari",
|
||||
"Maret",
|
||||
"April",
|
||||
"Mei",
|
||||
"Juni",
|
||||
"Juli",
|
||||
"Agustus",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"Desember",
|
||||
]
|
||||
tgl = now.strftime("%d")
|
||||
tahun = now.strftime("%Y")
|
||||
jam = now.strftime("%H:%M")
|
||||
try:
|
||||
# version = check_output(["git log -1 --date=format:v%y.%m%d.%H%M --pretty=format:%cd"], shell=True).decode()
|
||||
reply_markup = InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(text="❤️", callback_data="nightmd")]]
|
||||
)
|
||||
await app.set_chat_permissions(
|
||||
-1001128045651,
|
||||
ChatPermissions(can_send_messages=False, can_invite_users=True),
|
||||
)
|
||||
await app.send_message(
|
||||
-1001128045651,
|
||||
f"📆 {days[now.weekday()]}, {tgl} {month[now.month]} {tahun}\n⏰ Jam : {jam}\n\n**🌗 Mode Malam Aktif**\n`Grup ditutup dan semua member tidak akan bisa mengirim pesan. Selamat beristirahat dan bermimpi indah !!`",
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await app.send_message(LOG_CHANNEL, f"ERROR:\n<code>{exc}</code>")
|
||||
|
||||
|
||||
async def job_close_ymoviez():
|
||||
now = datetime.now(pytz.timezone("Asia/Jakarta"))
|
||||
days = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
|
||||
month = [
|
||||
"Unknown",
|
||||
"Januari",
|
||||
"Februari",
|
||||
"Maret",
|
||||
"April",
|
||||
"Mei",
|
||||
"Juni",
|
||||
"Juli",
|
||||
"Agustus",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"Desember",
|
||||
]
|
||||
tgl = now.strftime("%d")
|
||||
tahun = now.strftime("%Y")
|
||||
jam = now.strftime("%H:%M")
|
||||
try:
|
||||
# version = check_output(["git log -1 --date=format:v%y.%m%d.%H%M --pretty=format:%cd"], shell=True).decode()
|
||||
reply_markup = InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(text="❤️", callback_data="nightmd")]]
|
||||
)
|
||||
await app.set_chat_permissions(
|
||||
-1001255283935,
|
||||
ChatPermissions(can_send_messages=False, can_invite_users=True),
|
||||
)
|
||||
await app.send_message(
|
||||
-1001255283935,
|
||||
f"📆 {days[now.weekday()]}, {tgl} {month[now.month]} {tahun}\n⏰ Jam : {jam}\n\n**🌗 Mode Malam Aktif**\n`Grup ditutup hingga jam 9 pagi. Selamat beristirahat.....`",
|
||||
)
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await app.send_message(LOG_CHANNEL, f"ERROR:\n<code>{exc}</code>")
|
||||
|
||||
|
||||
async def job_open():
|
||||
now = datetime.now(pytz.timezone("Asia/Jakarta"))
|
||||
days = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
|
||||
month = [
|
||||
"Unknown",
|
||||
"Januari",
|
||||
"Februari",
|
||||
"Maret",
|
||||
"April",
|
||||
"Mei",
|
||||
"Juni",
|
||||
"Juli",
|
||||
"Agustus",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"Desember",
|
||||
]
|
||||
tgl = now.strftime("%d")
|
||||
tahun = now.strftime("%Y")
|
||||
jam = now.strftime("%H:%M")
|
||||
try:
|
||||
# version = check_output(["git log -1 --date=format:v%y.%m%d.%H%M --pretty=format:%cd"], shell=True).decode()
|
||||
reply_markup = InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(text="❤️", callback_data="nightmd")]]
|
||||
)
|
||||
await app.set_chat_permissions(
|
||||
-1001128045651,
|
||||
ChatPermissions(
|
||||
can_send_messages=True,
|
||||
can_send_media_messages=True,
|
||||
can_invite_users=True,
|
||||
can_add_web_page_previews=True,
|
||||
can_send_other_messages=False,
|
||||
),
|
||||
)
|
||||
await app.send_message(
|
||||
-1001128045651,
|
||||
f"📆 {days[now.weekday()]}, {tgl} {month[now.month]} {tahun}\n⏰ {jam}`\n\n🌗 Mode Malam Selesai\nSelamat pagi, grup kini telah dibuka semoga hari-harimu menyenangkan.`",
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await app.send_message(LOG_CHANNEL, f"ERROR:\n<code>{exc}</code>")
|
||||
|
||||
|
||||
async def job_open_ymoviez():
|
||||
now = datetime.now(pytz.timezone("Asia/Jakarta"))
|
||||
days = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
|
||||
month = [
|
||||
"Unknown",
|
||||
"Januari",
|
||||
"Februari",
|
||||
"Maret",
|
||||
"April",
|
||||
"Mei",
|
||||
"Juni",
|
||||
"Juli",
|
||||
"Agustus",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"Desember",
|
||||
]
|
||||
tgl = now.strftime("%d")
|
||||
tahun = now.strftime("%Y")
|
||||
jam = now.strftime("%H:%M")
|
||||
try:
|
||||
# version = check_output(["git log -1 --date=format:v%y.%m%d.%H%M --pretty=format:%cd"], shell=True).decode()
|
||||
reply_markup = InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(text="❤️", callback_data="nightmd")]]
|
||||
)
|
||||
await app.set_chat_permissions(
|
||||
-1001255283935,
|
||||
ChatPermissions(
|
||||
can_send_messages=True,
|
||||
can_send_media_messages=True,
|
||||
can_invite_users=True,
|
||||
can_add_web_page_previews=True,
|
||||
can_send_other_messages=True,
|
||||
),
|
||||
)
|
||||
await app.send_message(
|
||||
-1001255283935,
|
||||
f"📆 {days[now.weekday()]}, {tgl} {month[now.month]} {tahun}\n⏰ {jam}`\n\n🌗 Mode Malam Selesai\nSelamat pagi, grup kini telah dibuka semoga hari-harimu menyenangkan.`",
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await app.send_message(LOG_CHANNEL, f"ERROR:\n<code>{exc}</code>")
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^nightmd$"))
|
||||
async def _callbackanightmd(c: Client, q: CallbackQuery):
|
||||
# version = check_output(["git log -1 --date=format:v%y.%m%d.%H%M --pretty=format:%cd"], shell=True).decode()
|
||||
await q.answer(
|
||||
f"🔖 Hai, Aku MissKatyRoBot dibuat menggunakan Framework Pyrogram v{__version__} dan Python 3.10.\n\nMau buat bot seperti ini? Yuuk belajar di @botindonesia\nOwner: @YasirArisM",
|
||||
show_alert=True,
|
||||
cache_time=21600,
|
||||
)
|
||||
|
||||
|
||||
scheduler = AsyncIOScheduler(timezone="Asia/Jakarta")
|
||||
scheduler.add_job(job_close, trigger="cron", hour=22, minute=0)
|
||||
scheduler.add_job(job_close_ymoviez, trigger="cron", hour=22, minute=0)
|
||||
scheduler.add_job(job_open, trigger="cron", hour=6, minute=0)
|
||||
scheduler.add_job(job_open_ymoviez, trigger="cron", hour=10, minute=0)
|
||||
scheduler.start()
|
||||
38
misskaty/plugins/ocr.py
Normal file
38
misskaty/plugins/ocr.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import os
|
||||
from pyrogram import filters
|
||||
from telegraph import upload_file
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from misskaty import app
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.helper.http import http
|
||||
|
||||
__MODULE__ = "OCR"
|
||||
__HELP__ = "/ocr [reply to photo] - Read Text From Image"
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ocr"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def ocr(_, message):
|
||||
reply = message.reply_to_message
|
||||
if not reply or not reply.photo and not reply.sticker:
|
||||
return await message.reply_text(
|
||||
f"Reply photo with /{message.command[0]} command"
|
||||
)
|
||||
msg = await message.reply("Reading image...")
|
||||
try:
|
||||
file_path = await reply.download()
|
||||
if reply.sticker:
|
||||
file_path = await reply.download(f"ocr{message.from_user.id}.jpg")
|
||||
response = upload_file(file_path)
|
||||
url = f"https://telegra.ph{response[0]}"
|
||||
req = (
|
||||
await http.get(
|
||||
f"https://script.google.com/macros/s/AKfycbwURISN0wjazeJTMHTPAtxkrZTWTpsWIef5kxqVGoXqnrzdLdIQIfLO7jsR5OQ5GO16/exec?url={url}",
|
||||
follow_redirects=True
|
||||
)
|
||||
).json()
|
||||
await msg.edit(f"Hasil OCR:\n<code>{req['text']}</code>")
|
||||
os.remove(file_path)
|
||||
except Exception as e:
|
||||
await msg.edit(str(e))
|
||||
os.remove(file_path)
|
||||
195
misskaty/plugins/paste.py
Normal file
195
misskaty/plugins/paste.py
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
from os import remove
|
||||
from re import compile as compiles
|
||||
from misskaty.helper.http import http
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from json import loads as json_loads
|
||||
from misskaty import app
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from misskaty.helper.tools import rentry
|
||||
|
||||
__MODULE__ = "Paste"
|
||||
__HELP__ = """
|
||||
/paste [Text/Reply To Message] - Post text to Rentry using markdown style.
|
||||
/temp_paste [Text/Reply To Message] - Post text to tempaste.com using html style.
|
||||
"""
|
||||
|
||||
# Size Checker for Limit
|
||||
def humanbytes(size: int):
|
||||
"""Convert Bytes To Bytes So That Human Can Read It"""
|
||||
if not isinstance(command, int):
|
||||
try:
|
||||
size = size
|
||||
except ValueError:
|
||||
size = None
|
||||
if not size:
|
||||
return "0 B"
|
||||
size = int(size)
|
||||
power = 2**10
|
||||
raised_to_pow = 0
|
||||
dict_power_n = {
|
||||
0: "",
|
||||
1: "K",
|
||||
2: "M",
|
||||
3: "G",
|
||||
4: "T",
|
||||
5: "P",
|
||||
6: "E",
|
||||
7: "Z",
|
||||
8: "Y",
|
||||
}
|
||||
while size > power:
|
||||
size /= power
|
||||
raised_to_pow += 1
|
||||
try:
|
||||
real_size = f"{str(round(size, 2))} {dict_power_n[raised_to_pow]}B"
|
||||
except KeyError:
|
||||
real_size = "Can't Define Real Size !"
|
||||
return real_size
|
||||
|
||||
|
||||
# Pattern if extension supported, PR if want to add more
|
||||
pattern = compiles(r"^text/|json$|yaml$|xml$|toml$|x-sh$|x-shellscript$|x-subrip$")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["paste"], COMMAND_HANDLER))
|
||||
async def create(_, message):
|
||||
reply = message.reply_to_message
|
||||
target = str(message.command[0]).split("@", maxsplit=1)[0]
|
||||
if not reply and len(message.command) < 2:
|
||||
return await message.reply_text(
|
||||
f"**Reply To A Message With /{target} or with command**"
|
||||
)
|
||||
|
||||
msg = await message.reply_text("`Pasting to Rentry...`")
|
||||
data = ""
|
||||
limit = 1024 * 1024
|
||||
if reply and reply.document:
|
||||
if reply.document.file_size > limit:
|
||||
return await msg.edit(
|
||||
f"**You can only paste files smaller than {humanbytes(limit)}.**"
|
||||
)
|
||||
if not pattern.search(reply.document.mime_type):
|
||||
return await msg.edit("**Only text files can be pasted.**")
|
||||
file = await reply.download()
|
||||
try:
|
||||
with open(file, "r") as text:
|
||||
data = text.read()
|
||||
remove(file)
|
||||
except UnicodeDecodeError:
|
||||
try:
|
||||
remove(file)
|
||||
except:
|
||||
pass
|
||||
return await msg.edit("`File Not Supported !`")
|
||||
elif reply and (reply.text or reply.caption):
|
||||
data = reply.text.markdown or reply.caption.markdown
|
||||
elif not reply and len(message.command) >= 2:
|
||||
data = message.text.split(None, 1)[1]
|
||||
|
||||
if message.from_user:
|
||||
if message.from_user.username:
|
||||
uname = f"@{message.from_user.username}"
|
||||
else:
|
||||
uname = (
|
||||
f"[{message.from_user.first_name}](tg://user?id={message.from_user.id})"
|
||||
)
|
||||
else:
|
||||
uname = message.sender_chat.title
|
||||
|
||||
try:
|
||||
url = await rentry(data)
|
||||
except Exception as e:
|
||||
await msg.edit(f"`{e}`")
|
||||
return
|
||||
|
||||
if not url:
|
||||
return await msg.edit("Text Too Short Or File Problems")
|
||||
button = [[InlineKeyboardButton("Open Link", url=url)]]
|
||||
button.append(
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"Share Link", url=f"https://telegram.me/share/url?url={url}"
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
pasted = f"**Successfully pasted your data to Rentry<a href='{url}'>.</a>\n\nPaste by {uname}**"
|
||||
await msg.edit(pasted, reply_markup=InlineKeyboardMarkup(button))
|
||||
|
||||
|
||||
@app.on_message(filters.command(["temp_paste"], COMMAND_HANDLER))
|
||||
async def create(_, message):
|
||||
reply = message.reply_to_message
|
||||
target = str(message.command[0]).split("@", maxsplit=1)[0]
|
||||
if not reply and len(message.command) < 2:
|
||||
return await message.reply_text(
|
||||
f"**Reply To A Message With /{target} or with command**"
|
||||
)
|
||||
|
||||
msg = await message.reply_text("`Pasting to TempPaste...`")
|
||||
data = ""
|
||||
limit = 1024 * 1024
|
||||
if reply and reply.document:
|
||||
if reply.document.file_size > limit:
|
||||
return await msg.edit(
|
||||
f"**You can only paste files smaller than {humanbytes(limit)}.**"
|
||||
)
|
||||
if not pattern.search(reply.document.mime_type):
|
||||
return await msg.edit("**Only text files can be pasted.**")
|
||||
file = await reply.download()
|
||||
try:
|
||||
with open(file, "r") as text:
|
||||
data = text.read()
|
||||
remove(file)
|
||||
except UnicodeDecodeError:
|
||||
try:
|
||||
remove(file)
|
||||
except:
|
||||
pass
|
||||
return await msg.edit("`File Not Supported !`")
|
||||
elif reply and (reply.text or reply.caption):
|
||||
data = reply.text.html or reply.caption.html
|
||||
elif not reply and len(message.command) >= 2:
|
||||
data = message.text.split(None, 1)[1]
|
||||
|
||||
if message.from_user:
|
||||
if message.from_user.username:
|
||||
uname = f"@{message.from_user.username}"
|
||||
else:
|
||||
uname = (
|
||||
f"[{message.from_user.first_name}](tg://user?id={message.from_user.id})"
|
||||
)
|
||||
else:
|
||||
uname = message.sender_chat.title
|
||||
|
||||
try:
|
||||
req = await http.post(
|
||||
"https://tempaste.com/api/v1/create-paste/",
|
||||
data={
|
||||
"api_key": "xnwuzXubxk3kCUz9Q2pjMVR8xeTO4t",
|
||||
"title": "MissKaty Paste",
|
||||
"paste_content": data,
|
||||
"visibility": "public",
|
||||
"expiry_date_type": "months",
|
||||
"expiry_date": 12,
|
||||
},
|
||||
)
|
||||
url = f"https://tempaste.com/{json_loads(req.text)['url']}"
|
||||
except Exception as e:
|
||||
await msg.edit(f"`{e}`")
|
||||
return
|
||||
|
||||
if not url:
|
||||
return await msg.edit("Text Too Short Or File Problems")
|
||||
button = [[InlineKeyboardButton("Open Link", url=url)]]
|
||||
button.append(
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"Share Link", url=f"https://telegram.me/share/url?url={url}"
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
pasted = f"**Successfully pasted your data to Tempaste<a href='{url}'>.</a>\n\nPaste by {uname}**"
|
||||
await msg.edit(pasted, reply_markup=InlineKeyboardMarkup(button))
|
||||
55
misskaty/plugins/ping.py
Normal file
55
misskaty/plugins/ping.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import time
|
||||
from re import findall, MULTILINE
|
||||
from asyncio import Lock
|
||||
from pyrogram import filters
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from misskaty import app, botStartTime
|
||||
from misskaty.helper.human_read import get_readable_time
|
||||
from subprocess import run as srun
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ping"], COMMAND_HANDLER))
|
||||
async def ping(_, message):
|
||||
currentTime = get_readable_time(time.time() - botStartTime)
|
||||
start_t = time.time()
|
||||
rm = await message.reply_text("🐱 Pong!!...")
|
||||
end_t = time.time()
|
||||
time_taken_s = round(end_t - start_t, 3)
|
||||
try:
|
||||
await rm.edit(
|
||||
f"<b>🐈 MissKatyBot online.</b>\n\n<b>Ping:</b> <code>{time_taken_s} detik</code>\n<b>Uptime:</b> <code>{currentTime}</code>"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ping_dc"], COMMAND_HANDLER))
|
||||
async def ping_handler(_, message):
|
||||
m = await message.reply("Pinging datacenters...")
|
||||
async with Lock():
|
||||
ips = {
|
||||
"dc1": "149.154.175.53",
|
||||
"dc2": "149.154.167.51",
|
||||
"dc3": "149.154.175.100",
|
||||
"dc4": "149.154.167.91",
|
||||
"dc5": "91.108.56.130",
|
||||
}
|
||||
text = "**Pings:**\n"
|
||||
|
||||
for dc, ip in ips.items():
|
||||
try:
|
||||
shell = srun(
|
||||
["ping", "-c", "1", "-W", "2", ip],
|
||||
text=True,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
resp_time = findall(r"time=.+m?s", shell.stdout, MULTILINE)[0].replace(
|
||||
"time=", ""
|
||||
)
|
||||
|
||||
text += f" **{dc.upper()}:** {resp_time} ✅\n"
|
||||
except Exception:
|
||||
# There's a cross emoji here, but it's invisible.
|
||||
text += f" **{dc.upper}:** ❌\n"
|
||||
await m.edit(text)
|
||||
280
misskaty/plugins/quotly.py
Normal file
280
misskaty/plugins/quotly.py
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
from pyrogram import Client, filters
|
||||
from pyrogram.types import Message
|
||||
from misskaty import app
|
||||
from misskaty.helper.http import http
|
||||
from io import BytesIO
|
||||
|
||||
__MODULE__ = "Fun"
|
||||
__HELP__ = """
|
||||
/q [int] - Generate quotly from message
|
||||
/memify [text] - Reply to sticker to give text on sticker.
|
||||
"""
|
||||
|
||||
|
||||
class QuotlyException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
async def get_message_sender_id(m: Message):
|
||||
if m.forward_date:
|
||||
if m.forward_sender_name:
|
||||
return 1
|
||||
elif m.forward_from:
|
||||
return m.forward_from.id
|
||||
elif m.forward_from_chat:
|
||||
return m.forward_from_chat.id
|
||||
else:
|
||||
return 1
|
||||
elif m.from_user:
|
||||
return m.from_user.id
|
||||
elif m.sender_chat:
|
||||
return m.sender_chat.id
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
async def get_message_sender_name(m: Message):
|
||||
if m.forward_date:
|
||||
if m.forward_sender_name:
|
||||
return m.forward_sender_name
|
||||
elif m.forward_from:
|
||||
return (
|
||||
f"{m.forward_from.first_name} {m.forward_from.last_name}"
|
||||
if m.forward_from.last_name
|
||||
else m.forward_from.first_name
|
||||
)
|
||||
|
||||
elif m.forward_from_chat:
|
||||
return m.forward_from_chat.title
|
||||
else:
|
||||
return ""
|
||||
elif m.from_user:
|
||||
if m.from_user.last_name:
|
||||
return f"{m.from_user.first_name} {m.from_user.last_name}"
|
||||
else:
|
||||
return m.from_user.first_name
|
||||
elif m.sender_chat:
|
||||
return m.sender_chat.title
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
async def get_custom_emoji(m: Message):
|
||||
if m.forward_date:
|
||||
return (
|
||||
""
|
||||
if m.forward_sender_name
|
||||
or not m.forward_from
|
||||
and m.forward_from_chat
|
||||
or not m.forward_from
|
||||
else m.forward_from.emoji_status.custom_emoji_id
|
||||
)
|
||||
|
||||
return m.from_user.emoji_status.custom_emoji_id if m.from_user else ""
|
||||
|
||||
|
||||
async def get_message_sender_username(m: Message):
|
||||
if m.forward_date:
|
||||
if (
|
||||
not m.forward_sender_name
|
||||
and not m.forward_from
|
||||
and m.forward_from_chat
|
||||
and m.forward_from_chat.username
|
||||
):
|
||||
return m.forward_from_chat.username
|
||||
elif (
|
||||
not m.forward_sender_name
|
||||
and not m.forward_from
|
||||
and m.forward_from_chat
|
||||
or m.forward_sender_name
|
||||
or not m.forward_from
|
||||
):
|
||||
return ""
|
||||
else:
|
||||
return m.forward_from.username or ""
|
||||
elif m.from_user and m.from_user.username:
|
||||
return m.from_user.username
|
||||
elif (
|
||||
m.from_user or m.sender_chat and not m.sender_chat.username or not m.sender_chat
|
||||
):
|
||||
return ""
|
||||
else:
|
||||
return m.sender_chat.username
|
||||
|
||||
|
||||
async def get_message_sender_photo(m: Message):
|
||||
if m.forward_date:
|
||||
if (
|
||||
not m.forward_sender_name
|
||||
and not m.forward_from
|
||||
and m.forward_from_chat
|
||||
and m.forward_from_chat.photo
|
||||
):
|
||||
return {
|
||||
"small_file_id": m.forward_from_chat.photo.small_file_id,
|
||||
"small_photo_unique_id": m.forward_from_chat.photo.small_photo_unique_id,
|
||||
"big_file_id": m.forward_from_chat.photo.big_file_id,
|
||||
"big_photo_unique_id": m.forward_from_chat.photo.big_photo_unique_id,
|
||||
}
|
||||
elif (
|
||||
not m.forward_sender_name
|
||||
and not m.forward_from
|
||||
and m.forward_from_chat
|
||||
or m.forward_sender_name
|
||||
or not m.forward_from
|
||||
):
|
||||
return ""
|
||||
else:
|
||||
return (
|
||||
{
|
||||
"small_file_id": m.forward_from.photo.small_file_id,
|
||||
"small_photo_unique_id": m.forward_from.photo.small_photo_unique_id,
|
||||
"big_file_id": m.forward_from.photo.big_file_id,
|
||||
"big_photo_unique_id": m.forward_from.photo.big_photo_unique_id,
|
||||
}
|
||||
if m.forward_from.photo
|
||||
else ""
|
||||
)
|
||||
|
||||
elif m.from_user and m.from_user.photo:
|
||||
return {
|
||||
"small_file_id": m.from_user.photo.small_file_id,
|
||||
"small_photo_unique_id": m.from_user.photo.small_photo_unique_id,
|
||||
"big_file_id": m.from_user.photo.big_file_id,
|
||||
"big_photo_unique_id": m.from_user.photo.big_photo_unique_id,
|
||||
}
|
||||
elif m.from_user or m.sender_chat and not m.sender_chat.photo or not m.sender_chat:
|
||||
return ""
|
||||
else:
|
||||
return {
|
||||
"small_file_id": m.sender_chat.photo.small_file_id,
|
||||
"small_photo_unique_id": m.sender_chat.photo.small_photo_unique_id,
|
||||
"big_file_id": m.sender_chat.photo.big_file_id,
|
||||
"big_photo_unique_id": m.sender_chat.photo.big_photo_unique_id,
|
||||
}
|
||||
|
||||
|
||||
async def get_text_or_caption(m: Message):
|
||||
if m.text:
|
||||
return m.text
|
||||
elif m.caption:
|
||||
return m.caption
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
async def pyrogram_to_quotly(messages):
|
||||
if not isinstance(messages, list):
|
||||
messages = [messages]
|
||||
payload = {
|
||||
"type": "quote",
|
||||
"format": "png",
|
||||
"backgroundColor": "#1b1429",
|
||||
"messages": [],
|
||||
}
|
||||
|
||||
for message in messages:
|
||||
the_message_dict_to_append = {}
|
||||
if message.entities:
|
||||
the_message_dict_to_append["entities"] = [
|
||||
{
|
||||
"type": entity.type.name.lower(),
|
||||
"offset": entity.offset,
|
||||
"length": entity.length,
|
||||
}
|
||||
for entity in message.entities
|
||||
]
|
||||
elif message.caption_entities:
|
||||
the_message_dict_to_append["entities"] = [
|
||||
{
|
||||
"type": entity.type.name.lower(),
|
||||
"offset": entity.offset,
|
||||
"length": entity.length,
|
||||
}
|
||||
for entity in message.caption_entities
|
||||
]
|
||||
else:
|
||||
the_message_dict_to_append["entities"] = []
|
||||
the_message_dict_to_append["chatId"] = await get_message_sender_id(message)
|
||||
the_message_dict_to_append["text"] = await get_text_or_caption(message)
|
||||
the_message_dict_to_append["avatar"] = True
|
||||
the_message_dict_to_append["from"] = {}
|
||||
the_message_dict_to_append["from"]["id"] = await get_message_sender_id(message)
|
||||
the_message_dict_to_append["from"]["name"] = await get_message_sender_name(
|
||||
message
|
||||
)
|
||||
the_message_dict_to_append["from"][
|
||||
"username"
|
||||
] = await get_message_sender_username(message)
|
||||
the_message_dict_to_append["from"]["type"] = message.chat.type.name.lower()
|
||||
the_message_dict_to_append["from"]["photo"] = await get_message_sender_photo(
|
||||
message
|
||||
)
|
||||
if message.reply_to_message:
|
||||
the_message_dict_to_append["replyMessage"] = {
|
||||
"name": await get_message_sender_name(message.reply_to_message),
|
||||
"text": await get_text_or_caption(message.reply_to_message),
|
||||
"chatId": await get_message_sender_id(message.reply_to_message),
|
||||
}
|
||||
else:
|
||||
the_message_dict_to_append["replyMessage"] = {}
|
||||
payload["messages"].append(the_message_dict_to_append)
|
||||
r = await http.post("https://bot.lyo.su/quote/generate.png", json=payload)
|
||||
if not r.is_error:
|
||||
return r.read()
|
||||
else:
|
||||
raise QuotlyException(r.json())
|
||||
|
||||
|
||||
def isArgInt(txt) -> list:
|
||||
count = txt
|
||||
try:
|
||||
count = int(count)
|
||||
return [True, count]
|
||||
except ValueError:
|
||||
return [False, 0]
|
||||
|
||||
|
||||
@app.on_message(filters.command(["q"]) & filters.reply)
|
||||
async def msg_quotly_cmd(c: Client, m: Message):
|
||||
if len(m.text.split()) > 1:
|
||||
check_arg = isArgInt(m.command[1])
|
||||
if check_arg[0]:
|
||||
if check_arg[1] < 2 or check_arg[1] > 10:
|
||||
return await m.reply_text("Invalid range")
|
||||
try:
|
||||
messages = [
|
||||
i
|
||||
for i in await c.get_messages(
|
||||
chat_id=m.chat.id,
|
||||
message_ids=range(
|
||||
m.reply_to_message.id,
|
||||
m.reply_to_message.id + (check_arg[1] + 5),
|
||||
),
|
||||
replies=-1,
|
||||
)
|
||||
if not i.empty and not i.media
|
||||
]
|
||||
except Exception:
|
||||
return await m.reply_text("🤷🏻♂️")
|
||||
try:
|
||||
make_quotly = await pyrogram_to_quotly(messages)
|
||||
bio_sticker = BytesIO(make_quotly)
|
||||
bio_sticker.name = "biosticker.webp"
|
||||
return await m.reply_sticker(bio_sticker)
|
||||
except Exception:
|
||||
return await m.reply_text("🤷🏻♂️")
|
||||
try:
|
||||
messages_one = await c.get_messages(
|
||||
chat_id=m.chat.id, message_ids=m.reply_to_message.id, replies=-1
|
||||
)
|
||||
messages = [messages_one]
|
||||
except Exception:
|
||||
return await m.reply_text("🤷🏻♂️")
|
||||
try:
|
||||
make_quotly = await pyrogram_to_quotly(messages)
|
||||
bio_sticker = BytesIO(make_quotly)
|
||||
bio_sticker.name = "biosticker.webp"
|
||||
return await m.reply_sticker(bio_sticker)
|
||||
except Exception as e:
|
||||
return await m.reply_text(f"ERROR: {e}")
|
||||
417
misskaty/plugins/scrapwebsite.py
Normal file
417
misskaty/plugins/scrapwebsite.py
Normal file
|
|
@ -0,0 +1,417 @@
|
|||
# This plugin to scrape from melongmovie, and lk21
|
||||
from bs4 import BeautifulSoup
|
||||
import aiohttp
|
||||
import re
|
||||
import traceback
|
||||
from misskaty import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.errors import MessageTooLong
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.helper.tools import rentry
|
||||
from misskaty.helper.http import http
|
||||
|
||||
__MODULE__ = "WebScraper"
|
||||
__HELP__ = """
|
||||
/melongmovie - Scrape website data from MelongMovie Web. If without query will give latest movie list.
|
||||
/lk21 [query <opsional>] - Scrape website data from LayarKaca21. If without query will give latest movie list.
|
||||
/terbit21 [query <opsional>] - Scrape website data from Terbit21. If without query will give latest movie list.
|
||||
/savefilm21 [query <opsional>] - Scrape website data from Savefilm21. If without query will give latest movie list.
|
||||
/movieku [query <opsional>] - Scrape website data from Movieku.cc
|
||||
/gomov [query <opsional>] - Scrape website data from GoMov. If without query will give latest movie list.
|
||||
"""
|
||||
|
||||
|
||||
# Broken
|
||||
@app.on_message(filters.command(["nodrakor"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def nodrakor(_, message):
|
||||
try:
|
||||
judul = message.text.split(" ", maxsplit=1)[1]
|
||||
except IndexError:
|
||||
judul = ""
|
||||
|
||||
msg = await message.reply("Sedang proses scrap, mohon tunggu..")
|
||||
try:
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
html = await http.get(f"https://109.234.34.246/?s={judul}", headers=headers)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
res = soup.find_all(class_="content-thumbnail text-center")
|
||||
data = []
|
||||
for i in res:
|
||||
link = i.find_all("a")[0]["href"]
|
||||
judul = i.find_all("a")[0]["title"].split(": ")[1]
|
||||
data.append({"judul": judul, "link": link})
|
||||
if not data:
|
||||
return await msg.edit("Oops, data film tidak ditemukan.")
|
||||
res = "".join(f"<b>{i['judul']}</b>\n{i['link']}\n\n" for i in data)
|
||||
await msg.edit(
|
||||
f"<b>Hasil Pencarian di Nodrakor:</b>\n{res}\nScraped by @MissKatyRoBot"
|
||||
)
|
||||
except Exception as e:
|
||||
await msg.edit(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
# Broken
|
||||
@app.on_message(filters.command(["ngefilm21"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def ngefilm21(_, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Masukkan query yang akan dicari..!!")
|
||||
title = message.text.split(" ", maxsplit=1)[1]
|
||||
|
||||
msg = await message.reply("Sedang proses scrap, mohon tunggu..")
|
||||
try:
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
|
||||
html = await http.get(
|
||||
f"http://185.237.253.209/search?q={title}", headers=headers
|
||||
)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
res = soup.find_all("h2")
|
||||
data = []
|
||||
for i in res:
|
||||
a = i.find_all("a")[0]
|
||||
judul = a.find_all(class_="r-snippetized")
|
||||
b = i.find_all("a")[0]["href"]
|
||||
data.append({"judul": judul[0].text, "link": b})
|
||||
# print(f"{judul[0].text}{b}\n")
|
||||
if not data:
|
||||
return await msg.edit("Oops, data film tidak ditemukan.")
|
||||
res = "".join(f"<b>{i['judul']}</b>\n{i['link']}\n" for i in data)
|
||||
await msg.edit(f"<b>Hasil Scrap dari Ngefilm21:</b>\n{res}")
|
||||
except Exception as e:
|
||||
await msg.edit(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
# Scrape Web From Movieku.CC
|
||||
@app.on_message(filters.command(["movieku"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def movikucc(_, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Masukkan query yang akan dicari..!!")
|
||||
judul = message.text.split(" ", maxsplit=1)[1]
|
||||
msg = await message.reply("Sedang proses scrap, mohon tunggu..")
|
||||
try:
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
html = await http.get(f"https://107.152.39.187/?s={judul}", headers=headers)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
data = soup.find_all(class_="bx")
|
||||
res = "".join(
|
||||
f"<b>Judul: {i.find_all('a')[0]['title']}</b>\nLink: {i.find_all('a')[0]['href']}\n\n"
|
||||
for i in data
|
||||
)
|
||||
await msg.edit(
|
||||
f"<b>Hasil Scrap di Movieku.cc:</b>\n{res} ⚠️ Gunakan command /movieku_scrap <b>[link]</b> untuk mengambil link download (hanya untuk movie)."
|
||||
)
|
||||
except Exception as e:
|
||||
await msg.edit(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["savefilm21"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def savefilm21(_, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply("Masukkan query yang akan dicari..!!")
|
||||
judul = message.text.split(" ", maxsplit=1)[1]
|
||||
msg = await message.reply("Sedang proses scrap, mohon tunggu..")
|
||||
try:
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
|
||||
html = await http.get(
|
||||
f"http://38.242.196.210/?s={judul}", headers=headers, allow_redirects=False
|
||||
)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
res = soup.find_all(class_="entry-title")
|
||||
data = []
|
||||
for i in res:
|
||||
pas = i.find_all("a")
|
||||
judul = pas[0].text
|
||||
link = pas[0]["href"]
|
||||
data.append({"judul": judul, "link": link})
|
||||
if not data:
|
||||
return await msg.edit("Oops, data film tidak ditemukan")
|
||||
res = "".join(
|
||||
f"<b>Judul: {i['judul']}</b>\nLink: {i['link']}\n\n" for i in data
|
||||
)
|
||||
await msg.edit(
|
||||
f"Hasil Scrap <code>{judul}</code> dari Savefilm21:\n{res}\n\n⚠️ Gunakan /savefilm21_scrap <b>[link]</b> untuk mengambil link downloadnya."
|
||||
)
|
||||
except Exception as e:
|
||||
await msg.edit(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["melongmovie"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def melongmovie(_, message):
|
||||
try:
|
||||
judul = message.text.split(" ", maxsplit=1)[1]
|
||||
except IndexError:
|
||||
judul = ""
|
||||
|
||||
msg = await message.reply("Sedang proses scrap, mohon tunggu..")
|
||||
try:
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
|
||||
html = await http.get(f"http://167.99.31.48/?s={judul}", headers=headers)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
data = []
|
||||
for res in soup.select(".box"):
|
||||
dd = res.select("a")
|
||||
url = dd[0]["href"]
|
||||
title = dd[0]["title"]
|
||||
try:
|
||||
kualitas = dd[0].find(class_="quality").text
|
||||
except:
|
||||
kualitas = ""
|
||||
data.append({"judul": title, "link": url, "kualitas": kualitas})
|
||||
if not data:
|
||||
return await msg.edit("Oops, data film tidak ditemukan di melongmovie")
|
||||
res = "".join(
|
||||
f"<b>Judul: {i['judul']}</b>\n<b>Kualitas:</b> {i['kualitas']}\n<b>Link</b>: {i['link']}\n\n"
|
||||
for i in data
|
||||
)
|
||||
# return await message.reply(json.dumps(data, indent=2, ensure_ascii=False))
|
||||
return await msg.edit(res)
|
||||
except Exception as e:
|
||||
await msg.edit(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
@app.on_message(filters.command(["terbit21"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def terbit21_scrap(_, message):
|
||||
if len(message.command) == 1:
|
||||
r = await http.get("https://yasirapi.eu.org/terbit21")
|
||||
res = r.json()
|
||||
data = "".join(
|
||||
f"**Judul: {i['judul']}**\n`{i['kategori']}`\n{i['link']}\n**Download:** [Klik Disini]({i['dl']})\n\n"
|
||||
for i in res["result"]
|
||||
)
|
||||
try:
|
||||
return await message.reply(
|
||||
f"**Daftar rilis movie terbaru di web Terbit21**:\n{data}",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except MessageTooLong:
|
||||
msg = await rentry(data)
|
||||
return await message.reply(
|
||||
f"Karena hasil scrape terlalu panjang, maka hasil scrape di post ke rentry.\n\n{msg}"
|
||||
)
|
||||
judul = message.text.split(" ", maxsplit=1)[1]
|
||||
msg = await message.reply(f"Mencari film di Terbit21 dg keyword {judul}..")
|
||||
r = await http.get(f"https://yasirapi.eu.org/terbit21?q={judul}")
|
||||
res = r.json()
|
||||
data = "".join(
|
||||
f"**Judul: {i['judul']}**\n`{i['kategori']}`\n{i['link']}\n**Download:** [Klik Disini]({i['dl']})\n\n"
|
||||
for i in res["result"]
|
||||
)
|
||||
if not res["result"]:
|
||||
return await msg.edit("Yahh, ga ada hasil ditemukan")
|
||||
try:
|
||||
await msg.edit(
|
||||
f"<b>Hasil pencarian query {judul} di lk21:</b>\n{data}",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except MessageTooLong:
|
||||
pesan = await rentry(data)
|
||||
await msg.edit(
|
||||
f"Karena hasil scrape terlalu panjang, maka hasil scrape di post ke rentry.\n\n{pesan}"
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["lk21"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def lk21_scrap(_, message):
|
||||
if len(message.command) == 1:
|
||||
msg = await message.reply("Mendapatkan daftar post film terbaru di lk21")
|
||||
r = await http.get("https://yasirapi.eu.org/lk21")
|
||||
res = r.json()
|
||||
if res.get("detail", None):
|
||||
return await msg.edit(f"ERROR: {res['detail']}")
|
||||
data = "".join(
|
||||
f"**Judul: {i['judul']}**\n`{i['kategori']}`\n{i['link']}\n**Download:** [Klik Disini]({i['dl']})\n\n"
|
||||
for i in res["result"]
|
||||
)
|
||||
try:
|
||||
return await msg.edit(
|
||||
f"**Daftar rilis movie terbaru di web LK21**:\n{data}",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except MessageTooLong:
|
||||
msg = await rentry(data)
|
||||
await msg.edit(
|
||||
f"Karena hasil scrape terlalu panjang, maka hasil scrape di post ke rentry.\n\n{msg}"
|
||||
)
|
||||
judul = message.text.split(" ", maxsplit=1)[1]
|
||||
msg = await message.reply(f"Mencari film di lk21 dg keyword {judul}..")
|
||||
r = await http.get(f"https://yasirapi.eu.org/lk21?q={judul}")
|
||||
res = r.json()
|
||||
if res.get("detail", None):
|
||||
return await msg.edit(f"ERROR: {res['detail']}")
|
||||
data = "".join(
|
||||
f"**Judul: {i['judul']}**\n`{i['kategori']}`\n{i['link']}\n**Download:** [Klik Disini]({i['dl']})\n\n"
|
||||
for i in res["result"]
|
||||
)
|
||||
if not res["result"]:
|
||||
return await msg.edit("Yahh, ga ada hasil ditemukan")
|
||||
try:
|
||||
await msg.edit(
|
||||
f"<b>Hasil pencarian query {judul} di lk21:</b>\n{data}",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except MessageTooLong:
|
||||
pesan = await rentry(data)
|
||||
return await msg.edit(
|
||||
f"Karena hasil scrape terlalu panjang, maka hasil scrape di post ke rentry.\n\n{pesan}"
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(filters.command(["gomov", "gomov@MissKatyRoBot"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def gomov_scrap(_, message):
|
||||
try:
|
||||
judul = message.text.split(" ", maxsplit=1)[1]
|
||||
except IndexError:
|
||||
judul = ""
|
||||
|
||||
msg = await message.reply("Scraping GoMov Website..")
|
||||
try:
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
|
||||
html = await http.get(f"https://185.173.38.216/?s={judul}", headers=headers)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
entry = soup.find_all(class_="entry-title")
|
||||
DATA = []
|
||||
for i in entry:
|
||||
judul = i.find_all("a")[0].text
|
||||
link = i.find_all("a")[0]["href"]
|
||||
DATA.append({"judul": judul, "link": link})
|
||||
if not DATA:
|
||||
return await msg.edit("Oops, data film tidak ditemukan di GoMov")
|
||||
res = "".join(f"<b>Judul: {i['judul']}</b>\n{i['link']}\n\n" for i in DATA)
|
||||
await msg.edit(
|
||||
f"<b>Hasil Pencarian di website GoMov:</b>\n{res}\nScraped by @MissKatyRoBot"
|
||||
)
|
||||
except Exception:
|
||||
exc = traceback.format_exc()
|
||||
await msg.edit(f"ERROR: <code>{exc}</code>")
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.command(
|
||||
["savefilm21_scrap", "savefilm21_scrap@MissKatyRoBot"], COMMAND_HANDLER
|
||||
)
|
||||
)
|
||||
@capture_err
|
||||
async def savefilm21_scrap(_, message):
|
||||
try:
|
||||
link = message.text.split(" ", maxsplit=1)[1]
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
|
||||
html = await http.get(link, headers=headers, follow_redirects=False)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
res = soup.find_all(class_="button button-shadow")
|
||||
res = "".join(f"{i.text}\n{i['href']}\n\n" for i in res)
|
||||
await message.reply(f"<b>Hasil Scrap dari {link}</b>:\n\n{res}")
|
||||
except IndexError:
|
||||
return await message.reply(
|
||||
"Gunakan command /savefilm21_scrap <b>[link]</b> untuk scrap link download"
|
||||
)
|
||||
except Exception as e:
|
||||
await message.reply(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.command(["nodrakor_scrap", "nodrakor_scrap@MissKatyRoBot"], COMMAND_HANDLER)
|
||||
)
|
||||
@capture_err
|
||||
async def nodrakor_scrap(_, message):
|
||||
try:
|
||||
link = message.text.split(" ", maxsplit=1)[1]
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
|
||||
html = await http.get(link, headers=headers, follow_redirects=False)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
hasil = soup.find_all(class_="gmr-download-wrap clearfix")[0]
|
||||
await message.reply(f"<b>Hasil Scrap dari {link}</b>:\n{hasil}")
|
||||
except IndexError:
|
||||
return await message.reply(
|
||||
"Gunakan command /nodrakor_scrap <b>[link]</b> untuk scrap link download"
|
||||
)
|
||||
except Exception as e:
|
||||
await message.reply(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
# Scrape Link Download Movieku.CC
|
||||
@app.on_message(
|
||||
filters.command(["movieku_scrap", "movieku_scrap@MissKatyRoBot"], COMMAND_HANDLER)
|
||||
)
|
||||
@capture_err
|
||||
async def muviku_scrap(_, message):
|
||||
try:
|
||||
link = message.text.split(" ", maxsplit=1)[1]
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
|
||||
html = await http.get(link, headers=headers)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
res = soup.find_all(class_="smokeurl")
|
||||
data = []
|
||||
for i in res:
|
||||
for b in range(len(i.find_all("a"))):
|
||||
link = i.find_all("a")[b]["href"]
|
||||
kualitas = i.find_all("a")[b].text
|
||||
# print(f"{kualitas}\n{link
|
||||
data.append({"link": link, "kualitas": kualitas})
|
||||
if not data:
|
||||
return await message.reply("Oops, data film tidak ditemukan.")
|
||||
res = "".join(f"<b>Host: {i['kualitas']}</b>\n{i['link']}\n\n" for i in data)
|
||||
await message.reply(res)
|
||||
except IndexError:
|
||||
return await message.reply(
|
||||
"Gunakan command /movieku_scrap <b>[link]</b> untuk scrap link download"
|
||||
)
|
||||
except Exception as e:
|
||||
await message.reply(f"ERROR: {str(e)}")
|
||||
|
||||
|
||||
@app.on_message(
|
||||
filters.command(["melong", "melong@MissKatyRoBot"], COMMAND_HANDLER)
|
||||
& filters.user([617426792, 1985689491, 1172699512, 2024984460])
|
||||
)
|
||||
@capture_err
|
||||
async def melong_scrap(_, message):
|
||||
try:
|
||||
link = message.text.split(" ", maxsplit=1)[1]
|
||||
headers = {
|
||||
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
|
||||
}
|
||||
|
||||
html = await http.get(link, headers=headers)
|
||||
soup = BeautifulSoup(html.text, "lxml")
|
||||
for ep in soup.findAll(text=re.compile(r"(?i)episode\s+\d+|LINK DOWNLOAD")):
|
||||
hardsub = ep.findPrevious("div")
|
||||
softsub = ep.findNext("div")
|
||||
rep = f"{hardsub}\n{softsub}"
|
||||
await message.reply(rep)
|
||||
except IndexError:
|
||||
await message.reply(
|
||||
"Gunakan command /melong <b>[link]</b> untuk scrap link download"
|
||||
)
|
||||
53
misskaty/plugins/sed.py
Normal file
53
misskaty/plugins/sed.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2018-2022 Amano Team
|
||||
|
||||
import html
|
||||
|
||||
import regex
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message
|
||||
from pyrogram.errors import MessageEmpty
|
||||
from misskaty import app
|
||||
|
||||
|
||||
@app.on_message(filters.regex(r"^s/(.+)?/(.+)?(/.+)?") & filters.reply)
|
||||
async def sed(c: app, m: Message):
|
||||
exp = regex.split(r"(?<![^\\]\\)/", m.text)
|
||||
pattern = exp[1]
|
||||
replace_with = exp[2].replace(r"\/", "/")
|
||||
flags = exp[3] if len(exp) > 3 else ""
|
||||
|
||||
rflags = 0
|
||||
|
||||
count = 0 if "g" in flags else 1
|
||||
if "i" in flags and "s" in flags:
|
||||
rflags = regex.I | regex.S
|
||||
elif "i" in flags:
|
||||
rflags = regex.I
|
||||
elif "s" in flags:
|
||||
rflags = regex.S
|
||||
|
||||
text = m.reply_to_message.text or m.reply_to_message.caption
|
||||
|
||||
if not text:
|
||||
return
|
||||
|
||||
try:
|
||||
res = regex.sub(
|
||||
pattern, replace_with, text, count=count, flags=rflags, timeout=1
|
||||
)
|
||||
except TimeoutError:
|
||||
return await m.reply_text("Oops, your regex pattern has run for too long.")
|
||||
except regex.error as e:
|
||||
return await m.reply_text(str(e))
|
||||
else:
|
||||
try:
|
||||
await c.send_message(
|
||||
m.chat.id,
|
||||
f"<pre>{html.escape(res)}</pre>",
|
||||
reply_to_message_id=m.reply_to_message.id,
|
||||
)
|
||||
except MessageEmpty:
|
||||
return await m.reply_text("Please reply message to use this feature.")
|
||||
except Exception as e:
|
||||
return await m.reply_text(f"ERROR: {str(e)}")
|
||||
150
misskaty/plugins/sub_extractor.py
Normal file
150
misskaty/plugins/sub_extractor.py
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
from misskaty import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.plugins.dev import shell_exec
|
||||
import json, os, traceback
|
||||
from time import perf_counter
|
||||
from re import split as ngesplit, I
|
||||
from urllib.parse import unquote
|
||||
from misskaty.helper.tools import get_random_string
|
||||
|
||||
ARCH_EXT = [".mkv", ".avi", ".mp4", ".mov"]
|
||||
|
||||
__MODULE__ = "MediaExtract"
|
||||
__HELP__ = """
|
||||
/extractmedia [URL] - Extract subtitle or audio from video using link.
|
||||
"""
|
||||
|
||||
|
||||
def get_base_name(orig_path: str):
|
||||
if ext := [ext for ext in ARCH_EXT if orig_path.lower().endswith(ext)]:
|
||||
ext = ext[0]
|
||||
return ngesplit(f"{ext}$", orig_path, maxsplit=1, flags=I)[0]
|
||||
|
||||
|
||||
def get_subname(url, format):
|
||||
fragment_removed = url.split("#")[0] # keep to left of first #
|
||||
query_string_removed = fragment_removed.split("?")[0]
|
||||
scheme_removed = query_string_removed.split("://")[-1].split(":")[-1]
|
||||
if scheme_removed.find("/") == -1:
|
||||
return f"MissKatySub_{get_random_string(4)}.{format}"
|
||||
return f"{get_base_name(os.path.basename(unquote(scheme_removed)))}.{format}"
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ceksub", "extractmedia"], COMMAND_HANDLER))
|
||||
async def ceksub(_, m):
|
||||
cmd = m.text.split(" ", 1)
|
||||
if len(cmd) == 1:
|
||||
return await m.reply(
|
||||
f"Gunakan command /{m.command[0]} [link] untuk mengecek subtitle dan audio didalam video."
|
||||
)
|
||||
link = cmd[1]
|
||||
start_time = perf_counter()
|
||||
pesan = await m.reply("Sedang memproses perintah..", quote=True)
|
||||
try:
|
||||
res = (
|
||||
await shell_exec(
|
||||
f"ffprobe -loglevel 0 -print_format json -show_format -show_streams {link}"
|
||||
)
|
||||
)[0]
|
||||
details = json.loads(res)
|
||||
buttons = []
|
||||
for stream in details["streams"]:
|
||||
mapping = stream["index"]
|
||||
try:
|
||||
stream_name = stream["codec_name"]
|
||||
except:
|
||||
stream_name = "-"
|
||||
stream_type = stream["codec_type"]
|
||||
if stream_type not in ("audio", "subtitle"):
|
||||
continue
|
||||
try:
|
||||
lang = stream["tags"]["language"]
|
||||
except:
|
||||
lang = mapping
|
||||
buttons.append(
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
f"0:{mapping}({lang}): {stream_type}: {stream_name}",
|
||||
f"streamextract_{mapping}_{stream_name}",
|
||||
)
|
||||
]
|
||||
)
|
||||
end_time = perf_counter()
|
||||
timelog = "{:.2f}".format(end_time - start_time) + " second"
|
||||
buttons.append([InlineKeyboardButton("Cancel", "cancel")])
|
||||
await pesan.edit(
|
||||
f"Press the button below to extract subtitles/audio. Only support direct link at this time.\nProcessed in {timelog}",
|
||||
reply_markup=InlineKeyboardMarkup(buttons),
|
||||
)
|
||||
except Exception:
|
||||
err = traceback.format_exc()
|
||||
await pesan.edit(f"Gagal extract media data.\nLink: {link}\nERROR: {err}")
|
||||
|
||||
|
||||
ALLOWED_USER = [978550890, 617426792, 2024984460, 1533008300, 1985689491]
|
||||
|
||||
|
||||
@app.on_message(filters.command(["converttosrt"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def convertsrt(_, m):
|
||||
reply = m.reply_to_message
|
||||
if not reply and reply.document:
|
||||
return await m.reply(
|
||||
f"Gunakan command /{m.command[0]} dengan mereply ke file ass untuk convert subtitle ke srt."
|
||||
)
|
||||
msg = await m.reply("Sedang memproses perintah...")
|
||||
dl = await reply.download()
|
||||
(await shell_exec(f"mediaextract -i {dl} {os.path.basename(dl)}.srt"))[0]
|
||||
await m.reply_document(
|
||||
f"{os.path.basename(dl)}.srt", caption=f"{os.path.basename(dl)}.srt"
|
||||
)
|
||||
await msg.delete()
|
||||
try:
|
||||
os.remove(dl)
|
||||
os.remove(f"{os.path.basename(dl)}.srt")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^streamextract_"))
|
||||
async def stream_extract(bot, update):
|
||||
cb_data = update.data
|
||||
usr = update.message.reply_to_message
|
||||
if update.from_user.id != usr.from_user.id:
|
||||
return await update.answer("⚠️ Access Denied!", True)
|
||||
_, map, codec = cb_data.split("_")
|
||||
link = update.message.reply_to_message.command[1]
|
||||
await update.message.edit("Processing...")
|
||||
if codec == "aac":
|
||||
format = "aac"
|
||||
elif codec == "mp3":
|
||||
format = "mp3"
|
||||
elif codec == "eac3":
|
||||
format = "eac3"
|
||||
elif codec == "subrip":
|
||||
format = "srt"
|
||||
else:
|
||||
format == "ass"
|
||||
try:
|
||||
start_time = perf_counter()
|
||||
namafile = get_subname(link, format)
|
||||
extract = (await shell_exec(f"mediaextract -i {link} -map 0:{map} {namafile}"))[
|
||||
0
|
||||
]
|
||||
end_time = perf_counter()
|
||||
timelog = "{:.2f}".format(end_time - start_time) + " second"
|
||||
await update.message.reply_document(
|
||||
namafile,
|
||||
caption=f"<b>Filename:</b> <code>{namafile}</code>\n\nExtracted by @MissKatyRoBot in {timelog}",
|
||||
reply_to_message_id=usr.id,
|
||||
)
|
||||
await update.message.delete()
|
||||
try:
|
||||
os.remove(namafile)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
await update.message.edit(f"Failed extract sub. \n\nERROR: {e}")
|
||||
15
misskaty/plugins/tes_session.py
Normal file
15
misskaty/plugins/tes_session.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# This plugin to learn session using pyrogram
|
||||
from misskaty import app
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from pyrogram import filters
|
||||
|
||||
|
||||
@app.on_message(filters.command(["session"], COMMAND_HANDLER))
|
||||
async def session(_, message):
|
||||
nama = await app.ask(message.chat.id, "Ketik nama kamu:")
|
||||
umur = await app.ask(message.chat.id, "Ketik umur kamu")
|
||||
alamat = await app.ask(message.chat.id, "Ketik alamat kamu:")
|
||||
await app.send_message(
|
||||
message.chat.id,
|
||||
f"Nama Kamu Adalah: {nama.text}\nUmur Kamu Adalah: {umur.text}\nAlamat Kamu Adalah: {alamat.text}",
|
||||
)
|
||||
180
misskaty/plugins/ubot_plugin.py
Normal file
180
misskaty/plugins/ubot_plugin.py
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
import os
|
||||
from pyrogram import enums, filters
|
||||
from pyrogram.types import (
|
||||
Message,
|
||||
InlineKeyboardMarkup,
|
||||
InlineKeyboardButton,
|
||||
ChatEventFilter,
|
||||
)
|
||||
from pyrogram.raw import functions
|
||||
from misskaty import user, app
|
||||
from datetime import datetime
|
||||
|
||||
f = filters.chat([])
|
||||
|
||||
|
||||
@user.on_message(f)
|
||||
async def auto_read(_, message: Message):
|
||||
await user.read_history(message.chat.id)
|
||||
await message.continue_propagation()
|
||||
|
||||
|
||||
@user.on_message(filters.command("autoscroll", "!") & filters.me)
|
||||
async def add_keep(_, message: Message):
|
||||
if message.chat.id in f:
|
||||
f.remove(message.chat.id)
|
||||
await message.edit("Autoscroll dimatikan")
|
||||
else:
|
||||
f.add(message.chat.id)
|
||||
await message.edit("Autoscroll diaktifkan, semua chat akan otomatis terbaca")
|
||||
|
||||
|
||||
# @user.on_deleted_messages(filters.chat([-1001455886928, -1001255283935]))
|
||||
async def del_msg(client, message):
|
||||
async for a in user.get_chat_event_log(
|
||||
message[0].chat.id, limit=1, filters=ChatEventFilter(deleted_messages=True)
|
||||
):
|
||||
try:
|
||||
ustat = (
|
||||
await user.get_chat_member(
|
||||
message[0].chat.id, a.deleted_message.from_user.id
|
||||
)
|
||||
).status
|
||||
except:
|
||||
ustat = enums.ChatMemberStatus.MEMBER
|
||||
if (
|
||||
ustat
|
||||
in [enums.ChatMemberStatus.ADMINISTRATOR, enums.ChatMemberStatus.OWNER]
|
||||
or a.deleted_message.from_user.is_bot
|
||||
):
|
||||
return
|
||||
if a.user.id == a.deleted_message.from_user.id:
|
||||
if a.deleted_message.text:
|
||||
await app.send_message(
|
||||
a.deleted_message.chat.id,
|
||||
f"#DELETED_MESSAGE\n\n<a href='tg://user?id={a.deleted_message.from_user.id}'>{a.deleted_message.from_user.first_name}</a> menghapus pesannya 🧐.\n<b>Pesan:</b> {a.deleted_message.text}",
|
||||
)
|
||||
elif a.deleted_message.video:
|
||||
await app.send_message(
|
||||
a.deleted_message.chat.id,
|
||||
f"#DELETED_MESSAGE\n\n<a href='tg://user?id={a.deleted_message.from_user.id}'>{a.deleted_message.from_user.first_name}</a> menghapus pesannya 🧐.\n<b>Nama file:</b> {a.deleted_message.video.file_name}",
|
||||
)
|
||||
|
||||
|
||||
# @user.on_edited_message(filters.text & filters.chat(-1001455886928))
|
||||
async def edit_msg(client, message):
|
||||
try:
|
||||
ustat = (
|
||||
await user.get_chat_member(message.chat.id, message.from_user.id)
|
||||
).status
|
||||
except:
|
||||
ustat = enums.ChatMemberStatus.MEMBER
|
||||
if message.from_user.is_bot or ustat in [
|
||||
enums.ChatMemberStatus.ADMINISTRATOR,
|
||||
enums.ChatMemberStatus.OWNER,
|
||||
]:
|
||||
return
|
||||
async for a in user.get_chat_event_log(
|
||||
message.chat.id, limit=1, filters=ChatEventFilter(edited_messages=True)
|
||||
):
|
||||
if a.old_message.text.startswith(
|
||||
("/mirror", "/leech", "/unzipmirror", "/unzipleech")
|
||||
):
|
||||
await app.send_message(
|
||||
message.chat.id,
|
||||
f"#EDITED_MESSAGE\n\n<a href='tg://user?id={a.user.id}'>{a.user.first_name}</a> mengedit pesannya 🧐.\n<b>Pesan:</b> {a.old_message.text}",
|
||||
)
|
||||
|
||||
|
||||
@user.on_message(filters.private & ~filters.bot & ~filters.me & filters.text)
|
||||
async def message_pm(client, message):
|
||||
await app.send_message(
|
||||
617426792,
|
||||
f"Ada pesan baru dari {message.from_user.mention}\n\n<b>Pesan: </b>{message.text}",
|
||||
)
|
||||
|
||||
|
||||
@user.on_message(~filters.bot & filters.group & filters.mentioned)
|
||||
async def mentioned(client, message):
|
||||
if message.sender_chat:
|
||||
return
|
||||
cid = message.chat.id
|
||||
pesan = message.text or message.caption
|
||||
await app.send_message(
|
||||
617426792,
|
||||
f"{message.from_user.mention} mention kamu di {message.chat.title}\n\n<b>Pesan:</b> {pesan}",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="💬 Lihat Pesan",
|
||||
url=f"https://t.me/c/{str(cid)[4:]}/{message.id}",
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@user.on_message(filters.command("joindate", "!") & filters.me)
|
||||
async def join_date(app, message: Message):
|
||||
members = []
|
||||
async for m in app.iter_chat_members(message.chat.id):
|
||||
members.append(
|
||||
(
|
||||
m.user.first_name,
|
||||
m.joined_date or (await app.get_messages(message.chat.id, 1)).date,
|
||||
)
|
||||
)
|
||||
members.sort(key=lambda member: member[1])
|
||||
|
||||
with open("joined_date.txt", "w", encoding="utf8") as f:
|
||||
f.write("Join Date First Name\n")
|
||||
for member in members:
|
||||
f.write(
|
||||
str(datetime.fromtimestamp(member[1]).strftime("%y-%m-%d %H:%M"))
|
||||
+ f" {member[0]}\n"
|
||||
)
|
||||
|
||||
await user.send_document(message.chat.id, "joined_date.txt")
|
||||
os.remove("joined_date.txt")
|
||||
|
||||
|
||||
@user.on_message(filters.command("memberstats", "!") & filters.me)
|
||||
async def memberstats(client, message):
|
||||
people = {}
|
||||
total = await user.get_chat_members_count(message.chat.id)
|
||||
async for msg in user.iter_history(message.chat.id, limit=1000):
|
||||
if msg.from_user and not msg.from_user.is_bot:
|
||||
people[msg.from_user.id] = msg.from_user.first_name
|
||||
await message.edit(f"{round(len(people) / total)}%")
|
||||
|
||||
|
||||
@user.on_message(filters.command("recent_action", "!") & filters.me)
|
||||
async def recent_act(client, message):
|
||||
full_log = await user.invoke(
|
||||
functions.channels.GetAdminLog(
|
||||
channel=await user.resolve_peer(message.chat.id),
|
||||
q="",
|
||||
max_id=0,
|
||||
min_id=0,
|
||||
limit=0,
|
||||
)
|
||||
)
|
||||
with open(
|
||||
f"recent_actions_{message.chat.id}.txt", "w", encoding="utf8"
|
||||
) as log_file:
|
||||
log_file.write(str(full_log))
|
||||
await message.reply_document(f"recent_actions_{message.chat.id}.txt")
|
||||
|
||||
|
||||
@user.on_message(filters.command(["screenshot"], prefixes="!"))
|
||||
async def take_a_screenshot(client, message):
|
||||
await message.delete()
|
||||
await user.invoke(
|
||||
functions.messages.SendScreenshotNotification(
|
||||
peer=await user.resolve_peer(message.chat.id),
|
||||
reply_to_msg_id=0,
|
||||
random_id=app.rnd_id(),
|
||||
)
|
||||
)
|
||||
76
misskaty/plugins/webss.py
Normal file
76
misskaty/plugins/webss.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
from asyncio import gather
|
||||
from base64 import b64decode
|
||||
from io import BytesIO
|
||||
from pyrogram import filters
|
||||
from misskaty import app
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.helper.http import post
|
||||
|
||||
__MODULE__ = "WebSS"
|
||||
__HELP__ = """
|
||||
/webss [URL] [FULL_SIZE?, use (y|yes|true) to get full size image. (optional)] - Take A Screenshot Of A Webpage.
|
||||
"""
|
||||
|
||||
|
||||
async def take_screenshot(url: str, full: bool = False):
|
||||
url = url if url.startswith("http") else f"https://{url}"
|
||||
payload = {
|
||||
"url": url,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"scale": 1,
|
||||
"format": "jpeg",
|
||||
}
|
||||
if full:
|
||||
payload["full"] = True
|
||||
data = await post(
|
||||
"https://webscreenshot.vercel.app/api",
|
||||
data=payload,
|
||||
)
|
||||
if "image" not in data:
|
||||
return None
|
||||
b = data["image"].replace("data:image/jpeg;base64,", "")
|
||||
file = BytesIO(b64decode(b))
|
||||
file.name = "webss.jpg"
|
||||
return file
|
||||
|
||||
|
||||
@app.on_message(filters.command(["webss"], COMMAND_HANDLER))
|
||||
@capture_err
|
||||
async def take_ss(_, message):
|
||||
if len(message.command) < 2:
|
||||
return await message.reply("Give A Url To Fetch Screenshot.")
|
||||
|
||||
if len(message.command) == 2:
|
||||
url = message.text.split(None, 1)[1]
|
||||
full = False
|
||||
elif len(message.command) == 3:
|
||||
url = message.text.split(None, 2)[1]
|
||||
full = message.text.split(None, 2)[2].lower().strip() in [
|
||||
"yes",
|
||||
"y",
|
||||
"1",
|
||||
"true",
|
||||
]
|
||||
else:
|
||||
return await message.reply("Invalid Command.")
|
||||
|
||||
m = await message.reply("Capturing screenshot...")
|
||||
|
||||
try:
|
||||
photo = await take_screenshot(url, full)
|
||||
if not photo:
|
||||
return await m.edit("Failed To Take Screenshot")
|
||||
|
||||
m = await m.edit("Uploading...")
|
||||
|
||||
if not full:
|
||||
# Full size images have problem with reply_photo, that's why
|
||||
# we need to only use reply_photo if we're not using full size
|
||||
await gather(*[message.reply_document(photo), message.reply_photo(photo)])
|
||||
else:
|
||||
await message.reply_document(photo)
|
||||
await m.delete()
|
||||
except Exception as e:
|
||||
await m.edit(str(e))
|
||||
386
misskaty/plugins/ytdl_download.py
Normal file
386
misskaty/plugins/ytdl_download.py
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
"""
|
||||
* @author yasir <yasiramunandar@gmail.com>
|
||||
* @date 2022-12-01 09:12:27
|
||||
* @lastModified 2022-12-01 09:32:31
|
||||
* @projectName MissKatyPyro
|
||||
* Copyright @YasirPedia All rights reserved
|
||||
"""
|
||||
import os, logging, json, shutil, asyncio, time
|
||||
from misskaty import app
|
||||
from PIL import Image
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from misskaty.vars import COMMAND_HANDLER
|
||||
from datetime import datetime
|
||||
from hachoir.metadata import extractMetadata
|
||||
from hachoir.parser import createParser
|
||||
from misskaty.helper.ytdl_helper import random_char, DownLoadFile
|
||||
from misskaty.helper.human_read import get_readable_file_size
|
||||
from misskaty.plugins.dev import shell_exec
|
||||
from misskaty.core.decorator.errors import capture_err
|
||||
from misskaty.helper.pyro_progress import progress_for_pyrogram
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
user_time = {}
|
||||
|
||||
|
||||
@app.on_message(filters.command(["ytdown"], COMMAND_HANDLER) & ~filters.channel)
|
||||
@capture_err
|
||||
async def ytdown(_, message):
|
||||
if len(message.command) == 1:
|
||||
return await message.reply(
|
||||
f"Gunakan command /{message.command[0]} YT_LINK untuk download video dengan YT-DLP."
|
||||
)
|
||||
userLastDownloadTime = user_time.get(message.chat.id)
|
||||
try:
|
||||
if userLastDownloadTime > datetime.now():
|
||||
wait_time = round(
|
||||
(userLastDownloadTime - datetime.now()).total_seconds() / 60, 2
|
||||
)
|
||||
await message.reply_text(f"Wait {wait_time} Minutes before next request..")
|
||||
return
|
||||
except:
|
||||
pass
|
||||
|
||||
url = message.command[1]
|
||||
command_to_exec = f"yt-dlp --no-warnings --youtube-skip-dash-manifest -j {url}"
|
||||
t_response = (await shell_exec(command_to_exec))[0]
|
||||
if "ERROR" in t_response:
|
||||
await message.reply_text(t_response, quote=True, disable_web_page_preview=True)
|
||||
return False
|
||||
inline_keyboard = []
|
||||
if t_response:
|
||||
x_reponse = t_response
|
||||
if "\n" in x_reponse:
|
||||
x_reponse, _ = x_reponse.split("\n")
|
||||
response_json = json.loads(x_reponse)
|
||||
randem = random_char(5)
|
||||
if not os.path.exists("./YT_Down"):
|
||||
os.makedirs("./YT_Down")
|
||||
save_ytdl_json_path = f"YT_Down/{str(message.from_user.id)}{randem}.json"
|
||||
with open(save_ytdl_json_path, "w", encoding="utf8") as outfile:
|
||||
json.dump(response_json, outfile, ensure_ascii=False)
|
||||
duration = None
|
||||
if "duration" in response_json:
|
||||
duration = response_json["duration"]
|
||||
if "formats" in response_json:
|
||||
for formats in response_json["formats"]:
|
||||
format_id = formats.get("format_id")
|
||||
format_string = formats.get("format_note")
|
||||
if format_string in ["ultralow", "low", "medium"]:
|
||||
continue
|
||||
if format_string is None:
|
||||
format_string = formats.get("format")
|
||||
format_ext = formats.get("ext")
|
||||
if format_ext == "mhtml":
|
||||
continue
|
||||
if formats.get("filesize"):
|
||||
size = formats["filesize"]
|
||||
elif formats.get("filesize_approx"):
|
||||
size = formats["filesize_approx"]
|
||||
else:
|
||||
size = 0
|
||||
cb_string_video = f"ytdl|video|{format_id}|{format_ext}|{randem}"
|
||||
cb_string_file = f"ytdl|file|{format_id}|{format_ext}|{randem}"
|
||||
if format_string and "audio only" not in format_string:
|
||||
ikeyboard = [
|
||||
InlineKeyboardButton(
|
||||
f"🎬 {format_string} {format_ext} {get_readable_file_size(size)} ",
|
||||
callback_data=(cb_string_video).encode("UTF-8"),
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
f"📄 {format_string} {format_ext} {get_readable_file_size(size)} ",
|
||||
callback_data=(cb_string_file).encode("UTF-8"),
|
||||
),
|
||||
]
|
||||
|
||||
else:
|
||||
# special weird case :\
|
||||
ikeyboard = [
|
||||
InlineKeyboardButton(
|
||||
"SVideo [" + "] ( " + get_readable_file_size(size) + " )",
|
||||
callback_data=(cb_string_video).encode("UTF-8"),
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
"DFile [" + "] ( " + get_readable_file_size(size) + " )",
|
||||
callback_data=(cb_string_file).encode("UTF-8"),
|
||||
),
|
||||
]
|
||||
inline_keyboard.append(ikeyboard)
|
||||
if duration is not None:
|
||||
cb_string_64 = f"ytdl|audio|64k|mp3|{randem}"
|
||||
cb_string_128 = f"ytdl|audio|128k|mp3|{randem}"
|
||||
cb_string = f"ytdl|audio|320k|mp3|{randem}"
|
||||
inline_keyboard.extend(
|
||||
(
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"MP3 " + "(" + "64 kbps" + ")",
|
||||
callback_data=cb_string_64.encode("UTF-8"),
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
"MP3 " + "(" + "128 kbps" + ")",
|
||||
callback_data=cb_string_128.encode("UTF-8"),
|
||||
),
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"MP3 " + "(" + "320 kbps" + ")",
|
||||
callback_data=cb_string.encode("UTF-8"),
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
format_id = response_json["format_id"]
|
||||
format_ext = response_json["ext"]
|
||||
cb_string_file = f"ytdl|file|{format_id}|{format_ext}|{randem}"
|
||||
cb_string_video = f'ytdl|{"video"}|{format_id}|{format_ext}|{randem}'
|
||||
inline_keyboard.append(
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"SVideo", callback_data=(cb_string_video).encode("UTF-8")
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
"DFile", callback_data=(cb_string_file).encode("UTF-8")
|
||||
),
|
||||
]
|
||||
)
|
||||
cb_string_file = f'{"file"}={format_id}={format_ext}'
|
||||
cb_string_video = f'{"video"}={format_id}={format_ext}'
|
||||
inline_keyboard.append(
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"video", callback_data=(cb_string_video).encode("UTF-8")
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
"file", callback_data=(cb_string_file).encode("UTF-8")
|
||||
),
|
||||
]
|
||||
)
|
||||
reply_markup = InlineKeyboardMarkup(inline_keyboard)
|
||||
thumbnail = "https://uxwing.com/wp-content/themes/uxwing/download/signs-and-symbols/no-video-icon.png"
|
||||
thumbnail_image = "https://uxwing.com/wp-content/themes/uxwing/download/signs-and-symbols/no-video-icon.png"
|
||||
if "thumbnail" in response_json and response_json["thumbnail"] is not None:
|
||||
thumbnail = response_json["thumbnail"]
|
||||
thumbnail_image = response_json["thumbnail"]
|
||||
thumb_image_path = DownLoadFile(
|
||||
thumbnail_image,
|
||||
f"YT_Down/{str(message.from_user.id)}{randem}.jpg",
|
||||
128,
|
||||
None,
|
||||
"Trying to download..",
|
||||
message.id,
|
||||
message.chat.id,
|
||||
) # bot,
|
||||
await message.reply_photo(
|
||||
photo=thumb_image_path,
|
||||
quote=True,
|
||||
caption=f"Select the desired format: <a href='{thumbnail}'>file size might be approximate</a>",
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
|
||||
else:
|
||||
cb_string_file = f'{"file"}={"LFO"}={"NONE"}'
|
||||
cb_string_video = f'{"video"}={"OFL"}={"ENON"}'
|
||||
inline_keyboard.append(
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"SVideo", callback_data=(cb_string_video).encode("UTF-8")
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
"DFile", callback_data=(cb_string_file).encode("UTF-8")
|
||||
),
|
||||
]
|
||||
)
|
||||
reply_markup = InlineKeyboardMarkup(inline_keyboard)
|
||||
await message.reply_photo(
|
||||
photo="https://telegra.ph/file/ce37f8203e1903feed544.png",
|
||||
quote=True,
|
||||
caption=f"""Select the desired format: <a href='{""}'>file size might be approximate</a>""",
|
||||
reply_markup=reply_markup,
|
||||
reply_to_message_id=message.id,
|
||||
)
|
||||
|
||||
|
||||
@app.on_callback_query(filters.regex(r"^ytdl|"))
|
||||
async def youtube_dl_call_back(bot, update):
|
||||
cb_data = update.data
|
||||
usr = update.message.reply_to_message
|
||||
if update.from_user.id != usr.from_user.id:
|
||||
return await update.answer("⚠️ Akses Denied!", True)
|
||||
# youtube_dl extractors
|
||||
_, tg_send_type, youtube_dl_format, youtube_dl_ext, ranom = cb_data.split("|")
|
||||
thumb_image_path = f"YT_Down/{str(update.from_user.id)}{ranom}.jpg"
|
||||
save_ytdl_json_path = f"YT_Down/{str(update.from_user.id)}{ranom}.json"
|
||||
try:
|
||||
with open(save_ytdl_json_path, "r", encoding="utf8") as f:
|
||||
response_json = json.load(f)
|
||||
except FileNotFoundError:
|
||||
await update.message.delete()
|
||||
return False
|
||||
|
||||
custom_file_name = (
|
||||
f"{str(response_json.get('title'))}_{youtube_dl_format}.{youtube_dl_ext}"
|
||||
)
|
||||
custom_file_name = "%(title,fulltitle,alt_title)s %(height& |)s%(height|)s%(height&p|)s%(fps|)s%(fps&fps|)s%(tbr& |)s%(tbr|)d.%(ext)s"
|
||||
youtube_dl_url = update.message.reply_to_message.text.split(" ", 1)[1]
|
||||
await update.message.edit_caption("Trying to download media...")
|
||||
tmp_directory_for_each_user = os.path.join(
|
||||
f"downloads/{str(update.from_user.id)}{random_char(5)}"
|
||||
)
|
||||
if not os.path.isdir(tmp_directory_for_each_user):
|
||||
os.makedirs(tmp_directory_for_each_user)
|
||||
download_directory = os.path.join(tmp_directory_for_each_user, custom_file_name)
|
||||
if tg_send_type == "audio":
|
||||
command_to_exec = f"yt-dlp -c --ffmpeg-location '/usr/bin/mediaextract' --max-filesize 2097152000 --prefer-ffmpeg --extract-audio --embed-metadata --audio-format {youtube_dl_ext} --audio-quality {youtube_dl_format} {youtube_dl_url} --output '{download_directory}'"
|
||||
else:
|
||||
minus_f_format = youtube_dl_format
|
||||
if "youtu" in youtube_dl_url:
|
||||
minus_f_format = f"{youtube_dl_format}+bestaudio[ext=m4a]"
|
||||
command_to_exec = f"yt-dlp -c --ffmpeg-location '/usr/bin/mediaextract' --max-filesize 2097152000 --embed-subs --embed-metadata -f {minus_f_format} --hls-prefer-ffmpeg {youtube_dl_url} --output '{download_directory}'"
|
||||
start = datetime.now()
|
||||
t_response = (await shell_exec(command_to_exec))[0]
|
||||
if t_response:
|
||||
os.remove(save_ytdl_json_path)
|
||||
end_one = datetime.now()
|
||||
time_taken_for_download = (end_one - start).seconds
|
||||
file_size = 2097152000 + 1
|
||||
download_directory_dirname = os.path.dirname(download_directory)
|
||||
download_directory_contents = os.listdir(download_directory_dirname)
|
||||
for download_directory_c in download_directory_contents:
|
||||
current_file_name = os.path.join(
|
||||
download_directory_dirname, download_directory_c
|
||||
)
|
||||
file_size = os.stat(current_file_name).st_size
|
||||
|
||||
if file_size == 0:
|
||||
await update.message.edit(text="File Not found 🤒")
|
||||
asyncio.create_task(clendir(tmp_directory_for_each_user))
|
||||
return
|
||||
|
||||
if file_size > 2097152000:
|
||||
await update.message.edit_caption(
|
||||
caption="I cannot upload files greater than 1.95GB due to Telegram API limitations. This file has size {}.".format(
|
||||
get_readable_file_size(file_size)
|
||||
)
|
||||
)
|
||||
asyncio.create_task(clendir(thumb_image_path))
|
||||
asyncio.create_task(clendir(tmp_directory_for_each_user))
|
||||
return
|
||||
|
||||
else:
|
||||
await update.message.edit_caption(caption="Trying to upload..")
|
||||
# get the correct width, height, and duration
|
||||
# for videos greater than 10MB
|
||||
# ref: message from @BotSupport
|
||||
width = 0
|
||||
height = 0
|
||||
duration = 0
|
||||
if tg_send_type != "file":
|
||||
metadata = extractMetadata(createParser(current_file_name))
|
||||
if metadata is not None and metadata.has("duration"):
|
||||
duration = metadata.get("duration").seconds
|
||||
# get the correct width, height, and duration
|
||||
# for videos greater than 10MB
|
||||
if os.path.exists(thumb_image_path):
|
||||
# https://stackoverflow.com/a/21669827/4723940
|
||||
Image.open(thumb_image_path).convert("RGB").save(thumb_image_path)
|
||||
metadata = extractMetadata(createParser(thumb_image_path))
|
||||
if metadata.has("width"):
|
||||
width = metadata.get("width")
|
||||
if metadata.has("height"):
|
||||
height = metadata.get("height")
|
||||
if tg_send_type == "vm":
|
||||
height = width
|
||||
else:
|
||||
thumb_image_path = None
|
||||
start_time = time.time()
|
||||
# try to upload file
|
||||
if tg_send_type == "audio":
|
||||
await update.message.reply_audio(
|
||||
audio=current_file_name,
|
||||
caption=f"<code>{os.path.basename(current_file_name)}</code>",
|
||||
duration=duration,
|
||||
thumb=thumb_image_path,
|
||||
reply_to_message_id=usr.id,
|
||||
progress=progress_for_pyrogram,
|
||||
progress_args=(
|
||||
"Trying to upload...",
|
||||
update.message,
|
||||
start_time,
|
||||
),
|
||||
)
|
||||
elif tg_send_type == "file":
|
||||
await update.message.reply_document(
|
||||
document=current_file_name,
|
||||
thumb=thumb_image_path,
|
||||
caption=f"<code>{os.path.basename(current_file_name)}</code>",
|
||||
reply_to_message_id=usr.id,
|
||||
progress=progress_for_pyrogram,
|
||||
progress_args=(
|
||||
"Trying to upload...",
|
||||
update.message,
|
||||
start_time,
|
||||
),
|
||||
)
|
||||
elif tg_send_type == "vm":
|
||||
await update.message.reply_video_note(
|
||||
video_note=current_file_name,
|
||||
duration=duration,
|
||||
length=width,
|
||||
thumb=thumb_image_path,
|
||||
reply_to_message_id=usr.id,
|
||||
progress=progress_for_pyrogram,
|
||||
progress_args=(
|
||||
"Trying to upload...",
|
||||
update.message,
|
||||
start_time,
|
||||
),
|
||||
)
|
||||
elif tg_send_type == "video":
|
||||
await update.message.reply_video(
|
||||
video=current_file_name,
|
||||
caption=f"<code>{os.path.basename(current_file_name)}</code>",
|
||||
duration=duration,
|
||||
width=width,
|
||||
height=height,
|
||||
supports_streaming=True,
|
||||
reply_to_message_id=usr.id,
|
||||
thumb=thumb_image_path,
|
||||
progress=progress_for_pyrogram,
|
||||
progress_args=(
|
||||
"Trying to upload...",
|
||||
update.message,
|
||||
start_time,
|
||||
),
|
||||
)
|
||||
else:
|
||||
LOGGER.info("Did this happen? :\\")
|
||||
end_two = datetime.now()
|
||||
time_taken_for_upload = (end_two - end_one).seconds
|
||||
await update.message.edit_caption(
|
||||
caption="Downloaded in {} seconds.\nUploaded in {} seconds.".format(
|
||||
time_taken_for_download, time_taken_for_upload
|
||||
)
|
||||
)
|
||||
asyncio.create_task(clendir(thumb_image_path))
|
||||
asyncio.create_task(clendir(tmp_directory_for_each_user))
|
||||
await asyncio.sleep(5)
|
||||
await update.message.delete()
|
||||
|
||||
|
||||
async def clendir(directory):
|
||||
try:
|
||||
shutil.rmtree(directory)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
os.remove(directory)
|
||||
except:
|
||||
pass
|
||||
69
misskaty/vars.py
Normal file
69
misskaty/vars.py
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import logging
|
||||
from os import environ
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv("config.env", override=True)
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def getConfig(name: str):
|
||||
try:
|
||||
return environ[name]
|
||||
except:
|
||||
return ""
|
||||
|
||||
|
||||
# Required ENV
|
||||
try:
|
||||
BOT_TOKEN = getConfig("BOT_TOKEN")
|
||||
API_ID = getConfig("API_ID")
|
||||
API_HASH = getConfig("API_HASH")
|
||||
# MongoDB information
|
||||
DATABASE_URI = getConfig("DATABASE_URI")
|
||||
DATABASE_NAME = getConfig("DATABASE_NAME")
|
||||
LOG_CHANNEL = int(getConfig("LOG_CHANNEL"))
|
||||
USER_SESSION = getConfig("USER_SESSION")
|
||||
except Exception as e:
|
||||
LOGGER.error(f"One or more env variables missing! Exiting now.\n{e}")
|
||||
exit(1)
|
||||
COMMAND_HANDLER = environ.get("COMMAND_HANDLER", "! /").split()
|
||||
SUDO = list(
|
||||
{
|
||||
int(x)
|
||||
for x in environ.get(
|
||||
"SUDO",
|
||||
"617426792 2024984460",
|
||||
).split()
|
||||
}
|
||||
)
|
||||
SUPPORT_CHAT = environ.get("SUPPORT_CHAT", "YasirPediaChannel")
|
||||
|
||||
## Config For AUtoForwarder
|
||||
# Forward From Chat ID
|
||||
FORWARD_FROM_CHAT_ID = list(
|
||||
{
|
||||
int(x)
|
||||
for x in environ.get(
|
||||
"FORWARD_FROM_CHAT_ID",
|
||||
"-1001128045651 -1001455886928 -1001686184174",
|
||||
).split()
|
||||
}
|
||||
)
|
||||
# Forward To Chat ID
|
||||
FORWARD_TO_CHAT_ID = list(
|
||||
{int(x) for x in environ.get("FORWARD_TO_CHAT_ID", "-1001210537567").split()}
|
||||
)
|
||||
FORWARD_FILTERS = list(set(environ.get("FORWARD_FILTERS", "video document").split()))
|
||||
BLOCK_FILES_WITHOUT_EXTENSIONS = bool(
|
||||
environ.get("BLOCK_FILES_WITHOUT_EXTENSIONS", True)
|
||||
)
|
||||
BLOCKED_EXTENSIONS = list(
|
||||
set(
|
||||
environ.get(
|
||||
"BLOCKED_EXTENSIONS",
|
||||
"html htm json txt php gif png ink torrent url nfo xml xhtml jpg",
|
||||
).split()
|
||||
)
|
||||
)
|
||||
MINIMUM_FILE_SIZE = environ.get("MINIMUM_FILE_SIZE", None)
|
||||
100
utils.py
Normal file
100
utils.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import logging
|
||||
from pyrogram.errors import FloodWait, InputUserDeactivated, PeerIdInvalid, UserIsBlocked
|
||||
import asyncio
|
||||
from pyrogram.types import Message
|
||||
from typing import Union
|
||||
import os
|
||||
import emoji
|
||||
from database.users_chats_db import db
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
BANNED = {}
|
||||
|
||||
|
||||
# temp db for banned
|
||||
class temp(object):
|
||||
BANNED_USERS = []
|
||||
BANNED_CHATS = []
|
||||
ME = None
|
||||
CURRENT = int(os.environ.get("SKIP", 2))
|
||||
CANCEL = False
|
||||
MELCOW = {}
|
||||
U_NAME = None
|
||||
B_NAME = None
|
||||
|
||||
|
||||
def demoji(teks):
|
||||
return emoji.emojize(f":{teks.replace(' ', '_').replace('-', '_')}:")
|
||||
|
||||
|
||||
async def broadcast_messages(user_id, message):
|
||||
try:
|
||||
await message.copy(chat_id=user_id)
|
||||
return True, "Succes"
|
||||
except FloodWait as e:
|
||||
await asyncio.sleep(e.x)
|
||||
return await broadcast_messages(user_id, message)
|
||||
except InputUserDeactivated:
|
||||
await db.delete_user(int(user_id))
|
||||
logging.info(f"{user_id}-Removed from Database, since deleted account.")
|
||||
return False, "Deleted"
|
||||
except UserIsBlocked:
|
||||
logging.info(f"{user_id} -Blocked the bot.")
|
||||
return False, "Blocked"
|
||||
except PeerIdInvalid:
|
||||
await db.delete_user(int(user_id))
|
||||
logging.info(f"{user_id} - PeerIdInvalid")
|
||||
return False, "Error"
|
||||
except Exception:
|
||||
return False, "Error"
|
||||
|
||||
|
||||
def get_size(size):
|
||||
"""Get size in readable format"""
|
||||
|
||||
units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB"]
|
||||
size = float(size)
|
||||
i = 0
|
||||
while size >= 1024.0 and i < len(units):
|
||||
i += 1
|
||||
size /= 1024.0
|
||||
return "%.2f %s" % (size, units[i])
|
||||
|
||||
|
||||
def get_file_id(msg: Message):
|
||||
if msg.media:
|
||||
for message_type in ("photo", "animation", "audio", "document", "video", "video_note", "voice", "sticker"):
|
||||
if obj := getattr(msg, message_type):
|
||||
setattr(obj, "message_type", message_type)
|
||||
return obj
|
||||
|
||||
|
||||
def extract_user(message: Message) -> Union[int, str]:
|
||||
"""extracts the user from a message"""
|
||||
# https://github.com/SpEcHiDe/PyroGramBot/blob/f30e2cca12002121bad1982f68cd0ff9814ce027/pyrobot/helper_functions/extract_user.py#L7
|
||||
user_id = None
|
||||
user_first_name = None
|
||||
if message.reply_to_message:
|
||||
user_id = message.reply_to_message.from_user.id
|
||||
user_first_name = message.reply_to_message.from_user.first_name
|
||||
|
||||
elif len(message.command) > 1:
|
||||
if len(message.entities) > 1 and message.entities[1].type == "text_mention":
|
||||
|
||||
required_entity = message.entities[1]
|
||||
user_id = required_entity.user.id
|
||||
user_first_name = required_entity.user.first_name
|
||||
else:
|
||||
user_id = message.command[1]
|
||||
# don't want to make a request -_-
|
||||
user_first_name = user_id
|
||||
try:
|
||||
user_id = int(user_id)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
user_id = message.from_user.id
|
||||
user_first_name = message.from_user.first_name
|
||||
return (user_id, user_first_name)
|
||||
Loading…
Reference in a new issue