def test_get_user_chart_user_chart_does_not_exist(self): astrology_chart = AstrologyChart() AstrologyChartFactory() result = asyncio.run(astrology_chart.get_user_chart(98)) self.assertIsNone(result)
def test_calc_chart_invalid_time(self): astrology_chart = AstrologyChart() user_id = 14 date = '1997/08/10' time = 'invalid' city_name = "São Paulo" with self.assertRaises(AstrologyInvalidInput) as e: asyncio.run(astrology_chart.calc_chart(user_id, date, time, city_name)) self.assertIn('Invalid datetime', e.exception.message)
def test_calc_chart_invalid_city(self): astrology_chart = AstrologyChart() user_id = 14 date = '1997/08/10' time = '07:17' city_name = "InvalidCityForSure" with self.assertRaises(AstrologyInvalidInput) as e: asyncio.run(astrology_chart.calc_chart(user_id, date, time, city_name)) self.assertEqual(e.exception.message, 'City does not exist')
def test_get_user_chart_user_chart_exists(self): astrology_chart = AstrologyChart() user_id = 14 datetime = ('1997/08/10', '07:17', '-03:00') geopos = (-23.5506507, -46.6333824) chart = astrology_chart.calc_chart_raw(datetime, geopos) asyncio.run(astrology_chart.save_chart(user_id, chart)) result = asyncio.run(astrology_chart.get_user_chart(user_id)) self.assertEqual(str(chart.date), str(result.date)) self.assertEqual(str(chart.pos), str(result.pos))
def test_save_chart(self): user_id = 14 astrology_chart = AstrologyChart() datetime = ('1997/08/10', '07:17', '-03:00') geopos = (-23.5506507, -46.6333824) chart = astrology_chart.calc_chart_raw(datetime, geopos) result_id = asyncio.run(astrology_chart.save_chart(user_id, chart)) result = Session().query(AstrologyChartModel).get(result_id) self.assertIsNotNone(result) self.assertEqual(result.user_id, user_id) self.assertEqual(result.datetime.strftime( '%Y/%m/%d %H:%M'), f'{datetime[0]} {datetime[1]}') self.assertEqual(result.timezone, '-03:00:00') self.assertEqual(result.latitude, geopos[0]) self.assertEqual(result.longitude, geopos[1])
def test_get_user_profile_all_available_fields(self): user_1 = UserFactory(name='My very long name') user_2 = UserFactory() chess_game_1 = ChessGameFactory(player1=user_1, result=1) xp_point_1 = XpPointFactory(user=user_1, points=140) self.test_session.commit() astrology_bot = AstrologyChart() datetime = ('1997/08/10', '07:17', '-03:00') geopos = (-23.5506507, -46.6333824) chart = astrology_bot.calc_chart_raw(datetime, geopos) asyncio.run(astrology_bot.save_chart(user_1.id, chart)) with open(os.path.join('tests', 'support', 'user_avatar.png'), 'rb') as f: user_avatar_bytes = f.read() result = asyncio.run(Profile().get_user_profile(user_1.id, user_avatar_bytes, lang='pt')) with open( os.path.join('tests', 'support', 'get_user_profile_all_fields.png'), 'rb') as f: self.assertEqual(result.getvalue(), f.read())
def test_calc_chart_valid_params(self): astrology_chart = AstrologyChart() user_id = 14 date = '1997/08/10' time = '07:17' city_name = "São Paulo" chart = asyncio.run(astrology_chart.calc_chart(user_id, date, time, city_name)) sun = astrology_chart.get_sun_sign(chart) asc = astrology_chart.get_asc_sign(chart) moon = astrology_chart.get_moon_sign(chart) self.assertEqual(sun, 'Leo') self.assertEqual(asc, 'Leo') self.assertEqual(moon, 'Scorpio')
def __init__(self, client): self.client = client self.astrology_bot = AstrologyChart()
class AstrologyCog(commands.Cog): """ Astrologia """ def __init__(self, client): self.client = client self.astrology_bot = AstrologyChart() @commands.command() async def mapa_astral(self, ctx, date=None, time=None, *, city_name=None): """ Visualize ou crie via DM seu mapa astral Para criar seu mapa astral, envie esse comando em DM para o bot informando \ a data, hora e local de seu nascimento da seguinte forma: \ `YYYY/mm/dd HH:MM Nome da cidade`. Se já tiver criado seu mapa astral, envie esse comando sem argumentos para \ visualizá-lo em qualquer canal. Exemplo de uso para criação de mapa astral: `mapa_astral 2000/15/01 12:00 Brasília` Exemplo de uso para visualização de mapa criado: `mapa_astral` """ if not isinstance(ctx.channel, discord.channel.DMChannel): user_chart = await self.astrology_bot.get_user_chart(ctx.author.id) if not user_chart: return await ctx.send( i( ctx, 'You have not yet created your astrology chart. In order to do so, send this command to my DM 😁' )) return await self.send_astrology_triad(ctx, user_chart) try: await ctx.trigger_typing() chart = await self.astrology_bot.calc_chart( ctx.author.id, date, time, city_name) await self.astrology_bot.save_chart(ctx.author.id, chart) except AstrologyInvalidInput as e: return await ctx.send(i(ctx, e.message)) except Exception as e: logging.warning(e, exc_info=True) return await ctx.send( i( ctx, 'There has been a momentary failure. Please try again in a few moments. If this error persists, then this might be a bug 😬' )) await self.send_astrology_triad(ctx, chart) async def send_astrology_triad(self, ctx, chart): sign = self.astrology_bot.get_sun_sign(chart) asc = self.astrology_bot.get_asc_sign(chart) moon = self.astrology_bot.get_moon_sign(chart) embed = discord.Embed(title=i(ctx, 'Your astrology chart'), description=i(ctx, 'Your astrology triad'), colour=discord.Color.blurple(), timestamp=ctx.message.created_at) embed.add_field(name=i(ctx, 'Solar sign'), value=sign) embed.add_field(name=i(ctx, 'Ascending sign'), value=asc) embed.add_field(name=i(ctx, 'Moon sign'), value=moon) await ctx.send(embed=embed)
def __init__(self): self.astrology_bot = AstrologyChart()
class Profile(): def __init__(self): self.astrology_bot = AstrologyChart() async def set_user_profile_frame_color(self, user_id: int, color: str): """ Updates given user's profile frame color :param user_id: User id :type user_id: int :param color: Color in hex code :type color: str :return: Updated user :rtype: User :raises ValueError: Given color is invalid """ user = await User.get(user_id) or User(id=user_id) try: ImageColor.getcolor(color, 'RGB') except ValueError: raise user.profile_frame_color = color await User.save(user) return user async def get_user_profile(self, user_id: int, user_avatar: bytes, lang='en'): """ Generates an user profile image banner :param user_id: User id :type user_id: int :param user_avatar: User's avatar :type user_avatar: bytes :param lang: Language to which present the profile :type lang: str :return: User's profile banner :rtype: BytesIO """ text_max_width = 10 default_color = '#ca2222' user = await User.get(user_id, preload_profile_items=True) if not user: return user_name = user.name if user.name else '' user_profile_badges = [ item.profile_item for item in user.profile_items if item.equipped and item.profile_item.type == ProfileItemType.badge ] user_profile_wallpaper = next( (item.profile_item for item in user.profile_items if item.equipped and item.profile_item.type == ProfileItemType.wallpaper), None) user_chart = await self.astrology_bot.get_user_chart(user_id) user_sign = None if user_chart: user_sign = self.astrology_bot.get_sun_sign(user_chart) user_chess_victories = await ChessGame.get_number_of_victories(user_id) user_total_points = await XpPoint.get_user_aggregated_points(user_id) if not user_total_points: user_total_points = 0 with open(os.path.join('bot', 'images', 'profile_frame.png'), 'rb') as f: image_frame = Image.open(f).convert('RGBA') image_frame_draw = ImageDraw.Draw(image_frame) frame_color = ImageColor.getcolor( user.profile_frame_color or default_color, 'RGB') image_frame_draw.bitmap((0, 0), image_frame, fill=frame_color + (175, )) image_final = self._draw_wallpaper(image_frame, user_profile_wallpaper) image_font_title = ImageFont.truetype( os.environ.get("TRUETYPE_FONT_FOR_PROFILE"), size=48) image_font_subtitle = ImageFont.truetype( os.environ.get("TRUETYPE_FONT_FOR_PROFILE"), size=32) image_font_description = ImageFont.truetype( os.environ.get("TRUETYPE_FONT_FOR_PROFILE"), size=24) image_user_avatar = Image.open(BytesIO(user_avatar)) image_draw = ImageDraw.Draw(image_final) user_name_width = 390 image_frame_draw.rectangle([(0, 0), (user_name_width + 120, 107)], fill=frame_color + (255, )) image_final.alpha_composite(image_frame) image_draw.text((120, 25), user_name[:15], fill="#FFF", font=image_font_title) image_draw.text((30, 635), f'{i18n("Points", lang)}: {user_total_points}', fill="#FFF", font=image_font_description) image_draw.text((400, 620), f'{i18n("Chess wins", lang)}: {user_chess_victories}', fill="#FFF", font=image_font_subtitle) image_draw.text((400, 580), f'{i18n("Sign", lang)}: {user_sign}', fill="#FFF", font=image_font_subtitle) if image_user_avatar.mode == 'RGBA': user_avatar_mask = image_user_avatar.resize((108, 108)) else: user_avatar_mask = None image_final.paste(image_user_avatar.resize((108, 108)), (0, 0), mask=user_avatar_mask) image_final = self._draw_user_badges(image_final, user_profile_badges) bytesio = BytesIO() image_final.save(bytesio, format="png") bytesio.seek(0) return bytesio def _draw_wallpaper(self, image_frame, profile_item): image_bytes_io = profile_item and profile_item.get_file_contents() if not image_bytes_io: with open( os.path.join('bot', 'images', 'profile_default_background.jpg'), 'rb') as f: image_final = Image.open(f).crop( (100, 0, image_frame.size[0] + 100, image_frame.size[1])).convert('RGBA') else: image_final = Image.open(image_bytes_io).crop( (0, 0, image_frame.size[0], image_frame.size[1])).convert('RGBA').convert('RGBA') return image_final def _draw_user_badges(self, image, profile_items): for index, profile_item in enumerate(profile_items): image_bytes_io = profile_item.get_file_contents() if not image_bytes_io: continue image_badge = Image.open(image_bytes_io) image_badge_resized = image_badge.resize((60, 60)) x_position = 520 + index * 70 if image_badge_resized.mode == 'RGBA': image.paste(image_badge_resized, (x_position, 10), mask=image_badge_resized) else: image.paste(image_badge_resized, (x_position, 10)) return image