def str2glyphName(char): if char == ".point": char = "." codepoint = fontforge.unicodeFromName(char) if codepoint != -1: glyphName = fontforge.nameFromUnicode(codepoint) else: codes = codepoints.from_unicode(char) if len(codes) == 1: glyphName = fontforge.nameFromUnicode(codes[0]) else: glyphName = char return glyphName
async def _phase2(message): response = await self.bot.wait_for('message', timeout=120, check=check) content = response.content.strip() if response.content.lower().strip() == 'skip': return True if response.content.lower().strip() == 'reset': db.update_one({'_id': ctx.author.id}, {'$set': { 'regionFlag': None }}) await message.channel.send( 'I\'ve gone ahead and reset your setting for **regional flag**' ) return True for x in content: if x not in UNICODE_EMOJI: return False rawPoints = tuple(codepoints.from_unicode(content)) points = [] for x in rawPoints: if ( str(hex(x)[2:]) not in self.letterCodepoints ): # Flags are the 2 letter abbrev. in regional letter emoji return False points.append(str(hex(x)[2:])) pointStr = '-'.join(points) if not Path(f'{self.twemojiPath}{pointStr}.png').is_file(): return False db.update_one({'_id': ctx.author.id}, {'$set': { 'regionFlag': pointStr }}) return True
def test_to_and_from_unicode(unistr, code_points): assert_equal(code_points, tuple(codepoints.from_unicode(unistr))) assert_equal(unistr, codepoints.to_unicode(code_points))
async def _generate_profile_card(self, member: discord.Member) -> discord.File: db = mclient.bowser.users fs = gridfs.GridFS(mclient.bowser) dbUser = db.find_one({'_id': member.id}) guild = member.guild metaFont = ImageFont.truetype('resources/OpenSans-Regular.ttf', 36) userFont = ImageFont.truetype('resources/OpenSans-Regular.ttf', 48) subtextFont = ImageFont.truetype('resources/OpenSans-Light.ttf', 48) mediumFont = ImageFont.truetype('resources/OpenSans-Light.ttf', 36) smallFont = ImageFont.truetype('resources/OpenSans-Light.ttf', 30) # Start construction of key features pfp = (Image.open( io.BytesIO(await member.avatar_url_as( format='png', size=256).read())).convert("RGBA").resize( (250, 250))) pfpBack = Image.open('resources/pfp-background.png').convert('RGBA') pfpBack.paste(pfp, (50, 170), pfp) card = Image.open('resources/profile-{}.png'.format( dbUser['background'])).convert("RGBA") pfpBack.paste(card, mask=card) card = pfpBack snoo = Image.open('resources/snoo.png').convert("RGBA") trophyUnderline = Image.open( 'resources/trophy-case-underline.png').convert("RGBA") gameUnderline = Image.open( 'resources/favorite-games-underline.png').convert("RGBA") card.paste(snoo, (50, 50), snoo) card.paste(trophyUnderline, (1150, 100), trophyUnderline) card.paste(gameUnderline, (60, 645), gameUnderline) # Start header/static text draw = ImageDraw.Draw(card) draw.text((150, 50), '/r/NintendoSwitch Discord', (45, 45, 45), font=metaFont) draw.text((150, 90), 'User Profile', (126, 126, 126), font=metaFont) draw.text((60, 470), 'Member since', (126, 126, 126), font=smallFont) draw.text((440, 470), 'Messages sent', (126, 126, 126), font=smallFont) draw.text((800, 470), 'Timezone', (126, 126, 126), font=smallFont) draw.text((60, 595), 'Favorite games', (45, 45, 45), font=mediumFont) # draw.text((800, 600), 'Looking for group', (126, 126, 126), font=smallFont) # TODO: Find a way to see if game is online enabled draw.text((1150, 45), 'Trophy case', (45, 45, 45), font=mediumFont) # Start customized content -- userinfo memberName = '' nameW = 350 nameH = 0 for char in member.name: if char not in UNICODE_EMOJI: memberName += char else: if memberName: W, nameH = draw.textsize(memberName, font=userFont) draw.text((nameW, 215), memberName, (80, 80, 80), font=userFont) nameW += W memberName = '' charset = tuple(codepoints.from_unicode(char)) unicodePoint = [] for x in charset: unicodePoint.append(hex(x)[2:]) unicodeChar = '-'.join(unicodePoint) emojiPic = Image.open(self.twemojiPath + unicodeChar + '.png').convert('RGBA').resize((40, 40)) card.paste(emojiPic, (nameW + 3, 228), emojiPic) nameW += 46 if memberName: # Leftovers, text draw.text((nameW, 215), memberName, (80, 80, 80), font=userFont) draw.text((350, 275), '#' + member.discriminator, (126, 126, 126), font=subtextFont) if dbUser['regionFlag']: regionImg = Image.open(self.twemojiPath + dbUser['regionFlag'] + '.png').convert('RGBA') card.paste(regionImg, (976, 50), regionImg) # Friend code if dbUser['friendcode']: draw.text((350, 330), dbUser['friendcode'], (87, 111, 251), font=subtextFont) # Start customized content -- stats draw.text( (440, 505), f'{mclient.bowser.messages.find({"author": member.id}).count():,}', (80, 80, 80), font=mediumFont, ) joins = dbUser['joins'] joins.sort() joinDate = datetime.datetime.utcfromtimestamp(joins[0]) try: # -d doesn't work on all platforms, such as Windows joinDateF = joinDate.strftime('%b. %-d, %Y') except: joinDateF = joinDate.strftime('%b. %d, %Y') draw.text((60, 505), joinDateF, (80, 80, 80), font=mediumFont) if not dbUser['timezone']: draw.text((800, 505), 'Not specified', (126, 126, 126), font=mediumFont) else: tzOffset = datetime.datetime.now(pytz.timezone( dbUser['timezone'])).strftime('%z') draw.text((800, 505), 'GMT' + tzOffset, (80, 80, 80), font=mediumFont) # Start trophies trophyLocations = { 0: (1150, 150), 1: (1300, 150), 2: (1450, 150), 3: (1150, 300), 4: (1300, 300), 5: (1450, 300), 6: (1150, 450), 7: (1300, 450), 8: (1450, 450), 9: (1150, 600), 10: (1300, 600), 11: (1450, 600), 12: (1150, 750), 13: (1300, 750), 14: (1450, 750), } trophies = [] if dbUser['trophyPreference']: for x in dbUser: trophies.append(x) # Hardcoding IDs like a genius if member.id == guild.owner.id: # Server owner trophies.append('owner') if member.id in self.bot_contributors: # Developer trophies.append('developer') if guild.get_role(config.chatmod) in member.roles: # Chat-mod role trophies.append('chat-mod') if guild.get_role(config.submod) in member.roles: # Sub-mod role trophies.append('sub-mod') if (guild.get_role(config.modemeritus) in member.roles or guild.get_role( config.submodemeritus) in member.roles): # Mod emeritus trophies.append('mod-emeritus') if guild.get_role(config.helpfulUser) in member.roles: # Helpful user trophies.append('helpful-user') if guild.get_role(config.boostRole) in member.roles: # Booster role trophies.append('booster') if len(trophies) < 15: # Check for additional non-prefered trophies for x in dbUser['trophies']: if x not in trophies: trophies.append(x) while len(trophies) < 15: trophies.append('blank') trophyNum = 0 for x in trophies: trophyBadge = Image.open('resources/trophies/' + x + '.png').convert('RGBA') card.paste(trophyBadge, trophyLocations[trophyNum], trophyBadge) trophyNum += 1 # Start favorite games setGames = dbUser['favgames'] if not setGames: draw.text((60, 665), 'Not specified', (126, 126, 126), font=mediumFont) else: gameIconLocations = {0: (60, 665), 1: (60, 730), 2: (60, 795)} gameTextLocations = {0: 660, 1: 725, 2: 791} gameCount = 0 gamesDb = mclient.bowser.games for game in setGames: gameDoc = gamesDb.find_one({'_id': game}) if fs.exists(game): gameImg = fs.get(game) gameIcon = Image.open(gameImg).convert('RGBA').resize( (45, 45)) card.paste(gameIcon, gameIconLocations[gameCount], gameIcon) else: missingImage = Image.open( 'resources/missing-game.png').convert("RGBA").resize( (45, 45)) card.paste(missingImage, gameIconLocations[gameCount], missingImage) if gameDoc['titles']['NA']: gameName = gameDoc['titles']['NA'] elif gameDoc['titles']['EU']: gameName = gameDoc['titles']['EU'] else: gameName = gameDoc['titles']['JP'] nameW = 120 nameWMax = 950 for char in gameName: if nameW >= nameWMax: draw.text((nameW, gameTextLocations[gameCount]), '...', (80, 80, 80), font=mediumFont) break draw.text((nameW, gameTextLocations[gameCount]), char, (80, 80, 80), font=mediumFont) nameW += mediumFont.getsize(char)[0] gameCount += 1 bytesFile = io.BytesIO() card.save(bytesFile, format='PNG') return discord.File(io.BytesIO(bytesFile.getvalue()), filename='profile.png')
import codepoints import sys if len(sys.argv) != 3: print 'provide file and emoji' exit() filename = sys.argv[1] c = sys.argv[2] svgfile = hex(tuple(codepoints.from_unicode(c.decode('utf-8')))[0]).upper().replace('0X', 'u') + '.svg' print 'looking for', svgfile for line in open(filename, 'r').readlines(): if svgfile in line: print line.split(':')[1].strip()
async def _generate_profile_card(self, member: discord.Member) -> discord.File: db = mclient.bowser.users dbUser = db.find_one({'_id': member.id}) if 'default' in dbUser['backgrounds']: backgrounds = list(dbUser['backgrounds']) backgrounds.remove('default') backgrounds.insert(0, 'default-dark') backgrounds.insert(0, 'default-light') db.update_one({'_id': member.id}, {'$set': { 'backgrounds': backgrounds }}) if dbUser['background'] == 'default': db.update_one({'_id': member.id}, {'$set': { 'background': 'default-light' }}) dbUser = db.find_one({'_id': member.id}) background = self.backgrounds[dbUser['background']] theme = self.themes[background["theme"]] pfpBytes = io.BytesIO(await member.avatar_url_as(format='png', size=256).read()) pfp = Image.open(pfpBytes).convert("RGBA").resize((250, 250)) card = theme['pfpBackground'].copy() card.paste(pfp, (50, 170), pfp) card.paste(background["image"], mask=background["image"]) card.paste(theme['profileStatic'], mask=theme['profileStatic']) guild = member.guild draw = ImageDraw.Draw(card) fonts = self.profileFonts # userinfo memberName = '' nameW = 350 # Member name may be rendered in parts, so we want to ensure the font stays the same for the entire thing member_name_font = fonts['user'][self._determine_cjk_font(member.name)] for char in member.name: if char not in emoji_data.EmojiSequence: memberName += char else: if memberName: W, _ = draw.textsize(memberName, font=member_name_font) draw.text((nameW, 215), memberName, tuple(theme["primary"]), member_name_font) nameW += W memberName = '' charset = tuple(codepoints.from_unicode(char)) unicodePoint = [] for x in charset: unicodePoint.append(hex(x)[2:]) unicodeChar = '-'.join(unicodePoint) emojiPic = Image.open(self.twemojiPath + unicodeChar + '.png').convert('RGBA').resize((40, 40)) card.paste(emojiPic, (nameW + 3, 228), emojiPic) nameW += 46 if memberName: # Leftovers, text draw.text((nameW, 215), memberName, tuple(theme["primary"]), member_name_font) self._draw_text(draw, (350, 275), '#' + member.discriminator, theme["secondary"], fonts['subtext']) if dbUser['regionFlag']: regionImg = self._cache_flag_image(dbUser['regionFlag']) card.paste(regionImg, (976, 50), regionImg) # Friend code if dbUser['friendcode']: self._draw_text(draw, (350, 330), dbUser['friendcode'], theme["friend_code"], fonts['subtext']) # Start customized content -- stats message_count = f'{mclient.bowser.messages.find({"author": member.id}).count():,}' self._draw_text(draw, (435, 505), message_count, theme["primary"], fonts['medium']) joins = dbUser['joins'] joins.sort() joinDate = datetime.datetime.utcfromtimestamp(joins[0]) try: # -d doesn't work on all platforms, such as Windows joinDateF = joinDate.strftime('%b. %-d, %Y') except: joinDateF = joinDate.strftime('%b. %d, %Y') self._draw_text(draw, (60, 505), joinDateF, theme["primary"], fonts['medium']) if not dbUser['timezone']: self._draw_text(draw, (790, 505), 'Not specified', theme["secondary"], fonts['medium']) else: tznow = datetime.datetime.now(pytz.timezone(dbUser['timezone'])) localtime = tznow.strftime('%H:%M') tzOffset = tznow.strftime('%z') if tzOffset[-2:] == '00': # Remove 00 at end, if present tzOffset = tzOffset[:-2] if tzOffset[1] == '0': # Remove 0 at start of ±0X, if present tzOffset = tzOffset[0] + tzOffset[2:] self._draw_text(draw, (790, 505), f'{localtime} (UTC{tzOffset})', theme["primary"], fonts['medium']) # Start trophies trophyLocations = { 0: (1150, 150), 1: (1300, 150), 2: (1450, 150), 3: (1150, 300), 4: (1300, 300), 5: (1450, 300), 6: (1150, 450), 7: (1300, 450), 8: (1450, 450), 9: (1150, 600), 10: (1300, 600), 11: (1450, 600), 12: (1150, 750), 13: (1300, 750), 14: (1450, 750), } trophies = [] if dbUser['trophyPreference']: for x in dbUser: trophies.append(x) for trophy, lambda_function in self.special_trophies.items(): if lambda_function(member, guild): trophies.append(trophy) if len(trophies) < 15: # Check for additional non-prefered trophies for x in dbUser['trophies']: if x not in trophies: trophies.append(x) while len(trophies) < 15: trophies.append(None) trophyNum = 0 useBorder = None for x in trophies: if useBorder is None and x in self.borders['trophy_borders']: useBorder = self.borders['trophy_borders'][x] trophyBadge = self._cache_trophy_image(x, background["theme"]) card.paste(trophyBadge, trophyLocations[trophyNum], trophyBadge) trophyNum += 1 # border! useBorder = useBorder or self.borders['default'] border = self._cache_border_image(useBorder) card.paste(border, (0, 0), border) # Start favorite games setGames = dbUser['favgames'] gameCount = 0 Games = self.bot.get_cog('Games') if setGames: gameIconLocations = {0: (60, 665), 1: (60, 730), 2: (60, 795)} gameTextLocations = {0: 660, 1: 725, 2: 791} gamesDb = mclient.bowser.games setGames = list(dict.fromkeys( setGames)) # Remove duplicates from list, just in case setGames = setGames[:3] # Limit to 3 results, just in case for game_guid in setGames: if not Games: continue gameName = Games.get_preferred_name(game_guid) if not gameName: continue gameIcon = await self._cache_game_img(gamesDb, game_guid, theme) card.paste(gameIcon, gameIconLocations[gameCount], gameIcon) nameW = 120 nameWMax = 950 game_name_font = fonts['medium'][self._determine_cjk_font( gameName)] for char in gameName: if nameW >= nameWMax: draw.text((nameW, gameTextLocations[gameCount]), '...', tuple(theme["primary"]), font=game_name_font) break draw.text((nameW, gameTextLocations[gameCount]), char, tuple(theme["primary"]), font=game_name_font) nameW += game_name_font.getsize(char)[0] gameCount += 1 if gameCount == 0: # No games rendered self._draw_text(draw, (60, 665), 'Not specified', theme["secondary_heading"], fonts['medium']) bytesFile = io.BytesIO() card.save(bytesFile, format='PNG') return discord.File(io.BytesIO(bytesFile.getvalue()), filename='profile.png')