Report fixes + improvements (#1541)

* WIP

* fix perms issue

* better

* more work

* working

* working, tessted

* docs

* mutable default fix
This commit is contained in:
Michael H 2018-05-04 00:38:58 -04:00 committed by Kowlin
parent fca7686701
commit 7cd98c8a63
2 changed files with 177 additions and 76 deletions

View File

@ -2,7 +2,8 @@ import logging
import asyncio
from typing import Union
from datetime import timedelta
from copy import copy
import contextlib
import discord
from discord.ext import commands
@ -109,9 +110,10 @@ class Reports:
ret |= await self.bot.is_owner(m)
return ret
async def discover_guild(self, author: discord.User, *,
async def discover_guild(
self, author: discord.User, *,
mod: bool=False,
permissions: Union[discord.Permissions, dict]={},
permissions: Union[discord.Permissions, dict]=None,
prompt: str=""):
"""
discovers which of shared guilds between the bot
@ -120,10 +122,12 @@ class Reports:
prompt is for providing a user prompt for selection
"""
shared_guilds = []
if isinstance(permissions, discord.Permissions):
if permissions is None:
perms = discord.Permissions()
elif isinstance(permissions, discord.Permissions):
perms = permissions
else:
permissions = discord.Permissions(**perms)
perms = discord.Permissions(**permissions)
for guild in self.bot.guilds:
x = guild.get_member(author.id)
@ -170,26 +174,40 @@ class Reports:
author = guild.get_member(msg.author.id)
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 = guild.get_channel(channel_id)
if channel is not None:
try:
await channel.send(embed=em)
except (discord.Forbidden, discord.HTTPException):
if channel is 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:
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
await self.config.custom('REPORT', guild.id, ticket_number).report.set(
@ -198,8 +216,13 @@ class Reports:
return ticket_number
@commands.group(name="report", invoke_without_command=True)
async def report(self, ctx: RedContext):
"Follow the prompts to make a report"
async def report(self, ctx: RedContext, *, _report: str=""):
"""
Follow the prompts to make a report
optionally use with a report message
to use it non interactively
"""
author = ctx.author
guild = ctx.guild
if guild is None:
@ -243,6 +266,12 @@ class Reports:
pass
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:
dm = await author.send(
_("Please respond to this message with your Report."
@ -268,6 +297,8 @@ class Reports:
)
else:
val = await self.send_report(message, guild)
with contextlib.suppress(discord.Forbidden, discord.HTTPException):
if val is None:
await author.send(
_("There was an error sending your report.")

View File

@ -4,6 +4,7 @@ from redbot.core.utils.chat_formatting import pagify
import io
import sys
import weakref
from typing import List
_instances = weakref.WeakValueDictionary({})
@ -94,6 +95,88 @@ class Tunnel(metaclass=TunnelMeta):
def minutes_since(self):
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, *,
message: discord.Message,
topic: str=None,
@ -140,35 +223,22 @@ class Tunnel(metaclass=TunnelMeta):
else:
content = topic
attach = None
if message.attachments:
files = []
size = 0
max_size = 8 * 1024 * 1024
for a in message.attachments:
_fp = io.BytesIO()
await a.save(_fp)
size += sys.getsizeof(_fp)
if size > max_size:
await send_to.send(
attach = await self.files_from_attatch(message)
if not attach:
await message.channel.send(
"Could not forward attatchments. "
"Total size of attachments in a single "
"message must be less than 8MB."
)
break
files.append(
discord.File(_fp, filename=a.filename)
)
else:
attach = files
attach = []
rets = []
for page in pagify(content):
rets.append(
await send_to.send(content, files=attach)
rets = await self.message_forwarder(
destination=send_to,
content=content,
files=attach
)
if attach:
del attach
await message.add_reaction("\N{WHITE HEAVY CHECK MARK}")
await message.add_reaction("\N{NEGATIVE SQUARED CROSS MARK}")