async def register(self, ctx): """Add yourself to the database""" if repo_u.exists(ctx.author.id): return await ctx.author.send("You are already registered.") nickname = self.sanitise(ctx.author.name, limit=12).replace(")", "").replace("(", "") # get first available nickname i = 0 name_orig = nickname while repo_u.is_nickname_used(nickname): nickname = f"{name_orig}{i}" i += 1 # register repo_u.add(discord_id=ctx.author.id, nickname=nickname) if isinstance(ctx.channel, discord.TextChannel) and repo_w.get(ctx.channel.id): beam_name = repo_w.get(ctx.channel.id).beam repo_u.set(ctx.author.id, key=f"home_id:{beam_name}", value=ctx.channel.id) await self.event.user(ctx, f"Registered as **{nickname}**.") await ctx.author.send( f"You are now registered as `{nickname}`. " f"You can display your information with `{self.p}me`.\n" f"To see information about another user, enter `{self.p}whois [nickname]`.\n\n" f"You can tag other registered users with `((nickname))`." )
async def wormhole_remove(self, ctx, channel_id: int = None): """Remove wormhole from database""" if channel_id is None: if hasattr(ctx.channel, "id"): channel_id = ctx.channel.id else: raise errors.BadArgument("Missing channel ID") channel = self._get_channel(ctx=ctx, channel_id=channel_id) if channel is not None: beam_name = repo_w.get_attribute(channel_id, "beam") repo_w.delete(discord_id=channel_id) await self.event.sudo(ctx, f"{self._w2str_log(channel)} removed.") await self.announce( beam=beam_name, message=f"Wormhole closed: {self._w2str_out(channel)}.") await channel.send(f"Wormhole closed: {self._w2str_out(channel)}.") return # channel is not available wormhole = repo_w.get(channel_id) if wormhole is not None: await self.event.sudo(ctx, f"Wormhole {channel_id} removed.") repo_w.delete(discord_id=channel_id) return await ctx.send("Not found.")
async def settings(self, ctx: commands.Context): """Display settings for current beam""" db_w = repo_w.get(ctx.channel.id) db_b = repo_b.get(db_w.beam) db_u = repo_u.get(ctx.author.id) msg = ">>> **Settings**:\n" # beam settings pars = [] # fmt: off pars.append("active" if db_b.active else "inactive") pars.append(f"replacing (timeout **{db_b.timeout} s**)" if db_b. replace else "not replacing") pars.append(f"anonymity level **{db_b.anonymity}**") # fmt: on msg += ", ".join(pars) # wormhole settings pars = [] if db_w.active is False: pars.append("inactive") if db_w.readonly is True: pars.append("read only") if len(pars) > 0: msg += "\n**Wormhole overrides**:\n" msg += ", ".join(pars) # user settings if db_u is not None and db_u.readonly is True: msg += "\n**User overrides**:\n" msg += "read only" await ctx.send(msg, delete_after=self.delay())
def _get_prefix(self, message: discord.Message, first_line: bool = True): """Get prefix for message""" db_w = repo_w.get(message.channel.id) db_b = repo_b.get(db_w.beam) db_u = repo_u.get(message.author.id) # get user nickname if db_u is not None: if db_b.name in db_u.home_ids: # user has home wormhole home = repo_w.get(db_u.home_ids[db_b.name]) else: # user is registered without home home = None if home is not None: name = "__" + db_u.nickname + "__" else: name = db_u.nickname else: name = self.sanitise(message.author.name, limit=32) home = db_w # get logo if hasattr(home, "logo") and len(home.logo): if first_line: logo = home.logo else: logo = config["logo fill"] else: logo = self.sanitise(message.guild.name) # get prefix if db_b.anonymity == "none": # display everything prefix = f"{logo} **{name}**: " elif db_b.anonymity == "guild" and len(logo): # display guild logo prefix = logo + " " elif db_b.anonymity == "guild" and len(logo) == 0: # display guild name prefix = f"{logo}, **{name}**" else: # wrong configuration or full anonymity prefix = "" return prefix
async def on_message(self, message: discord.Message): # ignore non-textchannel sources if not isinstance(message.channel, discord.TextChannel): return # do not act if author is bot if message.author.bot: return # get wormhole db_w = repo_w.get(message.channel.id) if db_w is None: return # get additional information db_b = repo_b.get(db_w.beam) # check for attributes # fmt: off if db_b.active == 0 \ or db_w.active == 0 \ or repo_u.get_attribute(message.author.id, "readonly") == 1: return await self.delete(message) # fmt: on # do not act if message is bot command if message.content.startswith(config["prefix"]): return await self.delete(message) # get wormhole channel objects if db_b.name not in self.wormholes or len( self.wormholes[db_b.name]) == 0: self.reconnect(db_b.name) # process incoming message content = await self._process(message) # convert attachments to links first_line = True if message.attachments: for f in message.attachments: # don't add newline if message has only attachments if first_line: content += " " + f.url first_line = False else: content += "\n" + f.url if len(content) < 1: return # count the message self._update_stats(message) # send the message await self.send(message=message, text=content, files=message.attachments)
async def smart_send(self, ctx, *, content: str = None, embed: discord.Embed = None): if content is None and embed is None: return if hasattr(ctx.channel, "id") and repo_w.get(ctx.channel.id) is not None: await ctx.send(content=content, embed=embed, delete_after=self.delay()) else: await ctx.send(content=content, embed=embed)
async def send(self, ctx: commands.Context, error, text: str): if config["log level"] == "CRITICAL": return prefix = "> **Error:** " if hasattr(ctx.channel, "id") and repo_w.get(ctx.channel.id) is not None: # do not leave errors in wormhole await ctx.send(prefix + text, delete_after=20.0) else: await ctx.send(prefix + text)
async def info(self, ctx: commands.Context): """Display information about wormholes""" public = hasattr(ctx.channel, "id") and repo_w.get(ctx.channel.id) is not None if public: await ctx.send( self._get_info(repo_w.get_attribute(ctx.channel.id, "beam")), delete_after=self.delay(), ) return user_beams = repo_u.get_home(ctx.author.id).keys() for beam_name in user_beams: await ctx.send(self._get_info(beam_name, title=True))
async def set_home(self, ctx): """Set current channel as your home wormhole""" if not repo_u.exists(ctx.author.id): return await ctx.author.send(f"Register with `{self.p}register`") if repo_u.get_attribute(ctx.author.id, "restricted") == 1: return await ctx.author.send("You are forbidden to alter your settings.") if not isinstance(ctx.channel, discord.TextChannel) or not repo_w.exists(ctx.channel.id): return await ctx.author.send("Home has to be a wormhole") beam_name = repo_w.get(ctx.channel.id).beam repo_u.set(ctx.author.id, key=f"home_id:{beam_name}", value=ctx.channel.id) await ctx.author.send("Home set to " + ctx.channel.mention) await self.event.user( ctx, f"Home in **{beam_name}** set to **{ctx.channel.id}** ({ctx.guild.name})." )
async def send( self, *, message: discord.Message, text: str, files: list = None, ): """Distribute the message""" deleted_original = False # get variables messages = [message] db_w = repo_w.get(message.channel.id) db_b = repo_b.get(db_w.beam) # access control if db_b.active == 0: return if db_w.active == 0 or db_w.readonly == 1: return if repo_u.get_attribute(message.author.id, "readonly") == 1: return # remove the original, if possible manage_messages_perm = message.guild.me.permissions_in( message.channel).manage_messages if manage_messages_perm and db_b.replace == 1 and not files: try: messages[0] = message.author await self.delete(message) deleted_original = True except discord.Forbidden: pass # limit message length text = text[:1024] # update wormhole list if db_b.name not in self.wormholes.keys(): self.reconnect(db_b.name) wormholes = self.wormholes[db_b.name] users = self._get_users_from_tags(beam_name=db_b.name, text=text) # replicate messages tasks = [] for wormhole in wormholes: task = asyncio.ensure_future( self.replicate( wormhole, message, messages, users, text, files, db_b, manage_messages_perm, )) tasks.append(task) await asyncio.gather(*tasks, return_exceptions=True) # add checkmark to original, if it hasn't been deleted if not deleted_original: await message.add_reaction("✅") # save message objects in case of editing/deletion if db_b.timeout > 0: self.sent.append(messages) await asyncio.sleep(db_b.timeout) self.sent.remove(messages)