async def user_card(bot, message, args, **kwargs): user = message.author if args: ids = get_user_ids(args) if ids: user = message.guild.get_member(int(ids[0])) or \ bot.get_user(int(ids[0])) if not user: raise Send_error('User was not found') embed = discord.Embed() embed.colour = discord.colour.Colour.blue() embed.title = user.display_name created = utils.seconds_to_pretty( (datetime.now() - user.created_at).total_seconds()) + ' ago' joined = utils.seconds_to_pretty((datetime.now()-user.joined_at).total_seconds()) + ' ago' \ if hasattr(user, 'joined_at') and user.joined_at else None embed.add_field(name='Created', value=created, inline=False) embed.add_field( name='Joined', value=joined if joined else 'Not a member of this server', inline=False, ) await message.channel.send(embed=embed) raise Send_break()
async def accountage(bot, user_id, display_name, args, **kwargs): uid = user_id user = display_name if len(args) > 0: user = utils.safe_username(args[0]) uid = await utils.twitch_lookup_user_id(bot.ahttp, bot.db, user) if not uid: uid = user_id user = display_name data = await utils.twitch_request( bot.ahttp, 'https://api.twitch.tv/helix/users', params={'id': uid}, ) if not data or not data['data']: raise Send_error('Found no data on {}'.format(user, )) created_at = parse(data['data'][0]['created_at']).replace(tzinfo=None) return { 'accountage': utils.seconds_to_pretty(dt1=datetime.utcnow(), dt2=created_at), 'accountage_date': created_at.strftime('%Y-%m-%d'), 'accountage_datetime': created_at.strftime('%Y-%m-%d %H:%M:%S UTC'), }
async def stream_watchtime(bot, channel_id, user_id, args, **kwargs): if len(args) > 0: user_id = await utils.twitch_lookup_user_id(bot.ahttp, bot.db, utils.safe_username(args[0])) r = await bot.db.fetchone( 'SELECT time FROM twitch_stream_watchtime WHERE channel_id=%s AND stream_id=%s AND user_id=%s', ( channel_id, bot.channels_check[channel_id]['stream_id'], user_id, ) ) time = 0 if r: time = r['time'] total_live_seconds = bot.channels_check[channel_id]['uptime'] usertime = time if (usertime > total_live_seconds) or ((total_live_seconds - usertime) <= 60): usertime = total_live_seconds p = 0 if total_live_seconds > 0: p = usertime / total_live_seconds return { 'user.stream_watchtime': utils.seconds_to_pretty(usertime), 'user.stream_watchtime_percent': '{:.0%}'.format(p), }
async def followage(bot, user_id, display_name, channel_id, channel, args, **kwargs): uid = user_id user = display_name if len(args) > 0: user = utils.safe_username(args[0]) uid = await utils.twitch_lookup_user_id(bot.ahttp, bot.db, user) if not uid: uid = user_id user = display_name data = await utils.twitch_request( bot.ahttp, 'https://api.twitch.tv/helix/users/follows', params={ 'from_id': uid, 'to_id': channel_id, }) if not data['data']: raise Send_error('{} does not follow {}'.format(user, channel)) followed_at = parse(data['data'][0]['followed_at']).replace(tzinfo=None) return { 'followage': utils.seconds_to_pretty(dt1=datetime.utcnow(), dt2=followed_at), 'followage_date': followed_at.strftime('%Y-%m-%d'), 'followage_datetime': followed_at.strftime('%Y-%m-%d %H:%M:%S UTC'), }
def user_info(prefix, user): return { f'{prefix}.id': user.id, f'{prefix}.name': user.name, f'{prefix}.display_name': user.display_name, f'{prefix}.mention': user.mention, f'{prefix}.created_at': user.created_at.isoformat()[0:19] + ' UTC', f'{prefix}.created_time_since': \ utils.seconds_to_pretty((datetime.now()-user.created_at).total_seconds()), f'{prefix}.joined_at': user.joined_at.isoformat()[0:19] + ' UTC' \ if hasattr(user, 'joined_at') and user.joined_at else 'Unknown', f'{prefix}.joined_time_since': \ utils.seconds_to_pretty((datetime.now()-user.joined_at).total_seconds()) \ if hasattr(user, 'joined_at') and user.joined_at else 'Unknown', }
async def countdown(bot, var_args, **kwargs): d = ' '.join(var_args['countdown']) try: dt = parse(d).astimezone(tz.UTC).replace(tzinfo=None) except ValueError: raise Send_error(f'Invalid date format: "{d}". Use ISO 8601 format.') return { 'countdown': utils.seconds_to_pretty(dt1=datetime.utcnow(), dt2=dt), }
async def permit_manager(bot, cmd, args, channel, channel_id, var_args, **kwargs): if len(args) < 1: raise Send_error('Invalid syntax, use: !{} <user>'.format(cmd)) user = utils.safe_username(args[0]) user_id = await utils.twitch_lookup_user_id(bot.ahttp, bot.db, user) if not user_id: raise Send_error('Unknown user') time = int(var_args['permit'][0]) if 'permit' in var_args and var_args['permit'] else 60 key = 'tbot:filter:permit:{}:{}'.format( channel_id, user_id, ) permit = await bot.redis.setex(key, time, '1') bot.send("PRIVMSG", target='#'+channel, message='@{}, you will not receive a timeout for the next {}'.format( user, utils.seconds_to_pretty(time) if time > 60 else '{} seconds'.format(time), )) raise Send_break()
async def channel_watchtime(bot, channel_id, user_id, args, **kwargs): if len(args) > 0: user_id = await utils.twitch_lookup_user_id(bot.ahttp, bot.db, utils.safe_username(args[0])) r = await bot.db.fetchone(''' SELECT sum(tw.time) as time, min(ts.started_at) as date FROM twitch_stream_watchtime tw, twitch_streams ts WHERE tw.channel_id=%s AND tw.user_id=%s AND tw.stream_id=ts.stream_id ''', ( channel_id, user_id, ) ) return { 'user.channel_watchtime': utils.seconds_to_pretty(r['time'] if r else 0), 'user.channel_watchtime_since': r['date'].strftime('%Y-%m-%d') if r else 'Unknown', }
async def cmd_bot(bot, nick, channel, channel_id, target, args, **kwargs): if len(args) == 0: return elif args[0].lower() == 'uptime': seconds = (datetime.utcnow() - bot.starttime).total_seconds() msg = '@{}, I\'ve been up for {}'.format( kwargs['display-name'], utils.seconds_to_pretty(seconds)) bot.send("PRIVMSG", target=target, message=msg) elif args[0].lower() == 'version': msg = '@{}, I\'m running version {}'.format( kwargs['display-name'], constants.VERSION, ) bot.send("PRIVMSG", target=target, message=msg) elif args[0].lower() == 'time': msg = '@{}, My time is {}Z'.format( kwargs['display-name'], datetime.utcnow().replace(microsecond=0).isoformat(), ) bot.send("PRIVMSG", target=target, message=msg)
async def tvshow(ctx, *, title): try: shows = await request('/shows', { 'title': title, }) if not shows: await ctx.send('No show matching the title "{}"'.format(title)) return show = shows[0] embed = discord.Embed() embed.colour = discord.colour.Colour.blue() embed.title = '{} ({})'.format(show['title'], show['premiered'][:4]) if show['poster_image']: embed.set_thumbnail(url=show['poster_image']['url']+'@.jpg') episodes = await request('/shows/{}/episodes'.format(show['id']), { 'q': 'air_date:>={}'.format(datetime.utcnow().date().isoformat()), 'per_page': 2, }) embed.description = '' if episodes: episode = episodes[0] just_aired = None airing = parse(episode['air_datetime']).replace(tzinfo=None) if datetime.utcnow().time() > airing.time(): episode = episodes[1] if len(episodes) > 1 else None just_aired = episodes[0] if just_aired: embed.description = 'Episode {} in season {} just aired {} ago.\n\n'.format( just_aired['episode'], just_aired['season'], utils.seconds_to_pretty( abs((airing - datetime.utcnow()).total_seconds()) ) ) if episode: embed.description = '**Next episode**: S{:02d}E{:02d} in {}.\n'.format( episode['season'], episode['episode'], utils.seconds_to_pretty( (parse(episode['air_datetime']).replace(tzinfo=None) - datetime.utcnow()).total_seconds() ) ) total_episodes = 0 for season in show['seasons']: total_episodes += season['total'] embed.description += '**Number of episodes**: {} ({} of watchtime).\n'.format( total_episodes, utils.seconds_to_pretty((total_episodes * show['runtime'])*60), ) if show['genres']: embed.description += '**Genres**: {}.\n'.format( ', '.join(show['genres']) ) await ctx.send(embed=embed) except: logging.exception('tvshow')
async def uptime(bot, channel_id, **kwargs): return { 'uptime': utils.seconds_to_pretty(bot.channels_check[channel_id]['uptime']) }
def test_seconds_to_pretty(self): self.assertEqual('0 seconds', utils.seconds_to_pretty(0)) self.assertEqual('1 second', utils.seconds_to_pretty(1)) self.assertEqual('30 seconds', utils.seconds_to_pretty(30)) self.assertEqual('1 minute', utils.seconds_to_pretty(60)) self.assertEqual('1 minute and 1 second', utils.seconds_to_pretty(61)) self.assertEqual('1 hour', utils.seconds_to_pretty(3600)) self.assertEqual('1 hour and 3 seconds', utils.seconds_to_pretty(3603)) self.assertEqual('1 hour and 1 minute', utils.seconds_to_pretty(3660)) self.assertEqual('1 hour and 2 minutes', utils.seconds_to_pretty(3720)) self.assertEqual('1 day', utils.seconds_to_pretty(3600 * 24)) self.assertEqual('1 day and 2 seconds', utils.seconds_to_pretty((3600 * 24) + 2)) self.assertEqual( '403 days and 1 hour', utils.seconds_to_pretty(13 * (31 * (3600 * 24)) + 3600 + 900)) dt = parse('2017-01-28T21:22:11Z').replace(tzinfo=None) now = datetime(2021, 1, 25, 17, 37, 0) self.assertEqual('3 years, 11 months and 27 days', utils.seconds_to_pretty(dt1=now, dt2=dt))