async def ti_gethours(self, ctx, user): member = ctx.message.mentions[0] sender = ctx.message.author if config.get_timein_channel( ) is not None and ctx.message.channel.id == config.get_timein_channel( ): if (config.get_payday() is None) or (config.get_user_val( member, 'pay_rate') is None): await sender.send( '[Error] Please define a pay day and a pay rate for the user.' ) else: time_raw = ctx.message.created_at time = await self.get_time(member, time_raw) time_sum = 0 async for message in self.bot.get_channel( config.get_timein_channel()).history( limit=self.MESSAGE_LIMIT): if await self.valid_calc(member, message, time): time_sum += await self.get_timein_hours(message) await sender.send( member.display_name + ' has timed in: ' + str(time_sum) + ' hours and has earned: $' + str(config.get_user_val(member, 'pay_rate') * time_sum) + ' this pay period.') await member.send( '[Announcement] A time in report is being generated. Please notify an admin if you are currently timed in or your time ins are incorrect.' ) await ctx.message.delete() else: await sender.send( '[Error] Time in commands can only be run in the time in channel.' ) await ctx.message.delete()
async def ti_cont(self, ctx): member = ctx.message.author # If time in channel has not been set if config.get_timein_channel( ) is None or ctx.message.channel.id != config.get_timein_channel(): await member.send( '[Error] Time in commands can only be run in the time in channel.' ) await ctx.message.delete() # If member has not defined a timezone elif config.get_user_val(member, 'time_zone') is None: await member.send( '[Error] Please define your timezone: .set_timezone <zone_num>\n' 'Example: .set_timezone 1 \n \n' 'To find your timezone: .search_timezone <args>\n' 'Example: .search_timezone Pacific US') await ctx.message.delete() # If member is already timed in elif await self.is_timed_in(member): await member.send('[Error] You already have an' ' active time in.') await ctx.message.delete() # Member can time in else: task = await self.get_timein_task(member) time_raw = ctx.message.created_at time = await self.get_time(member, time_raw) await self.time_in(member, task, time) await ctx.message.delete()
async def time_in(self, member, task, time): emote = config.get_user_val(member, 'emote') emote_id = await self.get_emote_id(emote) emote_display = '<:' + emote + ':' + str(emote_id) + '>' if emote_id is None: emote_display = ':' + emote + ':' last_timein = await self.check_timein(member, time) # New time in for the day if last_timein is None: ti_message = '----------------------- \n' ti_message += (emote_display + ' ' + member.display_name + ' ' + emote_display) ti_message += '\n----------------------- \n*' + time.strftime( "%B %d, %Y") + '*' identifier = await self.get_identifier(member) task_message = '\n [' + identifier + '] ' + task + ' {' + time.strftime( "%H:%M") + ' - ???}' await self.bot.get_channel(config.get_timein_channel() ).send(ti_message + task_message) # Add on to an existing time in else: identifier = await self.get_identifier(member) updated_timein = last_timein.content + '\n [' + identifier + '] ' + task + ' {' + time.strftime( "%H:%M") + ' - ???}' await last_timein.edit(content=updated_timein)
async def get_identifier(self, member): key = self.random_string(5) if key in config.get_user_val(member, 'used_identifiers'): await self.get_identifier(member) else: config.add_indentifier(member, key) return key
async def check_pay(self): for member in self.bot.get_channel( config.get_timein_channel()).members: if member.id != self.bot.user.id: if (config.get_user_val(member, 'pay_rate') is None) and ( member.id not in config.get_timein_exclusions()): return False return True
async def timein(self, ctx, *description): member = ctx.message.author task = ' '.join(description) # if there is no description if len(description) <= 0: await member.send('[Error] Please include a timein description.') await ctx.message.delete() # If description is too long elif len(task) > 65: await member.send('[Error] Timein description is too long.') await ctx.message.delete() # If time in channel has not been set elif config.get_timein_channel( ) is None or ctx.message.channel.id != config.get_timein_channel(): await member.send( '[Error] Time in commands can only be run in the time in channel.' ) await ctx.message.delete() # If member has not defined a timezone elif config.get_user_val(member, 'time_zone') is None: await member.send( '[Error] Please define your timezone: .set_timezone <zone_num>\n' 'Example: .set_timezone 1 \n \n' 'To find your timezone: .search_timezone <args>\n' 'Example: .search_timezone Pacific US') await ctx.message.delete() # If member is already timed in elif await self.is_timed_in(member): await member.send('[Error] You already have an' ' active time in.') await ctx.message.delete() # Member has invalid characters elif not await self.message_valid(task): await member.send( '[Error] Invalid characters in time in description.') await ctx.message.delete() # Member can time in else: time_raw = ctx.message.created_at time = await self.get_time(member, time_raw) await self.time_in(member, task, time) await ctx.message.delete()
async def ti_manual(self, ctx, user, in_date, in_time, out_time, *description): member = ctx.message.mentions[0] sender = ctx.message.author if config.get_timein_channel( ) is not None and ctx.message.channel.id == config.get_timein_channel( ): date = datetime.datetime.strptime(in_date, '%m-%d-%Y') in_time_raw = datetime.datetime.strptime(in_time, '%H:%M') out_time_raw = datetime.datetime.strptime(out_time, '%H:%M') task = ' '.join(description) # if there is no description if len(description) <= 0: await sender.send( '[Error] Please include a timein description.') await ctx.message.delete() # If description is too long elif len(task) > 65: await member.send('[Error] Timein description is too long.') await ctx.message.delete() # Member has invalid characters elif not await self.message_valid(task): await sender.send( '[Error] Invalid characters in time in description.') await ctx.message.delete() # Check if time range is valid elif not await self.valid_range(in_time_raw, out_time_raw): await sender.send( '[Error] Time in time must be before time out time.') await ctx.message.delete() else: # See if time in already exists async for message in self.bot.get_channel( config.get_timein_channel()).history( limit=self.MESSAGE_LIMIT): curr_message = message.content # User has already timed in on this date if await self.valid_timein_user( message, member.display_name) and ( date.strftime("%B %d, %Y") in curr_message): identifier = await self.get_identifier(member) curr_message += '\n [' + identifier + '] ' + task + ' {' + in_time_raw.strftime( "%H:%M") + ' - ' + out_time_raw.strftime( "%H:%M") + '}' await message.edit(content=curr_message) await ctx.message.delete() return # User has not timed in on this date emote = config.get_user_val(member, 'emote') emote_id = await self.get_emote_id(emote) emote_display = '<:' + emote + ':' + str(emote_id) + '>' if emote_id is None: emote_display = ':' + emote + ':' ti_message = '----------------------- \n' ti_message += (emote_display + ' ' + member.display_name + ' ' + emote_display) ti_message += '\n----------------------- \n*' + date.strftime( "%B %d, %Y") + '*' identifier = await self.get_identifier(member) task_message = '\n [' + identifier + '] ' + task + ' {' + in_time_raw.strftime( "%H:%M") + ' - ' + out_time_raw.strftime("%H:%M") + '}' await self.bot.get_channel(config.get_timein_channel() ).send(ti_message + task_message) await ctx.message.delete() else: await sender.send( '[Error] Time in commands can only be run in the time in channel.' ) await ctx.message.delete()
async def timein_report(self, time): pay_day = config.get_payday() curr_month = time.month curr_day = time.day curr_year = time.year start_month = 0 start_year = curr_year start_day = pay_day end_month = 0 end_year = curr_year end_day = pay_day - 1 timein_users = await self.timein_users() # It is before pay day if curr_day < pay_day: end_month = curr_month - 1 start_month = curr_month - 2 # Account for new year if curr_month == 1: start_year -= 1 end_year -= 1 start_month = 11 end_month = 12 # Account for new year February elif curr_month == 2: start_year -= 1 start_month = 12 end_month = 1 # It is payday or after the pay day else: end_month = curr_month start_month = curr_month - 1 # Account for new year if curr_month == 1: start_year -= 1 start_month = 12 # Compute start and end date start_date = datetime.datetime(start_year, start_month, start_day) end_date = datetime.datetime(end_year, end_month, end_day) timeins = await self.timein_dic(start_date, end_date) # Write file name file_name = start_date.strftime("%d-%b-%Y") + '_' + end_date.strftime( "%d-%b-%Y") file = 'reports/' + file_name + '.xlsx' # Create workbook workbook = xlsxwriter.Workbook(file) worksheet = workbook.add_worksheet() # Header format header = workbook.add_format({ 'bold': True, 'border': 2, 'align': 'center' }) cell = workbook.add_format({'border': 1, 'align': 'center'}) # Write header worksheet.write(0, 0, "DATE", header) for i in range(0, len(timein_users)): worksheet.write(0, i + 1, timein_users[i].display_name.upper(), header) # Write dates in column day_row = 1 for day in self.daterange(start_date, end_date): worksheet.write(day_row, 0, day.strftime("%d %b, %Y"), cell) day_row += 1 user_count = 1 # Add timein hours for user in timein_users: user_timeins = timeins[user.display_name] for i in range(0, len(user_timeins)): worksheet.write(i + 1, user_count, str(user_timeins[i])[0:8], cell) # Write total hours total_time = 0 for time in user_timeins: total_time += time worksheet.write( len(user_timeins) + 1, user_count, str(total_time)[0:8], header) pay_rate = config.get_user_val(user, 'pay_rate') worksheet.write(day_row + 1, user_count, pay_rate, header) print("Name: " + user.display_name + ", Pay Rate: " + str(pay_rate) + ", Total Time: " + str(total_time)) worksheet.write(day_row + 2, user_count, str(pay_rate * total_time)[0:8], header) user_count += 1 # Write footer worksheet.write(day_row, 0, 'TOTAL', header) worksheet.write(day_row + 1, 0, 'PAY RATE', header) worksheet.write(day_row + 2, 0, 'INCOME', header) # Set width of first column worksheet.set_column(0, 0, 15) workbook.close() return file
async def get_time(self, member, time): convert_zone = pytz.timezone(config.get_user_val(member, 'time_zone')) return pytz.utc.localize(time, is_dst=None).astimezone(convert_zone)