示例#1
0
 async def game(self, ctx, *, game):
     await ctx.trigger_typing()
     msgs = await lang.get_lang(ctx)
     trending = ""
     if game.endswith(" --trending"):
         trending = "&trending=true"
     r = http.TwitchAPIRequest(
         "https://api.twitch.tv/kraken/search/games?" +
         urlencode({"query": game.strip(' --trending')}))
     if r.status_code != 200:
         await ctx.send(
             f"{msgs['games']['generic_error']} {r.status_code}-1")
         return
     elif r.json().get('games') == None:
         return await ctx.send(msgs['streams']['game_not_found'])
     elif len(r.json()['games']) < 1:
         await ctx.send(msgs['clips']['no_clips'])
         return
     game = r.json()['games'][0]['name']
     r = http.TwitchAPIRequest(
         "https://api.twitch.tv/kraken/clips/top?limit=50&" +
         urlencode({"game": game}) + trending)
     if r.status_code != 200:
         await ctx.send(
             f"{msgs['games']['generic_error']} {r.status_code}-2")
         return
     elif len(r.json()['clips']) < 1:
         await ctx.send(msgs['clips']['no_clips'])
         return
     clip = choice(r.json()['clips'])
     m = await ctx.send(msgs['clips']['clip_message'].format(
         user=clip['broadcaster']['display_name'],
         game=clip['game'],
         url=clip['url'].split('?')[0]))
示例#2
0
 async def game(self, ctx, *, name):
     await ctx.trigger_typing()
     msgs = await lang.get_lang(ctx)
     g = http.TwitchAPIRequest("https://api.twitch.tv/helix/games?" +
                               urllib.parse.urlencode({"name": name}))
     g.raise_for_status()
     try:
         g = g.json()['data'][0]
     except:
         return await ctx.send(msgs['streams']['game_not_found'])
     game = g['name']
     s = http.TwitchAPIRequest(
         "https://api.twitch.tv/helix/streams?game_id=" + g['id'])
     s.raise_for_status()
     if len(s.json()['data']) < 1:
         return await ctx.send(msgs['streams']['game_no_streams'])
     stream = choice(s.json()['data'])
     u = http.TwitchAPIRequest("https://api.twitch.tv/helix/users?id=" +
                               stream['user_id'])
     u.raise_for_status()
     u = u.json()['data'][0]
     await ctx.send(msgs['streams']['game_desc'].format(
         user=u['display_name'].replace("_", "\\_"),
         game=game,
         view_count=stream['viewer_count']))
示例#3
0
 async def user(self, ctx, *, user):
     await ctx.trigger_typing()
     msgs = await lang.get_lang(ctx)
     user = user.split('/')[-1]
     e = discord.Embed(color=discord.Color(0x6441A4))
     r = http.TwitchAPIRequest(
         "https://api.twitch.tv/helix/streams?user_login="******"data") in [[], None]:
         await ctx.send(msgs['streams']['stream_not_found'])
     else:
         r = r.json()["data"][0]
         u = http.TwitchAPIRequest(
             "https://api.twitch.tv/helix/users?login="******"data"][0]
         g = http.TwitchAPIRequest("https://api.twitch.tv/helix/games?id=" +
                                   r["game_id"])
         g.raise_for_status()
         try:
             g = g.json()["data"][0]
         except:
             g = {"id": 0, "name": "Unknown"}
         e.set_author(icon_url=u["profile_image_url"],
                      name=u["display_name"],
                      url="https://twitch.tv/{}".format(u["login"]))
         e.title = r["title"]
         e.description = msgs['streams']['stream_desc'].format(
             game=g['name'],
             view_count=r['viewer_count'],
             channel=u['login'])
         e.set_image(
             url=r["thumbnail_url"].format(width="1920", height="1080") +
             f"?{secrets.token_urlsafe(5)}")
         await ctx.send(embed=e)
示例#4
0
文件: audio.py 项目: JLexD/LUL
 async def listen(self, ctx, *, url: str):
     """Listen to the specified Twitch user in the current voice channel."""
     msgs = await lang.get_lang(ctx)
     url = "https://www.twitch.tv/" + url.split('/')[-1]
     if (not hasattr(ctx.author, "voice")) or ctx.author.voice is None:
         return await ctx.send(msgs['audio']['author_not_in_voice_channel'])
     voice_channel = ctx.author.voice.channel
     prem_check = requests.get(f"https://api.twitchbot.io/premium/{ctx.author.id}", headers={"X-Auth-Key": settings.DashboardKey})
     if prem_check.json().get('premium') != True or prem_check.status_code != 200:
         r = requests.get(f"https://dash.twitchbot.io/api/users/{ctx.author.id}/votes", headers={"X-Auth-Key": settings.DashboardKey})
         if r.status_code != 200 or r.json()['active'] == False:
             # Fallback in case the dashboard failed
             r = http.BotLists.DBLRequest(f"/bots/375805687529209857/check?userId={ctx.author.id}")
             if r.status_code == 200 and not r.json()['voted'] == 1:
                 return await ctx.send(embed=lang.EmbedBuilder(msgs['audio']['need_upvote_to_continue']))
     m = await ctx.send(msgs['audio']['please_wait'])
     try:
         try:
             channel = await voice_channel.connect()
         except discord.ClientException:
             session = ctx.message.guild.voice_client
             await session.disconnect()
             await asyncio.sleep(2)
             channel = await voice_channel.connect()
     except Exception as ex:
         return await ctx.send(f"A {type(ex).__name__} occurred: {ex}")
     try:
         r = http.TwitchAPIRequest("https://api.twitch.tv/helix/streams?user_login="******"twitch.tv/")[1])
         if len(r.json()["data"]) < 1:
             return await m.edit(content=msgs['audio']['user_does_not_exist_or_not_streaming'])
         r = r.json()["data"][0]
         r2 = http.TwitchAPIRequest("https://api.twitch.tv/helix/users?login="******"twitch.tv/")[1])
         if len(r2.json()["data"]) < 1:
             return await m.edit(content=msgs['audio']['user_does_not_exist_or_not_streaming'])
         r2 = r2.json()["data"][0]
         e = discord.Embed(color=0x6441A4, title=msgs['audio']['now_playing']['title'].format(channel=voice_channel.name), description=msgs['audio']['now_playing']['description'].format(title=r['title'], viewer_count=r['viewer_count']))
         e.set_author(name=r2['display_name'], url=url, icon_url=r2['profile_image_url'])
         e.set_image(url=r['thumbnail_url'].format(width=1920, height=1080) + f"?{secrets.token_urlsafe(5)}")
         e.set_footer(icon_url=ctx.author.avatar_url or ctx.author.default_avatar_url, text=f"{ctx.author} - {msgs['audio']['now_playing']['footer']}")
         player = await YTDLSource.from_url(url, loop=self.bot.loop, stream=True)
         channel.play(player, after=lambda e: logging.error("{}: {}".format(type(e).__name__, e)) if e else None)
         self.bot.active_vc[ctx.message.guild.id] = e
         await m.edit(content=None, embed=e)
     except youtube_dl.DownloadError:
         await ctx.send(msgs['audio']['user_does_not_exist_or_not_streaming'])
     except TimeoutError:
         await ctx.send(msgs['audio']['connection_timeout'])
     except discord.ClientException as ex:
         await ctx.send(f"{type(ex).__name__}: {ex}")
         #await ctx.send("I'm already in a voice channel. Please stop the existing stream and then start it in the new channel.")
     except:
         raise
示例#5
0
 async def top(self, ctx):
     await ctx.trigger_typing()
     msgs = await lang.get_lang(ctx)
     r = http.TwitchAPIRequest(
         "https://api.twitch.tv/helix/streams?first=20")
     r.raise_for_status()
     stream = choice(r.json()['data'])
     u = http.TwitchAPIRequest("https://api.twitch.tv/helix/users?id=" +
                               stream['user_id'])
     u.raise_for_status()
     u = u.json()["data"][0]
     g = http.TwitchAPIRequest("https://api.twitch.tv/helix/games?id=" +
                               stream["game_id"])
     g.raise_for_status()
     g = g.json()["data"][0]
     return await ctx.send(msgs['streams']['game_desc'].format(
         user=u['login'], game=g['name'],
         view_count=stream['viewer_count']))
示例#6
0
 async def preview(self, ctx, discord_channel: discord.TextChannel,
                   twitch_user: str):
     """Sends a preview for a notification."""
     msgs = await lang.get_lang(ctx)
     username = twitch_user.split('/')[-1]
     if self.regex.match(username) is None:
         return await ctx.send(msgs['notifs']['malformed_user'])
     await ctx.trigger_typing()
     req = http.TwitchAPIRequest(
         f"https://api.twitch.tv/helix/users?login={username}")
     if req.status_code == 404 or len(req.json().get('data', [])) < 1:
         return await ctx.send(msgs['notifs']['twitch_user_not_found_alt'])
     elif req.status_code != 200:
         return await ctx.send(
             f"{msgs['notifs']['invalid_data']} {req.status_code}")
     req = req.json()['data'][0]
     notif = r.table('notifications').filter(
         (r.row['streamer'] == req['id'])
         & (r.row['channel'] == str(discord_channel.id)))
     if notif.count().run(self.bot.rethink, durability="soft") == 0:
         return await ctx.send(msgs['notifs']['del_fail'])
     notif = list(notif.run(self.bot.rethink, durability="soft"))[0]
     e = discord.Embed(color=discord.Color(0x6441A4))
     e.title = "**Stream Title**"
     e.description = f"\nPlaying Game for 123 viewers\n[Watch Stream](https://twitch.tv/{req['login']})"
     e.timestamp = datetime.datetime.now()
     e.url = "https://twitch.tv/" + req['login']
     e.set_footer(text="Notification preview")
     author_info = {
         "name": "{} is now live on Twitch!".format(req['display_name']),
         "url": e.url,
         "icon_url": req['profile_image_url']
     }
     e.set_author(**author_info)
     e.set_image(
         url=
         "https://images-ext-1.discordapp.net/external/FueXlfSkrjOeYMx92Qe3Y2AaV4G5dk9ijVlNGpF-AgU/https/static-cdn.jtvnw.net/previews-ttv/live_user_overwatchcontenders-1920x1080.jpg"
     )
     fmt_vars = {
         "$title$": "Stream Title",
         "$viewers$": "123",
         "$game$": "Game",
         "$url$": "https://twitch.tv/{}".format(req['login']),
         "$name$": req['display_name'],
         "$everyone$": "@everyone",
         "$here$": "@here"
     }
     msg = functions.ReplaceAllInStr(notif['message'], fmt_vars)
     msg = functions.ReplaceAllInStr(msg, {
         "@everyone": "@\u200beveryone",
         "@here": "@\u200bhere"
     })
     return await ctx.send(msg, embed=e)
示例#7
0
 async def game(self, ctx, *, name):
     try:
         await ctx.trigger_typing()
         msgs = await lang.get_lang(ctx)
         e = discord.Embed(color=discord.Color(0x6441A4))
         r = http.TwitchAPIRequest(
             "https://api.twitch.tv/helix/games/?name=" + name)
         r.raise_for_status()
         try:
             r = r.json()["data"][0]
         except IndexError:
             return await ctx.send(msgs['games']['no_results'])
         e.title = r["name"]
         e.description = f"[{msgs['games']['view_streams']}](https://www.twitch.tv/directory/game/{r['name'].replace(' ', '%20')})"
         e.set_thumbnail(url=r["box_art_url"].format(width=285, height=380))
         r2 = http.Games.IGDBSearchGame(name)
         rjson = r2.json()
         if r2.status_code != 200 or len(rjson) == 0:
             e.add_field(name=msgs['games']['game_details_title'],
                         value=msgs['games']['igdb_fetch_error'].format(
                             error=r2.status_code))
             e.set_footer(text=msgs['games']['game_id'].format(id=r['id']))
         else:
             rjson = rjson[0]
             ratings = round(rjson['rating'] / 10, 1)
             summary = rjson['summary'][:1000]
             if len(summary) == 1000:
                 summary += f"... {msgs['games']['info_cutoff']}"
             if ratings > 5:
                 rate_emoji = "\\👍"
             else:
                 rate_emoji = "\\👎"
             e.add_field(name=msgs['games']['game_rating']['name'],
                         value=msgs['games']['game_rating']['value'].format(
                             emoji=rate_emoji,
                             score=ratings,
                             count=rjson['rating_count']))
             e.add_field(name=msgs['games']['release_date'],
                         value=time.strftime(
                             '%B %d, %Y',
                             time.gmtime(rjson['first_release_date'])))
             e.add_field(name=msgs['games']['game_description'],
                         value=summary,
                         inline=False)
             e.description += f" • [{msgs['games']['view_on_igdb']}](https://www.igdb.com/games/{rjson['slug']})"
             e.set_footer(
                 text=
                 f"{msgs['games']['game_id'].format(id=r['id'])} • IGDB ID: {rjson['id']}"
             )
         await ctx.send(embed=e)
     except:
         await ctx.send(traceback.format_exc())
示例#8
0
 async def watch(self, ctx, *, user):
     await ctx.trigger_typing()
     msgs = await lang.get_lang(ctx)
     user = user.split('/')[-1]
     r = http.TwitchAPIRequest(
         "https://api.twitch.tv/helix/streams?user_login="******"data"] == []:
         await ctx.send(msgs['streams']['stream_not_found'])
     else:
         await ctx.send(
             f"**<:twitch:404633403603025921> {msgs['streams']['live']}**\nhttps://twitch.tv/{user}"
         )
示例#9
0
 async def trending(self, ctx):
     await ctx.trigger_typing()
     msgs = await lang.get_lang(ctx)
     r = http.TwitchAPIRequest(
         "https://api.twitch.tv/kraken/clips/top?limit=50")
     if r.status_code != 200:
         await ctx.send(f"{msgs['games']['generic_error']} {r.status_code}")
     elif len(r.json()['clips']) < 1:
         await ctx.send(msgs['clips']['no_clips'])
         return
     else:
         clip = choice(r.json()['clips'])
         m = await ctx.send(msgs['clips']['clip_message'].format(
             user=clip['broadcaster']['display_name'],
             game=clip['game'],
             url=clip['url'].split('?')[0]))
示例#10
0
 async def top(self, ctx, cnt: int = 10):
     await ctx.trigger_typing()
     msgs = await lang.get_lang(ctx)
     e = discord.Embed(color=discord.Color(0x6441A4),
                       title=msgs['games']['top_games'])
     r = http.TwitchAPIRequest(
         "https://api.twitch.tv/kraken/games/top?limit=10")
     r.raise_for_status()
     r = r.json()["top"]
     place = 1
     for game in r:
         e.add_field(inline=False,
                     name=f"`{place}.` {game['game']['name']}",
                     value=msgs['games']['top_games_desc'].format(
                         view_count=game['viewers'],
                         channel_count=game['channels']))
         place += 1
     await ctx.send(embed=e)
示例#11
0
 async def _from(self, ctx, twitch_user: str, *args):
     await ctx.trigger_typing()
     msgs = await lang.get_lang(ctx)
     twitch_user = twitch_user.split('/')[-1]
     if self.regex.match(twitch_user) is None:
         return await ctx.send(msgs['notifs']['malformed_user'])
     trending = ""
     if "--trending" in args:
         trending = "&trending=true"
     r = http.TwitchAPIRequest(
         "https://api.twitch.tv/kraken/clips/top?limit=50&channel=" +
         twitch_user + trending)
     if r.status_code != 200:
         await ctx.send(f"{msgs['games']['generic_error']} {r.status_code}")
     elif len(r.json()['clips']) < 1:
         await ctx.send(msgs['clips']['no_clips'])
         return
     else:
         clip = choice(r.json()['clips'])
         m = await ctx.send(msgs['clips']['clip_message'].format(
             user=clip['broadcaster']['display_name'],
             game=clip['game'],
             url=clip['url'].split('?')[0]))
示例#12
0
 async def remove(self,
                  ctx,
                  discord_channel: discord.TextChannel,
                  twitch_user: str = None,
                  *,
                  flags=""):
     """Deletes notifications for a Twitch user in the specified channel."""
     msgs = await lang.get_lang(ctx)
     flags = flags.split(" ")
     if not ctx.guild:
         return await ctx.send(msgs['permissions']['no_pm'])
     if not ctx.message.author.permissions_in(
             ctx.message.channel).manage_guild:
         return await ctx.send(msgs['permissions']['user_need_perm'].format(
             permission="Manage Server"))
     if twitch_user == None:
         notifs = r.table('notifications').filter(r.row['channel'].eq(
             str(discord_channel.id)))
         cnt = notifs.count().run(self.bot.rethink, durability="soft")
         await ctx.send(
             f":warning: {msgs['notifs']['bulk_delete_confirm']}".format(
                 count=cnt, channel=discord_channel.mention))
         try:
             m = await self.bot.wait_for(
                 'message',
                 check=lambda m: m.author.id == ctx.author.id and m.channel.
                 id == ctx.channel.id,
                 timeout=60)
             if not "yes" in m.clean_content.lower():
                 return await ctx.send(msgs['notifs']['command_cancelled'])
             notifs.delete().run(self.bot.rethink,
                                 durability="soft",
                                 noreply=True)
             return await ctx.send(
                 msgs['notifs']['bulk_delete_success'].format(
                     count=cnt, channel=discord_channel.mention))
         except asyncio.TimeoutError:
             return await ctx.send(msgs['notifs']['response_timeout'])
     else:
         username = twitch_user.split('/')[-1]
         if self.regex.match(username) is None:
             return await ctx.send(msgs['notifs']['malformed_user'])
         try:
             if not "--force-user-id" in flags:
                 s = http.TwitchAPIRequest(
                     "https://api.twitch.tv/helix/users?login="******"data": [{"id": twitch_user}]}
             r.table('notifications').filter(
                 (r.row['streamer'] == s['data'][0]['id'])
                 & (r.row['channel'] == str(discord_channel.id))).delete(
                 ).run(self.bot.rethink, durability="soft", noreply=True)
         except KeyError:
             await ctx.send(msgs['notifs']['del_fail'])
         except IndexError:
             await ctx.send(msgs['notifs']['del_fail'])
         except:
             await ctx.send(traceback.format_exc())
         else:
             await ctx.send(msgs['notifs']['del_success'].format(
                 channel=discord_channel.mention, user=username))
示例#13
0
 async def add(self,
               ctx,
               discord_channel: discord.TextChannel = None,
               twitch_user: str = None,
               *,
               msg: str = None):
     """Sets up notifications for a Twitch user in the specified channel."""
     msgs = await lang.get_lang(ctx)
     try:
         if not ctx.guild:
             return await ctx.send(msgs['permissions']['no_pm'])
         if not ctx.message.author.permissions_in(
                 ctx.message.channel).manage_guild:
             return await ctx.send(
                 msgs['permissions']['user_need_perm'].format(
                     permission="Manage Server"))
         await ctx.send(
             "**Notice:** The preferred method for adding notifications is now through the dashboard. We recommend that you use <https://dash.twitchbot.io> for a better experience."
         )
         prem_check = requests.get(
             f"https://api.twitchbot.io/premium/{ctx.author.id}",
             headers={"X-Auth-Key": settings.DashboardKey})
         if prem_check.json().get(
                 'premium') != True or prem_check.status_code != 200:
             channels = list(map(lambda c: str(c.id), ctx.guild.channels))
             serv_notifs = r.table('notifications').filter(
                 lambda obj: r.expr(channels).contains(obj[
                     'channel'])).count().run(self.bot.rethink,
                                              durability="soft")
             if serv_notifs > 25:
                 return await ctx.send(msgs['notifs']['limit_reached'])
         s = None
         username = None
         if discord_channel is None:
             await ctx.send(msgs['notifs']['prompt1'])
             try:
                 m = await self.bot.wait_for(
                     'message',
                     check=lambda m: m.channel == ctx.channel and m.author.
                     id == ctx.author.id,
                     timeout=60)
                 discord_channel = discord.utils.find(
                     lambda c: c.name.lower().startswith(
                         m.clean_content.strip("#").lower()),
                     ctx.guild.text_channels)
                 if discord_channel is None:
                     return await ctx.send(
                         msgs['notifs']['text_channel_not_found'])
             except asyncio.TimeoutError:
                 return await ctx.send(msgs['notifs']['response_timeout'])
         perms = discord_channel.permissions_for(ctx.guild.me)
         check_val = functions.CheckMultiplePerms(perms, "read_messages",
                                                  "send_messages",
                                                  "embed_links",
                                                  "external_emojis")
         if check_val != True:
             return await ctx.send(
                 msgs['permissions']['bot_need_perm'].format(
                     permission=check_val))
         if twitch_user == None:
             await ctx.send(msgs['notifs']['prompt2'])
             try:
                 m = await self.bot.wait_for(
                     'message',
                     check=lambda m: m.channel == ctx.channel and m.author.
                     id == ctx.author.id,
                     timeout=60)
                 username = m.content.split('/')[-1]
                 s = http.TwitchAPIRequest(
                     "https://api.twitch.tv/helix/users?login="******"data" not in s.json().keys():
                     return await ctx.send(
                         f"{msgs['games']['generic_error']} {s.status_code}"
                     )
                 elif len(s.json().get('data', {})) == 0:
                     return await ctx.send(
                         msgs['notifs']['twitch_user_not_found'])
                 elif s.status_code > 399:
                     return await ctx.send(
                         f"{msgs['games']['generic_error']} {s.status_code}"
                     )
             except asyncio.TimeoutError:
                 return await ctx.send(msgs['notifs']['response_timeout'])
         else:
             username = twitch_user.split('/')[-1]
             s = http.TwitchAPIRequest(
                 "https://api.twitch.tv/helix/users?login="******"{msgs['notifs']['invalid_data']} KeyError: f{str(e)}")
         except IndexError as e:
             return await ctx.send(
                 f"{msgs['notifs']['invalid_data']} IndexError: f{str(e)}")
         if self.regex.match(username) is None:
             return await ctx.send(msgs['notifs']['malformed_user'])
         if msg == None:
             await ctx.send(msgs['notifs']['prompt3'])
             try:
                 m = await self.bot.wait_for(
                     'message',
                     check=lambda m: m.channel == ctx.channel and m.author.
                     id == ctx.author.id,
                     timeout=180)
                 if m.content.lower() == 'default' or m.content.lower(
                 ) == '`default`':
                     msg = msgs['notifs']['default_msg'].format(
                         channel=username)
                 else:
                     msg = m.content
             except asyncio.TimeoutError:
                 return await ctx.send(msgs['notifs']['response_timeout'])
         try:
             object = {
                 "channel": str(discord_channel.id),
                 "streamer": s['id'],
                 "name": username,
                 "last_stream_id": None,
                 "message": msg
             }
             existing_notif = r.table('notifications').filter(
                 (r.row['streamer'] == s['id'])
                 & (r.row['channel'] == str(discord_channel.id)))
             if existing_notif.count().run(self.bot.rethink,
                                           durability="soft") == 0:
                 r.table('notifications').insert(object).run(
                     self.bot.rethink, durability="soft", noreply=True)
             else:
                 existing_notif.update(object).run(self.bot.rethink,
                                                   durability="soft")
             return await ctx.send(msgs['notifs']['add_success'].format(
                 user=username, channel=discord_channel.mention))
         except KeyError as e:
             return await ctx.send(
                 msgs['notifs']['twitch_user_not_found_alt'])
         except IndexError as e:
             return await ctx.send(
                 msgs['notifs']['twitch_user_not_found_alt'])
         except:
             raise
     except:
         await ctx.send(traceback.format_exc())
示例#14
0
 async def user(self, ctx, *, user):
     try:
         await ctx.trigger_typing()
         msgs = await lang.get_lang(ctx)
         user = user.split('/')[-1]
         if self.regex.match(user) is None:
             return await ctx.send(msgs['notifs']['malformed_user'])
         e = discord.Embed(color=discord.Color(0x6441A4))
         # get user info
         r = http.TwitchAPIRequest(
             "https://api.twitch.tv/helix/users?login="******"data") == [] or r.status_code == 400 or len(
                 r.json()['data']) == 0:
             return await ctx.send(
                 msgs['notifs']['twitch_user_not_found_alt'])
         r.raise_for_status()
         r = r.json()["data"][0]
         # get user streaming status
         s = http.TwitchAPIRequest(
             "https://api.twitch.tv/helix/streams?user_login="******"data"]
         # get user follows
         ft = http.TwitchAPIRequest(
             "https://api.twitch.tv/helix/users/follows?first=1&to_id=" +
             r['id'])
         ft.raise_for_status()
         # get user following
         ff = http.TwitchAPIRequest(
             "https://api.twitch.tv/helix/users/follows?first=1&from_id=" +
             r['id'])
         ff.raise_for_status()
         emote = self.badges.get(r['type'] or r['broadcaster_type'], '')
         e.set_author(icon_url=r["profile_image_url"],
                      name=r["display_name"],
                      url="https://twitch.tv/{}".format(r["login"]))
         e.set_thumbnail(url=r["profile_image_url"])
         e.title = r["login"] + emote
         e.description = r["description"]
         e.add_field(name=msgs['users']['followers'],
                     value="{:,}".format(ft.json()['total']))
         e.add_field(name=msgs['users']['following'],
                     value="{:,}".format(ff.json()['total']))
         e.add_field(name=msgs['users']['views'],
                     value="{:,}".format(r["view_count"]))
         if not s == []:
             s = s[0]
             # get stream tags
             t = http.TwitchAPIRequest(
                 f"https://api.twitch.tv/helix/streams/tags?broadcaster_id={r['id']}"
             )
             t.raise_for_status()
             tag_text = []
             for tag in t.json()['data']:
                 if not tag['is_auto']:
                     tag_text.append(
                         f"[{tag['localization_names']['en-us']}](https://www.twitch.tv/directory/all/tags/{tag['tag_id']})"
                     )
             if tag_text == []:
                 tag_text = ["No stream tags"]
             e.add_field(inline=False,
                         name=msgs['users']['tags'],
                         value=", ".join(tag_text))
             # get game info
             g = http.TwitchAPIRequest(
                 f"https://api.twitch.tv/helix/games?id={s['game_id']}")
             g.raise_for_status()
             try:
                 g = g.json()["data"][0]
             except:
                 g = {"name": msgs['users']['unknown']}
             e.add_field(
                 inline=False,
                 name=msgs['users']['live'],
                 value=f"**{s['title']}**\n" +
                 msgs['users']['playing'].format(
                     game=g['name'], view_count=s['viewer_count']) +
                 f"\n\n**[{msgs['users']['watch_on_twitch']}](https://twitch.tv/{user})**"
             )
             e.set_image(
                 url=s['thumbnail_url'].format(width=1920, height=1080) +
                 f"?{secrets.token_urlsafe(5)}")
         else:
             e.add_field(
                 inline=False,
                 name=msgs['users']['not_live'],
                 value=
                 f"[{msgs['users']['view_profile']}](https://twitch.tv/{user})"
             )
             e.set_image(url=r['offline_image_url'])
         e.set_footer(text=f"{msgs['users']['streamer_id']} {r['id']}")
         await ctx.send(embed=e)
     except:
         await ctx.send(traceback.format_exc())