Пример #1
0
    async def setoutrotts(self, ctx, *, outrotts: str = None):
        """Sets your outro tts

		This is what is said after saying your name when announcing that you have left the channel

		Calling this command without any text will tell you your current tts intro. The default is simply `has left!`. To set your tts to be nothing, try `?setoutrotts nothing` or `?setoutrotts none`

		The argument is the name of the clip that will introduce you, for example:
		`{cmdpfx}setoutrotts dun gone left`
		**Note:** your intro tts cannot be longer than 32 characters
		"""
        user = ctx.message.author

        if outrotts is None:
            outrotts = botdata.userinfo(user.id).outrotts

            await ctx.send(
                f"Your outro tts sounds like: {ctx.author.name} {outrotts}")
            await self.play_clip(f"tts:{ctx.author.name} {outrotts}", ctx)
            return

        if len(outrotts) > 32:
            await ctx.send(
                f"Dat text is {len(outrotts)} characters long, and outrotts text must be 32 characters or less"
            )
            return

        if outrotts.lower() in ["nothing", "none", ""]:
            outrotts = " "

        botdata.userinfo(user.id).outrotts = outrotts
        await ctx.send(f"Yer intro tts is now `{outrotts}`")
Пример #2
0
    async def on_voice_state_update(self, member, before, after):
        if member.bot and member.id != self.bot.user.id:
            return  # ignore bots except for mahself
        if before and after and before.channel == after.channel:
            return  # if the member didnt change channels, dont worry about it
        if before and before.channel and botdata.guildinfo(
                before.channel.guild).outros:
            beforeplayer = await self.audioplayer(before.channel,
                                                  error_on_none=False)
            if beforeplayer is not None and beforeplayer.voice is not None and beforeplayer.voice.channel.id == before.channel.id:
                guildinfo = botdata.guildinfo(before.channel.guild)
                userinfo = botdata.userinfo(member.id)

                outroclip = userinfo.outro
                outrotts = userinfo.outrotts
                name = member.name
                if guildinfo.usenickname and member.nick:
                    name = member.nick

                text = (await self.fix_name(name)) + " " + outrotts
                print(text)

                await asyncio.sleep(0.5)
                if not outroclip is None:
                    await self.play_clip(outroclip, before.channel)
                await self.play_clip("tts:" + text, before.channel)
        if after and after.channel and botdata.guildinfo(
                after.channel.guild).intros:
            afterplayer = await self.audioplayer(after.channel,
                                                 error_on_none=False)
            if afterplayer is not None and afterplayer.voice is not None and afterplayer.voice.channel.id == after.channel.id:
                guildinfo = botdata.guildinfo(after.channel.guild)
                if member.id == self.bot.user.id:
                    guildinfo.voicechannel = after.channel.id

                userinfo = botdata.userinfo(member.id)

                introclip = userinfo.intro
                introtts = userinfo.introtts
                name = member.name
                if guildinfo.usenickname and member.nick:
                    name = member.nick

                # Special case for default
                if userinfo.intro == "local:helloits" and introtts == "it's":
                    introtts = ""

                text = introtts + " " + await self.fix_name(name)
                print(text + " joined the channel")

                await asyncio.sleep(3)
                if not introclip is None:
                    await self.play_clip(introclip, after.channel)
                await self.play_clip("tts:" + text, after.channel)
Пример #3
0
	async def getbotdata(self, ctx, selector, identifier : int):
		"""Gets info about a user or a server, depending on the selector given"""
		if selector in ["user", "player", "member"]:
			data = botdata.userinfo(identifier)
			user = self.bot.get_user(identifier)
			if user is None:
				raise UserError("Couldn't find that user")

			embed = discord.Embed(description=(user.mention + "\n```json\n" + json.dumps(data.json_data, indent='\t') + "\n```"))
			embed.set_thumbnail(url=user.avatar_url)
			if data.steam:
				embed.add_field(name="Profiles", value=(
					f"[Steam](http://steamcommunity.com/id/{data.steam})\n"
					f"[OpenDota](https://www.opendota.com/players/{data.steam})\n"))
			await ctx.send(embed=embed)
		elif selector in ["server", "guild"]:
			data = botdata.guildinfo(identifier)
			guild = self.bot.get_guild(identifier)
			if guild is None:
				raise UserError("Couldn't find that guild")
			invite = None
			for channel in guild.text_channels:
				if channel.permissions_for(guild.me).create_instant_invite:
					invite = await channel.create_invite()
					break

			embed = discord.Embed(description=("```json\n" + json.dumps(data.json_data, indent='\t') + "\n```"))
			embed.set_author(name=guild.name)
			if guild.icon_url != "":
				embed.set_thumbnail(url=guild.icon_url)
			if invite:
				embed.add_field(name="Invite", value=invite.url)
			await ctx.send(embed=embed)
Пример #4
0
    async def setsteam(self, ctx, steam_id: int, user: discord.User = None):
        """Links a discord user to their steam/dota account
		*The user parameter can only be specified by the bot owner*
		
		You have to give this command either your steam32 or steam64 id. An easy way to find this is to look at the end of your dotabuff/opendota profile url.

		**Example:**
		If my dotabuff url is https://www.dotabuff.com/players/70388657
		I would do: `{cmdpfx}setsteam 70388657`
		"""

        if user is None:
            user = ctx.message.author
        else:
            if not checks.is_owner_check(ctx.message.author):
                await ctx.send("You aint the boss of me 😠")
                return

        if steam_id > 76561197960265728:
            steam_id -= 76561197960265728

        player = await opendota_query(f"/players/{steam_id}")

        if player.get("profile") is None:
            raise UserError(
                "Either thats a bad id, you don't play dota, or ya haven't enabled public match data"
            )

        userinfo = botdata.userinfo(user.id)
        userinfo.steam32 = steam_id

        await ctx.send("Linked to {}".format(player['profile']['personaname']))
Пример #5
0
	async def convert(cls, ctx, player):
		is_author = player is None
		if is_author:
			player = ctx.message.author

		try:
			player = int(player)
		except (ValueError, TypeError):
			pass # This either this is a discord user or an invalid argument

		if isinstance(player, int):
			if player > 76561197960265728:
				player -= 76561197960265728
			# Don't have to rate limit here because this will be first query ran
			player_info = await httpgetter.get(f"https://api.opendota.com/api/players/{player}", cache=False, errors=opendota_html_errors)

			if player_info.get("profile") is None:
				raise CustomBadArgument(NoMatchHistoryError(player))
			return cls(player, f"[{player_info['profile']['personaname']}](https://www.opendota.com/players/{player})", is_author)

		if not isinstance(player, discord.abc.User):
			try:
				player = await commands.MemberConverter().convert(ctx, str(player))
			except commands.BadArgument:
				raise CustomBadArgument(UserError("Ya gotta @mention a user who has been linked to a steam id, or just give me their steam id"))

		userinfo = botdata.userinfo(player.id)
		if userinfo.steam is None:
			if is_author:
				raise CustomBadArgument(SteamNotLinkedError())
			else:
				raise CustomBadArgument(SteamNotLinkedError(player))
		return cls(userinfo.steam, player.mention, is_author)
Пример #6
0
    async def setoutro(self,
                       ctx,
                       clipname: str = None,
                       user: discord.User = None):
        """Sets your outro clip

		Calling this command without a clipname will tell you your current outro

		The argument is the name of the clip that will 'outroduce' you, for example:
		`{cmdpfx}setoutro math`
		**Note:** your outro clip cannot be longer than 4 seconds
		"""
        if user is None:
            user = ctx.message.author
        else:
            if not checks.is_owner_check(ctx.message.author):
                await ctx.send("You aint the boss of me 😠")
                return

        if clipname is None:
            outro = botdata.userinfo(user.id).outro
            if outro is None or outro == "":
                await ctx.send(
                    "Yer outro isn't set. Try doin somethin' like `?setoutro dota:troll_lose_03`"
                )
                return
            else:
                await ctx.send("Your outro is: {}".format(outro))
                await self.play_clip("tts:your outro is", ctx)
                await self.play_clip(outro, ctx)
                return

        clip = await self.get_clip_try_types(clipname, "local|dota")

        audiolength = clip.audiolength

        if audiolength > 3.1:
            await ctx.send(
                f"Dat clip is {audiolength:.1f} seconds long, and outros gotta be less than 3."
            )
            return

        botdata.userinfo(user.id).outro = clip.clipid
        await ctx.send("Yer outro is now " + clip.clipid)
Пример #7
0
    async def on_voice_state_update(self, member, before, after):
        if before and after and before.channel == after.channel:
            return  # if the member didnt change channels, dont worry about it
        if before and before.channel and botdata.guildinfo(
                before.channel.guild).outros:
            beforeplayer = await self.audioplayer(before.channel,
                                                  error_on_none=False)
            if beforeplayer is not None and beforeplayer.voice.channel.id == before.channel.id:
                text = (await self.fix_name(member.name)) + " has left!"
                print(text)
                outroclip = "local:farewell"

                userinfo = botdata.userinfo(member.id)
                if userinfo.outro != "" and userinfo.outro != outroclip:
                    outroclip = userinfo.outro

                await asyncio.sleep(0.5)
                await self.play_clip(outroclip, before.channel)
                await self.play_clip("tts:" + text, before.channel)
        if after and after.channel and botdata.guildinfo(
                after.channel.guild).intros:
            afterplayer = await self.audioplayer(after.channel,
                                                 error_on_none=False)
            if afterplayer is not None and afterplayer.voice.channel.id == after.channel.id:
                if member.id == self.bot.user.id:
                    botdata.guildinfo(
                        after.channel.guild.id).voicechannel = after.channel.id

                text = await self.fix_name(member.name)
                print(text + " joined the channel")
                introclip = "local:helloits"

                userinfo = botdata.userinfo(member.id)
                if userinfo.intro != "" and userinfo.intro != introclip:
                    introclip = userinfo.intro
                    text = "its " + text

                await asyncio.sleep(3)
                await self.play_clip(introclip, after.channel)
                await self.play_clip("tts:" + text, after.channel)
Пример #8
0
    async def userconfig(self, ctx, name, *, value=None):
        """Configures the bot's user-specific settings

		Below are the different user-specific settings that you can tweak to customize mangobyte. You can get more information about a setting by typing `{cmdpfx}userconfig <settingname>`, and you can configure a setting by typing `{cmdpfx}userconfig <settingname> <value>`

		{userconfig_help}
		"""
        var = next((v for v in UserInfo.variables if v["key"] == name), None)
        if not var:
            vars_list = "\n".join(
                map(lambda v: f"`{v['key']}`", UserInfo.variables))
            await ctx.send(
                f"There is no userconfig setting called '{name}'. Try one of these:\n{vars_list}"
            )
            return

        if not value:  # We are just getting a value
            value = botdata.userinfo(ctx.message.author)[var["key"]]
            await ctx.send(embed=await botdatatypes.localize_embed(
                ctx, var, value, f"{self.cmdpfx(ctx)}userconfig"))
        else:  # We are setting a value
            value = await botdatatypes.parse(ctx, var, value)
            botdata.userinfo(ctx.message.author)[var["key"]] = value
            await ctx.message.add_reaction("✅")
Пример #9
0
async def get_check_steamid(player, ctx, mention=False, no_error=False):
	is_author = player is None
	if is_author:
		player = ctx.message.author

	try:
		player = int(player)
	except (ValueError, TypeError):
		pass # This either this is a discord user or an invalid argument


	if isinstance(player, int):
		if player > 76561197960265728:
			player -= 76561197960265728

		# Don't have to rate limit here because this will be first query ran
		player_info = await opendota_query(f"/players/{player}")

		if player_info.get("profile") is None:
			raise UserError("Either this person doesn't play dota, or they haven't enabled public match data")
		if mention:
			return player, f"[{player_info['profile']['personaname']}](https://www.opendota.com/players/{player})"
		else:
			return player

	if not isinstance(player, discord.User):
		try:
			player = await commands.MemberConverter().convert(ctx, str(player))
		except commands.BadArgument:
			if no_error:
				return None
			raise UserError("Ya gotta @mention a user who has been linked to a steam id, or just give me a their steam id")

	userinfo = botdata.userinfo(player.id)
	if userinfo.steam32 is None:
		if no_error:
			return None
		if is_author:
			raise SteamNotLinkedError()
		else:
			raise SteamNotLinkedError(player)

	if mention:
		return userinfo.steam32, player.mention
	else:
		return userinfo.steam32
Пример #10
0
	async def on_voice_state_update(self, member, before, after):
		channel_id = "not sure yet"
		try:
			if member.bot and member.id != self.bot.user.id:
				return # ignore bots except for mahself
			if before and after and before.channel == after.channel:
				return # if the member didnt change channels, dont worry about it
			if before and before.channel and botdata.guildinfo(before.channel.guild).outros:
				beforeplayer = await self.audioplayer(before.channel, error_on_none=False)
				if beforeplayer is not None and beforeplayer.voice is not None and beforeplayer.voice.channel.id == before.channel.id:
					ctx = before.channel.guild
					guildinfo = botdata.guildinfo(before.channel.guild)
					userinfo = botdata.userinfo(member.id)
					channel_id = before.channel.id

					if member.id == self.bot.user.id:
						return # dont play outros for self, thatd be a bug

					try:
						outroclip = userinfo.outro
						if outroclip:
							outroclip = await self.get_clip(userinfo.outro, ctx)
							if outroclip.audiolength > botdatatypes.max_intro_outro_length + 0.5:
								userinfo.set_default(ctx, "outro")
								outroclip = userinfo.outro
					except:
						userinfo.set_default(ctx, "outro")
						outroclip = userinfo.outro

					outrotts = userinfo.outrotts
					name = member.name
					if guildinfo.usenickname and member.nick:
						name = member.nick


					text = (await self.fix_name(name)) + " " + outrotts
					print(text)

					await asyncio.sleep(0.5)
					if not outroclip is None:				
						await self.play_clip(outroclip, before.channel)
					await self.play_clip("tts:" + text, before.channel)
			if after and after.channel and botdata.guildinfo(after.channel.guild).intros:
				afterplayer = await self.audioplayer(after.channel, error_on_none=False)
				if afterplayer is not None and afterplayer.voice is not None and afterplayer.voice.channel.id == after.channel.id:
					ctx = after.channel.guild
					guildinfo = botdata.guildinfo(after.channel.guild)
					channel_id = after.channel.id
					if member.id == self.bot.user.id:
						guildinfo.voicechannel = after.channel.id
						return # dont play intros for self.

					userinfo = botdata.userinfo(member.id)

					try:
						introclip = userinfo.intro
						if introclip:
							introclip = await self.get_clip(userinfo.intro, ctx)
							if introclip.audiolength > botdatatypes.max_intro_outro_length + 0.5:
								userinfo.set_default(ctx, "intro")
								introclip = userinfo.intro
					except:
						userinfo.set_default(ctx, "intro")
						introclip = userinfo.intro

					introtts = userinfo.introtts
					name = member.name
					if guildinfo.usenickname and member.nick:
						name = member.nick

					# Special case for default
					if userinfo.intro == "local:helloits" and introtts == "it's":
						introtts = ""

					text = introtts + " " + await self.fix_name(name)
					print(text + " joined the channel")

					await asyncio.sleep(3)
					if not introclip is None:
						await self.play_clip(introclip, after.channel)
					await self.play_clip("tts:" + text, after.channel)
		except UserError as e:
			print(f"Bad voice channel connection to ({channel_id}) from on_voice_state_update: {e.message}")
Пример #11
0
    async def friendstats(self, ctx, player):
        """Statistics of games played with a friend"""
        await ctx.channel.trigger_typing()
        author_id = botdata.userinfo(ctx.message.author.id).steam32
        if not author_id:
            raise SteamNotLinkedError()

        friend_id, friend_mention = await get_check_steamid(player,
                                                            ctx,
                                                            mention=True)
        author_mention = ctx.message.author.mention

        if author_id == friend_id:
            raise UserError(
                "🙄 ...Try giving me someone other than yourself...")

        author_info = await opendota_query(f"/players/{author_id}")
        friend_info = await opendota_query(f"/players/{friend_id}")

        def on_same_team(match):
            heroes = match["heroes"]
            player1 = heroes[next(x for x in heroes
                                  if heroes[x].get("account_id") == author_id)]
            player2 = heroes[next(x for x in heroes
                                  if heroes[x].get("account_id") == friend_id)]
            return (player1["player_slot"] < 128) == (player2["player_slot"] <
                                                      128)

        def won_match(match):
            heroes = match["heroes"]
            player = heroes[next(x for x in heroes
                                 if heroes[x].get("account_id") == author_id)]
            return (player["player_slot"] < 128) == match["radiant_win"]

        url = f"/players/{author_id}/matches?included_account_id={friend_id}"
        matches = await opendota_query(url)
        matches = list(filter(on_same_team, matches))
        if len(matches) == 0:
            raise UserError("You haven't played any matches with them!")

        winrate = len(list(filter(won_match, matches))) / len(matches)

        def format_match(match):
            heroes = match["heroes"]
            author = heroes[next(x for x in heroes
                                 if heroes[x].get("account_id") == author_id)]
            friend = heroes[next(x for x in heroes
                                 if heroes[x].get("account_id") == friend_id)]
            timediff = time.time() - match['start_time']
            timediff -= timediff % 60
            if timediff > (60 * 60 * 24 * 30):
                timediff -= timediff % (60 * 60)
            return (
                f"{get_pretty_time(timediff)} ago, "
                f"you [{'won' if won_match(match) else 'lost'} a match](https://www.opendota.com/matches/{match['match_id']}) where "
                f"{author_mention} played **{self.hero_info[author['hero_id']]['name']}**, and "
                f"{friend_mention} played **{self.hero_info[friend['hero_id']]['name']}**"
            )

        embed = discord.Embed(description=(
            f"[Games Played](https://www.opendota.com{url}): {len(matches)}\n"
            f"Winrate: {winrate:.2%}\n"),
                              color=self.embed_color)

        embed.add_field(name="First Match", value=format_match(matches[-1]))
        embed.add_field(name="Most Recent Match",
                        value=format_match(matches[0]))

        embed.set_author(
            name=
            f"{author_info['profile']['personaname']} + {friend_info['profile']['personaname']}",
            url=f"https://www.opendota.com{url}")

        image = discord.File(
            await drawdota.combine_image_halves(
                author_info['profile']['avatarfull'],
                friend_info['profile']['avatarfull']), "profile.png")
        embed.set_thumbnail(url=f"attachment://{image.filename}")

        await ctx.send(embed=embed, file=image)