init
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# config files
|
||||
config.json
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
21
Timer/__init__.py
Normal file
@ -0,0 +1,21 @@
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
class Timer:
|
||||
def __init__(self, callback, timeout):
|
||||
logging.info("Created a schedule interval as " + str(timeout) + " seconds.")
|
||||
loop = asyncio.get_event_loop()
|
||||
self.callback = callback
|
||||
self.timeout = timeout
|
||||
self.task = loop.create_task(self.wait())
|
||||
|
||||
async def wait(self):
|
||||
await asyncio.sleep(self.timeout)
|
||||
logging.info("Successfully executed a timer schedule.")
|
||||
await self.callback
|
||||
|
||||
def stop(self):
|
||||
try:
|
||||
self.task.cancel()
|
||||
except asyncio.CancelledError:
|
||||
pass
|
BIN
bot.session
Normal file
BIN
bot.session-journal
Normal file
17
car.service
Normal file
@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=captcha
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/root/CAR
|
||||
ExecStart=/usr/bin/python3 /root/CAR/main.py
|
||||
Restart=always
|
||||
PrivateTmp=True
|
||||
KillSignal=SIGINT
|
||||
TimeoutStopSec=10s
|
||||
StartLimitInterval=400
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
80
challenge.py
Normal file
@ -0,0 +1,80 @@
|
||||
import random
|
||||
import configparser
|
||||
|
||||
class Challenge:
|
||||
"""
|
||||
如果你是 Python 高手,请继续;如果你根本不会Python或者语法乱七八糟,我建议你还是先去 https://docs.python.org 学习一个。
|
||||
一个简单的验证问题变量说明
|
||||
请注意,如果要使用中文写出各个选项,建议把main.py里344-346行修改为如下形式:
|
||||
[InlineKeyboardButton(str(c),
|
||||
callback_data=bytes(
|
||||
str(c), encoding="utf-8"))])
|
||||
这么做的目的是能让问题的选项每个一行,否则一行四个答案可能会显示不下
|
||||
__str__ 方法返回问题的具体内容,
|
||||
qus 返回上面的 __str__ 方法
|
||||
ans 返回 Challenge 的答案
|
||||
choices 返回 Challenge 的选项们
|
||||
_ans 属性是问题,
|
||||
_choices 是问题选项
|
||||
比如说你可以这么改写 Challenge 类
|
||||
def __init(self):
|
||||
self._ans= ''
|
||||
self._choices = []
|
||||
self.new()
|
||||
def __str__(self):
|
||||
return "下面哪一个不是路由器的架构?"
|
||||
def new(self):
|
||||
self._choices['MIPS','ARM','8051','x86']
|
||||
self._answer = '8051'
|
||||
|
||||
qus, ans,choices 这三个函数可以放着不动
|
||||
"""
|
||||
def __init__(self):
|
||||
self._a = 0
|
||||
self._pu = "A"
|
||||
# 所以为啥要把a,b两个属性丢这里?我不是太懂。。。
|
||||
self._op = "A"
|
||||
self._ans = 0
|
||||
self._choices = []
|
||||
self.new()
|
||||
|
||||
def __str__(self):
|
||||
return "{op} {a}的正确选项是?".format(a=self._a, op=self._op)
|
||||
|
||||
def new(self):
|
||||
conf = configparser.ConfigParser()
|
||||
conf.read("tk.json")
|
||||
operation = str(random.randint(0, int(conf.get("ans", "all"))))
|
||||
a, ans = "号题目", "A"
|
||||
try:
|
||||
f = open(str("pic/") + operation + str(".png"))
|
||||
f.close()
|
||||
pu = str("pic/") + operation + str(".png")
|
||||
except IOError:
|
||||
pu = str("pic/") + operation + str(".jpg")
|
||||
if operation in conf.get("ans", "A").split():
|
||||
ans = "A"
|
||||
elif operation in conf.get("ans", "B").split():
|
||||
ans = "B"
|
||||
elif operation in conf.get("ans", "C").split():
|
||||
ans = "C"
|
||||
elif operation in conf.get("ans", "D").split():
|
||||
ans = "D"
|
||||
choices = ['A','B','C','D']
|
||||
self._a = a
|
||||
self._op = operation
|
||||
self._ans = ans
|
||||
self._pu = pu
|
||||
self._choices = choices
|
||||
|
||||
def qus(self):
|
||||
return self.__str__()
|
||||
|
||||
def ans(self):
|
||||
return self._ans
|
||||
|
||||
def pu(self):
|
||||
return self._pu
|
||||
|
||||
def choices(self):
|
||||
return self._choices
|
11
do.txt
Normal file
@ -0,0 +1,11 @@
|
||||
2018年全国卷1数学(理科)高考试题
|
||||
2018年全国卷1数学(文科)高考试题
|
||||
2018年全国卷1理综高考试题
|
||||
2019年全国I卷高考数学(理科)试题
|
||||
2019年全国I卷高考理综试题
|
||||
2019年全国III卷高考理综试题
|
||||
1C 2B 3A 4B 5D 6A 7B 8D 9C 10A 11B 12A
|
||||
13A 14C 15A 16C 17B 18D 19A 20B 21B 22C 23B 24D
|
||||
25D 26B 27A 28C 29D 30C 31D 32A 33D 34B 35C 36B 37C 38B 39A 40D 41B 42C
|
||||
43C 44C 45B 46B 47D 48A 49B 50A 51A 52B 53C 54D
|
||||
55B 56C 57A 58D 59C 60D 61A 62B 63D 64D 65C 66B 67C 68A 69D 70B 71B 72C
|
600
main.py
Normal file
@ -0,0 +1,600 @@
|
||||
# !/usr/bin/env python3
|
||||
import asyncio
|
||||
import json
|
||||
import threading
|
||||
import configparser
|
||||
import logging, subprocess
|
||||
from time import time, sleep
|
||||
from challenge import Challenge
|
||||
from pyrogram import (Client, Filters, Message, User, InlineKeyboardButton,
|
||||
InlineKeyboardMarkup, CallbackQuery, ChatPermissions)
|
||||
from pyrogram.errors import ChatAdminRequired, ChannelPrivate, ChannelInvalid
|
||||
from Timer import Timer
|
||||
|
||||
_app: Client = None
|
||||
_channel: str = None
|
||||
_start_message: str = None
|
||||
# _challenge_scheduler = sched.scheduler(time, sleep)
|
||||
_current_challenges = dict()
|
||||
_cch_lock = threading.Lock()
|
||||
_config = dict()
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
# 设置一下日志记录,能够在诸如 systemctl status captchabot 这样的地方获得详细输出。
|
||||
conf = configparser.ConfigParser()
|
||||
|
||||
def load_config():
|
||||
global _config
|
||||
with open("config.json", encoding="utf-8") as f:
|
||||
_config = json.load(f)
|
||||
|
||||
|
||||
def save_config():
|
||||
with open("config.json", "w") as f:
|
||||
json.dump(_config, f, indent=4)
|
||||
|
||||
def _update(app):
|
||||
@app.on_message(Filters.command("ping") & Filters.private)
|
||||
async def ping_command(client: Client, message: Message):
|
||||
await message.reply("poi~poi~poi~")
|
||||
|
||||
@app.on_message(Filters.command("upload") & Filters.group)
|
||||
async def upload_command(client: Client, message: Message):
|
||||
if message.chat.id == -1001413542074:
|
||||
conf.read("tk.json")
|
||||
qustion_all = conf.get("ans", "all")
|
||||
qustion_a = conf.get("ans", "A")
|
||||
qustion_b = conf.get("ans", "B")
|
||||
qustion_c = conf.get("ans", "C")
|
||||
qustion_d = conf.get("ans", "D")
|
||||
if message.reply_to_message.document.mime_type == "image/jpeg":
|
||||
await client.download_media(message.reply_to_message, file_name="pic/" + str(int(qustion_all) + 1) + ".jpg")
|
||||
elif message.reply_to_message.document.mime_type == "image/png":
|
||||
await client.download_media(message.reply_to_message, file_name="pic/" + str(int(qustion_all) + 1) + ".png")
|
||||
if message.text.split()[-1] == "A":
|
||||
conf.set("ans", "A", qustion_a + " " + str(int(qustion_all) + 1))
|
||||
conf.set("ans", "all", str(int(qustion_all) + 1))
|
||||
conf.write(open("tk.json", "w"))
|
||||
if message.text.split()[-1] == "B":
|
||||
conf.set("ans", "B", qustion_b + " " + str(int(qustion_all) + 1))
|
||||
conf.set("ans", "all", str(int(qustion_all) + 1))
|
||||
conf.write(open("tk.json", "w"))
|
||||
if message.text.split()[-1] == "C":
|
||||
conf.set("ans", "C", qustion_c + " " + str(int(qustion_all) + 1))
|
||||
conf.set("ans", "all", str(int(qustion_all) + 1))
|
||||
conf.write(open("tk.json", "w"))
|
||||
if message.text.split()[-1] == "D":
|
||||
conf.set("ans", "D", qustion_d + " " + str(int(qustion_all) + 1))
|
||||
conf.set("ans", "all", str(int(qustion_all) + 1))
|
||||
conf.write(open("tk.json", "w"))
|
||||
await message.reply("done")
|
||||
|
||||
@app.on_message(Filters.command("start") & Filters.private)
|
||||
async def start_command(client: Client, message: Message):
|
||||
await message.reply("<a href='tg://user?id=" + str(message.from_user.id) + "'>" + message.from_user.first_name + "</a> " + _start_message)
|
||||
|
||||
@app.on_message(Filters.command("answer"))
|
||||
async def answer_command(client: Client, message: Message):
|
||||
if message.from_user.id == int(347437156) or message.from_user.id == int(
|
||||
616760897) or message.from_user.id == int(441229454):
|
||||
qustion_id = message.text.split()[-1]
|
||||
conf.read("tk.json")
|
||||
qustion_a = conf.get("ans", "A").split()
|
||||
qustion_b = conf.get("ans", "B").split()
|
||||
qustion_c = conf.get("ans", "C").split()
|
||||
qustion_d = conf.get("ans", "D").split()
|
||||
if qustion_id in qustion_a:
|
||||
await message.reply("<a href='tg://user?id=" + str(message.from_user.id) + "'>" + message.from_user.first_name + "</a> 此题的正确答案为:`A`")
|
||||
elif qustion_id in qustion_b:
|
||||
await message.reply("<a href='tg://user?id=" + str(
|
||||
message.from_user.id) + "'>" + message.from_user.first_name + "</a> 此题的正确答案为:`B`")
|
||||
elif qustion_id in qustion_c:
|
||||
await message.reply("<a href='tg://user?id=" + str(
|
||||
message.from_user.id) + "'>" + message.from_user.first_name + "</a> 此题的正确答案为:`C`")
|
||||
elif qustion_id in qustion_d:
|
||||
await message.reply("<a href='tg://user?id=" + str(
|
||||
message.from_user.id) + "'>" + message.from_user.first_name + "</a> 此题的正确答案为:`D`")
|
||||
|
||||
@app.on_message(Filters.command("leave") & Filters.private)
|
||||
async def leave_command(client: Client, message: Message):
|
||||
chat_id = message.text.split()[-1]
|
||||
if message.from_user.id == _config["manage_user"]:
|
||||
try:
|
||||
await client.send_message(int(chat_id),
|
||||
_config["msg_leave_msg"])
|
||||
await client.leave_chat(int(chat_id), True)
|
||||
except:
|
||||
await message.reply("指令出错了!可能是bot不在参数所在群里。")
|
||||
else:
|
||||
await message.reply("已离开群组: `" + chat_id + "`",
|
||||
parse_mode="Markdown")
|
||||
_me: User = await client.get_me()
|
||||
try:
|
||||
await client.send_message(
|
||||
int(_channel),
|
||||
_config["msg_leave_group"].format(
|
||||
botid=str(_me.id),
|
||||
groupid=chat_id,
|
||||
),
|
||||
parse_mode="Markdown")
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
else:
|
||||
pass
|
||||
|
||||
@app.on_callback_query()
|
||||
async def challenge_callback(client: Client,
|
||||
callback_query: CallbackQuery):
|
||||
query_data = str(callback_query.data)
|
||||
query_id = callback_query.id
|
||||
chat_id = callback_query.message.chat.id
|
||||
user_id = callback_query.from_user.id
|
||||
msg_id = callback_query.message.message_id
|
||||
chat_title = callback_query.message.chat.title
|
||||
user_name = callback_query.from_user.first_name
|
||||
group_config = _config.get(str(chat_id), _config["*"])
|
||||
if query_data in ["+", "-"]:
|
||||
admins = await client.get_chat_members(chat_id,
|
||||
filter="administrators")
|
||||
if not any([
|
||||
admin.user.id == user_id and
|
||||
(admin.status == "creator" or admin.can_restrict_members)
|
||||
for admin in admins
|
||||
]):
|
||||
await client.answer_callback_query(
|
||||
query_id, group_config["msg_permission_denied"])
|
||||
return
|
||||
|
||||
ch_id = "{chat}|{msg}".format(chat=chat_id, msg=msg_id)
|
||||
_cch_lock.acquire()
|
||||
# target: int = None
|
||||
challenge, target, timeout_event = _current_challenges.get(
|
||||
ch_id, (None, None, None))
|
||||
if ch_id in _current_challenges:
|
||||
del _current_challenges[ch_id]
|
||||
_cch_lock.release()
|
||||
timeout_event.stop()
|
||||
|
||||
if query_data == "+":
|
||||
try:
|
||||
await client.restrict_chat_member(
|
||||
chat_id,
|
||||
target,
|
||||
permissions=ChatPermissions(
|
||||
can_send_other_messages=True,
|
||||
can_send_messages=True,
|
||||
can_send_media_messages=True,
|
||||
can_add_web_page_previews=True,
|
||||
))
|
||||
except ChatAdminRequired:
|
||||
await client.answer_callback_query(
|
||||
query_id, group_config["msg_bot_no_permission"])
|
||||
return
|
||||
|
||||
await client.edit_message_caption(
|
||||
chat_id,
|
||||
msg_id,
|
||||
group_config["msg_approved"].format(user=user_name),
|
||||
reply_markup=None,
|
||||
)
|
||||
_me: User = await client.get_me()
|
||||
try:
|
||||
await client.send_message(
|
||||
int(_channel),
|
||||
_config["msg_passed_admin"].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(target),
|
||||
groupid=str(chat_id),
|
||||
grouptitle=str(chat_title),
|
||||
),
|
||||
parse_mode="Markdown",
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
else:
|
||||
try:
|
||||
await client.kick_chat_member(chat_id, target)
|
||||
except ChatAdminRequired:
|
||||
await client.answer_callback_query(
|
||||
query_id, group_config["msg_bot_no_permission"])
|
||||
return
|
||||
await client.edit_message_caption(
|
||||
chat_id,
|
||||
msg_id,
|
||||
group_config["msg_refused"].format(user=user_name),
|
||||
reply_markup=None,
|
||||
)
|
||||
_me: User = await client.get_me()
|
||||
try:
|
||||
await client.send_message(
|
||||
int(_channel),
|
||||
_config["msg_failed_admin"].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(target),
|
||||
groupid=str(chat_id),
|
||||
grouptitle=str(chat_title),
|
||||
),
|
||||
parse_mode="Markdown",
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
await client.answer_callback_query(query_id)
|
||||
return
|
||||
|
||||
ch_id = "{chat}|{msg}".format(chat=chat_id, msg=msg_id)
|
||||
_cch_lock.acquire()
|
||||
challenge, target, timeout_event = _current_challenges.get(
|
||||
ch_id, (None, None, None))
|
||||
_cch_lock.release()
|
||||
if user_id != target:
|
||||
await client.answer_callback_query(
|
||||
query_id, group_config["msg_challenge_not_for_you"])
|
||||
return None
|
||||
timeout_event.stop()
|
||||
try:
|
||||
await client.restrict_chat_member(
|
||||
chat_id,
|
||||
target,
|
||||
permissions=ChatPermissions(can_send_other_messages=True,
|
||||
can_send_messages=True,
|
||||
can_send_media_messages=True,
|
||||
can_add_web_page_previews=True,
|
||||
can_send_polls=True))
|
||||
except ChatAdminRequired:
|
||||
pass
|
||||
|
||||
correct = str(challenge.ans()) == query_data
|
||||
if correct:
|
||||
await client.edit_message_caption(
|
||||
chat_id,
|
||||
msg_id,
|
||||
group_config["msg_challenge_passed"],
|
||||
reply_markup=None)
|
||||
_me: User = await client.get_me()
|
||||
try:
|
||||
await client.send_message(
|
||||
int(_channel),
|
||||
_config["msg_passed_answer"].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(target),
|
||||
groupid=str(chat_id),
|
||||
grouptitle=str(chat_title),
|
||||
),
|
||||
parse_mode="Markdown",
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
else:
|
||||
if not group_config["use_strict_mode"]:
|
||||
await client.edit_message_caption(
|
||||
chat_id,
|
||||
msg_id,
|
||||
group_config["msg_challenge_mercy_passed"],
|
||||
reply_markup=None,
|
||||
)
|
||||
_me: User = await client.get_me()
|
||||
try:
|
||||
await client.send_message(
|
||||
int(_channel),
|
||||
_config["msg_passed_mercy"].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(target),
|
||||
groupid=str(chat_id),
|
||||
grouptitle=str(chat_title),
|
||||
),
|
||||
parse_mode="Markdown",
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
else:
|
||||
try:
|
||||
await client.edit_message_caption(
|
||||
chat_id,
|
||||
msg_id,
|
||||
group_config["msg_challenge_failed"].format(challengeans=challenge.ans()),
|
||||
reply_markup=None,
|
||||
)
|
||||
# await client.restrict_chat_member(chat_id, target)
|
||||
_me: User = await client.get_me()
|
||||
try:
|
||||
await client.send_message(
|
||||
int(_channel),
|
||||
_config["msg_failed_answer"].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(target),
|
||||
groupid=str(chat_id),
|
||||
grouptitle=str(chat_title),
|
||||
),
|
||||
parse_mode="Markdown",
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
except ChatAdminRequired:
|
||||
return
|
||||
|
||||
if group_config["challenge_timeout_action"] == "ban":
|
||||
await client.kick_chat_member(chat_id, user_id)
|
||||
elif group_config["challenge_timeout_action"] == "kick":
|
||||
await client.kick_chat_member(chat_id, user_id)
|
||||
await client.unban_chat_member(chat_id, user_id)
|
||||
elif group_config["challenge_timeout_action"] == "mute":
|
||||
await client.restrict_chat_member(
|
||||
chat_id=chat_id,
|
||||
user_id=user_id,
|
||||
permissions=ChatPermissions(can_send_other_messages=False,
|
||||
can_send_messages=False,
|
||||
can_send_media_messages=False,
|
||||
can_add_web_page_previews=False,
|
||||
can_send_polls=False))
|
||||
else:
|
||||
pass
|
||||
|
||||
if group_config["delete_failed_challenge"]:
|
||||
Timer(
|
||||
client.delete_messages(chat_id, msg_id),
|
||||
group_config["delete_failed_challenge_interval"],
|
||||
)
|
||||
if group_config["delete_passed_challenge"]:
|
||||
Timer(
|
||||
client.delete_messages(chat_id, msg_id),
|
||||
group_config["delete_passed_challenge_interval"],
|
||||
)
|
||||
|
||||
@app.on_message(Filters.new_chat_members)
|
||||
async def challenge_user(client: Client, message: Message):
|
||||
target = message.new_chat_members[0]
|
||||
if message.from_user.id != target.id:
|
||||
if target.is_self:
|
||||
group_config = _config.get(str(message.chat.id), _config["*"])
|
||||
try:
|
||||
await client.send_message(
|
||||
message.chat.id, group_config["msg_self_introduction"])
|
||||
_me: User = await client.get_me()
|
||||
try:
|
||||
await client.send_message(
|
||||
int(_channel),
|
||||
_config["msg_into_group"].format(
|
||||
botid=str(_me.id),
|
||||
groupid=str(message.chat.id),
|
||||
grouptitle=str(message.chat.title),
|
||||
),
|
||||
parse_mode="Markdown",
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
except ChannelPrivate:
|
||||
return
|
||||
return
|
||||
try:
|
||||
await client.restrict_chat_member(
|
||||
chat_id=message.chat.id,
|
||||
user_id=target.id,
|
||||
permissions=ChatPermissions(can_send_other_messages=False,
|
||||
can_send_messages=False,
|
||||
can_send_media_messages=False,
|
||||
can_add_web_page_previews=False,
|
||||
can_send_polls=False))
|
||||
except ChatAdminRequired:
|
||||
return
|
||||
group_config = _config.get(str(message.chat.id), _config["*"])
|
||||
challenge = Challenge()
|
||||
|
||||
def generate_challenge_button(e):
|
||||
choices = []
|
||||
answers = []
|
||||
for c in e.choices():
|
||||
answers.append(
|
||||
InlineKeyboardButton(str(c),
|
||||
callback_data=bytes(
|
||||
str(c), encoding="utf-8")))
|
||||
choices.append(answers)
|
||||
return choices + [[
|
||||
InlineKeyboardButton(group_config["msg_approve_manually"],
|
||||
callback_data=b"+"),
|
||||
InlineKeyboardButton(group_config["msg_refuse_manually"],
|
||||
callback_data=b"-"),
|
||||
]]
|
||||
|
||||
timeout = group_config["challenge_timeout"]
|
||||
reply_message = await client.send_photo(
|
||||
message.chat.id,
|
||||
photo = challenge.pu(),
|
||||
caption = group_config["msg_challenge"].format(target=target.first_name,
|
||||
target_id=target.id,
|
||||
timeout=timeout,
|
||||
challenge=challenge.qus()),
|
||||
reply_to_message_id=message.message_id,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
generate_challenge_button(challenge)),
|
||||
)
|
||||
_me: User = await client.get_me()
|
||||
chat_id = message.chat.id
|
||||
chat_title = message.chat.title
|
||||
target = message.from_user.id
|
||||
await client.send_message(
|
||||
int(_channel), _config['msg_attempt_try'].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(target),
|
||||
groupid=str(chat_id),
|
||||
grouptitle=str(chat_title),
|
||||
))
|
||||
timeout_event = Timer(
|
||||
challenge_timeout(client, message.chat.id, message.from_user.id, message.chat.title,
|
||||
reply_message.message_id),
|
||||
timeout=group_config["challenge_timeout"],
|
||||
)
|
||||
_cch_lock.acquire()
|
||||
_current_challenges["{chat}|{msg}".format(
|
||||
chat=message.chat.id,
|
||||
msg=reply_message.message_id)] = (challenge, message.from_user.id,
|
||||
timeout_event)
|
||||
_cch_lock.release()
|
||||
|
||||
async def challenge_timeout(client: Client, chat_id, from_id, chat_title, reply_id):
|
||||
global _current_challenges
|
||||
_me: User = await client.get_me()
|
||||
group_config = _config.get(str(chat_id), _config["*"])
|
||||
|
||||
_cch_lock.acquire()
|
||||
del _current_challenges["{chat}|{msg}".format(chat=chat_id,
|
||||
msg=reply_id)]
|
||||
_cch_lock.release()
|
||||
|
||||
# TODO try catch
|
||||
await client.edit_message_caption(
|
||||
chat_id=chat_id,
|
||||
message_id=reply_id,
|
||||
caption=group_config["msg_challenge_timeout"],
|
||||
reply_markup=None,
|
||||
)
|
||||
await client.send_message(chat_id=_config["channel"],
|
||||
text=_config["msg_failed_timeout"].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(from_id),
|
||||
grouptitle=str(chat_title),
|
||||
groupid=str(chat_id)))
|
||||
if group_config["challenge_timeout_action"] == "ban":
|
||||
await client.kick_chat_member(chat_id, from_id)
|
||||
elif group_config["challenge_timeout_action"] == "kick":
|
||||
await client.kick_chat_member(chat_id, from_id)
|
||||
await client.unban_chat_member(chat_id, from_id)
|
||||
elif group_config["challenge_timeout_action"] == "mute":
|
||||
await client.restrict_chat_member(
|
||||
chat_id=chat_id,
|
||||
user_id=user_id,
|
||||
permissions=ChatPermissions(can_send_other_messages=False,
|
||||
can_send_messages=False,
|
||||
can_send_media_messages=False,
|
||||
can_add_web_page_previews=False,
|
||||
can_send_polls=False))
|
||||
else:
|
||||
pass
|
||||
|
||||
if group_config["delete_failed_challenge"]:
|
||||
Timer(
|
||||
client.delete_messages(chat_id, reply_id),
|
||||
group_config["delete_failed_challenge_interval"],
|
||||
)
|
||||
|
||||
@app.on_message(Filters.command("challenge"))
|
||||
async def challenge_user(client: Client, message: Message):
|
||||
admins = await client.get_chat_members(message.chat.id,
|
||||
filter="administrators")
|
||||
if not any([
|
||||
admin.user.id == message.from_user.id and
|
||||
(admin.status == "creator" or admin.can_restrict_members)
|
||||
for admin in admins
|
||||
]):
|
||||
target = message.from_user
|
||||
group_config = _config.get(str(message.chat.id), _config["*"])
|
||||
challenge = Challenge()
|
||||
|
||||
def generate_challenge_button(e):
|
||||
choices = []
|
||||
answers = []
|
||||
for c in e.choices():
|
||||
answers.append(
|
||||
InlineKeyboardButton(str(c),
|
||||
callback_data=bytes(
|
||||
str(c), encoding="utf-8")))
|
||||
choices.append(answers)
|
||||
return choices
|
||||
|
||||
timeout = group_config["challenge_timeout"]
|
||||
reply_message = await client.send_photo(
|
||||
message.chat.id,
|
||||
photo = challenge.pu(),
|
||||
caption = group_config["msg_challeng"].format(target=target.first_name,
|
||||
target_id=target.id,
|
||||
timeout=timeout,
|
||||
challenge=challenge.qus()),
|
||||
reply_to_message_id=message.message_id,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
generate_challenge_button(challenge)),
|
||||
)
|
||||
_me: User = await client.get_me()
|
||||
chat_id = message.chat.id
|
||||
chat_title = message.chat.title
|
||||
target = message.from_user.id
|
||||
await client.send_message(
|
||||
int(_channel), _config['msg_challenge_try'].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(target),
|
||||
groupid=str(chat_id),
|
||||
grouptitle=str(chat_title),
|
||||
))
|
||||
timeout_event = Timer(
|
||||
challeng_timeout(client, message.chat.id, message.from_user.id, message.chat.title,
|
||||
reply_message.message_id),
|
||||
timeout=group_config["challenge_timeout"],
|
||||
)
|
||||
_cch_lock.acquire()
|
||||
_current_challenges["{chat}|{msg}".format(
|
||||
chat=message.chat.id,
|
||||
msg=reply_message.message_id)] = (challenge, message.from_user.id,
|
||||
timeout_event)
|
||||
_cch_lock.release()
|
||||
|
||||
async def challeng_timeout(client: Client, chat_id, from_id, chat_title, reply_id):
|
||||
global _current_challenges
|
||||
_me: User = await client.get_me()
|
||||
group_config = _config.get(str(chat_id), _config["*"])
|
||||
|
||||
_cch_lock.acquire()
|
||||
del _current_challenges["{chat}|{msg}".format(chat=chat_id,
|
||||
msg=reply_id)]
|
||||
_cch_lock.release()
|
||||
|
||||
# TODO try catch
|
||||
await client.edit_message_caption(
|
||||
chat_id=chat_id,
|
||||
message_id=reply_id,
|
||||
caption=group_config["msg_challeng_timeout"],
|
||||
reply_markup=None,
|
||||
)
|
||||
await client.send_message(chat_id=_config["channel"],
|
||||
text=_config["msg_challenge_time"].format(
|
||||
botid=str(_me.id),
|
||||
targetuser=str(from_id),
|
||||
grouptitle=str(chat_title),
|
||||
groupid=str(chat_id)))
|
||||
|
||||
if group_config["delete_failed_challenge"]:
|
||||
Timer(
|
||||
client.delete_messages(chat_id, reply_id),
|
||||
group_config["delete_failed_challenge_interval"],
|
||||
)
|
||||
|
||||
|
||||
def _main():
|
||||
global _app, _channel, _start_message, _config
|
||||
load_config()
|
||||
_api_id = _config["api_id"]
|
||||
_api_hash = _config["api_hash"]
|
||||
_token = _config["token"]
|
||||
_channel = _config["channel"]
|
||||
_start_message = _config["msg_start_message"]
|
||||
_proxy_ip = _config["proxy_addr"].strip()
|
||||
_proxy_port = _config["proxy_port"].strip()
|
||||
if _proxy_ip and _proxy_port:
|
||||
_app = Client("bot",
|
||||
bot_token=_token,
|
||||
api_id=_api_id,
|
||||
api_hash=_api_hash,
|
||||
proxy=dict(hostname=_proxy_ip, port=int(_proxy_port)))
|
||||
else:
|
||||
_app = Client("bot",
|
||||
bot_token=_token,
|
||||
api_id=_api_id,
|
||||
api_hash=_api_hash)
|
||||
try:
|
||||
_update(_app)
|
||||
_app.run()
|
||||
except KeyboardInterrupt:
|
||||
quit()
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
_main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
BIN
pic/10.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
pic/11.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
pic/12.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
pic/13.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
pic/14.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
pic/15.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
pic/16.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
pic/17.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
pic/18.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
pic/19.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
pic/20.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
pic/21.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
pic/22.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
pic/23.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
pic/24.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
pic/25.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
pic/26.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
pic/27.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
pic/28.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
pic/29.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
pic/30.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
pic/31.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
pic/32.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
pic/33.png
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
pic/34.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
pic/35.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
pic/36.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
pic/37.png
Normal file
After Width: | Height: | Size: 133 KiB |
BIN
pic/38.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
pic/39.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
pic/40.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
pic/41.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
pic/42.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
pic/43.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
pic/44.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
pic/45.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
pic/46.png
Normal file
After Width: | Height: | Size: 176 KiB |
BIN
pic/47.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
pic/48.png
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
pic/49.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
pic/50.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
pic/51.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
pic/52.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
pic/53.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
pic/54.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
pic/55.png
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
pic/56.png
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
pic/57.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
pic/58.png
Normal file
After Width: | Height: | Size: 166 KiB |
BIN
pic/59.png
Normal file
After Width: | Height: | Size: 175 KiB |
BIN
pic/60.png
Normal file
After Width: | Height: | Size: 255 KiB |
BIN
pic/61.png
Normal file
After Width: | Height: | Size: 139 KiB |
BIN
pic/62.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
pic/63.png
Normal file
After Width: | Height: | Size: 173 KiB |
BIN
pic/64.png
Normal file
After Width: | Height: | Size: 392 KiB |
BIN
pic/65.png
Normal file
After Width: | Height: | Size: 186 KiB |
BIN
pic/66.png
Normal file
After Width: | Height: | Size: 255 KiB |
BIN
pic/67.png
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
pic/68.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
pic/69.png
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
pic/70.png
Normal file
After Width: | Height: | Size: 142 KiB |
BIN
pic/71.png
Normal file
After Width: | Height: | Size: 154 KiB |
BIN
pic/72.png
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
pic/73.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
pic/74.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
pic/75.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
pic/76.png
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
pic/77.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
pic/78.png
Normal file
After Width: | Height: | Size: 121 KiB |
BIN
pic/79.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
pic/80.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
pic/81.png
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
pic/82.png
Normal file
After Width: | Height: | Size: 146 KiB |
BIN
pic/83.png
Normal file
After Width: | Height: | Size: 97 KiB |
BIN
pic/84.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
pic/85.png
Normal file
After Width: | Height: | Size: 213 KiB |
BIN
pic/86.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
pic/87.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
pic/88.png
Normal file
After Width: | Height: | Size: 154 KiB |
BIN
pic/89.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
pic/90.png
Normal file
After Width: | Height: | Size: 131 KiB |
7
tk.json
Normal file
@ -0,0 +1,7 @@
|
||||
[ans]
|
||||
a = 3 6 10 12 13 15 19 27 32 39 48 50 51 57 61 68 75 76 78 82 84 87
|
||||
b = 2 4 7 11 17 20 21 23 26 34 36 38 41 45 46 49 52 55 62 66 70 71 74 81 83 90
|
||||
c = 1 9 14 16 22 28 30 35 37 42 43 44 53 56 59 65 67 72 79 89
|
||||
d = 5 8 18 24 25 29 31 33 40 47 54 58 60 63 64 69 73 77 80 85 86 88
|
||||
all = 90
|
||||
|