Rilis Pertama

This commit is contained in:
yasir 2022-12-01 22:27:03 +07:00
commit 6142c2a5e5
71 changed files with 9610 additions and 0 deletions

26
.github/workflows/notify.yml vendored Normal file
View 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
View 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

Binary file not shown.

12
Dockerfile Normal file
View 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
View 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
View 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
[![GNU Affero General Public License 2.0](https://www.gnu.org/graphics/agplv3-155x51.png)](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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
img/profilepic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

32
logging.conf Normal file
View 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
View 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
View 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 -----------------------")

View 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

View 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
View 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)

View file

@ -0,0 +1 @@
from .misc import paginate_modules

View 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
View 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,
)

View 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
View 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)

View 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

View 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
View 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

View 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

View 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)

View 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
View 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")
)

View 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

View 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"]

View file

715
misskaty/plugins/admin.py Normal file
View 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
View 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

View 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)

View 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

View 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)

View 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}"
)

View 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..")

View 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)

View 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.")

View 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
View 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

View 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("&amp;", "&")
except:
url = resjson["result"]["links"]["sd"].replace("&amp;", "&")
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()

View 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
View 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

View 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")

View 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()

View 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
View 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
View 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)

View 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
View 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."
)

View 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>")

View 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
View 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
View 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
View 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
View 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}")

View 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
View 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)}")

View 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}")

View 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}",
)

View 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
View 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))

View 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
View 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
View 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)