mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 11:18:54 -05:00
Report fixes + improvements (#1541)
* WIP * fix perms issue * better * more work * working * working, tessted * docs * mutable default fix
This commit is contained in:
parent
fca7686701
commit
7cd98c8a63
@ -2,7 +2,8 @@ import logging
|
|||||||
import asyncio
|
import asyncio
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from copy import copy
|
||||||
|
import contextlib
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
|
||||||
@ -109,9 +110,10 @@ class Reports:
|
|||||||
ret |= await self.bot.is_owner(m)
|
ret |= await self.bot.is_owner(m)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
async def discover_guild(self, author: discord.User, *,
|
async def discover_guild(
|
||||||
|
self, author: discord.User, *,
|
||||||
mod: bool=False,
|
mod: bool=False,
|
||||||
permissions: Union[discord.Permissions, dict]={},
|
permissions: Union[discord.Permissions, dict]=None,
|
||||||
prompt: str=""):
|
prompt: str=""):
|
||||||
"""
|
"""
|
||||||
discovers which of shared guilds between the bot
|
discovers which of shared guilds between the bot
|
||||||
@ -120,10 +122,12 @@ class Reports:
|
|||||||
prompt is for providing a user prompt for selection
|
prompt is for providing a user prompt for selection
|
||||||
"""
|
"""
|
||||||
shared_guilds = []
|
shared_guilds = []
|
||||||
if isinstance(permissions, discord.Permissions):
|
if permissions is None:
|
||||||
|
perms = discord.Permissions()
|
||||||
|
elif isinstance(permissions, discord.Permissions):
|
||||||
perms = permissions
|
perms = permissions
|
||||||
else:
|
else:
|
||||||
permissions = discord.Permissions(**perms)
|
perms = discord.Permissions(**permissions)
|
||||||
|
|
||||||
for guild in self.bot.guilds:
|
for guild in self.bot.guilds:
|
||||||
x = guild.get_member(author.id)
|
x = guild.get_member(author.id)
|
||||||
@ -170,26 +174,40 @@ class Reports:
|
|||||||
|
|
||||||
author = guild.get_member(msg.author.id)
|
author = guild.get_member(msg.author.id)
|
||||||
report = msg.clean_content
|
report = msg.clean_content
|
||||||
avatar = author.avatar_url
|
|
||||||
|
|
||||||
em = discord.Embed(description=report)
|
|
||||||
em.set_author(
|
|
||||||
name=_('Report from {0.display_name}').format(author),
|
|
||||||
icon_url=avatar
|
|
||||||
)
|
|
||||||
|
|
||||||
ticket_number = await self.config.guild(guild).next_ticket()
|
|
||||||
await self.config.guild(guild).next_ticket.set(ticket_number + 1)
|
|
||||||
em.set_footer(text=_("Report #{}").format(ticket_number))
|
|
||||||
|
|
||||||
channel_id = await self.config.guild(guild).output_channel()
|
channel_id = await self.config.guild(guild).output_channel()
|
||||||
channel = guild.get_channel(channel_id)
|
channel = guild.get_channel(channel_id)
|
||||||
if channel is not None:
|
if channel is None:
|
||||||
try:
|
|
||||||
await channel.send(embed=em)
|
|
||||||
except (discord.Forbidden, discord.HTTPException):
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
files = await Tunnel.files_from_attatch(msg)
|
||||||
|
|
||||||
|
ticket_number = await self.config.guild(guild).next_ticket()
|
||||||
|
await self.config.guild(guild).next_ticket.set(ticket_number + 1)
|
||||||
|
|
||||||
|
if await self.bot.embed_requested(channel, author):
|
||||||
|
em = discord.Embed(description=report)
|
||||||
|
em.set_author(
|
||||||
|
name=_('Report from {0.display_name}').format(author),
|
||||||
|
icon_url=author.avatar_url
|
||||||
|
)
|
||||||
|
em.set_footer(text=_("Report #{}").format(ticket_number))
|
||||||
|
send_content = None
|
||||||
else:
|
else:
|
||||||
|
em = None
|
||||||
|
send_content = _(
|
||||||
|
'Report from {author.mention} (Ticket #{number})'
|
||||||
|
).format(author=author, number=ticket_number)
|
||||||
|
send_content += "\n" + report
|
||||||
|
|
||||||
|
try:
|
||||||
|
await Tunnel.message_forwarder(
|
||||||
|
destination=channel,
|
||||||
|
content=send_content,
|
||||||
|
embed=em,
|
||||||
|
files=files
|
||||||
|
)
|
||||||
|
except (discord.Forbidden, discord.HTTPException):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
await self.config.custom('REPORT', guild.id, ticket_number).report.set(
|
await self.config.custom('REPORT', guild.id, ticket_number).report.set(
|
||||||
@ -198,8 +216,13 @@ class Reports:
|
|||||||
return ticket_number
|
return ticket_number
|
||||||
|
|
||||||
@commands.group(name="report", invoke_without_command=True)
|
@commands.group(name="report", invoke_without_command=True)
|
||||||
async def report(self, ctx: RedContext):
|
async def report(self, ctx: RedContext, *, _report: str=""):
|
||||||
"Follow the prompts to make a report"
|
"""
|
||||||
|
Follow the prompts to make a report
|
||||||
|
|
||||||
|
optionally use with a report message
|
||||||
|
to use it non interactively
|
||||||
|
"""
|
||||||
author = ctx.author
|
author = ctx.author
|
||||||
guild = ctx.guild
|
guild = ctx.guild
|
||||||
if guild is None:
|
if guild is None:
|
||||||
@ -243,6 +266,12 @@ class Reports:
|
|||||||
pass
|
pass
|
||||||
self.user_cache.append(author.id)
|
self.user_cache.append(author.id)
|
||||||
|
|
||||||
|
if _report:
|
||||||
|
_m = copy(ctx.message)
|
||||||
|
_m.content = _report
|
||||||
|
_m.content = _m.clean_content
|
||||||
|
val = await self.send_report(_m, guild)
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
dm = await author.send(
|
dm = await author.send(
|
||||||
_("Please respond to this message with your Report."
|
_("Please respond to this message with your Report."
|
||||||
@ -268,6 +297,8 @@ class Reports:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
val = await self.send_report(message, guild)
|
val = await self.send_report(message, guild)
|
||||||
|
|
||||||
|
with contextlib.suppress(discord.Forbidden, discord.HTTPException):
|
||||||
if val is None:
|
if val is None:
|
||||||
await author.send(
|
await author.send(
|
||||||
_("There was an error sending your report.")
|
_("There was an error sending your report.")
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from redbot.core.utils.chat_formatting import pagify
|
|||||||
import io
|
import io
|
||||||
import sys
|
import sys
|
||||||
import weakref
|
import weakref
|
||||||
|
from typing import List
|
||||||
|
|
||||||
_instances = weakref.WeakValueDictionary({})
|
_instances = weakref.WeakValueDictionary({})
|
||||||
|
|
||||||
@ -94,6 +95,88 @@ class Tunnel(metaclass=TunnelMeta):
|
|||||||
def minutes_since(self):
|
def minutes_since(self):
|
||||||
return int((self.last_interaction - datetime.utcnow()).seconds / 60)
|
return int((self.last_interaction - datetime.utcnow()).seconds / 60)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def message_forwarder(
|
||||||
|
*, destination: discord.abc.Messageable,
|
||||||
|
content: str=None, embed=None, files=[]) -> List[discord.Message]:
|
||||||
|
"""
|
||||||
|
This does the actual sending, use this instead of a full tunnel
|
||||||
|
if you are using command initiated reactions instead of persistent
|
||||||
|
event based ones
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
destination: `discord.abc.Messageable`
|
||||||
|
Where to send
|
||||||
|
content: `str`
|
||||||
|
The message content
|
||||||
|
embed: `discord.Embed`
|
||||||
|
The embed to send
|
||||||
|
files: `List[discord.Files]`
|
||||||
|
A list of files to send.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
list of `discord.Message`
|
||||||
|
The `discord.Message`(s) sent as a result
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
discord.Forbidden
|
||||||
|
see `discord.abc.Messageable.send`
|
||||||
|
discord.HTTPException
|
||||||
|
see `discord.abc.Messageable.send`
|
||||||
|
"""
|
||||||
|
rets = []
|
||||||
|
files = files if files else None
|
||||||
|
if content:
|
||||||
|
for page in pagify(content):
|
||||||
|
rets.append(
|
||||||
|
await destination.send(
|
||||||
|
page, files=files, embed=embed)
|
||||||
|
)
|
||||||
|
if files:
|
||||||
|
del files
|
||||||
|
if embed:
|
||||||
|
del embed
|
||||||
|
elif embed or files:
|
||||||
|
rets.append(
|
||||||
|
await destination.send(files=files, embed=embed)
|
||||||
|
)
|
||||||
|
return rets
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def files_from_attatch(m: discord.Message) -> List[discord.File]:
|
||||||
|
"""
|
||||||
|
makes a list of file objects from a message
|
||||||
|
returns an empty list if none, or if the sum of file sizes
|
||||||
|
is too large for the bot to send
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
---------
|
||||||
|
m: `discord.Message`
|
||||||
|
A message to get attachments from
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
list of `discord.File`
|
||||||
|
A list of `discord.File` objects
|
||||||
|
|
||||||
|
"""
|
||||||
|
files = []
|
||||||
|
size = 0
|
||||||
|
max_size = 8 * 1024 * 1024
|
||||||
|
for a in m.attachments:
|
||||||
|
_fp = io.BytesIO()
|
||||||
|
await a.save(_fp)
|
||||||
|
size += sys.getsizeof(_fp)
|
||||||
|
if size > max_size:
|
||||||
|
return []
|
||||||
|
files.append(
|
||||||
|
discord.File(_fp, filename=a.filename)
|
||||||
|
)
|
||||||
|
return files
|
||||||
|
|
||||||
async def communicate(self, *,
|
async def communicate(self, *,
|
||||||
message: discord.Message,
|
message: discord.Message,
|
||||||
topic: str=None,
|
topic: str=None,
|
||||||
@ -140,35 +223,22 @@ class Tunnel(metaclass=TunnelMeta):
|
|||||||
else:
|
else:
|
||||||
content = topic
|
content = topic
|
||||||
|
|
||||||
attach = None
|
|
||||||
if message.attachments:
|
if message.attachments:
|
||||||
files = []
|
attach = await self.files_from_attatch(message)
|
||||||
size = 0
|
if not attach:
|
||||||
max_size = 8 * 1024 * 1024
|
await message.channel.send(
|
||||||
for a in message.attachments:
|
|
||||||
_fp = io.BytesIO()
|
|
||||||
await a.save(_fp)
|
|
||||||
size += sys.getsizeof(_fp)
|
|
||||||
if size > max_size:
|
|
||||||
await send_to.send(
|
|
||||||
"Could not forward attatchments. "
|
"Could not forward attatchments. "
|
||||||
"Total size of attachments in a single "
|
"Total size of attachments in a single "
|
||||||
"message must be less than 8MB."
|
"message must be less than 8MB."
|
||||||
)
|
)
|
||||||
break
|
|
||||||
files.append(
|
|
||||||
discord.File(_fp, filename=a.filename)
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
attach = files
|
attach = []
|
||||||
|
|
||||||
rets = []
|
rets = await self.message_forwarder(
|
||||||
for page in pagify(content):
|
destination=send_to,
|
||||||
rets.append(
|
content=content,
|
||||||
await send_to.send(content, files=attach)
|
files=attach
|
||||||
)
|
)
|
||||||
if attach:
|
|
||||||
del attach
|
|
||||||
|
|
||||||
await message.add_reaction("\N{WHITE HEAVY CHECK MARK}")
|
await message.add_reaction("\N{WHITE HEAVY CHECK MARK}")
|
||||||
await message.add_reaction("\N{NEGATIVE SQUARED CROSS MARK}")
|
await message.add_reaction("\N{NEGATIVE SQUARED CROSS MARK}")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user