def hots_free(self, ctx):
"""Retrieves the Heroes of the Storm free rotation."""
url = "http://us.battle.net/heroes/en/"
soup = BeautifulSoup(urlopen(url), 'html5lib')
parsedText = [] ## End result: finds cleaned text from HTML
freeHeroes = [] ## Index of all free heroes found
freeIndicator = "|| Free" ## This is what Blizzard uses to indicate free heroes in their webpage
for elem in soup.find_all('li'):
if "free-rotation" in str(elem):
index = str(elem).find(freeIndicator)
## General area of where the string needed is. I'm lazy. ##
parsedText.append(str(elem)[index-100:index+100])
## Find text via regex ##
for string in parsedText:
result = re.search('data-analytics-placement="(.*) Free"', string)
freeHeroes.append(result.group(1)[0:-3])
## Formats via Discord's markdown ##
botText = "```md\n<Free-Rotation>```" + "```"
for hero in freeHeroes:
botText += hero+", "
botText = botText[0:-2] + "```"
await self.bot.say(botText)
python类group()的实例源码
def _display_embed(self, ctx, name=None, *entities, whitelist, type_):
colour, action, icon = _value_embed_mappings[whitelist]
embed = (discord.Embed(colour=colour)
.set_author(name=f'{type_} {action}!', icon_url=icon)
)
if name not in {ALL_MODULES_KEY, None}:
cog, _, name = _extract_from_node(name)
embed.add_field(name=type_, value=name or cog)
sorted_entities = sorted(entities, key=_get_class_name)
for k, group in itertools.groupby(sorted_entities, _get_class_name):
group = list(group)
name = f'{k}{"s" * (len(group) != 1)}'
value = truncate(', '.join(map(str, group)), 1024, '...')
embed.add_field(name=name, value=value, inline=False)
await ctx.send(embed=embed)
def _leaderboard(self, ctx: commands.Context, league_id: str, matchday: str=None):
"""Gets league leaderboard"""
headers = [' ', 'ID', 'Team', 'Points', 'P', 'G', 'GA', 'GD']
data = await self._get_league_leaderboard(ctx.message.server.id, league_id, matchday)
pretty_data = []
# await self.bot.say('```diff\n+ ' + data['leagueCaption'] + '\n- Matchday: ' + str(data['matchday']) + '\n```')
await self.bot.say('```diff\n+ {}\n- Matchday: {}\n```'.format(data['leagueCaption'], data['matchday']))
if 'standing' in data:
for team in data['standing']:
pretty_data.append([team['rank'], team['teamId'], team['team'], team['points'], team['playedGames'], team['goals'], team['goalsAgainst'], team['goalDifference']])
await self.bot.say(box(tabulate(pretty_data, headers=headers)))
elif 'standings' in data:
for group, v in data['standings'].items():
asyncio.sleep(1)
await self.bot.say('```diff\n+ Group ' + group + '```')
pretty_data = []
for team in v:
pretty_data.append([team['rank'], team['team'], team['points'], team['playedGames'], team['goals'], team['goalsAgainst'], team['goalDifference']])
await self.bot.say(box(tabulate(pretty_data, headers=headers)))
def find_command(self, command):
# This method ensures the command given is valid. We need to loop through commands
# As self.bot.commands only includes parent commands
# So we are splitting the command in parts, looping through the commands
# And getting the subcommand based on the next part
# If we try to access commands of a command that isn't a group
# We'll hit an AttributeError, meaning an invalid command was given
# If we loop through and don't find anything, cmd will still be None
# And we'll report an invalid was given as well
cmd = None
for part in command.split():
try:
if cmd is None:
cmd = self.bot.commands.get(part)
else:
cmd = cmd.commands.get(part)
except AttributeError:
cmd = None
break
return cmd
def log(self, ctx, *, user: str):
"""Shows mod log entries for a user.
Only searches the past 300 cases.
"""
mod_log = ctx.message.server.get_channel('222010090226581504')
entries = []
async for m in self.bot.logs_from(mod_log, limit=300):
entry = self.pollr.match(m.content)
if entry is None:
continue
if user in entry.group('user'):
entries.append(m.content)
fmt = 'Found {} entries:\n{}'
await self.bot.say(fmt.format(len(entries), '\n\n'.join(entries)))
def raw(self, ctx, *, name: TagName(lower=True)):
"""Gets the raw content of the tag.
This is with markdown escaped. Useful for editing.
"""
try:
tag = await self.get_tag(ctx.guild.id, name, connection=ctx.db)
except RuntimeError as e:
return await ctx.send(e)
transformations = {
re.escape(c): '\\' + c
for c in ('*', '`', '_', '~', '\\', '<')
}
def replace(obj):
return transformations.get(re.escape(obj.group(0)), '')
pattern = re.compile('|'.join(transformations.keys()))
await ctx.send(pattern.sub(replace, tag['content']))
def uniquegroup(self, ctx, role: discord.Role, groupid: int):
"""Set a role to a unique group ID,
This means that a user cannot have more then one role from the same group.
Any role sharing the same ID will be considered a group.
GroupID 0 will not be considered unique and can share other roles."""
server = ctx.message.server
if role.id not in self.settings_dict[server.id]['roles']:
await self.bot.say('This role ins\'t in the buyrole list')
elif groupid < 0:
await self.bot.say('The group ID cannot be negative.')
else:
# Set the uniquegroup ID here, logic will remain in a subfunction of buyrole
self.settings_dict[server.id]['roles'][role.id]['uniquegroup'] = groupid
self.save_json()
if groupid == 0:
await self.bot.say('Unique Group ID set. {} isn\'t considered unique.'.format(role.name))
else:
await self.bot.say('Unique Group ID set. {} will now be unique in group ID {}'.format(role.name, groupid))
def __init__(self, bot):
self.bot = bot
self.dbpath = "data/gaming/settings.json"
self.db = fileIO(self.dbpath, "load")
self.version = "1.0.0"
self.update_type = "release"
self.patchnote = """
**Gaming cog, first release!**
Main purpose of this cog is to help large gaming communities. There are two groups of commands at the moment `profiles` and `lfg`
`profiles` is used for managing gaming networks profiles, such as steam, psn, xbl, etx. I see it being used to get users profile, while he/she is away.
Use `[p]help profiles` for more info
`lfg` is a bit barebone at the moment. It can be used to set your status as "looking for group", so other users can see you on the list
Use `[p]help lfg` and `[p]help lfg looking` for more info
More to come!
"""
# useful methids
def uniquegroup(self, ctx, role: discord.Role, groupid: int):
"""Set a role to a unique group ID,
This means that a user cannot have more then one role from the same group.
Any role sharing the same ID will be considered a group.
GroupID 0 will not be considered unique and can share other roles."""
server = ctx.message.server
if role.id not in self.settings_dict[server.id]['roles']:
await self.bot.say('This role ins\'t in the buyrole list')
elif groupid < 0:
await self.bot.say('The group ID cannot be negative.')
else:
# Set the uniquegroup ID here, logic will remain in a subfunction of buyrole
self.settings_dict[server.id]['roles'][role.id]['uniquegroup'] = groupid
self.save_json()
if groupid == 0:
await self.bot.say('Unique Group ID set. {} isn\'t considered unique.'.format(role.name))
else:
await self.bot.say('Unique Group ID set. {} will now be unique in group ID {}'.format(role.name, groupid))
def setcookie(self, ctx):
"""Cookie settings group command"""
if ctx.invoked_subcommand is None:
await send_cmd_help(ctx)
def roulette_round(self, settings, server, players, turn):
roulette_circle = players[:]
chamber = 6
await self.bot.say("*{} put one round into the six shot revolver and gave it a good spin. "
"With a flick of the wrist, it locks in place."
"*".format(self.bot.user.name))
await asyncio.sleep(4)
await self.bot.say("Let's begin round {}.".format(turn))
while chamber >= 1:
if not roulette_circle:
roulette_circle = players[:] # Restart the circle when list is exhausted
chance = random.randint(1, chamber)
player = random.choice(roulette_circle)
await self.bot.say("{} presses the revolver to their temple and slowly squeezes the "
"trigger...".format(player.name))
if chance == 1:
await asyncio.sleep(4)
msg = "**BOOM**\n```{} died and was removed from the group.```".format(player.name)
await self.bot.say(msg)
msg2 = random.choice(kill_message)
settings["Players"].pop(player.id)
remaining = [server.get_member(x) for x in list(settings["Players"].keys())]
player2 = random.choice(remaining)
death_time = strftime("%H:%M:%S", gmtime())
await asyncio.sleep(5)
await self.bot.say(msg2.format(player.name, player2.name, death_time))
await asyncio.sleep(5)
break
else:
await asyncio.sleep(4)
await self.bot.say("**CLICK**\n```{} survived and passed the "
"revolver.```".format(player.name))
await asyncio.sleep(3)
roulette_circle.remove(player)
chamber -= 1
def __init__(self, bot):
self.bot = bot
self.group = []
self.version = 2.01
def dtable(self, ctx):
"""Shows a list under this group commands."""
if ctx.invoked_subcommand is None:
await send_cmd_help(ctx)
def setrace(self, ctx):
"""Race cog's settings group command"""
if ctx.invoked_subcommand is None:
await send_cmd_help(ctx)
def group(name=None, **attrs):
return commands.command(name=name, cls=Group, **attrs)
def get_tsun(self, index: str):
r = requests.get('https://www.instagram.com/tsuntsunlive/')
html = r.content
soup = bs4.BeautifulSoup(html, 'html.parser')
tag_list = soup.find_all("script", type="text/javascript")
tag_list = [str(tag) for tag in tag_list]
tag_list = sorted(tag_list, key=len)
data_tag = tag_list[-1]
after = index.split()
try:
index = int(after[0])
except ValueError:
index = None
except IndexError:
index = None
post_list = re.split('"caption": "', data_tag)[1:]
if index is None:
post = random.choice(post_list)
else:
post = post_list[index - 1]
caption = post[:re.search('", "likes"', post).start()]
caption = re.sub(r"(\\u[0-9a-f]{4})", lambda match: codecs.decode(match.group(1), "unicode_escape"), caption)
caption = re.sub(r"\\n", "\n", caption)
img_part = post[re.search('"display_src": "', post).end():]
img = img_part[:re.search("\?", img_part).start()]
img = re.sub(r"\\", "", img)
data = [img, caption]
return data
def tax(self, ctx):
if ctx.invoked_subcommand is None:
await self.bot.say('Please lookup !help tax for commands in this group')
def channel_mangement(self, ctx):
if ctx.invoked_subcommand is None:
await global_methods.say_other(ctx, 'Please lookup !help man for commands in this group', self.bot)
def mention_id(mention):
match = ID_RE.match(mention)
if match is not None:
return int(match.group(1))
def group(*args, **kwargs):
if 'pass_context' not in kwargs:
kwargs['pass_context'] = True
ret = commands.group(*args, **kwargs)
return ret
def chan(self, ctx):
"""Voice Channel Access `role` command group
[p]vca chan add (voice channel id) (role id)
[p]vca chan rem (voice channel id)"""
pass
def THP(self, ctx, link): ## ctx is an invisible parameter ##
"""Dead site."""
author = ctx.message.author.id
frontpage = []
threads = []
frontpage_str = ''
try:
url = link ## build the web address ##
soup = BeautifulSoup(urlopen(url), 'html5lib')
except Exception:
url = "https://" + link
soup = BeautifulSoup(urlopen(url), 'html5lib')
try:
for elem in soup.find_all('li'):
if "@" in str(elem):
frontpage.append(str(elem)[4:17] + " - " + str(elem.a.contents)[2:-2])
if frontpage:
for link in frontpage:
frontpage_str += link + '\n'
else:
for elem in soup.select('span[id]'):
if "hidden." in str(elem):
regex_str = re.search('>(.*?)</a>', str(elem))
if regex_str:
threads.append(regex_str.group(1))
for thread in threads:
for elem in soup.find_all("input", value=thread):#, string=thread):
regex_str = re.search('>[\r\n]+(.*?)[\r\n]+</span>', str(elem.find_next()))
if regex_str:
frontpage.append(regex_str.group(1))
for link in frontpage:
frontpage_str += link + '\n'
await self.bot.say("```" + frontpage_str + "```")
except Exception as e:
await self.bot.say("Try a valid link.")
def disable(self, ctx, command: str):
"""
Disables a command in this server.
In order to disable a group, simply pass in the group's name.
For example: "d?disable feedback" will disable all feedback commands.
"""
if self.bot.has_prefix(command):
await ctx.send('You must leave off the prefix.')
return
await self.bot.disable_command(ctx.guild, command)
await ctx.ok()
def reddit(self, ctx):
"""
This command group contains all commands related to Reddit feeds.
Feeds will be updated every 30 minutes. Both self and link posts will be posted to the channel. NSFW posts will
only be posted if the channel that the bot is posting in is NSFW. Stickied posts are never posted.
"""
pass
def __init_subclass__(cls, *, game_cls, cmd=None, aliases=(), **kwargs):
super().__init_subclass__(**kwargs)
cls.__game_class__ = game_cls
cmd_name = cmd or cls.__name__.lower()
group_help = inspect.getdoc(cls._game).format(name=cls.name)
group_command = commands.group(
name=cmd_name, aliases=aliases, help=group_help, invoke_without_command=True
)(cls._game)
setattr(cls, f'{cmd_name}', group_command)
gc = group_command.command
for name, member in inspect.getmembers(cls):
if not name.startswith('_game_'):
continue
name = name[6:]
if name in {'invite', 'create'}:
# Special treatment is needed for these two
continue
help = inspect.getdoc(member).format(name=cls.name, cmd=cmd_name)
command = gc(name=name, help=help)(member)
setattr(cls, f'{cmd_name}_{name}', command)
setattr(cls, f'_{cls.__name__}__error', cls._error)
# Deprecate create and invite
dc = functools.partial(gc, cls=DeprecatedCommand, version='1.2')
setattr(cls, f'{cmd_name}_create', dc(name='create', instead=f'{cmd_name}')(cls._game_create))
setattr(cls, f'{cmd_name}_invite', dc(name='invite', instead=f'{cmd_name} @user')(cls._game_invite))
def warn_error(self, ctx, error):
original = getattr(error, 'original', None)
if isinstance(original, RuntimeError):
await ctx.send(original)
# XXX: Should this be a group?
def channel_online(self, twitch_url: str):
# Check a specific channel's data, and get the response in text format
channel = re.search("(?<=twitch.tv/)(.*)", twitch_url).group(1)
url = "https://api.twitch.tv/kraken/streams/{}".format(channel)
response = await utils.request(url, payload=self.params)
# For some reason Twitch's API call is not reliable, sometimes it returns stream as None
# That is what we're checking specifically, sometimes it doesn't exist in the returned JSON at all
# Sometimes it returns something that cannot be decoded with JSON (which means we'll get None back)
# In either error case, just assume they're offline, the next check will most likely work
try:
return response['stream'] is not None
except (KeyError, TypeError):
return False
def twitch(self, ctx, *, member: discord.Member = None):
"""Use this command to check the twitch info of a user
EXAMPLE: !twitch @OtherPerson
RESULT: Information about their twitch URL"""
await ctx.message.channel.trigger_typing()
if member is None:
member = ctx.message.author
result = await utils.get_content('twitch', member.id)
if result is None:
await self.bot.say("{} has not saved their twitch URL yet!".format(member.name))
return
url = result['twitch_url']
user = re.search("(?<=twitch.tv/)(.*)", url).group(1)
twitch_url = "https://api.twitch.tv/kraken/channels/{}".format(user)
payload = {'client_id': self.key}
data = await utils.request(twitch_url, payload=payload)
embed = discord.Embed(title=data['display_name'], url=url)
if data['logo']:
embed.set_thumbnail(url=data['logo'])
embed.add_field(name='Title', value=data['status'])
embed.add_field(name='Followers', value=data['followers'])
embed.add_field(name='Views', value=data['views'])
if data['game']:
embed.add_field(name='Game', value=data['game'])
embed.add_field(name='Language', value=data['broadcaster_language'])
await self.bot.say(embed=embed)
def add_tag(self, ctx, *, result: str):
"""Use this to add a new tag that can be used in this server
Format to add a tag is !tag add <tag> - <result>
EXAMPLE: !tag add this is my new tag - This is what it will be
RESULT: A tag that can be called by '!tag this is my new tag' and will output 'This is what it will be'"""
try:
# Use regex to get the matche for everything before and after a -
match = re.search("(.*) - (.*)", result)
tag = match.group(1).strip()
tag_result = match.group(2).strip()
# Next two checks are just to ensure there was a valid match found
except AttributeError:
await self.bot.say(
"Please provide the format for the tag in: {}tag add <tag> - <result>".format(ctx.prefix))
return
# If our regex failed to find the content (aka they provided the wrong format)
if len(tag) == 0 or len(tag_result) == 0:
await self.bot.say(
"Please provide the format for the tag in: {}tag add <tag> - <result>".format(ctx.prefix))
return
# Make sure the tag created does not mention everyone/here
if '@everyone' in tag_result or '@here' in tag_result:
await self.bot.say("You cannot create a tag that mentions everyone!")
return
entry = {'server_id': ctx.message.server.id, 'tag': tag, 'result': tag_result}
r_filter = lambda row: (row['server_id'] == ctx.message.server.id) & (row['tag'] == tag)
# Try to create new entry first, if that fails (it already exists) then we update it
if not await config.update_content('tags', entry, r_filter):
await config.add_content('tags', entry)
await self.bot.say(
"I have just updated the tag `{0}`! You can call this tag by entering !tag {0}".format(tag))
def add_synonym(self, other):
"""Every word in a group of synonyms shares the same list."""
self.synonyms.extend(other.synonyms)
other.synonyms = self.synonyms