Beispiel #1
0
def _is_admin_or_mod(ctx):
    if ctx.message.author.id == owner:
        return True
    else:
        admin_roles = gs.get(ctx.guild).perm_roles["admin"]
        mod_roles = gs.get(ctx.guild).perm_roles["mod"]
        for role in ctx.author.roles:
            if role.id in mod_roles or role.id in admin_roles:
                return True
    return False
Beispiel #2
0
    async def iam(self, ctx, *, role: discord.Role = None):
        """
		Self-assign yourself a role. Only one role at a time.
		Usage:
			{command_prefix}iam [role]
		Example:
			.iam OverwatchPing
		"""
        settings = gs.get(ctx.guild)

        if role is None:
            # Hacky way to get the error I want
            from inspect import Parameter
            raise commands.MissingRequiredArgument(Parameter("Role", False))

        if not settings.self_assign["enabled"]:
            embed = discord.Embed(
                colour=roxbot.EmbedColours.pink,
                description=
                "SelfAssignable roles are not enabled on this server")
            return await ctx.send(embed=embed)

        member = ctx.author

        if role in member.roles:
            return await ctx.send("You already have that role.")

        if role.id in settings.self_assign["roles"]:
            await member.add_roles(role, reason="'iam' command triggered.")
            return await ctx.send("Yay {}! You now have the {} role!".format(
                member.mention, role.name))
        else:
            return await ctx.send("That role is not self-assignable.")
Beispiel #3
0
    async def iamn(self, ctx, *, role: discord.Role = None):
        """
		Remove a self-assigned role
		Usage:
			{command_prefix}iamn [role]
		Example:
			.iamn OverwatchPing
		"""
        settings = gs.get(ctx.guild)

        if role is None:
            from inspect import Parameter
            raise commands.MissingRequiredArgument(Parameter("role", False))

        if not settings.self_assign["enabled"]:
            embed = discord.Embed(
                colour=roxbot.EmbedColours.pink,
                description=
                "SelfAssignable roles are not enabled on this server")
            return await ctx.send(embed=embed)

        member = ctx.author

        if role in member.roles and role.id in settings.self_assign["roles"]:
            await member.remove_roles(role, reason="'iamn' command triggered.")
            return await ctx.send("{} has been successfully removed.".format(
                role.name))
        elif role not in member.roles and role.id in settings.self_assign[
                "roles"]:
            return await ctx.send("You do not have {}.".format(role.name))
        else:
            return await ctx.send("That role is not self-assignable.")
Beispiel #4
0
    async def add(self, ctx, user: discord.User = None, *, warning=""):
        """Adds a warning to a user."""
        # Warning in the settings is a dictionary of user ids. The user ids are equal to a list of dictionaries.
        settings = gs.get(ctx.guild)
        warning_limit = 2
        warning_dict = {
            "warned-by": ctx.author.id,
            "date": time.time(),
            "warning": warning
        }
        user_id = str(user.id)

        if user_id not in settings.warnings:
            settings.warnings[user_id] = []

        settings.warnings[user_id].append(warning_dict)
        settings.update(settings.warnings, "warnings")

        amount_warnings = len(settings.warnings[user_id])
        if amount_warnings > warning_limit:
            await ctx.author.send(
                "{} has been reported {} time(s). This is a reminder that this is over the set limit of {}."
                .format(str(user), amount_warnings, warning_limit))

        return await ctx.send("Reported {}.".format(str(user)))
Beispiel #5
0
	async def skip(self, ctx, option=""):
		"""Skips or votes to skip the current video. Use option "--force" if your an admin and """
		voice = guild_settings.get(ctx.guild).voice
		if ctx.voice_client.is_playing():
			if voice["skip_voting"] and not (option == "--force" and roxbot.checks._is_admin_or_mod(ctx)):  # Admin force skipping
				if ctx.author in self.skip_votes[ctx.guild.id]:
					return await ctx.send("You have already voted to skip the current track.")
				else:
					self.skip_votes[ctx.guild.id].append(ctx.author)
					# -1 due to the bot being counted in the members generator
					ratio = len(self.skip_votes[ctx.guild.id]) / (len(ctx.voice_client.channel.members) - 1)
					needed_users = ceil((len(ctx.voice_client.channel.members) - 1) * voice["skip_ratio"])
					if ratio >= voice["skip_ratio"]:
						await ctx.send("{} voted the skip the video.".format(ctx.author))
						await ctx.send("Votes to skip now playing has been met. Skipping video...")
						self.skip_votes[ctx.guild.id] = []
					else:
						await ctx.send("{} voted the skip the song.".format(ctx.author))
						return await ctx.send("{}/{} votes required to skip the video. To vote, use the command `{}skip`".format(len(self.skip_votes[ctx.guild.id]), needed_users, ctx.prefix))
			else:
				await ctx.send("Skipped video")

			# This should be fine as the queue_logic function should handle moving to the next song and all that.
			self.now_playing[ctx.guild.id] = None
			ctx.voice_client.stop()
		else:
			await ctx.send("I'm not playing anything.")
Beispiel #6
0
 async def printsettings(self, ctx, option=None):
     """OWNER OR ADMIN ONLY: Prints the servers settings file."""
     # TODO: Use paginator to make the output here not break all the time.
     config = guild_settings.get(ctx.guild)
     settings = dict(config.settings.copy(
     ))  # Make a copy of settings so we don't change the actual settings.
     em = discord.Embed(colour=EmbedColours.pink)
     em.set_author(name="{} settings for {}.".format(
         self.bot.user.name, ctx.message.guild.name),
                   icon_url=self.bot.user.avatar_url)
     if option in settings:
         raw = bool(ctx.invoked_with == "printsettingsraw")
         settingcontent = self.parse_setting(ctx, settings[option], raw=raw)
         em.add_field(name=option, value=settingcontent, inline=False)
         return await ctx.send(embed=em)
     else:
         for setting in settings:
             if setting != "custom_commands" and setting != "warnings":
                 raw = bool(ctx.invoked_with == "printsettingsraw")
                 settingcontent = self.parse_setting(ctx,
                                                     settings[setting],
                                                     raw=raw)
                 em.add_field(name=setting,
                              value=settingcontent,
                              inline=False)
             elif setting == "custom_commands":
                 em.add_field(
                     name="custom_commands",
                     value=
                     "For Custom Commands, use the custom list command.",
                     inline=False)
         return await ctx.send(embed=em)
Beispiel #7
0
async def log(guild, channel, command_name, **kwargs):
    logging = guild_settings.get(guild).logging
    if logging["enabled"]:
        embed = discord.Embed(title="{} command logging".format(command_name),
                              colour=EmbedColours.pink)
        for key, value in kwargs.items():
            embed.add_field(name=key, value=value)
        return await channel.send(embed=embed)
Beispiel #8
0
def nsfw_predicate(ctx):
    nsfw = gs.get(ctx.guild).nsfw
    if not nsfw["channels"] and nsfw["enabled"]:
        return nsfw["enabled"] == 1
    elif nsfw["enabled"] and nsfw["channels"]:
        return ctx.channel.id in nsfw["channels"]
    else:
        return False
Beispiel #9
0
 def predicate(ctx):
     if ctx.author.id == owner:
         return True
     else:
         for role in ctx.author.roles:
             if role.id in gs.get(ctx.guild).perm_roles["admin"]:
                 return True
     return False
Beispiel #10
0
def _is_admin_or_mod(message):
    if message.author.id == roxbot.owner:
        return True
    perm_roles = gs.get(message.channel.guild).perm_roles
    for role in message.author.roles:
        if role.id in perm_roles.get("admin") or role.id in perm_roles.get(
                "mod"):
            return True
    return False
Beispiel #11
0
 async def on_member_remove(self, member):
     # TODO: Add some way of detecting whether a user left/was kicked or was banned.
     logging = guild_settings.get(member.guild).logging
     if logging["enabled"]:
         channel = self.bot.get_channel(logging["channel"])
         embed = discord.Embed(
             description="{} left the server".format(member),
             colour=EmbedColours.pink)
         return await channel.send(embed=embed)
Beispiel #12
0
	async def on_member_remove(self, member):
		"""
		The same but the opposite
		"""
		settings = guild_settings.get(member.guild)
		channel = settings.goodbyes["goodbye-channel"]
		if not settings.goodbyes["enabled"]:
			return
		else:
			channel = self.bot.get_channel(channel)
			return await channel.send(embed=discord.Embed(
				description="{}#{} has left or been beaned.".format(member.name, member.discriminator), colour=roxbot.EmbedColours.pink))
Beispiel #13
0
    async def list(self, ctx, *, user: roxbot.converters.UserConverter = None):
        """Lists all or just the warnings for one user."""
        settings = gs.get(ctx.guild)

        if user is None:
            output = ""
            for member in settings.warnings:
                # Remove users with no warning here instead of remove cause im lazy
                if not settings.warnings[member]:
                    settings.warnings.pop(member)
                else:
                    member_obj = discord.utils.get(ctx.guild.members,
                                                   id=int(member))
                    if member_obj:
                        output += "{}: {} Warning(s)\n".format(
                            str(member_obj), len(settings.warnings[member]))
                    else:
                        output += "{}: {} Warning(s)\n".format(
                            member, len(settings.warnings[member]))
            if not output:
                return await ctx.send("No warnings on record.")
            return await ctx.send(output)

        user_id = str(user.id)

        if not settings.warnings.get(user_id):
            return await ctx.send(
                "This user doesn't have any warning on record.")

        if not settings.warnings[user_id]:
            settings.warnings.pop(user_id)
            settings.update(settings.warnings, "warnings")

        em = discord.Embed(title="Warnings for {}".format(str(user)),
                           colour=roxbot.EmbedColours.pink)
        em.set_thumbnail(url=user.avatar_url)
        x = 1
        userlist = settings.warnings[user_id]
        for warning in userlist:
            try:
                warned_by = str(await
                                self.bot.get_user_info(warning["warned-by"]))
            except discord.ext.commands.CommandInvokeError:
                warned_by = warning["warned-by"]
            date = datetime.datetime.fromtimestamp(
                warning["date"]).strftime('%c')
            warn_reason = warning["warning"]
            em.add_field(name="Warning %s" % x,
                         value="Warned by: {}\nTime: {}\nReason: {}".format(
                             warned_by, date, warn_reason))
            x += 1
        return await ctx.send(embed=em)
Beispiel #14
0
	def predicate(ctx):
		gs = guild_settings.get(ctx.guild)
		if gs.voice["need_perms"]:  # Had to copy the admin or mod code cause it wouldn't work ;-;
			if ctx.message.author.id == roxbot.owner:
				return True
			else:
				admin_roles = gs.perm_roles["admin"]
				mod_roles = gs.perm_roles["mod"]
				for role in ctx.author.roles:
					if role.id in mod_roles or role.id in admin_roles:
						return True
			return False
		else:
			return True
Beispiel #15
0
 async def prune(self, ctx, dry_run=0):
     """Purges banned users from the warn list. Add a 1 at the end to do a dry run."""
     settings = gs.get(ctx.guild)
     warnings = settings.warnings.copy()
     count = 0
     for ban in await ctx.guild.bans():
         for user in warnings:
             if int(user) == ban.user.id:
                 if dry_run == 0:
                     settings.warnings.pop(user)
                 count += 1
     settings.update(settings.warnings, "warnings")
     return await ctx.send(
         "Purged {} banned users from the warn list.".format(count))
Beispiel #16
0
 async def on_member_join(self, member):
     logging = guild_settings.get(member.guild).logging
     if logging["enabled"]:
         channel = self.bot.get_channel(logging["channel"])
         embed = discord.Embed(title="{} joined the server".format(member),
                               colour=EmbedColours.pink)
         embed.add_field(name="ID", value=member.id)
         embed.add_field(name="Mention", value=member.mention)
         embed.add_field(name="Date Account Created",
                         value="{:%a %Y/%m/%d %H:%M:%S} UTC".format(
                             member.created_at))
         embed.add_field(name="Date Joined",
                         value="{:%a %Y/%m/%d %H:%M:%S} UTC".format(
                             member.joined_at))
         embed.set_thumbnail(url=member.avatar_url)
         return await channel.send(embed=embed)
Beispiel #17
0
    async def on_member_join(self, member):
        """
		Greets users when they join a server.
		"""
        settings = guild_settings.get(member.guild)
        if not settings.greets["enabled"]:
            return

        if settings.greets["custom-message"]:
            message = settings.greets["custom-message"]
        else:
            message = settings.greets["default-message"]
        em = discord.Embed(title="Welcome to {}!".format(member.guild),
                           description='Hey {}! Welcome to **{}**! {}'.format(
                               member.mention, member.guild, message),
                           colour=roxbot.EmbedColours.pink)
        em.set_thumbnail(url=member.avatar_url)

        channel = self.bot.get_channel(settings.greets["welcome-channel"])
        return await channel.send(embed=em)
Beispiel #18
0
    async def remove(self,
                     ctx,
                     user: roxbot.converters.UserConverter = None,
                     index=None):
        """Removes one or all of the warnings for a user."""
        user_id = str(user.id)
        settings = gs.get(ctx.guild)

        if index:
            try:
                index = int(index)
                index -= 1
                settings.warnings[user_id].pop(index)
                if not settings.warnings[user_id]:
                    settings.warnings.pop(user_id)

                settings.update(settings.warnings, "warnings")
                return await ctx.send("Removed Warning {} from {}".format(
                    index + 1, str(user)))

            except Exception as e:
                if isinstance(e, IndexError):
                    return await ctx.send(":warning: Index Error.")
                elif isinstance(e, KeyError):
                    return await ctx.send(
                        "Could not find user in warning list.")
                elif isinstance(e, ValueError):
                    return await ctx.send("Please enter a valid index number.")
                else:
                    raise e
        else:
            try:
                settings.warnings.pop(user_id)
                settings.update(settings.warnings, "warnings")
                return await ctx.send("Removed all warnings for {}".format(
                    str(user)))
            except KeyError:
                return await ctx.send("Could not find user in warning list.")
Beispiel #19
0
	async def logging(self, ctx, selection=None, *, changes=None):
		"""Edits the logging settings.

		Options:
			enable/disable: Enable/disables logging.
			channel: sets the channel.
		"""
		selection = selection.lower()
		settings = guild_settings.get(ctx.guild)

		if selection == "enable":
			settings.logging["enabled"] = 1
			await ctx.send("'logging' was enabled!")
		elif selection == "disable":
			settings.logging["enabled"] = 0
			await ctx.send("'logging' was disabled :cry:")
		elif selection == "channel":
			channel = self.get_channel(ctx, changes)
			settings.logging["channel"] = channel.id
			await ctx.send("{} has been set as the logging channel!".format(channel.mention))
		else:
			return await ctx.send("No valid option given.")
		return self.guild_settings.update(settings.logging, "logging")
Beispiel #20
0
async def log(guild, channel, command_name, **kwargs):
    """Logs activity internally for Roxbot. Will only do anything if the server enables internal logging.

	This is mostly used for logging when certain commands are used that can be an issue for admins. Esp when Roxbot outputs
	something that could break the rules, then deletes their message.

	Params
	=======
	guild: discord.Guild
		Used to check if the guild has logging enabled
	channel: discord.TextChannel
	command_name: str
	kwargs: dict
		All kwargs and two other params will be added to the logging embed as fields, allowing you to customise the output

	"""
    logging = guild_settings.get(guild).logging
    if logging["enabled"]:
        embed = discord.Embed(title="{} command logging".format(command_name),
                              colour=EmbedColours.pink)
        for key, value in kwargs.items():
            embed.add_field(name=key, value=value)
        return await channel.send(embed=embed)
Beispiel #21
0
    async def listroles(self, ctx):
        """
		List's all roles that can be self-assigned on this server.
		Usage:
			{command_prefix}listroles
		"""
        settings = gs.get(ctx.guild)
        if not settings.self_assign["enabled"]:
            embed = discord.Embed(
                colour=roxbot.EmbedColours.pink,
                description=
                "SelfAssignable roles are not enabled on this server")
            return await ctx.send(embed=embed)
        roles = []
        for role in settings.self_assign["roles"]:
            for serverrole in ctx.guild.roles:
                if role == serverrole.id:
                    roles.append("**" + serverrole.name + "**")
        roles = '\n'.join(roles)
        embed = discord.Embed(
            colour=roxbot.EmbedColours.pink,
            description="The self-assignable roles for this server are: \n" +
            roles)
        return await ctx.send(embed=embed)
Beispiel #22
0
	async def play(self, ctx, *, url, stream=False, from_queue=False):
		"""Plays from a url or search query (almost anything youtube_dl supports)"""
		voice = guild_settings.get(ctx.guild).voice
		guild = ctx.guild

		# Checks if invoker is in voice with the bot. Skips admins and mods and owner.
		if not roxbot.checks._is_admin_or_mod(ctx) or from_queue:
			if not ctx.author.voice:
				raise commands.CommandError("You're not in the same voice channel as Roxbot.")
			if ctx.author.voice.channel != ctx.voice_client.channel:
				raise commands.CommandError("You're not in the same voice channel as Roxbot.")

		# For internal speed. This should make the playlist management quicker when play is being invoked internally.
		if isinstance(url, dict):
			video = url
			url = video.get("webpage_url")
		else:
			video = ytdl.extract_info(url, download=False)

		# Playlist and search handling.
		if 'entries' in video and video.get("extractor_key") != "YoutubeSearch":
			await ctx.send("Looks like you have given me a playlist. I will que up all {} videos in the playlist.".format(len(video.get("entries"))))
			data = dict(video)
			video = data["entries"].pop(0)
			for entry in data["entries"]:
				self._queue_song(ctx, entry, stream)
		elif 'entries' in video and video.get("extractor_key") == "YoutubeSearch":
			video = video["entries"][0]

		# Duration limiter handling
		if video.get("duration", 1) > voice["max_length"] and not roxbot.checks._is_admin_or_mod(ctx):
			raise commands.CommandError("Cannot play video, duration is bigger than the max duration allowed.")

		# Actual playing stuff section.
		# If not playing and not queuing, and not paused, play the song. Otherwise queue it.
		if (not ctx.voice_client.is_playing() and self.am_queuing[guild.id] is False) and not ctx.voice_client.is_paused():
			self.am_queuing[guild.id] = True

			async with ctx.typing():
				player = await YTDLSource.from_url(url, loop=self.bot.loop, stream=stream, volume=self._volume[ctx.guild.id])
				player.stream = stream
				player.queued_by = ctx.author
				self.now_playing[guild.id] = player
				self.am_queuing[guild.id] = False

				ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None)

			# Create task to deal with what to do when the video ends or is skipped and how to handle the queue
			self.queue_logic[ctx.guild.id] = self.bot.loop.create_task(self._queue_logic(ctx))

			embed = self._generate_np_embed(ctx.guild, "Now Playing")
			await ctx.send(embed=embed)
		else:
			# Queue the song as there is already a song playing or paused.
			self._queue_song(ctx, video, stream)

			# Sleep because if not, queued up things will send first and probably freak out users or something
			while self.am_queuing[guild.id] is True:
				await asyncio.sleep(0.5)
			embed = discord.Embed(description='Added "{}" to queue'.format(video.get("title")), colour=roxbot.EmbedColours.pink)
			await ctx.send(embed=embed)
Beispiel #23
0
def tag_blacklist(guild):
	blacklist = ""
	for tag in gs.get(guild).nsfw["blacklist"]:
		blacklist += "-{} ".format(tag)
	return blacklist
Beispiel #24
0
 def self_assign(cls, guild):
     name = "Self Assign"
     settings = guild_settings.get(guild).self_assign
     params = settings.keys()
     return cls(name, settings, *params)
Beispiel #25
0
def isnt_anal():
    return commands.check(lambda ctx: gs.get(ctx.guild).is_anal[
        "y/n"] and nsfw_predicate(ctx) or not gs.get(ctx.guild).is_anal["y/n"])
Beispiel #26
0
 def twitch(cls, guild):
     name = "Twitch"
     settings = guild_settings.get(guild).twitch
     params = settings.keys()
     return cls(name, settings, *params)
Beispiel #27
0
 def voice(cls, guild):
     name = "Voice"
     settings = guild_settings.get(guild).voice
     params = settings.keys()
     return cls(name, settings, *params)
Beispiel #28
0
 def gss(cls, guild):
     name = "GaySoundsShitposts"
     settings = guild_settings.get(guild).gss
     params = settings.keys()
     return cls(name, settings, *params)
Beispiel #29
0
	async def subreddit(self, ctx, subreddit):
		"""
		Grabs an image or video (jpg, png, gif, gifv, webm, mp4) from the subreddit inputted.
		Example:
		{command_prefix}subreddit pics
		"""
		subreddit = subreddit.lower()
		links = await subreddit_request(subreddit)
		title = ""
		choice = {}

		if not links or not links.get("after") or links["children"][0]["kind"] == "t5":  # Determine if response is valid
			return await ctx.send("Error ;-; That subreddit probably doesn't exist. Please check your spelling")

		url = ""
		x = 0
		# While loop here to make sure that we check if there is any image posts in the links we have. If so, just take the first one.
		# Choosing a while loop here because, for some reason, the for loop would never exit till the end. Leading to slow times.
		while not url and x <= 20:
			choice = random.choice(links["children"])["data"]
			url = await parse_url(choice["url"])
			if url:
				x_old = int(x)
				# If the url or id are in the cache,  continue the loop. If not, proceed with the post.
				for cache in self.post_cache[ctx.guild.id]:
					if url in cache or choice["id"] in cache:
						x += 1
						break
				if x_old != x:  # Has x been incremented
					url = ""  # Restart search for new post
					if x > 20:
						break
					continue

				title = "**{}** \nby /u/{} from /r/{}\n".format(unescape(choice["title"]), unescape(choice["author"]), subreddit)
				break
			else:
				x += 1

		# Check if post is NSFW, and if it is and this channel doesn't past the NSFW check, then return with the error message.
		if choice["over_18"] and not roxbot.checks.nsfw_predicate(ctx):
			return await ctx.send("This server/channel doesn't have my NSFW stuff enabled. This extends to posting NFSW content from Reddit.")
		if not url:  # If no image posts could be found with the for loop.
			return await ctx.send("I couldn't find any images from that subreddit.")

		# Put the post ID and url in the cache. The url is used in case of two posts having the same link. Handy to avoid crossposts getting through the cache.
		cache_amount = 10
		post = (choice["id"], url)
		self.post_cache[ctx.guild.id].append(post)
		if len(self.post_cache[ctx.guild.id]) >= cache_amount:
			self.post_cache[ctx.guild.id].pop(0)

		if url.split("/")[-2] == "a":
			text = "This is an album, click on the link to see more.\n"
		else:
			text = ""

		if ctx.invoked_with == "subreddit":
			# Only log the command when it is this command being used. Not the inbuilt commands.
			logging = guild_settings.get(ctx.guild).logging
			log_channel = self.bot.get_channel(logging["channel"])
			await roxbot.log(
				ctx.guild,
				log_channel,
				"subreddit",
				User=ctx.author,
				Subreddit=subreddit,
				Returned="<{}>".format(url),
				Channel=ctx.channel,
				Channel_Mention=ctx.channel.mention,
				Time="{:%a %Y/%m/%d %H:%M:%S} UTC".format(ctx.message.created_at)
			)

		# Not using a embed here because we can't use video in rich embeds but they work in embeds now :/
		output = await ctx.send(title + text + url)
		await roxbot.utils.delete_option(self.bot, ctx, output, self.bot.get_emoji(444410658101002261) or "❌")
Beispiel #30
0
 async def settings(self, ctx):
     self.guild_settings = guild_settings.get(ctx.guild)