Add nightmode plugin and some fix

This commit is contained in:
yasir 2023-02-16 14:12:03 +07:00
parent 9992970b78
commit c4105fddbe
5 changed files with 217 additions and 10 deletions

17
database/nightmode_db.py Normal file
View file

@ -0,0 +1,17 @@
from . import mongo, dbname
import os
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.jobstores.mongodb import MongoDBJobStore
TZ = os.environ.get("TIME_ZONE", "Asia/Jakarta")
jobstores = {
'default': MongoDBJobStore(
client=mongo,
database=dbname,
collection='nightmode')}
scheduler = AsyncIOScheduler(
jobstores=jobstores,
timezone=TZ)

View file

@ -18,7 +18,7 @@ def ratelimiter(func: Callable) -> Callable:
@wraps(func)
async def decorator(client: Client, update: Union[Message, CallbackQuery]):
userid = update.from_user.id or update.sender_chat.id
userid = update.from_user.id if update.from_user else update.sender_chat.id
is_limited = await ratelimit.acquire(userid)
if is_limited and userid not in warned_users:

View file

@ -13,17 +13,17 @@ class RateLimiter:
def __init__(self) -> None:
# 3 requests per seconds
self.second_rate = RequestRate(3, Duration.SECOND)
# 2 requests per seconds
self.second_rate = RequestRate(2, Duration.SECOND)
# 20 requests per minute.
self.minute_rate = RequestRate(20, Duration.MINUTE)
# 15 requests per minute.
self.minute_rate = RequestRate(15, Duration.MINUTE)
# 1000 requests per hour
self.hourly_rate = RequestRate(1000, Duration.HOUR)
# 500 requests per hour
self.hourly_rate = RequestRate(500, Duration.HOUR)
# 10000 requests per day
self.daily_rate = RequestRate(10000, Duration.DAY)
# 1500 requests per day
self.daily_rate = RequestRate(1500, Duration.DAY)
self.limiter = Limiter(
self.minute_rate,

View file

@ -312,7 +312,7 @@ async def who_is(client, message):
if message.chat.type.value 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")
joined_date = chat_member_p.joined_date
message_out_str += "<b>➲Joined this Chat on:</b> <code>" f"{joined_date}" "</code>\n"
except UserNotParticipant:
pass

View file

@ -0,0 +1,190 @@
from email import message
import re
from datetime import datetime, timedelta
import pytz
from apscheduler.jobstores.base import ConflictingIdError
from pyrogram import filters
from pyrogram.errors import (ChannelInvalid, ChannelPrivate, ChatAdminRequired,
ChatNotModified)
from pyrogram.types import ChatPermissions
from database.nightmode_db import TZ, scheduler
from misskaty import BOT_NAME, app
from misskaty.core.message_utils import *
from misskaty.core.decorator.permissions import adminsOnly
from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL
__MODULE__ = "NightMode"
__HELP__ = """<b>Enable or disable nightmode (locks the chat at specified intervals everyday)</b>
<b>Flags:</b>
'-s': "Specify starting time in 24hr format."
'-e': "Specify duration in hours / minute"
'-d': "Disable nightmode for chat."
<b>Examples:</b>
/nightmode -s=23:53 -e=6h
/nightmode -s=23:50 -e=120m
/nightmode -d
"""
TIME_ZONE = pytz.timezone(TZ)
def extract_time(time_val: str):
if any(time_val.endswith(unit) for unit in ('m', 'h')):
unit = time_val[-1]
time_num = time_val[:-1]
if not time_num.isdigit():
return ""
if unit == 'm':
time = int(time_num) * 60
elif unit == 'h':
time = int(time_num) * 60 * 60
else:
return ""
return time
return ""
async def un_mute_chat(chat_id: int, perm: ChatPermissions):
try:
await app.set_chat_permissions(chat_id, perm)
except ChatAdminRequired:
await app.send_message(
LOG_CHANNEL,
f"#NIGHT_MODE_FAIL\nFailed to turn off nightmode at `{chat_id}`,"
f"since {BOT_NAME} is not an admin in chat `{chat_id}`")
except (ChannelInvalid, ChannelPrivate):
scheduler.remove_job(f"enable_nightmode_{chat_id}")
scheduler.remove_job(f"disable_nightmode_{chat_id}")
await app.send_message(
LOG_CHANNEL,
f"#NIGHT_MODE_FAIL\nFailed to turn off nightmode at `{chat_id}`,"
f"since {BOT_NAME} is not present in chat `{chat_id}`"
" Removed group from list.")
except ChatNotModified:
pass
except Exception as e:
await app.send_message(
LOG_CHANNEL,
f"#NIGHT_MODE_FAIL\nFailed to turn off nightmode at `{chat_id}`\n"
f"ERROR: `{e}`")
else:
job = scheduler.get_job(f"enable_nightmode_{chat_id}")
close_at = job.next_run_time
await app.send_message(
chat_id,
f"#AUTOMATED_HANDLER\nGroup is Opening.\nWill be closed at {close_at}")
await app.send_message(
LOG_CHANNEL,
f"#NIGHT_MODE_SUCCESS\nSuccessfully turned off nightmode at `{chat_id}`,")
async def mute_chat(chat_id: int):
try:
await app.set_chat_permissions(chat_id, ChatPermissions())
except ChatAdminRequired:
await app.send_message(
LOG_CHANNEL,
f"#NIGHT_MODE_FAIL\nFailed to enable nightmode at `{chat_id}`,"
f"since {BOT_NAME} is not an admin in chat `{chat_id}`")
except (ChannelInvalid, ChannelPrivate):
scheduler.remove_job(f"enable_nightmode_{chat_id}")
scheduler.remove_job(f"disable_nightmode_{chat_id}")
await app.send_message(
LOG_CHANNEL,
f"#NIGHT_MODE_FAIL\nFailed to enable nightmode at `{chat_id}`,"
f"since {BOT_NAME} is not present in chat `{chat_id}`"
" Removed group from list.")
except ChatNotModified:
pass
except Exception as e:
await app.send_message(
LOG_CHANNEL,
f"#NIGHT_MODE_FAIL\nFailed to enable nightmode at `{chat_id}`\n"
f"ERROR: `{e}`")
else:
job = scheduler.get_job(f"disable_nightmode_{chat_id}")
open_at = job.next_run_time
await app.send_message(
chat_id,
f"#AUTOMATED_HANDLER\nGroup is closing.\nWill be opened at {open_at}")
await app.send_message(
LOG_CHANNEL,
f"#NIGHT_MODE_SUCCESS\nSuccessfully turned on nightmode at `{chat_id}`,")
@app.on_message(filters.command("nightmode", COMMAND_HANDLER) & filters.group)
@adminsOnly("can_change_info")
async def nightmode_handler(c, msg):
chat_id = msg.chat.id
if "-d" in msg.text:
job = scheduler.get_job(job_id=f"enable_nightmode_{chat_id}")
if job:
scheduler.remove_job(job_id=f"enable_nightmode_{chat_id}")
scheduler.remove_job(job_id=f"disable_nightmode_{chat_id}")
if not bool(scheduler.get_jobs()) and bool(scheduler.state):
scheduler.shutdown()
return await kirimPesan(msg, 'Nightmode disabled.')
return await kirimPesan(msg, "Nightmode isn't enabled in this chat.")
starttime = re.findall(r"-s=(\d+:\d+)", msg.text)
start = starttime if starttime else "00:00"
now = datetime.now(TIME_ZONE)
try:
start_timestamp = TIME_ZONE.localize(
datetime.strptime(
(now.strftime('%m:%d:%Y - ') + start),
'%m:%d:%Y - %H:%M'))
except ValueError:
return await kirimPesan(msg, "Invalid time format. Use HH:MM format.")
lockdur = re.findall(r"-e=(\w+)", msg.text)
lockdur = lockdur if lockdur else "6h"
lock_dur = extract_time(lockdur.lower())
if not lock_dur:
return await kirimPesan(
msg,
'Invalid time duration. Use proper format.'
'\nExample: 6h (for 6 hours), 10m for 10 minutes.')
if start_timestamp < now:
start_timestamp = start_timestamp + timedelta(days=1)
end_time_stamp = start_timestamp + timedelta(seconds=int(lock_dur))
try:
# schedule to enable nightmode
scheduler.add_job(
mute_chat,
'interval',
[chat_id],
id=f"enable_nightmode_{chat_id}",
days=1,
next_run_time=start_timestamp,
max_instances=50,
misfire_grace_time=None)
# schedule to disable nightmode
scheduler.add_job(
un_mute_chat,
'interval',
[chat_id,
msg.chat.permissions],
id=f"disable_nightmode_{chat_id}",
days=1,
next_run_time=end_time_stamp,
max_instances=50,
misfire_grace_time=None)
except ConflictingIdError:
return await kirimPesan(
msg,
'Already a schedule is running in this chat. Disable it using `-d` flag.')
await kirimPesan(
msg,
'Successfully enabled nightmode in this chat.\n'
f'Group will be locked at {start_timestamp.strftime("%H:%M:%S")}'
f' and will be opened after {lockdur} everyday.')
if not bool(scheduler.state):
scheduler.start()
if bool(scheduler.get_jobs()):
scheduler.start()