mirror of
https://github.com/MuRuLOSE/limoka.git
synced 2026-06-16 14:34:17 +02:00
Commited backup
This commit is contained in:
454
AlpacaGang/ftg-modules/DND.py
Normal file
454
AlpacaGang/ftg-modules/DND.py
Normal file
@@ -0,0 +1,454 @@
|
||||
# -*- coding: future_fstrings -*-
|
||||
|
||||
# Friendly Telegram (telegram userbot)
|
||||
# By Magical Unicorn (based on official Anti PM & AFK Friendly Telegram modules)
|
||||
# Copyright (C) 2020 Magical Unicorn
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
import logging
|
||||
import datetime
|
||||
import time
|
||||
|
||||
from telethon import functions, types
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register(cb):
|
||||
cb(DoNotDisturbMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class DoNotDisturbMod(loader.Module):
|
||||
"""
|
||||
DND (Do Not Disturb) :
|
||||
-> Prevents people sending you unsolicited private messages.
|
||||
-> Prevents disturbing when you are unavailable.\n
|
||||
Commands :
|
||||
|
||||
"""
|
||||
strings = {"name": "DND",
|
||||
"afk": "<b>I'm AFK right now (since</b> <i>{}</i> <b>ago).</b>",
|
||||
"afk_back": "<b>I'm goin' BACK !</b>",
|
||||
"afk_gone": "<b>I'm goin' AFK !</b>",
|
||||
"afk_no_group_off": "<b>AFK status message enabled for group chats.</b>",
|
||||
"afk_no_group_on": "<b>AFK status message disabled for group chats.</b>",
|
||||
"afk_no_pm_off": "<b>AFK status message enabled for PMs.</b>",
|
||||
"afk_no_pm_on": "<b>AFK status message disabled for PMs.</b>",
|
||||
"afk_notif_off": "<b>Notifications are now disabled during AFK time.</b>",
|
||||
"afk_notif_on": "<b>Notifications are now enabled during AFK time.</b>",
|
||||
"afk_rate_limit_off": "<b>AFK status message rate limit disabled.</b>",
|
||||
"afk_rate_limit_on": ("<b>AFK status message rate limit enabled.</b>"
|
||||
"\n\n<b>One AFK status message max will be sent per chat.</b>"),
|
||||
"afk_reason": ("<b>I'm AFK right now (since {} ago).</b>"
|
||||
"\n\n<b>Reason :</b> <i>{}</i>"),
|
||||
"arg_on_off": "<b>Argument must be 'off' or 'on' !</b>",
|
||||
"pm_off": ("<b>Automatic answer for denied PMs disabled."
|
||||
"\n\nUsers are now free to PM !</b>"),
|
||||
"pm_on": "<b>An automatic answer is now sent for denied PMs.</b>",
|
||||
"pm_allowed": "<b>I have allowed</b> <a href='tg://user?id={}'>you</a> <b>to PM now.</b>",
|
||||
"pm_blocked": ("<b>I don't want any PM from</b> <a href='tg://user?id={}'>you</a>, "
|
||||
"<b>so you have been blocked !</b>"),
|
||||
"pm_denied": "<b>I have denied</b> <a href='tg://user?id={}'>you</a> <b>to PM now.</b>",
|
||||
"pm_go_away": ("Hey there! Unfortunately, I don't accept private messages from strangers."
|
||||
"\n\nPlease contact me in a group, or <b>wait</b> for me to approve you."),
|
||||
"pm_reported": "<b>You just got reported to spam !</b>",
|
||||
"pm_limit_arg": "<b>Argument must be 'off', 'on' or a number between 10 and 1000 !</b>",
|
||||
"pm_limit_off": "<b>Not allowed users are now free to PM without be automatically blocked.</b>",
|
||||
"pm_limit_on": "<b>Not allowed users are now blocked after {} PMs.</b>",
|
||||
"pm_limit_current": "<b>Current limit is {}.</b>",
|
||||
"pm_limit_current_no": "<b>Automatic user blocking is currently disabled.</b>",
|
||||
"pm_limit_reset": "<b>Limit reseted to {}.</b>",
|
||||
"pm_limit_set": "<b>Limit set to {}.</b>",
|
||||
"pm_notif_off": "<b>Notifications from denied PMs are now disabled.</b>",
|
||||
"pm_notif_on": "<b>Notifications from denied PMs are now enabled.</b>",
|
||||
"pm_triggered": ("Hey! I don't appreciate you barging into my PM like this !"
|
||||
"\nDid you even ask me for approving you to PM ? No ?"
|
||||
"\nGoodbye then."
|
||||
"\n\nPS: You've been reported as spam."),
|
||||
"pm_unblocked": ("<b>Alright fine! I'll forgive them this time. PM has been unblocked for</b> "
|
||||
"<a href='tg://user?id={}'>this user</a>."),
|
||||
"unknow": ("An unknow problem as occured."
|
||||
"\n\nPlease report problem with logs on "
|
||||
"<a href='https://github.com/LegendaryUnicorn/FTG-Unofficial-Modules'>Github</a>."),
|
||||
"who_to_allow": "<b>Who shall I allow to PM ?</b>",
|
||||
"who_to_block": "<b>Specify who to block.</b>",
|
||||
"who_to_deny": "<b>Who shall I deny to PM ?</b>",
|
||||
"who_to_report": "<b>Who shall I report ?</b>",
|
||||
"who_to_unblock": "<b>Specify who to unblock.</b>"}
|
||||
|
||||
def __init__(self):
|
||||
self._me = None
|
||||
self.default_pm_limit = 50
|
||||
|
||||
def config_complete(self):
|
||||
self.name = self.strings["name"]
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self._db = db
|
||||
self._client = client
|
||||
self._me = await client.get_me(True)
|
||||
|
||||
async def afkbackcmd(self, message):
|
||||
"""Remove the AFK status.\n """
|
||||
self._db.set(__name__, "afk", False)
|
||||
self._db.set(__name__, "afk_gone", None)
|
||||
self._db.set(__name__, "afk_rate", [])
|
||||
await utils.answer(message, self.strings["afk_back"])
|
||||
|
||||
async def afkgocmd(self, message):
|
||||
"""
|
||||
.afkgo : Enable AFK status.
|
||||
.afkgo [message] : Enable AFK status and add a reason.
|
||||
|
||||
"""
|
||||
if utils.get_args_raw(message):
|
||||
self._db.set(__name__, "afk", utils.get_args_raw(message))
|
||||
else:
|
||||
self._db.set(__name__, "afk", True)
|
||||
self._db.set(__name__, "afk_gone", time.time())
|
||||
self._db.set(__name__, "afk_rate", [])
|
||||
await utils.answer(message, self.strings["afk_gone"])
|
||||
|
||||
async def afknogroupcmd(self, message):
|
||||
"""
|
||||
.afknogroup : Disable/Enable AFK status message for group chats.
|
||||
.afknogroup off : Enable AFK status message for group chats.
|
||||
.afknogroup on : Disable AFK status message for group chats.
|
||||
|
||||
"""
|
||||
if utils.get_args_raw(message):
|
||||
afknogroup_arg = utils.get_args_raw(message)
|
||||
if afknogroup_arg == "off":
|
||||
self._db.set(__name__, "afk_no_group", False)
|
||||
await utils.answer(message, self.strings["afk_no_group_off"])
|
||||
elif afknogroup_arg == "on":
|
||||
self._db.set(__name__, "afk_no_group", True)
|
||||
await utils.answer(message, self.strings["afk_no_group_on"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["arg_on_off"])
|
||||
else:
|
||||
afknogroup_current = self._db.get(__name__, "afk_no_group")
|
||||
if afknogroup_current is None or afknogroup_current is False:
|
||||
self._db.set(__name__, "afk_no_group", True)
|
||||
await utils.answer(message, self.strings["afk_no_group_on"])
|
||||
elif afknogroup_current is True:
|
||||
self._db.set(__name__, "afk_no_group", False)
|
||||
await utils.answer(message, self.strings["afk_no_group_off"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
|
||||
async def afknopmcmd(self, message):
|
||||
"""
|
||||
.afknopm : Disable/Enable AFK status message for PMs.
|
||||
.afknopm off : Enable AFK status message for PMs.
|
||||
.afknopm on : Disable AFK status message for PMs.
|
||||
|
||||
"""
|
||||
if utils.get_args_raw(message):
|
||||
afknopm_arg = utils.get_args_raw(message)
|
||||
if afknopm_arg == "off":
|
||||
self._db.set(__name__, "afk_no_pm", False)
|
||||
await utils.answer(message, self.strings["afk_no_pm_off"])
|
||||
elif afknopm_arg == "on":
|
||||
self._db.set(__name__, "afk_no_pm", True)
|
||||
await utils.answer(message, self.strings["afk_no_pm_on"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["arg_on_off"])
|
||||
else:
|
||||
afknopm_current = self._db.get(__name__, "afk_no_pm")
|
||||
if afknopm_current is None or afknopm_current is False:
|
||||
self._db.set(__name__, "afk_no_pm", True)
|
||||
await utils.answer(message, self.strings["afk_no_pm_on"])
|
||||
elif afknopm_current is True:
|
||||
self._db.set(__name__, "afk_no_pm", False)
|
||||
await utils.answer(message, self.strings["afk_no_pm_off"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
|
||||
async def afknotifcmd(self, message):
|
||||
"""
|
||||
.afknotif : Disable/Enable the notifications during AFK time.
|
||||
.afknotif off : Disable the notifications during AFK time.
|
||||
.afknotif on : Enable the notifications during AFK time.
|
||||
|
||||
"""
|
||||
if utils.get_args_raw(message):
|
||||
afknotif_arg = utils.get_args_raw(message)
|
||||
if afknotif_arg == "off":
|
||||
self._db.set(__name__, "afk_notif", False)
|
||||
await utils.answer(message, self.strings["afk_notif_off"])
|
||||
elif afknotif_arg == "on":
|
||||
self._db.set(__name__, "afk_notif", True)
|
||||
await utils.answer(message, self.strings["afk_notif_on"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["arg_on_off"])
|
||||
else:
|
||||
afknotif_current = self._db.get(__name__, "afk_notif")
|
||||
if afknotif_current is None or afknotif_current is False:
|
||||
self._db.set(__name__, "afk_notif", True)
|
||||
await utils.answer(message, self.strings["afk_notif_on"])
|
||||
elif afknotif_current is True:
|
||||
self._db.set(__name__, "afk_notif", False)
|
||||
await utils.answer(message, self.strings["afk_notif_off"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
|
||||
async def afkratecmd(self, message):
|
||||
"""
|
||||
.afkrate : Disable/Enable AFK rate limit.
|
||||
.afkrate off : Disable AFK rate limit.
|
||||
.afkrate on : Enable AFK rate limit. One AFK status message max will be sent per chat.
|
||||
|
||||
"""
|
||||
if utils.get_args_raw(message):
|
||||
afkrate_arg = utils.get_args_raw(message)
|
||||
if afkrate_arg == "off":
|
||||
self._db.set(__name__, "afk_rate_limit", False)
|
||||
await utils.answer(message, self.strings["afk_rate_limit_off"])
|
||||
elif afkrate_arg == "on":
|
||||
self._db.set(__name__, "afk_rate_limit", True)
|
||||
await utils.answer(message, self.strings["afk_rate_limit_on"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["arg_on_off"])
|
||||
else:
|
||||
afkrate_current = self._db.get(__name__, "afk_rate_limit")
|
||||
if afkrate_current is None or afkrate_current is False:
|
||||
self._db.set(__name__, "afk_rate_limit", True)
|
||||
await utils.answer(message, self.strings["afk_rate_limit_on"])
|
||||
elif afkrate_current is True:
|
||||
self._db.set(__name__, "afk_rate_limit", False)
|
||||
await utils.answer(message, self.strings["afk_rate_limit_off"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
|
||||
async def allowcmd(self, message):
|
||||
"""Allow this user to PM.\n """
|
||||
user = await utils.get_target(message)
|
||||
if not user:
|
||||
await utils.answer(message, self.strings["who_to_allow"])
|
||||
return
|
||||
self._db.set(__name__, "allow", list(set(self._db.get(__name__, "allow", [])).union({user})))
|
||||
await utils.answer(message, self.strings["pm_allowed"].format(user))
|
||||
|
||||
async def blockcmd(self, message):
|
||||
"""Block this user to PM without being warned.\n """
|
||||
user = await utils.get_target(message)
|
||||
if not user:
|
||||
await utils.answer(message, self.strings["who_to_block"])
|
||||
return
|
||||
await message.client(functions.contacts.BlockRequest(user))
|
||||
await utils.answer(message, self.strings["pm_blocked"].format(user))
|
||||
|
||||
async def denycmd(self, message):
|
||||
"""Deny this user to PM without being warned.\n """
|
||||
user = await utils.get_target(message)
|
||||
if not user:
|
||||
await utils.answer(message, self.strings["who_to_deny"])
|
||||
return
|
||||
self._db.set(__name__, "allow", list(set(self._db.get(__name__, "allow", [])).difference({user})))
|
||||
await utils.answer(message, self.strings["pm_denied"].format(user))
|
||||
|
||||
async def pmcmd(self, message):
|
||||
"""
|
||||
.pm : Disable/Enable automatic answer for denied PMs.
|
||||
.pm off : Disable automatic answer for denied PMs.
|
||||
.pm on : Enable automatic answer for denied PMs.
|
||||
|
||||
"""
|
||||
if utils.get_args_raw(message):
|
||||
pm_arg = utils.get_args_raw(message)
|
||||
if pm_arg == "off":
|
||||
self._db.set(__name__, "pm", True)
|
||||
await utils.answer(message, self.strings["pm_off"])
|
||||
elif pm_arg == "on":
|
||||
self._db.set(__name__, "pm", False)
|
||||
await utils.answer(message, self.strings["pm_on"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["arg_on_off"])
|
||||
else:
|
||||
pm_current = self._db.get(__name__, "pm")
|
||||
if pm_current is None or pm_current is False:
|
||||
self._db.set(__name__, "pm", True)
|
||||
await utils.answer(message, self.strings["pm_off"])
|
||||
elif pm_current is True:
|
||||
self._db.set(__name__, "pm", False)
|
||||
await utils.answer(message, self.strings["pm_on"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
|
||||
async def pmlimitcmd(self, message):
|
||||
"""
|
||||
.pmlimit : Get current max number of PMs before automatically block not allowed user.
|
||||
.pmlimit off : Disable automatic user blocking.
|
||||
.pmlimit on : Enable automatic user blocking.
|
||||
.pmlimit reset : Reset max number of PMs before automatically block not allowed user.
|
||||
.pmlimit [number] : Modify max number of PMs before automatically block not allowed user.
|
||||
|
||||
"""
|
||||
if utils.get_args_raw(message):
|
||||
pmlimit_arg = utils.get_args_raw(message)
|
||||
if pmlimit_arg == "off":
|
||||
self._db.set(__name__, "pm_limit", False)
|
||||
await utils.answer(message, self.strings["pm_limit_off"])
|
||||
return
|
||||
elif pmlimit_arg == "on":
|
||||
self._db.set(__name__, "pm_limit", True)
|
||||
pmlimit_on = self.strings["pm_limit_on"].format(self.get_current_limit())
|
||||
await utils.answer(message, pmlimit_on)
|
||||
return
|
||||
elif pmlimit_arg == "reset":
|
||||
self._db.set(__name__, "pm_limit_max", self.default_pm_limit)
|
||||
pmlimit_reset = self.strings["pm_limit_reset"].format(self.get_current_pm_limit())
|
||||
await utils.answer(message, pmlimit_reset)
|
||||
return
|
||||
else:
|
||||
try:
|
||||
pmlimit_number = int(pmlimit_arg)
|
||||
if pmlimit_number >= 10 and pmlimit_number <= 1000:
|
||||
self._db.set(__name__, "pm_limit_max", pmlimit_number)
|
||||
pmlimit_new = self.strings["pm_limit_set"].format(self.get_current_pm_limit())
|
||||
await utils.answer(message, pmlimit_new)
|
||||
return
|
||||
else:
|
||||
await utils.answer(message, self.strings["pm_limit_arg"])
|
||||
return
|
||||
except ValueError:
|
||||
await utils.answer(message, self.strings["pm_limit_arg"])
|
||||
return
|
||||
await utils.answer(message, self.strings["limit_arg"])
|
||||
else:
|
||||
pmlimit = self._db.get(__name__, "pm_limit")
|
||||
if pmlimit is None or pmlimit is False:
|
||||
pmlimit_current = self.strings["pm_limit_current_no"]
|
||||
elif pmlimit is True:
|
||||
pmlimit_current = self.strings["pm_limit_current"].format(self.get_current_pm_limit())
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
return
|
||||
await utils.answer(message, pmlimit_current)
|
||||
|
||||
async def pmnotifcmd(self, message):
|
||||
"""
|
||||
.pmnotif : Disable/Enable the notifications from denied PMs.
|
||||
.pmnotif off : Disable the notifications from denied PMs.
|
||||
.pmnotif on : Enable the notifications from denied PMs.
|
||||
|
||||
"""
|
||||
if utils.get_args_raw(message):
|
||||
pmnotif_arg = utils.get_args_raw(message)
|
||||
if pmnotif_arg == "off":
|
||||
self._db.set(__name__, "pm_notif", False)
|
||||
await utils.answer(message, self.strings["pm_notif_off"])
|
||||
elif pmnotif_arg == "on":
|
||||
self._db.set(__name__, "pm_notif", True)
|
||||
await utils.answer(message, self.strings["pm_notif_on"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["arg_on_off"])
|
||||
else:
|
||||
pmnotif_current = self._db.get(__name__, "pm_notif")
|
||||
if pmnotif_current is None or pmnotif_current is False:
|
||||
self._db.set(__name__, "pm_notif", True)
|
||||
await utils.answer(message, self.strings["pm_notif_on"])
|
||||
elif pmnotif_current is True:
|
||||
self._db.set(__name__, "pm_notif", False)
|
||||
await utils.answer(message, self.strings["pm_notif_off"])
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
|
||||
async def reportcmd(self, message):
|
||||
"""Report the user to spam. Use only in PM.\n """
|
||||
user = await utils.get_target(message)
|
||||
if not user:
|
||||
await utils.answer(message, self.strings["who_to_report"])
|
||||
return
|
||||
self._db.set(__name__, "allow", list(set(self._db.get(__name__, "allow", [])).difference({user})))
|
||||
if message.is_reply and isinstance(message.to_id, types.PeerChannel):
|
||||
await message.client(functions.messages.ReportRequest(peer=message.chat_id,
|
||||
id=[message.reply_to_msg_id],
|
||||
reason=types.InputReportReasonSpam()))
|
||||
else:
|
||||
await message.client(functions.messages.ReportSpamRequest(peer=message.to_id))
|
||||
await utils.answer(message, self.strings["pm_reported"])
|
||||
|
||||
async def unblockcmd(self, message):
|
||||
"""Unblock this user to PM."""
|
||||
user = await utils.get_target(message)
|
||||
if not user:
|
||||
await utils.answer(message, self.strings["who_to_unblock"])
|
||||
return
|
||||
await message.client(functions.contacts.UnblockRequest(user))
|
||||
await utils.answer(message, self.strings["pm_unblocked"].format(user))
|
||||
|
||||
async def watcher(self, message):
|
||||
user = await utils.get_user(message)
|
||||
pm = self._db.get(__name__, "pm")
|
||||
if getattr(message.to_id, "user_id", None) == self._me.user_id and (pm is None or pm is False):
|
||||
if not user.is_self and not user.bot and not user.verified and not self.get_allowed(message.from_id):
|
||||
await utils.answer(message, self.strings["pm_go_away"])
|
||||
if self._db.get(__name__, "pm_limit") is True:
|
||||
pms = self._db.get(__name__, "pms", {})
|
||||
pm_limit = self._db.get(__name__, "pm_limit_max")
|
||||
pm_user = pms.get(message.from_id, 0)
|
||||
if isinstance(pm_limit, int) and pm_limit >= 10 and pm_limit <= 1000 and pm_user >= pm_limit:
|
||||
await utils.answer(message, self.strings["pm_triggered"])
|
||||
await message.client(functions.contacts.BlockRequest(message.from_id))
|
||||
await message.client(functions.messages.ReportSpamRequest(peer=message.from_id))
|
||||
del pms[message.from_id]
|
||||
self._db.set(__name__, "pms", pms)
|
||||
else:
|
||||
self._db.set(__name__, "pms", {**pms, message.from_id: pms.get(message.from_id, 0) + 1})
|
||||
pm_notif = self._db.get(__name__, "pm_notif")
|
||||
if pm_notif is None or pm_notif is False:
|
||||
await message.client.send_read_acknowledge(message.chat_id)
|
||||
return
|
||||
if message.mentioned or getattr(message.to_id, "user_id", None) == self._me.user_id:
|
||||
afk_status = self._db.get(__name__, "afk")
|
||||
if user.is_self or user.bot or user.verified or afk_status is False:
|
||||
return
|
||||
if message.mentioned and self._db.get(__name__, "afk_no_group") is True:
|
||||
return
|
||||
afk_no_pm = self._db.get(__name__, "afk_no_pm")
|
||||
if getattr(message.to_id, "user_id", None) == self._me.user_id and afk_no_pm is True:
|
||||
return
|
||||
if self._db.get(__name__, "afk_rate_limit") is True:
|
||||
afk_rate = self._db.get(__name__, "afk_rate", [])
|
||||
if utils.get_chat_id(message) in afk_rate:
|
||||
return
|
||||
else:
|
||||
self._db.setdefault(__name__, {}).setdefault("afk_rate", []).append(utils.get_chat_id(message))
|
||||
self._db.save()
|
||||
now = datetime.datetime.now().replace(microsecond=0)
|
||||
gone = datetime.datetime.fromtimestamp(self._db.get(__name__, "afk_gone")).replace(microsecond=0)
|
||||
diff = now - gone
|
||||
if afk_status is True:
|
||||
afk_message = self.strings["afk"].format(diff)
|
||||
elif afk_status is not False:
|
||||
afk_message = self.strings["afk_reason"].format(diff, afk_status)
|
||||
await utils.answer(message, afk_message)
|
||||
_notif = self._db.get(__name__, "_notif")
|
||||
if _notif is None or _notif is False:
|
||||
await message.client.send_read_acknowledge(message.chat_id)
|
||||
|
||||
def get_allowed(self, id):
|
||||
return id in self._db.get(__name__, "allow", [])
|
||||
|
||||
def get_current_pm_limit(self):
|
||||
pm_limit = self._db.get(__name__, "pm_limit_max")
|
||||
if not isinstance(pm_limit, int) or pm_limit < 10 or pm_limit > 1000:
|
||||
pm_limit = self.default_pm_limit
|
||||
self._db.set(__name__, "pm_limit_max", pm_limit)
|
||||
return pm_limit
|
||||
125
AlpacaGang/ftg-modules/Tag.py
Normal file
125
AlpacaGang/ftg-modules/Tag.py
Normal file
@@ -0,0 +1,125 @@
|
||||
# -*- coding: future_fstrings -*-
|
||||
|
||||
# Friendly Telegram (telegram userbot)
|
||||
# By Magical Unicorn (based on official Anti PM & AFK Friendly Telegram modules)
|
||||
# Copyright (C) 2020 Magical Unicorn
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
import logging
|
||||
|
||||
from telethon import functions, types
|
||||
from telethon.tl.types import PeerUser, PeerChat, PeerChannel, ChannelParticipantsAdmins
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register(cb):
|
||||
cb(TagMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class TagMod(loader.Module):
|
||||
"""
|
||||
Tag :
|
||||
-> Tag all admins (fast way to report).
|
||||
-> Tag all bots (why not ?).
|
||||
-> Tag all members (why not ?).\n
|
||||
Commands :
|
||||
|
||||
"""
|
||||
strings = {"name": "Tag",
|
||||
"error_chat": "<b>This command can be used in channels and group chats only.</b>",
|
||||
"unknow": ("An unknow problem as occured."
|
||||
"\n\nPlease report problem with logs on "
|
||||
"<a href='https://github.com/LegendaryUnicorn/FTG-Unofficial-Modules'>Github</a>."),
|
||||
"user_link": "\n• <a href='tg://user?id={}'>{}</a>"}
|
||||
|
||||
def config_complete(self):
|
||||
self.name = self.strings["name"]
|
||||
|
||||
async def admincmd(self, message):
|
||||
"""
|
||||
.admin : Tag all admins (excepted bots).
|
||||
.admin [message] : Tag all admins (excepted bots) with message before tags.
|
||||
|
||||
"""
|
||||
if isinstance(message.to_id, PeerUser):
|
||||
await utils.answer(message, self.strings["error_chat"])
|
||||
return
|
||||
if utils.get_args_raw(message):
|
||||
rep = utils.get_args_raw(message)
|
||||
else:
|
||||
rep = ""
|
||||
user = await utils.get_target(message)
|
||||
if isinstance(message.to_id, PeerChat) or isinstance(message.to_id, PeerChannel):
|
||||
async for user in message.client.iter_participants(message.to_id, filter=ChannelParticipantsAdmins):
|
||||
if not user.bot:
|
||||
user_name = user.first_name
|
||||
if user.last_name is not None:
|
||||
user_name += " " + user.last_name
|
||||
rep += self.strings["user_link"].format(user.id, user_name)
|
||||
await utils.answer(message, rep)
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
|
||||
async def allcmd(self, message):
|
||||
"""
|
||||
.all : Tag all members.
|
||||
.all [message] : Tag all members with message before tags.
|
||||
|
||||
"""
|
||||
if isinstance(message.to_id, PeerUser):
|
||||
await utils.answer(message, self.strings["error_chat"])
|
||||
return
|
||||
if utils.get_args_raw(message):
|
||||
rep = utils.get_args_raw(message)
|
||||
else:
|
||||
rep = ""
|
||||
user = await utils.get_target(message)
|
||||
if isinstance(message.to_id, PeerChat) or isinstance(message.to_id, PeerChannel):
|
||||
async for user in message.client.iter_participants(message.to_id):
|
||||
user_name = user.first_name
|
||||
if user.last_name is not None:
|
||||
user_name += " " + user.last_name
|
||||
rep += self.strings["user_link"].format(user.id, user_name)
|
||||
await utils.answer(message, rep)
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
|
||||
async def botcmd(self, message):
|
||||
"""
|
||||
.bot : Tag all bots.
|
||||
.bot [message] : Tag all bots with message before tags.
|
||||
|
||||
"""
|
||||
if isinstance(message.to_id, PeerUser):
|
||||
await utils.answer(message, self.strings["error_chat"])
|
||||
return
|
||||
if utils.get_args_raw(message):
|
||||
rep = utils.get_args_raw(message)
|
||||
else:
|
||||
rep = ""
|
||||
user = await utils.get_target(message)
|
||||
if isinstance(message.to_id, PeerChat) or isinstance(message.to_id, PeerChannel):
|
||||
async for user in message.client.iter_participants(message.to_id):
|
||||
if user.bot:
|
||||
user_name = user.first_name
|
||||
if user.last_name is not None:
|
||||
user_name += " " + user.last_name
|
||||
rep += self.strings["user_link"].format(user.id, user_name)
|
||||
await utils.answer(message, rep)
|
||||
else:
|
||||
await utils.answer(message, self.strings["unknow"])
|
||||
42
AlpacaGang/ftg-modules/contact.py
Normal file
42
AlpacaGang/ftg-modules/contact.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from .. import loader, utils
|
||||
|
||||
import logging
|
||||
import datetime
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register(cb):
|
||||
cb(CONTACTMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class CONTACTMod(loader.Module):
|
||||
"""Это модуль для игры в \"контакт\""""
|
||||
strings = {"name": "contact"}
|
||||
|
||||
def __init__(self):
|
||||
self.name = self.strings["name"]
|
||||
|
||||
def config_complete(self):
|
||||
pass
|
||||
|
||||
async def contactcmd(self, message):
|
||||
"""Эта команда пишет 10 сообщений для контакта"""
|
||||
try:
|
||||
await message.delete()
|
||||
x = 10
|
||||
lst = str(x)
|
||||
await message.respond(lst)
|
||||
|
||||
dd = time.time()
|
||||
|
||||
while time.time() - dd < x:
|
||||
now = str(x - round(time.time() - dd))
|
||||
if now != lst:
|
||||
await message.respond(now)
|
||||
lst = now
|
||||
except:
|
||||
await message.respond("Упс, ошибочка вышла! Напшите @gerasikoff, он вам поможет")
|
||||
95
AlpacaGang/ftg-modules/cuttly.py
Normal file
95
AlpacaGang/ftg-modules/cuttly.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import requests as rq
|
||||
from urllib.parse import quote_plus as escape
|
||||
import re
|
||||
|
||||
from .. import loader, utils
|
||||
import asyncio
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# simplified cuttly api
|
||||
class CuttlyApi:
|
||||
def __init__(self, token, api_url='https://cutt.ly/api/api.php'):
|
||||
self.token = token
|
||||
self.api_url = api_url
|
||||
self.error_codes = {
|
||||
1: 'Link is already shortened',
|
||||
2: 'Link to short is not a link',
|
||||
3: 'Short link https://cutt.ly/{name} is taken',
|
||||
4: 'Invalid API key',
|
||||
5: 'Link preferred alias contains invalid characters',
|
||||
6: 'Link is from blocked domain'
|
||||
}
|
||||
self.ok_code = 7
|
||||
|
||||
def shorten(self, short: str, name: str=None) -> dict:
|
||||
if not re.fullmatch(r'\w+://.+', short): # add scheme if needed
|
||||
short = 'http://' + short # assume that it supports http
|
||||
res = rq.get(self.api_url, params={
|
||||
"key": self.token,
|
||||
"short": escape(short, ':/%._-'),
|
||||
"name": name
|
||||
})
|
||||
res = res.json()['url']
|
||||
return res
|
||||
|
||||
@loader.tds
|
||||
class CuttlyMod(loader.Module):
|
||||
"""URL shortener module"""
|
||||
# make errors translatable
|
||||
strings = {
|
||||
"name": "Cutt.ly",
|
||||
"error_1": "<b>Link is already shortened</b>",
|
||||
"error_2": "<b>It is not a link</b>",
|
||||
"error_3": "<b>Short link https://cutt.ly/{name} is taken</b>",
|
||||
"error_4": "<b>Invalid API key. Change it in config.</b>",
|
||||
"error_5": "<b>Link preferred alias contains invalid characters</b>",
|
||||
"error_6": "<b>Link is from blocked domain</b>",
|
||||
"unknown_error": "<b>Unknown error {}. Check https://cutt.ly/cuttly-api for information.</b>",
|
||||
"ok": "<b>Shorted!</b>\nShort link: {short}\nFull link: {full}",
|
||||
"ok_nofull": "<b>Shorted!</b>\nShort link: {short}",
|
||||
"no_args": "<b>At least 1 argument needed - the link you gonna to short</b>",
|
||||
"many_args": "<b>At most 2 arguments - the link you gonna to short and preferred alias for it."
|
||||
}
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
# name - default - description
|
||||
"cuttly_api_url", "https://cutt.ly/api/api.php", "Cuttly API URL, took from https://cutt.ly/cuttly-api",
|
||||
"api_key", None, "API key for cutt.ly. Register there and take one.",
|
||||
"include_full_link", True, "Shall bot include full link into answer."
|
||||
)
|
||||
|
||||
def config_complete(self):
|
||||
self.name = self.strings['name']
|
||||
self.cl = CuttlyApi(self.config['api_key'], self.config['cuttly_api_url'])
|
||||
|
||||
async def shortcmd(self, message):
|
||||
'''usage: .short <link_to_short> [preferred_alias]'''
|
||||
args = utils.get_args(message)
|
||||
if len(args) < 1:
|
||||
await utils.answer(message, self.strings['no_args'])
|
||||
return
|
||||
elif len(args) > 2:
|
||||
await utils.answer(message, self.strings['many_args'])
|
||||
return
|
||||
|
||||
if len(args) == 1:
|
||||
args.append(None)
|
||||
|
||||
res = self.cl.shorten(*args)
|
||||
logger.debug(f'Got response from cutt.ly: {res}')
|
||||
if res['status'] != self.cl.ok_code:
|
||||
try:
|
||||
msg = self.strings[f'error_{res["status"]}']
|
||||
except KeyError: # Unknown error, not in strings yet
|
||||
msg = self.strings['unknown_error'].format(res['status'])
|
||||
else:
|
||||
if self.config['include_full_link']:
|
||||
msg = self.strings['ok']
|
||||
else:
|
||||
msg = self.strings['ok_nofull']
|
||||
await utils.answer(message, msg.format(
|
||||
short = res.get('shortLink', None), # If we got an error
|
||||
full = res.get('fullLink', None),
|
||||
name = args[1]
|
||||
))
|
||||
131
AlpacaGang/ftg-modules/dogbin.py
Normal file
131
AlpacaGang/ftg-modules/dogbin.py
Normal file
@@ -0,0 +1,131 @@
|
||||
# Copyright (C) 2019 The Raphielscape Company LLC.
|
||||
#
|
||||
# Licensed under the Raphielscape Public License, Version 1.c (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
""" Userbot module containing commands for interacting with dogbin(https://del.dog)"""
|
||||
|
||||
from requests import get, post, exceptions
|
||||
import asyncio
|
||||
import os
|
||||
from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, LOGS, TEMP_DOWNLOAD_DIRECTORY
|
||||
from userbot.events import register
|
||||
|
||||
DOGBIN_URL = "https://dogbin.f0x1d.com/"
|
||||
|
||||
|
||||
@register(outgoing=True, pattern=r"^.paste(?: |$)([\s\S]*)")
|
||||
async def paste(pstl):
|
||||
""" For .paste command, pastes the text directly to dogbin. """
|
||||
dogbin_final_url = ""
|
||||
match = pstl.pattern_match.group(1).strip()
|
||||
reply_id = pstl.reply_to_msg_id
|
||||
|
||||
if not match and not reply_id:
|
||||
await pstl.edit("`Elon Musk said I cannot paste void.`")
|
||||
return
|
||||
|
||||
if match:
|
||||
message = match
|
||||
elif reply_id:
|
||||
message = (await pstl.get_reply_message())
|
||||
if message.media:
|
||||
downloaded_file_name = await pstl.client.download_media(
|
||||
message,
|
||||
TEMP_DOWNLOAD_DIRECTORY,
|
||||
)
|
||||
m_list = None
|
||||
with open(downloaded_file_name, "rb") as fd:
|
||||
m_list = fd.readlines()
|
||||
message = ""
|
||||
for m in m_list:
|
||||
message += m.decode("UTF-8") + "\r"
|
||||
os.remove(downloaded_file_name)
|
||||
else:
|
||||
message = message.message
|
||||
|
||||
# Dogbin
|
||||
await pstl.edit("`Pasting text . . .`")
|
||||
resp = post(DOGBIN_URL + "documents", data=message.encode('utf-8'))
|
||||
|
||||
if resp.status_code == 200:
|
||||
response = resp.json()
|
||||
key = response['key']
|
||||
dogbin_final_url = DOGBIN_URL + key
|
||||
|
||||
if response['isUrl']:
|
||||
reply_text = ("`Pasted successfully!`\n\n"
|
||||
f"`Shortened URL:` {dogbin_final_url}\n\n"
|
||||
"`Original(non-shortened) URLs`\n"
|
||||
f"`Dogbin URL`: {DOGBIN_URL}v/{key}\n")
|
||||
else:
|
||||
reply_text = ("`Pasted successfully!`\n\n"
|
||||
f"`Dogbin URL`: {dogbin_final_url}")
|
||||
else:
|
||||
reply_text = ("`Failed to reach Dogbin`")
|
||||
|
||||
await pstl.edit(reply_text)
|
||||
if BOTLOG:
|
||||
await pstl.client.send_message(
|
||||
BOTLOG_CHATID,
|
||||
f"Paste query was executed successfully",
|
||||
)
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.getpaste(?: |$)(.*)")
|
||||
async def get_dogbin_content(dog_url):
|
||||
""" For .getpaste command, fetches the content of a dogbin URL. """
|
||||
textx = await dog_url.get_reply_message()
|
||||
message = dog_url.pattern_match.group(1)
|
||||
await dog_url.edit("`Getting dogbin content...`")
|
||||
|
||||
if textx:
|
||||
message = str(textx.message)
|
||||
|
||||
format_normal = f'{DOGBIN_URL}'
|
||||
format_view = f'{DOGBIN_URL}v/'
|
||||
|
||||
if message.startswith(format_view):
|
||||
message = message[len(format_view):]
|
||||
elif message.startswith(format_normal):
|
||||
message = message[len(format_normal):]
|
||||
elif message.startswith("del.dog/"):
|
||||
message = message[len("del.dog/"):]
|
||||
else:
|
||||
await dog_url.edit("`Is that even a dogbin url?`")
|
||||
return
|
||||
|
||||
resp = get(f'{DOGBIN_URL}raw/{message}')
|
||||
|
||||
try:
|
||||
resp.raise_for_status()
|
||||
except exceptions.HTTPError as HTTPErr:
|
||||
await dog_url.edit(
|
||||
"Request returned an unsuccessful status code.\n\n" + str(HTTPErr))
|
||||
return
|
||||
except exceptions.Timeout as TimeoutErr:
|
||||
await dog_url.edit("Request timed out." + str(TimeoutErr))
|
||||
return
|
||||
except exceptions.TooManyRedirects as RedirectsErr:
|
||||
await dog_url.edit(
|
||||
"Request exceeded the configured number of maximum redirections." +
|
||||
str(RedirectsErr))
|
||||
return
|
||||
|
||||
reply_text = "`Fetched dogbin URL content successfully!`\n\n`Content:` " + resp.text
|
||||
|
||||
await dog_url.edit(reply_text)
|
||||
if BOTLOG:
|
||||
await dog_url.client.send_message(
|
||||
BOTLOG_CHATID,
|
||||
"Get dogbin content query was executed successfully",
|
||||
)
|
||||
|
||||
|
||||
CMD_HELP.update({
|
||||
"dogbin":
|
||||
".paste <text/reply>\
|
||||
\nUsage: Create a paste or a shortened url using dogbin (https://dogbin.f0x1d.com/)\
|
||||
\n\n.getpaste\
|
||||
\nUsage: Gets the content of a paste or shortened url from dogbin (https://dogbin.f0x1d.com/)"
|
||||
})
|
||||
143
AlpacaGang/ftg-modules/inactive.py
Normal file
143
AlpacaGang/ftg-modules/inactive.py
Normal file
@@ -0,0 +1,143 @@
|
||||
import logging
|
||||
import json
|
||||
# import telethon
|
||||
from .. import loader, utils, security
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@loader.tds
|
||||
class InactiveDetectorMod(loader.Module):
|
||||
"""Detects inactive users"""
|
||||
strings = {
|
||||
"name": "Inactivity detector",
|
||||
"top_header": "These {un} users wrote {mn} messages or less since joining the group:\n\n",
|
||||
"top_place": "[{name}](tg://user?id={uid}) ({nmsg})", # FIXME: mentions
|
||||
"top_delimiter": ", ", # TODO: move to config
|
||||
"not_int": "<b>Most messages must be integer</b>",
|
||||
"recount_priv": "<b>I can't recount stats in private messages!</b>",
|
||||
"recount_started": "<b>Processing recount for chat {}. It may take a lot.</b>",
|
||||
"recount_db_dumped": "<b>Dumped database to owners and/or saved messages</b>",
|
||||
"recount_dump": "<b>Database dump for chat {cid}:<b>\n\n<pre>{dmp}</pre>",
|
||||
"recount_iter_done": "<b>Iterated over {} messages in this chat</b>",
|
||||
"recount_finish": "<b>Recount successful!</b>"
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
"default_chat_id", -1001457369532, "Chat ID to get top if command used in PM",
|
||||
"top_delimiter", ', ', "Separates inactivity top members",
|
||||
"dump_db_before_recount", False, "Dump database of chat before recounting. "
|
||||
"Dump will be sent to saved or bot owners"
|
||||
)
|
||||
self.name = self.strings['name']
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.client = client
|
||||
self.db = db
|
||||
self.me = await self.client.get_me()
|
||||
|
||||
async def inactivecmd(self, message):
|
||||
""".inactive <N>"""
|
||||
if message.is_private:
|
||||
chat_id = self.config['default_chat_id']
|
||||
else:
|
||||
chat_id = message.chat_id
|
||||
args = utils.get_args(message)
|
||||
if args:
|
||||
if args[0].isdigit():
|
||||
most = int(args[0])
|
||||
else:
|
||||
await utils.answer(message, self.strings("not_int", message))
|
||||
return
|
||||
else:
|
||||
most = 0
|
||||
users_db = self.db.get(__name__, str(chat_id), {})
|
||||
users = {}
|
||||
|
||||
async for user in self.client.iter_participants(chat_id):
|
||||
if not user.bot:
|
||||
if str(user.id) not in users_db:
|
||||
users_db[str(user.id)] = self.get_empty_user(user)
|
||||
users[str(user.id)] = users_db[str(user.id)]
|
||||
# We won't include users not CURRENTLY in chat,
|
||||
# but their stats will remain in the database
|
||||
|
||||
self.db.set(__name__, str(chat_id), users_db)
|
||||
|
||||
def key(x):
|
||||
return x[1]['cnt']
|
||||
|
||||
users = sorted(users.items(), key=key)
|
||||
text = []
|
||||
for uid, u in users:
|
||||
if u['cnt'] <= most:
|
||||
text.append(self.strings('top_place', message).format(
|
||||
name=u['name'], uid=uid, nmsg=u['cnt']
|
||||
))
|
||||
else:
|
||||
break
|
||||
msg = self.strings('top_header', message).format(un=len(text), mn=most)\
|
||||
+ self.config['top_delimiter'].join(text)
|
||||
|
||||
kw = {}
|
||||
if self.me.id != message.from_id:
|
||||
kw['silent'] = True
|
||||
await utils.answer(message, msg, parse_mode="md", **kw)
|
||||
|
||||
async def recountcmd(self, message):
|
||||
if message.is_private:
|
||||
await utils.answer(message, self.strings('recount_priv', message))
|
||||
return
|
||||
|
||||
chat_id = message.chat_id
|
||||
await utils.answer(message, self.strings('recount_started', message).format(chat_id))
|
||||
db = self.db.get(__name__, str(chat_id), {})
|
||||
json_db = json.dumps(db)
|
||||
msg = self.strings("recount_dump", message).format(cid=chat_id, dmp=json_db)
|
||||
logging.debug('Database dump (chat %d): %s', chat_id, json_db)
|
||||
owners = self.db.get(security.__name__, "owner", ["me"])
|
||||
if owners:
|
||||
for owner in owners:
|
||||
try:
|
||||
await self.client.send_message(owner, msg)
|
||||
except Exception:
|
||||
logger.warning("Dump of chat %d sending to %d failed",
|
||||
chat_id, owner, exc_info=True)
|
||||
new_db = {}
|
||||
n = 0
|
||||
async for msg in self.client.iter_messages(chat_id, limit=None):
|
||||
if not msg.sender.bot:
|
||||
n += 1
|
||||
from_id = msg.from_id
|
||||
# Ensure such user exists, or create him
|
||||
new_db[str(from_id)] = new_db.get(str(from_id),
|
||||
self.get_empty_user(msg.sender))
|
||||
new_db[str(from_id)]['cnt'] += 1
|
||||
await utils.answer(message, self.strings("recount_iter_done", message).format(n))
|
||||
self.db.set(__name__, str(chat_id), new_db)
|
||||
await utils.answer(message, self.strings("recount_finish", message))
|
||||
|
||||
async def watcher(self, message):
|
||||
if message.is_private:
|
||||
return
|
||||
else:
|
||||
chat_id = str(message.chat_id)
|
||||
users = self.db.get(__name__, chat_id, {})
|
||||
from_id = str(message.from_id)
|
||||
# this creates user if not exists
|
||||
if message.sender:
|
||||
users[from_id] = users.get(from_id, self.get_empty_user(message.sender))
|
||||
users[from_id]["cnt"] += 1
|
||||
self.db.set(__name__, chat_id, users)
|
||||
|
||||
def get_full_name(self, user):
|
||||
fn, ln = '', ''
|
||||
if user.first_name:
|
||||
fn = user.first_name
|
||||
if user.last_name: # Can be None, then we get an exception
|
||||
ln = user.last_name
|
||||
return (fn + ' ' + ln).strip()
|
||||
|
||||
def get_empty_user(self, user):
|
||||
return {"cnt": 0, "name": self.get_full_name(user)}
|
||||
154
AlpacaGang/ftg-modules/purge.py
Normal file
154
AlpacaGang/ftg-modules/purge.py
Normal file
@@ -0,0 +1,154 @@
|
||||
# Copyright (C) 2019 The Raphielscape Company LLC.
|
||||
#
|
||||
# Licensed under the Raphielscape Public License, Version 1.c (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
""" Userbot module for purging unneeded messages(usually spam or ot). """
|
||||
|
||||
from asyncio import sleep
|
||||
|
||||
from telethon.errors import rpcbaseerrors
|
||||
|
||||
from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP
|
||||
from userbot.events import register
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.purge$")
|
||||
async def fastpurger(purg):
|
||||
""" For .purge command, purge all messages starting from the reply. """
|
||||
chat = await purg.get_input_chat()
|
||||
msgs = []
|
||||
itermsg = purg.client.iter_messages(chat, min_id=purg.reply_to_msg_id)
|
||||
count = 0
|
||||
|
||||
if purg.reply_to_msg_id is not None:
|
||||
async for msg in itermsg:
|
||||
msgs.append(msg)
|
||||
count = count + 1
|
||||
msgs.append(purg.reply_to_msg_id)
|
||||
if len(msgs) == 100:
|
||||
await purg.client.delete_messages(chat, msgs)
|
||||
msgs = []
|
||||
else:
|
||||
await purg.edit("`I need a mesasge to start purging from.`")
|
||||
return
|
||||
|
||||
if msgs:
|
||||
await purg.client.delete_messages(chat, msgs)
|
||||
done = await purg.client.send_message(
|
||||
purg.chat_id, f"`Fast purge complete!`\
|
||||
\nPurged {str(count)} messages")
|
||||
|
||||
if BOTLOG:
|
||||
await purg.client.send_message(
|
||||
BOTLOG_CHATID,
|
||||
"Purge of " + str(count) + " messages done successfully.")
|
||||
await sleep(2)
|
||||
await done.delete()
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.purgeme")
|
||||
async def purgeme(delme):
|
||||
""" For .purgeme, delete x count of your latest message."""
|
||||
message = delme.text
|
||||
count = int(message[9:])
|
||||
i = 1
|
||||
|
||||
async for message in delme.client.iter_messages(delme.chat_id,
|
||||
from_user='me'):
|
||||
if i > count + 1:
|
||||
break
|
||||
i = i + 1
|
||||
await message.delete()
|
||||
|
||||
smsg = await delme.client.send_message(
|
||||
delme.chat_id,
|
||||
"`Purge complete!` Purged " + str(count) + " messages.",
|
||||
)
|
||||
if BOTLOG:
|
||||
await delme.client.send_message(
|
||||
BOTLOG_CHATID,
|
||||
"Purge of " + str(count) + " messages done successfully.")
|
||||
await sleep(2)
|
||||
i = 1
|
||||
await smsg.delete()
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.del$")
|
||||
async def delete_it(delme):
|
||||
""" For .del command, delete the replied message. """
|
||||
msg_src = await delme.get_reply_message()
|
||||
if delme.reply_to_msg_id:
|
||||
try:
|
||||
await msg_src.delete()
|
||||
await delme.delete()
|
||||
if BOTLOG:
|
||||
await delme.client.send_message(
|
||||
BOTLOG_CHATID, "Deletion of message was successful")
|
||||
except rpcbaseerrors.BadRequestError:
|
||||
if BOTLOG:
|
||||
await delme.client.send_message(
|
||||
BOTLOG_CHATID, "Well, I can't delete a message")
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.edit")
|
||||
async def editer(edit):
|
||||
""" For .editme command, edit your last message. """
|
||||
message = edit.text
|
||||
chat = await edit.get_input_chat()
|
||||
self_id = await edit.client.get_peer_id('me')
|
||||
string = str(message[6:])
|
||||
i = 1
|
||||
async for message in edit.client.iter_messages(chat, self_id):
|
||||
if i == 2:
|
||||
await message.edit(string)
|
||||
await edit.delete()
|
||||
break
|
||||
i = i + 1
|
||||
if BOTLOG:
|
||||
await edit.client.send_message(BOTLOG_CHATID,
|
||||
"Edit query was executed successfully")
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.sd")
|
||||
async def selfdestruct(destroy):
|
||||
""" For .sd command, make seflf-destructable messages. """
|
||||
message = destroy.text
|
||||
counter = int(message[4:6])
|
||||
text = str(destroy.text[6:])
|
||||
await destroy.delete()
|
||||
smsg = await destroy.client.send_message(destroy.chat_id, text)
|
||||
await sleep(counter)
|
||||
await smsg.delete()
|
||||
if BOTLOG:
|
||||
await destroy.client.send_message(BOTLOG_CHATID,
|
||||
"sd query done successfully")
|
||||
|
||||
|
||||
CMD_HELP.update({
|
||||
'purge':
|
||||
'.purge\
|
||||
\nUsage: Purges all messages starting from the reply.'
|
||||
})
|
||||
|
||||
CMD_HELP.update({
|
||||
'purgeme':
|
||||
'.purgeme <x>\
|
||||
\nUsage: Deletes x amount of your latest messages.'
|
||||
})
|
||||
|
||||
CMD_HELP.update({"del": ".del\
|
||||
\nUsage: Deletes the message you replied to."})
|
||||
|
||||
CMD_HELP.update({
|
||||
'edit':
|
||||
".edit <newmessage>\
|
||||
\nUsage: Replace your last message with <newmessage>."
|
||||
})
|
||||
|
||||
CMD_HELP.update({
|
||||
'sd':
|
||||
'.sd <x> <message>\
|
||||
\nUsage: Creates a message that selfdestructs in x seconds.\
|
||||
\nKeep the seconds under 100 since it puts your bot to sleep.'
|
||||
})
|
||||
298
AlpacaGang/ftg-modules/quotes.py
Normal file
298
AlpacaGang/ftg-modules/quotes.py
Normal file
@@ -0,0 +1,298 @@
|
||||
# -*- coding: future_fstrings -*-
|
||||
|
||||
# Friendly Telegram (telegram userbot)
|
||||
# Copyright (C) 2018-2019 The Authors
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
import requests
|
||||
import base64
|
||||
import json
|
||||
import telethon
|
||||
|
||||
from .. import loader, utils
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register(cb):
|
||||
cb(QuotesMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class QuotesMod(loader.Module):
|
||||
"""Quote a message."""
|
||||
strings = {
|
||||
"name": "Quotes",
|
||||
"api_token_cfg_doc": "API Key/Token for Quotes.",
|
||||
"api_url_cfg_doc": "API URL for Quotes.",
|
||||
"colors_cfg_doc": "Username colors",
|
||||
"default_username_color_cfg_doc": "Default color for the username.",
|
||||
"no_reply": "<b>You didn't reply to a message.</b>",
|
||||
"no_template": "<b>You didn't specify the template.</b>",
|
||||
"delimiter": "</code>, <code>",
|
||||
"server_error": "<b>Server error. Please report to developer.</b>",
|
||||
"invalid_token": "<b>You've set an invalid token.</b>",
|
||||
"unauthorized": "<b>You're unauthorized to do this.</b>",
|
||||
"not_enough_permissions": "<b>Wrong template. You can use only the default one.</b>",
|
||||
"templates": "<b>Available Templates:</b> <code>{}</code>",
|
||||
"cannot_send_stickers": "<b>You cannot send stickers in this chat.</b>",
|
||||
"admin": "admin",
|
||||
"creator": "creator",
|
||||
"hidden": "hidden",
|
||||
"channel": "Channel",
|
||||
"filename": "file.png"
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig("api_token", None, lambda: self.strings["api_token_cfg_doc"],
|
||||
"api_url", "http://api.antiddos.systems",
|
||||
lambda: self.strings["api_url_cfg_doc"],
|
||||
"username_colors", ["#fb6169", "#faa357", "#b48bf2", "#85de85",
|
||||
"#62d4e3", "#65bdf3", "#ff5694"],
|
||||
lambda: self.strings["colors_cfg_doc"],
|
||||
"default_username_color", "#b48bf2",
|
||||
lambda: self.strings["default_username_color_cfg_doc"])
|
||||
|
||||
def config_complete(self):
|
||||
self.name = self.strings["name"]
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.client = client
|
||||
|
||||
async def quotecmd(self, message): # noqa: C901
|
||||
"""Quote a message.
|
||||
Usage: .quote [template] [file/force_file]
|
||||
Or: .quote np [template] [file/force_file]
|
||||
If template is missing, possible templates are fetched.
|
||||
If no args provided, default template will be used, quote sent as sticker"""
|
||||
args = utils.get_args(message)
|
||||
if len(args) > 0 and args[0] == 'np':
|
||||
no_picture = True
|
||||
del args[0]
|
||||
else:
|
||||
no_picture = False
|
||||
reply = await message.get_reply_message()
|
||||
|
||||
if not reply:
|
||||
return await utils.answer(message, self.strings["no_reply"])
|
||||
|
||||
username_color = username = admintitle = user_id = None
|
||||
profile_photo_url = reply.from_id
|
||||
|
||||
admintitle = ""
|
||||
pfp = None
|
||||
if isinstance(reply.to_id, telethon.tl.types.PeerChannel) and reply.fwd_from:
|
||||
user = reply.forward.chat
|
||||
elif isinstance(reply.to_id, telethon.tl.types.PeerChat):
|
||||
chat = await self.client(telethon.tl.functions.messages.GetFullChatRequest(reply.to_id))
|
||||
participants = chat.full_chat.participants.participants
|
||||
participant = next(filter(lambda x: x.user_id == reply.from_id, participants), None)
|
||||
if isinstance(participant, telethon.tl.types.ChatParticipantCreator):
|
||||
admintitle = self.strings["creator"]
|
||||
elif isinstance(participant, telethon.tl.types.ChatParticipantAdmin):
|
||||
admintitle = self.strings["admin"]
|
||||
user = await reply.get_sender()
|
||||
else:
|
||||
user = await reply.get_sender()
|
||||
|
||||
username = telethon.utils.get_display_name(user)
|
||||
if reply.fwd_from is not None and reply.fwd_from.post_author is not None:
|
||||
username += f" ({reply.fwd_from.post_author})"
|
||||
user_id = reply.from_id
|
||||
|
||||
if reply.fwd_from:
|
||||
if reply.fwd_from.saved_from_peer:
|
||||
profile_photo_url = reply.forward.chat
|
||||
admintitle = self.strings["channel"]
|
||||
elif reply.fwd_from.from_name:
|
||||
username = reply.fwd_from.from_name
|
||||
profile_photo_url = None
|
||||
admintitle = ""
|
||||
elif reply.forward.sender:
|
||||
username = telethon.utils.get_display_name(reply.forward.sender)
|
||||
profile_photo_url = reply.forward.sender.id
|
||||
admintitle = ""
|
||||
elif reply.forward.chat:
|
||||
admintitle = self.strings["channel"]
|
||||
profile_photo_url = user
|
||||
else:
|
||||
if isinstance(reply.to_id, telethon.tl.types.PeerUser) is False:
|
||||
try:
|
||||
user = await self.client(telethon.tl.functions.channels.GetParticipantRequest(message.chat_id,
|
||||
user))
|
||||
if isinstance(user.participant, telethon.tl.types.ChannelParticipantCreator):
|
||||
admintitle = user.participant.rank or self.strings["creator"]
|
||||
elif isinstance(user.participant, telethon.tl.types.ChannelParticipantAdmin):
|
||||
admintitle = user.participant.rank or self.strings["admin"]
|
||||
user = user.users[0]
|
||||
except telethon.errors.rpcerrorlist.UserNotParticipantError:
|
||||
pass
|
||||
|
||||
if no_picture:
|
||||
profile_photo_url = ''
|
||||
else:
|
||||
if profile_photo_url is not None:
|
||||
pfp = await self.client.download_profile_photo(profile_photo_url, bytes)
|
||||
|
||||
if pfp is not None:
|
||||
profile_photo_url = "data:image/png;base64, " + base64.b64encode(pfp).decode()
|
||||
else:
|
||||
profile_photo_url = ""
|
||||
|
||||
if user_id is not None:
|
||||
username_color = self.config["username_colors"][user_id % 7]
|
||||
else:
|
||||
username_color = self.config["default_username_color"]
|
||||
|
||||
reply_username = ""
|
||||
reply_text = ""
|
||||
if reply.is_reply is True:
|
||||
reply_to = await reply.get_reply_message()
|
||||
reply_peer = None
|
||||
if reply_to.fwd_from is not None:
|
||||
if reply_to.forward.chat is not None:
|
||||
reply_peer = reply_to.forward.chat
|
||||
elif reply_to.fwd_from.from_id is not None:
|
||||
try:
|
||||
user_id = reply_to.fwd_from.from_id
|
||||
user = await self.client(telethon.tl.functions.users.GetFullUserRequest(user_id))
|
||||
reply_peer = user.user
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
reply_username = reply_to.fwd_from.from_name
|
||||
elif reply_to.from_id is not None:
|
||||
reply_user = await self.client(telethon.tl.functions.users.GetFullUserRequest(reply_to.from_id))
|
||||
reply_peer = reply_user.user
|
||||
|
||||
if reply_username is None or reply_username == "":
|
||||
reply_username = telethon.utils.get_display_name(reply_peer)
|
||||
reply_text = reply_to.message
|
||||
|
||||
date = ""
|
||||
if reply.fwd_from is not None:
|
||||
date = reply.fwd_from.date.strftime("%H:%M")
|
||||
else:
|
||||
date = reply.date.strftime("%H:%M")
|
||||
|
||||
request = json.dumps({
|
||||
"ProfilePhotoURL": profile_photo_url,
|
||||
"usernameColor": username_color,
|
||||
"username": username,
|
||||
"adminTitle": admintitle,
|
||||
"Text": reply.message,
|
||||
"Markdown": get_markdown(reply),
|
||||
"ReplyUsername": reply_username,
|
||||
"ReplyText": reply_text,
|
||||
"Date": date,
|
||||
"Template": args[0] if len(args) > 0 else 'default',
|
||||
"APIKey": self.config["api_token"]
|
||||
})
|
||||
|
||||
resp = await utils.run_sync(requests.post, self.config["api_url"] + "/api/v2/quote", data=request)
|
||||
resp.raise_for_status()
|
||||
resp = await utils.run_sync(resp.json)
|
||||
|
||||
if resp["status"] == 500:
|
||||
return await utils.answer(message, self.strings["server_error"])
|
||||
elif resp["status"] == 401:
|
||||
if resp["message"] == "ERROR_TOKEN_INVALID":
|
||||
return await utils.answer(message, self.strings["invalid_token"])
|
||||
else:
|
||||
raise ValueError("Invalid response from server", resp)
|
||||
elif resp["status"] == 403:
|
||||
if resp["message"] == "ERROR_UNAUTHORIZED":
|
||||
return await utils.answer(message, self.strings["unauthorized"])
|
||||
else:
|
||||
raise ValueError("Invalid response from server", resp)
|
||||
elif resp["status"] == 404:
|
||||
if resp["message"] == "ERROR_TEMPLATE_NOT_FOUND":
|
||||
newreq = await utils.run_sync(requests.post, self.config["api_url"] + "/api/v1/getalltemplates", data={
|
||||
"token": self.config["api_token"]
|
||||
})
|
||||
newreq = await utils.run_sync(newreq.json)
|
||||
|
||||
if newreq["status"] == "NOT_ENOUGH_PERMISSIONS":
|
||||
return await utils.answer(message, self.strings["not_enough_permissions"])
|
||||
elif newreq["status"] == "SUCCESS":
|
||||
templates = self.strings["delimiter"].join(newreq["message"])
|
||||
return await utils.answer(message, self.strings["templates"].format(templates))
|
||||
elif newreq["status"] == "INVALID_TOKEN":
|
||||
return await utils.answer(message, self.strings["invalid_token"])
|
||||
else:
|
||||
raise ValueError("Invalid response from server", newreq)
|
||||
else:
|
||||
raise ValueError("Invalid response from server", resp)
|
||||
elif resp["status"] != 200:
|
||||
raise ValueError("Invalid response from server", resp)
|
||||
|
||||
req = await utils.run_sync(requests.get, self.config["api_url"] + "/cdn/" + resp["message"])
|
||||
req.raise_for_status()
|
||||
file = BytesIO(req.content)
|
||||
file.seek(0)
|
||||
|
||||
if len(args) == 2:
|
||||
if args[1] == "file":
|
||||
await utils.answer(message, file)
|
||||
elif args[1] == "force_file":
|
||||
file.name = self.strings["filename"]
|
||||
await utils.answer(message, file, force_document=True)
|
||||
else:
|
||||
img = await utils.run_sync(Image.open, file)
|
||||
with BytesIO() as sticker:
|
||||
await utils.run_sync(img.save, sticker, "webp")
|
||||
sticker.name = "sticker.webp"
|
||||
sticker.seek(0)
|
||||
try:
|
||||
await utils.answer(message, sticker)
|
||||
except telethon.errors.rpcerrorlist.ChatSendStickersForbiddenError:
|
||||
await utils.answer(message, self.strings["cannot_send_stickers"])
|
||||
file.close()
|
||||
|
||||
|
||||
def get_markdown(reply):
|
||||
if not reply.entities:
|
||||
return []
|
||||
|
||||
markdown = []
|
||||
for entity in reply.entities:
|
||||
md_item = {
|
||||
"Type": None,
|
||||
"Start": entity.offset,
|
||||
"End": entity.offset + entity.length - 1
|
||||
}
|
||||
if isinstance(entity, telethon.tl.types.MessageEntityBold):
|
||||
md_item["Type"] = "bold"
|
||||
elif isinstance(entity, telethon.tl.types.MessageEntityItalic):
|
||||
md_item["Type"] = "italic"
|
||||
elif isinstance(entity, (telethon.tl.types.MessageEntityMention, telethon.tl.types.MessageEntityTextUrl,
|
||||
telethon.tl.types.MessageEntityMentionName, telethon.tl.types.MessageEntityHashtag,
|
||||
telethon.tl.types.MessageEntityCashtag, telethon.tl.types.MessageEntityBotCommand,
|
||||
telethon.tl.types.MessageEntityUrl)):
|
||||
md_item["Type"] = "link"
|
||||
elif isinstance(entity, telethon.tl.types.MessageEntityCode):
|
||||
md_item["Type"] = "code"
|
||||
elif isinstance(entity, telethon.tl.types.MessageEntityStrike):
|
||||
md_item["Type"] = "stroke"
|
||||
elif isinstance(entity, telethon.tl.types.MessageEntityUnderline):
|
||||
md_item["Type"] = "underline"
|
||||
else:
|
||||
logger.warning("Unknown entity: " + str(entity))
|
||||
|
||||
markdown.append(md_item)
|
||||
return markdown
|
||||
147
AlpacaGang/ftg-modules/range.py
Normal file
147
AlpacaGang/ftg-modules/range.py
Normal file
@@ -0,0 +1,147 @@
|
||||
# encoding: utf-8
|
||||
import asyncio
|
||||
import time
|
||||
import logging
|
||||
|
||||
from .. import loader, utils
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register(cb):
|
||||
cb(RangeMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class RangeMod(loader.Module):
|
||||
"""Provides numbers as in Python range with delay"""
|
||||
strings = {
|
||||
"name": "Range",
|
||||
"no_args": "<b>Not enough args (minimum {})</b>",
|
||||
"delay_num": "<b>Delay must be a number</b>",
|
||||
"args_int": "<b>All range args must be integers</b>",
|
||||
"many_args": "<b>There must be no more than {} arguments</b>"
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
"msg_format", "{0}", "Format of each message. {0} replaces current number.",
|
||||
"default_delay", 1.0, "Delay in all commands by default"
|
||||
)
|
||||
self.name = self.strings['name']
|
||||
|
||||
def config_complete(self):
|
||||
self.name = self.strings['name']
|
||||
|
||||
async def _do_range(self, range_args, delay, message):
|
||||
"""for internal usage; do range itself"""
|
||||
await message.delete()
|
||||
for now in range(*range_args):
|
||||
before = time.time()
|
||||
await message.respond(self.config['msg_format'].format(now))
|
||||
delta = time.time() - before
|
||||
await asyncio.sleep(max(delay - delta, 0))
|
||||
|
||||
async def _get_args(self, message, minn, maxn):
|
||||
args = utils.get_args(message)
|
||||
if len(args) < minn:
|
||||
logger.warning(f'Minimum {minn} {"args" if minn != 1 else "arg"}, {len(args)} provided')
|
||||
await utils.answer(message, self.strings['no_args'].format(minn))
|
||||
return None
|
||||
elif len(args) > maxn:
|
||||
logger.warning(f'Maximum {maxn} {"args" if maxn != 1 else "arg"}, {len(args)} provided')
|
||||
await utils.answer(message, self.strings['many_args'].format(maxn))
|
||||
return None
|
||||
return args
|
||||
|
||||
async def _check_range_args(self, range_args, message):
|
||||
"""for internal usage; check if range args are int"""
|
||||
try:
|
||||
range_args = [int(x) for x in range_args]
|
||||
return range_args
|
||||
except ValueError:
|
||||
logger.warning(f'Impossible to convert all range args to int ({range_args})')
|
||||
await utils.answer(message, self.strings['args_int'])
|
||||
return None
|
||||
|
||||
async def rangecmd(self, message):
|
||||
"""Iterates over the given range and returns each number in separate message.
|
||||
Usage: .range <python_range_args>"""
|
||||
args = await self._get_args(message, 1, 3)
|
||||
if args is None:
|
||||
return # user done sth wrong
|
||||
|
||||
delay = self.config['default_delay']
|
||||
range_args = await self._check_range_args(args, message)
|
||||
if range_args is None:
|
||||
return # user done sth wrong
|
||||
|
||||
await self._do_range(range_args, delay, message)
|
||||
|
||||
async def drangecmd(self, message):
|
||||
"""Iterates over the given range and returns each number in separate message.
|
||||
Usage: .drange <delay> <python_range_args>"""
|
||||
args = await self._get_args(message, 2, 4)
|
||||
if args is None:
|
||||
return # user done sth wrong
|
||||
|
||||
try:
|
||||
delay = float(args[0])
|
||||
except ValueError:
|
||||
logger.warning(f'Impossible to convert delay to float ({args[0]})')
|
||||
await utils.answer(message, self.strings['delay_num'])
|
||||
return
|
||||
|
||||
range_args = await self._check_range_args(args[1:], message)
|
||||
if range_args is None:
|
||||
return
|
||||
|
||||
await self._do_range(range_args, delay, message)
|
||||
|
||||
async def countcmd(self, message):
|
||||
"""Count from 1 to N.\nUsage: .count <delay> <N> or .count <N>"""
|
||||
args = await self._get_args(message, 1, 2)
|
||||
if args is None:
|
||||
return
|
||||
|
||||
if len(args) == 1:
|
||||
delay = self.config['default_delay']
|
||||
range_args = (1, args[0], 1)
|
||||
elif len(args) == 2:
|
||||
try:
|
||||
delay = float(args[0])
|
||||
except ValueError:
|
||||
logger.warning(f'Impossible to convert delay to float ({args[0]})')
|
||||
await utils.answer(message, self.strings['delay_num'])
|
||||
return
|
||||
range_args = (1, args[1], 1)
|
||||
|
||||
range_args = await self._check_range_args(range_args, message)
|
||||
if range_args is None:
|
||||
return
|
||||
range_args[1] += 1 # so last number we print will be N itself
|
||||
|
||||
await self._do_range(range_args, delay, message)
|
||||
|
||||
async def rcountcmd(self, message):
|
||||
"""Count from N to 1.\nUsage: .rcount <delay> <N> or .rcount <N>"""
|
||||
args = await self._get_args(message, 1, 2)
|
||||
if args is None:
|
||||
return
|
||||
|
||||
if len(args) == 1:
|
||||
delay = self.config['default_delay']
|
||||
range_args = (args[0], 0, -1)
|
||||
elif len(args) == 2:
|
||||
try:
|
||||
delay = float(args[0])
|
||||
except ValueError:
|
||||
logger.warning(f'Impossible to convert delay to float ({args[0]})')
|
||||
await utils.answer(message, self.strings['delay_num'])
|
||||
return
|
||||
range_args = (args[1], 0, -1)
|
||||
|
||||
range_args = await self._check_range_args(range_args, message)
|
||||
if range_args is None:
|
||||
return
|
||||
|
||||
await self._do_range(range_args, delay, message)
|
||||
66
AlpacaGang/ftg-modules/repl.py
Normal file
66
AlpacaGang/ftg-modules/repl.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from .. import loader, utils
|
||||
# from telethon import*
|
||||
from telethon import functions, types
|
||||
|
||||
import logging
|
||||
import datetime
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register(cb):
|
||||
cb(REPLMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class REPLMod(loader.Module):
|
||||
"""REPLIED for selected users"""
|
||||
strings = {"name": "REPL"}
|
||||
|
||||
d = dict()
|
||||
|
||||
def __init__(self):
|
||||
self.name = self.strings["name"]
|
||||
|
||||
def config_complete(self):
|
||||
pass
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self._db = db
|
||||
self._me = await client.get_me()
|
||||
|
||||
async def addtxcmd(self, message):
|
||||
"""Select users\nFor example: .addtx used_id \"text when reply (Default: \'.\'\""""
|
||||
args = utils.get_args(message)
|
||||
if not len(args):
|
||||
await utils.answer(message, "Напиши .help REPL, там есть пример, как нужно делать.\nТы сделал неправильно!")
|
||||
elif len(args) == 1:
|
||||
self.d[int(args[0])] = '.'
|
||||
else:
|
||||
f = ""
|
||||
for i in range(1, len(args)):
|
||||
f += args[i]
|
||||
if i != len(args) - 1:
|
||||
f += " "
|
||||
self.d[int(args[0])] = f
|
||||
await utils.answer(message, "Done.\nP.S: 3 seconds later it's automatic delete")
|
||||
await asyncio.sleep(3)
|
||||
await message.delete()
|
||||
|
||||
async def clrtxcmd(self, message):
|
||||
"""Unselect user\nFor example: `.clrtx used_id` for one user or `.clrtx` for all users"""
|
||||
args = utils.get_args(message)
|
||||
if not len(args):
|
||||
self.d.clear()
|
||||
else:
|
||||
self.d.pop(int(args[0]))
|
||||
await utils.answer(message, "Done.\nP.S: 3 seconds later it's automatic delete")
|
||||
await asyncio.sleep(3)
|
||||
await message.delete()
|
||||
|
||||
async def watcher(self, message):
|
||||
if (message.from_id in self.d) and (
|
||||
message.mentioned or getattr(message.to_id, "user_id", None) == self._me.id):
|
||||
await message.respond(self.d[message.from_id], reply_to=message)
|
||||
81
AlpacaGang/ftg-modules/sirius.py
Normal file
81
AlpacaGang/ftg-modules/sirius.py
Normal file
@@ -0,0 +1,81 @@
|
||||
# requires: pymongo dnspython
|
||||
|
||||
# Забейте
|
||||
import asyncio
|
||||
import pymongo
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
from .. import loader, utils
|
||||
|
||||
class Student:
|
||||
def __init__(self, id: int, last_name: str, first_name: str,
|
||||
patronymic: str, grade: int, region: str, academ: bool, approved: int=None):
|
||||
self.last_name = last_name
|
||||
self.first_name = first_name
|
||||
self.patronymic = patronymic
|
||||
self.grade = int(grade)
|
||||
self.region = region
|
||||
self.academ = bool(academ)
|
||||
self.approved = approved
|
||||
self.id = int(id)
|
||||
|
||||
def __str__(self):
|
||||
p = 'Академ' if self.academ else 'Отбор'
|
||||
# a = f'Уже вроде бы добавлен в чат (tg://user?id={self.approved})' if self.approved else 'Еще нет в чате'
|
||||
return f'[{p}.{self.id}] {self.last_name} {self.first_name} {self.patronymic}, '\
|
||||
f'{self.grade} класс, из {self.region}'
|
||||
|
||||
class SiriusMod(loader.Module):
|
||||
"""Ищем поступивших на ИЮ2020"""
|
||||
strings = {"name": "Sirius"}
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
# name - default - description
|
||||
"db_uri", None, "Database URI, if you dont know where to take it - nevermind",
|
||||
"db_db", None, "database",
|
||||
"db_coll", None, "collection",
|
||||
"replace_ё", True, "replace ё with е in requests, incorrect usage may return incorrect result"
|
||||
)
|
||||
self.name = self.strings['name']
|
||||
self.db = None
|
||||
|
||||
def config_complete(self):
|
||||
self.db = pymongo.MongoClient(self.config['db_uri'])\
|
||||
.get_database(self.config['db_db']).get_collection(self.config['db_coll'])
|
||||
|
||||
async def findcmd(self, message):
|
||||
arg = utils.get_args_raw(message).strip()
|
||||
if self.config['replace_ё']:
|
||||
arg = arg.replace('ё', 'е')
|
||||
arg = arg.replace('Ё', 'Е')
|
||||
logger.debug('Got: %s', arg)
|
||||
if not arg:
|
||||
await utils.answer(message, 'Только 1 аргумент - номер в списке или фамилия/имя')
|
||||
if arg.isdigit():
|
||||
add = f'людей с номером {arg}'
|
||||
arg = int(arg)
|
||||
users = list(self.db.find({"id": arg}))
|
||||
elif ' ' in arg or arg.lower() == 'янао': # Костыли костыли
|
||||
add = f'людей из региона {arg}'
|
||||
_users = list(self.db.find())
|
||||
users = []
|
||||
for user in _users:
|
||||
if user['region'].lower() == arg.lower():
|
||||
users.append(user)
|
||||
else:
|
||||
add = f'людей, которых зовут {arg}'
|
||||
arg = arg.capitalize()
|
||||
users = list(self.db.find({'$or': [{"last_name": arg}, {"first_name": arg}, {"patronymic": arg}]}))
|
||||
|
||||
msg = [f'{len(users)} всего {add}', '==']
|
||||
for user in users:
|
||||
del user['_id']
|
||||
s = Student(**user)
|
||||
msg += [str(s), '==']
|
||||
msg = msg[:-1]
|
||||
msg = '\n'.join(msg)
|
||||
await utils.answer(message, msg)
|
||||
|
||||
|
||||
|
||||
92
AlpacaGang/ftg-modules/spam.py
Normal file
92
AlpacaGang/ftg-modules/spam.py
Normal file
@@ -0,0 +1,92 @@
|
||||
# Copyright (C) 2019 The Raphielscape Company LLC.
|
||||
#
|
||||
# Licensed under the Raphielscape Public License, Version 1.c (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
||||
import asyncio
|
||||
from asyncio import wait, sleep
|
||||
|
||||
from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP
|
||||
from userbot.events import register
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.cspam (.*)")
|
||||
async def tmeme(e):
|
||||
cspam = str(e.pattern_match.group(1))
|
||||
message = cspam.replace(" ", "")
|
||||
await e.delete()
|
||||
for letter in message:
|
||||
await e.respond(letter)
|
||||
if BOTLOG:
|
||||
await e.client.send_message(
|
||||
BOTLOG_CHATID, "#CSPAM\n"
|
||||
"TSpam was executed successfully")
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.wspam (.*)")
|
||||
async def tmeme(e):
|
||||
wspam = str(e.pattern_match.group(1))
|
||||
message = wspam.split()
|
||||
await e.delete()
|
||||
for word in message:
|
||||
await e.respond(word)
|
||||
if BOTLOG:
|
||||
await e.client.send_message(
|
||||
BOTLOG_CHATID, "#WSPAM\n"
|
||||
"WSpam was executed successfully")
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.spam (.*)")
|
||||
async def spammer(e):
|
||||
counter = int(e.pattern_match.group(1).split(' ', 1)[0])
|
||||
spam_message = str(e.pattern_match.group(1).split(' ', 1)[1])
|
||||
await e.delete()
|
||||
await asyncio.wait([e.respond(spam_message) for i in range(counter)])
|
||||
if BOTLOG:
|
||||
await e.client.send_message(BOTLOG_CHATID, "#SPAM\n"
|
||||
"Spam was executed successfully")
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.picspam")
|
||||
async def tiny_pic_spam(e):
|
||||
message = e.text
|
||||
text = message.split()
|
||||
counter = int(text[1])
|
||||
link = str(text[2])
|
||||
await e.delete()
|
||||
await asyncio.wait([e.client.send_file(e.chat_id, link) for i in range(counter)])
|
||||
if BOTLOG:
|
||||
await e.client.send_message(
|
||||
BOTLOG_CHATID, "#PICSPAM\n"
|
||||
"PicSpam was executed successfully")
|
||||
|
||||
|
||||
@register(outgoing=True, pattern="^.delayspam (.*)")
|
||||
async def spammer(e):
|
||||
spamDelay = float(e.pattern_match.group(1).split(' ', 2)[0])
|
||||
counter = int(e.pattern_match.group(1).split(' ', 2)[1])
|
||||
spam_message = str(e.pattern_match.group(1).split(' ', 2)[2])
|
||||
await e.delete()
|
||||
for i in range(1, counter):
|
||||
await e.respond(spam_message)
|
||||
await sleep(spamDelay)
|
||||
if BOTLOG:
|
||||
await e.client.send_message(
|
||||
BOTLOG_CHATID, "#DelaySPAM\n"
|
||||
"DelaySpam was executed successfully")
|
||||
|
||||
|
||||
CMD_HELP.update({
|
||||
"spam":
|
||||
".cspam <text>\
|
||||
\nUsage: Spam the text letter by letter.\
|
||||
\n\n.spam <count> <text>\
|
||||
\nUsage: Floods text in the chat !!\
|
||||
\n\n.wspam <text>\
|
||||
\nUsage: Spam the text word by word.\
|
||||
\n\n.picspam <count> <link to image/gif>\
|
||||
\nUsage: As if text spam was not enough !!\
|
||||
\n\n.delayspam <delay> <count> <text>\
|
||||
\nUsage: .bigspam but with custom delay.\
|
||||
\n\n\nNOTE : Spam at your own risk !!"
|
||||
})
|
||||
37
AlpacaGang/ftg-modules/spf.py
Normal file
37
AlpacaGang/ftg-modules/spf.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# fuck python the encoding: utf-8
|
||||
from .. import loader, utils
|
||||
|
||||
import logging
|
||||
import datetime
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register(cb):
|
||||
cb(SPFMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class SPFMod(loader.Module):
|
||||
"""Этот модуль геи личку ваших друзей"""
|
||||
strings = {"name": "ЖУЖАКА НАХУЙ"}
|
||||
|
||||
def __init__(self):
|
||||
self.name = self.strings["name"]
|
||||
|
||||
def config_complete(self):
|
||||
pass
|
||||
|
||||
async def spfcmd(self, message):
|
||||
"""Чтобы использовать пишем так: .spf @ник_вашего_друга"""
|
||||
args = utils.get_args(message)
|
||||
if not args:
|
||||
await utils.answer(message, "Вы не указали кому хотите писать\nЧтобы использовать напишите так: .spf @ник_вашего_друга")
|
||||
return
|
||||
who = args[0][1:]
|
||||
conv = message.client.conversation("t.me/" + who,
|
||||
timeout=5, exclusive=True)
|
||||
for i in range(100):
|
||||
await conv.send_message("Ты гей")
|
||||
245
AlpacaGang/ftg-modules/tralka.py
Normal file
245
AlpacaGang/ftg-modules/tralka.py
Normal file
@@ -0,0 +1,245 @@
|
||||
from .. import loader, utils
|
||||
import logging
|
||||
import random
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
version = 4.8
|
||||
sentence_min = 3
|
||||
sentence_max = 10
|
||||
# paragraph_min = 10
|
||||
# paragraph_max = 20
|
||||
print_length = False
|
||||
|
||||
m = ['некультурный', 'необразованный',
|
||||
'гороховый', 'мудовый', 'глупенький',
|
||||
'малолетний', 'ебучий', 'гнилой',
|
||||
'собачий', 'ссаный', 'моржовый',
|
||||
'вредный', 'прибабахнутый', 'ебаный',
|
||||
'волшебный', 'сказочный', 'маленький',
|
||||
'приёмный', 'сральный', 'пердёжный',
|
||||
'обоссанный', 'обосранный', 'чёртов',
|
||||
'грязный', 'тупой', 'нищий', 'родной', 'мусорный',
|
||||
'дегенеративный',
|
||||
'распроклятый', 'турецкий', 'блядский',
|
||||
'ёбаный', 'хуев', 'хуёвый', 'ебанутый',
|
||||
'ёбнутый', 'грязный', 'зелёный', 'сукин',
|
||||
'лысый', 'пожилой', 'вонючий', 'чокнутый']
|
||||
|
||||
f = ['некультурная', 'необразованная',
|
||||
'гороховая', 'мудовая', 'глупенькая',
|
||||
'малолетняя', 'ебучая', 'гнилая',
|
||||
'собачья', 'ссаная', 'моржовая',
|
||||
'вредная', 'прибабахнутая', 'ебаная',
|
||||
'волшебная', 'сказочная', 'маленькая',
|
||||
'приёмная', 'сральная', 'пердёжная',
|
||||
'обоссанная', 'обосранная', 'чёртова',
|
||||
'грязная', 'тупая', 'нищая',
|
||||
'родная', 'мусорная', 'дегенеративная',
|
||||
'распроклятая', 'турецкая', 'блядская',
|
||||
'ёбаная', 'хуева', 'хуёвая', 'ебанутая',
|
||||
'ёбнутая', 'грязная', 'зелёная', 'сукина',
|
||||
'лысая', 'пожилая', 'вонючая', 'чокнутая']
|
||||
|
||||
s = ['некультурное', 'необразованное',
|
||||
'гороховое', 'мудовое', 'глупенькое',
|
||||
'малолетнее', 'ебучее', 'гнилое',
|
||||
'собачье', 'ссаное', 'моржовое',
|
||||
'вредное', 'прибабахнутое', 'ебаное',
|
||||
'волшебное', 'сказочное', 'маленькое',
|
||||
'приёмное', 'сральное', 'пердёжное',
|
||||
'обоссанное', 'обосранное', 'чёртово', 'грязное',
|
||||
'тупое', 'нищее', 'родное', 'мусорное', 'дегенеративное',
|
||||
'распроклятое', 'турецкое', 'блядское',
|
||||
'ёбаное', 'хуево', 'хуёвое', 'ебанутое',
|
||||
'ёбнутое', 'грязное', 'зелёное', 'сукино',
|
||||
'лысое', 'пожилое', 'вонючее', 'чокнутое']
|
||||
|
||||
k = ['из жопы', 'в ловушке', 'в бане',
|
||||
'на хуе', 'в дурке', 'из стула', 'в дурке ебаной',
|
||||
'в хуипе', 'в запечатанной колоде']
|
||||
|
||||
n = ['негра', 'джокера', 'тупого говна', 'хуйни ебаной',
|
||||
'хуя', 'феминизма', 'говна',
|
||||
'от народа', 'хуйни', 'Навального',
|
||||
'ловушкера', 'Путина', 'русского народа', 'вонючки', 'с функцией жопа']
|
||||
|
||||
o = ['пиздец', 'блять', 'попался в ловушку',
|
||||
'тебя забайтили', 'ловушка джокера', 'тебе бан',
|
||||
'фак ю', 'убейся', 'соси',
|
||||
'ёбаный твой рот', 'срал я на тебя',
|
||||
'убейся об стену', 'соси пизду', 'у тебя хуй вместо носа',
|
||||
'купи мою подписку на ютубе',
|
||||
'хуй соси', 'губой тряси', 'я съел деда',
|
||||
'насрал в пизду',
|
||||
'22 июня 1642 года Карл Первый поднял королевский штандарт (королевский флаг), что по английским традициям означало объявление войны',
|
||||
'мне этот мир абсолютно понятен',
|
||||
'я был на этой планете бесконечным множеством',
|
||||
'но тебе этого не понять',
|
||||
'иди преисполняться в гранях каких-то',
|
||||
'пиздуй - бороздуй',
|
||||
'бредишь', 'вот я какну и смываю, и ты так делай',
|
||||
'не надо шутить с войной',
|
||||
'твою дочку ебут', 'залупаешься',
|
||||
'хули ты пиздишь', 'поцелуй лошадиную сраку',
|
||||
'распронаёб тебя', 'ъеь', 'ьуь', 'аье',
|
||||
'какого хуя они в другом порядке разложены',
|
||||
'ай фак ю булщит щит',
|
||||
'он за углом сидит и тебе на голову дрочит',
|
||||
'армяне в нарды играют', 'жирняк гай',
|
||||
'иди сюда, попробуй меня трахнуть, я тебя сам трахну',
|
||||
'что ты там делаешь', 'беги за горизонт',
|
||||
'попал в дурку ебаную', 'был бы ты человек', 'нахуй',
|
||||
'запомни', 'хули ты сюда лезешь',
|
||||
'высрана твоя морда', 'возьми салфетку',
|
||||
'я бы никому не проиграл',
|
||||
'иди нахуй', 'иди',
|
||||
'я тебя ебал, гад, срать на нас говна',
|
||||
'я тебя ебал гадить нас срать так',
|
||||
'держи в курсе', 'несёшь хуйню какую-то',
|
||||
'русские вперёд']
|
||||
|
||||
d = ['бекон', 'сыр', 'пенис', 'член',
|
||||
'мудозвон', 'лицемер', 'лжец',
|
||||
'хуй', 'гомогей', 'чай', 'рукоблуд',
|
||||
'долбан', 'пидорас', 'сын', 'козёл',
|
||||
'газ', 'фашист', 'пососатель',
|
||||
'дегенерат', 'спермобак', 'долбоёб',
|
||||
'клоун', 'паразит', 'письколёт',
|
||||
'мудак', 'спидозник', 'пудж', 'кремлебот',
|
||||
'объебос', 'дурачок', 'хуебес', 'пиздолёт',
|
||||
'педик', 'педик - медведик', 'дебил', 'дифичент',
|
||||
'кок сакер', 'пиздабол', 'аутист', 'гадёныш', 'выблядок',
|
||||
'глиномес', 'даун', 'хер', 'булщит', 'засранец',
|
||||
'инвалид', 'дурак', 'болван',
|
||||
'минетчик', 'онанист', 'напёрдыш',
|
||||
'чилипиздрик', 'пиздюк', 'гей', 'ловушкер',
|
||||
'пендос', 'наркоман', 'алкаш', 'жиробас',
|
||||
'рак', 'укурок', 'крокодил', 'ебальник',
|
||||
'секс-раб', 'потомок', 'дрыщ',
|
||||
'урод', 'карлик', 'дед инсайд', 'волк',
|
||||
'калыван', 'либераст', 'шакал',
|
||||
'педофил', 'бомж', 'пингвин', 'жираф',
|
||||
'огурец', 'салат', 'лук', 'картофель',
|
||||
'деградант', 'спам', 'человек', 'гуманитарий',
|
||||
'язык', 'стол', 'PEP-8', 'ебалай', 'враг', 'недруг', 'супостат',
|
||||
'кретин', 'козолуп', 'свинарь',
|
||||
'униженец', 'опущенец', 'муравей',
|
||||
'дятел', 'козёл', 'жирняк', 'говноед',
|
||||
'чёрт', 'суслик', 'идиот', 'жлоб', 'мерзавец',
|
||||
'негодяй', 'подлец', 'ублюдок', 'гад',
|
||||
'гавкошмыг', 'чикибамбонатор', 'чикибамбог',
|
||||
'джокер', 'жмых', 'жмышок', 'жмышонок',
|
||||
'куколд', 'ебалай', 'ушлёпок',
|
||||
'хуесос', 'членосос', 'чикибамбонёнок',
|
||||
'чикибан', 'чикибомбастер', 'чайник',
|
||||
'чикибамбонизатор', 'чикибамбог']
|
||||
|
||||
dd = ['куколда', 'хуйолда', 'мудила', 'блядина', 'гнида',
|
||||
'пидрила', 'тварь', 'сука', 'сперма', 'пидорасина',
|
||||
'либераха', 'срака', 'жопа', 'петушара', 'залупа',
|
||||
'хуета', 'пупа', 'петька', 'блядь', 'елда', 'тряпка',
|
||||
'яма', 'хуемразь', 'срань', 'мошонка', 'ссанина',
|
||||
'вагина', 'пизда', 'пососательница',
|
||||
'ловушка', 'паста', 'макаронина',
|
||||
'жиробасина', 'радфемка', 'шлюха', 'прошмандовка',
|
||||
'жируха', 'доска', 'уродина',
|
||||
'плоскодонка', 'скотина', 'омега',
|
||||
'черешня', 'ватрушка', 'шишка',
|
||||
'ракушка', 'свинья', 'какашка',
|
||||
'гнилушка', 'лягушка', 'свинушка',
|
||||
'картошка', 'волчара', 'дочь', 'пешка',
|
||||
'давалка', 'пососательница',
|
||||
'колбаса', 'собака', 'мохнатка', 'жижа',
|
||||
'какашка', 'какуля', 'душа', 'вражина',
|
||||
'падла', 'болезнь', 'бумажка', 'вонючка',
|
||||
'тень', 'гадина', 'чикибамбони',
|
||||
'микробамбони', 'мышь', 'мразь',
|
||||
'мразина', 'мразота']
|
||||
|
||||
ddd = ['удобрение', 'уёбище', 'ебло', 'хуйло',
|
||||
'чудище', 'говно', 'яблоко', 'животное',
|
||||
'дерьмо', 'блядотище', 'дитя', 'порождение',
|
||||
'очко', 'растение', 'ебало', 'ведро',
|
||||
'мудило', 'хуепучило']
|
||||
|
||||
gens = ['03', '14', '25', '8',
|
||||
'06', '16', '26', '30',
|
||||
'41', '52', '303', '330', '0',
|
||||
'414', '441', '1', '8',
|
||||
'525', '552', '2', '067',
|
||||
'167', '267', '306', '416',
|
||||
'526', '07', '8', '8', '8',
|
||||
'17', '27', '8', '8', '8',
|
||||
'307', '417', '527', '8', '8',
|
||||
'3067', '4167', '5267']
|
||||
|
||||
array = [d, dd, ddd, m, f, s, k, n, o]
|
||||
|
||||
|
||||
def generate(word_count: int, caps_rate: int, name: str):
|
||||
res = []
|
||||
priv = ''
|
||||
if name:
|
||||
priv += f'Привет, {name}! '
|
||||
caps_rate %= 100
|
||||
priv += 'Ты, '
|
||||
word_count_now = 0
|
||||
while word_count_now < word_count:
|
||||
tempi = word_count + 1
|
||||
while word_count_now + tempi > word_count:
|
||||
random.seed()
|
||||
y = random.choice(gens)
|
||||
x = []
|
||||
for j in y:
|
||||
x.append(random.choice(array[int(j)]))
|
||||
x = ' '.join(x)
|
||||
tempi = len(x.split())
|
||||
res.append(x)
|
||||
word_count_now += tempi
|
||||
res = ', '.join(res)
|
||||
res = res.split()
|
||||
count = 0
|
||||
kek = random.randint(sentence_min, sentence_max)
|
||||
for v in range(len(res)):
|
||||
if res[v].endswith(','):
|
||||
count += 1
|
||||
if count % kek == 0:
|
||||
count = 0
|
||||
random.seed()
|
||||
kek = random.randint(sentence_min, sentence_max)
|
||||
res[v] = res[v][:-1] + '.'
|
||||
if v < len(res) - 1:
|
||||
res[v + 1] = res[v + 1][0].upper() + res[v + 1][1:]
|
||||
res[0] = priv + res[0]
|
||||
res = ' '.join(res).split()
|
||||
for v in range(len(res)):
|
||||
random.seed()
|
||||
z = random.randint(0, 99)
|
||||
if z < caps_rate:
|
||||
res[v] = res[v].upper()
|
||||
return ' '.join(res) + '.'
|
||||
# КТО ПРОЧИТАЛ ТОТ ЗДОХНЕТ
|
||||
|
||||
def register(cb):
|
||||
cb(TralkaMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class TralkaMod(loader.Module):
|
||||
"""Generates pastes"""
|
||||
strings = {"name": "Tralka"}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig()
|
||||
self.name = self.strings['name']
|
||||
|
||||
async def tralkacmd(self, message):
|
||||
""".tralka <word_count> <caps_rate (in %)> <recepient name>"""
|
||||
args = utils.get_args(message)
|
||||
if len(args) < 2:
|
||||
await utils.answer(message, "Not enough arguments")
|
||||
elif len(args) == 2:
|
||||
await utils.answer(message, generate(int(args[0]), int(args[1]), None))
|
||||
else:
|
||||
await utils.answer(message, generate(int(args[0]), int(args[1]), args[2]))
|
||||
94
AlpacaGang/ftg-modules/wait.py
Normal file
94
AlpacaGang/ftg-modules/wait.py
Normal file
@@ -0,0 +1,94 @@
|
||||
from .. import loader, utils
|
||||
|
||||
import logging
|
||||
import datetime
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register(cb):
|
||||
cb(WAITMod())
|
||||
|
||||
|
||||
@loader.tds
|
||||
class WAITMod(loader.Module):
|
||||
"""Этот модуль поможет вам удалить сообщение через n секунд/минут"""
|
||||
strings = {"name": "wait"}
|
||||
|
||||
def __init__(self):
|
||||
self.name = self.strings["name"]
|
||||
|
||||
def config_complete(self):
|
||||
pass
|
||||
|
||||
async def wait5cmd(self, message):
|
||||
"""Эта команда удаляет сообхение черезе 5 секунд"""
|
||||
await utils.answer(message, "Через 5 секунд это сообщение удалится")
|
||||
|
||||
for i in range(4, -1, -1):
|
||||
await asyncio.sleep(1)
|
||||
await utils.answer(message, "Через " + str(i) + " секунд это сообщение удалится")
|
||||
|
||||
await message.delete()
|
||||
|
||||
async def waitcmd(self, message):
|
||||
"""Эта команда удаляет сообхение через n секунд, \nписать нужно так: .wait <n>, если хотите секунды\nи так .wait <n>m, если хотите ждать в минутах\n(например .wait 5m)"""
|
||||
args = utils.get_args(message)
|
||||
if not args or len(args) > 1:
|
||||
await utils.answer(message, "Вы не указали число секунд или указали несколько параметров")
|
||||
else:
|
||||
try:
|
||||
g = -1
|
||||
h = ""
|
||||
try:
|
||||
g = int(args[0][:len(args[0])])
|
||||
except:
|
||||
try:
|
||||
g = int(args[0][:len(args[0]) - 1])
|
||||
h = args[0][len(args[0]) - 1]
|
||||
except:
|
||||
await utils.answer(message, "Вы указали не число!")
|
||||
if g > 0:
|
||||
if h == 's' or h == '':
|
||||
x = g
|
||||
lst = "Через " + str(x) + " секунд это сообщение удалится"
|
||||
await utils.answer(message, lst)
|
||||
|
||||
dd = time.time()
|
||||
|
||||
while time.time() - dd < x:
|
||||
now = "Через " + str(x - round(time.time() - dd)) + " секунд это сообщение удалится"
|
||||
if now != lst:
|
||||
await utils.answer(message, now)
|
||||
lst = now
|
||||
await message.delete()
|
||||
elif h == 'm':
|
||||
x = g
|
||||
lst = "Через " + str(x) + " минут это сообщение удалится"
|
||||
await utils.answer(message, lst)
|
||||
|
||||
dd = time.time()
|
||||
|
||||
ff = x * 60
|
||||
|
||||
llst = x
|
||||
while time.time() - dd < ff:
|
||||
oo = round((ff - round(time.time() - dd)) / 60)
|
||||
nw = oo
|
||||
if nw == llst:
|
||||
await asyncio.sleep(0.1)
|
||||
continue
|
||||
now = "Через " + str(nw) + " минут это сообщение удалится"
|
||||
await utils.answer(message, now)
|
||||
llst = nw
|
||||
await message.delete()
|
||||
else:
|
||||
await utils.answer(message, "Вы указали не число!")
|
||||
except:
|
||||
await utils.answer(message, "Упс, ошибочка вышла! Напшите @gerasikoff, он вам поможет")
|
||||
|
||||
async def tagcmd(self, message):
|
||||
"""Эта команда для троллинга друзей. \nЕй вы можете тегнуть друга, а сообщение само удалится!"""
|
||||
await message.delete()
|
||||
Reference in New Issue
Block a user