- 加入执行/cmd指令 开发部分shell命令使用
- 去掉响应所有文本消息的监听
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
# @Author : iouAkira(lof)
|
# @Author : iouAkira(lof)
|
||||||
# @mail : e.akimoto.akira@gmail.com
|
# @mail : e.akimoto.akira@gmail.com
|
||||||
# @CreateTime: 2020-11-02
|
# @CreateTime: 2020-11-02
|
||||||
# @UpdateTime: 2021-03-21
|
# @UpdateTime: 2021-03-23
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
@@ -40,10 +40,10 @@ def start(update, context):
|
|||||||
if admin_id == str(from_user_id):
|
if admin_id == str(from_user_id):
|
||||||
spnode_readme = ""
|
spnode_readme = ""
|
||||||
if "DISABLE_SPNODE" not in os.environ:
|
if "DISABLE_SPNODE" not in os.environ:
|
||||||
spnode_readme = "/spnode 获取可执行脚本的列表,选择对应的按钮执行。(拓展使用:运行指定路径脚本,例:/spnode /scripts/jd_818.js)\n" \
|
spnode_readme = "/spnode 获取可执行脚本的列表,选择对应的按钮执行。(拓展使用:运行指定路径脚本,例:/spnode /scripts/jd_818.js)\n\n" \
|
||||||
"使用bot交互+spnode后 后续用户的cookie维护更新只需要更新logs/cookies.list即可\n" \
|
"使用bot交互+spnode后 后续用户的cookie维护更新只需要更新logs/cookies.list即可\n" \
|
||||||
"使用bot交互+spnode后 后续执行脚本命令请使用spnode否者无法使用logs/cookies.list的cookies执行脚本,定时任务也将自动替换为spnode命令执行\n" \
|
"使用bot交互+spnode后 后续执行脚本命令请使用spnode否者无法使用logs/cookies.list的cookies执行脚本,定时任务也将自动替换为spnode命令执行\n" \
|
||||||
"spnode功能概述示例\n" \
|
"spnode功能概述示例\n\n" \
|
||||||
"spnode conc /scripts/jd_bean_change.js 为每个cookie单独执行jd_bean_change脚本(伪并发\n" \
|
"spnode conc /scripts/jd_bean_change.js 为每个cookie单独执行jd_bean_change脚本(伪并发\n" \
|
||||||
"spnode 1 /scripts/jd_bean_change.js 为logs/cookies.list文件里面第一行cookie账户单独执行jd_bean_change脚本\n" \
|
"spnode 1 /scripts/jd_bean_change.js 为logs/cookies.list文件里面第一行cookie账户单独执行jd_bean_change脚本\n" \
|
||||||
"spnode jd_XXXX /scripts/jd_bean_change.js 为logs/cookies.list文件里面pt_pin=jd_XXXX的cookie账户单独执行jd_bean_change脚本\n" \
|
"spnode jd_XXXX /scripts/jd_bean_change.js 为logs/cookies.list文件里面pt_pin=jd_XXXX的cookie账户单独执行jd_bean_change脚本\n" \
|
||||||
@@ -58,7 +58,7 @@ def start(update, context):
|
|||||||
"/git 获取可执行git指令列表,选择对应的按钮执行。(拓展使用:运行指定路径脚本,例:/git -C /scripts/ pull)\n" \
|
"/git 获取可执行git指令列表,选择对应的按钮执行。(拓展使用:运行指定路径脚本,例:/git -C /scripts/ pull)\n" \
|
||||||
"/logs 获取logs下的日志文件列表,选择对应名字可以下载日志文件\n" \
|
"/logs 获取logs下的日志文件列表,选择对应名字可以下载日志文件\n" \
|
||||||
"/env 获取系统环境变量列表。(拓展使用:设置系统环境变量,例:/env export JD_DEBUG=true,环境变量只针对当前bot进程生效) \n" \
|
"/env 获取系统环境变量列表。(拓展使用:设置系统环境变量,例:/env export JD_DEBUG=true,环境变量只针对当前bot进程生效) \n" \
|
||||||
"/bash 执行执行命令。参考:/bash ls -l 未完善不开放使用\n" \
|
"/cmd 执行执行命令。参考:/cmd ls -l 涉及目录文件操作请使用绝对路径,部分shell命令开放使用\n" \
|
||||||
"/gen_long_code 长期活动互助码提交消息生成\n" \
|
"/gen_long_code 长期活动互助码提交消息生成\n" \
|
||||||
"/gen_temp_code 短期临时活动互助码提交消息生成\n" \
|
"/gen_temp_code 短期临时活动互助码提交消息生成\n" \
|
||||||
"/gen_daily_code 每天变化互助码活动提交消息生成\n\n%s" % spnode_readme)
|
"/gen_daily_code 每天变化互助码活动提交消息生成\n\n%s" % spnode_readme)
|
||||||
@@ -81,7 +81,7 @@ def node(update, context):
|
|||||||
|
|
||||||
out_text = out_bytes.decode('utf-8')
|
out_text = out_bytes.decode('utf-8')
|
||||||
|
|
||||||
if len(out_text.split()) > 30:
|
if len(out_text.split()) > 50:
|
||||||
|
|
||||||
msg = context.bot.sendMessage(text='```{}```'.format(
|
msg = context.bot.sendMessage(text='```{}```'.format(
|
||||||
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)), chat_id=update.effective_chat.id,
|
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)), chat_id=update.effective_chat.id,
|
||||||
@@ -135,7 +135,7 @@ def spnode(update, context):
|
|||||||
|
|
||||||
out_text = out_bytes.decode('utf-8')
|
out_text = out_bytes.decode('utf-8')
|
||||||
|
|
||||||
if len(out_text.split()) > 30:
|
if len(out_text.split()) > 50:
|
||||||
|
|
||||||
msg = context.bot.sendMessage(text='```{}```'.format(
|
msg = context.bot.sendMessage(text='```{}```'.format(
|
||||||
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)), chat_id=update.effective_chat.id,
|
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)), chat_id=update.effective_chat.id,
|
||||||
@@ -189,7 +189,7 @@ def git(update, context):
|
|||||||
|
|
||||||
out_text = out_bytes.decode('utf-8')
|
out_text = out_bytes.decode('utf-8')
|
||||||
|
|
||||||
if len(out_text.split()) > 30:
|
if len(out_text.split()) > 50:
|
||||||
|
|
||||||
msg = context.bot.sendMessage(text='```{}```'.format(
|
msg = context.bot.sendMessage(text='```{}```'.format(
|
||||||
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)), chat_id=update.effective_chat.id,
|
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)), chat_id=update.effective_chat.id,
|
||||||
@@ -257,7 +257,7 @@ def env(update, context):
|
|||||||
|
|
||||||
out_text = out_bytes.decode('utf-8')
|
out_text = out_bytes.decode('utf-8')
|
||||||
|
|
||||||
if len(out_text.split()) > 30:
|
if len(out_text.split()) > 50:
|
||||||
|
|
||||||
msg = context.bot.sendMessage(text='```{}```'.format(
|
msg = context.bot.sendMessage(text='```{}```'.format(
|
||||||
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % 'env')), chat_id=update.effective_chat.id,
|
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % 'env')), chat_id=update.effective_chat.id,
|
||||||
@@ -327,7 +327,7 @@ def callback_run(update, context):
|
|||||||
out_bytes = subprocess.check_output(
|
out_bytes = subprocess.check_output(
|
||||||
query.data, shell=True, timeout=600, stderr=subprocess.STDOUT)
|
query.data, shell=True, timeout=600, stderr=subprocess.STDOUT)
|
||||||
out_text = out_bytes.decode('utf-8')
|
out_text = out_bytes.decode('utf-8')
|
||||||
if len(out_text.split()) > 30:
|
if len(out_text.split()) > 50:
|
||||||
context.bot.edit_message_text(text='```{}```'.format(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % query.data),
|
context.bot.edit_message_text(text='```{}```'.format(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % query.data),
|
||||||
chat_id=query.message.chat_id,
|
chat_id=query.message.chat_id,
|
||||||
message_id=query.message.message_id, parse_mode=ParseMode.MARKDOWN_V2)
|
message_id=query.message.message_id, parse_mode=ParseMode.MARKDOWN_V2)
|
||||||
@@ -378,7 +378,7 @@ def callback_run(update, context):
|
|||||||
out_bytes = subprocess.check_output(cmd, shell=True, timeout=600,
|
out_bytes = subprocess.check_output(cmd, shell=True, timeout=600,
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
out_text = out_bytes.decode('utf-8')
|
out_text = out_bytes.decode('utf-8')
|
||||||
if len(out_text.split()) > 30:
|
if len(out_text.split()) > 50:
|
||||||
|
|
||||||
context.bot.edit_message_text(text='```{}```'.format(
|
context.bot.edit_message_text(text='```{}```'.format(
|
||||||
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)),
|
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)),
|
||||||
@@ -551,10 +551,10 @@ def get_crontab_list(cmd_type):
|
|||||||
items = i.split('>>')
|
items = i.split('>>')
|
||||||
item_sub = items[0].split()[5:]
|
item_sub = items[0].split()[5:]
|
||||||
# logger.info(item_sub[0])
|
# logger.info(item_sub[0])
|
||||||
if cmd_type.find(item_sub[0])>-1:
|
if cmd_type.find(item_sub[0]) > -1:
|
||||||
if cmd_type == 'spnode':
|
if cmd_type == 'spnode':
|
||||||
#logger.info(str(' '.join(item_sub)).replace('node','spnode'))
|
# logger.info(str(' '.join(item_sub)).replace('node','spnode'))
|
||||||
button_list.append(str(' '.join(item_sub)).replace('node','spnode'))
|
button_list.append(str(' '.join(item_sub)).replace('node', 'spnode'))
|
||||||
else:
|
else:
|
||||||
button_list.append(' '.join(item_sub))
|
button_list.append(' '.join(item_sub))
|
||||||
elif cmd_type == 'crontab_l':
|
elif cmd_type == 'crontab_l':
|
||||||
@@ -710,6 +710,61 @@ def gen_daily_code(update, context):
|
|||||||
text="获取互助码消息生成配置文件失败,请检查%s文件是否存在" % _share_code_conf)
|
text="获取互助码消息生成配置文件失败,请检查%s文件是否存在" % _share_code_conf)
|
||||||
|
|
||||||
|
|
||||||
|
def shcmd(update, context):
|
||||||
|
"""
|
||||||
|
执行终端命令,超时时间为60,执行耗时或者不退出的指令会报超时异常
|
||||||
|
:param update:
|
||||||
|
:param context:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if is_admin(update.message.from_user.id):
|
||||||
|
commands = update.message.text.split()
|
||||||
|
commands.remove('/cmd')
|
||||||
|
if len(commands) > 1:
|
||||||
|
support_cmd = ["ls", "cp", "mv", "wget", "cat", "sed", "git", "sh", "docker_entrypoint.sh"]
|
||||||
|
if commands[1] in support_cmd:
|
||||||
|
cmd = ' '.join(commands)
|
||||||
|
try:
|
||||||
|
out_bytes = subprocess.check_output(
|
||||||
|
cmd, shell=True, timeout=60, stderr=subprocess.STDOUT)
|
||||||
|
out_text = out_bytes.decode('utf-8')
|
||||||
|
if len(out_text.split()) > 50:
|
||||||
|
msg = context.bot.sendMessage(text='```{}```'.format(
|
||||||
|
helpers.escape_markdown(' ↓↓↓ %s 执行结果超长,请查看log ↓↓↓' % cmd)),
|
||||||
|
chat_id=update.effective_chat.id,
|
||||||
|
parse_mode=ParseMode.MARKDOWN_V2)
|
||||||
|
log_name = '%sbot_%s_%s.log' % (
|
||||||
|
_logs_dir, 'git', os.path.splitext(commands[-1])[0])
|
||||||
|
with open(log_name, 'a+') as wf:
|
||||||
|
wf.write(out_text)
|
||||||
|
msg.reply_document(
|
||||||
|
reply_to_message_id=msg.message_id, quote=True, document=open(log_name, 'rb'))
|
||||||
|
else:
|
||||||
|
context.bot.sendMessage(text='```{}```'.format(
|
||||||
|
helpers.escape_markdown(' ↓↓↓ %s 执行结果 ↓↓↓ \n\n%s ' % (cmd, out_text))),
|
||||||
|
chat_id=update.effective_chat.id, parse_mode=ParseMode.MARKDOWN_V2)
|
||||||
|
|
||||||
|
except TimeoutExpired:
|
||||||
|
context.bot.sendMessage(text='```{}```'.format(helpers.escape_markdown(' →→→ %s 执行超时 ←←← ' % (
|
||||||
|
cmd))), chat_id=update.effective_chat.id, parse_mode=ParseMode.MARKDOWN_V2)
|
||||||
|
except Exception as e:
|
||||||
|
context.bot.sendMessage(
|
||||||
|
text='```{}```'.format(helpers.escape_markdown(' →→→ %s 执行出错,请检查确认命令是否正确 ←←← ' % (
|
||||||
|
cmd))), chat_id=update.effective_chat.id, parse_mode=ParseMode.MARKDOWN_V2)
|
||||||
|
logger.error(e)
|
||||||
|
else:
|
||||||
|
update.message.reply_text(
|
||||||
|
text='```{}```'.format(
|
||||||
|
helpers.escape_markdown(f' →→→ {commands[1]}指令不在支持命令范围,请输入其他支持的指令{"|".join(commands)} ←←← ')),
|
||||||
|
parse_mode=ParseMode.MARKDOWN_V2)
|
||||||
|
else:
|
||||||
|
update.message.reply_text(
|
||||||
|
text='```{}```'.format(helpers.escape_markdown(' →→→ 请在/cmd 后写自己需要执行的指的命令 ←←← ')),
|
||||||
|
parse_mode=ParseMode.MARKDOWN_V2)
|
||||||
|
else:
|
||||||
|
update.message.reply_text(text='此为私人使用bot,不能执行您的指令!')
|
||||||
|
|
||||||
|
|
||||||
# getSToken请求获取,s_token用于发送post请求是的必须参数
|
# getSToken请求获取,s_token用于发送post请求是的必须参数
|
||||||
s_token = ""
|
s_token = ""
|
||||||
# getSToken请求获取,guid,lsid,lstoken用于组装cookies
|
# getSToken请求获取,guid,lsid,lstoken用于组装cookies
|
||||||
@@ -885,40 +940,6 @@ def parseJDCookies(headers):
|
|||||||
jd_cookie = f'pt_key={pt_key};pt_pin={pt_pin};'
|
jd_cookie = f'pt_key={pt_key};pt_pin={pt_pin};'
|
||||||
|
|
||||||
|
|
||||||
def resp_text(update, context):
|
|
||||||
"""
|
|
||||||
监听用户输入的文本消息
|
|
||||||
"""
|
|
||||||
from_user_id = update.message.from_user.id
|
|
||||||
if admin_id == str(from_user_id):
|
|
||||||
msg_text = update.message.text
|
|
||||||
logger.info(msg_text)
|
|
||||||
if str(update.message.text).find("api.m.jd.com/client.action?functionId=liveDrawLotteryV842") > 0:
|
|
||||||
url = re.findall(r"已登陆京东):(.+?)?$", msg_text)[0]
|
|
||||||
body = re.findall(r"&body=(.+?)&", msg_text)[0]
|
|
||||||
url = url.replace(body, quote(body))
|
|
||||||
logger.info(url)
|
|
||||||
try:
|
|
||||||
os.putenv('LIVE_LOTTTERY_URL', url)
|
|
||||||
cmd = f'node {_base_dir}jd_live_lottery.js'
|
|
||||||
out_bytes = subprocess.check_output(
|
|
||||||
cmd, shell=True, timeout=600, stderr=subprocess.STDOUT)
|
|
||||||
out_text = out_bytes.decode('utf-8')
|
|
||||||
context.bot.sendMessage(text='```{}```'.format(
|
|
||||||
helpers.escape_markdown(' ↓↓↓ %s 执行结果 ↓↓↓ \n\n%s ' % (cmd, out_text))),
|
|
||||||
chat_id=update.effective_chat.id, parse_mode=ParseMode.MARKDOWN_V2)
|
|
||||||
except TimeoutExpired:
|
|
||||||
context.bot.sendMessage(text='```{}```'.format(helpers.escape_markdown(' →→→ %s 执行超时 ←←← ' % (cmd))),
|
|
||||||
chat_id=update.effective_chat.id, parse_mode=ParseMode.MARKDOWN_V2)
|
|
||||||
except Exception as e:
|
|
||||||
context.bot.sendMessage(
|
|
||||||
text='```{}```'.format(helpers.escape_markdown(' →→→ %s 执行出错,请检查确认命令是否正确 ←←← ' % (
|
|
||||||
cmd))), chat_id=update.effective_chat.id, parse_mode=ParseMode.MARKDOWN_V2)
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
update.message.reply_text(text='此为私人使用bot,不能执行您的指令!')
|
|
||||||
|
|
||||||
|
|
||||||
def unknown(update, context):
|
def unknown(update, context):
|
||||||
"""回复用户输入不存在的指令
|
"""回复用户输入不存在的指令
|
||||||
"""
|
"""
|
||||||
@@ -926,10 +947,10 @@ def unknown(update, context):
|
|||||||
if admin_id == str(from_user_id):
|
if admin_id == str(from_user_id):
|
||||||
spnode_readme = ""
|
spnode_readme = ""
|
||||||
if "DISABLE_SPNODE" not in os.environ:
|
if "DISABLE_SPNODE" not in os.environ:
|
||||||
spnode_readme = "/spnode 获取可执行脚本的列表,选择对应的按钮执行。(拓展使用:运行指定路径脚本,例:/spnode /scripts/jd_818.js)\n" \
|
spnode_readme = "/spnode 获取可执行脚本的列表,选择对应的按钮执行。(拓展使用:运行指定路径脚本,例:/spnode /scripts/jd_818.js)\n\n" \
|
||||||
"使用bot交互+spnode后 后续用户的cookie维护更新只需要更新logs/cookies.list即可\n" \
|
"使用bot交互+spnode后 后续用户的cookie维护更新只需要更新logs/cookies.list即可\n" \
|
||||||
"使用bot交互+spnode后 后续执行脚本命令请使用spnode否者无法使用logs/cookies.list的cookies执行脚本,定时任务也将自动替换为spnode命令执行\n" \
|
"使用bot交互+spnode后 后续执行脚本命令请使用spnode否者无法使用logs/cookies.list的cookies执行脚本,定时任务也将自动替换为spnode命令执行\n" \
|
||||||
"spnode功能概述示例\n" \
|
"spnode功能概述示例\n\n" \
|
||||||
"spnode conc /scripts/jd_bean_change.js 为每个cookie单独执行jd_bean_change脚本(伪并发\n" \
|
"spnode conc /scripts/jd_bean_change.js 为每个cookie单独执行jd_bean_change脚本(伪并发\n" \
|
||||||
"spnode 1 /scripts/jd_bean_change.js 为logs/cookies.list文件里面第一行cookie账户单独执行jd_bean_change脚本\n" \
|
"spnode 1 /scripts/jd_bean_change.js 为logs/cookies.list文件里面第一行cookie账户单独执行jd_bean_change脚本\n" \
|
||||||
"spnode jd_XXXX /scripts/jd_bean_change.js 为logs/cookies.list文件里面pt_pin=jd_XXXX的cookie账户单独执行jd_bean_change脚本\n" \
|
"spnode jd_XXXX /scripts/jd_bean_change.js 为logs/cookies.list文件里面pt_pin=jd_XXXX的cookie账户单独执行jd_bean_change脚本\n" \
|
||||||
@@ -943,7 +964,7 @@ def unknown(update, context):
|
|||||||
"/git 获取可执行git指令列表,选择对应的按钮执行。(拓展使用:运行指定路径脚本,例:/git -C /scripts/ pull)\n" \
|
"/git 获取可执行git指令列表,选择对应的按钮执行。(拓展使用:运行指定路径脚本,例:/git -C /scripts/ pull)\n" \
|
||||||
"/logs 获取logs下的日志文件列表,选择对应名字可以下载日志文件\n" \
|
"/logs 获取logs下的日志文件列表,选择对应名字可以下载日志文件\n" \
|
||||||
"/env 获取系统环境变量列表。(拓展使用:设置系统环境变量,例:/env export JD_DEBUG=true,环境变量只针对当前bot进程生效) \n" \
|
"/env 获取系统环境变量列表。(拓展使用:设置系统环境变量,例:/env export JD_DEBUG=true,环境变量只针对当前bot进程生效) \n" \
|
||||||
"/bash 执行执行命令。参考:/bash ls -l 未完善不开放使用\n" \
|
"/cmd 执行执行命令。参考:/cmd ls -l 涉及目录文件操作请使用绝对路径,部分shell命令开放使用\n" \
|
||||||
"/gen_long_code 长期活动互助码提交消息生成\n" \
|
"/gen_long_code 长期活动互助码提交消息生成\n" \
|
||||||
"/gen_temp_code 短期临时活动互助码提交消息生成\n" \
|
"/gen_temp_code 短期临时活动互助码提交消息生成\n" \
|
||||||
"/gen_daily_code 每天变化互助码活动提交消息生成\n\n%s" % spnode_readme,
|
"/gen_daily_code 每天变化互助码活动提交消息生成\n\n%s" % spnode_readme,
|
||||||
@@ -996,12 +1017,15 @@ def main():
|
|||||||
# 通过 git 函数 响应 '/git' 命令
|
# 通过 git 函数 响应 '/git' 命令
|
||||||
dp.add_handler(CommandHandler('git', git))
|
dp.add_handler(CommandHandler('git', git))
|
||||||
|
|
||||||
# 通过 logs 函数 响应 '/logs' 命令
|
# 通过 crontab 函数 响应 '/crontab' 命令
|
||||||
dp.add_handler(CommandHandler('crontab', crontab))
|
dp.add_handler(CommandHandler('crontab', crontab))
|
||||||
|
|
||||||
# 通过 logs 函数 响应 '/logs' 命令
|
# 通过 logs 函数 响应 '/logs' 命令
|
||||||
dp.add_handler(CommandHandler('logs', logs))
|
dp.add_handler(CommandHandler('logs', logs))
|
||||||
|
|
||||||
|
# 通过 cmd 函数 响应 '/cmd' 命令
|
||||||
|
dp.add_handler(CommandHandler('cmd', shcmd))
|
||||||
|
|
||||||
# 通过 callback_run 函数 响应相关按钮命令
|
# 通过 callback_run 函数 响应相关按钮命令
|
||||||
dp.add_handler(CallbackQueryHandler(callback_run))
|
dp.add_handler(CallbackQueryHandler(callback_run))
|
||||||
|
|
||||||
@@ -1024,7 +1048,7 @@ def main():
|
|||||||
dp.add_handler(MessageHandler(Filters.command, unknown))
|
dp.add_handler(MessageHandler(Filters.command, unknown))
|
||||||
|
|
||||||
# 响应普通文本消息
|
# 响应普通文本消息
|
||||||
dp.add_handler(MessageHandler(Filters.text, resp_text))
|
# dp.add_handler(MessageHandler(Filters.text, resp_text))
|
||||||
|
|
||||||
dp.add_error_handler(error)
|
dp.add_error_handler(error)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user