mirror of
https://github.com/osmarks/autobotrobot
synced 2025-02-07 12:40:00 +00:00
add tel searchrecent and tel delrecent commands
these look through all discord channels bridged to the given channel (including that channel itself) and search for messages matching the given query. the delrecent command, after asking for confirmation, will then delete all of those messages that it can across all the channels. it is capable of deleting messages sent by our own webhooks even if we don't have manage message permissions in the channel in question. the user interface is not amazing but these are both extpriv-only and only send any outputs in dms so this probably isn't very important.
This commit is contained in:
parent
31491d7ba9
commit
3c3ffbb036
@ -78,4 +78,4 @@ def setup(bot):
|
|||||||
if ext == "all":
|
if ext == "all":
|
||||||
for ext in util.extensions: bot.reload_extension(ext)
|
for ext in util.extensions: bot.reload_extension(ext)
|
||||||
else: bot.reload_extension(ext)
|
else: bot.reload_extension(ext)
|
||||||
await ctx.send("Done!")
|
await ctx.send("Done!")
|
||||||
|
@ -4,10 +4,12 @@ import logging
|
|||||||
import asyncio
|
import asyncio
|
||||||
import re
|
import re
|
||||||
import hashlib
|
import hashlib
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
import os
|
import os
|
||||||
import pydot
|
import pydot
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import collections
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
import util
|
import util
|
||||||
import eventbus
|
import eventbus
|
||||||
@ -179,6 +181,88 @@ When you want to end a call, use hangup.
|
|||||||
await ctx.send(f"Successfully deleted.")
|
await ctx.send(f"Successfully deleted.")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
async def _find_recent(self, chs, query):
|
||||||
|
one_week = timedelta(seconds=60*60*24*7)
|
||||||
|
one_week_ago = datetime.now()-one_week
|
||||||
|
|
||||||
|
found = collections.defaultdict(list)
|
||||||
|
async def find_msgs(ch):
|
||||||
|
# the parameters to history() here might need to be tweaked
|
||||||
|
# somewhat, for more general usage
|
||||||
|
async for msg in ch.history(limit=None,after=one_week_ago):
|
||||||
|
if query in msg.content.lower():
|
||||||
|
found[ch].append(msg)
|
||||||
|
await asyncio.gather(*(find_msgs(ch) for ch in chs))
|
||||||
|
return found
|
||||||
|
|
||||||
|
@telephone.command(brief="find recent messages in channels linked to this")
|
||||||
|
@commands.check(util.extpriv_check)
|
||||||
|
async def searchrecent(self, ctx, ch: discord.TextChannel, *, query):
|
||||||
|
author = ctx.author
|
||||||
|
chs = []
|
||||||
|
for dest in eventbus.find_all_destinations(('discord',ch.id)):
|
||||||
|
if dest[0] == 'discord':
|
||||||
|
chs.append(self.bot.get_channel(dest[1]))
|
||||||
|
|
||||||
|
found = await self._find_recent(chs, query)
|
||||||
|
|
||||||
|
out = ""
|
||||||
|
for ch,ms in found.items():
|
||||||
|
out += f"{ch.mention} (`#{ch.name}` in `{ch.guild.name}`)\n"
|
||||||
|
for m in ms:
|
||||||
|
u = m.author.name if m.author else None
|
||||||
|
w = "[WH]" if m.webhook_id else ""
|
||||||
|
out += f"- {m.content[:20]} @{m.created_at} by {u} {w}\n"
|
||||||
|
|
||||||
|
for c in util.chunks(out,2000):
|
||||||
|
await author.send(c)
|
||||||
|
|
||||||
|
return found
|
||||||
|
|
||||||
|
@telephone.command(brief="delete recent messages in channels linked to this")
|
||||||
|
@commands.check(util.extpriv_check)
|
||||||
|
async def delrecent(self, ctx, ch: discord.TextChannel, *, query):
|
||||||
|
author = ctx.author
|
||||||
|
found = await self.searchrecent(ctx,ch,query=query)
|
||||||
|
|
||||||
|
await author.send("please say 'GO' to confirm or wait 10 seconds to not confirm")
|
||||||
|
try:
|
||||||
|
await self.bot.wait_for('message',check=lambda m:m.author == ctx.author and m.content == "GO" and m.channel == ctx.author.dm_channel,timeout=10)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
await author.send("timed out")
|
||||||
|
return
|
||||||
|
|
||||||
|
async def try_delete(msg,session):
|
||||||
|
if msg.webhook_id is not None:
|
||||||
|
# note: assumes there is only one webhook we control per channel
|
||||||
|
# i think that's the case
|
||||||
|
wh_url = await self.bot.database.execute_fetchone("SELECT webhook FROM discord_webhooks WHERE channel_id = ?",(msg.channel.id,))
|
||||||
|
if wh_url is None:
|
||||||
|
await author.send(f"no access to webhook: {msg.id} {msg.channel.mention} {msg.jump_url}")
|
||||||
|
return
|
||||||
|
wh_url = wh_url['webhook']
|
||||||
|
|
||||||
|
wh = discord.Webhook.from_url(wh_url,session=session)
|
||||||
|
await wh.delete_message(msg.id)
|
||||||
|
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
await msg.delete()
|
||||||
|
except discord.errors.Forbidden:
|
||||||
|
await author.send(f"!!! couldn't delete msg {msg.id} in {msg.channel.mention}")
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for q in found.values():
|
||||||
|
msgs.extend(q)
|
||||||
|
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
await asyncio.gather(*(try_delete(msg,session) for msg in msgs))
|
||||||
|
|
||||||
|
await author.send("done")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@telephone.command(brief="Generate a webhook")
|
@telephone.command(brief="Generate a webhook")
|
||||||
@commands.check(util.server_mod_check)
|
@commands.check(util.server_mod_check)
|
||||||
async def init_webhook(self, ctx):
|
async def init_webhook(self, ctx):
|
||||||
@ -223,7 +307,7 @@ When you want to end a call, use hangup.
|
|||||||
if address == originating_address: return await ctx.send(embed=util.error_embed("A channel cannot dial itself. That means *you*, Gibson."))
|
if address == originating_address: return await ctx.send(embed=util.error_embed("A channel cannot dial itself. That means *you*, Gibson."))
|
||||||
recv_info = await self.get_addr_config(address)
|
recv_info = await self.get_addr_config(address)
|
||||||
if not recv_info: return await ctx.send(embed=util.error_embed("Destination address not found. Please check for typos and/or antimemes."))
|
if not recv_info: return await ctx.send(embed=util.error_embed("Destination address not found. Please check for typos and/or antimemes."))
|
||||||
|
|
||||||
current_call = await self.bot.database.execute_fetchone("SELECT * FROM calls WHERE from_id = ?", (originating_address,))
|
current_call = await self.bot.database.execute_fetchone("SELECT * FROM calls WHERE from_id = ?", (originating_address,))
|
||||||
if current_call: return await ctx.send(embed=util.error_embed(f"A call is already open (to {current_call['to_id']}) from this channel. Currently, only one outgoing call is permitted at a time."))
|
if current_call: return await ctx.send(embed=util.error_embed(f"A call is already open (to {current_call['to_id']}) from this channel. Currently, only one outgoing call is permitted at a time."))
|
||||||
|
|
||||||
@ -348,4 +432,4 @@ When you want to end a call, use hangup.
|
|||||||
def setup(bot):
|
def setup(bot):
|
||||||
cog = Telephone(bot)
|
cog = Telephone(bot)
|
||||||
bot.add_cog(cog)
|
bot.add_cog(cog)
|
||||||
asyncio.create_task(cog.initial_load_webhooks())
|
asyncio.create_task(cog.initial_load_webhooks())
|
||||||
|
@ -327,4 +327,9 @@ def random_id():
|
|||||||
second_time -= SIMPLEFLAKE_EPOCH
|
second_time -= SIMPLEFLAKE_EPOCH
|
||||||
millisecond_time = int(second_time * 1000)
|
millisecond_time = int(second_time * 1000)
|
||||||
randomness = random.getrandbits(SIMPLEFLAKE_RANDOM_LENGTH)
|
randomness = random.getrandbits(SIMPLEFLAKE_RANDOM_LENGTH)
|
||||||
return (millisecond_time << SIMPLEFLAKE_TIMESTAMP_SHIFT) + randomness
|
return (millisecond_time << SIMPLEFLAKE_TIMESTAMP_SHIFT) + randomness
|
||||||
|
|
||||||
|
def chunks(source, length):
|
||||||
|
for i in range(0, len(source), length):
|
||||||
|
yield source[i : i+length]
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user