From 3a77af3e79ed08db95b2e6940bc138567bfdb621 Mon Sep 17 00:00:00 2001 From: Tarun Kumar Date: Tue, 3 Nov 2020 20:25:54 +0500 Subject: [PATCH 001/355] Fix Yahoo search parser Yahoo search apparently parses "500.0" as 5000 which results in an inaccurate conversion as the module parses amount as float by default. Closes https://github.com/albertlauncher/albert/issues/917 --- currency_converter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/currency_converter.py b/currency_converter.py index 907b2982..ad8e32db 100644 --- a/currency_converter.py +++ b/currency_converter.py @@ -58,6 +58,8 @@ def __init__(self): self.name = "Yahoo" def convert(self, amount, src, dst): + if amount.is_integer: + amount = int(amount) url = 'https://search.yahoo.com/search?p=%s+%s+to+%s' % (amount, src, dst) with urlopen(url) as response: html = response.read().decode() From 0850bc5e0793914d47b15c318e8545bda4931629 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 4 Nov 2020 15:56:03 +0100 Subject: [PATCH 002/355] [dango] Archive dango extensions As discussed in https://github.com/albertlauncher/albert/issues/921 --- {dango_emoji => .archive/dango_emoji}/__init__.py | 0 .../dango_emoji}/dangoemoji.png | Bin {dango_kao => .archive/dango_kao}/__init__.py | 0 {dango_kao => .archive/dango_kao}/kaoicon.svg | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {dango_emoji => .archive/dango_emoji}/__init__.py (100%) rename {dango_emoji => .archive/dango_emoji}/dangoemoji.png (100%) rename {dango_kao => .archive/dango_kao}/__init__.py (100%) rename {dango_kao => .archive/dango_kao}/kaoicon.svg (100%) diff --git a/dango_emoji/__init__.py b/.archive/dango_emoji/__init__.py similarity index 100% rename from dango_emoji/__init__.py rename to .archive/dango_emoji/__init__.py diff --git a/dango_emoji/dangoemoji.png b/.archive/dango_emoji/dangoemoji.png similarity index 100% rename from dango_emoji/dangoemoji.png rename to .archive/dango_emoji/dangoemoji.png diff --git a/dango_kao/__init__.py b/.archive/dango_kao/__init__.py similarity index 100% rename from dango_kao/__init__.py rename to .archive/dango_kao/__init__.py diff --git a/dango_kao/kaoicon.svg b/.archive/dango_kao/kaoicon.svg similarity index 100% rename from dango_kao/kaoicon.svg rename to .archive/dango_kao/kaoicon.svg From 1c980ab3d0ef1ac755db124aeea80649b777b6be Mon Sep 17 00:00:00 2001 From: Andreas Dominik Preikschat Date: Wed, 4 Nov 2020 20:01:52 +0100 Subject: [PATCH 003/355] [timer] add optional timer names (#85) --- timer/__init__.py | 50 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/timer/__init__.py b/timer/__init__.py index bdbd7f42..a2cb44d6 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -2,12 +2,12 @@ """Set up timers. -Lists all timers when triggered. Additional arguments in the form of [[hours:]minutes:]seconds let \ -you set triggers. Empty field resolve to 0, e.g. "96::" starts a 96 hours timer. Fields exceeding \ -the maximum amount of the time interval are automatically refactorized, e.g. "9:120:3600" resolves \ -to 12 hours. +Lists all timers when triggered. Additional arguments in the form of "[[hours:]minutes:]seconds +[name]" let you set triggers. Empty field resolve to 0, e.g. "96::" starts a 96 hours timer. +Fields exceeding the maximum amount of the time interval are automatically refactorized, e.g. +"9:120:3600" resolves to 12 hours. -Synopsis: [[[hours]:][minutes]:]seconds""" +Synopsis: [[[hours]:][minutes]:]seconds [name]""" from albertv0 import * from threading import Timer @@ -17,9 +17,9 @@ __iid__ = "PythonInterface/v0.1" __prettyname__ = "Timer" -__version__ = "1.0" +__version__ = "1.1" __trigger__ = "timer " -__author__ = "Manuel Schneider" +__author__ = "Manuel Schneider, Andreas Preikschat" __dependencies__ = [] iconPath = os.path.dirname(__file__)+"/time.svg" @@ -29,23 +29,29 @@ class AlbertTimer(Timer): - def __init__(self, interval): + def __init__(self, interval, name): def timeout(): subprocess.Popen(["aplay", soundPath]) global timers timers.remove(self) + subtext="Timed out at %s" % strftime("%X", localtime(self.end)) + if self.name: + subprocess.Popen(['notify-send', 'Timer "%s"' % self.name, '-t', '0', subtext]) + else: + subprocess.Popen(['notify-send', 'Timer', '-t', '0', subtext]) super().__init__(interval=interval, function=timeout) self.interval = interval + self.name = name self.begin = int(time()) self.end = self.begin + interval self.start() -def startTimer(interval): +def startTimer(interval, name): global timers - timers.append(AlbertTimer(interval)) + timers.append(AlbertTimer(interval, name)) def deleteTimer(timer): @@ -64,12 +70,14 @@ def handleQuery(query): if query.isTriggered: if query.string.strip(): - fields = query.string.strip().split(":") + args = query.string.strip().split(maxsplit=1) + fields = args[0].split(":") + name = args[1] if 1 < len(args) else '' if not all(field.isdigit() or field == '' for field in fields): return Item( id=__prettyname__, text="Invalid input", - subtext="Enter a query in the form of '%s[[hours:]minutes:]'" % __trigger__, + subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % __trigger__, icon=iconPath, completion=query.rawString ) @@ -82,10 +90,10 @@ def handleQuery(query): return Item( id=__prettyname__, text=formatSeconds(seconds), - subtext="Set a timer", + subtext='Set a timer with name "%s"' % name if name else 'Set a timer', icon=iconPath, completion=query.rawString, - actions=[FuncAction("Set timer", lambda sec=seconds: startTimer(sec))] + actions=[FuncAction("Set timer", lambda sec=seconds: startTimer(sec, name))] ) else: @@ -97,13 +105,23 @@ def handleQuery(query): h, m = divmod(m, 60) identifier = "%d:%02d:%02d" % (h, m, s) + timer_name_with_quotes = '"%s"' % timer.name if timer.name else '' items.append(Item( id=__prettyname__, - text="Delete timer [%s]" % identifier, + text='Delete timer %s [%s]' % (timer_name_with_quotes, identifier), subtext="Times out %s" % strftime("%X", localtime(timer.end)), icon=iconPath, completion=query.rawString, actions=[FuncAction("Delete timer", lambda timer=timer: deleteTimer(timer))] )) + if items: + return items + # Display hint item + return Item( + id=__prettyname__, + text="Add timer", + subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % __trigger__, + icon=iconPath, + completion=query.rawString + ) - return items From 4327dc5a6a7f7fdaae52bc0ea1629f0cdfe9ce2a Mon Sep 17 00:00:00 2001 From: Dave Shoreman Date: Fri, 4 Sep 2020 13:53:11 +0100 Subject: [PATCH 004/355] [youtube] Fix 'simpleText' key error Fixes an issue that was preventing `yt foo` style commands from working. While channel results still use a `simpleText` key for the title, video results now have a `runs` list that contains the title as a `text` key in the first object. There's also an accessibility object that contains all data about the video as a string, but we don't need that. --- youtube.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/youtube.py b/youtube.py index a6317ca8..2ef8638e 100644 --- a/youtube.py +++ b/youtube.py @@ -51,6 +51,7 @@ def handleQuery(query): try: if type == 'videoRenderer': id = data['videoId'] + text = data['title']['runs'][0]['text'] subtext = 'Video' if 'lengthText' in data: subtext = subtext + " | %s" % data['lengthText']['simpleText'].strip() @@ -61,6 +62,7 @@ def handleQuery(query): actions=[ UrlAction('Watch on Youtube', 'https://youtube.com/watch?v=%s' % id) ] elif type == 'channelRenderer': id = data['channelId'] + text = data['title']['simpleText'] subtext = 'Channel' if 'videoCountText' in data: subtext = subtext + " | %s" % data['videoCountText']['simpleText'].strip() @@ -75,7 +77,7 @@ def handleQuery(query): item = Item(id=__prettyname__, icon=data['thumbnail']['thumbnails'][0]['url'].split('?', 1)[0] if data['thumbnail']['thumbnails'] else __icon__, - text=data['title']['simpleText'], + text=text, subtext=subtext, completion=query.rawString, actions=actions From ccef1bbd5c7c1b0e9cc2e97db0e2f4366eab980b Mon Sep 17 00:00:00 2001 From: Dave Shoreman Date: Fri, 4 Sep 2020 14:27:26 +0100 Subject: [PATCH 005/355] [youtube] Fix missing channel results Fixes a KeyError which prevented channel results from being included in the items list. This was caused by the video count text for a channel which, like video results, is now using the `runs` list instead. --- youtube.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube.py b/youtube.py index 2ef8638e..e5d0565b 100644 --- a/youtube.py +++ b/youtube.py @@ -65,7 +65,7 @@ def handleQuery(query): text = data['title']['simpleText'] subtext = 'Channel' if 'videoCountText' in data: - subtext = subtext + " | %s" % data['videoCountText']['simpleText'].strip() + subtext = subtext + " | %s videos" % data['videoCountText']['runs'][0]['text'].strip() if 'subscriberCountText' in data: subtext = subtext + " | %s" % data['subscriberCountText']['simpleText'].strip() actions=[ UrlAction('Show on Youtube', 'https://www.youtube.com/channel/%s' % id) ] From 01ed765b7a85f3a50be5fb0ca632215ceb68941a Mon Sep 17 00:00:00 2001 From: Dave Shoreman Date: Fri, 4 Sep 2020 16:49:26 +0100 Subject: [PATCH 006/355] [youtube] Properly load text from `runs` list While video titles seem to be stored as one string, the video count text is stored with the number in the first item, and the text in the second. This adds a small helper function that grabs the `text` value from all the items in `runs` and concatenates them, falling back to simpleText where the `runs` key isn't defined so we can use it for titles too. Also imports the `critical` function from `albertv0` since it's needed to catch any exceptions that get thrown (eg for shelf/movie renderers). --- youtube.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/youtube.py b/youtube.py index e5d0565b..7837fe63 100644 --- a/youtube.py +++ b/youtube.py @@ -11,7 +11,7 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen -from albertv0 import Item, UrlAction, iconLookup +from albertv0 import Item, UrlAction, iconLookup, critical __iid__ = 'PythonInterface/v0.1' __prettyname__ = 'Youtube' @@ -51,7 +51,6 @@ def handleQuery(query): try: if type == 'videoRenderer': id = data['videoId'] - text = data['title']['runs'][0]['text'] subtext = 'Video' if 'lengthText' in data: subtext = subtext + " | %s" % data['lengthText']['simpleText'].strip() @@ -62,10 +61,9 @@ def handleQuery(query): actions=[ UrlAction('Watch on Youtube', 'https://youtube.com/watch?v=%s' % id) ] elif type == 'channelRenderer': id = data['channelId'] - text = data['title']['simpleText'] subtext = 'Channel' if 'videoCountText' in data: - subtext = subtext + " | %s videos" % data['videoCountText']['runs'][0]['text'].strip() + subtext = subtext + " | %s" % textFrom(data['videoCountText']) if 'subscriberCountText' in data: subtext = subtext + " | %s" % data['subscriberCountText']['simpleText'].strip() actions=[ UrlAction('Show on Youtube', 'https://www.youtube.com/channel/%s' % id) ] @@ -77,10 +75,16 @@ def handleQuery(query): item = Item(id=__prettyname__, icon=data['thumbnail']['thumbnails'][0]['url'].split('?', 1)[0] if data['thumbnail']['thumbnails'] else __icon__, - text=text, + text=textFrom(data['title']), subtext=subtext, completion=query.rawString, actions=actions ) items.append(item) return items + +def textFrom(val): + text = val['simpleText'] if 'runs' not in val else \ + ''.join('{}'.format(v['text']) for v in val['runs']) + + return text.strip() From 281740c627d30f5f2ea8f07681b02d0173cab71f Mon Sep 17 00:00:00 2001 From: Dave Shoreman Date: Fri, 4 Sep 2020 17:03:18 +0100 Subject: [PATCH 007/355] [youtube] Bump version and update simpleText usage This updates any remaining uses of the `simpleText` key to use the `textFrom` helper to prevent future issues if any other values switch over to the new list-based `runs` format. `subtext` is also changed to a list so we only have to append the actual values and can join with pipe separators when it's passed to the Item. --- youtube.py | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/youtube.py b/youtube.py index 7837fe63..e54b52c1 100644 --- a/youtube.py +++ b/youtube.py @@ -15,7 +15,7 @@ __iid__ = 'PythonInterface/v0.1' __prettyname__ = 'Youtube' -__version__ = '1.0' +__version__ = '1.1' __trigger__ = 'yt ' __author__ = 'Manuel Schneider' __icon__ = iconLookup('youtube') # path.dirname(__file__) + '/icons/YouTube.png' @@ -37,9 +37,9 @@ def handleQuery(query): if not query.isValid: return - url_values = urlencode({'search_query': query.string.strip()}) - url = 'https://www.youtube.com/results?%s' % url_values - req = Request(url=url, headers=HEADERS) + req = Request(headers=HEADERS, url='https://www.youtube.com/results?{}'.format( + urlencode({ 'search_query': query.string.strip() }))) + with urlopen(req) as response: match = re.search(re_videos, response.read().decode()) if match: @@ -50,23 +50,26 @@ def handleQuery(query): for type, data in result.items(): try: if type == 'videoRenderer': - id = data['videoId'] - subtext = 'Video' + subtext = ['Video'] + action = 'Watch on Youtube' + link = 'watch?v={}'.format(data['videoId']) + if 'lengthText' in data: - subtext = subtext + " | %s" % data['lengthText']['simpleText'].strip() + subtext.append(textFrom(data['lengthText'])) if 'shortViewCountText' in data: - subtext = subtext + " | %s" % data['shortViewCountText']['simpleText'].strip() + subtext.append(textFrom(data['shortViewCountText'])) if 'publishedTimeText' in data: - subtext = subtext + " | %s" % data['publishedTimeText']['simpleText'].strip() - actions=[ UrlAction('Watch on Youtube', 'https://youtube.com/watch?v=%s' % id) ] + subtext.append(textFrom(data['publishedTimeText'])) + elif type == 'channelRenderer': - id = data['channelId'] - subtext = 'Channel' + subtext = ['Channel'] + action = 'Show on Youtube' + link = 'channel/{}'.format(data['channelId']) + if 'videoCountText' in data: - subtext = subtext + " | %s" % textFrom(data['videoCountText']) + subtext.append(textFrom(data['videoCountText'])) if 'subscriberCountText' in data: - subtext = subtext + " | %s" % data['subscriberCountText']['simpleText'].strip() - actions=[ UrlAction('Show on Youtube', 'https://www.youtube.com/channel/%s' % id) ] + subtext.append(textFrom(data['subscriberCountText'])) else: continue except Exception as e: @@ -76,9 +79,9 @@ def handleQuery(query): item = Item(id=__prettyname__, icon=data['thumbnail']['thumbnails'][0]['url'].split('?', 1)[0] if data['thumbnail']['thumbnails'] else __icon__, text=textFrom(data['title']), - subtext=subtext, + subtext=' | '.join(subtext), completion=query.rawString, - actions=actions + actions=[ UrlAction(action, 'https://www.youtube.com/' + link) ] ) items.append(item) return items From 7951b02c08551a4f1fbc48fec2b4734dafc4ec18 Mon Sep 17 00:00:00 2001 From: Dave Shoreman Date: Fri, 6 Nov 2020 20:27:29 +0000 Subject: [PATCH 008/355] Bail out if we can't find the initial data object Instead of checking for a match and just doing nothing if it fails, this throws a critical log stating what happened and saves the HTML received from youtube.com/results to a file in /tmp for debugging. --- youtube.py | 109 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 45 deletions(-) diff --git a/youtube.py b/youtube.py index e54b52c1..0b8f7cbb 100644 --- a/youtube.py +++ b/youtube.py @@ -11,7 +11,7 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen -from albertv0 import Item, UrlAction, iconLookup, critical +from albertv0 import Item, UrlAction, iconLookup, critical, info __iid__ = 'PythonInterface/v0.1' __prettyname__ = 'Youtube' @@ -37,57 +37,76 @@ def handleQuery(query): if not query.isValid: return + info("Searching YouTube for '{}'".format(query.string)) req = Request(headers=HEADERS, url='https://www.youtube.com/results?{}'.format( urlencode({ 'search_query': query.string.strip() }))) with urlopen(req) as response: - match = re.search(re_videos, response.read().decode()) - if match: - results = json.loads(match.group(1)) - results = results['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'][0]['itemSectionRenderer']['contents'] - items = [] - for result in results: - for type, data in result.items(): - try: - if type == 'videoRenderer': - subtext = ['Video'] - action = 'Watch on Youtube' - link = 'watch?v={}'.format(data['videoId']) - - if 'lengthText' in data: - subtext.append(textFrom(data['lengthText'])) - if 'shortViewCountText' in data: - subtext.append(textFrom(data['shortViewCountText'])) - if 'publishedTimeText' in data: - subtext.append(textFrom(data['publishedTimeText'])) - - elif type == 'channelRenderer': - subtext = ['Channel'] - action = 'Show on Youtube' - link = 'channel/{}'.format(data['channelId']) - - if 'videoCountText' in data: - subtext.append(textFrom(data['videoCountText'])) - if 'subscriberCountText' in data: - subtext.append(textFrom(data['subscriberCountText'])) - else: - continue - except Exception as e: - critical(e) - critical(json.dumps(result, indent=4)) - - item = Item(id=__prettyname__, - icon=data['thumbnail']['thumbnails'][0]['url'].split('?', 1)[0] if data['thumbnail']['thumbnails'] else __icon__, - text=textFrom(data['title']), - subtext=' | '.join(subtext), - completion=query.rawString, - actions=[ UrlAction(action, 'https://www.youtube.com/' + link) ] - ) - items.append(item) - return items + responseBytes = response.read() + match = re.search(re_videos, responseBytes.decode()) + if match is None: + critical("Failed to receive expected data from YouTube. This likely means API changes, but could just be a failed request.") + logHtml(responseBytes) + return + + results = json.loads(match.group(1)) + results = results['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'][0]['itemSectionRenderer']['contents'] + items = [] + for result in results: + for type, data in result.items(): + try: + if type == 'videoRenderer': + subtext = ['Video'] + action = 'Watch on Youtube' + link = 'watch?v={}'.format(data['videoId']) + + if 'lengthText' in data: + subtext.append(textFrom(data['lengthText'])) + if 'shortViewCountText' in data: + subtext.append(textFrom(data['shortViewCountText'])) + if 'publishedTimeText' in data: + subtext.append(textFrom(data['publishedTimeText'])) + + elif type == 'channelRenderer': + subtext = ['Channel'] + action = 'Show on Youtube' + link = 'channel/{}'.format(data['channelId']) + + if 'videoCountText' in data: + subtext.append(textFrom(data['videoCountText'])) + if 'subscriberCountText' in data: + subtext.append(textFrom(data['subscriberCountText'])) + else: + continue + except Exception as e: + critical(e) + critical(json.dumps(result, indent=4)) + + item = Item(id=__prettyname__, + icon=data['thumbnail']['thumbnails'][0]['url'].split('?', 1)[0] if data['thumbnail']['thumbnails'] else __icon__, + text=textFrom(data['title']), + subtext=' | '.join(subtext), + completion=query.rawString, + actions=[ UrlAction(action, 'https://www.youtube.com/' + link) ] + ) + items.append(item) + return items def textFrom(val): text = val['simpleText'] if 'runs' not in val else \ ''.join('{}'.format(v['text']) for v in val['runs']) return text.strip() + +def logHtml(html): + logTime = time.strftime("%Y%m%d-%H%M%S") + logName = 'albert.plugins.youtube_dump' + logPath = '/tmp/{}-{}.html'.format(logName, logTime) + + f = open(logPath, 'wb') + f.write(html) + f.close() + + critical("The HTML output has been dumped to {}.".format(logPath)) + critical("If the page looks ok in a browser, please include the dump in a new issue:") + critical(" https://www.github.com/albertlauncher/albert/issues/new") From 417ee522b4a3c9b0c39aa4b5671c0e45a6dc05eb Mon Sep 17 00:00:00 2001 From: Dave Shoreman Date: Fri, 6 Nov 2020 21:03:59 +0000 Subject: [PATCH 009/355] Add support for new scraper javascript The data object used by the youtube plugin is now set directly with 'var' inside a `// scraper_data_[begin|end]` block. This adds a new regex, falling back to the original that looks for a key being set on the main `window` object. --- youtube.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/youtube.py b/youtube.py index 0b8f7cbb..f971ff99 100644 --- a/youtube.py +++ b/youtube.py @@ -11,7 +11,7 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen -from albertv0 import Item, UrlAction, iconLookup, critical, info +from albertv0 import Item, UrlAction, iconLookup, critical, debug, info __iid__ = 'PythonInterface/v0.1' __prettyname__ = 'Youtube' @@ -27,7 +27,8 @@ ) } -re_videos = re.compile(r"^\s*window\[\"ytInitialData\"\] = (.*);$", re.MULTILINE) +DATA_REGEX_VAR = re.compile(r'^\s*var\sytInitialData\s*=\s*(.*)\s*;\s*$', re.MULTILINE) +DATA_REGEX_WINDOW = re.compile(r"^\s*window\[\"ytInitialData\"\] = (.*);$", re.MULTILINE) def handleQuery(query): if query.isTriggered and query.string.strip(): @@ -43,12 +44,17 @@ def handleQuery(query): with urlopen(req) as response: responseBytes = response.read() - match = re.search(re_videos, responseBytes.decode()) + match = re.search(DATA_REGEX_VAR, responseBytes.decode()) if match is None: - critical("Failed to receive expected data from YouTube. This likely means API changes, but could just be a failed request.") - logHtml(responseBytes) - return + debug("Could not find data object using 'var' regex, falling back to 'window'") + match = re.search(DATA_REGEX_WINDOW, responseBytes.decode()) + if match is None: + critical("Failed to receive expected data from YouTube. This likely means API changes, but could just be a failed request.") + logHtml(responseBytes) + return + + info("Found data object in window") results = json.loads(match.group(1)) results = results['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'][0]['itemSectionRenderer']['contents'] items = [] From 746798a0824abf79acdae39cd0e34c9196bb588c Mon Sep 17 00:00:00 2001 From: Dave Shoreman Date: Fri, 6 Nov 2020 21:20:27 +0000 Subject: [PATCH 010/355] Combine both data searches into a single regex Since the differences are minimal (window[foo] vs var foo) we can combine the regexes without them getting too overly complex. The original `re_videos` regex didn't work once tweaked for `var` due to an extra space after a semicolon, so all spaces in the new regex have been replaced with `\s*` to allow any length of whitespace in future. --- youtube.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/youtube.py b/youtube.py index f971ff99..f5e10bd1 100644 --- a/youtube.py +++ b/youtube.py @@ -20,6 +20,8 @@ __author__ = 'Manuel Schneider' __icon__ = iconLookup('youtube') # path.dirname(__file__) + '/icons/YouTube.png' +DATA_REGEX = re.compile(r'^\s*(var\s|window\[")ytInitialData("\])?\s*=\s*(.*)\s*;\s*$', re.MULTILINE) + HEADERS = { 'User-Agent': ( 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)' @@ -27,9 +29,6 @@ ) } -DATA_REGEX_VAR = re.compile(r'^\s*var\sytInitialData\s*=\s*(.*)\s*;\s*$', re.MULTILINE) -DATA_REGEX_WINDOW = re.compile(r"^\s*window\[\"ytInitialData\"\] = (.*);$", re.MULTILINE) - def handleQuery(query): if query.isTriggered and query.string.strip(): @@ -44,18 +43,13 @@ def handleQuery(query): with urlopen(req) as response: responseBytes = response.read() - match = re.search(DATA_REGEX_VAR, responseBytes.decode()) + match = re.search(DATA_REGEX, responseBytes.decode()) if match is None: - debug("Could not find data object using 'var' regex, falling back to 'window'") - match = re.search(DATA_REGEX_WINDOW, responseBytes.decode()) - - if match is None: - critical("Failed to receive expected data from YouTube. This likely means API changes, but could just be a failed request.") - logHtml(responseBytes) - return + critical("Failed to receive expected data from YouTube. This likely means API changes, but could just be a failed request.") + logHtml(responseBytes) + return - info("Found data object in window") - results = json.loads(match.group(1)) + results = json.loads(match.group(3)) results = results['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'][0]['itemSectionRenderer']['contents'] items = [] for result in results: From 91845ed824ef7d61e572890c41f75c65c8d0a477 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 8 Nov 2020 12:01:39 +0100 Subject: [PATCH 011/355] Transfer plugins from community repo --- lpass/__init__.py | 109 +++++++++++++++++++++++++++++++++++++++++++++ lpass/lastpass.svg | 10 +++++ vpn.py | 66 +++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 lpass/__init__.py create mode 100644 lpass/lastpass.svg create mode 100644 vpn.py diff --git a/lpass/__init__.py b/lpass/__init__.py new file mode 100644 index 00000000..dc7a9f57 --- /dev/null +++ b/lpass/__init__.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- + +"""LastPass Vault Search + +Synopsis: """ + +from shutil import which +from albertv0 import * +import subprocess +import re +import os + +__iid__ = 'PythonInterface/v0.1' +__prettyname__ = 'LastPass' +__version__ = '0.1.0' +__trigger__ = 'lp ' +__author__ = 'David Piçarra' +__dependencies__ = ['lpass'] + +if not which('lpass'): + raise Exception("`lpass` is not in $PATH.") +clipmgrs = ['xclip', 'xsel', 'pbcopy', 'putclip'] +hasclipmgr = False +for mgr in clipmgrs: + if which(mgr): + hasclipmgr = True + break +if not hasclipmgr: + raise Exception("`xclip`, `xsel`, `pbcopy`, or `putclip` is not in $PATH.") + +ICON_PATH = os.path.dirname(__file__)+"/lastpass.svg" + +def handleQuery(query): + if query.isTriggered: + stripped = query.string.strip() + + try: + lpass = subprocess.check_output(['lpass', 'status']) + except Exception as e: + return Item( + id=__prettyname__, + icon=ICON_PATH, + text=f'Not logged in.', + subtext=f'Please enter your lastpass email address', + completion=query.rawString, + actions=[ + ProcAction("lpass login with given email", ["lpass", "login", stripped]), + ] + ) + + + if stripped: + try: + lpass = subprocess.Popen(['lpass', 'ls', '--long'], stdout=subprocess.PIPE) + try: + output = subprocess.check_output(['grep', '-i', stripped], stdin=lpass.stdout) + except subprocess.CalledProcessError as e: + return Item( + id=__prettyname__, + icon=ICON_PATH, + text=__prettyname__, + subtext=f'No results found for {stripped}', + completion=query.rawString + ) + items = [] + for line in output.splitlines(): + match = re.match(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2} (.*) \[id: (\d*)\] \[username: (.*)\]', line.decode("utf-8")) + items.append(Item( + id=__prettyname__, + icon=ICON_PATH, + text=match.group(1), + subtext=match.group(3), + completion=query.rawString, + actions=[ + ProcAction("Copy password to clipboard", ["lpass", "show", "-cp", match.group(2)]), + ProcAction("Copy username to clipboard", ["lpass", "show", "-cu", match.group(2)]), + ProcAction("Copy notes to clipboard", ["lpass", "show", "-c", "--notes", match.group(2)]) + ] + )) + + return items + + except subprocess.CalledProcessError as e: + return Item( + id=__prettyname__, + icon=ICON_PATH, + text=f'Error: {str(e.output)}', + subtext=str(e), + completion=query.rawString, + actions=[ClipAction('Copy CalledProcessError to clipboard', str(e))] + ) + except Exception as e: + return Item( + id=__prettyname__, + icon=ICON_PATH, + text=f'Generic Exception: {str(e)}', + subtext=str(e), + completion=query.rawString, + actions=[ClipAction('Copy Exception to clipboard', str(e))] + ) + + else: + return Item( + id=__prettyname__, + icon=ICON_PATH, + text=__prettyname__, + subtext='Search the LastPass vault', + completion=query.rawString, + ) diff --git a/lpass/lastpass.svg b/lpass/lastpass.svg new file mode 100644 index 00000000..d55c869f --- /dev/null +++ b/lpass/lastpass.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/vpn.py b/vpn.py new file mode 100644 index 00000000..77f04516 --- /dev/null +++ b/vpn.py @@ -0,0 +1,66 @@ +"""VPN Extension + +Connect or disconnect from a network manager VPN profile""" + + +import subprocess +from collections import namedtuple +from albertv0 import * +from shutil import which + + +__iid__ = "PythonInterface/v0.2" +__prettyname__ = "VPN" +__version__ = "1.0" +__trigger__ = "vpn " +__author__ = "janeklb" +__dependencies__ = ['nmcli'] + + +iconPath = iconLookup('network-wireless') +if not iconPath: + iconPath = ":python_module" + +VPNConnection = namedtuple('VPNConnection', ['name', 'connected']) + + +def getVPNConnections(): + consStr = subprocess.check_output( + 'nmcli -t connection show', + shell=True, + encoding='UTF-8' + ) + for conStr in consStr.splitlines(): + con = conStr.split(':') + if con[2] == 'vpn': + yield VPNConnection(name=con[0], connected=con[3] != '') + + +def buildItem(con): + name = con.name + command = 'down' if con.connected else 'up' + text = f'Connect to {name}' if command == 'up' else f'Disconnect from {name}' + commandline = ['nmcli', 'connection', command, 'id', name] + return Item( + id=f'vpn-{command}-{name}', + text=name, + subtext=text, + icon=iconPath, + completion=name, + actions=[ ProcAction(text=text, commandline=commandline) ] + ) + + +def initialize(): + if which('nmcli') is None: + raise Exception("'nmcli' is not in $PATH") + + +def handleQuery(query): + if query.isValid and query.isTriggered: + connections = getVPNConnections() + if query.string: + connections = [ con for con in connections if query.string.lower() in con.name.lower() ] + return [ buildItem(con) for con in connections ] + return [] + From 36f7860f4bdf4bc41ea8b463d31bcafc3f24e897 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 8 Nov 2020 12:08:57 +0100 Subject: [PATCH 012/355] Move all exts to folders --- atom_projects.py => atom_projects/__init_.py | 0 base_converter.py => base_converter/__init_.py | 0 copyq.py => copyq/__init_.py | 0 currency_converter.py => currency_converter/__init_.py | 0 datetime.py => datetime/__init_.py | 0 fortune.py => fortune/__init_.py | 0 gnome_dictionary.py => gnome_dictionary/__init_.py | 0 gnote.py => gnote/__init_.py | 0 goldendict.py => goldendict/__init_.py | 0 google_translate.py => google_translate/__init_.py | 0 ip.py => ip/__init_.py | 0 kill.py => kill/__init_.py | 0 locate.py => locate/__init_.py | 0 mathematica_eval.py => mathematica_eval/__init_.py | 0 multi_google_translate.py => multi_google_translate/__init_.py | 0 pacman.py => pacman/__init_.py | 0 pass.py => pass/__init_.py | 0 pidgin.py => pidgin/__init_.py | 0 scrot.py => scrot/__init_.py | 0 tex_to_unicode.py => tex_to_unicode/__init_.py | 0 tomboy.py => tomboy/__init_.py | 0 trash.py => trash/__init_.py | 0 units.py => units/__init_.py | 0 virtualbox.py => virtualbox/__init_.py | 0 vpn.py => vpn/__init_.py | 0 window_switcher.py => window_switcher/__init_.py | 0 youtube.py => youtube/__init_.py | 0 zeal.py => zeal/__init_.py | 0 28 files changed, 0 insertions(+), 0 deletions(-) rename atom_projects.py => atom_projects/__init_.py (100%) rename base_converter.py => base_converter/__init_.py (100%) rename copyq.py => copyq/__init_.py (100%) rename currency_converter.py => currency_converter/__init_.py (100%) rename datetime.py => datetime/__init_.py (100%) rename fortune.py => fortune/__init_.py (100%) rename gnome_dictionary.py => gnome_dictionary/__init_.py (100%) rename gnote.py => gnote/__init_.py (100%) rename goldendict.py => goldendict/__init_.py (100%) rename google_translate.py => google_translate/__init_.py (100%) rename ip.py => ip/__init_.py (100%) rename kill.py => kill/__init_.py (100%) rename locate.py => locate/__init_.py (100%) rename mathematica_eval.py => mathematica_eval/__init_.py (100%) rename multi_google_translate.py => multi_google_translate/__init_.py (100%) rename pacman.py => pacman/__init_.py (100%) rename pass.py => pass/__init_.py (100%) rename pidgin.py => pidgin/__init_.py (100%) rename scrot.py => scrot/__init_.py (100%) rename tex_to_unicode.py => tex_to_unicode/__init_.py (100%) rename tomboy.py => tomboy/__init_.py (100%) rename trash.py => trash/__init_.py (100%) rename units.py => units/__init_.py (100%) rename virtualbox.py => virtualbox/__init_.py (100%) rename vpn.py => vpn/__init_.py (100%) rename window_switcher.py => window_switcher/__init_.py (100%) rename youtube.py => youtube/__init_.py (100%) rename zeal.py => zeal/__init_.py (100%) diff --git a/atom_projects.py b/atom_projects/__init_.py similarity index 100% rename from atom_projects.py rename to atom_projects/__init_.py diff --git a/base_converter.py b/base_converter/__init_.py similarity index 100% rename from base_converter.py rename to base_converter/__init_.py diff --git a/copyq.py b/copyq/__init_.py similarity index 100% rename from copyq.py rename to copyq/__init_.py diff --git a/currency_converter.py b/currency_converter/__init_.py similarity index 100% rename from currency_converter.py rename to currency_converter/__init_.py diff --git a/datetime.py b/datetime/__init_.py similarity index 100% rename from datetime.py rename to datetime/__init_.py diff --git a/fortune.py b/fortune/__init_.py similarity index 100% rename from fortune.py rename to fortune/__init_.py diff --git a/gnome_dictionary.py b/gnome_dictionary/__init_.py similarity index 100% rename from gnome_dictionary.py rename to gnome_dictionary/__init_.py diff --git a/gnote.py b/gnote/__init_.py similarity index 100% rename from gnote.py rename to gnote/__init_.py diff --git a/goldendict.py b/goldendict/__init_.py similarity index 100% rename from goldendict.py rename to goldendict/__init_.py diff --git a/google_translate.py b/google_translate/__init_.py similarity index 100% rename from google_translate.py rename to google_translate/__init_.py diff --git a/ip.py b/ip/__init_.py similarity index 100% rename from ip.py rename to ip/__init_.py diff --git a/kill.py b/kill/__init_.py similarity index 100% rename from kill.py rename to kill/__init_.py diff --git a/locate.py b/locate/__init_.py similarity index 100% rename from locate.py rename to locate/__init_.py diff --git a/mathematica_eval.py b/mathematica_eval/__init_.py similarity index 100% rename from mathematica_eval.py rename to mathematica_eval/__init_.py diff --git a/multi_google_translate.py b/multi_google_translate/__init_.py similarity index 100% rename from multi_google_translate.py rename to multi_google_translate/__init_.py diff --git a/pacman.py b/pacman/__init_.py similarity index 100% rename from pacman.py rename to pacman/__init_.py diff --git a/pass.py b/pass/__init_.py similarity index 100% rename from pass.py rename to pass/__init_.py diff --git a/pidgin.py b/pidgin/__init_.py similarity index 100% rename from pidgin.py rename to pidgin/__init_.py diff --git a/scrot.py b/scrot/__init_.py similarity index 100% rename from scrot.py rename to scrot/__init_.py diff --git a/tex_to_unicode.py b/tex_to_unicode/__init_.py similarity index 100% rename from tex_to_unicode.py rename to tex_to_unicode/__init_.py diff --git a/tomboy.py b/tomboy/__init_.py similarity index 100% rename from tomboy.py rename to tomboy/__init_.py diff --git a/trash.py b/trash/__init_.py similarity index 100% rename from trash.py rename to trash/__init_.py diff --git a/units.py b/units/__init_.py similarity index 100% rename from units.py rename to units/__init_.py diff --git a/virtualbox.py b/virtualbox/__init_.py similarity index 100% rename from virtualbox.py rename to virtualbox/__init_.py diff --git a/vpn.py b/vpn/__init_.py similarity index 100% rename from vpn.py rename to vpn/__init_.py diff --git a/window_switcher.py b/window_switcher/__init_.py similarity index 100% rename from window_switcher.py rename to window_switcher/__init_.py diff --git a/youtube.py b/youtube/__init_.py similarity index 100% rename from youtube.py rename to youtube/__init_.py diff --git a/zeal.py b/zeal/__init_.py similarity index 100% rename from zeal.py rename to zeal/__init_.py From 40e8c63fd11a704f00d569ddd67a9b5b73372da2 Mon Sep 17 00:00:00 2001 From: Nikos Koukis Date: Sun, 10 Nov 2019 13:56:59 +0000 Subject: [PATCH 013/355] Add xkcd plugin as submodule --- .gitmodules | 3 +++ xkcd | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 xkcd diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..b234c8d1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "xkcd"] + path = xkcd + url = https://github.com/bergercookie/xkcd-albert-plugin diff --git a/xkcd b/xkcd new file mode 160000 index 00000000..bf88a964 --- /dev/null +++ b/xkcd @@ -0,0 +1 @@ +Subproject commit bf88a964473d65b39c9e09eb48dabb847206f06f From be6fb258a17e6380bd917636571d29160a337da8 Mon Sep 17 00:00:00 2001 From: Xiaonan Shen Date: Sat, 23 Feb 2019 22:31:52 -0500 Subject: [PATCH 014/355] Fix installation command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 17b6d7f2..29f76e64 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This repository is shipped with albert. If you want to have bleeding edge extens To install the extensions in user space type the following in your terminal: ``` -git clone https://github.com/albertlauncher/python.git "~/.local/share/albert/org.albert.extension.python/modules" +git clone https://github.com/albertlauncher/python.git ~/.local/share/albert/org.albert.extension.python/modules ``` If you send a PR I'll invite you to the reviewers team (if I don't forget it), I'd appreciate if you could review others contributions. From a1ab7f47178948352ff21c8f6c22ea2c986fdec5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 8 Nov 2020 23:14:41 +0100 Subject: [PATCH 015/355] Manually merged matthewbogner:mbogner-timestamps Closes #44 --- datetime/__init_.py | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/datetime/__init_.py b/datetime/__init_.py index 043c7375..2bd3702e 100644 --- a/datetime/__init_.py +++ b/datetime/__init_.py @@ -10,14 +10,15 @@ [timestamp]""" -import datetime +from datetime import datetime, date import time from albertv0 import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "DateTime" -__version__ = "1.0" +__version__ = "1.1" +__trigger__ = None __author__ = "Manuel Schneider" __dependencies__ = [] @@ -38,23 +39,35 @@ def makeItem(text: str, subtext: str): ) if "date".startswith(fields[0]) and len(fields) == 1: - return makeItem(datetime.date.today().strftime("%x"), + return makeItem(date.today().strftime("%x"), "Current date") elif "time".startswith(fields[0]) and len(fields) == 1: - return makeItem(datetime.datetime.now().strftime("%X"), + return makeItem(datetime.now().strftime("%X"), "Current time (local)") elif "utc".startswith(fields[0]) and len(fields) == 1: - return makeItem(datetime.datetime.utcnow().strftime("%X"), + return makeItem(datetime.utcnow().strftime("%X"), "Current time (UTC)") elif "datetime".startswith(fields[0]) and len(fields) == 1: - return makeItem(datetime.datetime.now().strftime("%c"), + return makeItem(datetime.now().strftime("%c"), "Current date and time") - elif "unixtime".startswith(fields[0]) or "epoch".startswith(fields[0]): + elif "unixtime".startswith(fields[0]) or "epoch".startswith(fields[0]) or "ts".startswith(fields[0]): if len(fields) == 2: if fields[1].isdigit(): - return makeItem(time.strftime("%c", time.localtime(int(fields[1]))), - "Date and time of '%s'" % fields[1]) + timestamp = int(fields[1]) + if len(fields[1]) > 10: + timestamp = timestamp / 1000 + + return [ + makeItem(time.strftime("%c", time.localtime(timestamp)), + "Date and time of '%s'" % fields[1]), + makeItem(datetime.fromtimestamp(timestamp).astimezone().strftime("%Y-%m-%d %H:%M:%S.%f %Z"), + "Date and time of '%s'" % fields[1]), + makeItem(datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S.%f UTC"), + "UTC Date and time of '%s'" % fields[1]) + ] else: + # TODO: how to utilize dateparser even when available on system default python install? + # dt = dateparser.parse(query.string) return Item( id=__prettyname__, icon=iconPath, @@ -63,5 +76,13 @@ def makeItem(text: str, subtext: str): completion=query.rawString ) else: - return makeItem(datetime.datetime.now().strftime("%s"), - "Current unixtime") + return [ + makeItem(datetime.now().strftime("%s"), + "Current unixtime"), + makeItem(str(round(time.time() * 1000)), + "Millis since Epoch"), + makeItem(datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f UTC"), + "UTC timestamp"), + makeItem(datetime.now().astimezone().strftime("%Y-%m-%d %H:%M:%S.%f %Z"), + "Local timestamp") + ] From f5f5c5030c34b062ab07b40a1d69a53c01b57fff Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Thu, 10 Oct 2019 20:36:31 +0200 Subject: [PATCH 016/355] fix jetbrains recents parsing for 2019.3 eap --- jetbrains_projects/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 44c9b769..a10223d3 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -62,7 +62,7 @@ def get_proj(path): if add_info is not None: for i in add_info: for o in i[0][0]: - if o.attrib["name"] == 'projectOpenTimestamp': + if o.tag == 'option' and o.attrib["name"] == 'projectOpenTimestamp': items[i.attrib["key"]] = int(o.attrib["value"]) return [(items[e], e.replace("$USER_HOME$", HOME_DIR)) for e in items] From 700b3be94dbe3d5aa43dd41a8465d4ee91442e5d Mon Sep 17 00:00:00 2001 From: iyzana <16743652+iyzana@users.noreply.github.com> Date: Tue, 7 Jan 2020 20:49:20 +0100 Subject: [PATCH 017/355] jetbrains: also check for existence of attribute --- jetbrains_projects/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index a10223d3..dcef2bcf 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -62,7 +62,7 @@ def get_proj(path): if add_info is not None: for i in add_info: for o in i[0][0]: - if o.tag == 'option' and o.attrib["name"] == 'projectOpenTimestamp': + if o.tag == 'option' and 'name' in o.attrib and o.attrib["name"] == 'projectOpenTimestamp': items[i.attrib["key"]] = int(o.attrib["value"]) return [(items[e], e.replace("$USER_HOME$", HOME_DIR)) for e in items] From 328dcf59bd8ae61ac47da312139d9677e8ad16d1 Mon Sep 17 00:00:00 2001 From: Daniel Sager Date: Thu, 21 Nov 2019 16:05:08 +0100 Subject: [PATCH 018/355] Define path and binary for RubyMine RubyMine is another IDE from JetBrains that has the same structure as other IntelliJ based products. So just adding the path for it will make ruby projects appear in the launcher. --- jetbrains_projects/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index dcef2bcf..ec843898 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -28,6 +28,7 @@ "intellij-idea-ue-bundled-jre intellij-idea-ultimate-edition idea-ce-eap idea-ue-eap idea idea-ultimate"], ["PhpStorm", "phpstorm"], ["PyCharm", "pycharm pycharm-eap charm"], + ["RubyMine", "rubymine"], ["WebStorm", "webstorm"], ] From fb067b388b4dda78c787f52c94341c4daab834da Mon Sep 17 00:00:00 2001 From: Asger Hautop Drewsen Date: Mon, 12 Oct 2020 11:31:44 +0200 Subject: [PATCH 019/355] Add bitwarden extension --- bitwarden.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 bitwarden.py diff --git a/bitwarden.py b/bitwarden.py new file mode 100644 index 00000000..373b0546 --- /dev/null +++ b/bitwarden.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- + +"""'rbw' wrapper extension.""" + +import fnmatch +import os +from shutil import which +from subprocess import run + +from albertv0 import * + +__iid__ = "PythonInterface/v0.1" +__prettyname__ = "Bitwarden" +__version__ = "1.0" +__trigger__ = "bw " +__author__ = "Asger Hautop Drewsen" +__dependencies__ = ["rbw"] + + +if which("rbw") is None: + raise Exception("'rbw' is not in $PATH.") + +ICON_PATH = iconLookup("dialog-password") + + +def handleQuery(query): + if not query.isTriggered: + return + + passwords = get_passwords() + filtered_passwords = [] + search_fields = ["name", "user", "folder"] + words = query.string.strip().lower().split() + for p in passwords: + all_matches = True + for w in words: + for k in search_fields: + if w in p[k].lower(): + break + else: + all_matches = False + break + + if all_matches: + filtered_passwords.append(p) + + results = [] + for p in filtered_passwords: + results.append( + Item( + id=p["id"], + icon=ICON_PATH, + text=p["name"], + subtext=p["user"], + completion=f"rbw {p['name']}", + actions=[ + ProcAction( + "Copy", + [ + "sh", + "-c", + f"rbw get {p['id']} | tr -d '\\n' | xclip -selection clipboard -in", + ], + ), + TermAction("Edit", ["rbw", "edit", p["id"]]), + ], + ), + ) + + return results + + +def get_passwords(): + field_names = ["id", "name", "user", "folder"] + p = run( + ["rbw", "list", "--fields", *field_names], + capture_output=True, + encoding="utf-8", + check=True, + ) + passwords = [] + for l in p.stdout.splitlines(): + fields = l.split("\t") + d = {} + passwords.append(dict(zip(field_names, fields))) + + return passwords From 99181b75ad0bd737a5ab695d0fbc6636171cf2b6 Mon Sep 17 00:00:00 2001 From: Asger Hautop Drewsen Date: Tue, 3 Nov 2020 16:13:04 +0100 Subject: [PATCH 020/355] Combine folder and name into path --- bitwarden.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/bitwarden.py b/bitwarden.py index 373b0546..fdbd13d8 100644 --- a/bitwarden.py +++ b/bitwarden.py @@ -29,7 +29,7 @@ def handleQuery(query): passwords = get_passwords() filtered_passwords = [] - search_fields = ["name", "user", "folder"] + search_fields = ["path", "user"] words = query.string.strip().lower().split() for p in passwords: all_matches = True @@ -50,9 +50,9 @@ def handleQuery(query): Item( id=p["id"], icon=ICON_PATH, - text=p["name"], + text=p["path"], subtext=p["user"], - completion=f"rbw {p['name']}", + completion=f"rbw {p['path']}", actions=[ ProcAction( "Copy", @@ -81,7 +81,11 @@ def get_passwords(): passwords = [] for l in p.stdout.splitlines(): fields = l.split("\t") - d = {} - passwords.append(dict(zip(field_names, fields))) + d = dict(zip(field_names, fields)) + if d["folder"]: + d["path"] = d["folder"] + "/" + d["name"] + else: + d["path"] = d["name"] + passwords.append(d) return passwords From 6fb175b321021b16f35782c37560ba3935fddafd Mon Sep 17 00:00:00 2001 From: Asger Hautop Drewsen Date: Tue, 3 Nov 2020 16:13:22 +0100 Subject: [PATCH 021/355] Add action to copy auth code --- bitwarden.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bitwarden.py b/bitwarden.py index fdbd13d8..0d0adb65 100644 --- a/bitwarden.py +++ b/bitwarden.py @@ -62,6 +62,14 @@ def handleQuery(query): f"rbw get {p['id']} | tr -d '\\n' | xclip -selection clipboard -in", ], ), + ProcAction( + "Copy auth code", + [ + "sh", + "-c", + f"rbw code {p['id']} | tr -d '\\n' | xclip -selection clipboard -in", + ], + ), TermAction("Edit", ["rbw", "edit", p["id"]]), ], ), From 34960a19fc217765eb469a91b57b1b7cff0d7d14 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 9 Nov 2020 00:43:21 +0100 Subject: [PATCH 022/355] [pidgin] check if in PATH --- pidgin/__init_.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pidgin/__init_.py b/pidgin/__init_.py index 9d7ccaca..fc2db298 100644 --- a/pidgin/__init_.py +++ b/pidgin/__init_.py @@ -15,6 +15,9 @@ __trigger__ = "pidgin " __dependencies__ = ["dbus"] +if which("pidgin") is None: + raise Exception("'pidgin' is not in $PATH.") + iconPath = iconLookup("pidgin") bus = dbus.SessionBus() From c0f669b0d40e8fffaa2c938c391e3e2ef1e2b463 Mon Sep 17 00:00:00 2001 From: Hammed Oyedele Date: Mon, 9 Nov 2020 11:05:29 +0100 Subject: [PATCH 023/355] [php] Add new extension: php evaluator --- php_eval/__init__.py | 43 +++++++++++++++++++++++++++++++++++++++++++ php_eval/php.svg | 1 + 2 files changed, 44 insertions(+) create mode 100644 php_eval/__init__.py create mode 100644 php_eval/php.svg diff --git a/php_eval/__init__.py b/php_eval/__init__.py new file mode 100644 index 00000000..95e93069 --- /dev/null +++ b/php_eval/__init__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +"""Evaluate simple PHP expressions. Use it with care every keystroke triggers an evaluation.""" + +import os +import subprocess +from albertv0 import * +from shutil import which + +__iid__ = 'PythonInterface/v0.1' +__prettyname__ = 'PHP Eval' +__version__ = '1.0' +__trigger__ = 'php ' +__author__ = 'Hammed Oyedele' +__dependencies__ = ['php'] + +iconPath = os.path.dirname(__file__) + '/php.svg' + +if which('php') is None: + raise Exception('"php" is not in $PATH.') + + +def run(exp): + return subprocess.getoutput('php -r "%s"' % exp.replace('"', '\\"')) + + +def handleQuery(query): + if query.isTriggered: + item = Item( + id=__prettyname__, + icon=iconPath, + completion=query.rawString, + ) + stripped = query.string.strip() + + if stripped == '': + item.text = 'Enter a PHP expression...' + else: + item.text = run('echo %s;' % stripped) + item.subtext = run('echo gettype(%s);' % stripped) + item.addAction(ClipAction('Copy result to clipboard', item.text)) + + return item diff --git a/php_eval/php.svg b/php_eval/php.svg new file mode 100644 index 00000000..9a10ee4e --- /dev/null +++ b/php_eval/php.svg @@ -0,0 +1 @@ + \ No newline at end of file From 3f21308361ca15c95923bffd400cbd82f7a7bd3e Mon Sep 17 00:00:00 2001 From: Hammed Oyedele Date: Mon, 9 Nov 2020 11:11:15 +0100 Subject: [PATCH 024/355] [node] Add new extension: node.js evaluator --- node_eval/__init__.py | 44 +++++++++++++++++++++++++++++++++++++++++++ node_eval/nodejs.svg | 11 +++++++++++ 2 files changed, 55 insertions(+) create mode 100644 node_eval/__init__.py create mode 100644 node_eval/nodejs.svg diff --git a/node_eval/__init__.py b/node_eval/__init__.py new file mode 100644 index 00000000..22a59158 --- /dev/null +++ b/node_eval/__init__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +"""Evaluate simple JavaScript expressions. Use it with care every keystroke triggers an evaluation.""" + +import os +import subprocess +from albertv0 import * +from shutil import which + +__iid__ = 'PythonInterface/v0.1' +__prettyname__ = 'Node Eval' +__version__ = '1.0' +__trigger__ = 'node ' +__author__ = 'Hammed Oyedele' +__dependencies__ = ['node'] + +if which('node') is None: + raise Exception('"node" is not in $PATH.') + +iconPath = os.path.dirname(__file__) + '/nodejs.svg' + + +def run(exp): + return subprocess.getoutput('node --print "%s"' % exp.replace('"', '\\"')) + + +def handleQuery(query): + if query.isTriggered: + item = Item( + id=__prettyname__, + icon=iconPath, + completion=query.rawString, + ) + stripped = query.string.strip() + + if stripped == '': + item.text = 'Enter a JavaScript expression...' + else: + item.text = run(stripped) + item.subtext = run( + 'Object.prototype.toString.call(%s).slice(8, -1).toLowerCase()' % stripped) + item.addAction(ClipAction('Copy result to clipboard', item.text)) + + return item diff --git a/node_eval/nodejs.svg b/node_eval/nodejs.svg new file mode 100644 index 00000000..8d55040d --- /dev/null +++ b/node_eval/nodejs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + From ed2778c9f1f687e3c6f46d01ee837b698e791102 Mon Sep 17 00:00:00 2001 From: Dave Shoreman Date: Thu, 27 Jun 2019 02:58:50 +0100 Subject: [PATCH 025/355] [win] Improvements by dshoreman v1.5 [win] Expand search to include class and title Greatly improves usefulness in cases where many windows are open of the same application, for instance multiple Terminal or browser instances, where previously you could only search by the program name. Especially helps in the case of Firefox where the instance is not "Firefox" but instead "Navigator", meaning prior to this change you would be forced to search for Navigator to get any results. By including the window title in matches, we can now also filter by webpage (for browsers) or document titles (for editors). Previously where "Alacritty" could max out the results, we can instead type "vim" to get far fewer results with a higher likelihood of a good match. [win] Fix icon for Firefox windows Firefox has a `WM_CLASS` of "Navigator.Firefox", so searching for an icon based on the instance part (Navigator) doesn't find anything. This updates it to also search for the lower-case version of the actual window class which correctly shows the Firefox icon in its results. [win] Fix windows with spaces in WM_CLASS This commit fixes an issue where spaces in a windows's `WM_CLASS` attribute would be split incorrectly causing output to break. `Navigator.Firefox Developer Edition` would previously have its wm_class set to `Navigator.Firefox`, with `host` set to "Developer" and `wm_name` left set to "Edition ". By replacing spaces with dashes, we have the added benefit that the correct icon is now displayed for the developer edition of Firefox where before it would show the main Firefox icon. --- window_switcher/__init_.py | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/window_switcher/__init_.py b/window_switcher/__init_.py index afec45c8..26fc1556 100644 --- a/window_switcher/__init_.py +++ b/window_switcher/__init_.py @@ -14,8 +14,8 @@ __iid__ = "PythonInterface/v0.1" __prettyname__ = "Window Switcher" -__version__ = "1.4" -__author__ = "Ed Perez, Manuel Schneider" +__version__ = "1.5" +__author__ = "Ed Perez, manuelschneid3r, dshoreman" __dependencies__ = ["wmctrl"] if which("wmctrl") is None: @@ -26,11 +26,26 @@ def handleQuery(query): if stripped: results = [] for line in subprocess.check_output(['wmctrl', '-l', '-x']).splitlines(): - win = Window(*[token.decode() for token in line.split(None,4)]) - if win.desktop != "-1" and stripped in win.wm_class.split('.')[0].lower(): + win = Window(*parseWindow(line)) + + if win.desktop == "-1": + continue + + win_instance, win_class = win.wm_class.replace(' ', '-').split('.') + matches = [ + win_instance.lower(), + win_class.lower(), + win.wm_name.lower() + ] + + if any(stripped in match for match in matches): + iconPath = iconLookup(win_instance) + if iconPath == "": + iconPath = iconLookup(win_class.lower()) + results.append(Item(id="%s%s" % (__prettyname__, win.wm_class), - icon=iconLookup(win.wm_class.split('.')[0]), - text="%s - Desktop %s" % (win.wm_class.split('.')[-1].replace('-',' '), win.desktop), + icon=iconPath, + text="%s - Desktop %s" % (win_class.replace('-',' '), win.desktop), subtext=win.wm_name, actions=[ProcAction("Switch Window", ["wmctrl", '-i', '-a', win.wid] ), @@ -39,3 +54,10 @@ def handleQuery(query): ProcAction("Close the window gracefully.", ["wmctrl", '-c', win.wid])])) return results + +def parseWindow(line): + win_id, desktop, rest = line.decode().split(None, 2) + win_class, rest = rest.split(' ', 1) + host, title = rest.strip().split(None, 1) + + return [win_id, desktop, win_class, host, title] From 67fc0c27302a54494b48451b6512212d48cb0d2b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 9 Nov 2020 12:39:53 +0100 Subject: [PATCH 026/355] [bitwarden] Move to dir --- bitwarden.py => bitwarden/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename bitwarden.py => bitwarden/__init__.py (100%) diff --git a/bitwarden.py b/bitwarden/__init__.py similarity index 100% rename from bitwarden.py rename to bitwarden/__init__.py From 67743b81889d0f82ffa1ed95e04e8f157933eece Mon Sep 17 00:00:00 2001 From: mqus <8398165+mqus@users.noreply.github.com> Date: Sat, 14 Nov 2020 10:05:37 +0100 Subject: [PATCH 027/355] [jetbrains] Move ext into a git submodule --- .gitmodules | 3 + jetbrains_projects | 1 + jetbrains_projects/__init__.py | 130 ------------------------------- jetbrains_projects/jetbrains.svg | 66 ---------------- 4 files changed, 4 insertions(+), 196 deletions(-) create mode 160000 jetbrains_projects delete mode 100644 jetbrains_projects/__init__.py delete mode 100644 jetbrains_projects/jetbrains.svg diff --git a/.gitmodules b/.gitmodules index b234c8d1..3d4a210c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "xkcd"] path = xkcd url = https://github.com/bergercookie/xkcd-albert-plugin +[submodule "jetbrains_projects"] + path = jetbrains_projects + url = https://github.com/mqus/jetbrains-albert-plugin.git diff --git a/jetbrains_projects b/jetbrains_projects new file mode 160000 index 00000000..b7157473 --- /dev/null +++ b/jetbrains_projects @@ -0,0 +1 @@ +Subproject commit b7157473cc923fe4f15023c85a032eeab3627652 diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py deleted file mode 100644 index ec843898..00000000 --- a/jetbrains_projects/__init__.py +++ /dev/null @@ -1,130 +0,0 @@ -# -*- coding: utf-8 -*- - -"""List and open JetBrains IDE projects. - -Synopsis: """ - -import os -from shutil import which -from xml.etree import ElementTree - -from albertv0 import * - -__iid__ = "PythonInterface/v0.3" -__prettyname__ = "Jetbrains IDE Projects" -__version__ = "1.2" -__trigger__ = "jb " -__author__ = "Markus Richter, Thomas Queste" -__dependencies__ = [] - -default_icon = os.path.dirname(__file__) + "/jetbrains.svg" -HOME_DIR = os.environ["HOME"] - -paths = [ # , - ["CLion", "clion"], - ["DataGrip", "datagrip"], - ["GoLand", "goland"], - ["IntelliJIdea", - "intellij-idea-ue-bundled-jre intellij-idea-ultimate-edition idea-ce-eap idea-ue-eap idea idea-ultimate"], - ["PhpStorm", "phpstorm"], - ["PyCharm", "pycharm pycharm-eap charm"], - ["RubyMine", "rubymine"], - ["WebStorm", "webstorm"], -] - - -# find the executable path and icon of a program described by space-separated lists of possible binary-names -def find_exec(namestr: str): - for name in namestr.split(" "): - executable = which(name) - if executable: - icon = iconLookup(name) or default_icon - return executable, icon - return None - - -# parse the xml at path, return all recent project paths and the time they were last open -def get_proj(path): - r = ElementTree.parse(path).getroot() # type:ElementTree.Element - add_info = None - items = dict() - for o in r[0]: # type:ElementTree.Element - if o.attrib["name"] == 'recentPaths': - for i in o[0]: - items[i.attrib["value"]] = 0 - - else: - if o.attrib["name"] == 'additionalInfo': - add_info = o[0] - - if len(items) == 0: - return [] - - if add_info is not None: - for i in add_info: - for o in i[0][0]: - if o.tag == 'option' and 'name' in o.attrib and o.attrib["name"] == 'projectOpenTimestamp': - items[i.attrib["key"]] = int(o.attrib["value"]) - return [(items[e], e.replace("$USER_HOME$", HOME_DIR)) for e in items] - - -def handleQuery(query): - if query.isTriggered: - query.disableSort() - - binaries = {} - projects = [] - - for app in paths: - config_path = "config/options/recentProjectDirectories.xml" - if app[0] == "IntelliJIdea": - config_path = "config/options/recentProjects.xml" - - # dirs contains possibly multiple directories for a program (eg. .GoLand2018.1 and .GoLand2017.3) - dirs = [f for f in os.listdir(HOME_DIR) if - os.path.isdir(os.path.join(HOME_DIR, f)) and f.startswith("." + app[0])] - # take the newest - dirs.sort(reverse=True) - if len(dirs) == 0: - continue - - config_path = os.path.join(HOME_DIR, dirs[0], config_path) - if not os.path.exists(config_path): - continue - - # extract the binary name and icon - binaries[app[0]] = find_exec(app[1]) - - # add all recently opened projects - projects.extend([[e[0], e[1], app[0]] for e in get_proj(config_path)]) - projects.sort(key=lambda s: s[0], reverse=True) - - # List all projects or the one corresponding to the query - if query.string: - projects = [p for p in projects if p[1].lower().find(query.string.lower()) != -1] - - items = [] - for p in projects: - last_update = p[0] - project_path = p[1] - project_dir = project_path.split("/")[-1] - product_name = p[2] - binary = binaries[product_name] - if not binary: - continue - - executable = binary[0] - icon = binary[1] - - items.append(Item( - id="-" + str(last_update), - icon=icon, - text=project_dir, - subtext=project_path, - completion=__trigger__ + project_dir, - actions=[ - ProcAction("Open in %s" % product_name, [executable, project_path]) - ] - )) - - return items diff --git a/jetbrains_projects/jetbrains.svg b/jetbrains_projects/jetbrains.svg deleted file mode 100644 index f7c7652c..00000000 --- a/jetbrains_projects/jetbrains.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 0535a4b2b0af324e6e147e508e003b96c7c9e367 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Dec 2020 20:06:40 +0100 Subject: [PATCH 028/355] [bnc] Fix market url --- binance/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/binance/__init__.py b/binance/__init__.py index 1fe2d451..7befd625 100644 --- a/binance/__init__.py +++ b/binance/__init__.py @@ -17,14 +17,14 @@ __iid__ = "PythonInterface/v0.1" __prettyname__ = "Binance" -__version__ = "1.2" +__version__ = "1.3" __trigger__ = "bnc " __author__ = "Manuel Schneider" __dependencies__ = [] iconPath = os.path.dirname(__file__) + "/Binance.svg" exchangeInfoUrl = "https://api.binance.com/api/v1/exchangeInfo" -tradeUrl = "https://www.binance.com/tradeDetail.html?symbol=%s_%s" +tradeUrl = "https://www.binance.com/en/trade/%s_%s?layout=pro" markets = [] thread = None From 14d145daee6efae35156fd740cfa88d18c22e6bc Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Dec 2020 20:15:46 +0100 Subject: [PATCH 029/355] [cmc, bfx] Archive, since API is private now --- {bitfinex => .archive/bitfinex}/Bitfinex.svg | 0 {bitfinex => .archive/bitfinex}/__init__.py | 0 {coinmarketcap => .archive/coinmarketcap}/__init__.py | 0 {coinmarketcap => .archive/coinmarketcap}/emblem-money.svg | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {bitfinex => .archive/bitfinex}/Bitfinex.svg (100%) rename {bitfinex => .archive/bitfinex}/__init__.py (100%) rename {coinmarketcap => .archive/coinmarketcap}/__init__.py (100%) rename {coinmarketcap => .archive/coinmarketcap}/emblem-money.svg (100%) diff --git a/bitfinex/Bitfinex.svg b/.archive/bitfinex/Bitfinex.svg similarity index 100% rename from bitfinex/Bitfinex.svg rename to .archive/bitfinex/Bitfinex.svg diff --git a/bitfinex/__init__.py b/.archive/bitfinex/__init__.py similarity index 100% rename from bitfinex/__init__.py rename to .archive/bitfinex/__init__.py diff --git a/coinmarketcap/__init__.py b/.archive/coinmarketcap/__init__.py similarity index 100% rename from coinmarketcap/__init__.py rename to .archive/coinmarketcap/__init__.py diff --git a/coinmarketcap/emblem-money.svg b/.archive/coinmarketcap/emblem-money.svg similarity index 100% rename from coinmarketcap/emblem-money.svg rename to .archive/coinmarketcap/emblem-money.svg From 73762b03adf98a80f19cb0039f52a8bd66d24c0e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Dec 2020 20:24:14 +0100 Subject: [PATCH 030/355] Fix filenames. Closes https://github.com/albertlauncher/albert/issues/955 --- atom_projects/{__init_.py => __init__.py} | 0 base_converter/{__init_.py => __init__.py} | 0 copyq/{__init_.py => __init__.py} | 0 currency_converter/{__init_.py => __init__.py} | 0 datetime/{__init_.py => __init__.py} | 0 fortune/{__init_.py => __init__.py} | 0 gnome_dictionary/{__init_.py => __init__.py} | 0 gnote/{__init_.py => __init__.py} | 0 goldendict/{__init_.py => __init__.py} | 0 google_translate/{__init_.py => __init__.py} | 0 ip/{__init_.py => __init__.py} | 0 kill/{__init_.py => __init__.py} | 0 locate/{__init_.py => __init__.py} | 0 mathematica_eval/{__init_.py => __init__.py} | 0 multi_google_translate/{__init_.py => __init__.py} | 0 pacman/{__init_.py => __init__.py} | 0 pass/{__init_.py => __init__.py} | 0 pidgin/{__init_.py => __init__.py} | 0 scrot/{__init_.py => __init__.py} | 0 tex_to_unicode/{__init_.py => __init__.py} | 0 tomboy/{__init_.py => __init__.py} | 0 trash/{__init_.py => __init__.py} | 0 units/{__init_.py => __init__.py} | 0 virtualbox/{__init_.py => __init__.py} | 0 vpn/{__init_.py => __init__.py} | 0 window_switcher/{__init_.py => __init__.py} | 0 youtube/{__init_.py => __init__.py} | 0 zeal/{__init_.py => __init__.py} | 0 28 files changed, 0 insertions(+), 0 deletions(-) rename atom_projects/{__init_.py => __init__.py} (100%) rename base_converter/{__init_.py => __init__.py} (100%) rename copyq/{__init_.py => __init__.py} (100%) rename currency_converter/{__init_.py => __init__.py} (100%) rename datetime/{__init_.py => __init__.py} (100%) rename fortune/{__init_.py => __init__.py} (100%) rename gnome_dictionary/{__init_.py => __init__.py} (100%) rename gnote/{__init_.py => __init__.py} (100%) rename goldendict/{__init_.py => __init__.py} (100%) rename google_translate/{__init_.py => __init__.py} (100%) rename ip/{__init_.py => __init__.py} (100%) rename kill/{__init_.py => __init__.py} (100%) rename locate/{__init_.py => __init__.py} (100%) rename mathematica_eval/{__init_.py => __init__.py} (100%) rename multi_google_translate/{__init_.py => __init__.py} (100%) rename pacman/{__init_.py => __init__.py} (100%) rename pass/{__init_.py => __init__.py} (100%) rename pidgin/{__init_.py => __init__.py} (100%) rename scrot/{__init_.py => __init__.py} (100%) rename tex_to_unicode/{__init_.py => __init__.py} (100%) rename tomboy/{__init_.py => __init__.py} (100%) rename trash/{__init_.py => __init__.py} (100%) rename units/{__init_.py => __init__.py} (100%) rename virtualbox/{__init_.py => __init__.py} (100%) rename vpn/{__init_.py => __init__.py} (100%) rename window_switcher/{__init_.py => __init__.py} (100%) rename youtube/{__init_.py => __init__.py} (100%) rename zeal/{__init_.py => __init__.py} (100%) diff --git a/atom_projects/__init_.py b/atom_projects/__init__.py similarity index 100% rename from atom_projects/__init_.py rename to atom_projects/__init__.py diff --git a/base_converter/__init_.py b/base_converter/__init__.py similarity index 100% rename from base_converter/__init_.py rename to base_converter/__init__.py diff --git a/copyq/__init_.py b/copyq/__init__.py similarity index 100% rename from copyq/__init_.py rename to copyq/__init__.py diff --git a/currency_converter/__init_.py b/currency_converter/__init__.py similarity index 100% rename from currency_converter/__init_.py rename to currency_converter/__init__.py diff --git a/datetime/__init_.py b/datetime/__init__.py similarity index 100% rename from datetime/__init_.py rename to datetime/__init__.py diff --git a/fortune/__init_.py b/fortune/__init__.py similarity index 100% rename from fortune/__init_.py rename to fortune/__init__.py diff --git a/gnome_dictionary/__init_.py b/gnome_dictionary/__init__.py similarity index 100% rename from gnome_dictionary/__init_.py rename to gnome_dictionary/__init__.py diff --git a/gnote/__init_.py b/gnote/__init__.py similarity index 100% rename from gnote/__init_.py rename to gnote/__init__.py diff --git a/goldendict/__init_.py b/goldendict/__init__.py similarity index 100% rename from goldendict/__init_.py rename to goldendict/__init__.py diff --git a/google_translate/__init_.py b/google_translate/__init__.py similarity index 100% rename from google_translate/__init_.py rename to google_translate/__init__.py diff --git a/ip/__init_.py b/ip/__init__.py similarity index 100% rename from ip/__init_.py rename to ip/__init__.py diff --git a/kill/__init_.py b/kill/__init__.py similarity index 100% rename from kill/__init_.py rename to kill/__init__.py diff --git a/locate/__init_.py b/locate/__init__.py similarity index 100% rename from locate/__init_.py rename to locate/__init__.py diff --git a/mathematica_eval/__init_.py b/mathematica_eval/__init__.py similarity index 100% rename from mathematica_eval/__init_.py rename to mathematica_eval/__init__.py diff --git a/multi_google_translate/__init_.py b/multi_google_translate/__init__.py similarity index 100% rename from multi_google_translate/__init_.py rename to multi_google_translate/__init__.py diff --git a/pacman/__init_.py b/pacman/__init__.py similarity index 100% rename from pacman/__init_.py rename to pacman/__init__.py diff --git a/pass/__init_.py b/pass/__init__.py similarity index 100% rename from pass/__init_.py rename to pass/__init__.py diff --git a/pidgin/__init_.py b/pidgin/__init__.py similarity index 100% rename from pidgin/__init_.py rename to pidgin/__init__.py diff --git a/scrot/__init_.py b/scrot/__init__.py similarity index 100% rename from scrot/__init_.py rename to scrot/__init__.py diff --git a/tex_to_unicode/__init_.py b/tex_to_unicode/__init__.py similarity index 100% rename from tex_to_unicode/__init_.py rename to tex_to_unicode/__init__.py diff --git a/tomboy/__init_.py b/tomboy/__init__.py similarity index 100% rename from tomboy/__init_.py rename to tomboy/__init__.py diff --git a/trash/__init_.py b/trash/__init__.py similarity index 100% rename from trash/__init_.py rename to trash/__init__.py diff --git a/units/__init_.py b/units/__init__.py similarity index 100% rename from units/__init_.py rename to units/__init__.py diff --git a/virtualbox/__init_.py b/virtualbox/__init__.py similarity index 100% rename from virtualbox/__init_.py rename to virtualbox/__init__.py diff --git a/vpn/__init_.py b/vpn/__init__.py similarity index 100% rename from vpn/__init_.py rename to vpn/__init__.py diff --git a/window_switcher/__init_.py b/window_switcher/__init__.py similarity index 100% rename from window_switcher/__init_.py rename to window_switcher/__init__.py diff --git a/youtube/__init_.py b/youtube/__init__.py similarity index 100% rename from youtube/__init_.py rename to youtube/__init__.py diff --git a/zeal/__init_.py b/zeal/__init__.py similarity index 100% rename from zeal/__init_.py rename to zeal/__init__.py From 1791991fe6eb63ddd70504f780c51b2cfe3b06be Mon Sep 17 00:00:00 2001 From: iyzana <16743652+iyzana@users.noreply.github.com> Date: Tue, 8 Dec 2020 22:46:26 +0100 Subject: [PATCH 031/355] [units] v1.2 including to time conversion --- units/__init__.py | 61 +++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/units/__init__.py b/units/__init__.py index 40a6a871..b8e67466 100644 --- a/units/__init__.py +++ b/units/__init__.py @@ -17,9 +17,9 @@ __iid__ = "PythonInterface/v0.1" __prettyname__ = "GNU Units" -__version__ = "1.1" +__version__ = "1.2" __trigger__ = "units " -__author__ = "Manuel Schneider" +__author__ = "Manuel Schneider, iyzana" __dependencies__ = ["units"] if which("units") is None: @@ -30,33 +30,54 @@ icon = ":python_module" regex = re.compile(r"(\S+)(?:\s+to)\s+(\S+)") +unitListOutput = re.compile(r"(\d+(e[+-]\d{2,})?;)+[\d.]+(e[+-]\d{2,})?") -def handleQuery(query): +def getUnitsResult(args): + command = ['units', '--terse', '--'] + list(args) + query = "units -t -- %s" % ' '.join(args) + try: + output = sp.check_output(command, stderr=sp.STDOUT).decode().strip() + + # usually we want terse output, but when we get a unit-list output + # it looks like this 1;124;18;11;14.025322 which is not friendly + # so we're falling back to not quite terse output + if unitListOutput.fullmatch(output): + command = ['units', '--strict', '--one-line', + '--quiet', '--'] + list(args) + query = "units -s1q -- %s" % ' '.join(args) + output = sp.check_output( + command, stderr=sp.STDOUT).decode().strip() + + return (output, query, True) + except sp.CalledProcessError as e: + return (e.stdout.decode().strip().splitlines()[0], query, False) + + +def handleQuery(query): if query.isTriggered: args = query.string.split() - item = Item(id='python.gnu_units', icon=icon, completion=query.rawString) + item = Item(id='python.gnu_units', icon=icon, + completion=query.rawString) if args: - try: - item.text = sp.check_output(['units', '-t'] + query.string.split(), stderr=sp.STDOUT).decode().strip() - item.addAction(ClipAction("Copy to clipboard", item.text)) - except sp.CalledProcessError as e: - item.text = e.stdout.decode().strip().partition('\n')[0] - item.subtext = "Result of 'units -t %s'" % query.string + result, command, success = getUnitsResult(args) + item.text = result + item.subtext = "Result of '%s'" % command + item.addAction(ClipAction("Copy to clipboard", item.text)) else: item.text = "Empty input" - item.subtext = "Enter something to convert" + item.subtext = "Enter a query of the form []" return item - else: match = regex.fullmatch(query.string.strip()) if match: args = match.group(1, 2) - try: - item = Item(id='python.gnu_units', icon=icon, completion=query.rawString) - item.text = sp.check_output(['units', '-t'] + list(args)).decode().strip() - item.subtext = "Result of 'units -t %s %s'" % args - item.addAction(ClipAction("Copy to clipboard", item.text)) - return item - except sp.CalledProcessError as e: - pass + result, command, success = getUnitsResult(args) + if not success: + return + item = Item(id='python.gnu_units', icon=icon, + completion=query.rawString) + item.text = result + item.subtext = "Result of '%s'" % command + item.addAction(ClipAction("Copy to clipboard", item.text)) + return item From 3feac2e4ae8d3eb497d5e15b1998b2769a4a193b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 9 Dec 2020 23:56:04 +0100 Subject: [PATCH 032/355] add ignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..bee8a64b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ From ecc0429d1689f297e5fafcc53c08d2af689d1cea Mon Sep 17 00:00:00 2001 From: Andreas Dominik Preikschat Date: Thu, 10 Dec 2020 00:44:40 +0100 Subject: [PATCH 033/355] [timer] Use dbus instead of notify-send --- timer/__init__.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/timer/__init__.py b/timer/__init__.py index a2cb44d6..671c268a 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -12,20 +12,25 @@ from albertv0 import * from threading import Timer from time import strftime, time, localtime +import dbus import os import subprocess __iid__ = "PythonInterface/v0.1" __prettyname__ = "Timer" -__version__ = "1.1" +__version__ = "1.2" __trigger__ = "timer " -__author__ = "Manuel Schneider, Andreas Preikschat" -__dependencies__ = [] +__author__ = "manuelschneid3r, googol42" +__dependencies__ = ["dbus"] iconPath = os.path.dirname(__file__)+"/time.svg" soundPath = os.path.dirname(__file__)+"/bing.wav" timers = [] +dbusItem = "org.freedesktop.Notifications" +dbusPath = "/org/freedesktop/Notifications" +dbusInterface = "org.freedesktop.Notifications" + class AlbertTimer(Timer): @@ -35,11 +40,13 @@ def timeout(): subprocess.Popen(["aplay", soundPath]) global timers timers.remove(self) - subtext="Timed out at %s" % strftime("%X", localtime(self.end)) - if self.name: - subprocess.Popen(['notify-send', 'Timer "%s"' % self.name, '-t', '0', subtext]) - else: - subprocess.Popen(['notify-send', 'Timer', '-t', '0', subtext]) + + title = 'Timer "%s"' % self.name if self.name else 'Timer' + text = "Timed out at %s" % strftime("%X", localtime(self.end)) + + bus = dbus.SessionBus() + notify = dbus.Interface(bus.get_object(dbusItem, dbusPath), dbusInterface) + notify.Notify(__prettyname__, 0, iconPath, title, text, '', '', 0) super().__init__(interval=interval, function=timeout) self.interval = interval From 294599c445fa141826e25e0c7c82073c5c02dfa5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 10 Dec 2020 03:28:32 +0100 Subject: [PATCH 034/355] [docker] New extension prototype --- docker/__init__.py | 86 +++++++++++++++++++++++++++++++++++++++++++++ docker/running.png | Bin 0 -> 1532 bytes docker/stopped.png | Bin 0 -> 1549 bytes 3 files changed, 86 insertions(+) create mode 100644 docker/__init__.py create mode 100644 docker/running.png create mode 100644 docker/stopped.png diff --git a/docker/__init__.py b/docker/__init__.py new file mode 100644 index 00000000..026be0bb --- /dev/null +++ b/docker/__init__.py @@ -0,0 +1,86 @@ +""" +Docker wrapper (prototype) +""" + +from albertv0 import * +import os +import docker +import pathlib + +__iid__ = "PythonInterface/v0.3" +__prettyname__ = "Docker" +__version__ = "0.1" +__trigger__ = "d " +__author__ = "manuelschneid3r" +__dependencies__ = ["docker"] + + +icon_running = str(pathlib.Path(__file__).parent / "running.png") +icon_stopped = str(pathlib.Path(__file__).parent / "stopped.png") + +client = None + +def initialize(): + global client + client = docker.from_env() + if client: + return + client = docker.DockerClient(base_url='unix://var/run/docker.sock') + if not client: + raise "fcckit" + + +def build_container_item(container): + item + +def handleQuery(query): + if query.isValid and query.isTriggered: + + query.disableSort() + + items = [] + + for c in client.containers.list(all=True): + + # Create dynamic actions + if c.status == 'running': + actions = [ + FuncAction("Stop container", lambda c=c: c.stop()), + FuncAction("Restart", lambda c=c: c.restart()), + ] + else: + actions = [FuncAction("Start", lambda c=c: c.start())] + actions.extend([ + TermAction("Logs", ["docker", "logs", "-f", c.id], + behavior=TermAction.CloseBehavior.DoNotClose), + FuncAction("Remove (forced, with volumes)", lambda c=c: c.remove(v=True, force=True)), + ClipAction("Copy id to clipboard", c.id) + ]) + + item = Item( + id=c.id, + text="%s %s" % (c.name, ", ".join(c.image.tags)), + subtext=c.id, + icon=icon_running if c.status == 'running' else icon_stopped, + completion=query.rawString, + actions=actions + ) + + items.append(item) + + for i in reversed(client.images.list()): + item = Item( + id=i.short_id, + text=str(i.tags), + subtext=i.id, + icon=icon_stopped, + completion=query.rawString, + actions=[ + FuncAction("Run with commmand: %s" % query.string, lambda i=i: client.containers.run(i, query.string)), + FuncAction("Remove", lambda i=i: i.remove()) + ] + ) + + items.append(item) + + return items diff --git a/docker/running.png b/docker/running.png new file mode 100644 index 0000000000000000000000000000000000000000..4b004176255af0d33e67da6836b160f898723c7c GIT binary patch literal 1532 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 literal 0 HcmV?d00001 From 0abce64c2df31812e5062bd5dd9edcd15c5934f4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 11 Dec 2020 20:10:02 +0100 Subject: [PATCH 035/355] [aur] add yay helper --- aur/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aur/__init__.py b/aur/__init__.py index 5a3d0f7a..e0c9aaba 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -18,9 +18,9 @@ __iid__ = "PythonInterface/v0.3" __prettyname__ = "Archlinux User Repository" -__version__ = "1.2" +__version__ = "1.3" __trigger__ = "aur " -__author__ = "Manuel Schneider" +__author__ = "manuelschneid3r" __dependencies__ = [] iconPath = os.path.dirname(__file__)+"/arch.svg" @@ -31,6 +31,8 @@ install_cmdline = "yaourt -S aur/%s" elif which("pacaur"): install_cmdline = "pacaur -S aur/%s" +elif which("yay"): + install_cmdline = "yay -S aur/%s" def handleQuery(query): if not query.isTriggered: From 7d2cef21034ea4d0c842d4e6a4cd716ae0ca46b1 Mon Sep 17 00:00:00 2001 From: Florian Adamsky Date: Sat, 12 Dec 2020 19:17:46 +0100 Subject: [PATCH 036/355] [texdoc] Add texdoc plugin --- texdoc/__init__.py | 67 +++++++++++ texdoc/texdoc-logo.svg | 259 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 texdoc/__init__.py create mode 100644 texdoc/texdoc-logo.svg diff --git a/texdoc/__init__.py b/texdoc/__init__.py new file mode 100644 index 00000000..990390e6 --- /dev/null +++ b/texdoc/__init__.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +"""texdoc extension + +This is an extension to search for LaTeX documentation. + +Synopsis: """ + +import re +import subprocess + +from shutil import which +from pathlib import Path +from albertv0 import * + +__iid__ = 'PythonInterface/v0.3' +__prettyname__ = 'TeXdoc' +__version__ = '1.0' +__trigger__ = 'td' +__author__ = 'Florian Adamsky (@cit)' +__dependencies__ = ['texdoc'] + +iconPath = Path(__file__).parent / 'texdoc-logo.svg' +texdoc_cmd = ['texdoc', '-I', '-q', '-s', '-M'] + +if which("texdoc") is None: + raise Exception("'texdoc' is not in $PATH.") + +def handleQuery(query): + if not query.isTriggered: + return + + query.disableSort() + + stripped_query = query.string.strip() + + if stripped_query: + process = subprocess.run(texdoc_cmd + [stripped_query], + stdout=subprocess.PIPE) + texdoc_output = process.stdout.decode('utf-8') + + results = [] + for line in texdoc_output.split("\n"): + + match = re.search('\t(/.*/)([\w\.-]+)\t\t', line, re.IGNORECASE) + if match: + directory = match.group(1).strip() + filename = match.group(2).strip() + full_path = directory.join(['/', filename]) + + results.append(Item(id = __prettyname__, + icon = str(iconPath), + text = filename, + subtext = directory, + completion = full_path, + actions = [ + ProcAction(text = 'This action opens the documentation.', + commandline=['xdg-open', full_path]) + ])) + + return results + else: + return Item(id = __prettyname__, + icon = str(iconPath), + text = __prettyname__, + subtext = 'Enter a query to search with texdoc', + completion = query.rawString) diff --git a/texdoc/texdoc-logo.svg b/texdoc/texdoc-logo.svg new file mode 100644 index 00000000..47784fc3 --- /dev/null +++ b/texdoc/texdoc-logo.svg @@ -0,0 +1,259 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 660fa349215e236f23abff4d6c584e1ebfcd863c Mon Sep 17 00:00:00 2001 From: Rosen Tihomirov Date: Mon, 14 Dec 2020 12:48:30 +0200 Subject: [PATCH 037/355] [copyq] Disable albert sorting (#102) --- copyq/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/copyq/__init__.py b/copyq/__init__.py index f3df78a7..5b094d5b 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -67,6 +67,7 @@ def copyq_get_all(): def handleQuery(query): if query.isTriggered: + query.disableSort() items = [] pattern = re.compile(query.string, re.IGNORECASE) From 19ef60c0d9397a725730f997fa13e1c57f8afe41 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 14 Dec 2020 20:49:14 +0100 Subject: [PATCH 038/355] [vbox] Update dependecy --- virtualbox/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py index 396136e4..fb1f8a20 100644 --- a/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -21,7 +21,7 @@ __version__ = "1.2" __trigger__ = "vbox " __author__ = "Manuel Schneider" -__dependencies__ = ['pyvbox'] +__dependencies__ = ['virtualbox'] vbox = None From 253c07d5f2e1d6271faed9d7c7d0ee749cb9aa44 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 14 Dec 2020 20:57:54 +0100 Subject: [PATCH 039/355] Change module name (iid v0.4) --- .archive/bitfinex/__init__.py | 2 +- .archive/coinmarketcap/__init__.py | 2 +- .archive/dango_emoji/__init__.py | 2 +- .archive/dango_kao/__init__.py | 2 +- api_test/__init__.py | 2 +- arch_wiki/__init__.py | 2 +- atom_projects/__init__.py | 2 +- aur/__init__.py | 2 +- base_converter/__init__.py | 2 +- binance/__init__.py | 2 +- bitwarden/__init__.py | 2 +- copyq/__init__.py | 2 +- currency_converter/__init__.py | 2 +- datetime/__init__.py | 2 +- docker/__init__.py | 2 +- fortune/__init__.py | 2 +- gnome_dictionary/__init__.py | 2 +- gnote/__init__.py | 2 +- goldendict/__init__.py | 2 +- google_translate/__init__.py | 2 +- ip/__init__.py | 2 +- kill/__init__.py | 2 +- locate/__init__.py | 2 +- lpass/__init__.py | 2 +- mathematica_eval/__init__.py | 2 +- multi_google_translate/__init__.py | 2 +- node_eval/__init__.py | 2 +- npm/__init__.py | 2 +- packagist/__init__.py | 2 +- pacman/__init__.py | 2 +- pass/__init__.py | 2 +- php_eval/__init__.py | 2 +- pidgin/__init__.py | 2 +- pomodoro/__init__.py | 2 +- python_eval/__init__.py | 2 +- scrot/__init__.py | 2 +- tex_to_unicode/__init__.py | 2 +- texdoc/__init__.py | 2 +- timer/__init__.py | 2 +- tomboy/__init__.py | 2 +- trash/__init__.py | 2 +- unicode_emoji/__init__.py | 2 +- units/__init__.py | 2 +- virtualbox/__init__.py | 2 +- vpn/__init__.py | 2 +- wikipedia/__init__.py | 2 +- window_switcher/__init__.py | 2 +- youtube/__init__.py | 2 +- zeal/__init__.py | 2 +- 49 files changed, 49 insertions(+), 49 deletions(-) diff --git a/.archive/bitfinex/__init__.py b/.archive/bitfinex/__init__.py index 9053f8f2..7e1d97fa 100644 --- a/.archive/bitfinex/__init__.py +++ b/.archive/bitfinex/__init__.py @@ -6,7 +6,7 @@ filter [filter]""" -from albertv0 import * +from albert import * import time import os import urllib.request diff --git a/.archive/coinmarketcap/__init__.py b/.archive/coinmarketcap/__init__.py index 3513cd14..c688eac7 100644 --- a/.archive/coinmarketcap/__init__.py +++ b/.archive/coinmarketcap/__init__.py @@ -7,7 +7,7 @@ Synopsis: [filter]""" -from albertv0 import * +from albert import * from threading import Thread, Event from locale import format as lformat from urllib import request diff --git a/.archive/dango_emoji/__init__.py b/.archive/dango_emoji/__init__.py index b13b075c..390414f7 100644 --- a/.archive/dango_emoji/__init__.py +++ b/.archive/dango_emoji/__init__.py @@ -9,7 +9,7 @@ Synopsis: """ -from albertv0 import * +from albert import * import json import os import urllib.error diff --git a/.archive/dango_kao/__init__.py b/.archive/dango_kao/__init__.py index 0df90a20..74dbbef1 100755 --- a/.archive/dango_kao/__init__.py +++ b/.archive/dango_kao/__init__.py @@ -7,7 +7,7 @@ Synopsis: """ -from albertv0 import * +from albert import * import os import json import urllib.error diff --git a/api_test/__init__.py b/api_test/__init__.py index 9336b077..b5875c00 100644 --- a/api_test/__init__.py +++ b/api_test/__init__.py @@ -9,7 +9,7 @@ Synopsis: [delay|throw] """ -from albertv0 import * +from albert import * import os from time import sleep diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index ed457dd1..5a705360 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -4,7 +4,7 @@ Synopsis: """ -from albertv0 import * +from albert import * from urllib import request, parse import json import os diff --git a/atom_projects/__init__.py b/atom_projects/__init__.py index da6b96fe..945724b0 100644 --- a/atom_projects/__init__.py +++ b/atom_projects/__init__.py @@ -12,7 +12,7 @@ import cson -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Atom Projects" diff --git a/aur/__init__.py b/aur/__init__.py index e0c9aaba..e0fb63da 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -7,7 +7,7 @@ Synopsis: """ -from albertv0 import * +from albert import * from shutil import which from datetime import datetime from shlex import split diff --git a/base_converter/__init__.py b/base_converter/__init__.py index 23348950..183414f8 100644 --- a/base_converter/__init__.py +++ b/base_converter/__init__.py @@ -8,7 +8,7 @@ import numpy as np -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Base Converter" diff --git a/binance/__init__.py b/binance/__init__.py index 7befd625..110519ef 100644 --- a/binance/__init__.py +++ b/binance/__init__.py @@ -6,7 +6,7 @@ filter [filter]""" -from albertv0 import * +from albert import * import time import os import urllib.request diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 0d0adb65..422028ba 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -7,7 +7,7 @@ from shutil import which from subprocess import run -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Bitwarden" diff --git a/copyq/__init__.py b/copyq/__init__.py index 5b094d5b..c975648d 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -10,7 +10,7 @@ import subprocess from shutil import which -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "CopyQ" diff --git a/currency_converter/__init__.py b/currency_converter/__init__.py index ad8e32db..bd0ae271 100644 --- a/currency_converter/__init__.py +++ b/currency_converter/__init__.py @@ -11,7 +11,7 @@ from urllib.request import urlopen from xml.etree import ElementTree -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Currency converter" diff --git a/datetime/__init__.py b/datetime/__init__.py index 2bd3702e..c69982c6 100644 --- a/datetime/__init__.py +++ b/datetime/__init__.py @@ -13,7 +13,7 @@ from datetime import datetime, date import time -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "DateTime" diff --git a/docker/__init__.py b/docker/__init__.py index 026be0bb..53bc2630 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -2,7 +2,7 @@ Docker wrapper (prototype) """ -from albertv0 import * +from albert import * import os import docker import pathlib diff --git a/fortune/__init__.py b/fortune/__init__.py index 6695bfb8..5dc00f6e 100644 --- a/fortune/__init__.py +++ b/fortune/__init__.py @@ -9,7 +9,7 @@ import subprocess as sp from shutil import which -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Fortune" diff --git a/gnome_dictionary/__init__.py b/gnome_dictionary/__init__.py index a4d8092f..591ec2ed 100644 --- a/gnome_dictionary/__init__.py +++ b/gnome_dictionary/__init__.py @@ -9,7 +9,7 @@ from shutil import which from subprocess import run -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Gnome Dictionary" diff --git a/gnote/__init__.py b/gnote/__init__.py index 7b76032f..29fcd320 100644 --- a/gnote/__init__.py +++ b/gnote/__init__.py @@ -10,7 +10,7 @@ from dbus import DBusException, Interface, SessionBus -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Gnote" diff --git a/goldendict/__init__.py b/goldendict/__init__.py index d77ae7b4..8751b90c 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -7,7 +7,7 @@ from shutil import which from subprocess import run -from albertv0 import Item, ProcAction, iconLookup +from albert import Item, ProcAction, iconLookup __iid__ = "PythonInterface/v0.1" __prettyname__ = "GoldenDict" diff --git a/google_translate/__init__.py b/google_translate/__init__.py index 9c8bd6b0..039ab41f 100644 --- a/google_translate/__init__.py +++ b/google_translate/__init__.py @@ -10,7 +10,7 @@ import urllib.parse import urllib.request -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Google Translate" diff --git a/ip/__init__.py b/ip/__init__.py index 125e638a..240ca995 100644 --- a/ip/__init__.py +++ b/ip/__init__.py @@ -7,7 +7,7 @@ import socket from urllib import request -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "IP Addresses" diff --git a/kill/__init__.py b/kill/__init__.py index d2396722..659fff48 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -9,7 +9,7 @@ import os from signal import SIGKILL, SIGTERM -from albertv0 import FuncAction, Item, iconLookup +from albert import FuncAction, Item, iconLookup __iid__ = "PythonInterface/v0.1" __prettyname__ = "Kill Process" diff --git a/locate/__init__.py b/locate/__init__.py index 6c05d884..03b0c4dc 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -15,7 +15,7 @@ import subprocess from shutil import which -from albertv0 import Item, TermAction, UrlAction, iconLookup +from albert import Item, TermAction, UrlAction, iconLookup __iid__ = "PythonInterface/v0.1" __prettyname__ = "Locate" diff --git a/lpass/__init__.py b/lpass/__init__.py index dc7a9f57..e2523aab 100644 --- a/lpass/__init__.py +++ b/lpass/__init__.py @@ -5,7 +5,7 @@ Synopsis: """ from shutil import which -from albertv0 import * +from albert import * import subprocess import re import os diff --git a/mathematica_eval/__init__.py b/mathematica_eval/__init__.py index 3b4d8d16..71339e25 100644 --- a/mathematica_eval/__init__.py +++ b/mathematica_eval/__init__.py @@ -8,7 +8,7 @@ from shutil import which from tempfile import NamedTemporaryFile -from albertv0 import ClipAction, Item, iconLookup +from albert import ClipAction, Item, iconLookup __iid__ = 'PythonInterface/v0.1' __prettyname__ = 'Mathematica eval' diff --git a/multi_google_translate/__init__.py b/multi_google_translate/__init__.py index 8038ea65..b27e6bff 100644 --- a/multi_google_translate/__init__.py +++ b/multi_google_translate/__init__.py @@ -16,7 +16,7 @@ import urllib.request from time import sleep -from albertv0 import (ClipAction, Item, ProcAction, UrlAction, configLocation, +from albert import (ClipAction, Item, ProcAction, UrlAction, configLocation, iconLookup) __iid__ = "PythonInterface/v0.2" diff --git a/node_eval/__init__.py b/node_eval/__init__.py index 22a59158..1bc57b7c 100644 --- a/node_eval/__init__.py +++ b/node_eval/__init__.py @@ -4,7 +4,7 @@ import os import subprocess -from albertv0 import * +from albert import * from shutil import which __iid__ = 'PythonInterface/v0.1' diff --git a/npm/__init__.py b/npm/__init__.py index 9a6f384a..a3cc47e5 100644 --- a/npm/__init__.py +++ b/npm/__init__.py @@ -6,7 +6,7 @@ Synopsis: [filter]""" -from albertv0 import * +from albert import * from shutil import which import os import json diff --git a/packagist/__init__.py b/packagist/__init__.py index cf70bca6..c7cf659a 100644 --- a/packagist/__init__.py +++ b/packagist/__init__.py @@ -7,7 +7,7 @@ Synopsis: [tag|type] """ -from albertv0 import * +from albert import * import os import json import urllib.request diff --git a/pacman/__init__.py b/pacman/__init__.py index 63cb8ed9..94dd9931 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -13,7 +13,7 @@ import subprocess from shutil import which -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "PacMan" diff --git a/pass/__init__.py b/pass/__init__.py index 95780bf7..564fffe5 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -12,7 +12,7 @@ import os from shutil import which -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.3" __prettyname__ = "Pass" diff --git a/php_eval/__init__.py b/php_eval/__init__.py index 95e93069..61d4ade4 100644 --- a/php_eval/__init__.py +++ b/php_eval/__init__.py @@ -4,7 +4,7 @@ import os import subprocess -from albertv0 import * +from albert import * from shutil import which __iid__ = 'PythonInterface/v0.1' diff --git a/pidgin/__init__.py b/pidgin/__init__.py index fc2db298..722af7d3 100644 --- a/pidgin/__init__.py +++ b/pidgin/__init__.py @@ -6,7 +6,7 @@ import dbus -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Pidgin" diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 913a80ea..7a1339bb 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -6,7 +6,7 @@ Synopsis: [duration [break duration [long break duration [count]]]]""" -from albertv0 import * +from albert import * from shutil import which import subprocess import threading diff --git a/python_eval/__init__.py b/python_eval/__init__.py index 13dedabc..fb9b5294 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -4,7 +4,7 @@ Synopsis: """ -from albertv0 import * +from albert import * from math import * from builtins import pow try: diff --git a/scrot/__init__.py b/scrot/__init__.py index 005930c2..5bf36fb7 100644 --- a/scrot/__init__.py +++ b/scrot/__init__.py @@ -13,7 +13,7 @@ import tempfile from shutil import which -from albertv0 import FuncAction, Item, iconLookup +from albert import FuncAction, Item, iconLookup __iid__ = "PythonInterface/v0.1" __prettyname__ = "SCReenshOT utility" diff --git a/tex_to_unicode/__init__.py b/tex_to_unicode/__init__.py index abf1f5e7..0b1582d5 100644 --- a/tex_to_unicode/__init__.py +++ b/tex_to_unicode/__init__.py @@ -9,7 +9,7 @@ from pylatexenc.latex2text import LatexNodes2Text -from albertv0 import * +from albert import * __iid__ = 'PythonInterface/v0.1' __prettyname__ = 'TeX to unicode' diff --git a/texdoc/__init__.py b/texdoc/__init__.py index 990390e6..372f97cb 100644 --- a/texdoc/__init__.py +++ b/texdoc/__init__.py @@ -11,7 +11,7 @@ from shutil import which from pathlib import Path -from albertv0 import * +from albert import * __iid__ = 'PythonInterface/v0.3' __prettyname__ = 'TeXdoc' diff --git a/timer/__init__.py b/timer/__init__.py index 671c268a..d88c92be 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -9,7 +9,7 @@ Synopsis: [[[hours]:][minutes]:]seconds [name]""" -from albertv0 import * +from albert import * from threading import Timer from time import strftime, time, localtime import dbus diff --git a/tomboy/__init__.py b/tomboy/__init__.py index eaae4fa7..284384a3 100644 --- a/tomboy/__init__.py +++ b/tomboy/__init__.py @@ -10,7 +10,7 @@ from dbus import DBusException, Interface, SessionBus -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Tomboy" diff --git a/trash/__init__.py b/trash/__init__.py index a684c331..7531c476 100644 --- a/trash/__init__.py +++ b/trash/__init__.py @@ -9,7 +9,7 @@ import re -from albertv0 import Item, UrlAction, iconLookup +from albert import Item, UrlAction, iconLookup __iid__ = "PythonInterface/v0.1" __prettyname__ = "Trash" diff --git a/unicode_emoji/__init__.py b/unicode_emoji/__init__.py index 28359776..4f6daaaf 100644 --- a/unicode_emoji/__init__.py +++ b/unicode_emoji/__init__.py @@ -4,7 +4,7 @@ Synopsis: [filter]""" -from albertv0 import * +from albert import * from collections import namedtuple from threading import Thread import datetime diff --git a/units/__init__.py b/units/__init__.py index b8e67466..3f429b6d 100644 --- a/units/__init__.py +++ b/units/__init__.py @@ -13,7 +13,7 @@ import subprocess as sp from shutil import which -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "GNU Units" diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py index fb1f8a20..6e86ecbf 100644 --- a/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -14,7 +14,7 @@ VBoxErrorInvalidVmState, VBoxErrorIprtError, VBoxErrorObjectNotFound) -from albertv0 import FuncAction, Item, critical, iconLookup +from albert import FuncAction, Item, critical, iconLookup __iid__ = "PythonInterface/v0.1" __prettyname__ = "Virtual Box" diff --git a/vpn/__init__.py b/vpn/__init__.py index 77f04516..47c7d755 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -5,7 +5,7 @@ import subprocess from collections import namedtuple -from albertv0 import * +from albert import * from shutil import which diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index bd59ff68..4deb3556 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -4,7 +4,7 @@ Synopsis: """ -from albertv0 import * +from albert import * from locale import getdefaultlocale from urllib import request, parse import json diff --git a/window_switcher/__init__.py b/window_switcher/__init__.py index 26fc1556..dd5966a6 100644 --- a/window_switcher/__init__.py +++ b/window_switcher/__init__.py @@ -8,7 +8,7 @@ from collections import namedtuple from shutil import which -from albertv0 import Item, ProcAction, iconLookup +from albert import Item, ProcAction, iconLookup Window = namedtuple("Window", ["wid", "desktop", "wm_class", "host", "wm_name"]) diff --git a/youtube/__init__.py b/youtube/__init__.py index f5e10bd1..16cacd75 100644 --- a/youtube/__init__.py +++ b/youtube/__init__.py @@ -11,7 +11,7 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen -from albertv0 import Item, UrlAction, iconLookup, critical, debug, info +from albert import Item, UrlAction, iconLookup, critical, debug, info __iid__ = 'PythonInterface/v0.1' __prettyname__ = 'Youtube' diff --git a/zeal/__init__.py b/zeal/__init__.py index 059bbc03..7b62a586 100644 --- a/zeal/__init__.py +++ b/zeal/__init__.py @@ -7,7 +7,7 @@ from shutil import which from subprocess import run -from albertv0 import * +from albert import * __iid__ = "PythonInterface/v0.1" __prettyname__ = "Zeal" From 674fcffb76451b3025e7994b568b55e1524b1b44 Mon Sep 17 00:00:00 2001 From: Keating950 Date: Wed, 9 Dec 2020 10:49:05 -0500 Subject: [PATCH 040/355] Python-style base prefixes to detect source base --- base_converter/__init__.py | 40 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/base_converter/__init__.py b/base_converter/__init__.py index 183414f8..cfa24c5a 100644 --- a/base_converter/__init__.py +++ b/base_converter/__init__.py @@ -3,12 +3,16 @@ """Convert representations of numbers. Synopsis: - - [padding]""" + + [padding] + + where is a literal of the form '0bXXX' (binary), '0XXX' (octal), + or '0xXXX' (hexadecimal).""" import numpy as np +from collections import defaultdict -from albert import * +from albert import Item, ClipAction __iid__ = "PythonInterface/v0.1" __prettyname__ = "Base Converter" @@ -17,12 +21,21 @@ __author__ = "Manuel Schneider" __dependencies__ = ["numpy"] -base_keywords = {"bin": 2, "oct": 8, "dec": 10, "hex": 16} -def buildItem(completion, src, dst, number, padding=0): +class keyed_defaultdict(defaultdict): + def __missing__(self, key): + return self.default_factory(key) + + +base_prefixes = keyed_defaultdict(lambda k: 8 if k[0] == "0" and len(k) > 1 else 10) +base_prefixes["0b"] = 2 +base_prefixes["0x"] = 16 + + +def buildItem(completion, dst, number, padding=0): item = Item(id=__prettyname__, completion=completion) try: - src = int(src) + src = base_prefixes[number[:2]] dst = int(dst) padding = int(padding) integer = int(number, src) @@ -36,26 +49,27 @@ def buildItem(completion, src, dst, number, padding=0): item.subtext = str(e) return item + def handleQuery(query): if query.isTriggered: fields = query.string.split() - if len(fields) == 3: - return buildItem(query.rawString, fields[0], fields[1], fields[2]) + if len(fields) == 2: + return buildItem(query.rawString, fields[0], fields[1]) else: item = Item(id=__prettyname__, completion=query.rawString) item.text = __prettyname__ - item.subtext = "Enter a query in the form of \"<srcbase> <dstbase> <number>\"" + item.subtext = "Enter a query in the form of \"<dstbase> <number>\"" return item else: fields = query.string.split() - if len(fields) < 2 or fields[0] not in base_keywords: + if len(fields) < 2: return - src = base_keywords[fields[0]] + src = base_prefixes[fields[:3]] number = fields[1] padding = 0 if len(fields) < 3 else fields[2] results = [] - for dst in sorted(base_keywords.values()): + for dst in sorted(base_prefixes.values().append(8)): if dst == src: continue - results.append(buildItem(query.rawString, src, dst, number, padding)) + results.append(buildItem(query.rawString, dst, number, padding)) return results From 7d58914f54a3f996361f1fa4fa479902510d522e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 15 Dec 2020 12:29:13 +0100 Subject: [PATCH 041/355] Adpot APIv0.4 changes --- .archive/bitfinex/__init__.py | 14 +++++----- .archive/coinmarketcap/__init__.py | 14 +++++----- .archive/dango_emoji/__init__.py | 20 ++++++-------- .archive/dango_kao/__init__.py | 18 +++++-------- api_test/__init__.py | 27 ++++++++++--------- arch_wiki/__init__.py | 22 +++++++-------- atom_projects/__init__.py | 20 +++++--------- aur/__init__.py | 33 +++++++++++------------ base_converter/__init__.py | 19 +++++++------ binance/__init__.py | 14 +++++----- bitwarden/__init__.py | 16 ++++------- copyq/__init__.py | 17 +++++------- currency_converter/__init__.py | 12 ++++----- datetime/__init__.py | 17 +++++------- docker/__init__.py | 15 +++++------ fortune/__init__.py | 20 +++++--------- gnome_dictionary/__init__.py | 24 +++++++---------- gnote/__init__.py | 40 +++++++++++---------------- goldendict/__init__.py | 25 +++++++---------- google_translate/__init__.py | 14 +++++----- ip/__init__.py | 13 +++++---- kill/__init__.py | 11 +++----- locate/__init__.py | 30 +++++++-------------- lpass/__init__.py | 39 +++++++++++---------------- mathematica_eval/__init__.py | 17 +++++------- multi_google_translate/__init__.py | 19 ++++++------- node_eval/__init__.py | 20 +++++--------- npm/__init__.py | 25 +++++++---------- packagist/__init__.py | 22 ++++++--------- pacman/__init__.py | 42 +++++++++++------------------ pass/__init__.py | 19 +++++-------- php_eval/__init__.py | 21 +++++---------- pidgin/__init__.py | 17 +++++------- pomodoro/__init__.py | 14 ++++------ python_eval/__init__.py | 12 ++++----- scrot/__init__.py | 21 ++++++--------- tex_to_unicode/__init__.py | 13 +++++---- texdoc/__init__.py | 22 ++++++--------- timer/__init__.py | 34 ++++++++++------------- tomboy/__init__.py | 43 +++++++++++------------------- trash/__init__.py | 7 +++-- unicode_emoji/__init__.py | 18 +++++-------- units/__init__.py | 22 +++++---------- virtualbox/__init__.py | 11 ++++---- vpn/__init__.py | 20 ++++---------- wikipedia/__init__.py | 19 ++++++------- window_switcher/__init__.py | 18 +++++-------- youtube/__init__.py | 12 ++++----- zeal/__init__.py | 26 +++++++----------- 49 files changed, 387 insertions(+), 621 deletions(-) diff --git a/.archive/bitfinex/__init__.py b/.archive/bitfinex/__init__.py index 7e1d97fa..b0b496f8 100644 --- a/.archive/bitfinex/__init__.py +++ b/.archive/bitfinex/__init__.py @@ -15,12 +15,10 @@ from collections import namedtuple from threading import Thread, Event -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "BitFinex" -__version__ = "1.0" -__trigger__ = "bfx " -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "BitFinex" +__version__ = "0.4.0" +__triggers__ = "bfx " +__authors__ = "manuelschneid3r" iconPath = os.path.dirname(__file__) + "/Bitfinex.svg" symbolsEndpoint = "https://api.bitfinex.com/v1/symbols" @@ -74,11 +72,11 @@ def finalize(): def makeItem(market): url = tradeUrl % (market.base, market.quote) return Item( - id="%s_%s%s" % (__prettyname__, market.base, market.quote), + id="%s_%s%s" % (__title__, market.base, market.quote), icon=iconPath, text="%s/%s" % (market.base, market.quote), subtext="Open the %s/%s market on bitfinex.com" % (market.base, market.quote), - completion="%s%s%s" % (__trigger__, market.base, market.quote), + completion="%s%s%s" % (__trigger_s_, market.base, market.quote), actions=[ UrlAction("Show market in browser", url), ClipAction('Copy URL to clipboard', url) diff --git a/.archive/coinmarketcap/__init__.py b/.archive/coinmarketcap/__init__.py index c688eac7..63a577b7 100644 --- a/.archive/coinmarketcap/__init__.py +++ b/.archive/coinmarketcap/__init__.py @@ -16,12 +16,10 @@ import os import json -__iid__ = "PythonInterface/v0.2" -__prettyname__ = "CoinMarketCap" -__version__ = "1.4" -__trigger__ = "cmc " -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "CoinMarketCap" +__version__ = "0.4.4" +__triggers__ = "cmc " +__authors__ = "manuelschneid3r" iconPath = os.path.dirname(__file__)+"/emblem-money.svg" thread = None @@ -124,7 +122,7 @@ def handleQuery(query): if coin.name.lower().startswith(stripped) or coin.symbol.lower().startswith(stripped): url = "https://coinmarketcap.com/currencies/%s/" % coin.identifier items.append(Item( - id=__prettyname__, + id=__title__, icon=iconPath, text="#%s %s (%s) %s$" % (coin.rank, pattern.sub(lambda m: "%s" % m.group(0), coin.name), pattern.sub(lambda m: "%s" % m.group(0), coin.symbol), coin.price), @@ -139,7 +137,7 @@ def handleQuery(query): for coin in coins: url = "https://coinmarketcap.com/currencies/%s/" % coin.identifier items.append(Item( - id=__prettyname__, + id=__title__, icon=iconPath, text="#%s %s (%s) %s$" % (coin.rank, coin.name, coin.symbol, coin.price), subtext="Change: %s/%s/%s, Cap: %s, Volume: %s" % (coin.change_hour, coin.change_day, coin.change_week, coin.cap, coin.vol), diff --git a/.archive/dango_emoji/__init__.py b/.archive/dango_emoji/__init__.py index 390414f7..886853c8 100644 --- a/.archive/dango_emoji/__init__.py +++ b/.archive/dango_emoji/__init__.py @@ -17,12 +17,10 @@ from urllib.parse import urlencode -__iid__ = "PythonInterface/v0.2" -__prettyname__ = "Dango Emoji" -__version__ = "1.1" -__trigger__ = ":" -__author__ = "David Britt" -__dependencies__ = [] +__title__ = "Dango Emoji" +__version__ = "0.4.1" +__triggers__ = ":" +__authors__ = "David Britt" iconPath = os.path.dirname(__file__) + "/dangoemoji.png" @@ -35,11 +33,9 @@ def handleQuery(query): if query.isTriggered: item = Item( - id=__prettyname__, + id=__title__, icon=icon_path, - completion=query.rawString, - text=__prettyname__, - actions=[] + text=__title__ ) if len(query.string) >= 2: @@ -58,7 +54,7 @@ def handleQuery(query): string_emojis = ''.join(all_emojis) results.append(Item( - id=__prettyname__, + id=__title__, icon=icon_path, text=string_emojis, subtext="Score > 0.025", @@ -70,7 +66,7 @@ def handleQuery(query): for emoj in json_data["results"]: results.append(Item( - id=__prettyname__, + id=__title__, icon=icon_path, text=str(emoj["text"]), subtext=str(emoj["score"]), diff --git a/.archive/dango_kao/__init__.py b/.archive/dango_kao/__init__.py index 74dbbef1..8701ecc3 100755 --- a/.archive/dango_kao/__init__.py +++ b/.archive/dango_kao/__init__.py @@ -14,12 +14,10 @@ from urllib.request import urlopen, Request from urllib.parse import urlencode -__iid__ = "PythonInterface/v0.2" -__prettyname__ = "Dango Kaomoji" -__version__ = "1.0" -__trigger__ = "kao " -__author__ = "David Britt" -__dependencies__ = [] +__title__ = "Dango Kaomoji" +__version__ = "0.4.0" +__triggers__ = "kao " +__authors__ = "David Britt" icon_path = os.path.dirname(__file__) + "/kaoicon.svg" dangoUrl = "https://customer.getdango.com/dango/api/query/kaomoji" @@ -31,11 +29,9 @@ def handleQuery(query): if query.isTriggered: item = Item( - id=__prettyname__, + id=__title__, icon=icon_path, - completion=query.rawString, - text=__prettyname__, - actions=[] + text=__title__, ) if len(query.string) >= 2: @@ -45,7 +41,7 @@ def handleQuery(query): json_data = json.loads(response.read().decode()) for emoj in json_data["items"]: results.append(Item( - id=__prettyname__, + id=__title__, icon=icon_path, text=emoj["text"], actions=[ diff --git a/api_test/__init__.py b/api_test/__init__.py index b5875c00..7597d444 100644 --- a/api_test/__init__.py +++ b/api_test/__init__.py @@ -14,12 +14,11 @@ from time import sleep -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Api Test" -__version__ = "1.0" -__trigger__ = "test " -__author__ = "Manuel Schneider" -__dependencies__ = ["whatever"] +__title__ = "Api Test" +__version__ = "0.4.2" +__triggers__ = "test " +__authors__ = "manuelschneid3r" +#__exec_deps__ = ["whatever"] iconPath = iconLookup("albert") @@ -45,7 +44,7 @@ def handleQuery(query): if query.string.startswith("delay"): sleep(2) - return Item(id=__prettyname__, + return Item(id=__title__, icon=os.path.dirname(__file__)+"/plugin.svg", text="Delayed test item", subtext="Query string: %s" % query.string) @@ -71,7 +70,7 @@ def handleQuery(query): item.icon = iconPath item.text = 'Python item containing %s' % query.string item.subtext = 'Python description' - item.completion = __trigger__ + 'Completion Harharhar' + item.completion = __triggers__ + 'Completion Harharhar' item.urgency = ItemBase.Notification # Alert, Normal info(item.icon) info(item.text) @@ -83,11 +82,11 @@ def function(): info(query.string) item.addAction(FuncAction("Print warning", lambda: warning(query.string))) results.append(item) - item = Item(id=__prettyname__, + item = Item(id=__title__, icon=os.path.dirname(__file__)+"/plugin.svg", text="This is the primary text", subtext="This is the subtext, some kind of description", - completion=__trigger__ + 'Hellooohooo!', + completion=__triggers__ + 'Hellooohooo!', urgency=ItemBase.Alert, actions=[ FuncAction(text="FuncAction", @@ -98,10 +97,14 @@ def function(): info(query.string) url="https://www.google.de"), ProcAction(text="ProcAction", commandline=["espeak", "hello"], - cwd="~"), # optional + cwd="~"), TermAction(text="TermAction", commandline=["sleep", "5"], - cwd="~/git") # optional + cwd="~/git"), + TermAction(text="TermAction", + script="[ -e issue ] && cat issue | echo /etc/issue not found.", + behavior=TermAction.CloseBehavior.DoNotClose, + cwd="/etc") ]) results.append(item) diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index 5a705360..87a61c13 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -9,12 +9,10 @@ import json import os -__iid__ = "PythonInterface/v0.3" -__prettyname__ = "Arch Wiki" -__version__ = "1.1" -__trigger__ = "awiki " -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "Arch Wiki" +__version__ = "0.4.1" +__triggers__ = "awiki " +__authors__ = "manuelschneid3r" iconPath = os.path.dirname(__file__) + "/ArchWiki.svg" baseurl = 'https://wiki.archlinux.org/api.php' @@ -48,7 +46,7 @@ def handleQuery(query): summary = data[2][i] url = data[3][i] - results.append(Item(id=__prettyname__, + results.append(Item(id=__title__, icon=iconPath, text=title, subtext=summary if summary else url, @@ -60,16 +58,14 @@ def handleQuery(query): if results: return results - return Item(id=__prettyname__, + return Item(id=__title__, icon=iconPath, text="Search '%s'" % query.string, subtext="No results. Start a online search on Arch Wiki", - completion=query.rawString, actions=[UrlAction("Open search", "https://wiki.archlinux.org/index.php?search=%s" % query.string)]) else: - return Item(id=__prettyname__, + return Item(id=__title__, icon=iconPath, - text=__prettyname__, - subtext="Enter a query to search on the Arch Wiki", - completion=query.rawString) + text=__title__, + subtext="Enter a query to search on the Arch Wiki") diff --git a/atom_projects/__init__.py b/atom_projects/__init__.py index 945724b0..e8734d28 100644 --- a/atom_projects/__init__.py +++ b/atom_projects/__init__.py @@ -8,24 +8,19 @@ import re import time from pathlib import Path -from shutil import which import cson from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Atom Projects" -__version__ = "1.0" -__trigger__ = "atom " -__author__ = "Manuel Schneider" -__dependencies__ = ["python-cson"] +__title__ = "Atom Projects" +__version__ = "0.4.0" +__triggers__ = "atom " +__authors__ = "manuelschneid3r" +__exec_deps__ = ["atom"] +__py_deps__ = ["cson"] projects_file = str(Path.home()) + "/.atom/projects.cson" - -if which("atom") is None: - raise Exception("'atom' is not in $PATH.") - iconPath = iconLookup('atom') mtime = 0 projects = [] @@ -55,11 +50,10 @@ def handleQuery(query): items = [] for project in projects: if re.search(stripped, project['title'], re.IGNORECASE): - items.append(Item(id=__prettyname__ + project['title'], + items.append(Item(id=__title__ + project['title'], icon=iconPath, text=project['title'], subtext="Group: %s" % (project['group'] if 'group' in project else "None"), - completion=query.rawString, actions=[ ProcAction(text="Open project in Atom", commandline=["atom"] + project['paths']) diff --git a/aur/__init__.py b/aur/__init__.py index e0fb63da..a6dbd699 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -10,18 +10,15 @@ from albert import * from shutil import which from datetime import datetime -from shlex import split from urllib import request, parse import json import os import re -__iid__ = "PythonInterface/v0.3" -__prettyname__ = "Archlinux User Repository" -__version__ = "1.3" -__trigger__ = "aur " -__author__ = "manuelschneid3r" -__dependencies__ = [] +__title__ = "Archlinux User Repository" +__version__ = "0.4.3" +__triggers__ = "aur " +__authors__ = "manuelschneid3r" iconPath = os.path.dirname(__file__)+"/arch.svg" baseurl = 'https://aur.archlinux.org/rpc/' @@ -56,11 +53,10 @@ def handleQuery(query): data = json.loads(response.read().decode()) if data['type'] == "error": return Item( - id=__prettyname__, + id=__title__, icon=iconPath, text="Error", - subtext=data['error'], - completion=query.rawString + subtext=data['error'] ) else: results = [] @@ -72,10 +68,10 @@ def handleQuery(query): for entry in results_json: name = entry['Name'] item = Item( - id = __prettyname__, + id = __title__, icon = iconPath, text = "%s %s (%s)" % (pattern.sub(lambda m: "%s" % m.group(0), name), entry['Version'], entry['NumVotes']), - completion = "%s%s" % (__trigger__, name) + completion = "%s%s" % (__triggers__, name) ) subtext = entry['Description'] if entry['Description'] else "[No description]" if entry['OutOfDate']: @@ -85,9 +81,11 @@ def handleQuery(query): item.subtext = subtext if install_cmdline: - tokens = split(install_cmdline % name) - item.addAction(TermAction("Install with %s" % tokens[0], tokens)) - item.addAction(TermAction("Install with %s (noconfirm)" % tokens[0], tokens + ["--noconfirm"])) + pkgmgr = install_cmdline.split(" ", 1) + item.actions = [ + TermAction("Install using %s" % pkgmgr[0], install_cmdline % name), + TermAction("Install using %s (noconfirm)" % pkgmgr[0], install_cmdline % name + " --noconfirm") + ] item.addAction(UrlAction("Open AUR website", "https://aur.archlinux.org/packages/%s/" % name)) @@ -97,9 +95,8 @@ def handleQuery(query): results.append(item) return results else: - return Item(id=__prettyname__, + return Item(id=__title__, icon=iconPath, - text=__prettyname__, + text=__title__, subtext="Enter a query to search the AUR", - completion=query.rawString, actions=[UrlAction("Open AUR packages website", "https://aur.archlinux.org/packages/")]) diff --git a/base_converter/__init__.py b/base_converter/__init__.py index cfa24c5a..6ae82acb 100644 --- a/base_converter/__init__.py +++ b/base_converter/__init__.py @@ -6,7 +6,7 @@ [padding] - where is a literal of the form '0bXXX' (binary), '0XXX' (octal), + where is a literal of the form '0bXXX' (binary), '0XXX' (octal), or '0xXXX' (hexadecimal).""" import numpy as np @@ -14,12 +14,11 @@ from albert import Item, ClipAction -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Base Converter" -__version__ = "1.1" -__trigger__ = "base " -__author__ = "Manuel Schneider" -__dependencies__ = ["numpy"] +__title__ = "Base Converter" +__version__ = "0.4.1" +__triggers__ = "base " +__authors__ = ["manuelschneid3r", "Keating950"] +__py_deps__ = ["numpy"] class keyed_defaultdict(defaultdict): @@ -33,7 +32,7 @@ def __missing__(self, key): def buildItem(completion, dst, number, padding=0): - item = Item(id=__prettyname__, completion=completion) + item = Item(id=__title__, completion=completion) try: src = base_prefixes[number[:2]] dst = int(dst) @@ -56,8 +55,8 @@ def handleQuery(query): if len(fields) == 2: return buildItem(query.rawString, fields[0], fields[1]) else: - item = Item(id=__prettyname__, completion=query.rawString) - item.text = __prettyname__ + item = Item(id=__title__) + item.text = __title__ item.subtext = "Enter a query in the form of \"<dstbase> <number>\"" return item else: diff --git a/binance/__init__.py b/binance/__init__.py index 110519ef..76488c16 100644 --- a/binance/__init__.py +++ b/binance/__init__.py @@ -15,12 +15,10 @@ import json from threading import Thread, Event -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Binance" -__version__ = "1.3" -__trigger__ = "bnc " -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "Binance" +__version__ = "0.4.3" +__triggers__ = "bnc " +__authors__ = "manuelschneid3r" iconPath = os.path.dirname(__file__) + "/Binance.svg" exchangeInfoUrl = "https://api.binance.com/api/v1/exchangeInfo" @@ -77,11 +75,11 @@ def finalize(): def makeItem(market): url = tradeUrl % (market.base, market.quote) return Item( - id="%s_%s%s" % (__prettyname__, market.base, market.quote), + id="%s_%s%s" % (__title__, market.base, market.quote), icon=iconPath, text="%s/%s" % (market.base, market.quote), subtext="Open the %s/%s market on binance.com" % (market.base, market.quote), - completion="%s%s%s" % (__trigger__, market.base, market.quote), + completion="%s%s%s" % (__triggers__, market.base, market.quote), actions=[ UrlAction("Show market in browser", url), ClipAction('Copy URL to clipboard', url) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 422028ba..ca1410da 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -4,21 +4,15 @@ import fnmatch import os -from shutil import which from subprocess import run from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Bitwarden" -__version__ = "1.0" -__trigger__ = "bw " -__author__ = "Asger Hautop Drewsen" -__dependencies__ = ["rbw"] - - -if which("rbw") is None: - raise Exception("'rbw' is not in $PATH.") +__title__ = "Bitwarden" +__version__ = "0.4.0" +__triggers__ = "bw " +__authors__ = "Asger Hautop Drewsen" +__exec_deps__ = ["rbw"] ICON_PATH = iconLookup("dialog-password") diff --git a/copyq/__init__.py b/copyq/__init__.py index c975648d..e56c736b 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -8,21 +8,16 @@ import json import re import subprocess -from shutil import which from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "CopyQ" -__version__ = "1.1" -__trigger__ = "cq " -__author__ = "Manuel Schneider" -__dependencies__ = ["copyq"] +__title__ = "CopyQ" +__version__ = "0.4.1" +__triggers__ = "cq " +__authors__ = "manuelschneid3r" +__exec_deps__ = ["copyq"] -if which("copyq") is None: - raise Exception("'copyq' is not in $PATH.") - iconPath = iconLookup('copyq') copyq_script_getAll = r""" @@ -83,7 +78,7 @@ def handleQuery(query): text = pattern.sub(lambda m: "%s" % m.group(0), text) items.append( Item( - id=__prettyname__, + id=__title__, icon=iconPath, text=text, subtext="%s: %s" % (row, ", ".join(json_obj['mimetypes'])), diff --git a/currency_converter/__init__.py b/currency_converter/__init__.py index bd0ae271..ed28351b 100644 --- a/currency_converter/__init__.py +++ b/currency_converter/__init__.py @@ -13,11 +13,9 @@ from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Currency converter" -__version__ = "1.0" -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "Currency converter" +__version__ = "0.4.0" +__authors__ = "manuelschneid3r" iconPath = iconLookup('accessories-calculator') if not iconPath: @@ -43,7 +41,7 @@ def convert(self, amount, src, dst): rate = float(child.attrib['rate']) self.exchange_rates[curr] = rate self.exchange_rates["EUR"] = 1.0 # For simpler algorithmic - info("%s: Updated foreign exchange rates." % __prettyname__) + info("%s: Updated foreign exchange rates." % __title__) debug(str(self.exchange_rates)) self.lastUpdate = time.time() @@ -75,7 +73,7 @@ def handleQuery(query): match = regex.fullmatch(query.string.strip()) if match: prep = (float(match.group(1)), match.group(2).upper(), match.group(3).upper()) - item = Item(id=__prettyname__, icon=iconPath, completion=query.rawString) + item = Item(id=__title__, icon=iconPath) for provider in providers: result = provider.convert(*prep) if result: diff --git a/datetime/__init__.py b/datetime/__init__.py index c69982c6..7738d110 100644 --- a/datetime/__init__.py +++ b/datetime/__init__.py @@ -15,12 +15,9 @@ from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "DateTime" -__version__ = "1.1" -__trigger__ = None -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "DateTime" +__version__ = "0.4.1" +__authors__ = "manuelschneid3r" iconPath = iconLookup('x-office-calendar') @@ -30,11 +27,10 @@ def handleQuery(query): if fields: def makeItem(text: str, subtext: str): return Item( - id=__prettyname__, + id=__title__, icon=iconPath, text=text, subtext=subtext, - completion=query.rawString, actions=[ClipAction("Copy to clipboard", text)] ) @@ -69,11 +65,10 @@ def makeItem(text: str, subtext: str): # TODO: how to utilize dateparser even when available on system default python install? # dt = dateparser.parse(query.string) return Item( - id=__prettyname__, + id=__title__, icon=iconPath, text="Invalid input", - subtext="Argument must be empty or numeric.", - completion=query.rawString + subtext="Argument must be empty or numeric." ) else: return [ diff --git a/docker/__init__.py b/docker/__init__.py index 53bc2630..d18f8d68 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -7,12 +7,11 @@ import docker import pathlib -__iid__ = "PythonInterface/v0.3" -__prettyname__ = "Docker" -__version__ = "0.1" -__trigger__ = "d " -__author__ = "manuelschneid3r" -__dependencies__ = ["docker"] +__title__ = "Docker" +__version__ = "0.4.1" +__triggers__ = "d " +__authors__ = "manuelschneid3r" +__py_deps__ = ["docker"] icon_running = str(pathlib.Path(__file__).parent / "running.png") @@ -51,7 +50,7 @@ def handleQuery(query): else: actions = [FuncAction("Start", lambda c=c: c.start())] actions.extend([ - TermAction("Logs", ["docker", "logs", "-f", c.id], + TermAction("Logs", "docker logs -f %s" % c.id, behavior=TermAction.CloseBehavior.DoNotClose), FuncAction("Remove (forced, with volumes)", lambda c=c: c.remove(v=True, force=True)), ClipAction("Copy id to clipboard", c.id) @@ -62,7 +61,6 @@ def handleQuery(query): text="%s %s" % (c.name, ", ".join(c.image.tags)), subtext=c.id, icon=icon_running if c.status == 'running' else icon_stopped, - completion=query.rawString, actions=actions ) @@ -74,7 +72,6 @@ def handleQuery(query): text=str(i.tags), subtext=i.id, icon=icon_stopped, - completion=query.rawString, actions=[ FuncAction("Run with commmand: %s" % query.string, lambda i=i: client.containers.run(i, query.string)), FuncAction("Remove", lambda i=i: i.remove()) diff --git a/fortune/__init__.py b/fortune/__init__.py index 5dc00f6e..9c552296 100644 --- a/fortune/__init__.py +++ b/fortune/__init__.py @@ -7,20 +7,13 @@ Synopsis: """ import subprocess as sp -from shutil import which - from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Fortune" -__version__ = "1.0" -__trigger__ = "fortune" -__author__ = "Kelvin Wong" -__dependencies__ = ["fortune"] - -cmd = __dependencies__[0] -if which(cmd) is None: - raise Exception("'%s' is not in $PATH." % cmd) +__title__ = "Fortune" +__version__ = "0.4.0" +__triggers__ = "fortune" +__authors__ = "Kelvin Wong" +__exec_deps__ = ["fortune"] iconPath = iconLookup("font") @@ -41,10 +34,9 @@ def generateFortune(): def getFortuneItem(query, fortune): return Item( - id=__prettyname__, + id=__title__, icon=iconPath, text=fortune, subtext="Copy this random, hopefully interesting, adage", - completion=query.rawString, actions=[ClipAction("Copy to clipboard", fortune)] ) diff --git a/gnome_dictionary/__init__.py b/gnome_dictionary/__init__.py index 591ec2ed..9d598bd6 100644 --- a/gnome_dictionary/__init__.py +++ b/gnome_dictionary/__init__.py @@ -6,30 +6,24 @@ Sysnopsis: """ -from shutil import which from subprocess import run from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Gnome Dictionary" -__version__ = "1.0" -__trigger__ = "def " -__author__ = "Nikhil Wanpal" -__dependencies__ = ["gnome-dictionary"] - -if which("gnome-dictionary") is None: - raise Exception("'gnome-dictionary' is not in $PATH.") +__title__ = "Gnome Dictionary" +__version__ = "0.4.0" +__triggers__ = "def " +__authors__ = "Nikhil Wanpal" +__exec_deps__ = ["gnome-dictionary"] iconPath = iconLookup('accessories-dictionary') def handleQuery(query): if query.isTriggered: - return Item(id=__prettyname__, + return Item(id=__title__, icon=iconPath, - text=__prettyname__, - subtext="Search for '%s' using %s" % (query.string, __prettyname__), - completion=query.rawString, - actions=[ProcAction("Opens %s and searches for '%s'" % (__prettyname__, query.string), + text=__title__, + subtext="Search for '%s' using %s" % (query.string, __title__), + actions=[ProcAction("Opens %s and searches for '%s'" % (__title__, query.string), ["gnome-dictionary", "--look-up=%s" % query.string])]) diff --git a/gnote/__init__.py b/gnote/__init__.py index 29fcd320..fde614d9 100644 --- a/gnote/__init__.py +++ b/gnote/__init__.py @@ -6,28 +6,22 @@ import re from datetime import datetime -from shutil import which from dbus import DBusException, Interface, SessionBus from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Gnote" -__version__ = "1.1" -__trigger__ = "gn " -__author__ = "Manuel Schneider" -__dependencies__ = ["gnote", "python-dbus"] +__title__ = "Gnote" +__version__ = "0.4.1" +__triggers__ = "gn " +__authors__ = "manuelschneid3r" +__exec_deps__ = ["gnote"] +__py_deps__ = ["python-dbus"] -BUS = "org.gnome.%s" % __prettyname__ -OBJ = "/org/gnome/%s/RemoteControl" % __prettyname__ -IFACE = 'org.gnome.%s.RemoteControl' % __prettyname__ - -cmd = __prettyname__.lower() -if which(cmd) is None: - raise Exception("'%s' is not in $PATH." % cmd) - -iconPath = iconLookup(cmd) +BUS = "org.gnome.%s" % __title__ +OBJ = "/org/gnome/%s/RemoteControl" % __title__ +IFACE = 'org.gnome.%s.RemoteControl' % __title__ +iconPath = iconLookup("gnote") def handleQuery(query): @@ -35,7 +29,7 @@ def handleQuery(query): if query.isTriggered: try: if not SessionBus().name_has_owner(BUS): - warning("Seems like %s is not running" % cmd) + warning("Seems like gnote is not running") return obj = SessionBus().get_object(bus_name=BUS, object_path=OBJ) @@ -44,12 +38,11 @@ def handleQuery(query): if query.string.strip(): for note in iface.SearchNotes(query.string.lower(), False): results.append( - Item(id="%s%s" % (__prettyname__, note), + Item(id="%s%s" % (__title__, note), icon=iconPath, text=iface.GetNoteTitle(note), subtext="%s%s" % ("".join(["#%s " % re.search('.+:.+:(.+)', s).group(1) for s in iface.GetTagsForNote(note)]), datetime.fromtimestamp(iface.GetNoteChangeDate(note)).strftime("Note from %c")), - completion=query.rawString, actions=[ FuncAction("Open note", lambda note=note: iface.DisplayNote(note)), @@ -61,13 +54,12 @@ def createAndShowNote(): note = iface.CreateNote() iface.DisplayNote(note) - results.append(Item(id="%s-create" % __prettyname__, + results.append(Item(id="%s-create" % __title__, icon=iconPath, - text=__prettyname__, - subtext="%s notes" % __prettyname__, - completion=query.rawString, + text=__title__, + subtext="%s notes" % __title__, actions=[ - FuncAction("Open %s" % __prettyname__, + FuncAction("Open %s" % __title__, lambda: iface.DisplaySearch()), FuncAction("Create a new note", createAndShowNote) ])) diff --git a/goldendict/__init__.py b/goldendict/__init__.py index 8751b90c..71396f73 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -4,30 +4,23 @@ Synopsis: """ -from shutil import which from subprocess import run - from albert import Item, ProcAction, iconLookup -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "GoldenDict" -__version__ = "1.0" -__trigger__ = "gd " -__author__ = "Manuel Schneider" -__dependencies__ = ["goldendict"] - -if which("goldendict") is None: - raise Exception("'goldendict' is not in $PATH.") +__title__ = "GoldenDict" +__version__ = "0.4.0" +__triggers__ = "gd " +__authors__ = "manuelschneid3r" +__exec_deps__ = ["goldendict"] iconPath = iconLookup('goldendict') def handleQuery(query): if query.isTriggered: - return Item(id=__prettyname__, + return Item(id=__title__, icon=iconPath, - text=__prettyname__, - subtext="Look up '%s' using %s" % (query.string, __prettyname__), - completion=query.rawString, - actions=[ProcAction("Start query in %s" % __prettyname__, + text=__title__, + subtext="Look up '%s' using %s" % (query.string, __title__), + actions=[ProcAction("Start query in %s" % __title__, ["goldendict", query.string])]) diff --git a/google_translate/__init__.py b/google_translate/__init__.py index 039ab41f..627446f0 100644 --- a/google_translate/__init__.py +++ b/google_translate/__init__.py @@ -12,12 +12,10 @@ from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Google Translate" -__version__ = "1.0" -__trigger__ = "tr " -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "Google Translate" +__version__ = "0.4.0" +__triggers__ = "tr " +__authors__ = "manuelschneid3r" ua = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36" urltmpl = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=%s&tl=%s&dt=t&q=%s" @@ -30,7 +28,7 @@ def handleQuery(query): if query.isTriggered: fields = query.string.split() - item = Item(id=__prettyname__, icon=iconPath, completion=query.rawString) + item = Item(id=__title__, icon=iconPath) if len(fields) >= 3: src = fields[0] dst = fields[1] @@ -45,6 +43,6 @@ def handleQuery(query): item.addAction(ClipAction("Copy translation to clipboard", result)) return item else: - item.text = __prettyname__ + item.text = __title__ item.subtext = "Enter a query in the form of \"<srclang> <dstlang> <text>\"" return item diff --git a/ip/__init__.py b/ip/__init__.py index 240ca995..f8830953 100644 --- a/ip/__init__.py +++ b/ip/__init__.py @@ -9,11 +9,10 @@ from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "IP Addresses" -__version__ = "1.0" -__trigger__ = "ip " -__author__ = "Manuel Schneider, Benedict Dudel" +__title__ = "IP Addresses" +__version__ = "0.4.0" +__triggers__ = "ip " +__authors__ = "manuelschneid3r, Benedict Dudel" iconPath = iconLookup("preferences-system-network") @@ -33,7 +32,7 @@ def handleQuery(query): items = [] if externalIP: items.append(Item( - id = __prettyname__, + id = __title__, icon = iconPath, text = externalIP, subtext = "Your external ip address from ipecho.net", @@ -42,7 +41,7 @@ def handleQuery(query): if internalIP: items.append(Item( - id = __prettyname__, + id = __title__, icon = iconPath, text = internalIP, subtext = "Your internal ip address", diff --git a/kill/__init__.py b/kill/__init__.py index 659fff48..23280295 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -11,12 +11,10 @@ from albert import FuncAction, Item, iconLookup -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Kill Process" -__version__ = "1.4" -__trigger__ = "kill " -__author__ = "Benedict Dudel, Manuel Schneider" -__dependencies__ = [] +__title__ = "Kill Process" +__version__ = "0.4.4" +__triggers__ = "kill " +__authors__ = "Benedict Dudel, manuelschneid3r" iconPath = iconLookup('process-stop') @@ -37,7 +35,6 @@ def handleQuery(query): icon=iconPath, text=proc_command.replace(query.string, "%s" % query.string), subtext=proc_cmdline, - completion=query.rawString, actions=[ FuncAction("Terminate", lambda pid=int(dir_entry.name): os.kill(pid, SIGTERM)), FuncAction("Kill", lambda pid=int(dir_entry.name): os.kill(pid, SIGKILL)) diff --git a/locate/__init__.py b/locate/__init__.py index 03b0c4dc..11ae1332 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -13,32 +13,23 @@ import os import re import subprocess -from shutil import which -from albert import Item, TermAction, UrlAction, iconLookup +from albert import Item, TermAction, UrlAction, iconLookup, warning -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Locate" -__version__ = "1.0" -__trigger__ = "'" -__author__ = "Manuel Schneider" -__dependencies__ = ['locate'] - -if which("locate") is None: - raise Exception("'locate' is not in $PATH.") - -for iconName in ["system-search", "search", "text-x-generic"]: - iconPath = iconLookup(iconName) - if iconPath: - break +__title__ = "Locate" +__version__ = "0.4.0" +__triggers__ = "'" +__authors__ = "manuelschneid3r" +__exec_deps__ = ['locate'] +iconPath = iconLookup(["preferences-system-search", "system-search" "search", "text-x-generic"]) def handleQuery(query): results = [] if query.isTriggered: if len(query.string) > 2: pattern = re.compile(query.string, re.IGNORECASE) - proc = subprocess.Popen(['locate', '-bi', query.string], stdout=subprocess.PIPE) + proc = subprocess.Popen(['locate', '-i', query.string], stdout=subprocess.PIPE) for line in proc.stdout: path = line.decode().strip() basename = os.path.basename(path) @@ -48,16 +39,15 @@ def handleQuery(query): icon=iconPath, text=pattern.sub(lambda m: "%s" % m.group(0), basename), subtext=path, - completion="%s%s" % (__trigger__, basename), + completion="%s%s" % (__triggers__, basename), actions=[UrlAction("Open", "file://%s" % path)])) else: results.append( Item( - id=__prettyname__, + id=__title__, icon=iconPath, text="Update locate database", subtext="Type at least three chars for a seach", - completion=query.rawString, actions=[TermAction("Update database", ["sudo", "updatedb"])])) return results diff --git a/lpass/__init__.py b/lpass/__init__.py index e2523aab..b1689497 100644 --- a/lpass/__init__.py +++ b/lpass/__init__.py @@ -10,12 +10,11 @@ import re import os -__iid__ = 'PythonInterface/v0.1' -__prettyname__ = 'LastPass' -__version__ = '0.1.0' -__trigger__ = 'lp ' -__author__ = 'David Piçarra' -__dependencies__ = ['lpass'] +__title__ = 'LastPass' +__version__ = '0.4.1' +__triggers__ = 'lp ' +__authors__ = 'David Piçarra' +__exec_deps__ = ['lpass'] if not which('lpass'): raise Exception("`lpass` is not in $PATH.") @@ -38,11 +37,10 @@ def handleQuery(query): lpass = subprocess.check_output(['lpass', 'status']) except Exception as e: return Item( - id=__prettyname__, + id=__title__, icon=ICON_PATH, text=f'Not logged in.', subtext=f'Please enter your lastpass email address', - completion=query.rawString, actions=[ ProcAction("lpass login with given email", ["lpass", "login", stripped]), ] @@ -56,21 +54,19 @@ def handleQuery(query): output = subprocess.check_output(['grep', '-i', stripped], stdin=lpass.stdout) except subprocess.CalledProcessError as e: return Item( - id=__prettyname__, + id=__title__, icon=ICON_PATH, - text=__prettyname__, - subtext=f'No results found for {stripped}', - completion=query.rawString + text=__title__, + subtext=f'No results found for {stripped}' ) items = [] for line in output.splitlines(): match = re.match(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2} (.*) \[id: (\d*)\] \[username: (.*)\]', line.decode("utf-8")) items.append(Item( - id=__prettyname__, + id=__title__, icon=ICON_PATH, text=match.group(1), subtext=match.group(3), - completion=query.rawString, actions=[ ProcAction("Copy password to clipboard", ["lpass", "show", "-cp", match.group(2)]), ProcAction("Copy username to clipboard", ["lpass", "show", "-cu", match.group(2)]), @@ -82,28 +78,25 @@ def handleQuery(query): except subprocess.CalledProcessError as e: return Item( - id=__prettyname__, + id=__title__, icon=ICON_PATH, text=f'Error: {str(e.output)}', subtext=str(e), - completion=query.rawString, actions=[ClipAction('Copy CalledProcessError to clipboard', str(e))] ) except Exception as e: return Item( - id=__prettyname__, + id=__title__, icon=ICON_PATH, text=f'Generic Exception: {str(e)}', subtext=str(e), - completion=query.rawString, actions=[ClipAction('Copy Exception to clipboard', str(e))] ) - + else: return Item( - id=__prettyname__, + id=__title__, icon=ICON_PATH, - text=__prettyname__, - subtext='Search the LastPass vault', - completion=query.rawString, + text=__title__, + subtext='Search the LastPass vault' ) diff --git a/mathematica_eval/__init__.py b/mathematica_eval/__init__.py index 71339e25..63b99c98 100644 --- a/mathematica_eval/__init__.py +++ b/mathematica_eval/__init__.py @@ -5,20 +5,15 @@ Synopsis: [expr]""" import subprocess -from shutil import which from tempfile import NamedTemporaryFile from albert import ClipAction, Item, iconLookup -__iid__ = 'PythonInterface/v0.1' -__prettyname__ = 'Mathematica eval' -__version__ = '1.0' -__trigger__ = 'mma ' -__author__ = 'Asger Hautop Drewsen' -__dependencies__ = ['mathematica'] - -if not which('wolframscript'): - raise Exception("`wolframscript` is not in $PATH.") +__title__ = 'Mathematica eval' +__version__ = '0.4.0' +__triggers__ = 'mma ' +__authors__ = 'Asger Hautop Drewsen' +__exec_deps__ = ['wolframscript'] ICON_PATH = iconLookup('wolfram-mathematica') @@ -26,7 +21,7 @@ def handleQuery(query): if not query.isTriggered: return - item = Item(completion=query.rawString, icon=ICON_PATH) + item = Item(icon=ICON_PATH) stripped = query.string.strip() if stripped: diff --git a/multi_google_translate/__init__.py b/multi_google_translate/__init__.py index b27e6bff..c4a62809 100644 --- a/multi_google_translate/__init__.py +++ b/multi_google_translate/__init__.py @@ -19,12 +19,10 @@ from albert import (ClipAction, Item, ProcAction, UrlAction, configLocation, iconLookup) -__iid__ = "PythonInterface/v0.2" -__prettyname__ = "MultiTranslate" -__version__ = "1.2" -__trigger__ = "mtr " -__author__ = "David Britt" -__dependencies__ = [] +__title__ = "MultiTranslate" +__version__ = "0.4.2" +__triggers__ = "mtr " +__authors__ = "David Britt" iconPath = iconLookup('config-language') if not iconPath: @@ -34,7 +32,7 @@ urltmpl = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=%s&dt=t&q=%s" urlbrowser = "https://translate.google.com/#auto/%s/%s" configurationFileName = "language_config.json" -configuration_directory = os.path.join(configLocation(), __prettyname__) +configuration_directory = os.path.join(configLocation(), __title__) language_configuration_file = os.path.join(configuration_directory, configurationFileName) languages = [] @@ -65,10 +63,9 @@ def handleQuery(query): return item = Item( - id=__prettyname__, + id=__title__, icon=iconPath, - completion=query.rawString, - text=__prettyname__, + text=__title__, actions=[ProcAction("Open the language configuration file.", commandline=["xdg-open", language_configuration_file])] ) @@ -90,7 +87,7 @@ def handleQuery(query): else: results.append( Item( - id=__prettyname__, + id=__title__, icon=iconPath, text="%s" % (translText), subtext="%s" % lang.upper(), diff --git a/node_eval/__init__.py b/node_eval/__init__.py index 1bc57b7c..f5ec8f73 100644 --- a/node_eval/__init__.py +++ b/node_eval/__init__.py @@ -5,17 +5,12 @@ import os import subprocess from albert import * -from shutil import which -__iid__ = 'PythonInterface/v0.1' -__prettyname__ = 'Node Eval' -__version__ = '1.0' -__trigger__ = 'node ' -__author__ = 'Hammed Oyedele' -__dependencies__ = ['node'] - -if which('node') is None: - raise Exception('"node" is not in $PATH.') +__title__ = 'Node Eval' +__version__ = '0.4.0' +__triggers__ = 'node ' +__authors__ = 'Hammed Oyedele' +__exec_deps__ = ['node'] iconPath = os.path.dirname(__file__) + '/nodejs.svg' @@ -27,9 +22,8 @@ def run(exp): def handleQuery(query): if query.isTriggered: item = Item( - id=__prettyname__, - icon=iconPath, - completion=query.rawString, + id=__title__, + icon=iconPath ) stripped = query.string.strip() diff --git a/npm/__init__.py b/npm/__init__.py index a3cc47e5..c956ae59 100644 --- a/npm/__init__.py +++ b/npm/__init__.py @@ -7,22 +7,15 @@ Synopsis: [filter]""" from albert import * -from shutil import which import os import json import subprocess - -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "npm" -__version__ = "1.0" -__trigger__ = "npm " -__author__ = "Benedict Dudel" -__dependencies__ = ["npm"] - - -if which("npm") is None: - raise Exception("'npm' is not in $PATH.") +__title__ = "npm" +__version__ = "0.4.0" +__triggers__ = "npm " +__authors__ = "Benedict Dudel" +__exec_deps__ = ["npm"] iconPath = iconLookup("npm") if not iconPath: @@ -33,19 +26,19 @@ def handleQuery(query): if query.isTriggered: if not query.string.strip(): return Item( - id = __prettyname__, + id = __title__, icon = iconPath, text = "Update", subtext = "Update all globally installed packages", actions = [ - TermAction("", ["npm", "update", "--global"]) + TermAction("Update packages", ["npm", "update", "--global"]) ] ) items = getSearchResults(query.string.strip()) if not items: return Item( - id = __prettyname__, + id = __title__, icon = iconPath, text = "Search on npmjs.com", subtext = "No modules found in local database. Try to search on npmjs.com", @@ -66,7 +59,7 @@ def getSearchResults(query): for module in json.loads(proc.stdout.decode()): items.append( Item( - id = __prettyname__, + id = __title__, icon = iconPath, text = "%s (%s)" % (module["name"], module["version"]), subtext = module.get("description", ""), diff --git a/packagist/__init__.py b/packagist/__init__.py index c7cf659a..a370ec05 100644 --- a/packagist/__init__.py +++ b/packagist/__init__.py @@ -11,18 +11,12 @@ import os import json import urllib.request -from shutil import which -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Packagist" -__version__ = "1.0" -__trigger__ = "packagist " -__author__ = "Benedict Dudel" -__dependencies__ = ["composer"] - - -if which("composer") is None: - raise Exception("'composer' is not in $PATH.") +__title__ = "Packagist" +__version__ = "0.4.0" +__triggers__ = "packagist " +__authors__ = "Benedict Dudel" +__exec_deps__ = ["composer"] iconPath = os.path.dirname(__file__)+"/logo.png" @@ -36,7 +30,7 @@ def handleQuery(query): icon = iconPath, text = "by tag", subtext = "Searching for packages by tag", - completion = "%stag " % __trigger__, + completion = "%stag " % __triggers__, actions=[] ), Item( @@ -44,7 +38,7 @@ def handleQuery(query): icon = iconPath, text = "by type", subtext = "Searching for packages by type", - completion = "%stype " % __trigger__, + completion = "%stype " % __triggers__, actions=[] ) ] @@ -70,7 +64,7 @@ def getItems(url): icon = iconPath, text = package["name"], subtext = package["description"], - completion = "%sname %s" % (__trigger__, package["name"]), + completion = "%sname %s" % (__triggers__, package["name"]), actions = [ UrlAction( text = "Open on packagist.org", diff --git a/pacman/__init__.py b/pacman/__init__.py index 94dd9931..44c32f8d 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -11,25 +11,15 @@ import re import subprocess -from shutil import which - from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "PacMan" -__version__ = "1.3" -__trigger__ = "pacman " -__author__ = "Manuel Schneider, Benedict Dudel" -__dependencies__ = ["pacman", "expac"] - -for dep in __dependencies__: - if which(dep) is None: - raise Exception("'%s' is not in $PATH." % dep) +__title__ = "PacMan" +__version__ = "0.4.3" +__triggers__ = "pacman " +__authors__ = "manuelschneid3r, Benedict Dudel" +__exec_deps__ = ["pacman", "expac"] -for iconName in ["archlinux-logo", "system-software-install"]: - iconPath = iconLookup(iconName) - if iconPath: - break +iconPath = iconLookup(["archlinux-logo", "system-software-install"]) def handleQuery(query): if query.isTriggered: @@ -38,11 +28,11 @@ def handleQuery(query): id="%s-update" % __name__, icon=iconPath, text="Pacman package manager", - subtext="Enter the name of the package you are looking for", - completion=__trigger__, + subtext="Enter the package you are looking for or hit enter to update.", + completion=__triggers__, actions=[ - TermAction("Update the system (no confirm)", ["sudo", "pacman", "-Syu", "--noconfirm"]), - TermAction("Update the system", ["sudo", "pacman", "-Syu"]) + TermAction("Update the system (no confirm)", "sudo pacman -Syu --noconfirm"), + TermAction("Update the system", "sudo pacman -Syu") ] ) @@ -82,10 +72,10 @@ def next_stripped(it): actions = [] if pkg_installed: - item.addAction(TermAction("Remove", ["sudo", "pacman", "-Rs", pkg_name])) - item.addAction(TermAction("Reinstall", ["sudo", "pacman", "-S", pkg_name])) + item.addAction(TermAction("Remove", "sudo pacman -Rs %s" % pkg_name)) + item.addAction(TermAction("Reinstall", "sudo pacman -S %s" % pkg_name)) else: - item.addAction(TermAction("Install", ["sudo", "pacman", "-S", pkg_name])) + item.addAction(TermAction("Install", "sudo pacman -S %s" % pkg_name)) item.addAction(UrlAction("Show on packages.archlinux.org", "https://www.archlinux.org/packages/%s/x86_64/%s/" % (pkg_repo, pkg_name))) if pkg_purl: item.addAction(UrlAction("Show project website", pkg_purl)) @@ -98,7 +88,6 @@ def next_stripped(it): icon=iconPath, text="Search on archlinux.org", subtext="No results found in the local database", - completion=__trigger__, actions=[ UrlAction("Search on archlinux.org", "https://www.archlinux.org/packages/?q=%s" % query.string.strip()) @@ -111,9 +100,8 @@ def next_stripped(it): icon=iconPath, text="Update all packages on the system", subtext="Synchronizes the repository databases and updates the system's packages", - completion=__trigger__, actions=[ - TermAction("Update the system (no confirm)", ["sudo", "pacman", "-Syu", "--noconfirm"]), - TermAction("Update the system", ["sudo", "pacman", "-Syu"]) + TermAction("Update the system (no confirm)", "sudo pacman -Syu --noconfirm"), + TermAction("Update the system", "sudo pacman -Syu") ] ) diff --git a/pass/__init__.py b/pass/__init__.py index 564fffe5..c4694729 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -10,20 +10,13 @@ import fnmatch import os -from shutil import which - from albert import * -__iid__ = "PythonInterface/v0.3" -__prettyname__ = "Pass" -__version__ = "1.1" -__trigger__ = "pass " -__author__ = "Benedict Dudel" -__dependencies__ = ["pass"] - - -if which("pass") is None: - raise Exception("'pass' is not in $PATH.") +__title__ = "Pass" +__version__ = "0.4.1" +__triggers__ = "pass " +__authors__ = "Benedict Dudel" +__exec_deps__ = ["pass"] HOME_DIR = os.environ["HOME"] PASS_DIR = os.environ.get("PASSWORD_STORE_DIR", os.path.join(HOME_DIR, ".password-store/")) @@ -42,7 +35,7 @@ def generatePassword(query): location = query.string.strip()[9:] return [Item( - id=__prettyname__, + id=__title__, icon=ICON_PATH, text="Generate a new password", subtext="The new password will be located at %s" % location, diff --git a/php_eval/__init__.py b/php_eval/__init__.py index 61d4ade4..60ceac1f 100644 --- a/php_eval/__init__.py +++ b/php_eval/__init__.py @@ -5,21 +5,15 @@ import os import subprocess from albert import * -from shutil import which -__iid__ = 'PythonInterface/v0.1' -__prettyname__ = 'PHP Eval' -__version__ = '1.0' -__trigger__ = 'php ' -__author__ = 'Hammed Oyedele' -__dependencies__ = ['php'] +__title__ = 'PHP Eval' +__version__ = '0.4.0' +__triggers__ = 'php ' +__authors__ = 'Hammed Oyedele' +__exec_deps__ = ['php'] iconPath = os.path.dirname(__file__) + '/php.svg' -if which('php') is None: - raise Exception('"php" is not in $PATH.') - - def run(exp): return subprocess.getoutput('php -r "%s"' % exp.replace('"', '\\"')) @@ -27,9 +21,8 @@ def run(exp): def handleQuery(query): if query.isTriggered: item = Item( - id=__prettyname__, - icon=iconPath, - completion=query.rawString, + id=__title__, + icon=iconPath ) stripped = query.string.strip() diff --git a/pidgin/__init__.py b/pidgin/__init__.py index 722af7d3..20d1bdc5 100644 --- a/pidgin/__init__.py +++ b/pidgin/__init__.py @@ -8,15 +8,12 @@ from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Pidgin" -__version__ = "1.0" -__author__ = "Greizgh" -__trigger__ = "pidgin " -__dependencies__ = ["dbus"] - -if which("pidgin") is None: - raise Exception("'pidgin' is not in $PATH.") +__title__ = "Pidgin" +__version__ = "0.4.0" +__authors__ = "Greizgh" +__triggers__ = "pidgin " +__exec_deps__ = ["python"] +__py_deps__ = ["dbus"] iconPath = iconLookup("pidgin") bus = dbus.SessionBus() @@ -77,7 +74,7 @@ def handleQuery(query): for match in handler.getMatch(target): items.append( Item( - id=__prettyname__, + id=__title__, icon=iconPath, text="Chat with {}".format(match[0]), subtext="Open a pidgin chat window", diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 7a1339bb..0ae31429 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -7,18 +7,15 @@ Synopsis: [duration [break duration [long break duration [count]]]]""" from albert import * -from shutil import which import subprocess import threading import re import time import os -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Pomodoro" -__version__ = "1.0" -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "Pomodoro" +__version__ = "0.4.0" +__authors__ = "manuelschneid3r" class PomodoroTimer: @@ -88,10 +85,9 @@ def handleQuery(query): global pomodoro pattern = re.compile(query.string, re.IGNORECASE) item = Item( - id=__prettyname__, + id=__title__, icon=iconPath, - text=pattern.sub(lambda m: "%s" % m.group(0), "Pomodoro Timer"), - completion=query.rawString + text=pattern.sub(lambda m: "%s" % m.group(0), "Pomodoro Timer") ) if len(tokens) == 1 and pomodoro.isActive(): diff --git a/python_eval/__init__.py b/python_eval/__init__.py index fb9b5294..be1f37cc 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -13,12 +13,10 @@ pass import os -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Python Eval" -__version__ = "1.0" -__trigger__ = "py " -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "Python Eval" +__version__ = "0.4.0" +__triggers__ = "py " +__authors__ = "manuelschneid3r" iconPath = os.path.dirname(__file__)+"/python.svg" @@ -26,7 +24,7 @@ def handleQuery(query): if query.isTriggered: - item = Item(id=__prettyname__, icon=iconPath, completion=query.rawString) + item = Item(id=__title__, icon=iconPath) stripped = query.string.strip() if stripped == '': diff --git a/scrot/__init__.py b/scrot/__init__.py index 5bf36fb7..2eeceb03 100644 --- a/scrot/__init__.py +++ b/scrot/__init__.py @@ -15,16 +15,11 @@ from albert import FuncAction, Item, iconLookup -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "SCReenshOT utility" -__version__ = "1.0" -__trigger__ = "scrot " -__author__ = "Benedict Dudel" -__dependencies__ = ["scrot", "xclip"] - -for dep in __dependencies__: - if not which(dep): - raise Exception("'%s' is not in $PATH." % dep) +__title__ = "SCReenshOT utility" +__version__ = "0.4.0" +__triggers__ = "scrot " +__authors__ = "Benedict Dudel" +__exec_deps__ = ["scrot", "xclip"] iconPath = iconLookup("camera-photo") @@ -33,7 +28,7 @@ def handleQuery(query): if query.isTriggered: return [ Item( - id = "%s-whole-screen" % __prettyname__, + id = "%s-whole-screen" % __title__, icon = iconPath, text = "Screen", subtext = "Take a screenshot of the whole screen", @@ -49,7 +44,7 @@ def handleQuery(query): ] ), Item( - id = "%s-area-of-screen" % __prettyname__, + id = "%s-area-of-screen" % __title__, icon = iconPath, text = "Area", subtext = "Draw a rectangle with your mouse to capture an area", @@ -61,7 +56,7 @@ def handleQuery(query): ] ), Item( - id = "%s-current-window" % __prettyname__, + id = "%s-current-window" % __title__, icon = iconPath, text = "Window", subtext = "Take a screenshot of the current active window", diff --git a/tex_to_unicode/__init__.py b/tex_to_unicode/__init__.py index 0b1582d5..45b55e74 100644 --- a/tex_to_unicode/__init__.py +++ b/tex_to_unicode/__init__.py @@ -11,12 +11,11 @@ from albert import * -__iid__ = 'PythonInterface/v0.1' -__prettyname__ = 'TeX to unicode' -__version__ = '1.0' -__trigger__ = 'tex ' -__author__ = 'Asger Hautop Drewsen' -__dependencies__ = ['python-pylatexenc'] +__title__ = 'TeX to unicode' +__version__ = '0.4.0' +__triggers__ = 'tex ' +__authors__ = 'Asger Hautop Drewsen' +__py_deps__ = ['python-pylatexenc'] COMBINING_LONG_SOLIDUS_OVERLAY = '\u0338' @@ -25,7 +24,7 @@ def handleQuery(query): if not query.isTriggered: return - item = Item(completion=query.rawString) + item = Item() stripped = query.string.strip() success = False diff --git a/texdoc/__init__.py b/texdoc/__init__.py index 372f97cb..5b2d6fd5 100644 --- a/texdoc/__init__.py +++ b/texdoc/__init__.py @@ -8,24 +8,18 @@ import re import subprocess - -from shutil import which from pathlib import Path from albert import * -__iid__ = 'PythonInterface/v0.3' -__prettyname__ = 'TeXdoc' -__version__ = '1.0' -__trigger__ = 'td' -__author__ = 'Florian Adamsky (@cit)' -__dependencies__ = ['texdoc'] +__title__ = 'TeXdoc' +__version__ = '0.4.0' +__triggers__ = 'td' +__authors__ = 'Florian Adamsky (@cit)' +__exec_deps__ = ['texdoc'] iconPath = Path(__file__).parent / 'texdoc-logo.svg' texdoc_cmd = ['texdoc', '-I', '-q', '-s', '-M'] -if which("texdoc") is None: - raise Exception("'texdoc' is not in $PATH.") - def handleQuery(query): if not query.isTriggered: return @@ -48,7 +42,7 @@ def handleQuery(query): filename = match.group(2).strip() full_path = directory.join(['/', filename]) - results.append(Item(id = __prettyname__, + results.append(Item(id = __title__, icon = str(iconPath), text = filename, subtext = directory, @@ -60,8 +54,8 @@ def handleQuery(query): return results else: - return Item(id = __prettyname__, + return Item(id = __title__, icon = str(iconPath), - text = __prettyname__, + text = __title__, subtext = 'Enter a query to search with texdoc', completion = query.rawString) diff --git a/timer/__init__.py b/timer/__init__.py index d88c92be..1d34809f 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -16,12 +16,11 @@ import os import subprocess -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Timer" -__version__ = "1.2" -__trigger__ = "timer " -__author__ = "manuelschneid3r, googol42" -__dependencies__ = ["dbus"] +__title__ = "Timer" +__version__ = "0.4.2" +__triggers__ = "timer " +__authors__ = "manuelschneid3r, googol42" +__py_deps__ = ["dbus-python"] iconPath = os.path.dirname(__file__)+"/time.svg" soundPath = os.path.dirname(__file__)+"/bing.wav" @@ -46,7 +45,7 @@ def timeout(): bus = dbus.SessionBus() notify = dbus.Interface(bus.get_object(dbusItem, dbusPath), dbusInterface) - notify.Notify(__prettyname__, 0, iconPath, title, text, '', '', 0) + notify.Notify(__title__, 0, iconPath, title, text, '', '', 0) super().__init__(interval=interval, function=timeout) self.interval = interval @@ -82,11 +81,10 @@ def handleQuery(query): name = args[1] if 1 < len(args) else '' if not all(field.isdigit() or field == '' for field in fields): return Item( - id=__prettyname__, + id=__title__, text="Invalid input", - subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % __trigger__, - icon=iconPath, - completion=query.rawString + subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % __triggers__, + icon=iconPath ) seconds = 0 @@ -95,11 +93,10 @@ def handleQuery(query): seconds += int(fields[i] if fields[i] else 0)*(60**i) return Item( - id=__prettyname__, + id=__title__, text=formatSeconds(seconds), subtext='Set a timer with name "%s"' % name if name else 'Set a timer', icon=iconPath, - completion=query.rawString, actions=[FuncAction("Set timer", lambda sec=seconds: startTimer(sec, name))] ) @@ -114,21 +111,18 @@ def handleQuery(query): timer_name_with_quotes = '"%s"' % timer.name if timer.name else '' items.append(Item( - id=__prettyname__, + id=__title__, text='Delete timer %s [%s]' % (timer_name_with_quotes, identifier), subtext="Times out %s" % strftime("%X", localtime(timer.end)), icon=iconPath, - completion=query.rawString, actions=[FuncAction("Delete timer", lambda timer=timer: deleteTimer(timer))] )) if items: return items # Display hint item return Item( - id=__prettyname__, + id=__title__, text="Add timer", - subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % __trigger__, - icon=iconPath, - completion=query.rawString + subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % __triggers__, + icon=iconPath ) - diff --git a/tomboy/__init__.py b/tomboy/__init__.py index 284384a3..e7c4fcd9 100644 --- a/tomboy/__init__.py +++ b/tomboy/__init__.py @@ -6,36 +6,27 @@ import re from datetime import datetime -from shutil import which - from dbus import DBusException, Interface, SessionBus - from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Tomboy" -__version__ = "1.1" -__trigger__ = "tb " -__author__ = "Manuel Schneider" -__dependencies__ = ["tomboy", "python-dbus"] - -BUS = "org.gnome.%s" % __prettyname__ -OBJ = "/org/gnome/%s/RemoteControl" % __prettyname__ -IFACE = 'org.gnome.%s.RemoteControl' % __prettyname__ - -cmd = __dependencies__[0] -if which(cmd) is None: - raise Exception("'%s' is not in $PATH." % cmd) - -iconPath = iconLookup(cmd) +__title__ = "Tomboy" +__version__ = "0.4.1" +__triggers__ = "tb " +__authors__ = "manuelschneid3r" +__exec_deps__ = ["tomboy"] +__py_deps__ = ["dbus"] +BUS = "org.gnome.%s" % __title__ +OBJ = "/org/gnome/%s/RemoteControl" % __title__ +IFACE = 'org.gnome.%s.RemoteControl' % __title__ +iconPath = iconLookup("tomboy") def handleQuery(query): results = [] if query.isTriggered: try: if not SessionBus().name_has_owner(BUS): - warning("Seems like %s is not running" % cmd) + warning("Seems like %s is not running" % __title__) return obj = SessionBus().get_object(bus_name=BUS, object_path=OBJ) @@ -44,12 +35,11 @@ def handleQuery(query): if query.string.strip(): for note in iface.SearchNotes(query.string.lower(), False): results.append( - Item(id="%s%s" % (cmd, note), + Item(id="%s%s" % (__title__, note), icon=iconPath, text=iface.GetNoteTitle(note), subtext="%s%s" % ("".join(["#%s " % re.search('.+:.+:(.+)', s).group(1) for s in iface.GetTagsForNote(note)]), datetime.fromtimestamp(iface.GetNoteChangeDate(note)).strftime("Note from %c")), - completion=query.rawString, actions=[ FuncAction("Open note", lambda note=note: iface.DisplayNote(note)), @@ -61,13 +51,12 @@ def createAndShowNote(): note = iface.CreateNote() iface.DisplayNote(note) - results.append(Item(id="%s-create" % cmd, + results.append(Item(id="%s-create" % __title__, icon=iconPath, - text=__prettyname__, - subtext="%s notes" % __prettyname__, - completion=query.rawString, + text=__title__, + subtext="%s notes" % __title__, actions=[ - FuncAction("Open %s" % __prettyname__, + FuncAction("Open %s" % __title__, lambda: iface.DisplaySearch()), FuncAction("Create a new note", createAndShowNote) ])) diff --git a/trash/__init__.py b/trash/__init__.py index 7531c476..0a1e6c9b 100644 --- a/trash/__init__.py +++ b/trash/__init__.py @@ -11,10 +11,9 @@ from albert import Item, UrlAction, iconLookup -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Trash" -__version__ = "1.0" -__author__ = "Manuel Schneider" +__title__ = "Trash" +__version__ = "0.4.0" +__authors__ = "manuelschneid3r" iconPath = iconLookup("user-trash-full") def handleQuery(query): diff --git a/unicode_emoji/__init__.py b/unicode_emoji/__init__.py index 4f6daaaf..2c8ed136 100644 --- a/unicode_emoji/__init__.py +++ b/unicode_emoji/__init__.py @@ -9,23 +9,17 @@ from threading import Thread import datetime import os -import shutil import subprocess import urllib.request +import shutil -__iid__ = "PythonInterface/v0.2" -__prettyname__ = "Unicode Emojis" -__version__ = "1.3" -__trigger__ = ":" -__author__ = "Tim Zeitz, Manuel Schneider" -__dependencies__ = ["convert"] - -for dep in __dependencies__: - if shutil.which(dep) is None: - raise Exception("'%s' is not in $PATH." % dep) +__title__ = "Unicode Emojis" +__version__ = "0.4.3" +__triggers__ = ":" +__authors__ = "Tim Zeitz, manuelschneid3r" +__exec_deps__ = ["convert"] EmojiSpec = namedtuple('EmojiSpec', ['string', 'name', 'modifiers']) - emoji_data_src_url = "https://unicode.org/Public/emoji/latest/emoji-test.txt" emoji_data_path = os.path.join(dataLocation(), "emoji.txt") icon_path_template = os.path.join(cacheLocation(), __name__, "%s.png") diff --git a/units/__init__.py b/units/__init__.py index 3f429b6d..cea52cbc 100644 --- a/units/__init__.py +++ b/units/__init__.py @@ -11,19 +11,13 @@ import re import subprocess as sp -from shutil import which - from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "GNU Units" -__version__ = "1.2" -__trigger__ = "units " -__author__ = "Manuel Schneider, iyzana" -__dependencies__ = ["units"] - -if which("units") is None: - raise Exception("'units' is not in $PATH.") +__title__ = "GNU Units" +__version__ = "0.4.2" +__triggers__ = "units " +__authors__ = "manuelschneid3r, iyzana" +__exec_deps__ = ["units"] icon = iconLookup('calc') if not icon: @@ -57,8 +51,7 @@ def getUnitsResult(args): def handleQuery(query): if query.isTriggered: args = query.string.split() - item = Item(id='python.gnu_units', icon=icon, - completion=query.rawString) + item = Item(id='python.gnu_units', icon=icon) if args: result, command, success = getUnitsResult(args) item.text = result @@ -75,8 +68,7 @@ def handleQuery(query): result, command, success = getUnitsResult(args) if not success: return - item = Item(id='python.gnu_units', icon=icon, - completion=query.rawString) + item = Item(id='python.gnu_units', icon=icon) item.text = result item.subtext = "Result of '%s'" % command item.addAction(ClipAction("Copy to clipboard", item.text)) diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py index 6e86ecbf..47dc0804 100644 --- a/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -16,12 +16,11 @@ from albert import FuncAction, Item, critical, iconLookup -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Virtual Box" -__version__ = "1.2" -__trigger__ = "vbox " -__author__ = "Manuel Schneider" -__dependencies__ = ['virtualbox'] +__title__ = "Virtual Box" +__version__ = "0.4.2" +__triggers__ = "vbox " +__authors__ = "manuelschneid3r" +__py_deps__ = ['virtualbox'] vbox = None diff --git a/vpn/__init__.py b/vpn/__init__.py index 47c7d755..c598fe9f 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -6,16 +6,12 @@ import subprocess from collections import namedtuple from albert import * -from shutil import which - - -__iid__ = "PythonInterface/v0.2" -__prettyname__ = "VPN" -__version__ = "1.0" -__trigger__ = "vpn " -__author__ = "janeklb" -__dependencies__ = ['nmcli'] +__title__ = "VPN" +__version__ = "0.4.0" +__triggers__ = "vpn " +__authors__ = "janeklb" +__exec_deps__ = ['nmcli'] iconPath = iconLookup('network-wireless') if not iconPath: @@ -51,11 +47,6 @@ def buildItem(con): ) -def initialize(): - if which('nmcli') is None: - raise Exception("'nmcli' is not in $PATH") - - def handleQuery(query): if query.isValid and query.isTriggered: connections = getVPNConnections() @@ -63,4 +54,3 @@ def handleQuery(query): connections = [ con for con in connections if query.string.lower() in con.name.lower() ] return [ buildItem(con) for con in connections ] return [] - diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 4deb3556..a3baff85 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -11,12 +11,10 @@ import time import os -__iid__ = "PythonInterface/v0.3" -__prettyname__ = "Wikipedia" -__version__ = "1.4" -__trigger__ = "wiki " -__author__ = "Manuel Schneider" -__dependencies__ = [] +__title__ = "Wikipedia" +__version__ = "0.4.4" +__triggers__ = "wiki " +__authors__ = "manuelschneid3r" iconPath = iconLookup('wikipedia') if not iconPath: @@ -78,7 +76,7 @@ def handleQuery(query): summary = data[2][i] url = data[3][i] - results.append(Item(id=__prettyname__, + results.append(Item(id=__title__, icon=iconPath, text=title, subtext=summary if summary else url, @@ -90,8 +88,7 @@ def handleQuery(query): return results else: - return Item(id=__prettyname__, + return Item(id=__title__, icon=iconPath, - text=__prettyname__, - subtext="Enter a query to search on Wikipedia", - completion=query.rawString) + text=__title__, + subtext="Enter a query to search on Wikipedia") diff --git a/window_switcher/__init__.py b/window_switcher/__init__.py index dd5966a6..9566695b 100644 --- a/window_switcher/__init__.py +++ b/window_switcher/__init__.py @@ -6,20 +6,14 @@ import subprocess from collections import namedtuple -from shutil import which - from albert import Item, ProcAction, iconLookup -Window = namedtuple("Window", ["wid", "desktop", "wm_class", "host", "wm_name"]) - -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Window Switcher" -__version__ = "1.5" -__author__ = "Ed Perez, manuelschneid3r, dshoreman" -__dependencies__ = ["wmctrl"] +__title__ = "Window Switcher" +__version__ = "0.4.5" +__authors__ = "Ed Perez, manuelschneid3r, dshoreman" +__exec_deps__ = ["wmctrl"] -if which("wmctrl") is None: - raise Exception("'wmctrl' is not in $PATH.") +Window = namedtuple("Window", ["wid", "desktop", "wm_class", "host", "wm_name"]) def handleQuery(query): stripped = query.string.strip().lower() @@ -43,7 +37,7 @@ def handleQuery(query): if iconPath == "": iconPath = iconLookup(win_class.lower()) - results.append(Item(id="%s%s" % (__prettyname__, win.wm_class), + results.append(Item(id="%s%s" % (__title__, win.wm_class), icon=iconPath, text="%s - Desktop %s" % (win_class.replace('-',' '), win.desktop), subtext=win.wm_name, diff --git a/youtube/__init__.py b/youtube/__init__.py index 16cacd75..5dc49b3c 100644 --- a/youtube/__init__.py +++ b/youtube/__init__.py @@ -13,11 +13,10 @@ from albert import Item, UrlAction, iconLookup, critical, debug, info -__iid__ = 'PythonInterface/v0.1' -__prettyname__ = 'Youtube' -__version__ = '1.1' -__trigger__ = 'yt ' -__author__ = 'Manuel Schneider' +__title__ = 'Youtube' +__version__ = '0.4.1' +__triggers__ = 'yt ' +__authors__ = 'manuelschneid3r' __icon__ = iconLookup('youtube') # path.dirname(__file__) + '/icons/YouTube.png' DATA_REGEX = re.compile(r'^\s*(var\s|window\[")ytInitialData("\])?\s*=\s*(.*)\s*;\s*$', re.MULTILINE) @@ -82,11 +81,10 @@ def handleQuery(query): critical(e) critical(json.dumps(result, indent=4)) - item = Item(id=__prettyname__, + item = Item(id=__title__, icon=data['thumbnail']['thumbnails'][0]['url'].split('?', 1)[0] if data['thumbnail']['thumbnails'] else __icon__, text=textFrom(data['title']), subtext=' | '.join(subtext), - completion=query.rawString, actions=[ UrlAction(action, 'https://www.youtube.com/' + link) ] ) items.append(item) diff --git a/zeal/__init__.py b/zeal/__init__.py index 7b62a586..461cf1a3 100644 --- a/zeal/__init__.py +++ b/zeal/__init__.py @@ -4,32 +4,24 @@ Synopsis: """ -from shutil import which from subprocess import run - from albert import * -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Zeal" -__version__ = "1.0" -__trigger__ = "zl " -__author__ = "Manuel Schneider" -__dependencies__ = ["zeal"] - -if which("zeal") is None: - raise Exception("'zeal' is not in $PATH.") +__title__ = "Zeal" +__version__ = "0.4.0" +__triggers__ = "zl " +__authors__ = "manuelschneid3r" +__exec_deps__ = ["zeal"] iconPath = iconLookup('zeal') - def handleQuery(query): if query.isTriggered: return Item( - id=__prettyname__, + id=__title__, icon=iconPath, - text=__prettyname__, - subtext="Look up %s" % __prettyname__, - completion=query.rawString, - actions=[ProcAction("Start query in %s" % __prettyname__, + text=__title__, + subtext="Look up %s" % __title__, + actions=[ProcAction("Start query in %s" % __title__, ["zeal", query.string])] ) From 0600e72679971e095806c33c42432f2ad1c04aa0 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 15 Dec 2020 17:55:33 +0100 Subject: [PATCH 042/355] split multiple authors in lists --- ip/__init__.py | 2 +- kill/__init__.py | 2 +- pacman/__init__.py | 2 +- timer/__init__.py | 2 +- unicode_emoji/__init__.py | 4 ++-- units/__init__.py | 2 +- window_switcher/__init__.py | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ip/__init__.py b/ip/__init__.py index f8830953..e27b72f8 100644 --- a/ip/__init__.py +++ b/ip/__init__.py @@ -12,7 +12,7 @@ __title__ = "IP Addresses" __version__ = "0.4.0" __triggers__ = "ip " -__authors__ = "manuelschneid3r, Benedict Dudel" +__authors__ = ["manuelschneid3r", "Benedict Dudel"] iconPath = iconLookup("preferences-system-network") diff --git a/kill/__init__.py b/kill/__init__.py index 23280295..2a404ff1 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -14,7 +14,7 @@ __title__ = "Kill Process" __version__ = "0.4.4" __triggers__ = "kill " -__authors__ = "Benedict Dudel, manuelschneid3r" +__authors__ = ["Benedict Dudel", "manuelschneid3r"] iconPath = iconLookup('process-stop') diff --git a/pacman/__init__.py b/pacman/__init__.py index 44c32f8d..18e1df20 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -16,7 +16,7 @@ __title__ = "PacMan" __version__ = "0.4.3" __triggers__ = "pacman " -__authors__ = "manuelschneid3r, Benedict Dudel" +__authors__ = ["manuelschneid3r", "Benedict Dudel"] __exec_deps__ = ["pacman", "expac"] iconPath = iconLookup(["archlinux-logo", "system-software-install"]) diff --git a/timer/__init__.py b/timer/__init__.py index 1d34809f..b7a55b1b 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -19,7 +19,7 @@ __title__ = "Timer" __version__ = "0.4.2" __triggers__ = "timer " -__authors__ = "manuelschneid3r, googol42" +__authors__ = ["manuelschneid3r", "googol42"] __py_deps__ = ["dbus-python"] iconPath = os.path.dirname(__file__)+"/time.svg" diff --git a/unicode_emoji/__init__.py b/unicode_emoji/__init__.py index 2c8ed136..f8c9d209 100644 --- a/unicode_emoji/__init__.py +++ b/unicode_emoji/__init__.py @@ -16,7 +16,7 @@ __title__ = "Unicode Emojis" __version__ = "0.4.3" __triggers__ = ":" -__authors__ = "Tim Zeitz, manuelschneid3r" +__authors__ = ["Tim Zeitz", "manuelschneid3r"] __exec_deps__ = ["convert"] EmojiSpec = namedtuple('EmojiSpec', ['string', 'name', 'modifiers']) @@ -80,7 +80,7 @@ def initialize(): os.remove(new_path) except Exception as e: - warn(e) + warning(e) # Build the index and icon cache global thread diff --git a/units/__init__.py b/units/__init__.py index cea52cbc..de598616 100644 --- a/units/__init__.py +++ b/units/__init__.py @@ -16,7 +16,7 @@ __title__ = "GNU Units" __version__ = "0.4.2" __triggers__ = "units " -__authors__ = "manuelschneid3r, iyzana" +__authors__ = ["manuelschneid3r", "iyzana"] __exec_deps__ = ["units"] icon = iconLookup('calc') diff --git a/window_switcher/__init__.py b/window_switcher/__init__.py index 9566695b..5fc1bb4b 100644 --- a/window_switcher/__init__.py +++ b/window_switcher/__init__.py @@ -10,7 +10,7 @@ __title__ = "Window Switcher" __version__ = "0.4.5" -__authors__ = "Ed Perez, manuelschneid3r, dshoreman" +__authors__ = ["Ed Perez", "manuelschneid3r", "dshoreman"] __exec_deps__ = ["wmctrl"] Window = namedtuple("Window", ["wid", "desktop", "wm_class", "host", "wm_name"]) From 2f2de7035239dbf90d203883c1a41549a5295743 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 16 Dec 2020 21:23:40 +0100 Subject: [PATCH 043/355] [timer] Make notification stay. --- timer/__init__.py | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/timer/__init__.py b/timer/__init__.py index b7a55b1b..96280a93 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -9,15 +9,16 @@ Synopsis: [[[hours]:][minutes]:]seconds [name]""" -from albert import * +from albert import warning, Item, FuncAction from threading import Timer from time import strftime, time, localtime import dbus import os +from datetime import timedelta import subprocess __title__ = "Timer" -__version__ = "0.4.2" +__version__ = "0.4.3" __triggers__ = "timer " __authors__ = ["manuelschneid3r", "googol42"] __py_deps__ = ["dbus-python"] @@ -26,10 +27,9 @@ soundPath = os.path.dirname(__file__)+"/bing.wav" timers = [] -dbusItem = "org.freedesktop.Notifications" -dbusPath = "/org/freedesktop/Notifications" -dbusInterface = "org.freedesktop.Notifications" - +bus_name = "org.freedesktop.Notifications" +object_path = "/org/freedesktop/Notifications" +interface = bus_name class AlbertTimer(Timer): @@ -39,13 +39,10 @@ def timeout(): subprocess.Popen(["aplay", soundPath]) global timers timers.remove(self) - title = 'Timer "%s"' % self.name if self.name else 'Timer' text = "Timed out at %s" % strftime("%X", localtime(self.end)) - - bus = dbus.SessionBus() - notify = dbus.Interface(bus.get_object(dbusItem, dbusPath), dbusInterface) - notify.Notify(__title__, 0, iconPath, title, text, '', '', 0) + notify = dbus.Interface(dbus.SessionBus().get_object(bus_name, object_path), interface) + notify.Notify(__title__, 0, iconPath, title, text, [], {"urgency":2}, 0) super().__init__(interval=interval, function=timeout) self.interval = interval @@ -65,13 +62,6 @@ def deleteTimer(timer): timers.remove(timer) timer.cancel() - -def formatSeconds(seconds): - m, s = divmod(seconds, 60) - h, m = divmod(m, 60) - return "%02d:%02d:%02d" % (h, m, s) - - def handleQuery(query): if query.isTriggered: @@ -94,7 +84,7 @@ def handleQuery(query): return Item( id=__title__, - text=formatSeconds(seconds), + text=str(timedelta(seconds=seconds)), subtext='Set a timer with name "%s"' % name if name else 'Set a timer', icon=iconPath, actions=[FuncAction("Set timer", lambda sec=seconds: startTimer(sec, name))] From 18e19058cc2823bde8ebf1b0635d1247e9453db6 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 17 Dec 2020 01:22:32 +0100 Subject: [PATCH 044/355] [locate] ' for basename '' for full path lookups --- locate/__init__.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/locate/__init__.py b/locate/__init__.py index 11ae1332..2e40a9e8 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -8,17 +8,19 @@ This extensions is intended as secondary way to find files. Use the files extension for often used \ files and fast lookups and this extension for everything else. -Synopsis: [filter]""" +Synopsis: [filter] + +where ' searches basenames and '' searches the full path """ import os import re import subprocess -from albert import Item, TermAction, UrlAction, iconLookup, warning +from albert import Item, TermAction, UrlAction, iconLookup __title__ = "Locate" -__version__ = "0.4.0" -__triggers__ = "'" +__version__ = "0.4.1" +__triggers__ = ["''", "'"] # Order matters since 2 is prefix of 1 __authors__ = "manuelschneid3r" __exec_deps__ = ['locate'] @@ -29,7 +31,7 @@ def handleQuery(query): if query.isTriggered: if len(query.string) > 2: pattern = re.compile(query.string, re.IGNORECASE) - proc = subprocess.Popen(['locate', '-i', query.string], stdout=subprocess.PIPE) + proc = subprocess.Popen(['locate', '-i' if query.trigger == "''" else "-bi", query.string], stdout=subprocess.PIPE) for line in proc.stdout: path = line.decode().strip() basename = os.path.basename(path) From 66015dfab5be3a2cee449e19e4b40ec859cdc2d4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 17 Dec 2020 21:59:45 +0100 Subject: [PATCH 045/355] Fix dependency nammes Fix dependency nammes --- gnote/__init__.py | 2 +- tex_to_unicode/__init__.py | 2 +- timer/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gnote/__init__.py b/gnote/__init__.py index fde614d9..d3d6b123 100644 --- a/gnote/__init__.py +++ b/gnote/__init__.py @@ -16,7 +16,7 @@ __triggers__ = "gn " __authors__ = "manuelschneid3r" __exec_deps__ = ["gnote"] -__py_deps__ = ["python-dbus"] +__py_deps__ = ["dbus"] BUS = "org.gnome.%s" % __title__ OBJ = "/org/gnome/%s/RemoteControl" % __title__ diff --git a/tex_to_unicode/__init__.py b/tex_to_unicode/__init__.py index 45b55e74..6ce04486 100644 --- a/tex_to_unicode/__init__.py +++ b/tex_to_unicode/__init__.py @@ -15,7 +15,7 @@ __version__ = '0.4.0' __triggers__ = 'tex ' __authors__ = 'Asger Hautop Drewsen' -__py_deps__ = ['python-pylatexenc'] +__py_deps__ = ['pylatexenc'] COMBINING_LONG_SOLIDUS_OVERLAY = '\u0338' diff --git a/timer/__init__.py b/timer/__init__.py index 96280a93..55788f91 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -21,7 +21,7 @@ __version__ = "0.4.3" __triggers__ = "timer " __authors__ = ["manuelschneid3r", "googol42"] -__py_deps__ = ["dbus-python"] +__py_deps__ = ["dbus"] iconPath = os.path.dirname(__file__)+"/time.svg" soundPath = os.path.dirname(__file__)+"/bing.wav" From 2a6975a0356063161282f8454e08a540d25088a9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 21 Dec 2020 00:38:43 +0100 Subject: [PATCH 046/355] Archive virtualbox --- .archive/virtualbox/README.md | 20 +++++++++++++++++++ .../virtualbox}/__init__.py | 6 ++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 .archive/virtualbox/README.md rename {virtualbox => .archive/virtualbox}/__init__.py (97%) diff --git a/.archive/virtualbox/README.md b/.archive/virtualbox/README.md new file mode 100644 index 00000000..d7b8c8b4 --- /dev/null +++ b/.archive/virtualbox/README.md @@ -0,0 +1,20 @@ +# Python virtualbox + + +```bash +cd /usr/lib/virtualbox +URL="https://download.virtualbox.org/virtualbox/6.1.16/VirtualBoxSDK-6.1.16-140961.zip" +wget "$URL" +unzip $(basename $URL) + +cd sdk/installer + +export VBOX_INSTALL_PATH=/usr/lib/virtualbox +export VBOX_SDK_PATH=/usr/lib/virtualbox/sdk +export PYTHONPATH=/usr/lib/virtualbox/sdk/bindings/xpcom/python +python vboxapisetup.py install + + +Gave it up here + +``` diff --git a/virtualbox/__init__.py b/.archive/virtualbox/__init__.py similarity index 97% rename from virtualbox/__init__.py rename to .archive/virtualbox/__init__.py index 47dc0804..57448afc 100644 --- a/virtualbox/__init__.py +++ b/.archive/virtualbox/__init__.py @@ -24,10 +24,7 @@ vbox = None -for iconName in ["virtualbox", "unknown"]: - iconPath = iconLookup(iconName) - if iconPath: - break +iconPath = iconLookup(["virtualbox", "unknown"]) def initialize(): global vbox @@ -113,6 +110,7 @@ def handleQuery(query): results = [] try: for vm in vbox.machines: + albert.critical(vm.name) if (pattern and pattern in vm.name.lower() or not pattern and query.isTriggered): results.append(buildVmItem(vm)) except Exception as e: From 7f571aceaf8e60eee8bb21e1ec4efa0e95523d13 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 21 Dec 2020 00:39:08 +0100 Subject: [PATCH 047/355] Lean code. Nice py sugar. --- currency_converter/__init__.py | 4 +--- google_translate/__init__.py | 5 +---- npm/__init__.py | 5 +---- units/__init__.py | 4 +--- vpn/__init__.py | 4 +--- wikipedia/__init__.py | 4 +--- window_switcher/__init__.py | 5 +---- 7 files changed, 7 insertions(+), 24 deletions(-) diff --git a/currency_converter/__init__.py b/currency_converter/__init__.py index ed28351b..131a89ef 100644 --- a/currency_converter/__init__.py +++ b/currency_converter/__init__.py @@ -17,9 +17,7 @@ __version__ = "0.4.0" __authors__ = "manuelschneid3r" -iconPath = iconLookup('accessories-calculator') -if not iconPath: - iconPath = ":python_module" +iconPath = iconLookup('accessories-calculator') or ":python_module" class EuropeanCentralBank: diff --git a/google_translate/__init__.py b/google_translate/__init__.py index 627446f0..b8deaede 100644 --- a/google_translate/__init__.py +++ b/google_translate/__init__.py @@ -20,10 +20,7 @@ ua = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36" urltmpl = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=%s&tl=%s&dt=t&q=%s" -iconPath = iconLookup('config-language') -if not iconPath: - iconPath = ":python_module" - +iconPath = iconLookup('config-language') or ":python_module" def handleQuery(query): if query.isTriggered: diff --git a/npm/__init__.py b/npm/__init__.py index c956ae59..381a1a50 100644 --- a/npm/__init__.py +++ b/npm/__init__.py @@ -17,10 +17,7 @@ __authors__ = "Benedict Dudel" __exec_deps__ = ["npm"] -iconPath = iconLookup("npm") -if not iconPath: - iconPath = os.path.dirname(__file__)+"/logo.svg" - +iconPath = iconLookup("npm") or os.path.dirname(__file__)+"/logo.svg" def handleQuery(query): if query.isTriggered: diff --git a/units/__init__.py b/units/__init__.py index de598616..25e8adfb 100644 --- a/units/__init__.py +++ b/units/__init__.py @@ -19,9 +19,7 @@ __authors__ = ["manuelschneid3r", "iyzana"] __exec_deps__ = ["units"] -icon = iconLookup('calc') -if not icon: - icon = ":python_module" +icon = iconLookup('calc') or ":python_module" regex = re.compile(r"(\S+)(?:\s+to)\s+(\S+)") unitListOutput = re.compile(r"(\d+(e[+-]\d{2,})?;)+[\d.]+(e[+-]\d{2,})?") diff --git a/vpn/__init__.py b/vpn/__init__.py index c598fe9f..4095ae12 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -13,9 +13,7 @@ __authors__ = "janeklb" __exec_deps__ = ['nmcli'] -iconPath = iconLookup('network-wireless') -if not iconPath: - iconPath = ":python_module" +iconPath = iconLookup('network-wireless') or ":python_module" VPNConnection = namedtuple('VPNConnection', ['name', 'connected']) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index a3baff85..37b9af1d 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -16,9 +16,7 @@ __triggers__ = "wiki " __authors__ = "manuelschneid3r" -iconPath = iconLookup('wikipedia') -if not iconPath: - iconPath = os.path.dirname(__file__)+"/wikipedia.svg" +iconPath = iconLookup('wikipedia') or os.path.dirname(__file__)+"/wikipedia.svg" baseurl = 'https://en.wikipedia.org/w/api.php' user_agent = "org.albert.extension.python.wikipedia" limit = 20 diff --git a/window_switcher/__init__.py b/window_switcher/__init__.py index 5fc1bb4b..9b114508 100644 --- a/window_switcher/__init__.py +++ b/window_switcher/__init__.py @@ -33,10 +33,7 @@ def handleQuery(query): ] if any(stripped in match for match in matches): - iconPath = iconLookup(win_instance) - if iconPath == "": - iconPath = iconLookup(win_class.lower()) - + iconPath = iconLookup(win_instance) or iconLookup(win_class.lower()) results.append(Item(id="%s%s" % (__title__, win.wm_class), icon=iconPath, text="%s - Desktop %s" % (win_class.replace('-',' '), win.desktop), From 86cde236bb0a11500589703d62e2112069292dcd Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 12 Jan 2021 15:52:31 +0100 Subject: [PATCH 048/355] Give init a timeout. Closes albertlauncher/albert#975. --- wikipedia/__init__.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 37b9af1d..2c9a0340 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -10,15 +10,16 @@ import json import time import os +from socket import timeout __title__ = "Wikipedia" -__version__ = "0.4.4" +__version__ = "0.4.5" __triggers__ = "wiki " __authors__ = "manuelschneid3r" iconPath = iconLookup('wikipedia') or os.path.dirname(__file__)+"/wikipedia.svg" baseurl = 'https://en.wikipedia.org/w/api.php' -user_agent = "org.albert.extension.python.wikipedia" +user_agent = "org.albert.wikipedia" limit = 20 @@ -34,12 +35,17 @@ def initialize(): get_url = "%s?%s" % (baseurl, parse.urlencode(params)) req = request.Request(get_url, headers={'User-Agent': user_agent}) - with request.urlopen(req) as response: - data = json.loads(response.read().decode('utf-8')) - languages = [lang['code'] for lang in data['query']['languages']] - local_lang_code = getdefaultlocale()[0][0:2] - if local_lang_code in languages: - baseurl = baseurl.replace("en", local_lang_code) + try: + with request.urlopen(req, timeout=5) as response: + data = json.loads(response.read().decode('utf-8')) + languages = [lang['code'] for lang in data['query']['languages']] + local_lang_code = getdefaultlocale()[0][0:2] + if local_lang_code in languages: + baseurl = baseurl.replace("en", local_lang_code) + except timeout: + critical('Error getting languages - socket timed out. Defaulting to EN.') + except Exception as error: + critical('Error getting languages (%s). Defaulting to EN.' % error) def handleQuery(query): From 7e6d6821c7b7757b218b473d04a6a30aa78481b1 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 26 Feb 2021 14:08:55 +0100 Subject: [PATCH 049/355] [pacman] Make query have to match package name. Also improve readabililty --- pacman/__init__.py | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/pacman/__init__.py b/pacman/__init__.py index 18e1df20..c483b973 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -11,16 +11,19 @@ import re import subprocess -from albert import * +import time + +from albert import TermAction, iconLookup, Item, UrlAction __title__ = "PacMan" -__version__ = "0.4.3" +__version__ = "0.4.4" __triggers__ = "pacman " -__authors__ = ["manuelschneid3r", "Benedict Dudel"] +__authors__ = ["Manuel Schneider", "Benedict Dudel"] __exec_deps__ = ["pacman", "expac"] iconPath = iconLookup(["archlinux-logo", "system-software-install"]) + def handleQuery(query): if query.isTriggered: if not query.string.strip(): @@ -36,41 +39,38 @@ def handleQuery(query): ] ) + time.sleep(0.1) + if not query.isValid: + return + # Get data. Results are sorted so we can merge in O(n) - proc_s = subprocess.Popen(["expac", "-Ss", "%n\t%v\t%r\t%d\t%u\t%E", query.string], stdout=subprocess.PIPE, universal_newlines=True) + proc_s = subprocess.Popen(["expac", "-Ss", "%n\t%v\t%r\t%d\t%u\t%E", query.string], + stdout=subprocess.PIPE, universal_newlines=True) proc_q = subprocess.Popen(["expac", "-Qs", "%n", query.string], stdout=subprocess.PIPE, universal_newlines=True) proc_q.wait() - def next_stripped(it): - n = next(it, None) - if n: - n = n.rstrip("\n") - return n - - items = [] pattern = re.compile(query.string, re.IGNORECASE) - local_iter = iter(proc_q.stdout.readline, '') - next_local_package = next_stripped(local_iter) - for line in proc_s.stdout: + local_pkgs = set(proc_q.stdout.read().split('\n')) + remote_pkgs = [tuple(line.split('\t')) for line in proc_s.stdout.read().split('\n')[:-1]] # newline at end + + for pkg_name, pkg_vers, pkg_repo, pkg_desc, pkg_purl, pkg_deps in remote_pkgs: + if not pattern.search(pkg_name): + continue - # Parse data - pkg_name, pkg_vers, pkg_repo, pkg_desc, pkg_purl, pkg_deps = line.rstrip("\n").split("\t") - pkg_installed = next_local_package == pkg_name - if next_local_package == pkg_name: - next_local_package = next_stripped(local_iter) + pkg_installed = True if pkg_name in local_pkgs else False - # Create item item = Item( id="%s:%s:%s" % (__name__, pkg_repo, pkg_name), icon=iconPath, - text="%s %s [%s]" % (pattern.sub(lambda m: "%s" % m.group(0), pkg_name), pkg_vers, pkg_repo), - subtext="%s%s (%s)" % ("[Installed] " if pkg_installed else "", pattern.sub(lambda m: "%s" % m.group(0), pkg_desc), pkg_deps) if pkg_deps else pattern.sub(lambda m: "%s" % m.group(0), pkg_desc), + text="%s %s [%s]" + % (pattern.sub(lambda m: "%s" % m.group(0), pkg_name), pkg_vers, pkg_repo), + subtext=("[Installed] %s%s" if pkg_installed else "%s%s") + % (pkg_desc, (" (%s)" % pkg_deps) if pkg_deps else ""), completion="%s%s" % (query.trigger, pkg_name) ) items.append(item) - actions = [] if pkg_installed: item.addAction(TermAction("Remove", "sudo pacman -Rs %s" % pkg_name)) item.addAction(TermAction("Reinstall", "sudo pacman -S %s" % pkg_name)) From 45b6de383c527a3b58916a02d0504408211f177c Mon Sep 17 00:00:00 2001 From: Lorenz Henk Date: Tue, 13 Jul 2021 12:13:20 +0200 Subject: [PATCH 050/355] [docker] Fix typo (#121) --- docker/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/__init__.py b/docker/__init__.py index d18f8d68..c57011b7 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -73,7 +73,7 @@ def handleQuery(query): subtext=i.id, icon=icon_stopped, actions=[ - FuncAction("Run with commmand: %s" % query.string, lambda i=i: client.containers.run(i, query.string)), + FuncAction("Run with command: %s" % query.string, lambda i=i: client.containers.run(i, query.string)), FuncAction("Remove", lambda i=i: i.remove()) ] ) From d5b7b461cd23982a23fa4fdc82ddedad75825710 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 11 Oct 2021 12:31:17 +0200 Subject: [PATCH 051/355] [docker] minor improvements --- docker/__init__.py | 48 ++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/docker/__init__.py b/docker/__init__.py index c57011b7..9f6f7220 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -2,8 +2,7 @@ Docker wrapper (prototype) """ -from albert import * -import os +from albert import TermAction, FuncAction, ClipAction, Item import docker import pathlib @@ -13,12 +12,11 @@ __authors__ = "manuelschneid3r" __py_deps__ = ["docker"] - icon_running = str(pathlib.Path(__file__).parent / "running.png") icon_stopped = str(pathlib.Path(__file__).parent / "stopped.png") - client = None + def initialize(): global client client = docker.from_env() @@ -26,55 +24,51 @@ def initialize(): return client = docker.DockerClient(base_url='unix://var/run/docker.sock') if not client: - raise "fcckit" + raise "Failed to initialize client." -def build_container_item(container): - item - def handleQuery(query): if query.isValid and query.isTriggered: query.disableSort() - items = [] - for c in client.containers.list(all=True): + for container in client.containers.list(all=True): # Create dynamic actions - if c.status == 'running': + if container.status == 'running': actions = [ - FuncAction("Stop container", lambda c=c: c.stop()), - FuncAction("Restart", lambda c=c: c.restart()), + FuncAction("Stop container", lambda c=container: c.stop()), + FuncAction("Restart", lambda c=container: c.restart()), ] else: - actions = [FuncAction("Start", lambda c=c: c.start())] + actions = [FuncAction("Start", lambda c=container: c.start())] actions.extend([ - TermAction("Logs", "docker logs -f %s" % c.id, + TermAction("Logs", "docker logs -f %s" % container.id, behavior=TermAction.CloseBehavior.DoNotClose), - FuncAction("Remove (forced, with volumes)", lambda c=c: c.remove(v=True, force=True)), - ClipAction("Copy id to clipboard", c.id) + FuncAction("Remove (forced, with volumes)", lambda c=container: c.remove(v=True, force=True)), + ClipAction("Copy id to clipboard", container.id) ]) item = Item( - id=c.id, - text="%s %s" % (c.name, ", ".join(c.image.tags)), - subtext=c.id, - icon=icon_running if c.status == 'running' else icon_stopped, + id=container.id, + text="%s %s" % (container.name, ", ".join(container.image.tags)), + subtext=container.id, + icon=icon_running if container.status == 'running' else icon_stopped, actions=actions ) items.append(item) - for i in reversed(client.images.list()): + for image in reversed(client.images.list()): item = Item( - id=i.short_id, - text=str(i.tags), - subtext=i.id, + id=image.short_id, + text=str(image.tags), + subtext=image.id, icon=icon_stopped, actions=[ - FuncAction("Run with command: %s" % query.string, lambda i=i: client.containers.run(i, query.string)), - FuncAction("Remove", lambda i=i: i.remove()) + FuncAction("Run with command: %s" % query.string, lambda i=image: client.containers.run(i, query.string)), + FuncAction("Remove", lambda i=image: i.remove()) ] ) From fce8b8b7b4e8068b566b9ca960830bef32004669 Mon Sep 17 00:00:00 2001 From: Manuel Parati Date: Sat, 8 Oct 2022 13:29:55 +0200 Subject: [PATCH 052/355] [aur] added paru AUR helper (#128) --- aur/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aur/__init__.py b/aur/__init__.py index a6dbd699..4ca548af 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -16,7 +16,7 @@ import re __title__ = "Archlinux User Repository" -__version__ = "0.4.3" +__version__ = "0.4.4" __triggers__ = "aur " __authors__ = "manuelschneid3r" @@ -30,6 +30,8 @@ install_cmdline = "pacaur -S aur/%s" elif which("yay"): install_cmdline = "yay -S aur/%s" +elif which("paru"): + install_cmdline = "paru -S aur/%s" def handleQuery(query): if not query.isTriggered: From 6d0c445e6c3513dab7d237225c5e0c8f0e571ce5 Mon Sep 17 00:00:00 2001 From: Cyprien RUFFINO Date: Sat, 8 Oct 2022 11:33:52 +0000 Subject: [PATCH 053/355] Adding rand.py script for randomly drawing integers (#92) --- rand/__init__.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++ rand/rand.png | Bin 0 -> 35513 bytes 2 files changed, 74 insertions(+) create mode 100644 rand/__init__.py create mode 100644 rand/rand.png diff --git a/rand/__init__.py b/rand/__init__.py new file mode 100644 index 00000000..da93ba10 --- /dev/null +++ b/rand/__init__.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- + +"""Draws a random integer. + +This extension provides the rand item, which can be used with : + - 1 argument a : draws an integer between 1 and a (included) + - 2 argumens a, b: draws an integer between a and b (included) + - 3 arguments a, b, nb: draws nb integers between a and b (included) + +Synopsis: + rand [min] max [numbers] +""" + +import os + +import random + +from albertv0 import * + +__iid__ = "PythonInterface/v0.1" +__prettyname__ = "Rand" +__version__ = "0.1" +__trigger__ = "rand " +__author__ = "Cyprien Ruffino" +__dependencies__ = [] + + +usage_string = "Usage: [min] max [numbers]" + + +def createBlankItem(text): + return Item( + id=__prettyname__, + icon="rand/rand.png", + text=str(text), + subtext="", + actions=[]) + + +def handleQuery(query): + if query.isTriggered: + + tokens = query.string.split(" ") + + # No arguments + if len(tokens) == 1 and tokens[0] == "": + return createBlankItem(usage_string) + + # At least one argument + try: + tokens = [int(token) for token in tokens] + except ValueError: + return createBlankItem(usage_string) + + if len(tokens) == 1: + b = tokens[0] + rand = random.randint(1, b) + return createBlankItem(str(rand)) + + elif len(tokens) == 2: + a, b = tokens + rand = random.randint(a, b) + return createBlankItem(str(rand)) + + elif len(tokens) == 3: + a, b, nb = tokens + items = [] + for i in range(nb): + rand = random.randint(a, b) + items.append(createBlankItem(rand)) + return items + + else: + return createBlankItem(usage_string) diff --git a/rand/rand.png b/rand/rand.png new file mode 100644 index 0000000000000000000000000000000000000000..2e58996ad46203a68b489b2f18a620ebab9a5fad GIT binary patch literal 35513 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 FV1lGP@Av=! literal 0 HcmV?d00001 From 36ad4718c919619f0fa9692a81c765df53cfc15f Mon Sep 17 00:00:00 2001 From: David Britt Date: Tue, 11 Oct 2022 20:50:56 +0100 Subject: [PATCH 054/355] Update __init__.py (#110) The current copy action does not use the standard implementation. It uses xclip, which is fine, but then it should be added as a depedency. So that users know they need to install it. --- bitwarden/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index ca1410da..45487088 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -12,7 +12,7 @@ __version__ = "0.4.0" __triggers__ = "bw " __authors__ = "Asger Hautop Drewsen" -__exec_deps__ = ["rbw"] +__exec_deps__ = ["rbw", "xclip"] ICON_PATH = iconLookup("dialog-password") From 159938149cb53ec5ec751239312fabfbbb98249f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 16 Nov 2021 23:58:28 +0100 Subject: [PATCH 055/355] Consistent author names --- .archive/bitfinex/__init__.py | 4 ++-- .archive/coinmarketcap/__init__.py | 2 +- .archive/virtualbox/__init__.py | 2 +- api_test/__init__.py | 2 +- arch_wiki/__init__.py | 2 +- atom_projects/__init__.py | 2 +- aur/__init__.py | 2 +- base_converter/__init__.py | 2 +- binance/__init__.py | 2 +- copyq/__init__.py | 2 +- currency_converter/__init__.py | 2 +- datetime/__init__.py | 2 +- docker/__init__.py | 2 +- gnote/__init__.py | 2 +- goldendict/__init__.py | 2 +- google_translate/__init__.py | 2 +- ip/__init__.py | 2 +- kill/__init__.py | 2 +- locate/__init__.py | 2 +- pacman/__init__.py | 2 +- pomodoro/__init__.py | 2 +- python_eval/__init__.py | 2 +- timer/__init__.py | 2 +- tomboy/__init__.py | 4 ++-- trash/__init__.py | 2 +- unicode_emoji/__init__.py | 2 +- units/__init__.py | 2 +- wikipedia/__init__.py | 2 +- window_switcher/__init__.py | 2 +- youtube/__init__.py | 2 +- zeal/__init__.py | 2 +- 31 files changed, 33 insertions(+), 33 deletions(-) diff --git a/.archive/bitfinex/__init__.py b/.archive/bitfinex/__init__.py index b0b496f8..188785cd 100644 --- a/.archive/bitfinex/__init__.py +++ b/.archive/bitfinex/__init__.py @@ -18,7 +18,7 @@ __title__ = "BitFinex" __version__ = "0.4.0" __triggers__ = "bfx " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = os.path.dirname(__file__) + "/Bitfinex.svg" symbolsEndpoint = "https://api.bitfinex.com/v1/symbols" @@ -76,7 +76,7 @@ def makeItem(market): icon=iconPath, text="%s/%s" % (market.base, market.quote), subtext="Open the %s/%s market on bitfinex.com" % (market.base, market.quote), - completion="%s%s%s" % (__trigger_s_, market.base, market.quote), + completion="%s%s%s" % (__triggers__, market.base, market.quote), actions=[ UrlAction("Show market in browser", url), ClipAction('Copy URL to clipboard', url) diff --git a/.archive/coinmarketcap/__init__.py b/.archive/coinmarketcap/__init__.py index 63a577b7..ae024db4 100644 --- a/.archive/coinmarketcap/__init__.py +++ b/.archive/coinmarketcap/__init__.py @@ -19,7 +19,7 @@ __title__ = "CoinMarketCap" __version__ = "0.4.4" __triggers__ = "cmc " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = os.path.dirname(__file__)+"/emblem-money.svg" thread = None diff --git a/.archive/virtualbox/__init__.py b/.archive/virtualbox/__init__.py index 57448afc..d42dcdbe 100644 --- a/.archive/virtualbox/__init__.py +++ b/.archive/virtualbox/__init__.py @@ -19,7 +19,7 @@ __title__ = "Virtual Box" __version__ = "0.4.2" __triggers__ = "vbox " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __py_deps__ = ['virtualbox'] vbox = None diff --git a/api_test/__init__.py b/api_test/__init__.py index 7597d444..6bb95d64 100644 --- a/api_test/__init__.py +++ b/api_test/__init__.py @@ -17,7 +17,7 @@ __title__ = "Api Test" __version__ = "0.4.2" __triggers__ = "test " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." #__exec_deps__ = ["whatever"] iconPath = iconLookup("albert") diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index 87a61c13..24131d69 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -12,7 +12,7 @@ __title__ = "Arch Wiki" __version__ = "0.4.1" __triggers__ = "awiki " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = os.path.dirname(__file__) + "/ArchWiki.svg" baseurl = 'https://wiki.archlinux.org/api.php' diff --git a/atom_projects/__init__.py b/atom_projects/__init__.py index e8734d28..c0fbabcf 100644 --- a/atom_projects/__init__.py +++ b/atom_projects/__init__.py @@ -16,7 +16,7 @@ __title__ = "Atom Projects" __version__ = "0.4.0" __triggers__ = "atom " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __exec_deps__ = ["atom"] __py_deps__ = ["cson"] diff --git a/aur/__init__.py b/aur/__init__.py index 4ca548af..2aebeb24 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -18,7 +18,7 @@ __title__ = "Archlinux User Repository" __version__ = "0.4.4" __triggers__ = "aur " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = os.path.dirname(__file__)+"/arch.svg" baseurl = 'https://aur.archlinux.org/rpc/' diff --git a/base_converter/__init__.py b/base_converter/__init__.py index 6ae82acb..ba0b23cc 100644 --- a/base_converter/__init__.py +++ b/base_converter/__init__.py @@ -17,7 +17,7 @@ __title__ = "Base Converter" __version__ = "0.4.1" __triggers__ = "base " -__authors__ = ["manuelschneid3r", "Keating950"] +__authors__ = ["Manuel S.", "Keating950"] __py_deps__ = ["numpy"] diff --git a/binance/__init__.py b/binance/__init__.py index 76488c16..4810b4e0 100644 --- a/binance/__init__.py +++ b/binance/__init__.py @@ -18,7 +18,7 @@ __title__ = "Binance" __version__ = "0.4.3" __triggers__ = "bnc " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = os.path.dirname(__file__) + "/Binance.svg" exchangeInfoUrl = "https://api.binance.com/api/v1/exchangeInfo" diff --git a/copyq/__init__.py b/copyq/__init__.py index e56c736b..d23a16b2 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -14,7 +14,7 @@ __title__ = "CopyQ" __version__ = "0.4.1" __triggers__ = "cq " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __exec_deps__ = ["copyq"] diff --git a/currency_converter/__init__.py b/currency_converter/__init__.py index 131a89ef..2647d662 100644 --- a/currency_converter/__init__.py +++ b/currency_converter/__init__.py @@ -15,7 +15,7 @@ __title__ = "Currency converter" __version__ = "0.4.0" -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = iconLookup('accessories-calculator') or ":python_module" diff --git a/datetime/__init__.py b/datetime/__init__.py index 7738d110..3d7ab5a0 100644 --- a/datetime/__init__.py +++ b/datetime/__init__.py @@ -17,7 +17,7 @@ __title__ = "DateTime" __version__ = "0.4.1" -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = iconLookup('x-office-calendar') diff --git a/docker/__init__.py b/docker/__init__.py index 9f6f7220..bdd40a7a 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -9,7 +9,7 @@ __title__ = "Docker" __version__ = "0.4.1" __triggers__ = "d " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __py_deps__ = ["docker"] icon_running = str(pathlib.Path(__file__).parent / "running.png") diff --git a/gnote/__init__.py b/gnote/__init__.py index d3d6b123..d46d4040 100644 --- a/gnote/__init__.py +++ b/gnote/__init__.py @@ -14,7 +14,7 @@ __title__ = "Gnote" __version__ = "0.4.1" __triggers__ = "gn " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __exec_deps__ = ["gnote"] __py_deps__ = ["dbus"] diff --git a/goldendict/__init__.py b/goldendict/__init__.py index 71396f73..53185d87 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -10,7 +10,7 @@ __title__ = "GoldenDict" __version__ = "0.4.0" __triggers__ = "gd " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __exec_deps__ = ["goldendict"] iconPath = iconLookup('goldendict') diff --git a/google_translate/__init__.py b/google_translate/__init__.py index b8deaede..ed3114f2 100644 --- a/google_translate/__init__.py +++ b/google_translate/__init__.py @@ -15,7 +15,7 @@ __title__ = "Google Translate" __version__ = "0.4.0" __triggers__ = "tr " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." ua = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36" urltmpl = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=%s&tl=%s&dt=t&q=%s" diff --git a/ip/__init__.py b/ip/__init__.py index e27b72f8..c8cc042d 100644 --- a/ip/__init__.py +++ b/ip/__init__.py @@ -12,7 +12,7 @@ __title__ = "IP Addresses" __version__ = "0.4.0" __triggers__ = "ip " -__authors__ = ["manuelschneid3r", "Benedict Dudel"] +__authors__ = ["Manuel S.", "Benedict Dudel"] iconPath = iconLookup("preferences-system-network") diff --git a/kill/__init__.py b/kill/__init__.py index 2a404ff1..2dee7e49 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -14,7 +14,7 @@ __title__ = "Kill Process" __version__ = "0.4.4" __triggers__ = "kill " -__authors__ = ["Benedict Dudel", "manuelschneid3r"] +__authors__ = ["Benedict Dudel", "Manuel S."] iconPath = iconLookup('process-stop') diff --git a/locate/__init__.py b/locate/__init__.py index 2e40a9e8..5316893f 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -21,7 +21,7 @@ __title__ = "Locate" __version__ = "0.4.1" __triggers__ = ["''", "'"] # Order matters since 2 is prefix of 1 -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __exec_deps__ = ['locate'] iconPath = iconLookup(["preferences-system-search", "system-search" "search", "text-x-generic"]) diff --git a/pacman/__init__.py b/pacman/__init__.py index c483b973..d5e11b95 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -18,7 +18,7 @@ __title__ = "PacMan" __version__ = "0.4.4" __triggers__ = "pacman " -__authors__ = ["Manuel Schneider", "Benedict Dudel"] +__authors__ = ["Manuel S.", "Dudel B."] __exec_deps__ = ["pacman", "expac"] iconPath = iconLookup(["archlinux-logo", "system-software-install"]) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 0ae31429..13dd08af 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -15,7 +15,7 @@ __title__ = "Pomodoro" __version__ = "0.4.0" -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." class PomodoroTimer: diff --git a/python_eval/__init__.py b/python_eval/__init__.py index be1f37cc..c91e1c5f 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -16,7 +16,7 @@ __title__ = "Python Eval" __version__ = "0.4.0" __triggers__ = "py " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = os.path.dirname(__file__)+"/python.svg" diff --git a/timer/__init__.py b/timer/__init__.py index 55788f91..8ffe5d92 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -20,7 +20,7 @@ __title__ = "Timer" __version__ = "0.4.3" __triggers__ = "timer " -__authors__ = ["manuelschneid3r", "googol42"] +__authors__ = ["Manuel S.", "googol42"] __py_deps__ = ["dbus"] iconPath = os.path.dirname(__file__)+"/time.svg" diff --git a/tomboy/__init__.py b/tomboy/__init__.py index e7c4fcd9..a9c92186 100644 --- a/tomboy/__init__.py +++ b/tomboy/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -""""Search, open, create and delete Tomboy notes. +"""Search, open, create and delete Tomboy notes. Synopsis: """ @@ -12,7 +12,7 @@ __title__ = "Tomboy" __version__ = "0.4.1" __triggers__ = "tb " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __exec_deps__ = ["tomboy"] __py_deps__ = ["dbus"] diff --git a/trash/__init__.py b/trash/__init__.py index 0a1e6c9b..af9f94f1 100644 --- a/trash/__init__.py +++ b/trash/__init__.py @@ -13,7 +13,7 @@ __title__ = "Trash" __version__ = "0.4.0" -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = iconLookup("user-trash-full") def handleQuery(query): diff --git a/unicode_emoji/__init__.py b/unicode_emoji/__init__.py index f8c9d209..deb1e9a8 100644 --- a/unicode_emoji/__init__.py +++ b/unicode_emoji/__init__.py @@ -16,7 +16,7 @@ __title__ = "Unicode Emojis" __version__ = "0.4.3" __triggers__ = ":" -__authors__ = ["Tim Zeitz", "manuelschneid3r"] +__authors__ = ["Tim Zeitz", "Manuel S."] __exec_deps__ = ["convert"] EmojiSpec = namedtuple('EmojiSpec', ['string', 'name', 'modifiers']) diff --git a/units/__init__.py b/units/__init__.py index 25e8adfb..9d50a3cc 100644 --- a/units/__init__.py +++ b/units/__init__.py @@ -16,7 +16,7 @@ __title__ = "GNU Units" __version__ = "0.4.2" __triggers__ = "units " -__authors__ = ["manuelschneid3r", "iyzana"] +__authors__ = ["Manuel S.", "iyzana"] __exec_deps__ = ["units"] icon = iconLookup('calc') or ":python_module" diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 2c9a0340..3165d7a7 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -15,7 +15,7 @@ __title__ = "Wikipedia" __version__ = "0.4.5" __triggers__ = "wiki " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." iconPath = iconLookup('wikipedia') or os.path.dirname(__file__)+"/wikipedia.svg" baseurl = 'https://en.wikipedia.org/w/api.php' diff --git a/window_switcher/__init__.py b/window_switcher/__init__.py index 9b114508..0648808c 100644 --- a/window_switcher/__init__.py +++ b/window_switcher/__init__.py @@ -10,7 +10,7 @@ __title__ = "Window Switcher" __version__ = "0.4.5" -__authors__ = ["Ed Perez", "manuelschneid3r", "dshoreman"] +__authors__ = ["Ed Perez", "Manuel S.", "dshoreman"] __exec_deps__ = ["wmctrl"] Window = namedtuple("Window", ["wid", "desktop", "wm_class", "host", "wm_name"]) diff --git a/youtube/__init__.py b/youtube/__init__.py index 5dc49b3c..fb5b9008 100644 --- a/youtube/__init__.py +++ b/youtube/__init__.py @@ -16,7 +16,7 @@ __title__ = 'Youtube' __version__ = '0.4.1' __triggers__ = 'yt ' -__authors__ = 'manuelschneid3r' +__authors__ = "Manuel S." __icon__ = iconLookup('youtube') # path.dirname(__file__) + '/icons/YouTube.png' DATA_REGEX = re.compile(r'^\s*(var\s|window\[")ytInitialData("\])?\s*=\s*(.*)\s*;\s*$', re.MULTILINE) diff --git a/zeal/__init__.py b/zeal/__init__.py index 461cf1a3..a039b486 100644 --- a/zeal/__init__.py +++ b/zeal/__init__.py @@ -10,7 +10,7 @@ __title__ = "Zeal" __version__ = "0.4.0" __triggers__ = "zl " -__authors__ = "manuelschneid3r" +__authors__ = "Manuel S." __exec_deps__ = ["zeal"] iconPath = iconLookup('zeal') From 7d168128223df50049b9542806411850576b960c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 20 Dec 2021 07:36:20 +0100 Subject: [PATCH 056/355] 12-20 checkpoint --- .gitignore | 1 + wikipedia/__init__.py | 2 +- wikipedia/wikipedia.svg | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 wikipedia/wikipedia.svg diff --git a/.gitignore b/.gitignore index bee8a64b..cd165dfd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__ +/.idea diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 3165d7a7..edd6d131 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -17,7 +17,7 @@ __triggers__ = "wiki " __authors__ = "Manuel S." -iconPath = iconLookup('wikipedia') or os.path.dirname(__file__)+"/wikipedia.svg" +iconPath = ":wikipedia" baseurl = 'https://en.wikipedia.org/w/api.php' user_agent = "org.albert.wikipedia" limit = 20 diff --git a/wikipedia/wikipedia.svg b/wikipedia/wikipedia.svg deleted file mode 100644 index f082c72f..00000000 --- a/wikipedia/wikipedia.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 55d5f89a7bf67d5ac2cbe28f991aa5e69813f0c7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 26 Dec 2022 00:04:51 +0100 Subject: [PATCH 057/355] archive or update extensions --- .../arch_wiki}/ArchWiki.svg | 4 + {arch_wiki => .archive/arch_wiki}/__init__.py | 2 + .../atom_projects}/__init__.py | 2 + {aur => .archive/aur}/__init__.py | 2 + {aur => .archive/aur}/arch.svg | 4 + .../base_converter}/__init__.py | 2 + {binance => .archive/binance}/Binance.svg | 4 + {binance => .archive/binance}/__init__.py | 2 + {bitwarden => .archive/bitwarden}/__init__.py | 2 + {copyq => .archive/copyq}/__init__.py | 2 + .../currency_converter}/__init__.py | 2 + {datetime => .archive/datetime}/__init__.py | 2 + .archive/find/__init__.py | 80 +++ {fortune => .archive/fortune}/__init__.py | 2 + .../gnome_dictionary}/__init__.py | 2 + {gnote => .archive/gnote}/__init__.py | 2 + .../goldendict}/__init__.py | 2 + .../google_translate}/__init__.py | 2 + {ip => .archive/ip}/__init__.py | 2 + .archive/jetbrains_projects/.gitignore | 2 + .archive/jetbrains_projects/LICENSE | 674 ++++++++++++++++++ .archive/jetbrains_projects/README.md | 39 + .archive/jetbrains_projects/__init__.py | 144 ++++ .archive/jetbrains_projects/jetbrains.svg | 70 ++ {kill => .archive/kill}/__init__.py | 2 + .archive/locate/__init__.py | 100 +++ {lpass => .archive/lpass}/__init__.py | 2 + {lpass => .archive/lpass}/lastpass.svg | 4 + .../mathematica_eval}/__init__.py | 2 + .../multi_google_translate}/__init__.py | 2 + {node_eval => .archive/node_eval}/__init__.py | 2 + {node_eval => .archive/node_eval}/nodejs.svg | 4 + {npm => .archive/npm}/__init__.py | 2 + {npm => .archive/npm}/logo.svg | 4 + {packagist => .archive/packagist}/__init__.py | 2 + {packagist => .archive/packagist}/logo.png | Bin {pacman => .archive/pacman}/__init__.py | 2 + {pass => .archive/pass}/__init__.py | 2 + {php_eval => .archive/php_eval}/__init__.py | 2 + {php_eval => .archive/php_eval}/php.svg | 4 + {pidgin => .archive/pidgin}/__init__.py | 2 + {pomodoro => .archive/pomodoro}/__init__.py | 2 + {pomodoro => .archive/pomodoro}/bing.wav | Bin {pomodoro => .archive/pomodoro}/pomodoro.svg | 4 + {scrot => .archive/scrot}/__init__.py | 2 + .../tex_to_unicode}/__init__.py | 2 + {texdoc => .archive/texdoc}/__init__.py | 2 + {texdoc => .archive/texdoc}/texdoc-logo.svg | 4 + {timer => .archive/timer}/__init__.py | 2 + {timer => .archive/timer}/bing.wav | Bin {timer => .archive/timer}/time.svg | 4 + {tomboy => .archive/tomboy}/__init__.py | 2 + {trash => .archive/trash}/__init__.py | 2 + .../unicode_emoji}/__init__.py | 2 + .../unicode_emoji}/emoji.txt | 0 {units => .archive/units}/__init__.py | 2 + {vpn => .archive/vpn}/__init__.py | 2 + .../window_switcher}/__init__.py | 2 + .archive/xkcd/.gitignore | 72 ++ .archive/xkcd/LICENSE | 18 + .archive/xkcd/README.md | 54 ++ .archive/xkcd/__init__.py | 126 ++++ .archive/xkcd/image.png | Bin 0 -> 4959 bytes .archive/xkcd/install-plugin.sh | 75 ++ .archive/xkcd/misc/demo.gif | Bin 0 -> 730052 bytes {youtube => .archive/youtube}/__init__.py | 2 + {zeal => .archive/zeal}/__init__.py | 2 + api_test/__init__.py | 227 +++--- docker/__init__.py | 90 ++- jetbrains_projects | 1 - locate/__init__.py | 55 -- python_eval/__init__.py | 70 +- wikipedia/__init__.py | 132 ++-- xkcd | 1 - 74 files changed, 1866 insertions(+), 282 deletions(-) rename {arch_wiki => .archive/arch_wiki}/ArchWiki.svg (97%) rename {arch_wiki => .archive/arch_wiki}/__init__.py (98%) rename {atom_projects => .archive/atom_projects}/__init__.py (97%) rename {aur => .archive/aur}/__init__.py (98%) rename {aur => .archive/aur}/arch.svg (97%) rename {base_converter => .archive/base_converter}/__init__.py (98%) rename {binance => .archive/binance}/Binance.svg (91%) rename {binance => .archive/binance}/__init__.py (98%) rename {bitwarden => .archive/bitwarden}/__init__.py (98%) rename {copyq => .archive/copyq}/__init__.py (98%) rename {currency_converter => .archive/currency_converter}/__init__.py (98%) rename {datetime => .archive/datetime}/__init__.py (98%) create mode 100644 .archive/find/__init__.py rename {fortune => .archive/fortune}/__init__.py (95%) rename {gnome_dictionary => .archive/gnome_dictionary}/__init__.py (95%) rename {gnote => .archive/gnote}/__init__.py (98%) rename {goldendict => .archive/goldendict}/__init__.py (94%) rename {google_translate => .archive/google_translate}/__init__.py (97%) rename {ip => .archive/ip}/__init__.py (96%) create mode 100644 .archive/jetbrains_projects/.gitignore create mode 100644 .archive/jetbrains_projects/LICENSE create mode 100644 .archive/jetbrains_projects/README.md create mode 100644 .archive/jetbrains_projects/__init__.py create mode 100644 .archive/jetbrains_projects/jetbrains.svg rename {kill => .archive/kill}/__init__.py (97%) create mode 100644 .archive/locate/__init__.py rename {lpass => .archive/lpass}/__init__.py (98%) rename {lpass => .archive/lpass}/lastpass.svg (86%) rename {mathematica_eval => .archive/mathematica_eval}/__init__.py (96%) rename {multi_google_translate => .archive/multi_google_translate}/__init__.py (99%) rename {node_eval => .archive/node_eval}/__init__.py (96%) rename {node_eval => .archive/node_eval}/nodejs.svg (99%) rename {npm => .archive/npm}/__init__.py (98%) rename {npm => .archive/npm}/logo.svg (94%) rename {packagist => .archive/packagist}/__init__.py (98%) rename {packagist => .archive/packagist}/logo.png (100%) rename {pacman => .archive/pacman}/__init__.py (99%) rename {pass => .archive/pass}/__init__.py (98%) rename {php_eval => .archive/php_eval}/__init__.py (95%) rename {php_eval => .archive/php_eval}/php.svg (96%) rename {pidgin => .archive/pidgin}/__init__.py (98%) rename {pomodoro => .archive/pomodoro}/__init__.py (99%) rename {pomodoro => .archive/pomodoro}/bing.wav (100%) rename {pomodoro => .archive/pomodoro}/pomodoro.svg (97%) rename {scrot => .archive/scrot}/__init__.py (98%) rename {tex_to_unicode => .archive/tex_to_unicode}/__init__.py (97%) rename {texdoc => .archive/texdoc}/__init__.py (98%) rename {texdoc => .archive/texdoc}/texdoc-logo.svg (99%) rename {timer => .archive/timer}/__init__.py (99%) rename {timer => .archive/timer}/bing.wav (100%) rename {timer => .archive/timer}/time.svg (99%) rename {tomboy => .archive/tomboy}/__init__.py (98%) rename {trash => .archive/trash}/__init__.py (95%) rename {unicode_emoji => .archive/unicode_emoji}/__init__.py (99%) rename {unicode_emoji => .archive/unicode_emoji}/emoji.txt (100%) rename {units => .archive/units}/__init__.py (98%) rename {vpn => .archive/vpn}/__init__.py (97%) rename {window_switcher => .archive/window_switcher}/__init__.py (98%) create mode 100644 .archive/xkcd/.gitignore create mode 100644 .archive/xkcd/LICENSE create mode 100644 .archive/xkcd/README.md create mode 100644 .archive/xkcd/__init__.py create mode 100644 .archive/xkcd/image.png create mode 100755 .archive/xkcd/install-plugin.sh create mode 100644 .archive/xkcd/misc/demo.gif rename {youtube => .archive/youtube}/__init__.py (99%) rename {zeal => .archive/zeal}/__init__.py (93%) delete mode 160000 jetbrains_projects delete mode 100644 locate/__init__.py delete mode 160000 xkcd diff --git a/arch_wiki/ArchWiki.svg b/.archive/arch_wiki/ArchWiki.svg similarity index 97% rename from arch_wiki/ArchWiki.svg rename to .archive/arch_wiki/ArchWiki.svg index b95bef86..5a193897 100644 --- a/arch_wiki/ArchWiki.svg +++ b/.archive/arch_wiki/ArchWiki.svg @@ -1 +1,5 @@ + + \ No newline at end of file diff --git a/arch_wiki/__init__.py b/.archive/arch_wiki/__init__.py similarity index 98% rename from arch_wiki/__init__.py rename to .archive/arch_wiki/__init__.py index 24131d69..006de12f 100644 --- a/arch_wiki/__init__.py +++ b/.archive/arch_wiki/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + from albert import * from urllib import request, parse import json diff --git a/atom_projects/__init__.py b/.archive/atom_projects/__init__.py similarity index 97% rename from atom_projects/__init__.py rename to .archive/atom_projects/__init__.py index c0fbabcf..e8f50d1d 100644 --- a/atom_projects/__init__.py +++ b/.archive/atom_projects/__init__.py @@ -4,6 +4,8 @@ Synopsis: [filter]""" +# Copyright (c) 2022 Manuel Schneider + import os import re import time diff --git a/aur/__init__.py b/.archive/aur/__init__.py similarity index 98% rename from aur/__init__.py rename to .archive/aur/__init__.py index 2aebeb24..148b32c8 100644 --- a/aur/__init__.py +++ b/.archive/aur/__init__.py @@ -7,6 +7,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + from albert import * from shutil import which from datetime import datetime diff --git a/aur/arch.svg b/.archive/aur/arch.svg similarity index 97% rename from aur/arch.svg rename to .archive/aur/arch.svg index b95bef86..5a193897 100644 --- a/aur/arch.svg +++ b/.archive/aur/arch.svg @@ -1 +1,5 @@ + + \ No newline at end of file diff --git a/base_converter/__init__.py b/.archive/base_converter/__init__.py similarity index 98% rename from base_converter/__init__.py rename to .archive/base_converter/__init__.py index ba0b23cc..5ed47926 100644 --- a/base_converter/__init__.py +++ b/.archive/base_converter/__init__.py @@ -9,6 +9,8 @@ where is a literal of the form '0bXXX' (binary), '0XXX' (octal), or '0xXXX' (hexadecimal).""" +# Copyright (c) 2022 Manuel Schneider + import numpy as np from collections import defaultdict diff --git a/binance/Binance.svg b/.archive/binance/Binance.svg similarity index 91% rename from binance/Binance.svg rename to .archive/binance/Binance.svg index f03f7c99..c79e1829 100644 --- a/binance/Binance.svg +++ b/.archive/binance/Binance.svg @@ -1 +1,5 @@ + + \ No newline at end of file diff --git a/binance/__init__.py b/.archive/binance/__init__.py similarity index 98% rename from binance/__init__.py rename to .archive/binance/__init__.py index 4810b4e0..6ae6feb9 100644 --- a/binance/__init__.py +++ b/.archive/binance/__init__.py @@ -6,6 +6,8 @@ filter [filter]""" +# Copyright (c) 2022 Manuel Schneider + from albert import * import time import os diff --git a/bitwarden/__init__.py b/.archive/bitwarden/__init__.py similarity index 98% rename from bitwarden/__init__.py rename to .archive/bitwarden/__init__.py index 45487088..8b87a400 100644 --- a/bitwarden/__init__.py +++ b/.archive/bitwarden/__init__.py @@ -2,6 +2,8 @@ """'rbw' wrapper extension.""" +# Copyright (c) 2022 Manuel Schneider + import fnmatch import os from subprocess import run diff --git a/copyq/__init__.py b/.archive/copyq/__init__.py similarity index 98% rename from copyq/__init__.py rename to .archive/copyq/__init__.py index d23a16b2..77e26824 100644 --- a/copyq/__init__.py +++ b/.archive/copyq/__init__.py @@ -4,6 +4,8 @@ Synopsis: [filter]""" +# Copyright (c) 2022 Manuel Schneider + import html import json import re diff --git a/currency_converter/__init__.py b/.archive/currency_converter/__init__.py similarity index 98% rename from currency_converter/__init__.py rename to .archive/currency_converter/__init__.py index 2647d662..9bd8d99c 100644 --- a/currency_converter/__init__.py +++ b/.archive/currency_converter/__init__.py @@ -6,6 +6,8 @@ Synopsis: [to|as|in] """ +# Copyright (c) 2022 Manuel Schneider + import re import time from urllib.request import urlopen diff --git a/datetime/__init__.py b/.archive/datetime/__init__.py similarity index 98% rename from datetime/__init__.py rename to .archive/datetime/__init__.py index 3d7ab5a0..6aa74de4 100644 --- a/datetime/__init__.py +++ b/.archive/datetime/__init__.py @@ -10,6 +10,8 @@ [timestamp]""" +# Copyright (c) 2022 Manuel Schneider + from datetime import datetime, date import time diff --git a/.archive/find/__init__.py b/.archive/find/__init__.py new file mode 100644 index 00000000..1b035bc6 --- /dev/null +++ b/.archive/find/__init__.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +""" +broken +""" +# Copyright (c) 2022 Manuel Schneider + +import albert +from albert import * +from time import sleep +import io +import os +import subprocess +from pathlib import Path + +__iid__ = "0.5" +__version__ = "1.0" +__id__ = "find" +__name__ = "Find" +__description__ = "Online search your file system" +__license__ = "BSD-3" +__url__ = "https://github.com/albertlauncher/python/tree/master/find" +__maintainers__ = "@manuelschneid3r" +__authors__ = ["@manuelschneid3r"] +__bin_dependencies__ = ["find"] +__default_trigger__ = "find " +__synopsis__ = "" + + +class Plugin(Plugin, QueryHandler): + def __init__(self): + albert.Plugin.__init__(self) + albert.QueryHandler.__init__(self) + + def id(self): + return __id__; + + def name(self): + return __name__; + + def takeThisAndModifyR(self, item): + item.id = "takeThisAndModifyR"; + + def takeThisAndModifyR_(self, item): + item.id = "takeThisAndModifyR_"; + + def takeThisAndModifyP(self, item): + item.id = "takeThisAndModifyP"; + + def description(self): + return __description__; + + def handleQuery(self, query): + info(query.string) + proc = subprocess.Popen(["find", Path.home(), "iname", query.string], stdout=subprocess.PIPE) + for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"): + absolute = os.path.abspath(line) + item = Item( + id=absolute, + text=os.path.basename(absolute), + subtext=absolute, + completion="", + icon=[":python"], + actions=[ + Action( + id="clip", + text="setClipboardText (ClipAction)", + callable=lambda: setClipboardText(text=configLocation()) + ) + ] + ) + query.add(item) + + + def initialize(self): + info("Find::initialize") + +# def extensions(self): +# return [self.e] +## pass diff --git a/fortune/__init__.py b/.archive/fortune/__init__.py similarity index 95% rename from fortune/__init__.py rename to .archive/fortune/__init__.py index 9c552296..c1ba896f 100644 --- a/fortune/__init__.py +++ b/.archive/fortune/__init__.py @@ -6,6 +6,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import subprocess as sp from albert import * diff --git a/gnome_dictionary/__init__.py b/.archive/gnome_dictionary/__init__.py similarity index 95% rename from gnome_dictionary/__init__.py rename to .archive/gnome_dictionary/__init__.py index 9d598bd6..a171a979 100644 --- a/gnome_dictionary/__init__.py +++ b/.archive/gnome_dictionary/__init__.py @@ -6,6 +6,8 @@ Sysnopsis: """ +# Copyright (c) 2022 Manuel Schneider + from subprocess import run from albert import * diff --git a/gnote/__init__.py b/.archive/gnote/__init__.py similarity index 98% rename from gnote/__init__.py rename to .archive/gnote/__init__.py index d46d4040..18f7b59e 100644 --- a/gnote/__init__.py +++ b/.archive/gnote/__init__.py @@ -4,6 +4,8 @@ Synopsis: [filter]""" +# Copyright (c) 2022 Manuel Schneider + import re from datetime import datetime diff --git a/goldendict/__init__.py b/.archive/goldendict/__init__.py similarity index 94% rename from goldendict/__init__.py rename to .archive/goldendict/__init__.py index 53185d87..7cfe4b53 100644 --- a/goldendict/__init__.py +++ b/.archive/goldendict/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + from subprocess import run from albert import Item, ProcAction, iconLookup diff --git a/google_translate/__init__.py b/.archive/google_translate/__init__.py similarity index 97% rename from google_translate/__init__.py rename to .archive/google_translate/__init__.py index ed3114f2..30710ba8 100644 --- a/google_translate/__init__.py +++ b/.archive/google_translate/__init__.py @@ -6,6 +6,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import json import urllib.parse import urllib.request diff --git a/ip/__init__.py b/.archive/ip/__init__.py similarity index 96% rename from ip/__init__.py rename to .archive/ip/__init__.py index c8cc042d..18f9910f 100644 --- a/ip/__init__.py +++ b/.archive/ip/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import socket from urllib import request diff --git a/.archive/jetbrains_projects/.gitignore b/.archive/jetbrains_projects/.gitignore new file mode 100644 index 00000000..84528e5c --- /dev/null +++ b/.archive/jetbrains_projects/.gitignore @@ -0,0 +1,2 @@ +*.pyc +__pycache/* diff --git a/.archive/jetbrains_projects/LICENSE b/.archive/jetbrains_projects/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/.archive/jetbrains_projects/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/.archive/jetbrains_projects/README.md b/.archive/jetbrains_projects/README.md new file mode 100644 index 00000000..4fb746a3 --- /dev/null +++ b/.archive/jetbrains_projects/README.md @@ -0,0 +1,39 @@ +# Jetbrains-albert-plugin + +This is a plugin for the albert launcher(https://albertlauncher.github.io/) which lists and lets you start projects of Jetbrains IDEs such as IntelliJ IDEA, PyCharm, GoLand, etc. + +I made this project to maintain this plugin, which was originally part of the albert community plugins. The plugin itself(the python file(s)) is licensed under the GPLv3 license. + +DISCLAIMER: I have no affiliation with JetBrains s.r.o. The included fallback logo `jetbrains.svg` is not my property, I am using it under the terms specified [here](https://www.jetbrains.com/company/useterms.html). + +## How to install: +If you are using git, you can use the following command which will clone the repository into the right directory (respecting the XDG standard). +``` +$ git clone https://github.com/mqus/jetbrains-albert-plugin.git ${XDG_DATA_HOME:-$HOME/.local/share}/albert/org.albert.extension.python/modules/jetbrains-projects +``` + + +If you don't have git, you can simply download a zip archive, extract it and move the folder containing `__init__.py` into the `.local/share/albert/org.albert.extension.python/modules` directory in your home directory, while creating any folders that don't exist yet. + +After that, you should have the following structure: +``` +[...] +'- modules + '- + |- __init.py + '- jetbrains.svg + +``` + +Now, open your albert settings and go to Extensions and then Python. You can then activate the plugin there. You might have to restart albert if it does not show up there at first. + +## Contributors: + +Thomas Queste (@tomsquest) + +@iyzana + +@Sharsie + +@dsager + diff --git a/.archive/jetbrains_projects/__init__.py b/.archive/jetbrains_projects/__init__.py new file mode 100644 index 00000000..8d6d32db --- /dev/null +++ b/.archive/jetbrains_projects/__init__.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- + +"""List and open JetBrains IDE projects.""" + +# Copyright (c) 2022 Manuel Schneider + +import os +from shutil import which +from xml.etree import ElementTree + +from albertv0 import * + +__iid__ = "PythonInterface/v0.1" +__prettyname__ = "Jetbrains IDE Projects" +__version__ = "1.3" +__trigger__ = "jb " +__author__ = "Markus Richter, Thomas Queste" +__dependencies__ = [] + +default_icon = os.path.dirname(__file__) + "/jetbrains.svg" +HOME_DIR = os.environ["HOME"] +JETBRAINS_XDG_CONFIG_DIR = os.path.join(HOME_DIR, ".config/JetBrains") + +paths = [ # , + ["AndroidStudio", "android-studio"], + ["CLion", "clion"], + ["DataGrip", "datagrip"], + ["GoLand", "goland"], + ["IntelliJIdea", + "intellij-idea-ue-bundled-jre intellij-idea-ultimate-edition idea-ce-eap idea-ue-eap idea idea-ultimate"], + ["PhpStorm", "phpstorm"], + ["PyCharm", "pycharm pycharm-eap charm"], + ["RubyMine", "rubymine jetbrains-rubymine jetbrains-rubymine-eap"], + ["WebStorm", "webstorm"], +] + + +# find the executable path and icon of a program described by space-separated lists of possible binary-names +def find_exec(namestr: str): + for name in namestr.split(" "): + executable = which(name) + if executable: + icon = iconLookup(name) or default_icon + return executable, icon + return None + + +# parse the xml at path, return all recent project paths and the time they were last open +def get_proj(path): + r = ElementTree.parse(path).getroot() # type:ElementTree.Element + add_info = None + items = dict() + for o in r[0]: # type:ElementTree.Element + if o.attrib["name"] == 'recentPaths': + for i in o[0]: + items[i.attrib["value"]] = 0 + + else: + if o.attrib["name"] == 'additionalInfo': + add_info = o[0] + + if len(items) == 0: + return [] + + if add_info is not None: + for i in add_info: + for o in i[0][0]: + if o.tag == 'option' and 'name' in o.attrib and o.attrib["name"] == 'projectOpenTimestamp': + items[i.attrib["key"]] = int(o.attrib["value"]) + return [(items[e], e.replace("$USER_HOME$", HOME_DIR)) for e in items] + + +def handleQuery(query): + if query.isTriggered: + binaries = {} + projects = [] + + for app in paths: + config_path = "options/recentProjects.xml" + + full_config_path = None + + # newer versions (since 2020.1) put their configuration here + if os.path.isdir(JETBRAINS_XDG_CONFIG_DIR): + # dirs contains possibly multiple directories for a program (eg. .GoLand2018.1 and .GoLand2017.3) + dirs = [f for f in os.listdir(JETBRAINS_XDG_CONFIG_DIR) if + os.path.isdir(os.path.join(JETBRAINS_XDG_CONFIG_DIR, f)) and f.startswith(app[0])] + # take the newest + dirs.sort(reverse=True) + if len(dirs) != 0: + full_config_path = os.path.join(JETBRAINS_XDG_CONFIG_DIR, dirs[0], config_path) + + # if no config was found in the newer path, repeat for the old ones + if full_config_path is None or not os.path.exists(full_config_path): + if app[0] != "IntelliJIdea" and app[0] != "AndroidStudio": + config_path = "options/recentProjectDirectories.xml" + # dirs contains possibly multiple directories for a program (eg. .GoLand2018.1 and .GoLand2017.3) + dirs = [f for f in os.listdir(HOME_DIR) if + os.path.isdir(os.path.join(HOME_DIR, f)) and f.startswith("." + app[0])] + # take the newest + dirs.sort(reverse=True) + if len(dirs) == 0: + continue + + full_config_path = os.path.join(HOME_DIR, dirs[0], "config", config_path) + if not os.path.exists(full_config_path): + continue + + # extract the binary name and icon + binaries[app[0]] = find_exec(app[1]) + + # add all recently opened projects + projects.extend([[e[0], e[1], app[0]] for e in get_proj(full_config_path)]) + projects.sort(key=lambda s: s[0], reverse=True) + + # List all projects or the one corresponding to the query + if query.string: + projects = [p for p in projects if p[1].lower().find(query.string.lower()) != -1] + + items = [] + for p in projects: + last_update = p[0] + project_path = p[1] + project_dir = project_path.split("/")[-1] + product_name = p[2] + binary = binaries[product_name] + if not binary: + continue + + executable = binaries[p[2]][0] + icon = binaries[p[2]][1] + + items.append(Item( + id="-" + str(last_update), + icon=icon, + text=project_dir, + subtext=project_path, + completion=__trigger__ + project_dir, + actions=[ + ProcAction("Open in %s" % product_name, [executable, project_path]) + ] + )) + + return items diff --git a/.archive/jetbrains_projects/jetbrains.svg b/.archive/jetbrains_projects/jetbrains.svg new file mode 100644 index 00000000..6d3eb0f3 --- /dev/null +++ b/.archive/jetbrains_projects/jetbrains.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kill/__init__.py b/.archive/kill/__init__.py similarity index 97% rename from kill/__init__.py rename to .archive/kill/__init__.py index 2dee7e49..f6f87516 100644 --- a/kill/__init__.py +++ b/.archive/kill/__init__.py @@ -6,6 +6,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import os from signal import SIGKILL, SIGTERM diff --git a/.archive/locate/__init__.py b/.archive/locate/__init__.py new file mode 100644 index 00000000..dfae775d --- /dev/null +++ b/.archive/locate/__init__.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- + +""" +Unix 'locate' wrapper extension. Note that it is up to you to ensure that the locate database is \ +up to date. + +This extensions is intended as secondary way to find files. Use the files extension for often used \ +files and fast lookups and this extension for everything else. + +Synopsis: [filter] + +where ' searches basenames and '' searches the full path """ + +# Copyright (c) 2022 Manuel Schneider + +import os +import re +import subprocess +from albert import * + +__iid__ = "0.5" +__version__ = "1.5" +__name__ = "Locate" +__description__ = "Find ond open files using locate" +__license__ = "BSD-3" +__url__ = "https://github.com/albertlauncher/python/tree/master/locate" +__maintainers__ = "@manuelschneid3r" +__authors__ = ["@manuelschneid3r"] +__bin_dependencies__ = ["locate"] + +iconUrls = ["xdg:preferences-system-search", "xdg:system-search", "xdg:search", "xdg:text-x-generic"] + + +def handleQuery_(query, params): + if len(query.string) > 2: + + result = subprocess.run(['locate', "-i", *params, query.string], stdout=subprocess.PIPE, text=True) + lines = sorted(result.stdout.splitlines(), reverse=True) + + + for path in lines: + print(path) + basename = os.path.basename(path) + query.add( + Item( + id=path, + text=basename, + subtext=path, + completion=basename, + icon=iconUrls, + actions=[ + Action("open", "Open", lambda: openUrl("file://%s" % path)) + ])) + else: + query.add( + Item( + id="updatedb", + text="Update locate database", + subtext="Type at least three chars for a search", + completion="bla", + icon=iconUrls, + actions=[ + Action("update", "Update", lambda: runTerminal(["sudo", "updatedb"])) + ])) + +class LocateBaseName(QueryHandler): + def id(self): + return "locate-base"; + def name(self): + return "Locate (Base name)"; + def description(self): + return "Find files by base name matching"; + def defaultTrigger(self): + return "'"; + def handleQuery(self, query): + handleQuery_(query, []) + +class LocateFullPath(QueryHandler): + def id(self): + return "locate-full"; + def name(self): + return "Locate (Full path)"; + def description(self): + return "Find files by full path matching"; + def defaultTrigger(self): + return "''"; + def handleQuery(self, query): + handleQuery_(query, ["-b"]) + + + + + +class Plugin(Plugin): + def initialize(self): + self.exts = [LocateFullPath(), LocateBaseName()] + + def extensions(self): + return self.exts + diff --git a/lpass/__init__.py b/.archive/lpass/__init__.py similarity index 98% rename from lpass/__init__.py rename to .archive/lpass/__init__.py index b1689497..0ea9d392 100644 --- a/lpass/__init__.py +++ b/.archive/lpass/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + from shutil import which from albert import * import subprocess diff --git a/lpass/lastpass.svg b/.archive/lpass/lastpass.svg similarity index 86% rename from lpass/lastpass.svg rename to .archive/lpass/lastpass.svg index d55c869f..8fa4c946 100644 --- a/lpass/lastpass.svg +++ b/.archive/lpass/lastpass.svg @@ -1,4 +1,8 @@ + + diff --git a/mathematica_eval/__init__.py b/.archive/mathematica_eval/__init__.py similarity index 96% rename from mathematica_eval/__init__.py rename to .archive/mathematica_eval/__init__.py index 63b99c98..6941121e 100644 --- a/mathematica_eval/__init__.py +++ b/.archive/mathematica_eval/__init__.py @@ -4,6 +4,8 @@ Synopsis: [expr]""" +# Copyright (c) 2022 Manuel Schneider + import subprocess from tempfile import NamedTemporaryFile diff --git a/multi_google_translate/__init__.py b/.archive/multi_google_translate/__init__.py similarity index 99% rename from multi_google_translate/__init__.py rename to .archive/multi_google_translate/__init__.py index c4a62809..ba8eb56e 100644 --- a/multi_google_translate/__init__.py +++ b/.archive/multi_google_translate/__init__.py @@ -9,6 +9,8 @@ Synopsis: [query]""" +# Copyright (c) 2022 Manuel Schneider + import json import os import urllib.error diff --git a/node_eval/__init__.py b/.archive/node_eval/__init__.py similarity index 96% rename from node_eval/__init__.py rename to .archive/node_eval/__init__.py index f5ec8f73..a9dc25f8 100644 --- a/node_eval/__init__.py +++ b/.archive/node_eval/__init__.py @@ -2,6 +2,8 @@ """Evaluate simple JavaScript expressions. Use it with care every keystroke triggers an evaluation.""" +# Copyright (c) 2022 Manuel Schneider + import os import subprocess from albert import * diff --git a/node_eval/nodejs.svg b/.archive/node_eval/nodejs.svg similarity index 99% rename from node_eval/nodejs.svg rename to .archive/node_eval/nodejs.svg index 8d55040d..aa75111e 100644 --- a/node_eval/nodejs.svg +++ b/.archive/node_eval/nodejs.svg @@ -1,4 +1,8 @@ + + diff --git a/npm/__init__.py b/.archive/npm/__init__.py similarity index 98% rename from npm/__init__.py rename to .archive/npm/__init__.py index 381a1a50..5c481197 100644 --- a/npm/__init__.py +++ b/.archive/npm/__init__.py @@ -6,6 +6,8 @@ Synopsis: [filter]""" +# Copyright (c) 2022 Manuel Schneider + from albert import * import os import json diff --git a/npm/logo.svg b/.archive/npm/logo.svg similarity index 94% rename from npm/logo.svg rename to .archive/npm/logo.svg index 77b50052..15e123ca 100644 --- a/npm/logo.svg +++ b/.archive/npm/logo.svg @@ -1,4 +1,8 @@ + + [tag|type] """ +# Copyright (c) 2022 Manuel Schneider + from albert import * import os import json diff --git a/packagist/logo.png b/.archive/packagist/logo.png similarity index 100% rename from packagist/logo.png rename to .archive/packagist/logo.png diff --git a/pacman/__init__.py b/.archive/pacman/__init__.py similarity index 99% rename from pacman/__init__.py rename to .archive/pacman/__init__.py index d5e11b95..5f4edf66 100644 --- a/pacman/__init__.py +++ b/.archive/pacman/__init__.py @@ -9,6 +9,8 @@ Synopsis: [filter]""" +# Copyright (c) 2022 Manuel Schneider + import re import subprocess import time diff --git a/pass/__init__.py b/.archive/pass/__init__.py similarity index 98% rename from pass/__init__.py rename to .archive/pass/__init__.py index c4694729..90452fcc 100644 --- a/pass/__init__.py +++ b/.archive/pass/__init__.py @@ -8,6 +8,8 @@ generate """ +# Copyright (c) 2022 Manuel Schneider + import fnmatch import os from albert import * diff --git a/php_eval/__init__.py b/.archive/php_eval/__init__.py similarity index 95% rename from php_eval/__init__.py rename to .archive/php_eval/__init__.py index 60ceac1f..513f3b38 100644 --- a/php_eval/__init__.py +++ b/.archive/php_eval/__init__.py @@ -2,6 +2,8 @@ """Evaluate simple PHP expressions. Use it with care every keystroke triggers an evaluation.""" +# Copyright (c) 2022 Manuel Schneider + import os import subprocess from albert import * diff --git a/php_eval/php.svg b/.archive/php_eval/php.svg similarity index 96% rename from php_eval/php.svg rename to .archive/php_eval/php.svg index 9a10ee4e..de22880b 100644 --- a/php_eval/php.svg +++ b/.archive/php_eval/php.svg @@ -1 +1,5 @@ + + \ No newline at end of file diff --git a/pidgin/__init__.py b/.archive/pidgin/__init__.py similarity index 98% rename from pidgin/__init__.py rename to .archive/pidgin/__init__.py index 20d1bdc5..f3d648c9 100644 --- a/pidgin/__init__.py +++ b/.archive/pidgin/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import dbus from albert import * diff --git a/pomodoro/__init__.py b/.archive/pomodoro/__init__.py similarity index 99% rename from pomodoro/__init__.py rename to .archive/pomodoro/__init__.py index 13dd08af..a9b8ceaf 100644 --- a/pomodoro/__init__.py +++ b/.archive/pomodoro/__init__.py @@ -6,6 +6,8 @@ Synopsis: [duration [break duration [long break duration [count]]]]""" +# Copyright (c) 2022 Manuel Schneider + from albert import * import subprocess import threading diff --git a/pomodoro/bing.wav b/.archive/pomodoro/bing.wav similarity index 100% rename from pomodoro/bing.wav rename to .archive/pomodoro/bing.wav diff --git a/pomodoro/pomodoro.svg b/.archive/pomodoro/pomodoro.svg similarity index 97% rename from pomodoro/pomodoro.svg rename to .archive/pomodoro/pomodoro.svg index fea164ad..29cc53cf 100644 --- a/pomodoro/pomodoro.svg +++ b/.archive/pomodoro/pomodoro.svg @@ -1 +1,5 @@ + + \ No newline at end of file diff --git a/scrot/__init__.py b/.archive/scrot/__init__.py similarity index 98% rename from scrot/__init__.py rename to .archive/scrot/__init__.py index 2eeceb03..80c2d44a 100644 --- a/scrot/__init__.py +++ b/.archive/scrot/__init__.py @@ -8,6 +8,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import os import subprocess import tempfile diff --git a/tex_to_unicode/__init__.py b/.archive/tex_to_unicode/__init__.py similarity index 97% rename from tex_to_unicode/__init__.py rename to .archive/tex_to_unicode/__init__.py index 6ce04486..87daf423 100644 --- a/tex_to_unicode/__init__.py +++ b/.archive/tex_to_unicode/__init__.py @@ -4,6 +4,8 @@ Synopsis: ''' +# Copyright (c) 2022 Manuel Schneider + import re import unicodedata diff --git a/texdoc/__init__.py b/.archive/texdoc/__init__.py similarity index 98% rename from texdoc/__init__.py rename to .archive/texdoc/__init__.py index 5b2d6fd5..de3f42b6 100644 --- a/texdoc/__init__.py +++ b/.archive/texdoc/__init__.py @@ -6,6 +6,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import re import subprocess from pathlib import Path diff --git a/texdoc/texdoc-logo.svg b/.archive/texdoc/texdoc-logo.svg similarity index 99% rename from texdoc/texdoc-logo.svg rename to .archive/texdoc/texdoc-logo.svg index 47784fc3..0245dcd6 100644 --- a/texdoc/texdoc-logo.svg +++ b/.archive/texdoc/texdoc-logo.svg @@ -1,4 +1,8 @@ + + [[[hours]:][minutes]:]seconds [name]""" +# Copyright (c) 2022 Manuel Schneider + from albert import warning, Item, FuncAction from threading import Timer from time import strftime, time, localtime diff --git a/timer/bing.wav b/.archive/timer/bing.wav similarity index 100% rename from timer/bing.wav rename to .archive/timer/bing.wav diff --git a/timer/time.svg b/.archive/timer/time.svg similarity index 99% rename from timer/time.svg rename to .archive/timer/time.svg index f6cc4d0b..0f675ad2 100644 --- a/timer/time.svg +++ b/.archive/timer/time.svg @@ -1 +1,5 @@ + + \ No newline at end of file diff --git a/tomboy/__init__.py b/.archive/tomboy/__init__.py similarity index 98% rename from tomboy/__init__.py rename to .archive/tomboy/__init__.py index a9c92186..6e8f03ec 100644 --- a/tomboy/__init__.py +++ b/.archive/tomboy/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import re from datetime import datetime from dbus import DBusException, Interface, SessionBus diff --git a/trash/__init__.py b/.archive/trash/__init__.py similarity index 95% rename from trash/__init__.py rename to .archive/trash/__init__.py index af9f94f1..d123aec1 100644 --- a/trash/__init__.py +++ b/.archive/trash/__init__.py @@ -7,6 +7,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import re from albert import Item, UrlAction, iconLookup diff --git a/unicode_emoji/__init__.py b/.archive/unicode_emoji/__init__.py similarity index 99% rename from unicode_emoji/__init__.py rename to .archive/unicode_emoji/__init__.py index deb1e9a8..a1191072 100644 --- a/unicode_emoji/__init__.py +++ b/.archive/unicode_emoji/__init__.py @@ -4,6 +4,8 @@ Synopsis: [filter]""" +# Copyright (c) 2022 Manuel Schneider + from albert import * from collections import namedtuple from threading import Thread diff --git a/unicode_emoji/emoji.txt b/.archive/unicode_emoji/emoji.txt similarity index 100% rename from unicode_emoji/emoji.txt rename to .archive/unicode_emoji/emoji.txt diff --git a/units/__init__.py b/.archive/units/__init__.py similarity index 98% rename from units/__init__.py rename to .archive/units/__init__.py index 9d50a3cc..aef326b8 100644 --- a/units/__init__.py +++ b/.archive/units/__init__.py @@ -9,6 +9,8 @@ [dst] to """ +# Copyright (c) 2022 Manuel Schneider + import re import subprocess as sp from albert import * diff --git a/vpn/__init__.py b/.archive/vpn/__init__.py similarity index 97% rename from vpn/__init__.py rename to .archive/vpn/__init__.py index 4095ae12..c6039c31 100644 --- a/vpn/__init__.py +++ b/.archive/vpn/__init__.py @@ -3,6 +3,8 @@ Connect or disconnect from a network manager VPN profile""" +# Copyright (c) 2022 Manuel Schneider + import subprocess from collections import namedtuple from albert import * diff --git a/window_switcher/__init__.py b/.archive/window_switcher/__init__.py similarity index 98% rename from window_switcher/__init__.py rename to .archive/window_switcher/__init__.py index 0648808c..ea65e157 100644 --- a/window_switcher/__init__.py +++ b/.archive/window_switcher/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import subprocess from collections import namedtuple from albert import Item, ProcAction, iconLookup diff --git a/.archive/xkcd/.gitignore b/.archive/xkcd/.gitignore new file mode 100644 index 00000000..8f793ad3 --- /dev/null +++ b/.archive/xkcd/.gitignore @@ -0,0 +1,72 @@ +# Compiled source # +###################### +*.com +*.class +*.dll +*.exe +*.o +*.so +*.pyc + +# Packages # +###################### +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +tags + +_build + +# CMake +build* +documentation +*.user* +log +*.dir* +*.a +*.make +doc/html* +doc/latex* + +# Python +.mypy_cache +# Python - Coverage +.coverage +coverage.xml +htmlcov/ + +# Vim +Session.vim +.netrwhist +*~ +tags +.projections.json +compile_commands.json + + +# backup files - created during sed operations +*.bak diff --git a/.archive/xkcd/LICENSE b/.archive/xkcd/LICENSE new file mode 100644 index 00000000..de8114f9 --- /dev/null +++ b/.archive/xkcd/LICENSE @@ -0,0 +1,18 @@ +Copyright 2019 Nikos Koukis + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.archive/xkcd/README.md b/.archive/xkcd/README.md new file mode 100644 index 00000000..e271f7d1 --- /dev/null +++ b/.archive/xkcd/README.md @@ -0,0 +1,54 @@ +# Albert xkcd Plugin + + + + + + +## Description + +The xkcd Albert plugin lets you launch an xkcd comic in your browser from the +albert prompt. Here are its main features: + +* On toggle (default trigger: `xkcd`) it shows you the comics in newest-first + order. +* If you want to find a comic with a specific title then you can use fuzzy search to do so): + * `xkcd some words from the title` + +## Demo + +![demo_gif](https://github.com/bergercookie/xkcd-albert-plugin/blob/master/misc/demo.gif) + +## Motivation + +I love reading xkcd. I also wanted to get into developing plugins for Albert +thus this was the perfect opportunity to do so. + +## Manual installation instructions + +Requirements: + +- Albert - [Installation instructions](https://albertlauncher.github.io/docs/installing/) + - Albert Python Interface: v0.2 +- Python version >= 3.5 + + +Download and run the ``install-plugin.sh`` script or run the following to do +that automatically: + +``````sh +curl https://raw.githubusercontent.com/bergercookie/xkcd-albert-plugin/master/install-plugin.sh | bash +`````` + +## Self Promotion + +If you find this tool useful, please [star it on +Github](https://github.com/bergercookie/xkcd-albert-plugin) + +## TODO List + +See [ISSUES list](https://github.com/bergercookie/xkcd-albert-plugin/issues) for +the things that I'm currently either working on or interested in implementing in +the near future. In case there's something you are interesting in working on, +don't hesitate to either ask for clarifications or just do it and directly make +a PR. diff --git a/.archive/xkcd/__init__.py b/.archive/xkcd/__init__.py new file mode 100644 index 00000000..0089739b --- /dev/null +++ b/.archive/xkcd/__init__.py @@ -0,0 +1,126 @@ +"""Fetch xkcd comics like a boss.""" + +# Copyright (c) 2022 Manuel Schneider + +from datetime import datetime, timedelta +from pathlib import Path +import json +import os +import subprocess +import sys + +import albertv0 as v0 +from fuzzywuzzy import process +from shutil import which + +__iid__ = "PythonInterface/v0.2" +__prettyname__ = "xkcd" +__version__ = "0.1" +__trigger__ = "xkcd" +__author__ = "Nikos Koukis" +__dependencies__ = [] +__homepage__ = "https://github.com/bergercookie/xkcd-albert-plugin" + + +# TODO pyproject toml file +# TODO xkcd-dl executable? +# TODO Upload to github - change support url on error +# TODO Send to albert plugins + +if not which("xkcd-dl"): + raise RuntimeError("xkcd-dl not in $PATH - Please install it via pip3 first.") + +iconPath = v0.iconLookup("xkcd") +if not iconPath: + iconPath = os.path.join(os.path.dirname(__file__), "image.png") +SETTINGS_PATH = Path(v0.cacheLocation()) / "xkcd" +LAST_UPDATE_PATH = SETTINGS_PATH / "last_update" +XKCD_DICT = Path.home() / ".xkcd_dict.json" + + +def initialize(): + # Called when the extension is loaded (ticked in the settings) - blocking + + # create cache location + SETTINGS_PATH.mkdir(parents=False, exist_ok=True) + if not LAST_UPDATE_PATH.is_file(): + update_date_file() + update_xkcd_db() + + +def finalize(): + pass + + +def handleQuery(query): + results = [] + + # check whether I have downlaoded the latest metadata + with open(LAST_UPDATE_PATH, "r") as f: + date_str = float(f.readline().strip()) + + last_date = datetime.fromtimestamp(date_str) + if datetime.now() - last_date > timedelta(days=1): # run an update daily + update_date_file() + update_xkcd_db() + + if query.isTriggered: + try: + with open(XKCD_DICT, "r", encoding="utf-8") as f: + d = json.load(f) + + if len(query.string) in [0, 1]: # Display all items + for k, v in d.items(): + results.append(get_as_item(k, v)) + else: # fuzzy search + desc_to_item = {item[1]["description"]: item for item in d.items()} + matched = process.extract( + query.string.strip(), list(desc_to_item.keys()), limit=20 + ) + for m in [elem[0] for elem in matched]: + # bypass a unicode issue - use .get + item = desc_to_item.get(m) + if item: + results.append(get_as_item(*item)) + + except Exception as e: # user to report error + results.insert( + 0, + v0.Item( + id=__prettyname__, + icon=iconPath, + text="Something went wrong! Press [ENTER] to copy error and report it", + actions=[ + v0.ClipAction( + f"Copy error - report it to {__homepage__[8:]}", + f"{sys.exc_info()}", + ) + ], + ), + ) + + return results + + +def get_as_item(k: str, v: dict): + return v0.Item( + id=__prettyname__, + icon=iconPath, + text=v["description"], + subtext=v["date-published"], + completion="", + actions=[ + v0.UrlAction("Open in xkcd.com", f"https://www.xkcd.com/{k}"), + v0.ClipAction("Copy URL", f"https://www.xkcd.com/{k}"), + ], + ) + + +def update_date_file(): + now = (datetime.now() - datetime(1970, 1, 1)).total_seconds() + with open(LAST_UPDATE_PATH, "w") as f: + f.write(str(now)) + + +def update_xkcd_db(): + return subprocess.call(["xkcd-dl", "-u"]) diff --git a/.archive/xkcd/image.png b/.archive/xkcd/image.png new file mode 100644 index 0000000000000000000000000000000000000000..690194bc73d1c467f2658eeccc52c284313a1c1a GIT binary patch literal 4959 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 literal 0 HcmV?d00001 diff --git a/.archive/xkcd/install-plugin.sh b/.archive/xkcd/install-plugin.sh new file mode 100755 index 00000000..2e98fac9 --- /dev/null +++ b/.archive/xkcd/install-plugin.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +set -Eeuo pipefail +## do this if there's any error with the installation and you want to report a bug +# set -x + +# supplementary funs ----------------------------------------------------------- +function announce +{ + echo + echo "**********************************************************************" + echo -e "$@" + echo "**********************************************************************" + echo +} + +function announce_err +{ + announce "[ERROR] $*" +} + +function install_pkg +{ + announce "Installing \"$*\"" + pip3 install --user --upgrade "$*" + announce "Installed $*" +} + +function is_installed +{ + if [ "$(which "$*" 2>&1 1>/dev/null)" = "1" ] + then + return 1 + else + return 0 + fi +} + +# Check prereqs ---------------------------------------------------------------- +ret=$(is_installed albert) +if [ "$ret" = "1" ] +then + announce_err "Please install albert first. Exiting" + return 1 +fi +ret=$(is_installed git) +if [ "$ret" = "1" ] +then + announce_err "Please install git first. Exiting" + return 1 +fi + +DST="$HOME/.local/share/albert/org.albert.extension.python/modules" +if [[ ! -d "$DST" ]] +then + announce_err "Local extensions directory doesn't exist. Please check your albert installation. Exiting" + return 1 +fi + +# Install ---------------------------------------------------------------------- +install_pkg git+https://github.com/tasdikrahman/xkcd-dl +install_pkg fuzzywuzzy + +# Seesm like the xkcd-dl beautifulsoup4 version is outdated +install_pkg beautifulsoup4 + +PLUGIN_DIR="$DST/xkcd" +if [ -d "$PLUGIN_DIR" ] +then + rm -rf "$PLUGIN_DIR" +fi +announce "Cloning and installing xkcd-albert-plugin -> $PLUGIN_DIR" +git clone https://github.com/bergercookie/xkcd-albert-plugin "$PLUGIN_DIR" +announce "Installed xkcd-albert-plugin -> $PLUGIN_DIR" + +announce "Plugin ready - Enable it from the Albert settings" diff --git a/.archive/xkcd/misc/demo.gif b/.archive/xkcd/misc/demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..4205356f9266a0c9076bdd0588c1c1d23e181516 GIT binary patch literal 730052 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

Hse)Nr=~A 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

2o>KaeCp=nC~{6l7D&%`<{8o5 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ÿR!u~q~u~9(XIu68!Q$% z?MYLv#H8)pLFj}vZcuZX(50Q;Lio$Eq(T6~Q%(e63LFzZEJHO~kUjWA>;#VmFak;V zLpBtGXBYq?h#FG>0qf+?cy*6o1c`4Izz59AS$;}dI>cJGB>)syUcja7oXT9*It@)TI{^IHw4 zgD3PO-qiw-pvB&_13DDp(R~9F(!(OvgFN_@nUEDEuvI!#97M=NI*h|N*wxdxT_v$Y z-*m&&un`jCq<_|fPnBmK;K2uS7KZA@TYwIRA03fcNN}AeMp<*9OyeTIPkDT@eor;EL}xFFTk;Da#T8(B!UDoNll1AtIue;Q~TQiHb! z2qB>V!i7!`gt9||swb1+l|g8zCZS0nSVK2V&t3FQIMmToZBaO^5jwDgRB74Y@Z36} zXkJLwzhcQFP(u|VDyIDdJXFqvqKPF`l94cI5{A@aXx>IO*QtQl=-sBX%+?er55YZz zcFmK@Hj{3_iW^W*2N9E(GUh6fmi`#PA{35s`HDXbld}DTn_Ay#kw$7R&}8UO(8kly z?(9MwEnb9PgK;eVJlMo#<)@@d`w{K(7%kE&3ob0J^6cBwf`woTP*Qvx*;P~rwX zpaVASh{#fd-#EzF{A5V+!_bOTjK%~fU%d%8O2VLz)5b!S-HsjX&NY>dvS=NMh~uG6gFJ}( z;#oLMiMMXfI7k(a;aHB{F+U{LI;6uM^RYVATsR0Q)ETHfkZ<=&5hTnpchLia{>=$` zsE8s(J$yqMl2t8GL;OAjgl=dN;#tEY=)r13!^%TG!o%9&nd&l@J%B?cUkNI7L#^!w ze{3i=utFo4aUEC!IB*?@;+Ys_G7M!;vB-vTm6L7EZT-$|1mu+_zHdhrfNT}>@GQUt z2!SNHSEh(FZ%IdAuii<#_vpTc0J3GW`FiJds zhV9k!Bf_lNvV=~|-vWI~s_~n7eIC1MGdFuPIE!-&F&k~d1UY4*7N6V`S20eT)D-75 zPruX^*ECQAb>;E~->d^ne$_*k12({1jD;>2Next!4K<8HmJsNZ>|SVLcB3GcQ8FgwK7!6Y`cC)Ob0Puc@KSi^p%ktJ9|`2H>^Hz>3Bl5XH5{Z94#F?=-EL5!L`p+3bS~J8gN8Ey6^S^kj|NR!2PGq2 zAR~cosg1UOUfNxR+dq6ZBrXzegtp#D4lu8FM7XwIfE%KkHhciHZpZd+(>5WqTW!4M zY!fnTNwUd3{9T+6j56AnC( zBrbn%Xw$=%S;$j~s8Js*i73`;%M}|3AzIKwH~a!wo#c89q1!=-CH#T+jsx?8H_wfZ za&I?`$M|#e&RNK~g+=#u=ePoDhYqb{ukY>0_h zi8A55!-gJgIH&`~{sSSYZ#m>eJCJvl_(&D?MqF_y3W_Z@PI@H>ZDk$_)9%k;4p(fT@>2l_qc|5P+$VfCiWoK9sttp8&j6m_MX~ z3ADNlyvIJkf*=$D3%r04sKF%Us*!Us6M1oa?2RdxY&ndQLu}wP80DXBLhnL}I#iVu z&DbTq2RiI`S-Uk!QhSYTj+4}eoF7S=+m(}`gQA!JyEIhv^1cIH`!YQELp!X)-!O@u zLqt0~D}(y(L!d)Rx-yLR2G=R**r=Xtr-wYr=ZvyrXFfE+3YajT0*=tIoR`dL~uC{ zuEhBE(bBM0aoe?A$q}{=B%SMbjH!KU56QmcS=O=rzUTR#_YH$o5{5%bn8#}!$b!7S(aqb3R0nJ-e>NS+%m3pu#w0FKz5i^D4<4 zVJnlI$Qhl9B~XKw%P19k(fZy+TM0 z`W2C5N00yN!7KL-8#Zm|+OZnc=VHq`md4rpM~_`XZQsVFgD3N2PoF=51{FG#Xi=j_ zktS8Tlxb6^PoYMYy40S#7=e26oVu0&YgeyJ6C{u{mTXzGXVIoryOwQRw{PLbl{=Si zUAuSjs-0D=SRTKB`Q{Zom~dgkhY=@E9QJGDrT)B)kW2u^G_C*05g;I0vY5;J3T>9W z1ES-t{8E|VEQ2YzCY)i%E+NKrZK7e%GKMNIp~-LM(xDSxuH3j@i!CJ_7T=wp*|O6w^k|Fl^Moq_&o$0lvYfd@l^=n+YwaL{3g98DzrvD>iQUk7;r?bmAG5cDJR!mch%Kb;n3MGxNu&juD$mnYKNLl@R&|H z7qQuCKY9@SkHAkq#fC(7w5cUkG0s@yjX7>CQ#L^k zS>%z?6qC#{iy>L%m050?u1z~`${u~_&{NO|_sK+0&QcI3B7A1x3Iu>y?o)Jrj~wTwd5CcisBDJlDzhs!*$@1hHU%ru;iI`$R%h-c+$Ds zBog1LXGRLcDaXTz6u-Mjhw?SfZ0a8QrJST_?3|#^r@>*a$wR5Sv1&`O^(HbY?!)lk5tVQ)&vc-a}8Atk2B3$C2i3Pbu;^m)Ej|4Qv%`ZM$2JFGleQg|);*%&5=> zF^EBv+=zo4+~7@aLL_Mr&RBn&l03SBiq|P8BhSE>jQX=7lX#6p>pBKj{K5Fo%?o*u*(cq=$}HVjoD1 zgCo2lj*$YGMm4UHjcs&e@|u@DInI%ea+w~Ps#ixn?vamVA>bPe;*RfWKw5EoHaGieZAMDo!D(e$h*-sqoXP++Hs#3E?1F=e8Bax_#D#2u$R zB_|KH0?9D4BkuU*2sjDIhzu|RQK3h!h;%_B1@m3waFqiuf`>s+}BO!F7A>`_DoNvl5ejKUCJI?hV zoS=hs4pRt+E<`AM%xg&2*cOK9@eJwM#}d>So>1;t4jQ6E9yC%3gJ4oFb)f-u36KVSfkref zz(i^P>=BC<$g%@KkP<##Bbi)wWFK^prUG=I|eZ~)+ zfl`z|yTMgcFb$FN(wFL>SFLJAw|%w)9ku8igOr1ZLDV80?ck0&)}ao>qGKJy$rUvr z8_j9v)t!H(pnGOij$a_tB7=}cH|jYQnhb}F2ZD$%ILjVuoa3PAo&}?3bcy< z$*7)SsvL0#4q_A6+$vQxXHD8qRQcdQn)R%lIfpx;gHf5Dj{J< zV}T`{QI#$o;VDNg2mx681fmwym@YhUEDs#RqaEz<@rl#1jvxzJv5F1yk%N;RVto^{ z?KsW~T{2i3KQt&bg2#!^MUv>zBMxfC(+M(Xlt3~yAr)1hv(o&qR4fQu@O z#-z9*Nr$JpxDMc6l%aGE=R*K3x^!-r(1kYip%IOg?wXg;jkb$;^N>eJPnyzkLGK$O zLp9p`gQz1I8qMNc8JXPU1fuCvZjAu~(Kr=#Q01A=I)WNgmH-hEiUkf%K!aTWe^@fP z_BB{NB322rlES{$^|4>@18)4;Cpnwc4*W4!v6$u3iIc95;qeYER}(w$AmTTwC}Rqu zVjQeZVxXmq?k~zCMCS1jdEUM5azKK~cKwBAFA|9BoMX^GnUQqo^-nbu#LM5LhEMFl z*CAC1I}YKA0c}(g4!vV1D4I|?-c=%*zylRA?(_Xd%UcV<*&qq)Gjt!)??kVh3|2 zvH9OeS~=FBM7VwtDXZ3Vt8!U44G}62Ac>zcrP;C@9tf%?V=Fo(4HaDf+!pDB;VK%= zDeYZzdxtKH_>Q{3qXXZaWkouyu}lV`BFtu2r+e$M4s?~yA2OkPivT8}*B%ia-d6iR zMC7<|z!UKI%+)mc2@!aV0F5&#A4$7{mVgm+zkUz4v_^W1e&2m)GVl z9scnhy>m9!gJ$mIB+xcPntx1k1XcTo_dtn@2qkr?l3{gjT`d_3z?vieJ;9u^Pp+!K z2H1u|)Ue5F*7g%+ABJe~33d?LH=mpoawe+vJ49K=Fgx~<{5e`m5=w+CO2&tB6;bv&`1R_TN_@nKFT<5 zh|4Gj%6587UF4zmCeR`>>i2x`2Z1mMV3?K!Atqr=ulVyl(K?-HiI_o z;U0Jj+B%H@B0yUDi!+?gPoioC3XCAC3a(tClsZ5RhG+f24#M8A>n5xXg(4mbf!CBk z#H1}ZddVw9Vn|9SbUFeZ3b5`P#1g*Yg}j3BzUdJZ?`-}>_o%{QE@&Lqp)@X!g&u*7 z)Jb2eY4l!bMl!HM+@*`yAqPDI;5tfLbc8_&VH9SE2JHc#hC~`hZ_RWEqh?SDb#WJY zu@`NF2$e7x

Fdu^9V^3E7AoN@>38Ar&;ks6A)aL>}1bj4E#JC}eIb#LU$1A(BY# z;9(QK$rX=6y70*+#vuiD@Z@|kCS`IaY0@Zw(HL>kWr#5+c@le&QH^S<39d>EK+V&L zrqj~LmNtXdE`#aVk!r?p>^uztRrXy z%eo_8LL{F!gg8F3^A?aJIPRNH;T4Ml;2P_0C@Mm35hiPLG)c2GWAY|@GBrVFCsngG zS>`9zNWI)g27*olL<~=s5)q66{o?8}xR2K=jQj|q8Z|(4B|d$`i;w(*p} z@*j$FDzOVKr$Q}Dg)Kee8`wtN^57Sqt})U9F011aB1pzuWE}RfCuZb4&f`czLP#W1 zVmR<@ddDL`amR3LCfemDe8pX2t1^?tB+o__(7`PGjvlnFu~Lv9O>RAK&om`;LMe3j zP}4Or)Js@1LpgL!U^9*Ihi8@{Xuv18%;A&&(!d$9N(R=`zu1w$#Njf`Z&2zX3)80~ z?7f$FwcUwxgrY?J>vUbIM^b3$rEqz#@GJ&_2+C#oCy62= zGP6Abx^JALOb+O4P!$Qby2m)9<8hAJWUWffBAGK}rRtgn``5*?c}4tF#t@Ig|9mB^{{YAM1`eH1jLQ zlgZLS8^X;#T2Uvww8w-jSV#-6&PYuEb?ktIh&~CkA`^2c784zAgc1>}iLm1WJE9#3 zbV`F2D&RpCth6Frk5Jw9UEwv243$yowJsF3Uh$PMJ~V)suVyym2}hv43W8>O4PZk_ zG5xElo+_$@PAd+K9SPtEgp-xnuPA!dIpxrY=AjV?K@kFh8w7O!YSoW!H7aK0&LBp3 z@&{l2P)@?naYri&Z$F^)c;vNp* z0Oq!Be`W&=cWplaK{*0)C0A}K*HSHaZZkJ=3wLeXRx9u!bmw+;G;~q9ZZZ#lA zwn1(SURskj!89LW>Nq2V-H=Vkc ze9aeq)t5@(mURJG0Mtiwm1kb_^?=#pUJ-bK=VD(22>W0|!HgyoKmazT(QLy>sbuL3 z1+3S`&uCKNDFc=gq(n#m+mSix$44{PC*q+%280?2`0PejYf3ilr0ZbvV|Q(5_f9wgnyHzUO1UTe zA)B|En+w33J0c%8K$HC#e%bhV448rSx#sxdWFpP@_Bo*6!hr)w8Lci}>R}sh$@|E~ zMZZsT!cPpzuj(AE19m`FS2%H7bsb;zCk}=Eni-^w^lBdyXf>`Nn3NEs3>C`36uClQ zXg11NfgQpr9r$KlEy6sD0f8h=6qA&0(yRrCB)L+LAbbI*2jPlE%XUm6V%W}zLd8T> z&Q90k?yQyupKf!|VH9vWLWu`5P}z?Q-~a;PsHiFu;5Y#6fJjlt9eml3;}`*6S$e~o zb;tSu@-IgJ_5rQuR;}6Ek#sqg7F(7ZnPTeeYol|OGE9Kn7&o3<(8NOU=l=b9k?mv_$^v;Ue@ms_wU z`MFKh0XSQBQ`>m*S)dVEfz3O;Nmjdp^1}#V3I4h&N{#F$1{+oFzdUs~8Fs2%G?IiD zQ2wh@46I^_A{|w@qkX~&IiomfRS#cU9^L`tiiG6;!KN3gssSqy&S`z0f*#6&Jllh& z2_hZ;{7S|$Vibx&K)xnaQ1A3cQHX59K)ARxs`PAZOh(|;LL4GQ0uv{6LgmDG&X{6G z8YYWL0jGPAcC9ci{B`2u! zZWEvbvRuot5D*Mkfc>P9Bl&}!V$h}ABlZE(C-=_zffI=Nvw5P^UeSBo&6}XPM>a)+mV_5nq3{$PdSRsw)=D*C&si!< z0B@nogrifVQy60rT%BW~g8xef=yIe+x+xY@!ncJdw4pnx;|~VG_A-JPs%tCi;lr6s z#AhNMY@rcM+-;u0H$vr%T5vc@rKkS`Kn}#EZ)jZyAzGq0oU(XC7zm_gT8Yu zU=KRXAF=_?Bl))rLg`tz=_4ZO5qapzu;||x)+RfS1$a280Fs$mDcU}g-yZ1y;(m4K zKIxNp?EkKNml+RNL_oGjy`6n}0RKkVK2@gskFCtvN9`*JOS5%|p>_Q4d4ewIm<)-j(TPPuqvB=qHW^f_(0 z<+k--KlW$8viV`PB^}YU-P;$n+nIl#!F_o$O=#4|vaQP0koh<9J3N7IzhUiRCBrs7 zf*j&2RK-7#R<*!4I{q>`*ir#t--r7FeugC>`ai^~ym)h;a}rb`I^;8&}H`#*u>_p(=*$TexxK%DH_1S#DgoZ`iO| zt7+4kwsPy}*=uNR)S!_D@%$=BZ=%F{@X(F>wsRf4r2p#4LpL*AId%1vK7@yg=s`>4 zetJC{kttSEeZ&?dYZk5Cxpe8`;{hP=j=2Byy~$f3f=`G3kQK;_IBx`aeEa^*J78Kz zd--@A2B6_*;RBZyNbcxv1LDkt4JSstnD1T0dms7*EcmCp0|ycp5P+-Uw#$eMsAydG z-|X7GaqH#{_&3DD$Wb$vI2=HM)(}Gj{@@SdHpB?T01w`f`Dw+^A6oBSK!Lc1tMdXe z+iwbD^^>Wp&{a>V;hYL9 zJzf3d(K<7IGY&fIo&^spZMkI$HS>B|&pW1CLI|yJg-Y;5(E$)agAVZnOCt_f0?~mK zyg^)K5w#cCIS`rSKwjPbl#hIQ34ka>@gep>ToO~vUv;!8rf@?HJKPAw4I#r>Uc}*M zk3Lfn$6bjo;(Xc8xb*z4XqnUNMWoLmeB@EbE$iO%vTuCx z6A5Al9IbNG06dL1dx2j*I7EdXp7^@>Y;aiwau}^{burP=ks<7^_y62!=GGb*gA# zLxIx5Nll{VtZ_)CdH*QKF9awSJXqow?Vt-i&`}O&g`+3WJDxh;6|e10L>|5v#Jz|T zh;L{NO!Q#KIIsaQT0vqQ-6I&>xYGhPY=RmTj0itCAvsEHZDf>t$k{HFpN7Q47(AfR z;BW?*I??5bNn9cTcovr*dMt=TEaJjAaTx>uRIvb)tH*;1fPfpMv1=_lVj9=j#y7@s zj*mlPUJRf_#DEbZcKl<>q~^r}bSN>Ak=|Lj_{Tspv55Zgq5#f-07YsbSEd2LZ>3YaHz!8WSj>IGlMa%Kz zQI4#PLmm=ohfGj4n6uF182f|atG;y86H4O~>>CML_UWP%Nk@^2On?w3(alJeQU#mw zn;jy8#j#NpGQDWXJ^*nUp3&tzrtGRNzv`OD0EVj6ylPhWQveB2jE$Jk2U-g-07qP= zkuAcjUO8iczWz0^gPjIn*vi$g?#**@wHQS9!LspamI7IA5oFyuS+i!A0^}gw7csGq zNOXoz|EMI|5D^h~@J5Sg32W8P@>$8k)ghQA4rxtGved2?X|*W;1v`RQK(JEphi?-eRthmSj<*jm=i%sWR=rUtHP1`IA)gJZ}p6qR}d&`N=bmH#4 z^sTRbUH8xQ>UY2V?XQ2mvfliDX?!-FnO*Azl`6>^Xc$LwO zbcA>wfd@#66;f1CBVH_x39}lw6P~Pt9q(AjJKh10eboaUMJ388ka9YY`1D-y;%P)Y z`mS=w1HBKShcwpbD_?-ak!P{TsL=6^XM7@H_$mjJ{d*S#XcjOO=tf-pQn6n6gJXd4 z&O;!#<-{Q12i!1AWlGmsuYj4XWA2!A%>0lnr`fn()?A1HfmlqCxd1iTE5hPj7mUdO z(0mvk7xQ4mTWd=_FWl$66H>cS))QM_l2OwrL-b_P*Zx;4=MEyTAk{oVdi+FJ51YpJ%#3+w;_IMEMLrlHA&N1)CItE zv8D3?WGnjv>q_mWMfqQEuJ^v=F1NXb6kprT_uTAmx4UU1;Bd=(-t?|FrvjXSf)V&s zD|yBvKui)@gu{&Gct(v$BI10yh#vaOFtB{7Eqk(>D_)0*5y%sG zOvNAcpoc%6=a6)4LZ(j5MLL>n6@#jz9O=N{L$30aYc&|<5}^mT08SE1SmVk{v4=cL z6=h4X93um>cSL^w!Vg!_!Ooh^3@C|nfF)$-+NR{ocE61P4RlV7okmM20g&~ro3`s= z`bX5Ko@T4_EoTT=1E5_=>j5-ljQ}V+cv4ySy8|-sd(Tx#b&8Km` zyT1>9_of?4>kPm7&;QPNbASEpZ@<0qt#5d!W1uQ|21tpLub_4W9rsTtD}G5s4d*Kw zwow#h59vVv4Vy4Pbr1-@&3BO6=eZ2Zs=YpbOw|7FL0DsM26P zM?Mks4kbrqRZ$MMFkuHlKgB?F6TuYeU@HD*EKTQr8&y59a0pIddi()0$tE2LZ~{1h z12d2_hn8n+mjEw-gg0P%ij;K@kxB?65&n=4TbK?rq(cA!GA zb^v%LGiYQ;UGjy7h=hm;GYf0!71tIR3a4#gc!^_} zRh!uVHJ%8HeuD_dLv6zcYuX1}>@pjGQFdo#G!jyXM)-<}xNE|viJBDvz4&~?20b&l zgJc6G0E^kbv|EgZ7vz#B+35AuaJT6~@DJ4&igea&eFF3;Guk^zaT? z;Vd*aWIbmt<|7pwS#;-M4How;wGd;wa*^Rs3`iz0)Zl*mAP8;X1zwN_{=iYpR#}e4 z538VMfH7CRks^dKO~dC8-Y{EcF&mfRcfvt;-m#NCDIGsKA87)UGD(v*NkJ#lNN6Vi z9SRT*ss%?CKpTlgG<@YET$vtUsYnPQmIpwVoMDzS!;`%smBy4N3lj;&Wov{aiMk|R zafKL`RY!B_lT!thcUeekXoeSJY=U$&xiX1XBWz|}+mWLA}IC2S<6C-Uyt*X(ig2 z2kR!B$BCRl0*<}OoXzQ+-t(K_lW*rpDmNHFzVZv_U~^#tKQWb2kAMyGAdPlnbmPz} z{6m06hkz?LK>30W$HNpJ7cJ+*4%@jD=^!h{f(ogkD>W2C29_<~!4xrJK3f6*lFIWx z2}UcMkSe<}e?dWI0)s2#c~7i~FgJ;l^U)xq^KF0hm^XtV8e$%eGfMs-MxH@gX>~Ll z+M%Chio{_$MRXzx&>&xjFzeuYv~d_301uKVdr>895rCtpmNPu+qk_qz-{ztY(GPF1 zdUt6ePAVOdu`l@$gtZACNxErE+H9F9CTlkzgHuTu;*5UQl~Ae_7veFDcotfkW?U+z zO!%eEQ6R{tOK$=ZrDbfKWg#I7C;kvj(m`8px@Dh48I}_Oc=`}}Djj?ZqS6ss&*>%A zn4FbrsWd{I#(AlmYN^X9shY(SI0 z@CZHikPc6w4GOt}$8)O!`4&gfCA^9aqyVl55ePfge#N9qY>+1YkPU*RGfQ9(!quT< zyjZc#W3Zcsuz6-V7Tar<$zn5pF#w{{}H53lP z(5!v13EEIoUV&4!FbKbj5es%d6j~MZ;8V?7E9vPK6=86UI})2<4f0Zh=b{xoF&E>2 zVDlra+2TJc@`fVZtO=1I(CwXvB1Vi}t)lf28@yin(Q!&|&d_@kG37#Y$^f`fd* z2TF;NvPwa|Z*{($lfF^3z1q>eP86A$X*|Cu9e!uE2*9TQa5ae0|Gr95znXZz_Q1cl z<#?k8GJ!))9gs~RFo)zN1FZNE#RNwZ3|=g7C}v}4)4{!!=8KgH!nWZZNLfnO>j2p+ zOmPu>hjG12h=;Uwzz)H@Bn*1!0RRcm!pQM435ysBz`@wWTqnS$1Dt$&+YoPSw@(~? za|^{&jE#89#8-^P{nfX_BMLjp-Z#BiWRR}bL83JRJ*kB|%P0J$O<4wS2_MfXAS zV=QwkgQ4F@oUNLbww19Px zFYn-fT*t$LgeY2>u~rzu)InW*p}~Zev)|^jo*WU$YZjV3|5u4YGJWcy{?M0rSR$$P zH)9Hn(qpxgL(9AoA-F7}s=P6w%&(W>v!!9et!Hd|smuL~JjCoo#@t$acu0=Hi`I3p z8h~gLQGJ?a9MTNRyIjqBdCgKKv&Q2mFY|5NXI6fcW(Xhy+9J*;49)Da&Ono9?)=Tn z2wTrQ9gxen(MiPx9mPzNPQ^*L2F=jzX2n?y(GguwTdXMqs<^#d2PUy(bde6<00|g< zES!4|k*pNO3J!2=x%Bc4x^S)qLAct`4w9QwD}gP_x)kSd(X^t`FXs?yQ9cr+E@zRF zP%#ebV695wQMJ&X&+wi^*A%&+3N4KgG1OoJJx^vh{|}ip9te;Ej^$R$crj~7hG!?4 z5K(He>>7@cW(lAKZT8i}H#cIfF<7nDO4HS5!L;fD&?p*KhT2=g^s>^c*NMc}#PLaQ zEfHLYid;FpjR84^ea(H5H0eQ=nU#lG7*=2%F>>v8c{!y~V-I1KYZ<$XTNVIp(9IHY zcAKWxnGM(M!P$@f*0v z>Tu-34%Wbu^K)YlW~?ib4(~wH|9}lbVJv~5{|ny`7ye0sRBN+2J1^;y6y?CXRCKYITW3ufmI>rZ`7(q2$NIr`XM-X`U3>5|QN*5i*|nv80Bw&sEF4LBv7;3A1OJtDw(b z`x|L))?2P3ZGN%@+*xM054-RMZFvDmfK}uG1xx@2gKiJ=AP6Du02AN>T7Xr7E`)0C z=N)0QhK}fpeh!T8=rh#fBFm>`zL!i)|J~Z{>g0souP*E9H=W;Y>$k361np0?&M6+& ze+YpGqd*N@0UjXH(u05sAjl$WfkW|aQ!%Fv8|XsDViMROa#+DEJkj0~u_}~X2YnC- zqwowk#;Y=6J`IW%?ND&2@T>-!W8lD!rdtdA*<>E}3+&FgeW2cf(7E+Fjb_+O(1TCO zvmy$2Jf%ovtZEjlT8hgv@HPb;XCs(%fx%(&9STqI%2O#a-WU>Z=S}wTjs)-qn3D z!4ckHVnJXW2+|-gGe{5PunC$A|AT`-3?&F27FiC>K7bGB6;76t)}RaZ?JKCT74yd| z3Tg6H!49k-)xl~%TS%ax3%na959$Cy;9w1#@NcNVt!RM`UQg}001mM7KEL$0T?|6h zu#!thKZ9_tk01>ine><6*$0p^68+elkNKYu`Y*!sL{Iuy66>Xp`rpXwq0joQ9}!FM zCB*P=Vxg+3-DC*((e}+yD>5owkJ4aYbO#v@)M9Wg-3JR64j&{FD-obJMGxVixC1l@ zf$*#(#bfA@g3vQ@*5C`HU3<~M`-)#;X01yT+|JD0f(BMIY2^B76*wEoahzQMX5J)iMMT{9WZsgd}<42Go zMUEs{(qMuFl2oo_+0x}pm@#F}q*>GEO`JJ(?&R6i=g*k4iWSRK)aX#4NtG^T+SKV& zs8CUwq*~SLRjgUHZqdJky7H-_LQG*22#q+4vICSO0ZAJ%=-rk4ssG$lxnQk9TqfqH$ z#SGgw$KbSS!)DFeuV1w+Jt~WKls3%rKs&THYOZOteFi~7RSP%nT9-!gHm$b!px%=o z{R&r(okgzU#g8Xn|1h4Z4G4gMFW=ta`Sk1E&!=DC{(bxjy+-BV-~WFA1B6N_qKqmE zDFG8ya6tweWD2bOB9w4K3M*V_Kb9aQX&hQgn~V@?KJ&;Pd&U9A66Eaqr5q72>Z=@W zP(+R}!yZBmopHXwW*l|Wv4*-7QS+sobaK?D9ChGfZ=t=~87;-S@aTh(M^y7g7gQ{< zM3X@Vk@C2@ehUYkcIbg99cmtdlCnDR@Uo6KkyGxMc36>Y#$&$Wu|*5}^fRP`gtu$W6b_4HFvchV42QcE?}Pf1l86(oAn z`Q?#21+#1%|B=`M2bEYS!^4tV&N0(Pzp#o;oQiHII*YU$Q$IW2Kn9$fK7E0AHd8S|ZfM|S%v65oy}Zn^8W`|g4w?s#v$ z`_AcN{{u7jdvL-FU&&;=6IcAtk`oxo9S0zBXORX@Z8GU;JE3}<^xAB&Q%tuzn|Y?j7tM38ix5<_`OMz0^Zi8|b%S2~ zdFZ2;e)`1qHvD?*DF*x~PP6y^dr%Rlethz;YJ4Pmn8n>JOL9TSqk!~!{^1u?z=~?ZL(V9^aX}(sL><~7&HAjS zoKaxo90Wn02ee@!J6}lB5u^1T%^F&x3Sy{1uFyftR}aZw9?>GYhC~fUY6~EH z()TV8nk5jU00uV3%?XE_-s#7m}Aok1CjrY70Fb;eVknKWlT-PTEv+=`lm_ys(k|5lQ8 z9K(vHK}9!u$B@qrv@WoOT9HsVrUn{B9^I(L1Sg}GX8>m%hP+7JmKB#=$}3!CEJsOy z_Ko*tghaPgsJ94V30qhrTAdLQAdwRYY$Q-m;k0K@efm?NilmY9B&s7NNy(xnb%*o} zYEwyt&yS=79JhH+Ev$;A=CI|TBv}?Vp7T|({sJ6jVr8&u(H!T5^%v3r$IBD~IULPq z91L929o2f**T4ozZjHzty;_TD=CTjUd4x65`ip1ev>fe7M>&>Oj(Ti0mZTepHO{&T zSgo&1sj=!YsDX_g17`NhXva9P0lR}5ghY}>$Qp5^K$oS_A@q<(&*n&`$aaK@ z-5AYo%5~oJKBBOw0LCwS~8}6G9Iy zI@4vt{cVFC{NVA?cDEDm8*V9l;p_Dl!W$+}a7mK7V=0YD{#>qDo}1i{Sa%$>T!-w$ zTMv1xqnX{YpMe>oVrvvb8rHxDHNZiQaR6D!N*f1}*x@Tf$)iZq8i!|IEDyyv_Qye{ zGLVamj&z(OGvAG9U*Dmb3!>v4F6MBV&3tBuNf^Uxo|uK%{N|2n|5#-GIKv3+d}ln5 z-~~regD1{`=7)Ls!w5zPIv8jJfN_A}INNIgPK z8_YO)bPa*>V)SG!2A>RS)1}9ke})-$Ao?Paer&8O4QO2FTGtRmC!BrV=5}H%x4$N~ zr{o+mebhP6%f2%VDzR&S3HotNWCuJvlj=Sxn$gsHM~aoKnFW^V)^BB^fE|-0zCxsS zKAX(~ySx!a|1TWX4zE^}+{`024ciW>$6FptS7--Z-~;E1nu~q#1i2aE3!l`nA6Aci ze1QPWrg#a`K=4ONnNsubV-=dx|0h>>=`!6ki@mad#M)I*+SV9`88xxI5h{qKo-gkgGJ@QHW9!rt@rzG7)2aUWpC}yilXptk8)gqWUtr=R;DRPR?|DVQp$U1G!Jio~ zA&pCKrS!e>nB{x2zQBWDf47mR9eZWhmVDm|iT7q&%X2%@cUsK@{^Q~|;|zL4=Q~aO z>7D<4Ks%oD)3=G_sek>RSe{|_NcQGWAO?lRBNH94|1$wlfD76~KP#!9UccFa4t2bP zUm!^xJ!F^ucBLaT<)Gtd9`B*_gNHQ$GouK-rQ$ z?7P60us#gjK$_6LgMm1Sv$GSh14FTgd1!(au(K8z2nw7J_ESA-^9;9R5(F#>Pg@5= zqc{IcjC5EB)Db}1`8LNewBk!K`?EiEV4hHGz_{|Ibl|8Kj6x~wDGTJl3)Da>%)*xN zz=KJ)3s`}P13!h(2Rhii7NCTKz=zSZvlI{qjqrvOxHA;Mgop5lY6t}{aDo*$0VCi7 zNZ^JUEVCDEKY6&nKIu1kur?(LM96`McaTAm|45zpYrP`$2pE%xM1&E?fUmU6h5$u5g-5p zC=|)^hioW>W!tM<6mqRfN1$j7JV+#Z%$FGx$O~6GMd9hfDy*6958)P($)tffV4y zh;RoS$g>ofhK1mVUATd)lS5nx#0Psu#j7{81HvUjMEk4819ZRo>W*rYy-wVk1T&+( zvPgGqNtX;6c%;Xvn@5?vKzlS55ERA{|5yPo*pkodghN6n}_?8vw?M9D#;BI*dHMjZ_@S`7#mf3`IOi{5cjz+YvN+NwiE$#fiz9WH_2^ zOX|BxQ|Z2mBtJV_Ms7%mqcq5(bcl%CJUo+uRJ(^D0L&QBgB2NvYA^+0oVYaL$Og+w z#(O=kjInX_!G42>jswCqDiYAb3}8}A(Hu>f{5rVAz_&cj$&*V`aYcQs$`L>TG}Ox` zAU|E~%ZBiVJ39f1w6pUwn0+V&z?6Y*C^;{(2XdH7HWUZQ^exFG%~DyTcc?a}2|7rN zH_+;i(1cFz>`q8wOVuQ{)C^Cm|6@%^!AHQXN&;wsMZrb#BY=bK#b0DYSC|1i>i{ue z4>gp-Y4|5&^gL_AOBxG4Kb2Aj9X^=+PjhFd&UnVjI#%amC#vL4}A)s+0lu9D&=6h!Z6M z4Tvm!P*OYFfw_x?&EwMH|425fq)0OTIy-e!QxQijvo%ZIR8IW}IHgnFnp04Pvr7HA zA`L@^zz6%>$rQ-Tf;dX}6wrjwO%Wu)dI-*mGrut{2yd{<5!iu)=!Y^~w)30RudupK zl^%~g!sbj?XWh|H9aW_gRcT$bQvH*hghf3~2zxlx%|n6y+zSvDQHSuw#ykNUKv$|f z(vl+wFx<%>aKnP2%RDPqf-BQ!%~yThSGkGSY9%Ua{Z|UR)<2=w5#Yy!FozPjvxWo> zCzaKMP)OJ$fOwtPGcdzNh@0Vv%5UA(fx}mR4Ox*L*{3p1fjzi@Jz3o%SQ*VcBi&Yn zn1>LwGY#OyqYPAs|Az`&wAYWN zRHb!VyvN7}d=>K2(EAI7twl zNI$LJ5x6*optJIef!Qs&day%KfPx-afgC^rJ>Uityn{Q416QrvV|`x^?%?)~-}?O? z`VHZwy4%F52NXtOPCL0~RioyVxy?Ns6ZT*lu3@GHVG_ok5zgTnx?kx1;Ptg(As*t9 z#bF*UoE<)5-kM<|F3k;YVknN{O*LXA_M0TG;_UHZDHf06-C{5P;wYqIEZ&8~EGLGZHL1QKI16Mq&fa$zOiFI7OFKaWJFHn z#`9xA|AwSMZe)%jWJT_XJf37rzGR<*V@L*-N8aR$kz`C>xeu4YSN=3#zjY3^ok{!VJfX2ZE=ac(#!{^l40W^`U>c6Q=&R%K*< zr+4n*b8hFV;AVTyXMGOcd9ERH?q>zjW?{zXeJ*H&wu)i~X#ehq&WW=w<+NUFyT)mlj_U@2 zYrVFKxhCbhzH7mz>%8u3OetxpGwe(G>rf8t!G3H@ZfnJc3BI1}m|$$HIA1n&NQGER z5V*6)^%HZj-qi&HFReh2hHTZ|XUVqg3`A_#Hnw_}8+(X_6#&LoeaKY!Y>tA)eW zy)yzZ?Ne6g)jn>0Ztd7siOODX&Xpco-E7_F?Gf;83mNU;E&&vgtT%`NXZwn{l{dVpCcJBXPBHPAo0;k>Ges4d)Hha+Q z0Y?aI{HY4Ra2KcH47cnJU+xY!2?5XT&K~gtZ_QYs0fr6ni%jhoA9BDhZ1R4(nbzea zH)qvL@AU?9gD~*wUI+%x!xPxEI`9OyD%&ef!&M!D?=6U>1k4?%?}$Kg9B+s!cY-TF zf-L_=7;14MpL64l@yVX?*sk%7yK&~saq712f(YN+W;PgD1f%1JOaRRM|15|A7j6_# z+jXORRqOT# zV^B_to46>D*OD`bI1EM^5D@|H@>dnghRp~x@AEyK^-ae!TgP<@7xGYl_B$SR!!C8p zKJ}3h@DU*GJL>=w2+V_!by}au6A(<$n8hET*D?gmB>)X_XjH*esUAP~V-I)zC3j8w zbZF1_rIq%+ruNCU_K-kt_0H}oUtBzEfk4QG(t?FA==Pl~fi4yEOyKPm40dIg0e|Ay zi7Nq^y$Cdia*Mw+gjaZJV0edL0f;wqM8bD{Z+U*@cfIy^#Rhng|7diAFZh2zbiho3 zTX0c-@P~a!g)N1F{_I)c-p7JaSim&DTMSNMd~}3~cQ(x6gV1?~?RkRu`Jf;Aq9ngd|>4KgoX8c|N6zx{r83WxHkK~o_z6g@~NM060ZkF zy|YE<)_a5{OUUXee9QR|LsjM&%2e!ecdnrI&b{Q zUuwut{{#Vkj<9)5FL2C%Tqngim?x)-~jKfN)1(U>bdNR*ZnrD;0qeBQ(IX z_irM_iWVu_i$%lXh!oQ<`b%YkqnL{n@ilQsAcZ)SE?>foDRU;xnl}F>NFZq^&zv`Z z0u3s3DAA%uk0MQ~bScxOPM<=JDs?K=s#dRJ&8l^4)SNuOf(XmmMdd2)$q>)D==~jF= z#$=B%AT(s3OZibYkv%AJgo1__?NdmUCzMptXHjyb!D#cO)PZXbi6+!-xjAOhl_@!- zrAb|W877lW=_tvPdjcA$po0=xsG)}1v`v z^_l6h%QD-nv(G{st+Y%oda1S7V!KwP=S`Zex8H)RBD0Dy_Ti`cjgVkH?%+^g40`-h z4mQGkF_1$i&}PwP_TFoUWenBV0wP1b>0z%Gt=ld~@5VcCyvd)oRERKUq${HGedn*4rHqg#98D{hjsSym^t-H zxuHg#xeI-ve#dWNAi$hlU;UrD-Y@Ai zPW0=sQ{6b_$0MJ-^2;;toaLZHAH5`-cP_p4(Tg4^xgIWly4wk2kvp;4kt^yR`EFCegqviK_~e_9zWVHM&3MflAOQ<#zyl)CBG0=X1IbpNKb(gU z)oUOH%a%Q8)uVnhv4;j>Vvk%U|K>3tB+3UnSQ8FDPJjtqAq!jR!WT|!ffbw~$jbAH z^L&CBCZiz_y>>wu0+A^y3?dPWXv8BT(Rn)QArnzno?(3A4}{Q!4tLnZD}L*TN!%h$ zhRDS)f-#I@9Al1_h{ZEzt2}mD;~LTEMr&!2jAHa6QR49xN|=yY-{46lptg@o>|_$$ zsEt2l!IN8nP>zaZ3O@{K7C{!#jy%ERBAX?{H)4`UYGh*@GwI1B#j%oGq@z&$A&sw0 zqJ7S?M?3&22}n{zk~`^z{2VFBM2a$(Luuq$UEIPBW0!9Os~l$;@{KW|PT; zCq32UOm@C7nm~~yA2D{yogmUO%IIco_P7&o;xnN#NoOvo;n0UZRG10m=Rp-pOf%Lq zqu!CHGBxVa!c@$nU)1MK{Bex1gwtZOti)r|`AXsdbC!7&={To3iD}@{h$cm;L}}_G zcYZXeXyGUug=$p3+|#E9B&ki-;mAr5V<(qbCq?+-N|{o5vRWLq&MvhHecDjZSwJ}{fR4C5Lw8pinTwo zKrBx#k&AB7!y@mn|3)p+`ioq^l(1t7Xn)L#)=Q|Bt*3KqMdIqJ!;)nZZ=GyqL3`Pr zQiQdZ#cW0Pu~o8q7OkFmEC_A-)_<7RGK)=ZOI#{dwVorV`Wo(7RQnI(N&>W)1)*&# zs#&ohvbvH$C~nW1*0t)+x24VIPtu7~nUvML(iLqwX&Fmujs~^PH3@2)yIRW57Pd0k z2OtW706kHpA5$m*1XU1F-TY*ovd<(QVmuqP&N zf7V=B;P^uu&Ar87&k|55HgmVmrOh4CDgK0c<( zehws{-3(*Jip7%1SXopYwVN8c5)QXNSLjBQev9RTsG#OLrQt~T+N8@et;auwT+xVo z`63UuOsTZqTFUUwQe(AD!`ytMf4)pCw;IoLHMTmm9N2I?X$i zYT!UOn0E#GD?9%2q6<3e9FNJ&EB;)g-`iNJ&iPp|K@V~Nqvs6&Imd;5^_!S?)@cWO zH{)w=U!#1xFeNR0=}yg-Fdd~z4~jolaR3AWKmfQP(6b9*fGvqC5(l6*KUM*N5Af9= z@yNsm4zL3VE;{S?xH z|3ed_I}v!QTv-Wu)Pot>Bv6r2=_x|r)-unycTcN)>NZo88s|ULE)!ViVzpw5u#_-Jj`8y&m#c@=GzIKVTa;X}}&UJ;qVap!oy*Ny072gFU=MTzS*{ zeO(~&Ox!TnBxoP^d0%9KAAG^p_+j5m37Y^CpaCM_O9bE{72pB(lgL?F2EGzCbVECU zLpf0bpM{@k{Tc&mka*DpI^10)G@Jg>;FOTo4d!45nIKEapG24*Mx>qbS%#ZI;P!Rj zAyMGPrIZZ9o!?pDu%)0AP9Q58-#LUJR%KvHfdu|-pa^K$1PlwTR)58@yn38A>To9x{c0>Tvj z@t_7;)a~_NJ?UO1W+L$cU-A^3Oh6wZnI9VV8~`378cvfdRnx4c6H86Ru5l0tC7h@9 z+zZ-6Tq)g5EmuYHQYyWJA>9)E(Oa2Gl{zI-UBwQIf#7f{9GJ-zYBii<0aCmfV<9$~ z-p!&t)FKStQDW#~1~FsbRbz(@moVO+T#w=l@;ov|13hJ=w09} zt<(`@~&mLxjfggG35;#nRA{FZD5+PsG4zAm_0zFBv6C#X^@9)mtcLNT)|B}tR7x(+WC-);|3KDdvpMH0b!m>?W0(%8 zNjls?=3`;qX+k0$LOq?8Cgc#JTa4zZmpL7mdKH~oCZcJwP8H ztr&+1o1K~U4EKvl-#hc>B*ZrTw} zgi)eipF+)_B4^PtRyQrFC8i^jTBYz^XpLEDv({LKYG~wes7vH%B|ww_!s0||S0xA| zHyG4eot%sU)Y%;pE`ihF`6uyQ7@z`OC7^>N-GVi|U3tmtKhaW;R@L$VsOy^&<)? z<3+TqmAKS7C1@pX)(0&t$ad^cY(oJI08SO2)xL~-{zE>@WKGr~tlH;Am;(S@ZA@Hi zwrc9SlGRZ*>CGlBq4vkS9c+i~pVJcTvO?>=J?q{Ym9$Q43NdR}PABTI-a)}%FI2-T zY9I;oUw)=%HGf$$IH4{U0x01U)>}VhLzGRzg=rtY6}s8w(I6jLg&7o|5&{42h{`Z+V0xD#O&5?vD(!-^b?jY zVa1tjJzyE|Iw?=QE>Sk%`E}6s?nL(TYR!6?L^$ub(%zshq&Lm%y7BH)`7ZF@XDX@GOvE6N`HO8W4OZsG=LpE2G{DL13Vt9!sgaBtd`n7uuz%g(RsdhSRutKSAy->UFO0dC+1(BS@_Py`;Iaw{K6 zlDEE6IUMA4+M4x&-usc4ML-`dO)qrKl}(_iFz($>I4=E-g{_5e^djpRzNkEWgQa#> zIh4aL%0oG{;1JWF7|vx97cqZ6RXrdv{}mS_5|$MgdodXQU(#@K7iZ8HhcVHmuMocy zpy{P!w5u9}-D!~_aN=o@b#Ec-rjkObm>y`7O>qUPZ*^A086WW=+pDZ44JA{=8C&j1 zTCtl#Xcb$@7Td8s;PD*a1hPR`w?)|4{(}PVgCi7x0(8TxGT5@21Tp|Xn{;Tg=56@4 zDF+`dZ;t6}mL$HtgCN3^clstNv(tpO@ENi2G-uQc!*JGA>qY1s!=X^Smap+8EtHPM zk@Z>qtQ3fPBL@dEaV{D8d8{2>RfQ2&D}Iw%R9G>8GC&@y7}k}T86ODA5>@GQ-W^|U z)MBC@R0aj!neiQDFycKA;^_pm|3u4`$wKMs`XwNzu{&$>!ByqV4s$>Db4WkzNGtRS zA|%w9U~;B2LW^EX>!3&XF+3;fQZ5}IsdEK#a8|u&KbPi1`$|M-BUKrk;U&Nd&;Sdt z01a#a0w~@@C~((K0Rrp*Cjh_$%POtB!Q`1xHxm??UaOZd7d7mPa!HGn zG+T2MRdZa!6E=s$F;OWnfHwwncq6I@2@Cud_14ZkdDR;#`HczjXXS{_9-@FPu)UG1Z2-(TgO&8(Uxd) zr%8PFZ2v6ep5GmtnfA3q|2aG$M<-@$gN1u(He@Jb4(@a)8!BJ71Q6=_vabMtK%A$8SM1!?V-D8^YyJ4>XoAcI37 z0xzQ3MISDAbL&&dxKyoEK?g6v&MdD|TsK*ylEZj86UX$DZ-||i1&isEGol7@IctwI zArhC#elwQS9-mI9|2;ROS%_(xgIt)iEk>Z-l;e1Ia`(mYxR2{+IlZ?@s9oJy8GWt6yUz$hkRi zSoe#eSQEe5We?y9k5USQI5T~CtbdY-k9gGNwPmPyqh|D1b?ZBx!#JB(zb59FgR=ho z`F2^Pj=v+5AvJ(`P`YA7IvFTM47;c$<`^%d2!Dl`YWBhHhG$CcO~+_G{OqGGdq+d* znQ{BMUMH0&@4Mr8OLxZX(p@F^!bn>Ax>p*Ti#6=UERzm8aL6rR$Bsct_&=Dt-_7)p zH+-`L$Fs*o|ExE-GQ9pEdaE`M7u(b zhgDO+Vt6tmWoPT})6OhKj&F|R*LR_PvQDmLkiFTfRpFDUW3xS68h4?C=HQ?GOmQRS zFFryaWWkdCXF*^+v|#h9d)tp@p+lE+O>OA;`{|DuiE8mDqpzO!N8(3U=39i?H$3TM z>_5Q0|J>iSB#<;n(0=99*Om!7M!p=Yx9sJ&7V%R=@598XCV=mItsPE!VyL90A3!S~ zzyt`vjqZ7ETRnk)kUxAw^Vh;Hw1WbQxrj}d>r42?U&3zf^kpZ%s{Tg;`*|TZawtX9S z?uE08_4fT+cW~jui5EA1ocPPt%b7QK{v3LA>8&A3lztuizkD|kQO^Dye0cHW$(P^W zy}Wtu-qW{t{~mt)jMS0Ww|^ghe*Fn~|MtHhzyJjtkidnMlMlfJ6ppo0-cc)Z%QGE) z6jFl1lrhpuEp;?aLFaK(&Q3j*6NX$6U6fRi_$(FGR8?J-)mB}7HM>SHot4%WC;hM1 zTy-rlQ$O?hVueqIm9vC2=rI)5Qcq2m*=C)67TRc~Em788t-ZFmTY&B07v6Z~op;`9y}cJ-hqRqB-+ujV2wXMwIV0FkTc~4{S2{VQ z2~P=tp%;2dZCB!oExs7zj5XHK-hVyLci-MV9(m+|v&83ya^+NlM2hy=|AhdRPY`2c zKPj#m=bUxkndhE4>X_u9cMW+=p^f&|WGvk&cmx!15saTyI$c2qWPOhC=Bu^dn(MB; zRu$-@#g3HdvCY;s=_}oNQ_cv^$!O_Lf8geySY|MHSQ#wxry5YaaN>j)j;OMQe{^z2;} zUHk64H2ukenU*2>&wv_N<>GVq$Cw*@cX)&-#IXo*+iyp=BGj38|9)rat^Xf@0Tkf$ zu;)Dk0*HGDRA7t1*Ccz;!y6X}76De!0yETtZXAgP4o*OW4*ITxA=DfD+*iC4RE;S0 z>r@CmI0P1W>Id_i$nxaGLL1V6e>(Hu0D0I$AO0|71zg||kCQ+m9&tYnY*Ib;kqY~* zkO*9OL@vs=5qIG3aEX&s3+@CCX~5zOCXmw#(50>!Ho{tUF_zPT)3+?1K&kYXK&dSHcy5qlfnKDAr1}8Lfj3-D#SL{KKm^t$z=8&K> z)nX3&RZ@i`FeOFe0W+1!z;ORqUhnX>12aC)js?l*J4sqnlb+Nh@x13f>$y^wCS;^f zLd-<`5f4ykv1yq2iaXNx%zxA)7U>fMd;Ws5PH6xhHqqw$JOu+>c!!2~BY;PJrcRVz z6{}g*YDHA~(qFdJt6_Z*9$6)mO{t6kX+Y;hnmGcW|N0{p0L@|k5=Q_vjHtRZV$h53Ef$Sj z!B8_|)V3urqLM3t9I6;qbFF}?l@shh9(!2Z-WIp9oNZ%y%UIstv$iF=Wcp%@5psaw zs2QaQPbs-Khsx=%4K2YKA&SNodXNU6>Oc#g+RB2-F)SYi=^b-hUh|%pdWrq*5q-N} zc?LH`;<}rh-iVQ?6>O^FWh)keLOlAi@*?{vgv^{5(Yw-g9(1tXHKFQCSYpnq=#}t< zDSR>Yx_5!?#qciS8zOwnAd|NsDhUgA0&Gsj|Fa0S$R&{*GaZc6Wu{1}5(a?^U7R8m!17cIL}?M` zs<bvp6%uz+`@`I)rdc`L5FGz3k8hmrbew> z$|@EVttg!U_U+1T{dS8^W_9 zf8El_zCob}GY}l%=8ado-uqVt8?6~#i??X^56KNL_{?cub5kLC;e=Fp&PgZp4dn$X zrU80MgdP&B%~aZhwfWMS-t_C?oaac~dDK7WbEj`e$XD0;)}4NEs*h~yUmu&*xz3=h zmmTeCzqZ%K{;#mN-DqT2yL`?*ce~%6$ZUr@$i&32z0;c7c)wEJ1z&i>+g9&?_tx7L z|1r5AemsPS{NyQL(!@6&Ta3rN|Gyqz`B=p~@SYd_=q(TR&5us=r^i?4Ne>;#w;uMf z2jJyZpR3f@zFVx9{c>Kvd*A>5ap`roG&^0}YV?3W+?>E9Ui#eb&ox8G9aSAR&BKY#n*Us>LVzsKIc z|I%3>|GuOC0+0X;FiY6a|3atlL?!`+M*a*CBL)xxCy)ZOP5&AYU-}ON%j5woa3Uno z14B>*69fS_&_*=S1ihpKJrD#(&;?(RJW4PHUjzkb5Jy(90$UIUcaR68Lk4Y-MQRWT zYXk==PzQSu36l^tesBm0|3nCz&_#-H0*_D$tI!I~4+{Bi0kiO4q!0qB@Cw6F41eYV zxsdo4uxQK>TfEQ!!Eg-U5Dx!=3Dqz^o{$a&gbfSO4dajxt#A(S&_3)C5R(W1`_Loy z&=3=G2mf#oiwF%HvHBFTBoI*&E0G1u5E9Kq5Hry}@{j;2(Go+k4Ka}uzho0j@i;s& z06|d{Tk-xF5fydg6k{SWKW|10mLlws(s2U9g0Br5fFB-$K3a9ZJW5XKD(KfO%Jie*XMj)-4 z@w}c<9OqH?$Ppb~|Kl9*aW>QuJihExJgwE_ksb$f^z2a|8zLVM5;piTJECS-2w;`q zvAhJ5AS-h63{oK#A|W&KAs7-nekGcm;N6TxB5{i%EfOUK4?SfzgKL1df0V0-+a(YH#}HZz_&(l&d1*#+fuuc`i)@-o|cfs*P zMj7X)cBB%_G^Q%AQZTnJE4xw>T+%QP;wzzJ(ZUHASgccaAR}~ADo=p5_NINFtz6{C z%h<-Pkn+RI|D^+-(jL&qFDcDp0&_4|lj#bxD-km>0}fS|4Z1Xd9_qmy=yIF>Z7R~z z&9LhQkWsT@z#A(qGffDE=JKMH%O2dJ1SSZUHi(5l2)j-QXH=6lvvcNLQ!8OJHfhTi z^F+W@X0#@vED4|lBCR4QQ%+v)A0|YopbDqBC>Oj4j6|!9lyfN`CuNN1DKTQwstO#n zlR%S?J73Z}zf%$x(>c_Fj zBP=N?D~1$rPJlCcG^ln=C@FNUOP+$-~K@)CO6AZzAoTk5U3U7X(7lHz=t5Fi`?@c#*@Cf3o=~{#!^`m^qt>S!GtT%c0h`DC34ehaUm=q)UC>ANO96-gbliY)F#A? z%sR!)&`izPOlAg(BJ=@Cf5#KbAh?{WazF2J69Npd#Htp@rCa(hFkB4ga25G zXODLWcsPm}9gp}+ad(NU*sz8;7@@cvrMMue*owb6tFV|BwfGvjSoD$@jMF&yn%Ieh zgN&)sj6DyH)tHXAMvPgK>{3Z;t;Mk$JX_1!RzEv5+sa zj}uvv^C*x@v5{l(ksRz z8J_dGV&r)c>G=-r*b^<}4vS~q6;>VR6Pn_4_x+6-eF3Kd!@{jwYNL?=hq<<^KEpj(R#0isZDR^1pd0K;d-zy8%5|E3hf#Q@&B4w%m7zI8&@p> z5~TM^hO`9KK(tre5+(sDVI{CJTeeq1vzw5!ZP2rurn`nhPuALTJ7QG0d0uCmxSgc7 zhw!#%(6b4^0^l}PP#Y0S5^OBHxT{-1jvEM*I|V&^1)L^R52vqgr@+Ena%T3dS7_ua zLBF&jEz|S6Gh$pm1qj589X$ooG{SuUD{A$QA{;WALVU%frq9)rB2IiPIqkF!{Rjh$jOf@TRo1LQ%6|WPd43Gv56ao) zvL0T21kzd~_Q4dKfCv@=+8-mb@kY)nA{MgiQ@q)`>nW|o#!1MzeEkc51;^u9smTuxoM)kqx&pk!85nuh4O1)R7uc19^~aSP8uG|)!pkWAJS94((eez4*@~1znF~8--e*bQKw@076hXuA~zWasc`zb>8ry{=Hk#I9&8|H{dbBZ3%!43IQNkj2O`Z(Z7QSy$u|3!cM(<`w9^lK>!6Vg#Y}d z63EaYLVQg+P)usjvAc3TpFk7yiNwcQSn>cgo+{v@2&!0ep3LQ$csL`WH zlPX=xw5ijlP@_tnN|k9#m{_xF-O9DA*Z;3z!-^eCwyfE+Xw#})3wBnqw{YXKolCc_ z-Me`6>eVZ=s^63DPD~_V0hc|S_-?Ei7=hm5lm0L!UOb}lW0R2)-V;nw13k>CCNdPW zvfq>g08+~+xiVjqg(VPOrdco6jfG;oU087zyJSt zao65aflai6MfD)2*a$29AWlt_G3a1Tn+@ifN&3(s8VZ=ql+PR+TmZ&{E7=1QY#exvs_U-2_FCSTZ3Zjsuw$BeW--JjtL(D$z3J+G`_XRPtY9Cz&T#~||r zEVCq+Y;sw~o_X@hEVr!H#m~w~m|+SciZH1uOoQZt1l&Ao&If^uaL+gYz>QIlw&-)h zX*^~dZuKbSV+)w@Q^*PvfhzStO`Bw}fiU!PP^!4CO6hP3%ixs7vxe;U+i=G%_uO>X zt<=aa=dJg!DeJfQ-+;3Tv#)YWOYKY%ChQ~7|0J&XK#T|a_y`th%hS4(lez>#x=|)Z zJ&7Tl0ymw0O7L-%QGJrA?JlAxkq@WaxOJ1O-4xq)=dSziy!Y<=?^xm;`0&Kr*SB27 zC$Ic`gZC;koi%5ksQ=E5FF5)1LFcQu4!v03Q_`6)ggR6rDVPhNk2ZIZ6}3nV{$O3D{t*%T6-S2pN=ZL3MSvJ| z2zDKzR+9X;wg5g!fk;fE5|_xtCgzHP6^x=3UlPH$O!10Xe8~WxWe+_WrHeWNBSO5_ z9y0#Jj3)77i4J$h@ZipgaEzlI=SasoE(MBN%wzGYh%7z&(ScjEqafXAL@i!$kcdpA zA{WU>-{J9(kpFZUA0tW0;RUjhn7m^lC2`42dh(N?45cW&w8=`El4X-Tr7Bt0$x*s8 zCvSYEEN4l}TH4Ylk6fiL*_6s%`Z8IqyrnQ>Da>LT^O(rQWG;WnOaS$=nb1sAFq8R8 zVp8*(*vzIjf49tNdUHO{{H8ejGtF&!(wgQ>r#jckPF;0#oba?uIO9oA_>{Aqi9{zp z_sP$G`jb5GtfxTFGS7h;bT0S&=N$E^(1tqnp%4X1Ko3e$uN1VR7$r+WBf3O}a`dAh z4e3KCn$eO<;-V%^=~gx>QUrRmr7(@DOsPpyl~NR?Hq9wZXUfe@?v$rM4XRM(Sks&i z6sJZ_>HklMYPXj%^{G&eYDY_%)SM!~-t$OvVV5M78u?o+tl9i%b4Xekx zs@Ar;^{u-a>sh~P*0~Net#HK{Tl31-zWOyvand1!;`OiY^ywiH%h<*`c07SC z>@Nu`*>N8Bv9#JNW;e^(&ITp2mDMF>L+j1UdNxa%J*{e2%UXc_bMs5d7bHLzXsoZ4 zSpSg#7ih)502Z)<7yMBI8<@ZG+%JUxc!UHzBESq@Pa_g=1g%u~!Wj;+i1)eS4o`TT z5kV-?etyjJvaGy@S`bm(|W)=dB;v_j+r z82QLhj`Ay$yksFqGsRY(qJK&8Vk!IO69wkVmb>ibGMhPxV196xn~CK$SCGXoAoH1@ zVviHdm@9CW^PKn0XWiBL&TeLAn*%*T^qxY`eMX8U5`Y1(7#h)ujRJMicLpz)jlPk;Kzr~>;GQ+ zno76MHLOLO>0z%j5G^6aubuLU>jnZW$WDN=mrdQR5c($=s`RZ*GPYo?OhP9F6 zikNG zB)hF}z}-3lf8aH{AO7#LJUrqC&$z~+Lh**1lHnfTn;N3)f@yDjCZDh~2IOs)kr&wH zCy%+zeUfrUvpnRG1Ub(076|kv-~^9&^34BHjz(ahB`&BkT6*3RpbLHIP>(uBihlG0 zD}Cq9tvA*o$%W{)L<*;n1~{JXZghM@8kT@UOA^q5imRpTYX`g7$u9M}m;e3jXOn5R4jxNw)i4?gpt z554F|Px{iE{`9C%z3Nxb`qsPt^{|h<>}OB=+S~s2qu>1B`wryYQ?d?7c!AGxPyFH= z|M<7ZfD5#MhfC}Q_`*lN^ruh#>RbQ%*w4Q9x6l3Vd;j~BS3dKd@B5tlz5M7;e_1A> z{`R~7{q|-*{IRI>`P={g_|L!o_s@U)*T4S&7=QvefCN~821r)_cYq4GfDG7x4)}l& z7&r+SffQJQ7I=Xen1LD?78AIE9{7PE7=j`=f?L;tBzS@-n1U*}g8wXtRVLViFc^a} zID<4;gHrT@HkgAtxPv^{gFeU~IGBTwfCpOOU*LCyNSK65xP(mDgiiQ`P#A?$IE7SL zh1>T6NPq`d_k(m1gfj>UTwsJ&IEG|chGuw%Xqbj-xQ1-lhHm(Vk>>)O$Aw*Zesri7 zF4qzra0iy43*aDeb{B|(7<1p?3z~2TqSg`^;C6Rt7GBtbfnbCf&!+#ZvP<0jM$is8}|q1MvY%# zj3S5!(KTzlsEy`$j#74O6R?Heh!x-%f=6cr<%o{-SdTE40|^iV?Z_4H_<<~j0d!}N z0y&Uksv8$qDG7R zxRDtsYN{}gA-R$)xmnF-Vi|c-)3}e(#ttoclQ=nF<8WOuNkuc+jw~hxIXRR>iCp;D zd@*T~7buLMppr%Tlu*f37D)y@sgxEdYQ^A`QMr{|*;1;I076ieKk1Dvp$%PmmS_oA z%n)WtIhNGe5&@Z(aygemwUd^XkycrO!$p^T*_YY0T>mYYmlU{{ep#4?c}sxFf`S== zgn5{b`Iw=Um@BxL5ZIWId6}4*PgE6+l=*;`nVFy&ns6kUD%hD0_?e=anyTqin@NnO z*?_3InzA{YyF;2O_?iqDo3y!`y!ke^iGsMffV$b6#95pf^P49aoC-Lc#@U?Cc`L|C zg35V-%=w(wd7Z)2nzcBc23Vcg`JLcdT-qs$+*yF$8J_5wp5hUmBUqjUc%JGRpYmBT zs(~x2e=Yi=Hu{}0 znt?N#e>HleKI)t~ih(VSKyetqhq_pkw}k*JD_01eOqNB{}kz(%r!4?Iu+ih8MuiU1eD1t;{U?G&gD zIH>7Ys3&@;n0l%JkN_iMOZmV9sCucES^x-;Kc1>ipvr)vihiVOqNe()iCO@_N&!bh zOO)!Xm|6e_K&!R7O}Dy$xmtd^`k}pQtpBM2tjhXItxBz!8US{X8O!>Y^?8TS>U+`Z zq0@>0I-m&ZstAYh1si}Gi5dVfBuggZs?`bujj*ojdI%tL0G65>5pap$icQU`faAJ* z<$9sLS^xn+F#q61`;ZC_pr`{tJ=kim0I&emfe>D#4{z|V1yHdA3$9|>dp&7LBkL5? z+OR0W56A$o0Du4+J4*FhtqCx*Cb12_DgYOevNRR0ba=3Tm#`MPvJQ(OZ&0lT;3_EL z57{6HO;7;`&;Xk%3G;Ij`v41bkO2-*02LsIxv(eZ0J9N*8Qw6li7Ko?vjP9A03@;! z(`u|Nget-y2tB|72e1GfKm=wGssAa#4|RLDdAqlLE2*u4u`-(y^$62vvgCELC~Lb)VYDi-x~bu~CXo$qfB^mqtp5rC7LW#p8!EBzt^km{z={AIG8S`rw0uXj73#Ywv9c+GD%;StzFGhp&Qcc$9lu7GsZP+#$)8birTsup|hYX8}{H2qf5rHdH@H|xqspgJDeK+dlFTQs>nOV zCVV$Q%Y`bubu8?lF6<~6TL5D482+#g0&J`{{3`sw34JWcJo^|yytG47#L;WNno+?@ z47Z4ysRw`n#>>j9i~uau4@tYI6@a#hdH{1P%a@7(wS1|#e80t-zg)Zy)sP9v+q#!A z$(5YOucFL$T*lbZ!2g(de#?)*Qx=hQqoEpDe z$Vh?02AIfLx5y3J$R}YMFbf2a;SLoH009sMweStm;0indv#<=r>1+XJkPG1u4W^LF z(F?{0@yTWD529QEs{tscoW&?Ht*5LK=3vVfPzjc35A#3=v04BMK*Im<(E}{fmRQm! zozi5KtxAijn=G&1`Vab?y#4&o0X@)}TE06Sul@|s0!`3!E6uR_0h#f+acqfnT)}^A z5B#tSC%puc8qB|X00CPkES(x5J<>28y(q2H>|7M?T!8SrbMnlf^o+EM>cKSR2o!q@ zk70@Xpu>qe0RLh`Lx7OH3ZOHLVh>*(vVASl6m820ume|%!~oFIFPzF{O%re&vyprl zU9`c`+sXe>*)n^Hnf+8HUDtPQ4|(0ceZAUyZPy2Z*Lv;8eXZ0F zOg&7D%~AcYe;m=ti_a$kyaiy(Zk)4Q4BGXe*#*GaXH67oO@M2Sb8TIqZ;cTi8`p=S z&HUUU8a&GYZ~&3qI2DY{VH^qZ3f>Ye%8NZH7!AJPBH56Q6376ujExcg5DPfa-xhHY z_g$^|O(^{B-#zOg7)z}NKnZo?-QbK8+pW&!?cm@I*AkA|Y~04+UD=8nx^t|}A#1Vw zK)mZ)&i@FZ*#IyAv9P`e00hO2-_2a$IPl-mE!~IwgVh~!*G-_=jS%*nsQ7FT9NyI@ zA>>M{0hZ_uFiQbf%MasF4p7b-L7b{Pi~vATz>Zzt7+uq-isT6avj<=SYTyayU@s`4 zu|IA&$!Oy~Gaft6u&OtqQW0JOO+gwzIM8O8c+Ap3roT;J=Em`sxRBAnMc0 zF#khh>Od~O4(+z3e(Kb&>JQTAE&%CB?$idr0|@ZVa$M*&Y&3O}$^Y8ARsFBnj1a<3 z*2Mnn$ByX|rRhD$=?&-U{0Zv+0K=g&&edAJCNa9zssKlm;lyndv3{vc8`-sv%G#Ri zE4|M(ZK(#p2Crfc7H{YnukpZ)u^NjJBdrgBkmyRR?gOt91|Pi$ukz7L@RC8_N7LtA zAnF4k4!tS?Z?L|;?cJ}6(!Ib&TFvD4pwEe_0csS{9WTHiPr3HK6Vp9_`mS*NzMuXM zya3?1*FNxuYY!YP4)u`X9*jl}zttDL(HTA86W`kLPzam6)m%*?miYE@U#)md$p17! z(*>ZvMQ#q`9=tu<^)dhTVNdu4fYm4g_SL@aY+L|faPka`32Z6~i4?pBf|HjGN)o2c|R~rx7 z5d7Mp(y=}OrhvAx3IsV_$`POKNvzSPuiyR{zm8 z&7MV@R_$80ZQZ`@I;+@Rx^>~+#hX{}UcP<(`o(Hh@Lc#M93fwVB)ybqe+ziIu{gxt6u1Y{00^bfXJRba|9nwgNMu}fCggxJ#JV~ zfjFU%3l>mtE~v)^Bvae_&AB1Q2=$md#|1rQXX>ki=HqcZ!RDUE3x1aF88pw)$4j3E z@R_y5_7_XrLnax(5_csFc;JDc0d9#zve;%@C^!Hhl4!Pl00HT_g#Y>jNk0pbBkrH; z4tOrQgt#l9y7?R*!m&mjcjU20ANLB3MInbI zvPdJ3L=rLcCgW+JSavIb!G!iHP_hAf*=Zk6FhdQODc`US017hXjE4v@NvO8tBH)Oh zRVs`PIFN=bF0za01d7VzG#e2-$s#yM&yd9EGrWQT4ay#T3&6P^AM^dT%$ z(vnL6Qk$|$OS9ZkGEV=&Pd^~~nWCWGB6!fYgH&S3p(rCt$s^m)`-dM+Dzs3)0^+2! z$^!V@$}w%QtR#E~v*x8=55Z~xZ{@>y}mCAVC2pIs7x z9~5C%5kKbGU^jz&YtS7#3pgMEGi(_r8dsXo?*JfDs*NCrEJ%bJbgUb*EFdos3w@gB94 z$%^egF5i9o{Wsu&f4)~}e*FblGJzX}xu7K~b+6I`p^Nn*DHDq4Nm;KrhBkxzr{Omy{W}E+hX4@W$4!$BS!BMUWv zhc$cn(M?wW9Jeq6GIQmmaeTuxfU-1g%g8%>@|l8ku>aE|TR)0FyqDKrAyU-Li)=!m zf-uiRvv$iJ%6<3vHU_Hp%*X@IK!hr$+$MZ6!rXN-C$Ic==w$~$bEx%Oq8{D!i?mhP zmQPSt>@Si`1Mj{s2#7)>yi{!K8`a%HTouPZfBp9_^6tU^2Velv(zk30(0~U-pjQgV zKL$3?fe)<8l3J%93UGrblY5fzE;Oc{_(LC#m|#H?kOuGkLt@#RPu4J^0B(c^KCKIp zbV6vQX>i0F76~B&mf)cq&QOOQ0!q$y))R&tFC`eP$pj0)!6Wh`gGyv##i9m)fk_Y| zR+A0Z6cobL=%hZ8nv_IzwI@O)q=z}&Aq3U9M*lXp5h(skU>xO`Hv;Bpj(5bPw-)F| zKK9X%iId<2699(I9nl};0Mq#lkOq461cN>6l?5s>8;M9PM66kjIqXytM44ubWQ!r} zW_TM)l4A;*>XiT%0mOfp5|tKGB`bYmyn;CDf~Yee1*Q>3=pa&F`dMTnFL=mAjxCrw zA(?&bfhzrIAW#?^AFMt}wgFL+Lc%E|snq0wyuglk;cvQBNu)vk91R|49)SHAWYDwIrAJ;Epy zf81;+p@|M94XYTy3Z=0r0peqS64}L$%tMl0N?|iwS!8ndh?u0LEJr30(I&Kbti-He zRl8c&UL`Adg>7uVLf5&-*0#6RN<3S;Ti*88x4#8$aD_YE!n_r?$4w_~|At)V##Oh( zg>H1EJ6-Bl*Sgo8n{k`F-2^I^yZ_%k=X0?;UhD{MVyd#{YDt|NQ7lpIFkJrgEhy+SEVhG^j=VX;l|l)Tf4Z ztYtmx1E;#x5@z+SZ~SUn_uALL1~zeRt?L2jn%F1ib+DDaY-Tr`oWnl0e2pD#5hvT( z*T#0XwS72fQ@g#>_O^try=`)r+uY|SQn$m+U2v~^z~e@DyyZP_dRIl=?q+Vg@hx9? z*W2I!26(`Ca_@cPR^J70Z@&e;aE3QL+XP3rY!4oB?ke2j7sq(UVGVJL<8|U4XRgIH zK5~+meA6-pIj;Ry*OXUVuO=7QY-B!jn%CUsH^+I-b^ceK_uS_{2YS$jKJ=gSoajeK zdeW7?^r0J_=}(7x)c=w0bg5T8wJ--X%3EISmDhIb78W_y1#@%3mfh@UM|;}UzIL{k z{pLs^d)wtcce>Zz?svyK+TVVZxaZyPe+PWv1<&@q8>R1qM||QHKlj2HGQOFl;`OhDJ{`cSi{|CST6hQWy zKYDOGV-fB1K0NBa7j&+dW5E@{zw$%BcW4K8P=_A$!5;*|AQZwOB*G$Ohjw@e z`J=xTj6QqFKMl;m9W25rq{1q+!YjnWEUdyKOhR~&hb6SY8-zl5&_N#5!ZSp}G*rVi zyh1KiLIYGm&Jx4@D?>K4!#l)7Ep$UK1VcGgzzn2ADa^w=+`}(~Lnf@j?9)0KWVfzc zE=G(m@JmF#`$H&v2OdlZbkIaiEC+Px#B%t=Q1nDm1jSJ_#Zp8?QY1xB+(b=G2X$bF zB>X}VT>q>aJikj+hfHk6Pdr6c?8RS9MPT&BU?j$2G)7@W#$r50R&2#rj72`A#aXJv zTg1dxWW{4t#%#pKZA?aP)W&WE$8Y4tW`spqJjAQBMKY|$UA#tbbjNUfM{$ftZ?r~q za7J^C#)NW0@}tIFv_@W(M|ccJX57SkgvL0W#1wHsNbD|0WXMRQ!Gt7{8&pSK1jTX~ zhm6$7jpWFV^vI6{Nsz?IQnbfsJja`%$V;?HPz=eIbjg>5$(WSMnRLmK?8K5x!jo*m z{HsV#WJ#I?%Agd=p(IL}v`JSq$$b2*eWZt;97T*Q%BYmesg%j1#7TJ2$bVrOoyaINQo?wg?vZ@iovrCuZSc|#;8PiXa|3U%5eY(aQKFA&<4EJhP~v=zVyq# z1kAt$OuW3yZ>Y;~7>81P#dg3-5sW^bjLS@%%euVFycEpK#LUdp%+2J?&b&;*yvxH( z%uZa)##F(_BtN*6OO2#V!t~77gw5EL&Dq3E&@@bNKupC{2gW={)NIPg^hDOQOV^~$ z;xx|V{LH)zP23z!d)!Ua#H_aj&dD53%S6u3v`x{}P2P0OwsfmSRLk2+%kaD-N%T%> zbi&_Mhf$K8P6z>+SWl?@2Kc1UXJ7_qIEFDL(=s*FGey%hRnsyJ(`R@F|IE-% zjKx`etPYh2Ee+0b=+Xw21~3)VH3if_71Ti`)Iv4XGi}p1wFYd6Q*@Y90-X;##ZxZz z(moB-L&elg)znSp)HO|1IPFnKeFr*?)bza5EzQV1{nAVA)K+!XR|V8hUH{ZZebm#u zz$`^oJ*`wfg;homPmY z*pH$2*nGY5fF{rP*u!1Z@~ibr{w9J0ih?Sx=PN zniblirP!Oz*_|z+it*WZh*@ozS)zs7sD)ai1x1~e2cB(^rES`$mH*nV_1bQw+H$a3 ztX0~2_}Ov@+OHkhupQf^Em^`i*_HK{WR=_hX<1@@*5LexSGd+HP=h)E+`tvw!6n?n zHQd8RT)|ZXD!A5H_=dzp2PO^Dbk$qFr2)T9+|1S7&E?$A_1w=r+{JC&$L&PPB^4ND zhsy2SzXjdab=}v6-PqM!(WL>$g)s@}e_1)k7T-vqW(p}iorCi;$T+9Vt z;1yodjojjWTe|_zx_u|QrQX1~+bb2)^`uK|u+}PA-tYz7DhOF@C|7kT-t9$)?)_fz zb>H`0Uh=&I^UYWE%~*Zj*$zCT_K$z8CYq(a{rQqPbR%;;Lu?4IVX4(=y z;S{Ff1XhC;ZsDDMVJ9SEJvCt(K;aq|;vo*)8>RskPD~dL4H)*;6nKW1b{#^lX~ zWJ%uPJ$~aw&Sb*fJ0 zp66ih=YmGue;(i^PR$6GWqvkjM@Hy?UTAr4Xo3#qi1y}l7BW3i)Kw^N#=ZU7vl0NB&4&-Z9>BnX15+Z4nwrH8=X_{W?gr?>QhUuN=X({$; zn+ED{h6kb6>1|HwpGIblMrV!&X|!DBs?H;kmjB3ncH*WU=ch($iEc{n?dq5=YNH10 zd&X&(E^DGb>wZ3JwN~h{Uf;HU>zPjLo1W{XuIr(8>YA2osorR;R^^W-?5t*1!Dfnl z)&^@h2D64}8aM`Pz*&0~YrY>89=K#_a3H?jhE0(XQ?8PHv~(?d`rk-zEy+CT_kM?)Ih;hl(F?pBBT&h77hIB^&k zaEz4k{-*Kpb#WBWaTVur>6YvpPwERNW2)}(lr`)nH=qx%!4Ti^2`6$JfAOT2@(~~M z9tYkZ$8r7EaV@8EF8Ayrzw#Itb23k0FURtQ4)YnuWHyg#Bv*OW}!k=$B5AX*mz_DRr8hhrR6sHFsS}KXgiO zT{b`#f5-;HjRRWYhe0QEPgn3a-~V#h4RlrSbTc>f^rmyy()0hx^IX>pJ`X=XfAzv$ z1ci`w_+|B=cJ)MG-c#o+f2f8{FX&@e>H!CJ(6#iz@`-p*1WpHCX$N*?7hE|&mU`HS zMi|^UXrWwz^i`+zFK=~3@84k;bU|+SBfoW|uybBdi(S`uB}?pkKP)$g_t%YeXgBtH zNAo}D-$f@ZVaRTTpY$|u-D@9;dEoZX^>%@;_Rke{iKvHcF!(w+_0}kM8qfH#PWJvS z_-BTAa|ZbJR`P!5o2!<25dQa>AGly6;ePl;3)+>y@} zSb*XvW`uS3ajTzpv~S(H-`t+3_d<7foIi?uuX(cI_rYfiU&p?0hjr+Hg`^+clZl7E zH}ZrJ_RWR-%w_nuAKXQdhc@wff3|zYpLnfz_`y|sVki5u4}G0i_{8makDmuT2wZe; z6S|+{N?3=_mtC``_MHb^+}HiVUHMt}dwU0bp%8q-4~xQA{(Bn#FDbTf`%9^Z#?O47SO=#q|2$~~Jg}gDn0mnlgZQ8SZeM+r z$NJBuctHnq_1QHxbsUE_3e;N*Ca}MFYMhzeS;|FVCoN4wDl9X32 zS|^GPCFM#-58la?6y;n*=ua5II0s42Q|a?(9U3%_Nz*p2oH}^)>W%zouii^_<;H1~ zc1$SHtOIG1w7GB~7;XqXg524)Yes`jdxE4yGF~6IXXj?i`j8(lt$Ke7C2AC@Ql zMx9#qDviBB@8;FIDB(xNe1{f2nsjN?xtcd~?(F$9=+L4^lP+!gH0so6vcrH zME~Gq5NGYxRaR&FbP@+gWD&GSQxggp6lH&1CYV$GnRi%vA1=t0KhUUzU`LTP6w*lk zXxI=}PO&vmC1XWKqh|KJgA+x1^a4?42~|S~jx{-z4MS{*#Zw#~4uqeGfi*?mi2zzz zhecy?15rF0)e*;(9;tDrS(;^32UqPywud|;Sy%@q4Q^(Shdw=K4?TT;NfDNoX~|z< z=OH%epMh${o_m89svn8sS$Zj^nQFQzr=-1R9jKv-Ix4B9N|zjSshYYftF5~Fs&v?O zIxDTU+W&ehu4i%i-=d5{2Gk<-j0D%9Ao^wKekCS~Vt~aG6zs6?0R`lZW!1P4jC;OW z2ZWsM(?=h2bhy!2p?o>%h+CS-Yl;G{_)k4wH5rka4W)4wloW;O)H^a#axF+AaaOHG z^l(P(R!;tdu((~(cW#KtlDMm)?b?^)K9khRCrD{_B2c!P@e@iMeLNOXAKm&hAx9Ak zs$h@sRwJ#m=pL%9e-$^YV$Ai-4D7FxMoejvxf*>m(n%}b*{85N{WR23n~G|x%SnAT z)>&&UoUBWG{WaKOUrI5v#X>6Yj4}H&GtC0poGjU1I(w$tZ0iN1LKN*GY)2$_yDc7) zO#c}vjN3NEP`3z&gfhg(5{+oiWm~zTJ@!N+3o4nTl1oiDsf5QZdj9jRv^mntqmT6g zxsM{;26D?_2pc5WKCe6yNF^JuOpxiL%fz0;Ra*J>#Ovz(<-Qrkd?%VCsmUfr_4|Mp`k_8X<^dR!<6m>CxyAEhX}#mhu~K}cJ1t9HTf1zo-&U(G%rRJ z8eIi}5~p{_10wv8N%kVbB=r!e9#5Q`7&A!5x%Kgn6nUVGZs<4+DzK4`d?cruM!-o@ zvXa2@U)3zB$xU*yHU@+wC_^bq*66T|0%~7Fz;L9F@B)Nx!y(*^C%HkX(vGdo^!#pl* zkLtl9M(`-KMapwo^eh%aeaAjIEt8qBtkftos?m+!uah4Ar~omkDv*-2q+0tVM^ma& zQ99FC5F7{=nNlqaGBlPBZQzGuYLA)TO<CH znmJFLst1~Lc?!Y^lDIxFb!5T=Q%&M=BtOQ*jvv9pQ{niYG$3gnYDg>VRKivrB@7|# z5EfkIfRK0a4V(6n>P>g37>t4IsZ9;UnA~{OqzWoz^8n%E7A8H(U~wrPF%UenWYfq! z6r$X)EG#fv2Si5oqVZcPYEyeaNt(2^u3eQ#oAcV)(sooRRV{9F`~S6;ehHO4VoE#| z3P{tA@pyx(1aO7BmymVEAL~HLjM{V-e>@h7E^CPO>|r6Uyi}3#+^hyo$wLMSv>|~L zOFjA}t$QH^O6;vipK>%0Ij|@jYHMQU)HknstPxF&o5@A^Ti1n6qaGGI**9wPPVZ{A zc!3qKVv<+E_sSwouvimwefTnHK}NJQ(w-G7`V*ZXHLDDkn7SSuzOs~9TE0E;<8&+I z87GakwY@QpixXR`<+#T_=2`-1EaV~Aink678jtLx+|t(6!JMV4eSoLMstSy!FOseg z*MY|jlLWpEVM90IWnYwuI4gjCvS61>-XjtOc(teK7LsAiNFvj^*5R@7k8`bS+3Z+3yZ$w>V{=35wRUe6-c+4g~vl_U57EA`8|>Mh2oezOji3o`67GGV3hLGc?uF{5%}Dr6=uL(NlAgs~+d2JAPXUZp z{7tB>!qn2~MIV22ct z<3$~#gkq^F$ns^KDq=(&tx0mN6t-P5~gIZM-b_y%Kc=rHD*@Kqhi$K zT3)6Ch2>dpW^|M#XMQHAq$OsKrqWQ%H&}y1D#ljAB{j%pWe$Zk7zH|{0~1cgX{P3v z=s{~HregLcp}?kW(k3?EX6gB+aUQ4B#pXE7W^IlGao!+uM(0K_ACoC3a}FnJ7N=HF z0(HXLK}wu;3TIN0CV7U9X8(dFdJ2bUrYCzkhiH~3d={CBpaWH8Cv@TReZ zClk`AHrS_N#=(9{r-5okU-&0@0jPi;sDnP}UL-PUwPGsCH&W zhAIYSMksJDr+A)Le5PowoM(HsXl|^hi^k}0yr+uR=-AAshu)`SNTgs&sEJZ&fLiE< z4(UQEsI)PtkP@kqDyENK=aJ^4(nEYI5K)7%7U{sF!XEi^`~&N&<|I zshQdajee<`ZU>jp=V>y-mBvth5~ffvgEf4^a{eEVzG<9Fsh|2po!)7lQYfG5=${^H zY1t{BqJy4Bg_~Lfoc|gsq9SUbE^4Ee$D>B7agL}(De9mm%bJF2riAI4wrH7_DypWb zsIKa1wCOm21ElupkXGuaJ}Inf>ZIl>g3^GeGAf1Ms;ug&u!>%#~AKvEB@;R;zcADypXEsb;I0s;aeqt7o_>IAFsw1S^CJ#WP?7IMnLdAuG9> zYqXv#4W#S3I;*X|tFp$czM`wTvTOOcYq{pDzCI|w)~m4sEWA2s!TKw>HY{skE4O~; zwnnUsdaJ`;Eab2QI+Vk>J_8O2th~}|IiLeO5TC|!EV+K{zz%D{j%>+p*2#9P%C0QU zik`@ltjTVy%>ROH%_3*Z;w;SSY|8Si!p^I@x-7L~tkQ}G#8T{8POQ_msKqWVxK>U* z$U{5mY*i%efeJ-YfWyePLmmB))ncvIN(0yStZ#a)Hh?WUh%HlW$y1mu$8Igrs;!^0 zt=qya+0Jd&)-BrJE#A^84Sa3bj;-8Y?caif-A1e49&X%Ht>k`2(?+dWLapVd=hRLv ztCsCMq=Ri*gHT|fuBw4h2r5$0QRF(s+Z*h4_U+ZWu5*em4Ulf^ z4(#mK?(HV7Jm~Ie!tU=9Y4GA{>LRXC|643#g&U21NtLPE%Eyobu1m?)Gxrt{bEGbeS`D^`Fsg#LJOF48%7yJ$w^A3 z)IybZFq(TnQR53I?!dbaD7!SM+8;(tw@|MiAbDMB|M)J-wUTT2Ax%6O#Qo@^B(@&- zLQA=zX|1+TC73^MFEaQjx`_#qld_Gqvb~pN|JcgDBFT}Z{yEi4vG%6+e}`MWk{k#r zZl*SFPAQ%nZQMUvKcD)s6aPt?x3+SLNb%dW@jFNfh)D4sw{qT~;Og>Q?)MW&lM>21 z;`cf7denx{^5=?c6B;;Tt7zlp%^|Jv8%bCiHe(X@+_bsUjzYLi3)D0@F}m^GTwK;d{A6jWtnKxPaXOOMW>YKlHlmt5zBckLSH8i4RbPXUb@|`Yfa`$wuS%aO<`!aHF z8n@CK6(w3BrP85Pr=yIgPB%K8O*-96P%k z1~PvFvQC|C{&*1Sg1tEZc=`NsxRiD<*drb+hQ;}$SILjw{^=dnW<4N`ejMe*+9`L^ z6+x88LA!B?Zrpy?(YT&IeR+SosLk* zaOh5n3rVekBpjb5jEp!opwn$aG6K#r*3nV>-BxeqyTAPohkUjV4*hxlJU8OLtE|#c)`p&9q5=WhOF$@=F)0$}&c{C~ zJQL|^BJL>^UiOsf^j4ZER@w9tc*6?wj!Tr#72qddmaC za@&8^jA+zqDAwEc)_Y!*cU|PK{8o!PS9_|^Of1gdy1?WrsEk7z+cmC{K5c2D?egJn zYT>CmeeDKH9VSZcK8Fcey?5$Di8|dpB z3-8lV>U8bP4Cw3H3QaHW?&b|I6<6vUxqLyXJoGkv2=QX*hVpQ8_)C$?mn)(D!C@5< zVFOu8gCc*2T$M+C{tkO8zjVEfUsq~~QX1gwdz} zI7QsL(=zr~g*Lo(1k%_AX={j@MySkO2SzznW^X*1ZP!rx652I4G9FC!p7ruQ^yRFB z$_Lk%AAD3k2LD@-emPefG_NzB@aOSDxXP!Rm!FzdJ_o2QUcOiyQC^DZT^fK)cd2~c zdigc{-)FUdi~D*@7B83W{(bFwvNHCv|Hq5x{^wJF@~7mlnm1p3^Z9lY$vyuTvT*t0 zyN~KtaQ{|>>UP}IF5ai!AA>e|7dBn{x0_XeT+b5*RQJZNzPqT-(>Y;cJPS0mS{wTJ z{`Bt?RS%%Vt-1cFyerq@{$DQr2jXhS^28r>13wLvSLcF{j{A=xY9|rlcTJwANU3hD zEUptHBAWD6|EPVtnQ|S8d3n*ScG)#>IiU7;EaE4f(~i$TgN54e+kvZnHR2yN%rqT3 z-4PoFMG9C7w%Cuvo^q-GmCtZ~orvUC^y*G`(MjXP#?mXy5=O(Af8MgxLssc!iaU*F zznS5i$PuygDDG*m)Gm_8lQAe}yO~w!WC&RGX1iO|n3QR26>{PE8f;o0EcE7h+B7>1 z#WE=6dfjSwovF6!ll#%=?6Wp{Un%e5-M-+%?+Xoi^_Bw>ASk19zOU2BQ!{Ouo_s%- zu{7>d!(!TLCG>tp-9DSd3A0bB3ObOt{E2@d-4vDNh>$Gm^={>o5X9=X-y(BrL{ z8XJV_ZrGpwwQJRJ-_GO9KZiv=rKM_{KZzhJ(?L)c%(xeVG&IF-WZS`;NV$_uhbi8d zrw&p|PMVHTE9^~=Ah1+suaJ78Gq32(zD#3ax4dRvlduN1?i`Nt7kFhhGP4JoPYBh`3+wQ;PMW_J>)D%qD?UVJF)1l&*)}0P z@lIic<<${M7T#Yt>7tcF0Mu)zgsxq zP_ge;V!2~YSEGfR7QZD)zFQoL;r$iT9j5|6?@5roxwMgGW_;`ZYCY}JCiecu$z}l^ zb&iC&FhIbSg#KFED#gQZZVSIb1s^HA~~;*W^Nva%m9D8#=U zj3B#MaZnkdWS2s2dCHA(p_-(7)&9?JA5SUle>r}SMch4^(Gy=jnKLuF`+MP*&+_k& zvf=~WUxvqnUAG@m>$J`vI;%70g(~6seqL;ozFL& z)BH9X0jd@*awldD)VuUp*<>fu>qt5M$GZOPP(*j3oATybel!UBr@qvJlkj^_{Od>`q zGppoe;|3NrVXSxrYg;e-`OvwKZ<~tx4*jNx6UyM$yUdJ!W^G;$g7gjRj66Ft2XTDp z>&o$8p!c?@5}AxKm8QzHw!RU`ElW6^Zf542Yl|+%SJ^F7h={OIx=&&giqrPWGW<|G z`0f#fVbGO%i50zodG#saFc0B)-nyl7SYYzxS5|2g9;(7pW@ss85n0_Br+iUh8gnzd zj5^58W!ntljl&fR-b*<09|d`_os_Zv-qyjg%#M+7z`x$9*0-#a)|$4c6bsrhaJpR- z29Ju_@wy?t6gqdK|5)%971`1F5`QCU2N1?qt6$ioK_Ck<5CTE9KoWXM#;-C_vfLl? zC#tf)3}xSVuB(qA#7C^&Y_J>tBCNYjx-7e(#NCBNzMMGQ z|3q?&VODk4v=zYWpcS#O>c2<7YaRaSpkM2Mc*U{P=uTvxyuBhU)%76P-%o7f&OgN^ zo@LqQlx0tB4$JKsxKIlN|DG(u;Nt?Bd#k>znARZ6(o*Uvr`tl+?WwV)-`>{UGRLB3 zm_9q6j1RS48r}{$Z$CvSFFgOyQSVjpw&K%M>6|oDjO|$AGMCk9S0434KM|cfC%t>! z8hTA35wGsNG>>jxj1f<~&AQ-GUs)fkwf7{vWBJ^euWOA|B5m9bC~A`T-@V^5_DLlB z4~MPJ(aWEjyA8KtMS=rS&zmBC_BkOb&W0DG8u40>%Spt~hP-ol+HT+JA&1@{7P^@c zQ}SbM{?nNz``6~rFjhP2V`fc0vaR4CgL}09F?UNoJRl~Oh`JO}SC8tGAyd!KzR=j+ z(olUS%S8J3E8->TsIXslBZ=m+Bw=b;!_^7kK&fEJJ?(^KrGwN>XyV(|9y$e~Pzq>zs z)0x`Q&kH9!*OH>zqgpN;z%sV?LtlAjhsjR?1L-XwqK4PK8$T8)$8y`OhP}F4FFbyH zJ?dPcrZ)*zl7zQ*M(i5-B}cLGBFvJ2lsT-M!@he#f;7%9X>wgZ ztt+KH8W;;O^-YE}R8^0^H0j$)V*R4{m&`vu@7>7?`IpwX++G~b71MPv*_wJQtc~j- zGT~47fY!jI=7dv*ow7N^Y~&{ zNv5CRH+aM}=`XpTtXDw2v(6(JjzSm9Lk|M2VvwT*=s|rzqxR*g{&CA1^8=@!M*#Jx zBUL7bPC%UB_#3M)K;8JAZx_#@Uk|u#c`TBhS5q<@uOaENbgEbeJ`)b(GAIWCjRZ)v z-2&VQK9h(WT#@W7PE-W0hsrhJU#lT9MyxGsth1mIuYElI5DDYz1$h6co+48C-BKVH zsf%UjisVSe)1ToWV}q0|rVN!s#P8|NY>{}zO8oM>CN^CVb)>I{@G9M|UTFScz%PuH z+dgNv&*1Qn%S9ih(f#s?X5@3;f4)hpnTE8@BmXMFSKIp*-<#>2USA1-HGl>Ou?3)&u#GD$yCt6Z3qx^>3lcaU@WQe2 zUCU(k1FD<6{48sI_qGuEYozaQGOuEMb#((&*ElWlf%e?Hds7^d+$f=VCL^vqnHv;* z;>W8v2pS+EV2~HubH>hWqXf_DSc*pc))kgD5edISda|f<1X2O88IF!J1SJhnoPH$r zjq`CCv^o}~IwZisO(a*Xf!3R{n<7c33Ct)=Tq^d!ks5hee|gf_kVr#^SV#7W(K@y5 zOeD8X@6meB%F9R!qmlH|n{@ai3r#T7yydI)934O zb33!$@uPZJ&R#79nFqn|jZwCgu`N2)?~3u;9WsO-0O(cvKs>6$iEW~c9WW*N3F62k z#7qqNkhKEzLkPJWl)cxa$9YxMD0mP$MdSH>=dh;I|3Ns*A*qlH$FlHkD9-{oJBkpBy%+_sAC4c)fh|j)DkG4_dd5>VW{*#v1$l zd_LH}urlZubNPZLH$^8Mm1~(;UVySyTZjK7zr2+^PmT)l=L5AVa|XYEA-NXeZ`+uE zzR=EDBkZ|lc~6k63uXy}{Nid2FBx!dx z&pe3D&50_~7c^n&OEu2}-gSuyjD&F^-aX{$cPfOh((i$UQ*>CE;~|4(MF1B?y~M-F zK^6ig4ufHz2jx|hfkp{1Kj>{rE=aLCzXcu71fEC=BY<0myvGd2I!cz?bnR*MpVvINmcJF@M8 zaHNs!yH1=)jIlVH*W@RC^@Cyz;UaR7(rt;dX%+7LsF!35AP|tEbnsso*Aq$G(2A}H!IP<=k(3)& zWkmHd$NlhZkcL&=7d@EY!RR=tBa8X(2%qzdkaMF94UpvY6I!Bx2*H0ibS|&$<^F1>#kE18$hxablQ?=SjYD z^Xqb>Uc*cSs-fF!2JUB^#@u=ERgj|v51avDso~L21Ys^%S8)_dab&t>-#WMk|?YwsZ6`yr?1RXDMHa&^MEaA zpA*hVGQ&-Dl^SF~a6!(v6#2n?Dq}6JHlEoswSIAd3OKSb0(t&5jbs&JT?gcYib>@! zd#PEA!+7jLa9hXTW=E>-Ll+y_htqzPWrNo}f#uG^NEiWn5nIo*%Nb_TI@0oa+9?Oa z_0Vw8TIDAn+^V<}N-~V*PsGwa;9efZC!FX8!wGG~HPr0Fz>{7mjH_rH#2UCpcjZ_J zTSfj|JK9}C$$+R|5Xfx_2qcEZd^ioZTJSCvJQosXXSZ2vFwk%4+S)Z{ar1dZZfe38 zA$vO^=f2Lo=+2Tm`VYh3ntx*-l$znd>K53OT&1x?mcsnx4;Pq~=L1J^HYk;aMv2Lg}2m}NZ{((O~pyDP-i8(zvT zl=}knN`69|bfUFHue$gHk8{khYz=W0zDoE~7ciF+d|j{511Wn@*fhkhSGztZ?ZNBsGsr8HVUcQ^2KFGBtNNVI$TC=A&(xoTLOM z0${8trGmK%Gk)fd;KPd?hTlH$PnRD;K8f(EG&HPyUEE3G`IJ$-n^yj*=G&*PWz&wA zKfEhH%ffjg@hmDeNct{v`;OTv5c}#N1N9Gw*6M2UTW`)w%GoRxOX%(Wez5niv3KtR zkFf#&ftpO*A^{xz##*RLmeyP~8?7C~7bEGo$n?C$EGy8jeJ<&xkA|SatvxJLV71{= z=+~A9wXAsFG2p+7pM0wwRLu+cMQzV`CZNTMrfV8nfJ5lwQP=+0azg^8J0yw8CdR(k zPeyu4gY}2auQ3(FUDm?$_d($S<`z{%pT`D6g;aY{{uMnDx2BmS_-^u4n+0I9Ny7lx zs3SAI^-q4c(ynWecNy|dEBMM!7EcZpP@9rg&IG=_8;Cf$Dg&iE-BAfU-9!GBCmRGi z1k-q2ew3(CW+AVl4m_K&AF`l=)1Pla0i5&ct^$dIMD=8WjDuoef*1slfsYNDQE*Xo zM;!5d13uF7YRB2b*bdA=xavxMrcMY5cqQ8CyDO97nk6dq3i*F)*9Fbc(_AX(A9r(b`%7Koegm_9rW}f1fH=3csRK z?AV^EG$<1INyBChX#9-)XLD0H&L_v@bAO6b*RSOl;g^p>bfoTw<|W(!`C?`?Rwj#- zBH${D0nKCOjE>K)L#aQ%^o0}QsxQtCH{KShrK!HW_`UbJF9NZ0+30-o<8xY?+Q8Mn zzn7OpqQj#}y;F?DbA?k{d&HNrHzMyJOT+z~L6{NK(%MQrm7i3VQ-0UY3mQf2R!5` z@asyOL1h5LajLsWoqlL>2*9Rl&Fbx9@>|*xuw(#7A6YlTE3~<`p&tF&M69H1-^OuP>vgb^m=}iEMeJU39;yALiNE)(s2OOGWCkREA+W8xbT8|g+ zz4Yw)@KLQs_XD~1D2L*;@H`+P!z|8F08FAc7lZ7H?qY3 zh3J4tmFYIs*7L8)5{gz5RQYoM=p+Gw(r;SX)K(;e4EC}@Cr$-Yk3@`0j8ENL9u82; zx75^U?>fO>lMQ-#k4*)yJk_uf`Rx8a+tdH;zm$+~i7Rq@cCYOzLpL%_ZvJea{-6{3 zz0l{KLio~Y=g+SOO99EgryVZaZ>ayh8rGT=6rfSQx>|n=A#HJdk4B4*=D9t6sim($ z`jQfy&KVlR1m2u1&&*lpu>7tzYw3$29ZXhw0AdJW}ni>RLv35Kqdni}dhjf7g6WiU8 zQ&ZCSB(vF&788NpcyhoN!%s&($-jO9mHQG+7T>+Y5Q~}{ZCShVzS!F$?iTC)-sjzH zyS{OG1+1PE*6J^IsN*dNHOlUs7Ho>Zr>fr zPV!NSM88|5>qgu0@%a&gFwl?)xo+eM9o--e+dbNNWqb4VQ0`TRoqS7J+$cOS+l6gi z5PDZPzL}xUOsf8jZjhcaGb}jqoR3=zcS%JX?($03k+qn}{cSlMnE2=Ud(;E2r!@c`M~)7IX6_7M4Q~fY^X!eP)Tt z2(}TUB<|NYR%vo-DK=323WL)A0$Gvs+rW@Zr1Re!h>+|NCY5w5$Po?0sKkcsHs&qE z)nO9^xRVC0+q zD%I*7Dg+!?=<%=7JsuxnCzz7ZSQ5Zof?)bzt4NvHO@#1a437dha)iR?`dRV%qkZF) zrZZE-%b{RAn4U#1ID5tRXqv{@-t5-%&UDB;DnL5jEc3WRwMzzt-$U3Jh**LiG z3u%fD6H8V)M^oR1So2b)o~Q_mXZ4=jBjAHNQRr+s4YQz3N0`LQ2p15^o8n+M=1qv;z0&)4A$=~Vui zgX&kgL|$^JEkLeHd0XVQE_*P59pI>fi4*Woez%ZON=ZnqflE~8%8TZh|s z4>SBafXVm266rmNv_uVp1P+|o)XiTpL@E!d`9*^cYU6nFTUfez0N9`|l-m03=3M_h zO`(oB9>+#n#z_X|TGLJClug0K1Q%hwZ&7mVf8u>W)OssGmkMAH3hABfTzx<^3>@Y!1(3z3A zLtw@dpdTTtgOtAGkgk9S2+xD_6#iLl>+s;aVeCZj;|coj&A4@Xi4%QEdJrkiJph*Iwy@BTg&BQO%#bpx4PXt^ zFns%>GU-8RMf>G;!H?p&tVhWqrQOE_PP4g}Jv?=3seylSECG5xy>lvgIFNU;UFu|gBY1XGk8#T563|WRB^)FEUgF!*^Dn+esPqjRQv6* zaXXpZs_J`rTFC>rQ*1Xw8M)D zi}P?RZye^;Fg`!Z-4d^w|+VponLj=cddw9PDMl_b2{nJW zrFl~~YEb=2pVO0-nkb#FCk`D^YVm<2XjW`(V|M|lo^B4g~kamMlPx6uhx zX0ft?v7+&DrSYs@x?vB=6RXDABy`bIZtm6NiM?fUJwtJkf=MEz@$GI&l3MXKPVsTf zp{at(_>YMm-3cCZ2}5qlo!p7d*u=5%JxgAzN}T?a`rDRuVGUhG{E%`vuJCz0jhL^n zV#~5-%YyQQVtuJn+|n|vQ>nBfe|4u1b*J*TB_q#M579I;ZW+IAQ@Z?80E+96SIdwo zliytotj9v4$8xib+DwvxrYEDIGd${hIN~r}GBkr;OFlXFu10j$PJBj+nfu9E*4Sc3 z=V69GT{dwo&0r^cJTkMQEVE*bp`V6<+d4b%L%O7s+bx9@x=^#9*YY|yzE1TxX>{&n zNOny|w#iQJ!A!P~P~JH*r(80p-vaA4qbpI6OZz-$U`yzlXnK=8SAHuiN+{#LLY%66 z+N1dVknY^-YxRg;!4@(vC!t{1EU(Njugr|5l)(I&ke){DF^h1|!s`__+UBd&-L0cY z#MWgrohM}6V#z8f=n~@Oee)GP_rJH?%mUyO5!$*n_+% z<-9mpx2V#o=w)b8UP8%dil=5ZVis|+&#-J6c)kjS67B5bt&nH#i^a}8&-Uu_^$24D1vH|bQHCWP>bXq| zme7Vpo(ZvB?3DT}m9mEw0lO%$@H1UrrwXDvKp6i?M8_(ZK6lRSF%IL&4RGe=7g$sg{zjayze<3a%n#RNZCCypvdCa$Z%0 ztS-W`4f$1mSE%XFtVZ6hV zWWeO(SSrd{%#v=`R|{*U>1WpqXPwzo`-`;hL{x7g>XoE1ZFOU;Viu2EEUfpxS*yl1;U@aq zS*?0ae6Jfz)*5F$l4f?BmUaKjbNbJ~5=lnXsNL}}U;cDwWup8-*qz$rZpHR9;79HE zu-tTymZu37t+$^ju`~-%G$WHzj(3@Vd&EBU0~|YBDtQ{&8_d>WZ8eE4$9h$~Nd)R7 zb9#~1-km7XzHG*DX6Db26a9gY#|?r>teg$)W_)cb;hN*Hj`6y-3-b1BGqw(E`&SCZ z)q?tu9@d)$?Wx;>7DY|UN*!7!?YD|z_&-0Eop`Q)yQ8hXgG-_H{*O2*13DRlWR@Qd z-`qmG^PbzXb}Do{4@%OsXN_{a)(a|jB9c0R&`$hil!p?XS5cxIYkjR#Fo@YbC*Ln! zyX#33I@qA+DQ`z!1Nz4V>ZgA9vV36lItdz1-F9XA(qIolqPz(j6Q; zVpZ?Ax{R;biUDdPP6^cYEjBg2I?rl`lNU9(k$flV!8U^=rmLh)uKh-6iHwg)yKje` z7o&Opj{NEy(U|L#tt$rKc~Re*g&^)0>+TKs3zj;Bw;AurkrboI8V8m0J8s=+HT2Xr z_7tYd=v{MsR`F5E6HEEfpY-^Ixn9Cf00472f=y{Onpct0yEI1x>XlV(T0^>704kFX zay!HZ{TcrLgL&JLx&s3fs(}TqvA{u8qL^{t9FQA^)#c0sB2BZ3f!Y5aN?eRjXX>F| z93~Q|3w=q^(-8XuD7#LqmU1Lf|MgYFE4asFQoFYUnLT}fMXZxiwv(^Ra|cHr2U7h- zz>DcQI)PZ_etl-zO#n=K08pGG_9Q4>(m{!!+fG$XE;wNNBtmD=r*iO`SMT3)gLacZ z847@N*kq|B$n3WmT!^Ni>=}ojro$092!kmt2E^o{j!j$@pap^T0Co5Y(6Q=Oh$Ex@ zNd6yp2oXT|9suMm0Q9%1aU1u6FYG-HZ$_~P3l;p6Dct;&mbHf5cMw{C0Ovb_KRy89 zl`^a@stk+%ZF|jzyKi5JwkR*XQc)Q&-RncJ4XRU%3_eB;drcNwPa27Nj5kg~>1A0n z6R_p*!~+VUJC=YJisL^E4Ax2%AoWcrNu*&Uub@p^MNq9Vy!VCrnp)F6;Re#J8to7@ z02D%EbCZ!Ig@$TV;{K^AoDDl>FA4wl{TrE^|jAvlO6*1Yab6}0wreP4p=yGT>-hM=NKWA=pT7tn*iQ&NLH-;^O3x&KxV*>@g z91#uFC3l;+;fZhrE6zaf6RnV> z064;tdQ(ET83P*)uz&Hf`JK_*56fn1Q?Gg(H!IAS9c~IQK4Jd!b9wLgysN5%x!6}F zgBce;nfrS*a{)@fgH?S8?fxCnK>=_u%{|r-DK8#LH4A|qUw-Y^c7!iJmtdgTGeE42 z0*!%a`9klI0yPH+^jw6o%OV6Rn0N?i0noHTs?(BqQrDfwjss+I`dOKvodcNVFv(Lc z6uJdSNumBzBgpyczG*s%#ECSy1pWNbH%bEe&Ve+WsZfp%!W(QOd8HamAWs>*zbYZF zbOh}O;FAP$vRQcF2$26|x9-E2S7%?GjhF8{dn=Ln%g%UyE3E7%hwwe3G2Mfv?~*y+ z|9rLgvgb;!Pd%0wNBe%={-;OT&vVK}Z8;3yIgoiFE18qg_uCwSJOnmP5k9gEyxge7 zr*x--+vN#!&DIG1yTPk~_*IEN8M%;{In4^e;*DAGodQJ!Ih`gQL*z^-;!v9EfP#ZW zBU}ak&oJm?$&NswTE|3Tcb0&Qv|LNNyD!CM0QkUQF;D*`CPCi2Pys#PEuwf9Yi z0Hb_uYpOAJ|5PyCY~oyG{~h&<@QekN_szbPO1e+BRaXbtt!D-tpkO%;C z^aN_{gXn{hu79CwenT0c|Mk0JUvU-W*NlkW&16zXBU6kNjXD=v^rgt_Np3yLZH^ z5}pFEncmOJp0GiC>rW*}@ERmRiB1{-fVFXCAVP0j-d-z^C1W9SKX*6zs)i;N)}@rn z#0%qf*Q(f$P3(1Ar4i}nHK`mgqdDnrXVtoiIX_GPSyf@Sif;;BZ*dnH(;@{1kp>IDJr`T=zpuXg`PBPMPtgANb-EjE&H}sG(O;40d6${oo+cjt(6sG z1OTD;#egYg()({En)zbM5P=6+a^7rTb(l!wfy$v}I9L9MXYINyaA4epYtSBI#3iHc zTwbE2?J-dq5yqSltHu&qN%x?7f)Wl$5zj^|!=}qXIM~Gb7JW`Cs0~G_8u;6|TK3J0M@0 zi|q=F7hr+cr2ZY`9bE*#5wvC~_@FVZ8;nDAZFIzCgK5q*Wr}Erwae9NBQp>S@096q z($d!pHAQHnI^66X4Y5A>O#5%^I{^z;imTDQH;rkDSU9lhvHaWiUY3>h#~*IX@S0!! zcAmF98lIotUYU1!uW}}Oa%$&0!Vvt0obKMi9sfD2;Jc4L=g^Go%50=7Y#D>Ug8+4J zSvfqdFf^{J$q@vwEw)nBNoo_#L--QY^~sB=V9XUI2d3%-K#QJbC+pS~ZXHHPZ@q(Z zX`pu#$h-=Dz$fFIsa>u_cHy!XgKVk37bz-yBT6sDXgf<96{%kGjbt`vT-#Om^OY{l5$HypxA}jKleY3;E2J7Z232Z#vr0*C2aLrDPmaa0}vDj;g4s@^G#UJ*Wqd}Yyn(8@r}!`>-PX= z|Dw_x@2aFnqBm2uIB+Ro1OOzawktxuP~QDo5|Ss*l)5Zt0NH${v$NT&VPOD#4M3vz zRM1c4@Ff-S#XQvP)lgDYPgEXUgFkj7;rxYx!~*LkAyGMBjYs5f&v*tXZ8#wsPSRGH zo6u;5)Nl8;H24H&{4(ZJJ%xi6__fUvQ-0hDuRnhF;l5dt9bd_gu?^MDShHjo`j0=V z>6F+n$b{^YW|zHOkc2uC=t=vyUiL6xzWt4P9T-z8e2}I_&jsl)ea&!Py)5k2vEgqo zLNa~hw2RBNhz!%CG)~7g03(<1BD3D#?{b;R|DsG&+@b|^*C-!YwmtR#1gou>lh^4&J#FlJ`rK5!;h~j4J47VD;Xa;4{l7r|`;_oN^E>HE=F<>;a z{C6t;(4sro2b*0U#%9Iq%GPVKE_(k_HQ284xhgH+;t=?hu0+)3qF)I$d0f54`Qz{l zL!Xv5j?9t(9DUm%3p0%t=umx-4QDBXRKUO(y#^Vxn*13x)dNk*1-oqV-g3P>weDmv3ZLN=rM6FYvx5@jzW;6|1@USeGX)pV7@&itOzH zIe^h4P8!{_1U=(lsdga5M>`gD%I`h}>g)BQNs9mr#TDRw`bAzZ-QZ-7CYZz4=J?Ld;bgpDGO%0t|fJ32l4T}ed7ckk6e29-NesnNF!2`R&d*yadui;;S-+v z+4JO@+*|JUvif$dFTCmoVrE2VXCc|%>G`MA+BOp8IMZBRu3cb};YB+=nr(u|2Eb7e zUy(7Z-6w(KU(#V0hf+%!`R>^R=5wFS5miT-`W1Cf@)So?BVpFBc%SLhyr*ca!<@$R zJ!n;0-&w=EJ&F{oK2*W}Fj@F+JGLj~9rft13s+py^J%~T0z{8epGD%Vx_jP8e~63i zI{Crbj0V7k>dk8B&U~Z*mLqkD?U61C^#d><_qSsP=nZ`B5(SLi89uB3$c#-uxfRfe95@dljETA0f|AjLc7)o6Kum$3HUe@~`}BTPye z&t?k`n^S&{uv$Qqun!)!v(LNCE7*OSdvq5pHJ=`;5-61j1J6v`eGcR+15C%;wM5k^ zbKD}Mn6&lpFuvST`=G(&5??DD2+jl^U~7ZfeZp4B=L%Fd~)$mrxL_vZ@$_9fSwv8N;y7oKGNji zhDADLLklA+*Yj*}Sx3`{8$N>03K8lPmq3dUS=#*~_OC@wo=?1L5jQ^y-sEZJVGU~Z zyt!Dw-nl7P6x3qjSNeHa^7+)$N0%5oteb22=XL3gE&3h>#`DqWiphI;;yACC&uEYA z2OUdSsWA>zU5}Zfa|TwrOzZy5LM=__b|LqZH5Usg&#hxb1Gi(;T5Ej%hVs{#{b(_l zH?SOI=W58fgmNYG$#seq;Z@0xhz~VTAY-fw%$_2NSD48@3qNvy`3>FLy;SrU|6;)$3#oX(rXtdK-- z2r{OquowmP9vr&BX8`H|KQdQoI!i<%Gr|A= zNOg!1m;%SCo|Q>dcK4(asCXo^QN7Y+A*5AOAh=N0@0k}u_~%twvc-hw_I+x~(Kon` z817Os{&}l`iDrB2&*)S!;7qBh$(HsvEA<~8M#u0!Vz{Q>q$Jo24%wqlIv`zeOi;BP zN_5NMyGDdF$90&>hlP--5)+LvG666ZG#Q9EOB1f`a? zP|$4vnG^^mVH^a5{d1V;#2jaH7RBWVq8SHh96{yvoWx2AIub6FQ41Q$&GPIFD#aS* zY#I$SrDh@YM=+Bmgy4)NhVg=N`rsiUEVZQ*by#f@#1VuZhu|ggt+0ar#rAk%a4UDb znj<+~EtHQf0plJF&>Yt<-{7s3L7*f0JOpJ`94;?INfofr*cpSl6I0(%ud!Z!W zgth2T54Z}zwE)S{XR*oS%;AKXj76@*i}+wiJQbP@Ut2=8%7MzRBke|o<08vKaBJ;# zV(a|JpIJz75XN*?IGQxzILi-UZZ^#)a@fL?;%gxx0HYvS!x?}WAZg+?!f{Z)a2%T+ z#{D9in4syRG-d zD>aRzUTxB7MfA;E;ep8X))morpWXDfL*5kLc_&t=_xToI!6lPbPM^PdfY9Vco*_As&RgrZM@QSbU-6clBUcAmg7hRFYHPB zbxuN8YewS;&MYwcRIIV~x8;~pa=qBxL`HJ#+f;g`x!8ZTtFLsweKD8Vq<`ARbN}+j zwz9>7pRvr{x%mv^uY`A*9njm!LrVq2N*Yn*$&*Uy@joacMb4t*Y=^a{V=IebKZKZ# z&@p`tiQn~+<55B+kaFFNy40463`YicNAU3pSj#j9!yfM^p`nlt4=r0#0~bUj{KDy zf691!voi8&JGmzYqAJ0i>$+#88ru zZ3ji@V9S~vK<5}KIUZ$9AbpS?>p~zUXCr@bkk59Xq4)gBYjjSfkI<%xl@B|0+EHiQagvt3+=nM*1;u!u(^2c{96li^{8|yLxTj@b>$5 zD=IY4|J_{+qUoBV?oRofM4lmez}xqayHkuqGPaOXTO#|A;msFP&BbNerT-jO8t+D)ng5%bTK=8# zmE9hEnzkzDNOG0-?RCm}6?HmuTmV(e?%jbWw*j^gp_3p-N)d1^h|@89TByr9s{~adf7U_NS2L-o%HHEsW<6 zFSAXjll85wqEc5Bi&s$gZy1bQ8B?88qn%z#YKjQFVfmiI`fH8ttCIxBI%j7Jm-SGZ zL|x|KGKc=MST5{_oLb7`^`_^a=sX96tJjrZITIILFniyY&%Q}&J4$lgEI@w#5u^}JNQo_+Grx}UCmDlA&&^XKK71l>pV!S!Ej z-t4D7>QJ90q>nDo7ah$FsDaO-<+`a(l9_<*IrDX%1|QKU-p(EWi8XiK8@cYLXgpT@ zU*7S?FM*BEnCo_@OSa~|VBd{}ppBHA#5%?jvXkQ1o|g(~*R2ckb%ZncUB1}63V%EP zw9&MGJ(%Z)$K0GG&$kdtHSa+>A79^gH{Xa0w;Kg?ei!9i5;)rukA5rKw>q?6Bxc9E zUj0I~6L070r^ln1Ihz z?@|lnU+@dr&C4%wB!zk;99hK~qT@@p%Ss5aAW@i>Dz-lmZAp{f_i`JRw;N-bnBV4K zJ!(JqcD?1|W!k~|Vqoj@Q&q+BeFo0mMbX`MO`CR}z%aMnkAAln+hIJzfL!VBBOJ{7 z5R7Q4r#-}5Y`vzD$i7RYbUTa}DtljogRR!VhjVie3Mf6ca-A7GmyWl4%t)`Y>2tKk%dF0VO9Rld|*Y zmZacibAK=PePOsinnKwF%mKu}>TqgjX)|Rk)*dlZl1VfHPpr zI7j=di3XN&(T(Yola&7qE_t|i{zLV=zj)E-)x0-=XoiBgB2G#INNoGIRV(b?S*%1j z^xJ!vf1WUX4}1%}j~yS&Ka`W&8Ox8G%f<}VD|*)Jdoq9AZyIz?9}i{F{n2uAJnr>l zAt;!=c9>1;WV0%`p(XfV`IV@J-l-RKRRHCRBOs5C_c(L4#zLY%z%vf`{lj>53~058 zGqx#FL%jHvrEn;YM_zfFeC=t;VeE@JZ$K3Oz05;<9wDCg(*O#`yHO!5f6f zzW@@b-SV=YrGl3MO?13x7Ny%{98{xAtovu?PyC$s;D5t!v~YMX-+Pn)#g|14+O)K*8)py>E^bw4ZdzwnWqxkPFVD8yH z?YDjOyV&Pmeb7ClDQE&ZH*d4cY!wKYERRHLUJ6NQj#zI8Hp*}#t@%C86$lg)Q=*cW z8#GF7WTc^eF8B^455FpxOR14vVtY&6V44+iYD$d4rGfwsLcsYdJJbX0U)UPi8C$*_ zn<@@)AQy!E$gWo=#gnj2`j&Js%WN6xLrj z5nWgnQQ8twxttA;bY2`9OdtN%aDOP55!oP3lXG29yQ zcPIHGvKW#hpvkzt!#Vf^Y_}A06+dGhIfmF7wax3!^hf zmuZez%4ZtDWGp=n%q5@SZDh68pO%h5868>hSS24{h=~ILqPNEWx!3!KdlDa;-T%YW zN!*uQX!F^R51>K_TD5P81Ivfc8Wy_le_wsy7XCM_89@LcD!ULSvo@H) ztLt0(gY7dol}RwGDnf2^yi6+=Ar&dVJzZl_Y5puyVRx?iT3DG~fa3mQ%bm6HXAhLV zf9Z+#c9%TS#&q3ydJ1HfyAC|J;5EK2-?C~P#2-xXp1NxmoC>|QI1^8}LE#JEzkF|J zmxfOH@BJ@*j~*CYwaz8H_~jp!eP3|}uq4S1-p-#=mIsJ9MMh)DN6^G(pdEQnY>%Wp zX_GD)L}Vl92`~ciC|TY}KMnjWWX(^2G0h!uJgdajUu|OASCdpw@|SVLD`TrVyhasK zgv?W5Mgcmi!D}&yS6@M+VzF~+avK! z%K(mmLrWhP`4^VU6=y#S?sUB=mu(U#PxF4W^;Qp{|b%Wyl1k8{>zWoVx<uyv&=~yiBDi*tatB?ED=aA>Z;@7IaP!(uTw8R;-dR`Z#BZk4BA)>x(s+pSB z9xe(-l2HrRAZGP{v#rbo`KOWN(X2$s+E(M6D#v^t8TzztwAy(m%NP3-Fckaqa$Jd1U?|ST$FlePJFm&=Mga?2e7E$ORJ0t z3StF%ZqVBq>APrFj%x+kf!6)K(CjL65Lqx!Ur?aF#qbwUR6DsMxaFM-S$W{-+YEDi zlz@n`M+Q3|3`Zfl&Aa9S0L_@JP{2DyYJ12yAxtQhxQ5~~M)nNa#2Co;(g+U$5ai({ zXw{OReId!zwj8dE1;OM!KzzIa;z6FbGdq@7eGl{m46k|s1XXIZIa~(nWA6ZLeae?D zHn+Oh@D4>!N9&->MQ<_1?nUmROY-cZeyf6SRSVT8twt68dFx4e;zDgj7;ec|z|nQY z@9sD7kJ@ADg)h^&W|QzB9w{ln(%EL~nAB}7M*wf+et_ocXy1Nj32_tE{ejXQ9Xqtb zmWt|26mxKQy|3U{5;fEi(0hw)mCT&cvxth(ZYKNmbMSlivawAL>r;xlTafqxqnNge ztD9n-V3G)%B_Q0r7VJ|sp{3l5-@o3Eu4=-n-aVyHR9|M3`CTcFij-^5;y22QN)#S? zi3)9(g$suhzk@?9+Lez$lH7f4c-9^TUctri&F&J9mo3@mEBBR%&C{vwxOT~-7Qq;3XS z^d6r#Q~Tf`!k5C%vUSYZ` z@TDnvNTMnSBsz%}2_wJ!>6I}$(ILP8H1MHZy{Qyxdv1bXe7(5dWq*f1m#!kJ+%w|V z?OpTukBYCpC_ERr=iXfvCi&(CtQqOy+nQ#r7T5lmw*@4dmGs*!TH%E`t89i7l95_m zb`JlY_A$EYqj1)PC(X5K}~{;nB-&rpn#kt;DLQ0q5<65KJzvTV z257_5(T8vyGHxdT>Dw+ym8)qF;#r|7T=k$8TwFEgm|}FZEEYmLelPm7y1jm$`&$3$ zgGQ_9N$u9+gUE@4`vQx*|3P?^UO#kMrnz(0C4^O`5z9BCx~o#t9$j=K1)vbFICPZG z=ktAI5mp>T6tzOX*mR$QIF+%^h2`|)Tg#aSJr*oYa-$XlQie-m_tvZ6i`|t5dyzQW zNgS0QP)PO7E3*{i>E}KImvaQeBGM|k*6Ln}z7j<-=dZ1up^-L+XL7Zde65y@KI0f7|GZOvl?NHHt zoW|JD`|8*Q(roo_l31sC(m#k;nxR0Hn;~0;NRCdi{Oa{;r%9){f9Z>~r{rOqEEI4U zGlhAt90WxzLjhEb>T(*vY&;?jvfrXRHPjE1$IA~T>JcCaQJ72AJArk0E0@uO7D(;u zCz{cV_3_1@7ra!uvX&^QzYGvm+Pvpym)$29=|{X*=)MGut!Z$$BNqpd;0z7;xGg-3 z5f901N;Tk`Hwto$Zturo(!Ij7cj_VVrv4Y*rK10IWsug1f`o-u7#&etpcE{3T&~#C z&*q_P?zax-p|#)w9$MK5ps<|f@%K^MmdV4@;fO6!aBCABb~{)9A>Na&Wbkd00yU#T z50ssx{qDrmpbl*PIadLor4!XL6&{*hcmabc8<7_DL&U4E z3b<$gI_uLCG-QaHsb5*W9K_Cpw@oaj8B3p**dOfr?BtaLx^1fY9x)hI+;dxy( zOM&YH@jKW1SB!KS2OT842wqVe|BQVL*!mAqM7BDzvHyq9N3*)-uG$*2*8hYIDFBfU z?2teO1g|I3`Zv}c48VtyPmCQcBvbum4X93;ycqprx3-0ktSDl@gPx*T9 zTgLszzDHY`_dnh!*7q}?vH7db^81EE8Y8}G^s7go;0nxny`uTpCqC=Ti}_epHdo3z z9mcabwtO$Mkv!`NGudaxrF?KMzdp#{*$6>ow$+SQx9$O{|0=#;u3e9ZK=I)O_d(^G z7MB=c%M4@J`vr#wRlIwR2KHZX`zn0RKTbne`(tqCui5y+QM%?R!H>rAtW6)ah!D;g zWOS98!o7`RI=9rtx=#a6cS9G9Ba8_-y=pkJx%M23ss{w`D0;WKUu`T+WE`B`3Q=go zDMSw2OzQsX_wge5rEt_xwfRXk@3cQ$qhhyJ6-K37?{=hIZ3<@1!b>23`*r3>AgTPF zklWn<^exz)ny@Ss(9QI{r6PW2elQ>yS32C0%xDwNkeKgfT8J|e)we6;K7Te+_(3Aq zXvemD(}(~mE==x8uomE<$1Y02D3i@W}w%H~Yl0tKPmzhT;fgPZrC_xqp~9Sq<$ zhf#Ww;4woU%2^pU#i$ZJ;<~%>JL9^(Rz0)6F;6R~VDWW(+%*3yU#k9kLki4X|9Ht` zO`HO*FT4;ZtUk$205Rc!2T64rC~_>ns=kV!E`MvH@N8TfI?38BGtDPSy5OcJiR!NQ z?p-0_>BVQ)TF}&`bPzr|lK*j*lZ-^qBeQtYsrKC)WhuwES-S%@3v|D+{9 z)oWy7u+lu}PaMb2K5%sj6oi0H1MebXyB+-xo)l|TLGXX`r0XERmq-=D0SX%WKbdh0 zZJSz-5WXetQ(Iyi^1W786^2nSmiPguuCEdYXR2b+F?zbqAUrjl>7bMQwZ_k2as+QC z`35=7+^y?8Jl;Y$|(g(v<91gjF}R4#G*L($3+c6>CU!G5ARq2!gU%DS4lm3dG>4D{x4*&nWMAxrEB^9U~oca zy%9GN&8L33iig-u5n>-_XsbFx#6E+zo-xuK69v@uFG_cO>FU}mFpjh?b}U5nAB^^v zjww7&+RO;)Lk12hNNnNS1}1vhO{H!z2qw&&4HV*vyFQd>Mp>%EyONxOUxek}6;u0Z z>DVY~9!I4Wq7WjKF_J|$a;O+WO&ju4=}+i-zuW|F zYUk++U?3@Z5MKU}qhd?bW2c|KdNO{7Zg$vjCslTYcvbmcZlgdG21YJ6*Y%8HZA`s} z+2WsI>`)4oM);Jf(;c@W;7F4Sw|eJ>(+js!Jxi0;CkJDO0=OJo=Vy6+N;qAW`SHqL zc+d%1@A5{0K|vI`H<8oQ86wg>=9IKUSGyYBMPDe(hFH(MR5l2~S%k7l8j@V4lZC2CI*_vElTR-_b1`(T}ZI8b0oB5}vLQN3WFA5WBx*O^T*>!0z8 zSDdS2MOi@O**XtzW9pu~GZq$gbxaG6GE|w=dBoFy%;4IycNcF9z@geux17Xp`Bs%X zqPr(fl8UZ-rUrEo<+|YmzcJTtUhvtFe$;J4IOB&YoOG0~N_VV4ZlHzaP*uJtS&E!& z@tOC_|vejIV}x#4qx=ct$)6BJG&omxF%4j1(pja*Mr*KjXyf6 zzNvCend1cwK8V<{pCrx^7ml*_5Qbm%n~8i2=A+0oq5D=EHGhQP(K^%vof%!5hQQ_! z?OVpKa_?OyUMpCf$vd2>`kqtW2zLtzPs;7`iwdu=JoiiMbj&-0|4{+AlV3U!KTbO9 z%192e{K-5%rq69UYJMbAFD7lU{}OwdDbw!qFvXA$VP^}}|XzkLKHMX9vJEWro% z=2TH!IOCHvz1p&yA|bJ(C$XciJD=~={O3`trqcWCc3sIpUF~_lX>YyF-+^0$4T<`V z-W1Mykx3?-E=teYR%XTzeXOvn6xp>csrs$IMnVgA$f_Cg+;NJ6zrrKehCW&3+rO#z zn)_D}cA@(BebZxUExbCLfrHI}(yXzH=z96XI42P+dxd-YC{sHyHW*1Zws3qkc_}#8 z;kAEJk*;--=ryP%{^pHsEySuSj&i7fK@VQ*9vJ=Ce@opl=r7r)J`zRZR@)tYuyuF$ zgymnASnbd!@$HGmB2gNRPo`hwkc=?F=l}>nQw4$X5T#`)6d4US=lh~4Eyf2^KZMrhBP*Eiuy4~DrN^rr{7QMUf%3>T-% zg?+dZ`PcU9ZdlfW#eYj9ntc=hEiGy~Eo**fJw1TL3C2LESmeWzWKW%V8g|9dGo+VZ zGLx8nyQ7RY{t>6j{o^wR!67if1O4N0#m6M`^dfx?0Mff3N!rb|M=;$mf1(y~diSAkJ*-v4xBbsXo^gD*+@{|CWu$`OXfPVdRTs3w+mQ_nX%-LX@L+DA>`nQk zW>5m6WFBrTW^d2nf#}N!PuX#I8+jkn`}KLn0D-G7w)h6Sa)p$UadfdhPR(Ed@wH0x z^e=m;-&Cb>qfZ2^VLDGX7f>c_U7MMH;s3ECx8I@rryD@jNy1F=gEVE+rt3B)gd4JSm_au#$*NgvQCO(;n+X?V0-)Hf5SP| z>dwW3?19HPN%>;_3E4dP7~PUbJ-_1$!o)`#>MfK#__UAa&j+Dxz?neHPyP~GTrYfY zt8GlNWTFRU=bAlGY;OAgZKh)go#KLXH^V!wnVEE@uZ%5-A#^-fj?qd%2x6E&-!*4g zII;ggZr@C2Tcn_!eLJH&^mERrw1zXi*oVTq;tJw#)#c>>8tKup>7!ycCI2oK=jzQM zQf=Nx619hA>TxQ>X2{>I$!>Zv&L8Gu@@r#e^4!rVYc;FfD+ZaqQBoa73QO|VJfN-p z7hg;Nr_5fB-ZBy_QOo~e?xCDPx{CoxLaOw0)xcaPpcIbI;P5n=si#w6Oqtiwm@LKS=o(R>%DYxo(e_bjU^W4JK+` z?SuFC-@a0`&^|Gnb@=y>b$Q*|?qwm4PLs_u)hjx{{@$&P)Fv%+YF1hI7rkMo{aaPa z1D*p>nP$Ja1`B=u)>PZOG@2Fs#1t%A3DLJ$H{W(;xMJ|wD(Bvp*A1*2lcqRgSIJI0NZieJ^gwL31e%W(>cJD2MOW-Gr1R`x4S!fpBLdW8xsP-gpLEY? z+|a0t{IA6R&#_MC+Hks1>&&M`^SiR(R&TCl@|l5Zdwb5?p;-E$mZG0&BHewo6N&Fe z`Jdu88NvzPTpPd288(cV_c~l2LP_+m{xBpbz8pl`$LmF%UhYW zY8l?hOUS))yfDX)MD;qIB;UI<9R(B`8Cz6r#Y3^IK^|Zv!PCpEHBp+y5?2=|@o-N$ zLHMq*$hFTa^j)1SQ@5fWa*+MO>ro7=vrNBiv+$y!% zD6@bDJte(p#X`j>5f`v-L|m!g=+eO^ zgEbE7AY22=lg#)mP!*T}I|+X$VZ>*8^&%GKj*E@`rdRE>vO zI8_?@r%oy3{Zgh>9k|`dE-qgeg)8~WAM-wP`Fw;s7U#dZeb?fK^*0P_7rpDYt+TU4 z!F)UL94)eK2yp-!6CNt`HCP3sxu^{<* zhX=D8KouHgBHvgPAVvYB06@w&J6qMbD4^H58N3F6!0#3lzGYix|a!HfhY-@Ndo-pv3bexn{{SQA$Psk13cTf*o1(hm@f(x3LUeP z;LzG~8Ff4*5ZUNkcnKMB>}#@@7ijf*Ai4JNw<2Twr!{eEUpXz|PBgo;;lyX(3G_$t zk@SPoC*MAk@l)&*PfHFg8%l;B&F6t|*Ix*7u2Hb1*E&V9dD_~xda`^jXXpbARj2uw zmT-xnfkFx=W%Q`okNKe|{?u}^LBJKv1kXIhZg|xZLOyLBX!rBt*#D7i{oe^dW7Nwn zADrUt=goChf5$E5O!^I`)u}=GCPm8+Dmt-n+VrjKDkHvycl~rYbkn>=oG^r@`ATkY zGz~;H!1PMH0LD+52$A>PdX-X0VaOhaT%JsFaP;Qd!X*YMQ@Uggcf1N@>D&ucdnfa= zV+`UD9`=PoARTdgh2bf6X(Rup`ZX?(`-5kLk2`LZA1~bcNP(p+WH{XV5E{o-_{CuP z2OJhe?g*RS5~DK$WrQg=NgW>c){a?c27(CxrCyK0Cl`vn?~-$gasq%s+yVMRm)i_Y z1NIr&$&lYbtu+HosO%zIj|Bl;N*vX)$EZvwtB{DIuM1BME_)dmHJ8HDSCJ6+#I6i! z07S5)arGcZK+dn_yx8$5F*|6PU5l5`W5Lspt4i0R3q2raE<<~J$a@IR7JFqfSTkgy z|0}P*U$2mRq}p({>**&c{i|OijTQgi=%qmSyIuQJVp%HAvUzr3S{?j_d|}5!Pd)Tq z;BHQddZcJF4SYx-)BA8$sCl>~u!UQ^ zWuyYZ1gV-E<{W)BLlxkbG^v(@d*=qhm-K9LY%K>L#1Ac(vz*gU2kVy*?B53>6A$NW zzB2Bl&BB(ACQe-~#zIra?oPt4P`b0+boZqXc{mBbw#$2e%_fiXtT@XyYJ#eA(m0M@ zH0esD;%bjLVV&}s7l-cmOORhn3=0Q{E^qI0+ux{~{MQ`MJsV?ztmMYy1fl6p%jg=# zEoNdYJ&Q#8g*GbyRg|n@7}8v5?w|H>D{c0svi4mn2~43af=wlOf9hq8r;YNNnCCu@0^7DIW6r zu7G;0WDXhu&2l-_byP+#^8?WrvXbyX1dq8H&5T%ELA4Aj^<0@yc0pqOoI$l7Bh^HD zX2AG)E|X$i`?HY_pVL)V1Ebgr5O-M&i+PM3Z6)_yCM1%Yk?ai-y1+@=dd`(@@ZRzN zI#|aLASNDa6@g2X8qr2v^$-whjR?ZCJs)Qap5$1Hr+?h4Upy6zY?g?&#1Mq(fP3ZD*S>R96=eq94>&ET$0J@&rHw z(py&>*6D z)?byoQ#NHGbRe0C(PFY&J+l%0n~Noj+~b4hSzkHfqs+KWGc3aefdRFGxZKdl2JG#{a689>3X{T%@$w*SZPzSAcFKRk z-w2WdL&C8XXP2P84^GmSu|z&;12BjP<{4)aG6K0sc3|_Kpq)&v!-MAE2S?u&@WNj7ZI?)QEg3LCi_GrluJ~ne``FkSD`A+0=CWB_} zTCk3a2TLJ#m>SD4TTUkD>Ffldo%0M48&~_X#33UfZdEZz5PW!uU;k%_lyjK}+RKe(`obT_7IB;mJBPj8$%AP`%=OGX+_WI6tm8dVn4< z(i0{S03O0ssyHc4ZDC%s!EP`#h{);)=EOql#c>poX!EF2;P_<<&hWdl6UrS6g6!4Q=dy%1c=Z?oUNA z{wy%t%ArKUCJn?#VuIO;&>$Q|ff9TYcg_Z|O~#z#fynN)&8W1CQm@ap+O5LB1Wb+u z?ba;jGpWd(UL($<0bi+M^5sp!hZBJgZyKzl_G0u;wt0_`0HbNfB*9H2&8f5jeAH2r z08;(A>LY~cX^H%+T=C^|`C%SBNS(t|&*_kL$Jqz=%+)D_q zNMMH5Fj`ARSBO@}ABYd?ZW|?a?w5ZiTajPnyl+Em5GLosWK93IdgS$hypYbL-CO>Sm;& zuu%+%dYQV1RB)Q5x~q+lSbntTqi?9g#6$9bpZdYli|aU$HqtNaxwX*r&m6h4Ji|({ zs7pNPXs)*M=z)m0-1#e$1#jc?SN8KF&S&{+)A=sNSnuD$zOS!elu!M&6N8^TA|D_4 zH4e~!P3_;)eq5P?MWaCNq{PDOx4Ti;ZY+;*U*s=Jp{_!i=#BF)eA0!)Laz2i$sa)b zC{GWnxy6&~VZDI!8feb{Kk8tCDn1!rtZ#rxS(s5hRS|dpv$zx^p1e~q^GYE?;PD+L zmCVEsL=qHk$zfp2afYON7o%c4y>lw;$vkrRBUAOKge#FdPc%7R=|r9woVRI=RB_kz*l>ob6#_PNw%rEjjy>gbgv_!HMT-*JqxnMx|_id*=y#hIsgHjJg0QJe+nXZ zpxm;w)Tih77qp`~@I@7Z5Ou$J=RJ_OzZBjaz}Xzk~L$J)y_GRkKljl;zI4j*}r!5@)m!`8!FDAYSCyN;Zka- z;Xfmk05x5=2kkO0mzo&KSt~Wa0wsI?Lwb}Ar>fhMJ|9l-Os;Si#xOIk z^DgrBm2yN?>I>gL0396j_NRl&NaD=5{;?6baHIlMj=7@4pLx;(a+zsTo3n+)QC808 z9>a`}X-+^GtwFgnZpO7R1%}@g%vokm@NAh}Zc(K>Jz7q>WJQx*U4N5h>HA zw?d90SBXmk)0#VJTuVOA)%et_!ksBwdTRDBQ#DFNGpfJDvj5sYPE%JQb60U<`IAzW zQN0shTB%nHHDW0s^$T#^nVk&pvJe3<{Mq}=(vm4)`wHs@?EEs-Ewg3q zCMZh)&>R4Pib3_p2!(nEYO(0xYrZIfBgon24vHah3FX{F{%?{Koeq{ST_D_lvApj9 zx=YYJs+>Vnn`{?ziQz?`)!~0lxNFCz0Dvg|;M&_qNCAWPUzSgrEz&u%!37Afw~1TL z;bQlLD!Lzqp>pK?kZwpybX0zx(ahTag8G8L!`g)PE`52-0PwDSqS7c=+-;=2ex}y4 z(&UMW!m92qF5t6_^UFquWJ=Oy?P2q>RqX$}OVf8hz6x3!d1Csid8v!?JFV2>%;xa_ z+@fU^~umlU)jM(FysjnP86TVKXrzu250=%(^q?P}kisk3PuRBtTY z{n+9#T6XnK$Ns0zkj=7y@GWwzM_@Ha)8lD9r&#x?hDiGfo}<|DcQ0e>0=d+xp356o zZkE>kj9k?8loOYtPlUkPP(MPbxhBKbi0PbYj=W9`>7hU_^{a4G@U z?~JVj-DRiKqQV`bD>-ccl`S{D8 zxkrLM0FRF1J`b3CLHhce8hRYVv8po$6`x@a(6i*mDnwHL!1k3!bQc~M8nkcPt)=M)~QM_?7WmsR|D3=9Qif$;K~ zPMqpATk342D_z-c0=C?{HK&8B;_30uA$&}~980d@yj4wZy;DkaWEVV2%}g?@3Mge` z6}6@iofyJ`QqW3j&ePJ)QLb6t;l{uI)pF@yn!7tg2Cr9Vn;8A^5OEl;QO+5Td*)p& zSrq@SE8uE&r+m61@VfoJU!QD3=vC=NW3veiqjW~;NLV*;Y91e~Gmwkbm8zKfh>ap`XeSHo$4x)$^qfuQkwKzrhpi~X3`?~9 zyBy8aHnIZ4E!UwPd)Kmi{{C*aZWy{~b>7!+R@F~*#uC!W9;c<_R!~@XkU&r1@N=b4 zRfgC8RDYlMW`m(q8VWn6oYHe&4efuJvHmqO5~=Vy=7XfGvZ=G?Lwo=7d@+~C(WTEt z9pZHwg-$haKoglzKKWrsYmvc(gYCXsXS$I>ezE&o)x_>9cIA0nZh^n<%Xi`^yf?8ZSU=U z&FBe#KlwMfrYmI=GJ!CcYLaEj?Uqzh^6EWnY9X*jKbJ5S8g-td)XvR9yghNMJw0Ow zmqu*%NVoVFk1bTE_m|%>l7&pSGdwQQs0mQjKqv4aLH*7bP@}S)z zOs%|4`0zDT%5L-4;(Vu?gxaO<7@AfNhI`-@{TOM5F#t%|PwzG3Y2sZ%Ihe*n`yp9k zGFA<6pH*$BJqxm-D=goqV@ppoovI{=)P_I0pZKA_9AF3Duq` zUvbaxSe)kl&-mY-v`0;)h3J8f+f1(?40t~=lv|2YJby-ZeS^)7dU$jxjXGw5gl%zS zr&jvrDM9ftV3}Ip*pUYt1TY0K(UI$jAV+`=VY^IC<3UWh(7w;%O4^}#HvC+M`tHk{ zzqWB7(}$np?-nY+c)TgG829E-it7}J2I?-g7fZy?DbCv=>=_!<+Ogn(^Fa{?bOgt#>8E#{Y5_0 z1!aJ;4VB^ihj1Z`->NUwFSqvR6BhxL-}8F=Xhokp;zY%SBKW>GaA{k*>yBI#EDdov zu~^L38AS6n&@D;oCz6G%EN=aKk#l0Z61fP&SUCWFVN3vqjZC19U}dPC#38dWut^qq zE08e2FxGyDe(Qn44_w3~FHfQ$pJ4#R5f9D<-mcgr^~&&)5XKl(>PP>|!4MW(5M`)i zyIw?Ye#pfQWqJ@|*an1Pw7py7So!#o#+kuiR#Rg?V?dc1?1w*NyvK}Ys3l%Sl3>7L zFfs-KSjPV+Vxq|qh4j>BJEopyWY{54rys%|d1(8IFg!3Mi(3mTT8AfAkfN`yM9-~C zk`Jk9EdjF@nZsYa>-scl?}QI(eXshdtI49m&=PhbkGMna(j5&=JIx=T>05|0TO}nP zGv1R#Gx&8flK~ij4Q8-%V9dtoTQM;sq1WL6oi>gCSt69e^QU1n;1R80mG~Bt(%Z=% zIfRNji$2C+#|xzQM7&Vd_b7;hinU3qY&So=NbV&uy=UQ{NpcLCySXvvIDe*JRCjX? zuJeSA`KfXmjz6WUju{z~(g0^@VoM03Ol>=(XR%G4_M)G#1n3W`l#b|00B|hAz!x6< z=v@Y_6Z=3X>Rl%vxtwOz5VGar-|!2$n5ABsN7laCmh?C*BP$+(i-E8v$Lh~ttMduu zFVfj?yd|}uxeaIDozDti&0w%faq5g`T#5H!ivfZ%nF}-joY8mGQJrQnK1DM;^~joa z0HS`S_W33%4rkEUqZs_9=w&FWWzgXt(oXczhd~rERxTbzZ0Lw|nT5n<%Lnd6^*r6= zDp=$#cC{-`kGF#Xadv*RH_KOK5*ouJS|4&6#P|s5I(NUo&nf-WU{ZJl3r7+2QeM&*zc{tQ zoaeta!-`7a^0^jPxrHhsxZm`6Dth`LGSCGuY-g$eGzv;qN&TCYXLFoFqm0U-Vwk(E z1t2OCle9xEn%f!2nC>6XXxP zB!la-F;cGi#eFylfwtc{-xl&8HU?7*)34A_2UCAk zRJofRr?I0BimaN`C0z9+h&pppQD-uMXpIj6pcW1>EJ8J8rbgs>22;QjA+ z$6eG{-Dh{QoN@j4uFkaK@zGjM%=E22uZnY@`sc7(1-{xFD=uOn0FBeus|$G#LO8qw z?_f(*M~aWwbHIy&+c?CR+1j^4k*~xua#E@?MqIb^BHwbTnT?>#N9r45>US&Z<>D`E z%j)Gp4eQ1^)F6tg_3X!rT<2R6zZG1+4`bEN9`=drbUEMXR&B1yt=dYtnzs`=UMw=w zAU)RQ_TA*}q&UO$xeR>_ol`mU$zi_SP5O6POxlx(bmeSz zH3$E0%!m18o3!qkkkuYgSwuTM4`qD5BKsWuC-fHw!|z2IvJ4H4r2`{ni-8iKcO2k; z+H&ovR<^D+>1N5do5`xCRV->wJEt#lZJJDjn}pOj_-UjCOWF_bw;{9JjDGM2{tvns zz(y4U#nV9tK=lc==J*$SH0{YGtq9w=DnATbl}vThqHzW(^m;+%-UdD}p{7>DY%g8Yw(|Uf+>q+MzDddgGRc|84`n z-s?Cc3C5pNfofhUGZp!2uiUL(83(_L{>1)fR=%gd=F37C{`6H$V;f4QffmiApWg}1 zK`i^amp%~mDj}ELe1LrI^}@uaDwV@7*fee^MrrDkW~iJ}CB89Krfc**_7vcqL(@$k z(&ZayUrTta+Sp}8>S}Lff7oxTCSVljQzY2gW9$1yJiKl$^#KbMfMcTHmURB%5F&c^ z1X*=UsmPKeTMk27YTw9>skMHI?dFx?KPD1mZ20#q5j%hkV8ZW_gIGMIB`(v<0hi=S znsg#8EDQFqrS}nmdd?CN5_TKPWvwk?$Uf>>Vak@y!iOsB59r0_AS3n% z)s!sRWaNQM)*pu)PEsuAJ3c*rKRjLWBs^sjUW}ocAoQa)$`D+w|ENf%y8IJUhz$(l zE1K724;gO9xJRHe1HfiPSWU{a+#!8322qs-Q*213wgPm6M`~O_-UOLd{PVxI zI3krRsin7n=Y-)9gN0kZS5kUcP+PEbgrTF=iKJ!NIHY}k2yd$%{Vj}qW;gn|$tr2g zv1nK0i#%fbkjgy^dYRZ3#zHK!VCjd{C?mE!M#h>k=mv&V>@rFwBA!l0AQKEnw#rlQ z*D~H2(%$`_>Hm-a-+9B#oX^Z5=fjl49GmmV`4E-E9CDT^=aexFjh37% z%_%}sC`#I#c`2ikqFOnGP9sXCeE0r*zTdy#`}2O<^K#jqkH__XyWg(jXaGRz7X-?4 z-c0tiy}V5vDw02Pul-mVcmkB+?FJr~W}f}T9+;n9~c9(}peS#bk$SE~3(lPS7?O9v!Z7aR%nTA*YU3Y&x@b}N| z_sYLIGXL;@0Wb{?86puyJYT1jL>1@0sdJEoJ7~Pm6+0UBK97F094&nejfaKhk_z4z zs8&RMDAc&oQW_PGSq}Ab``i41W;hqMRE&G-=wY3Vu4kM%xT>*C=h2ttOEohibaA}$ z`toHD2hEi-pQF($<^B=>m%gl267w}ztHLXySF5A`4}H0}zIuf;s`>H%r7x>DKh|dc z_`mdJjgc!6vsPE2*1A?tGu~KhpgU--HS}af>r;F8T+F9iy{oOCI{JTXe7enqX@Bk2nv` zLHkSh^P{m}dgdeAzT8_(`5%4B*Z$hOToL=VZ|%na=*zuNUmtQuwZHZMANsPp+V*W= z@Bh#jxDJ;Ik&NTA5bEvRL8QrN?hx8hXLDH0FK%;0DzbfZR4(=N<`{;mvo)?-8Mif| z(cHc@sdNAH)_>SBo$phIFXO&H!F_E1{?y{<=kL>axb8OFPBMObhM<0nM_)|7Y(MjG z)ZKaR;}^g4!awrX&RhTwzPuz-b$`tN55ByLYQFX3b=>_gKNd)1x<40_UdI1?llJk} z&$pRB_rLsnM~3U|a&je4?Y=Ki@7Vo7Gx@r^M0eEtwOreotDWXG@7tEpdqePmGe zey=rFp8CDs(%kWTqy7F@9(@_p`}4W`<*7eB`qJ^|YyZ#x(HFS>9(PzWVQ+I>{r2A0 zl*zZf?`%i?zuV9K68`SYN8bMXV=?vH-=7?+{=ePj%7lNv)|zks`~CU;w|{@QWBU7h z+brjKC$RXBb91Do7%-D@ z7Ak{F!654pj)Xyx8g8zJOC7)8_@KlCZXT9ahm0f)$-L&~P0HYhtc?T{!{f5_s2){GBz&|kquH~gwcaFo3tpG z2AP-Rqs9+5i%GoQxsQY~v)7v?X;TdfKgY+ces5kRBO5Vrr*RvZEjo|BC`(R^JD6=< zqSG2x)tx4sk8hP$O*N{SOiZ|CY+Ys`n=~AqCcSF5%D#6|wUoRrW}q46t?h8j&%(T= z_PZ6WQ%!owuO>4-iPi^;7?vLs#F2sp)j}O`XoTeD!-$q}AEz{UZtI zMX&u^RzLXu)uX`IXKE*|s$0(2p_03YYCbL>&^e~bPSLu|fLeaEj&u@A>jukn*!f1a zp2)z?9Pw^0^iVsnB(V`(|Ia7#&?`Py+Ns;sJM=M~1y5AG+>&T6c}S`X4Uyw8;P$

OKZ_sn49AU6M}cWonB$p~D*=q+V+{23r3{2Jg3g5G~#vl4oOK z`UI9hI5Aemid7Uz2Ft&+TRUjYLuE1D<=awF6pjhhGOU-lWAA9Dpe1x|wX}JTn5WFa zc`J4zK(NO^0o(__Fji*|iPk(pi_uYmH4jwGgNrqUE!G^tq zRI$23&$S$>(@okIXr$1n$kM$&@eOgq%sc~L{ID1^qEir3oKQxQSA84dtNS2e=Jiiy zKPyFJ{Th$c%7-eKudayru3yaH1+cXu@Sx*+WIh-2K3Ix_hr3}RO{n^tD>$mb$@Q5e zMuXf6V%@-Pv*5N`HcSm`E!@wAyY4E>eal=im^OW}^1-*_+N~}7t^i@TBi^l_$_Q?< z8_p@Sw({#9a7%icOIDe*!V>-rSc*+H>e>bJF_J-A^lVf=hR?UxRsm7R=hc!kp;u1T zue-uCN&Ab}MCB@f#fRVmDujxpI<$!9DBovW9lz~9VuAcmYG!@X87Dh#s4LGT%!aX6 zq{eVerG>+>V7W=Fo$El|1pFUad4OM!9>;^|iGe`_}C+e_Pot*qBLoc5=#|wETv~ zj+4bBRzOAiGG(0E?$^Hx?@R;6CIC8KxWw+~5TVux?s00H0Jtk`x~q(8HkvIMx~4q% zAP+3l&)j`ZJd%}OC z@}G1-LZ@MEA}w^hys`5focT&AqKqC$DLXo5f?$z)4`Dvsi%9Hv`8M?UGqVpu1^=#` zCFT9Nn>x@5@xN!E&lQ<4)&wjlJ~GoINjbdwN*?(BtN(sQ{VA zIeNbFtN|(>X)DRZBBwFwf(J5(xO|Na!C8&~6A-**lrTp^G683Mn+0JA+R&9~NeRlr;h`X7F9~L+Xs2bD4KnYIfha zVY$ObZ7@+^xSq!(gSU8Yu% zmsE+LnR=s{B$Hy&%iy`SlPe68TW+xv4!+Ft_e)yJkKP?dsq7%9I07}y3)dL}_4Dx-FGWTO z)LUh!F$S$~l*R`DO0qL48aX{ji=VaRuwzxrhfNC$6MHW9<=65xMKwQ0`AxzMW&L`KJORgtocKuBmw(w%5;Hmo`G0A3W+k z?`ptC1l;5w!Xl?If^Uu%Ihm$BHq4SAE;HmqrZT86dM}BPfaehB)W>u9*ulak#o9M2 z)0}d&=QDdHs-(G~Ao8&WJo0BsmQWsX3*bdr^|kE*sdR#DqQa|pkgwHGtmA`MRB4DEPI6%1aY|#d25>4h^vdKy|B+jgWHDMlqZFHw3#= z)2=fvi>E+608p>aqs0zH`JeeMRc_;#-EdW?o3Qhp)a186T;6f{Lp9HQ6w7~&_1jcS z=TtbpA*bTEX+jV}Yk$2J>NnM)a#wh-=AXp{i+>f15JZ z2&rm_s@QuG2#?~fqm>vgsNw~D7>fM;^TH}YXoW1;1Mo@3LtQ)|rfAC7SA5ML#IYUJ zHB%a+FTJmkm}QJQUKlpU72E^93>MWHf>2`4bgta%R@*;znstK3+Y2KO!bS6S>cMYX@3{gE^b_h-unqvEM!Z>!LJ4CS<=U%TwGRBa9B%`Jo0)a0O^PC%E8^RA7QG0UakQIdXCyIuZ)+Po0iE=E!C4KP>{ZTF6x>J8bUINGaBU= zO$&IGUe}$RR;6)12=5cc;CqL4ss7k1-Rs&MQGWa;Ultc}o6|N5Lk=(mno0b(*}k_s zz5M(ca{we_O+fw+Vs?(FtwxFTmF=LT{+b}=sWIf${ObLCr^I}O_~Fo)m!YEETOu4F z9|s`I4o0x4sLo=ZCSbYd(#Wyc&obvw9DtAq@Z$za_eZ_j1~v8A?YZ$#2NDzs2bp4^ zsaQliUT`8jT)do9;VV+d^#VzFcC8M6Dd4dwhYOb zCn3AJa3=sXmEAsF6rAQP^osu;ZI*eBY| z&-w>*nK5(qT9cLMZbroYtnZO%SU`YS$sp0a2dSn&3=?99zQ|!VA}sk) z0>9;Nfg=(3i0`<9kLSIonMor*1kc~#zlP_ZV;p(S;A4`mT#g7nR#E0<+|*i`G)ru+ zg9{y&xx0eD-niiWjtLYElrbj_KQENP6im!iR z9;kR4q`6T)x&T~#iCFq1(7A7Nc80Ulgo2&`j3=lKK}T;sx314#!sIeX4ZFOzpwBnKCvUONpMw63m=yE8|xUazRLUq za9K#vTuV_anA$nc>NOryE$m2EFIK_@^AnIt?|r}!sH)DI=OSDH zP5`*PH+^*YJ!g z52vVjZ4l=7e-jfVttb`=eon8V$I<*+N?g5sMu$dUj;2;(!LEcnU@$9vM%)reV(_HKr->lWe(NQnW*@m%z>E6+Md{A3S>o?1MB zNR`Hev(QfiTgZudZ^W69BIX-&7t41~%4W?H1XBW7Jf&qmiZ2fZgVAVtc`oY1)^U$F z<&S^2oSerBTqNlzVO|ZaIPSBHu)O6q} z<9e}=nWvjGpTxC1UI8$q z1YxU*urG(7gbR9*M|)u1r_(FZ#D$)JOoh&c{V*9U16t2<^7!*5Z~ECO(yP#-Kr#ByAO8Y{4mt-1(6 zJthW>koe!!!g=zhMgZ#4=qvbVi~cgy3CE!^5;COk{I!m02o}|J(767%d| zWA@g_x&6R&WNWm*Nx=u)N1y`14UDi4A$guVfAnqkFqf;m$K*rv_O=#;&;T@cRVo26 zjGDRo=tcW~(80{g*HTrF0$7h|KzTAyBdc4GeA|x;5=B2z)-6zFLMpJRVGrT}mcJ+f znacj&4p?vaw0)S`w=s_Fkwg~$xi(iL{0>i<%teL1dh|hCaE;uoIFjI+%6qX99jvy+ zLz+g2?E~EJbq9o+ z1ApTKz6MSeAF<4W$sga2nr(8u?r`n+PR!h`z{mOWS2TOQt@lMN2xJTkB8e8+tHoI7 ze1o8K&-T(S`k?Oz@`T(mb@_<*2nkg#d+#TOpHCt{zvB@rANKO{a!6@5i^BI-6swVS zjRlfPHGJVUGAYyPIgoV8hLUaGXx)r$t=DSTypl24a;RJ)X^qLwKge!j$n9wy0BgF? z4Jnu+v54jt5;@-Di~FE4$_CsF-Ky<)q%!?R7+d zWcvVZK>*E^`l$P#u{n{$@sQ95?wzQ&)kHiFM1HpOXl5QJisH0 zcFFSp&|wD-!4m6JuGjQ7CDm5jmlJzS9j+v@qsQFN4*r#rj~IB>qCm>|wS39FHvQ+x z^taORE0HC?_+?|;*Du#*OYe0m7@XtFul94Bf$m>PVP3jX6*)NQQ10$_DPO*6Wd-Nm zHSJ&?-}5r!Vf_8TA%v`JMlY%#YB%!4$8#vwZSJE8;pyDRnB5+~LC159uM2u;IS>-< ze=kRU3lR#6P>jON|F?7|o9^yk2dxSvTjy;buJR|-Prp`bQ@Cr@;72$s8*$u0P+#Ha zQvSu^?}2osptMloSZWoa3B5&)d;O_sVo7G&Rcn`i#yyR&{zrGfQLfNp_x<{Pcvjj+ zUA6mXsR!IVZ_JAu4z#ASXYwoD4eOw?@n4&f^2y8DrmHvsZK{!59iQtINbZ-)l*4SD z_#f$8`m|p#vt6orA!A5pz#~tu{~!v){I)Oc9h$E<*~lM3vz5Pn_5{CguZ_e#cAkE2 zU6jHW(x#sX?46MPuyr(>A1gq*H(8Rz_-?E8I|gT+OBQ-~MmEHi;irsQL|5+Q=p+$+ z1jy51&gBuPAp>FN4aJgK{DHe4BwHDaAQ_-g+W690^WXj@5%;ZLPs|WyMT7FvBBkC{ zy9Z@`7S3lwE#!UOZI3GlCK(hl$?S`Ubu1}ajw zckQGUpE-NUf#otht05zKsA#gSE>VkWOt?|#4Oog&KcrMq+bHS{? z(;HSb3E#A$y*917nxw%^n7$Lwq}~gkZQ6Si1(Q~KdF!U`9KH1K4{tTsJ!|2{T|1RE zF{U?q=!D1mY^7O_pcngt^gBepvRfj}|HhK+lm<`z9#VYke3(Qt!YBCY>w{H2+wxf- zo&}%>j|3ZrN?o3Dn9JW+s!XCie|#y_-l;wS(dy?GmD?yg(NRg;DlJf|_DhvM9j|;_?umZ;SLd8f-YpCJo zL9rY)W_m6?<)^uCBfiIw^C%{(!SSsFtbBHJa+@3Qy30-dqPBDoSZ9E*jfBJCw1RoC<=V=*k7KSi!6nb^;^}gEe^a)4bph&ZgOqclsCmOBt4Sy4_btE5Y_^Nkg$W7~qJonbIA}>(n ztmmMB=$zHO-(*>s+#C^h$Vy{vqP<;iYA^$aj7&FJOh_98-8u9Yqvt*wtib?ij|wUHqH z{_>IpHTIBB2AsdUYICN@^GR^j2Yzh;OZ~wqf2icObz*SzY^4O}_kVur$EVHq&fMOr zf3WSPS=^%Utc=aQ({pvhtZl1t_rWy>nTHKt`dy-u-RAl|qP++g^S>8b!F-n!33ro+ z@)07k8h2nM0z8@BnnV&AAm;Nw1P79-{}OAvaIj>lD@W?7DFxcW8q&|di##D+Q_NMg zFSr-|@FB74&IE`yd`2syKs(k0YVQG+KLU>jz`QgJ;&}!0#QYEdEEoV^SbAjWGh`HQ zyMHDF0hl;=N%q!zaK*b`6udyr!lLV0sD%DQ@<}JTi?a2L03qF3TS_YsfdC9xm*}QJ zGy%Y&=q}nrrJ~avCYN9_0BU4ft`ZR_hspc(@UgQ1vyco=A;KRp6fO~|cL+Tt>eTw~ry?PWEDF+pd{;5x0vH>oLfDji*Q=FWvPBb2T5Z7TD| z85}%~B<+0AXh+&SSOuV-sMc<4`{kE{pZV>=&Z1kP)ugS_OK9Y=@G(J)+RYehQm3fa z^ZcYV)xs!|_IZJn1{yEzkxti^crJ4Gp*gXt=Bg(I%#X|G)i;E|NJMH|7kvMoS^hpQ zFQilC&auMT|N2AdNRcv;2#k!xumjwsFoh$A8@ISzjf|_3InIWGh>t=^gPAU)o^eC9 z+Y{Fz&V=*=ce35eL)7A0{lY=#L$ZC#4MR|zoz)+)qF5ma)0V>=`qa{O{1xsXCQqAJ z>&pcQbII>IQJ;EC_~@X(s?y^a*q@pFA4A!~#2oK6GjwiG_3VXm%`5pzERvjKArp4I zYJ7O<@iZCU-Xa>9I}V5&3;K+IN~Ze9m=)Dg&#dL2YSCYPRj|CNy8Bxt>k>THf=Zga z=2YVVVo;~1re?*o&K5M@_nKhbRT0oa|K)cnGBsaxF-q&~-;t&6hkUlLV&@;jwmpe5 zKOSym`dZ+Q6E$={bnKdQMp7eR6i4n${`5M zK0Mt?ILm2D7{}TvwP&0`By;nA{i;dmypV`)Anx}2$4EDO6(rGNu2Q@i7UeKIH?;Fc zSQRwn?nHYCEVRM6A32G9!4_QcICd7I)+yJRbn(-;+@+;MH_L<+k5`nQA)D@@u(20E zXkBbuMD1ex?2u#_6EOE0ONV++6AGL4-be5xCMLx9RK5fIQhQcySdL&~!8=8Ei)ayOSuS zWQq|!_XOiY#`sYa?9l-G(I?vqSJ-NSRe7>!b1e_};-tW?M77Igcy%1atJudr4f14x zFGGqtcAV|NaC)Cfca3YiR9cWogk6({@9TtE2IKN9;vx1Nu+t;nz3!!UFU1i-WpkR` z(Z_sA?s-vEB0JaX5!TGpCuO(Ioz#|LPzWf!-zuH|OxnV}hq<0nnt*G&#gD8!W>IeH zm)5E=f+kDcql&P&AEpEj?F87$J) zlpJ2W??->>zAGaErV0$g&XPK_XqPjF*eK{CQ+yF=kFa589}JWDL=r+uJ)Sb1DL4*z z(;_?W3a}U!d?O_ekDAGz9fFep!+b5b0wl_1QI5Ge0`s0F7bJ1Wi9dFEJNvdbK#+^(;7@man)24kq1& zPL$H-2Mve-wKd3p0u~yC9LyS!w@14*0@NUb13A{Q9DjTIQ^`w+Kzz3G2Xp zIgJM>Zv5DU2PcCStMV7h95QCPpJhbpZ$tEGf0G9c$W9h`}w!sHJpdPo1U8WE;2*W%{}_+SYDkV*mj zdQ7KcE%xn>a3rAFyjjGj zi9l8UPBFj+|4-S02egS*>=4ONi901swP%e50Xbj@A;*D(0TJQxyA;(1$r~Zr<2;@+r zWN*}6K*WLI?YCU?4&)ssQ((T*gE8=TWiYSa&d9Z}-Ns`BGVTANWp(%@+YmLklmwEA zu#+lE56?m)I(0z3HMaoBInSpo@wIHVD9t}qio;r#N9o};GT(UbaH5bL2E4C^1OAt| zIQ0uPQEnUg{_Z&RqPXS2lDV#V(nSuP%!d{~u|A;U(I zJ9E7;5D5gY1`f9SyfoKgE%{Pm7zZrVLRR*GkakzfG^l>P6a$AKbb+t0Mh-t0V3;iu@dJrTJs2b0Ek_PQ#0Yy0g3G%1x4<+z%fCL-D2ZHJM<`{Ise7q3B zy5^GW9T&?4wF}^TX@75 zs*eRe9au7c3NGIfPQvAxqdC;52wyx{jspI#;Xbw5Mm5c-cMM+^F&k-U#AQ}MR@6l`w0wjYb)%_VM*k!p(fmJoq^Flh}V7 zARHMw4&aepS5BDT3y3}d=*#(1gkO6MI`Sti&j1fF^vDANBS0-w|Hb=ZH##EY^3PT58?0-OeOhO^IGy8soR8$O7(g%^(|Bj4glXT_@Ok% zah#${%;8OHb_W3aJE)NL`f!7;)YdDK#X_!!t>i%BYq3#9XHlvi;AL!yoldzsOAv*~ zIXo|P)I+ai7II`4EJ6U;bEMV3U3dPbR|&|!X+^Gi28r!ub$k-xkz#O50&JYD+WW(7 zm2A#10EbLCkUuG4!{p@d;zw)_H5Eqgf+tQvI(jJ}W|$%3l{O+#gACI5Kb--{*WUdW zdqTC4XSOE-W!SkjE+YG0os&o+$dC)hpNClWf_Q;TLpIdDS}$-Myz2&11MDjBq;Y9s z-NlF`jknY18FY3_8!p>bi-_~c z#iWsMoTu)mYET!ZXch-@wAKG!KB*6bDwMUYlyX`ieDmt+1ByHo$ zcMpJwpYP^___+l>IQ_cz7#MyLU{|n`8SS;bUfvP;Zq{BEp#P>fVSaR?E%Mv4Q-Oy0 z-MICw15;H8BWK&AzpFjHYL>e7dHuUOn_)v0(T&;Gm~GVAH;8{N7HOHDs-{E0zPAR! zL>-vYP0{QI3$J`J&8<+IJeZ(_VGCXyxX>fe8G7*$3sUFj^4S8^k02y}78cCn`>4z@U6LGfc>=k+w;e zoLYvJs5$LP*eT4Dy1i1Iem@gbw%X-5nQU)6PV1h+y>d1AH~&oVfK>r!RCoV=dzV|e z+i%i^iZ}l2wk9S;RQb|**RFhovPXTBv!;D_c-4Jk`i06|4TB902cH@=Uj1;v_&S64KCm(_a5H<~ z3U;^ryUsU#sHlnwQJn5gLdvLxa|=%`(IXe+AI3B|D{SR3_{?`)3}N6R;){ai&*CTOvapi)dfJ%#T$Xp1S`VS|Ot`mGuSGv^`SgUsgc z3_mrgp}ptHb=JI|+A2O1ogIz(T>^r{t`ozAVp@G;7_N6$HDwWS9qezZYlH?j z%P&#S5ZyYA#7Rv<^iL=Ap*hU^)IArO8Zro;!$5R5QN*Iy9#}|y zVSY7-zld#b-bgLYNE#A#tGBC|T(Q==<>cb&DR$r#OQ`NZj4LgNT648=bnl#w`@gFE z%XTCI6V{iUZKg=wQ(z0>){x>h`naV=Pm^Qzy2n3~4`Zt8aW4yIwDku9K1k;Y1oJhg zITZR9ULa|0HGVaQX!+c_NSVxl*R+&aa+C!3xzHA2lr`KKF$!^I3?0~J!(pFn*NStqF^4(OkARrYU&Oltp@RcU9oIOr{luqSwuCEM%bTmVOlQv=^41fn4 z7D$EplW~>F@_V}NAyF8p*)GPQXkyuDi%`%Oup>xfsKoOc2yu;@$Ot*GRCn5lHaW5A zFx^IWoeno^HxMALsi}3Q3!3TtzK0uWHRUoLX59<~0DJk55 z5;~S#uq^uVhQ17T9)~+2AKm1i-C?JFCi;ggx*8fEJw^ z7QTr`08I?ga7&*2WJrg2N~m zJF>}OQkA{aVPVL^RDI?2E`<+IhX;4t2^*#{#oLAT)NQ1srf~LXhCrT&Wmn@4)4o#q zh2Z(jGTOf1WGO}|SxsbNNbzF3NaJ2EO8ZrzA~yS3X;i->^4{=>m4xawwDpH;)({Va zRqB=VqX!6mN=H1uV1OQHM0_!od_!rnx(p`oO7x-3{a&@>D2oarGw(rj#(!3I0u1{> z@+%sn;!>PE{((lhOe_%em0cR1A|dw#qIJQPM~QKPnB*{DFhQwTPhO zK7Lu#WLqGK36EzCUHcQxNe213Q!m*lWbG!6c!5ic>nQTlE1HfLUMOOwjZAw+zM7$@ zXFMrN?i+5xBqGG~;>@zqO0Vw4KYb!{(G+Q;9=PQ|U6DC2D4P|PtA~%BET=6=kFobh z)1UOb@gwzKB%gxg8a-)=Rk`CQ&YAQt>3&Op_VDcw1!uoUuPjm&T^bRilBbic#lo0wv7Q(^9?{Vt^?b8M>zCX4qdp*>!+0{qJ^obCa zGyq7C$_%spS_w}gA}{Xd>1T!%Pw&=CQF?7)EzF{MEB6fHiPW-dvrbJ5lnim6H*ODW zt+x1HGz%XJ8zoOCvO!lzvVWK`E29q+Y)xWg?L;KdxeoqAW-cMcWnVl?+$0Z+*k4nDze-|;)r==J{g?bK`Azo4wg-GHcuXz;WbP;&(GdbqW*EM_d z9;YL>4K}Oiln5rnI2!bKSb=5sg=C8&k-e7Z3%8eqq&{uR9iRN?gq)ViLd-hZe7%3T z@-s#4vbK4?>gDR!5X&nLueN*#wvz9z7vC3{SmMvp zY;i51)3j`@M#_LN`PzGF85-E!L*csav+KZjv5nxmzjMH-8sjn%Z=K_vyEbNa>^E^WyjZl+NXwhcH_z2@cCRcoiS*LI#>)Yj#C@0`H$2;v6ZkMo|TwW=!XpE(Z-^e%1B&bJ$bhn>d#LwIb0prF! zW}fgT_VMHP-tJjmH`B0_ueX)Re)UMaUP(b&S*>1KuilL-yCN??`)lEjlXY-_J(va% zrL!bdS$rh&u|zza0F;YkiQ}`yY1W!%a-v9Up`;IxZ~z=}H7NaQV0p>LuKijs>L{%w zI0+z)2TnmpiEA%D&MWiLSt@KB0|MCC!q(+QjxwIt|0M9R(6i->>@4)@tdXO^_7RxR zo2EPD#&qj^AH0ahMN2YIU%)R)&q?tIEBXKubBh+&_d)Eu%l1IbV*Fc`02Ywf3hG0a zgxH#L<-yx{g++-&?Qk)}L6hENrgX2rnp4_%Ybe(m%T+?$kQC^zFwU&&o3RmwWXI18 znTON#H9&}PW^4~7hF8Jw1AwQox{SsK5qxs}gXYWGF7+(fZ>re`fZ#3=yNr;rJE9Oy zfTda6|Dqb_zmqqbxQtU=#3)u=wJqqgHiaNl428^*r9v*YlIeU>p3dImlk&H+D?eXy zQe|Xgg?_Q-e?5{14j=e_;CgaD%wnog?vemvlD|BWDK187pI1RatP2|{W_wC)i25>% zru|nGBPLJ)L)I1i@cqt^N;p%Hk?nSF-$uj&Ah(udmL~39Hl*mYDz!N0JvA5=kbOOQ z{x0jy<6;a5qAEINV{JTAKf{zq4&l}i0Gf4S)Y4%eo=qjfY?lQzWE?4w8KRAAGKX%u zPMxw+macea-cQ-Hp!AS!aRiFndX85A;6V^YPs}#XCSuQG=vCRQR8Ba&nDS|da||YP zk=K6DJLTBhWpoZ|lWm=JWi5MaBCzk>t4k~UWREZ@3Kh2XJ4h8bjl82Rc|jWalf^2N z&6241hiSG31lH903y8;?<8Od+ycLFara%%vBZqt;g^6yg7o!2C87v8!wM2k5ipKP1 z+WUT1KDzi~XVG`eH~*v9z9yJWmLUcn?|urlyBSoD@-rON$UO0&4y4ToMf&cYK^Bn?y&)gJ-@w1iWW%%UU1oB4J20ufG>J` znJVl)d2^=69mXLmV=2~Z*(|{SoMDPM)gV%87rr=3*3DT$SfRJhT&F zWN;D}74D2*JscNYkUi7*8M#&HBxgBcy1Zf+p=~C0?D8$!OyjZc51zsNjBUnfcSUgV zrHV9CVI_Wl;@kV_QlH?>yp33o>P$;YI|MAV$S;*6jf z%MG2Si@ddZ1y_@`vl}t*wq^G>aUxni=;4d#e{;?##Mil0nF zp_W;eR_g(F>w0&geinn}p~b8c(Brgq`DI#^uk(p}4zE+%-zSSNo)kcBYwGS%fPwOY z+hoc9(koYM`LL}G^|{@}3aIwzA`>+88rGEKt8 zclat=R;pc`)qDKqgx_KMtZ@aD!^43;tnH3ZUfN8&b7F91tB|aI6)Y)=7xx}CTR!Pm zYgeDfr#v;|By}BbG&W5i1otPTb;5vALt?K+#c?HyH0!l`mSVrnsjKVr4$o-VY(4D3 zl&ffXCmt(CQ6`I~UG-D1qwtOh`C>z#UJXqISY71)M0Fr>NWFJU5ev4|u*qaupA}35eH9S-%Q9dOJ*&`B&3NI|Pf;*d(T%&M ztTCwB*lbAnHv2}MaL(3%S=x70K{$t^Ulk*bT5}@X8pJ{FnC^R+^;Tb5+;r-s*!WY@ zejngST**1Az_ska3mIBVc3Z!5U2fGCHv2G$2TtD1J3(Ud>Bvd%S(hA@RgwataEp8x z)JHON<8Agb9VoZR!XUm0XQZUIyE%$p-0*~)r%OKzmIRykk4Ww-@mnS6`Z2M-F~ zrr8`BDbM+JtLmu!?~zDVheJ5qTr*hq&j|Q@3rNwz#_Zu8t^UqGI@1y?TLm({JUbal z9eQhj>x8lvNMq2Xp9^BLa8h4Q(1(Ef;lSNaFcSqL<5g%BSzhyz#U<2_+2Gp2HSugi zu^?#eFqW3hrvqrP1bmib9v0z?F8!i@Rzcu~uHk|Gm1lMGaP0TDMmoIvHCV$&)Y20O zU?$1kvrIh+IDP5T&8o`heDTlj3ANkG-F{c%Y7jRaTZIi)5wBHzJo=-0!cZ!>mT)>+ zy1H?GvpWSWcH*6J>Ghh-!YcpCxZ^ISQ8~9{TtGi$joMVh-x+~9Mj#wOZtsnqmkut| z2IfL-D7j-PHzYs5uGw#+rvDbjyET;B)CsO?T-OmBRufXzi!LPAZCaZyvl3|5xLq-v zAxO9Fgm5^SuQyC61=0+9Bi|3QAoOO+pXpZP=-d%mFzrI;gr~&3zd)oIdJM~Rv(*+W zEabdepbW;$paHi_@u94D=1`7Ccbt`|F=RjLZv2d+Ci2~?OYrw$i#|yo`R+1z({jJQ z@~|+QFw@89z*;y%gVRibtKjmj%1X?ipJbWUFU?YEu7Cq+x@0hCL?^P_Z zxKjAs;fu|Gsb*qeQBILoxTDs&p}F1Hv1AX=Of-9R~G3IN!>yalp7B~@VTV3)9P zuUgC^-sIS+=1aweN3$(bck;lrUu2os!sh`^vZ74!hC*~!SJ_`%X#wd)-NNdq%-0o( zq^0JLe0ebQuCd*XDAtexPpL!$imFer)PhUT^^FpIm}e-AF6$wujWs&AlkZY^&3KLe;&-%A_v!E0})v@#aSk54Z{Gb-l?oJwHSw?e03i8pzSNur*D4B31Lro0m53#fj!?37;>x z7cc8`lVU6urw=q#Se>@k+|M);rdHO=E zkOKfgy7KU<{YMKxG=U`n$rkpPmD>g?ttnJ5=pCo0!#PZJxH9iDbR0cOd{G~m_5s3l z`zm6tz087&&5avm_(FuWb(U6-fVJs^Dm*nWnW-pOTJ=DzIHidl8JMiPhtN~;o%J<9Xzur+7m25%$O8>N9^6}?5Y>!5RfS^g8r0FdTdDcnR zEIJj%AvZ+N8AQK+ZbWP0qQDa8NB?%gg-)orK47lO#a?3%%Di)(vCbW#uHqWy-yC!?G#-LJFN^ zFjDSOZlsFd0nY6OLq%oGA36;&qw8FzaDmIZy`VdB|J1Lxj~B^aXWwA|;KfeWs6V;? zpwNn1gTH^~pG?Nw;*(C>XF^J9xgTG_51ijY9r~>H%5|-mD*pS*BL}XvIjo#3& z8QKd}Me%FB{Cqh5b>_L*=W8#z5@bwOXGTbM(Y3`|*k2I0==J=uuM8l>*Z)-;$i6+B zYVqZ>HC0Ssp|`&3bXm;`s$_7}-2nEVx5hPh%w9unBB3rDtmfu4_K?3cYFLH{v9qoG z{W*jr7u>Nw&M7&z{7bcvzbFmXmoe#S|Nl^Q?(t0he;hx%&#;TR8|ISxWiDx<%w>$+ za~I7e5osj1RGZ7(8L3cdZjmGjNz&ZqQX{1M+)6j0n=aq{_Io_`*ZFJb@%UWd=k<=WNNkOo3@LLXe|)1w$23yaUqU+-ApT)d{Jaz|&T98?OurX96!%uMey zn)G_&vitMQ6E|yd?->tA{hgkA9(%5jdr75UEg?$yaapi}(IvETJTo+3g;LIYinAAR zGgP>(i$zvzWYr9rx^-|KflTA3ix>--87eKSOcu2BDD#Cs9+{Mmj^DWmW#E&64E-Z2 z%TToZy4eALx%EU4JU!X&LO?4BL5R)?p`O)eY|C2XPJVDqzGrbR^!ua1&OZo(mXdH6 z*!Gyentl-yM3P-$PTWn=&Q-!FA!(cECyu*H@Bz8i7v+JOpDIUedF z_;eywrd5^!t=o0{-yQgBns5Z^he^`5PKQtxa*DL+0ew({xYW{<`!oupdx z(}}*ZZGp@Y^X^A!KbOy2{dvM~Ut@0n2$e?d3&Yl=&S)bpwTgDyabpzEw-wT z0Orkv*lTpz8a-cDK6)u#gy0S}S*^}93g;qvb41J|*bstcjpDq2>HJ=!qEx#mv4%#^ zWuKjA(NV~7zs2ec^2Rk`LKy`I@}xqjvpAZpzk8p@m<114pgB9>e$aM?T&E%)Q=q2E zL`i0wLhY?@JoY+dx+FJMZojjor0{6MlEQ-Qi1RI!x3{Ud(dK$OqD~h??HW)nq#}(a zt0C)S06cAog@an7!ezH@aT+A3>3p7;Gr13CF1QXY;3DvxSxERS^Qb;C2%ikX*R^ID z9aw_seB}OMlC8kzG|Qa z+LrB705Xk)mSZ6}DqjE!qh(`6I5-U=(ee$&JF(RiO(iV=PyddbY~cZ>X^T=x42o}) z9n+q38@D^8=G?z2B)(cj^9ylEN{0tvBl}6HDZ8yV#F1KS~xWfJqjS-yCFh`szAgzL^5Yd`JDa=p=bjH z+Ri~>PH$x>eOpIZk@jCck?_{!PT-i$2P5&vxyyc)OM=+4Qx8u7T^5M z6TkH-Ae4pf=xXzgxC*n*_gK zOPHs#O;IM4{(ukp@d@i0DufUbxAK0e&h;!g>WF#EO_gpU1l=>lgq2St1Btdu@*%of zVhgZ6qad{LZWf#@4iR2@(RDz!CAJ2a(KR5QPD-~KBbTXFoolwYgyIkO!OZ7u&_Bvq z`lg|h=eumtiMy}+=XRCZ^6m878w(Fx+RAs3hotO*EH~0^J@Ko7O*Q^+3|z!OO3Txy z)!HUwt7N!PMnzd#oNd8}SPcOaBL4gu_C#6+2E*->RRSTP30b`$mt5sxypi{RwsrF*Vz6y-@W}{;YRMJxfwtkl~u}j+b8076!wXm*GE3gD^_M-+ogK07Ol#VxzyA4=f!I_GOW|wTn9z2WdD}| z8FnvtT66rq?`F!{vdbS3}#nwT?ah5I8d2cBd#tISl(|qu|@@&uwRcFuoX#p|wAW`Yi2Bg_puWOn(0$sKQ_;!)tzI^fM6Ux@dgS}5 zKdw%%Sr$38;>9N@4(KV-eZ3%Y3UTURwUS^#a*nN*Dgf35vN|_#PH^l8pYOXd^uh1A6@o!$iDEJq^>4~?i;3mL&$rx zmGhj8AANYyJ*c!ABCiE%?q)rhyP?pS_xd#ArTIIPP_;*XE22Uh%i9_S%j{QZH|@2f zuW~dS;i4XrV8xz&Rg%#b!p@eaa9hcK3riPVT}T=)^T8NP(wIUjSIHPtkrgmOc}z^V zCPS7eqO`F6a#^j18-Uih9}(M0gn5rG2>(5>MbZ3VtrWo$@e|nPF*}OZWX(sRdqK6Y zLkRMHQCzz0Siig}3%>2l#g(fl{sW*o00>32WacReAgH|_q3r6zWpK=k==(FScjwUi zcnfkljq@m~_Hc+zZ)C_!wUVI+Q>Lz%~$EXh7bs(_=2mi)6?W_@XlOf z!~!*b**JGy?-L6{p@Uj@^3&CXaxCZ)R+SQcDU&UAA}1}vHnG2YS9=D)wcZ5L$F_p{-Il$ zr*4AJm+Gihn(vdRfwVg_B{1R2CMDX;zJL~uUXRx^)cApUi=4kYd;0GWf#|JHW#0YJEKwpN>NLk*E+0XkTP zz!w0>+W>=zX$GB?1Oa-qn&tG*+=tnE#cvpmMIS&}%!M!~1a60oyhclkG(5jEasibU zl4B2%91Wvx3<~LYfXCl@`#gh9jeNWb8H1;^was z0D>>T`3Z+%pA3^FwbxoIGDOq|5cgWpDQr-Akf3`rJaqBczg|0oPd5o`d6v9BjE?~D zDSSK=rvYyTUgfHcg~&#J2Hs9@f7k@p;&Yv{nceEAw<+{2q3MRggb290`2tL@wY=Cn zc)f~ZB2Bx07#jIuM&N`Kk}B3H3Y$DoDid?0MP+zFGV%s8vYjvtLNo1f36m=AEJ^c5 z>KI6=T;B}uA^(@IraG2GkU$^G7QJIDdWtFfcmab8QGD*K!qE(^|7!Y=l&F+(!!%4@ zu#V9NDWWleH?<|fM%3Ct!zrVssa9d$+BO1mqG?IG1roC6d>eTbKO(p)Keg+*$sN6o zjtCn`7a~MG-{kYM+*J-_uZm*nTT4?F5kCN7zM$~WP6?U^X>{SEu}Vsr5N9Ta8S*s3 zi15&At_oEc15+29n1V^DF+IfN>oGzPoaL z(++{j0%-h@&jDfpMLS5I3nmFL|L90_BE*0j|CK%*&%`QKr+pksUdjsWtw)RsG*7F@ zrdj{p8zSjtjfw=&kqiF5-p5}Yd!ng;C!w?xk)U1H`6>AzfVS_GsVtT4caw3q z77kn3CjF?|TV`PA6}(^Q=18TypEfNdlS|~QcbRH+0lx%p66A~*o)u*_O6e@jwlR=- zq2u7r1>BaP7#is6$dXLEYjL_RO7SzgHAK2aV9<0G>?d5GSjgL7o%^q@Hiowm``3Dy zRQYPfNR{&FcyNEs}_R^+vg{9Aq>}uFw=`1YwFO(*E znVLiHg{XCZ5`q{gyhn!Q@g7QWY7$x_(zq0hWxeI5f-ObD?% z>~(9VT2_AHebrmJ(H{zut>8!jI<5LJpC$Ea5#;W!(6UZ)8aNa2v10q=PuJ!1HrIYB z*GXM0M&}(#zKU8>@B)cP0u_!R1>g{ERuw`sfc%X=GJFm3`dNT{b=8x;?iK;Qc_D26 z=J6M|vQK}@9UPQ@U7%D9A~@^2m(>u`KxO|K6s(1py}^}<8*cE@YNsqGXVWI1^%RiE zl}e!%O(RxLwkp_loQAPWhn`QOV?axBnK|a98&Bx2LdFz}K~D-%?Pp&f0t;75TGRn% zJ)(|2lIV%jc#r$dL>0mO3+T{9?Xq4O63uakd$nv{$OMxmTV*YU3_&uO*z&$zO%4)9 zSyyl{!eUew4e~X@K*Tj9wA4`!Kuh-~|Vi0R8s50gef3`-0+f z5zh1%cP_)q>0)nl@1$3NXp^FmP70=dqGaaCZhBR_bpdinssCyvUm#gWQ((WxgViAd ziqxZw3<}TKaRDz0LP5jDy3HPm017XkLI37RS~^AFIwzUO)+Rv3(>};%iOd9e7vkhRV5cXRQs{{xjti`S}H!)X;l3 zOOGxBN(a!dSm3^~Had$&%Uesy_ZckK;&>q|(0aw``x|$_=mQ^bLDeBTJmZW7mC9r> zC0_q597}261=C-9Wu|dl^_xk;jX-t(do&W{&*lBnbNta__^pLE z`0|dLeu$(yNXkA$a_<6;vGNnBvCe>rO6XxD*NJ^_!?mrp9}|^3>AdD^V^5Z-YSGY7 zDSuZ>n4=}?`zkG?BnV{)viU4zTjZ;n2~{IKaxrrAg`&KieAcHeeEsOLND3hmIuq=W z`urc%nt=#3FS(2*l7$EF44BVNRYt48nr)#vwI{%z*>~mG=jG}@%dkul!v_9C{4d-W zx8mu40xhQS&TLvJubqB&xep@WFgBav>*`S=7HSgC07AvC#V0xR4-9LLW}wdNlDMo0 zY4cR&sS=w3VC;Gv@jY&Z0=YI_r~L86y_JEH8?o#5KiG(uBb9;wR{ujAsHT1s+?l)e z`sm{;R!)2CPMRYyue+D`zI^#SDX4Ly=Uwbw+``otyU&pRyL|D->Fyjs|G?#YYg1O+ z(4D2GVXZvYAu$3VOaqX(+kSA3#zmYkv1t?l6B?eaVHk$Ho!S!btgo}utnFiyLP0AK zrRYNk6Nbuc>3iO<#v>55{`PWUQ{Fy?rQnNz3NVd+3 zsbgd{yT;4SVtyi`#$knUyukF+GPQ2cIun8`ymzBPlFV^Br_?}FbUJeFYE|Bmrlyv$ zBiCDcQPIt9kDQ`!biU4uZt1=nP?Nh}U^{9frp{wh#IYB75OGU)e%nZ_H^=6YE2j@> zEqiN7I-JJZ9#(u^8kZ$XBqa#ux0c_`d#dS7EHVu6ZG^I>(^LNMwfGexSO-OcGBj(n#WMIMs{Qn!2imePf^o zl&&vee`(K6N}ruX7#B36c;-`&iL&yaxIEfAt@fd;5KxuRQPuxV(`-spldLZS z*N)0M^MNoN^&2l;L@#+N$E+Dg!I&6mvJOi`YHjA3DV{5HH7YLffL1y4rjYte*oTiu zXTlj-r9F4Aj;akg9|+yGC309XQTdreuI4~r*qdXq>%On`&mv~)tzI$Sv6sL3|9+ug z_A-6@(Qc^OFP!BQASwUMKVWt$Y)M!gS*^VJwbT>*{OjWvsn2R%W&@NDLM0<#PW)Yf zwwgTBPD=Jjf-6+=?3Aw1AZ}lDM!bqlH4uGZ@uXcf<406|ukD*9GXbzDH5s?@`Z}ID zsm)m45WCQ>a74O0$|n2^T_|yGm6Le3q_{$+Dz(7Vi3eDiIv(5HHMBS$P{Raw^;gU+ zG#=*E;410%KkYox2mgXlS9taoi6@#+Q((g8yew$Cx{$u5s#s=RR9K}_7~dWi_JiZF zTRmNzL1ypIxu-041v#YU6qo1KTqAWeXGrfzT>kw$M~mK#?33cx{YJZ=Ld5!+BHMcT ze&VuoaxykpsJd{FuL5W`5oY`{1Y6u{*PTZKX}n}%Yqds{N$X5>3=8GBN>NbYvET_S z#3QECVC*Ir<_w@R=vk(X8{$V-ZKS%Bp#)d=Ob`B5kIvr{M$I8snnh5;8TU*>AGxvw z!jjZc3n}x64Wt#eR-NdGFzfn;i?*yGb<^2GVCTJ(WJiTJf+w`$>O6l!n7dXU!le#0+F2hBAS z+v*bdLco8cu7^GP+SAX*yq9Hb@NQAXo`(@0H%6o$$v_`$1Xt9ymBH(UFeTZqlGbUT z`ok;c`FV-$b^14=-148#G)Z3q|CeLlT!IKI*$5snA5}O@)jOm;9t_bQl^dA{%oFKQ z%`UY&uVJHjS(aGJXa-J$$HenOME3~Sgvfi?XFtrk7~3&CX?Y`5Xe5Lnbb#yfJ78by zkA-wLAYq5nCc{R9O4GFjf$WHv^N!*;`jXsn#bDfLutWlVKz?2pktWqB zlgPDI9Fh~U_=Ze1OF z7PVS!vsj|$kl=Mp)WmMU=#tTZ9p#X81+Gt}kUZ|M0Nt@lKJ6@#S_gU5&CR-U>Q;lM zGAeaic9>LjjrZlVhKGR8HWcQFqnMD)uTmo0wId)R-_w!zGwb@EZwEr|&txdhli7w< zAT)72dEkou2)Vs)K&kZCla*F()ShYduu{f!k6ecV&DvjM)>h#$*JQCLQ}{VTCgOgy zYK5=p=g560pU<>(cHF#iy?mxNX*GFR@zRie*!^2~7TEG(T08=$hww^sBvv`U$g9 z|0>DP%${m9jN2ncO}}HOkFPi{7pB^6zxFLUOK6wb-u#cdmH^QW`gnaHHOlHgv7my; zS>=*!!w;dVsR;_Q{{k_PTMNzy5=-vSx7>U6rRZnR$5UTO1&)=L(~piN$*6!dljR0p z4I}h*1ExHG9?MWTfOV!6y{lr%Kc;0^a;gy}ddQ>sD=CAzb$)mXQAcU|;K71Lrn4VQ zvU%fY{>jVUw>7;!yV%SXk5>&Csqe1-AVeC^V7;9W2R(h?a-!wze;@2NU(a0G^W8J9 z;+%6t{bN^g)l3naqlnK@MC&Lh1{0!2g3k-$ z-^%EI`e`?G=TwVore9rL@C9#u-_u=5Y46_IEy>uDs981Br}CuZ$Axsi_)Nhrzo5ty zE|Djlwb&clrp@qfF_!jYNC(d<*J*=LYBtWon9 zoidqSew7RuB+l^JP7u^uuV5rdVJj!!fdRS`RF)hBzJmp_AxU(RS`NaNV%VD%_+Uq_ zPM4Gz2b4*{J)p$!c&G--HY(g*pTRW>vI|dd%)d99e}6T9FzHMKAf{d#CSZy;MMSOB z#T&S!i=k@2zKXradOx5Q&PEnK%_*eOjDn^u1bn1BJr^XyS{RP4i_DX2jD`9ZAvaP$ zh}7w6$Qf?R+B8kJi}mVz;Gn0T6ada#7we^n%~QnMd8j5HDv|@zWFX{iE$(};pCLLoxght>}Xr=??mj7vHboh@j;5%1Co;vRoP5|NEu#OBQfuojVF`GG`&pV#qs)F5dOyQ!=w8B2w2#ITO zA$RrnGmtw4ZU}(C8Dl4ESWmOA)bS6_&=2-vL$9>Lq=>Let~R~%qHfdG=&`G<@zv<> zVz;sT{>v0sJc9WEi1iZPs9tD}8Ttd=T_fPcQK!bNBaL%rC#IQjQ{vg9?S_@h;4ALv z_jK{o2?$MQ;Fr5+t9G$q4Y`Yrj=LF%Mm{n{;PA4|B$HBQeipG?aOJo0w*9mXOAV`u z7WT;iVk$q7zV4t%5^B>f2bncgnv(e6gd!Sw;I$wK!2b{O?X7q!Rs&AE$Yw z`B~GA7bt4(2bh|BZt-ApUM6alB3>u#die@=m18w@>EZdHa|tP*km-tiSY4}gEmvgX zkVyBsXcH6FK@#esz{?SVzolcRcETI!mp~cUw|*Cj3$QAAS1}K7$mHLesh~61;_ChE z36l1Ax_GZZ7V=%JuQfW1+$cBRrvI_6^Ie*einuQT{t%fv8Go^siQ0SynV5w*YwPpt z9W{B-2`b!{1oruTnR7un9T1sZky%_*lRzm9u_leMyIXC?_ubLkeP)FxHqk2ojV?aKMT@D6zi1Crc04?XIvwJF zC--_+_E=%_TijzFlt5uf3C@D8kJ+yyuge%%3z3)WU@1mkS$GN_fw=q)nIvd}-NBw~ z2Z#VHW5%J0Ugb=IWf|3@;)>VKW5+$ANj%hZchSWaMs0g1ejQ;js2&u0D}TIa(t`Qn zf{g8PF#)k~8Y}i*P%_P@7y86(pUW)z*t4M9d&E4N*e7NU1a<7loiv6D38o$HRh0;s zET!U}1&9nFGFu%QNT_0BUdM^t+^2vdV;j7i1b1_7Kk`u6XP8A#iG zVu-nOP4>V{JZSwagh3a9y?0=ct_ z*8V=9{BSd{SW{nQ9B^JobQ8s!h@v%is8ZNjJW)0FZuTzckrQdul^2=vcJv{VXj0Db z8^F#cq1j(6D=}s?TP#Q27sI22L+uZiS`r9g2xVYw7Sn1}sk-=1Yf~ z@FS(`iOHV0z{3(sDcr$JE<+?zxyBunf*X$}CSOft-`IJinF4Ow4Kf5^&o}i0 znI=u$&YO)X6FY_iT471tS~)(bsT)S6-%KJNJ0F<``AOr=Hu|E5@1965UWQcyV%w?v zhUlCt*t`+K!IWgx@sE>>GMR52sN>D?gc|`5KTheSp5%mNTydAJa~D!9#e3{etKp|* z#Ge?Q3g}>|u8>gbf)oO$QH?u_jB50Pg25P@jWa0zB{#^$4nW!%x4ugqWyQAZ>Bi3x-<*$y_IKp*Fpl@*4d2DE=yX#|cS&pXt0*#UH_dIma9+M8Mqd4^` z^c4R0%f46W`L0V~LGAr~HB0Q3LgDG~2%|g(qO(2xkl#xw z^rA|UuI6IeXRdSUNk>Iu<*7Q63<|Q4gv_$8T7LiJ+Hb^()>od+a5DE8bv?J3QALqU z{}uYi=EF5=OS(ut9LOKuUajnPH{C-4*O88oJ@P{Zzf`-)VhjE0z7Iiyh+S)@;o|gj;YEOqc z^Pojg@QppFI_%j++Vkg9WnY8d|Gb>b`wlQT4L;i99TZ$!>vd}^R5DbROD%h9V3db8TH2GZ{v5*Cb7#Sp(m z-wvS;9m#np{3KY|=8UaO9N?))CR^dI89Ks216QhNG5t#^%N*b-wZjSCTf zfW_@v6)olomjF1A6#cj89V+qC<;zOQ=?yU@{FDE-QN69x zE9=6xMmECg`$5bPO+tiOKWcX=i?3R7UE3`|`QS z_os^ApL=BQS%K)_#@zfRE~MuVu8Zs@(k3`3u1H^=+{Xru#^3Wj5l0~F6Pgz?JTKNs!^rrCU;j6%G$DzBZdjuFoQdH zz;v<0pYQ4gHtT=YD-I_a9LALS|M&BK>@rAki_AetJBxER#hWPSYMBtBva9@1PV%jz zix$7E=3kgW@0S;^*sgx7e6u2I@F#f>x^G>iSopFWja7~%UzqJ&nGXTkG;P1Y`qPNx|m~i z;TO-V%?I9;YWS-)(hH`{r&Zx z=w(sGp0UdZ4G+J5`Rn-VRJ~h6@cp|{m&)R5o~ZADJcA)i;Z(}DQYH?MmxZbf+G$NS zQ72uA&%^j?Hi15^m-Ei+J^QyD5Uq6=nYQo7HA?a##yc(LZTZ1Ek0A+RC(A;fTYI0j z(M6`{q&c>JKiYK8rvKC6V|&xjCQnOs^@k*E_1?G39%|n(I{A9a{+#{4WU72XmB)yD zP_qz7I*FWSOL~`UXWL01D~os1x!%6%q<4G9vqNe;1&aFK8US2F6rhfz<9Y+>nfj5) z4-aa7pZv;FiH(Nl-C|GUZ~U7;F?d~K1>?=t5=5awCZPmYez-2hUdFp_DjaG^n~J!# z%xKFU*SFYdv^$v}mq1A7{`G2z>y>j*%qzW}t@LbIJ9~E9$KldLrIZ=%2E}QgfLlsI zeU2mh^O30ygz%C-9KQ%7u#YEI(xYD1GdN{fCa8DeL`{5p%F4N8W%{>FBsU2S30?NqNuG4 z9jfP#XBwIAwwDR0TgaF7uS$Vt8o2%%o)yG989OC9sv?z6a1Qtwr9KZqXr|6PYAT+1 zUE*Jp8jda`rl$2awsA*rcX9OLXHmwfbf0X+6zTp(;}guN_)E3NY8nWy6GZGUR;@T1 zeMp-3xTl!>{E>EKir|+2(T-VK1gDNh zrIhK|cb5m>M>sr76@c!Q`?flc93F2UPkC2$MuQl6$57{aY%=ru&g047&aZmkeP6wM zE%8&tz0a3zFae5;JUMnnTw~(pwnnKl4M&qRtL`2e9nQ*W2$T1yE7|WgWq0<|2{{L) z_4m(m8;(V&P~{UYDL?mFeUY?%YHR7joBCN&N5ds6hWi)LzmHh}1UWw*d}wS8y5)P7 ztk?=dC-b0eVIFfi1nW%m^Z08kX*0W`BVmz$#kgEr%x6eXjUueeRp$rz*~&Kq!$vt% zNG!KcW{I9NCK)y`G4Vxhlaj5oi^j(iYSt#-ZXF(IfW?$KK+=1)6tb z4dJmG({yhig363O_5&EXqp=%DsanKMY^j+g7>z|rZA#gLUH6Q6h*7x{49e!R$=rno9aF~+>9rzg{$mYUU`qpRM#6pii;tmUHjjyb9$T=idIKgQ@fk zUyst^%Ps4~y(AWdxXO}w`O8cgwUt|4=U<@IsrEURS?zmt09= zfh|5#_#G#mlkHFcu2MY>_p!<-qLWzgE1WRuDhnO7ENuMYfzZyB=l$lnK#fg}Vm=RQ zn6?8m{N6{+G$m_Wl}|)|3b(=fxzGCY8U9e*gd&#%mGxD z9ML89L5aLR&8xZM)Z}X2$aSz}@c1M9R$GMzrmaLCHdFN*5gCm9NQs?B)9X&$_S;B3g`*JpqCn`)mn=-v zmi_FsQNGo;ANQ?SL6TeRc}v(j!l25{l#oAC%DMU1HLFX)UGa~vpRSd?-8#2xOsElR zTs+sn&pKGO!KEW5WuFTjN&FJD`e(oKz_;-i?td!h7>5&*0Be5&#SlrO)JOTezpudr zM8~#29&}(~{Oy7BcuF!3zvWU0pLsMgVKaKl_tmsal!!93Qr!y(Ro8`bxobFy9N^|=UMb+JRn z2zhS^m^2NRtrP--XeuQ~Y*?+8`u&RNu!__IwFgb3DxhY+Om)9nMVV)zO2z=pD*SP$ zJJ(ub*@^kV`)3iAXSTm*9o4!s9o9VrLMrhgt;>JVO|m0?4iNM~BCZw5wN`iYASakE zqUv1IMaawy-DL&z>Euk)tNvm>*Ud%N3iWGWY~-rj^*Bx=Nu5$2VqvUW-1g)SLvd%t zf~1)xxjcc1JT1=SB(?#Gp-|xILaip=PG*G)G12*(YsBE} zV2r(0hFm-Hrbt4eH_`-za3se{l$VaU^<6(yGl44i!ZH&a8S&^>|_Rx`qx z6;v6Cu~1(4D|F-EMoHG?yDG?^_Ux?4HS)*$_ANqTt(GwpA=?B_P8{Fu}ogM0Yd| z5h1MO1HA(z^+i!JlRmT4oNi+o8_Xgt-IAg_rUl=t1vZpbNg5DbdegLRm9d85N>=Kgh96o5F|r8E438vKcRFh*{SgE&geAb~jW zbztW`VCTNu^6uK>_n6yVOw-#kWXOFH0rQqS=V~JW2gi#D zk`E0cvJa0^z34D+B2;ITX$c?_1rkg9dv-*19nVKbZ)K>K+Xl!&ewxFwx!DPkPxXUY9Bp9Kgu&r>E2U zDMj-mgMqlbExl+mJc19?I0k37M7c;0us8){yC!N_HoJ87pgaj z&$nyu@7ZvLuYzodFds5p>Nm`9b0KFitu5hz7&=SPGS_en(!KdI6tA%0ZjRD_e4{l8h3cUR4X; zO)y!oi+k1&J(o}|_~(a^=|7M}cjdt?nw#nQfn}!A7F+lDgL~m^4kQ*-a$ouu+?$rJ z#K7)aX42_$QP@$X)(3wICfJ1Dsu**_M&|x5xok2F^9OQ53+aipf|3C%GCM>C;N0ug zy@9k!%e?pPQg8`U*pY;%WW*B{FVz+-dO_=&y&lu$)D8ja+xoa2H=JsEax`b19Gm^K zfxAK;r{`2*7zNU10ZYwsz8NT$%YUl03JO|>QF);H{ZRR>n*Cz{p|vT_y=#~FWv%Kg zi=O?F`}MRK%soTw;cwu@XBGK*ISCX9b`+Z!DV(deczQZ7IcIWa2YtTc_#UO2jeFl~ zXLp}s2V8=!-5rWUvO`+o(aCM_`_jdZSEbV@?Fph@H%di%b#P?Q`*SC|c8%(DHTlkv*((a0ozoHs|J^<*^Qv ziFfeY%Ct-dqluYK56h-jsF!mll(f>VWZ{f?52NkBY|%f@6I&H8x+9LRr%!sqs5CHk zbl{MjpCOoCc?c<9_fYM|`>Nt2%SbD`OC?L_VnzeC$7BOQvzeTF|RAIk(EEYAu^u)dM^tm3~>`Mb|9oh!I}Kf{+8_@j?(I`8Bg~Oyi|;c1^L*lCDii~Ur!7k)Y-L(7)lPgKauYI4 z?p3WEf*<7#2~&8XTI?_~{6Q-me5lQ4I|3fP{!&A7cI>zK%#HAUy~_s)k8U;7D$G&K zg_t%ZGh&DtUT2Amd^9h-jL_y@pD=;f_k4)P{2E)#_Wc%tX4B6KeEE;a(DE>(n$874lyCf z*eE$OiC!D(*RUU=aFh?1gs{{p%3mR4x_t1mwK<s^~zt{6!ifUn|*!^Ul((Pj7N`$4iZxGQlq7w?TiWd_A&E zj@Ud%epm93JzZez&4)RhhhM$g7>Z9O{X$whn<6ChGS#&pDgPS>e^@* zLsFTse}i`IGx;Dk7kcP+gfsBS=b9+r5u+Z!W zMTdM zS32Th;|p-trZ~So-uRPhRrp=>Gbnzz{^+hDsib z+i@#|t+~JYFu)Gsv5#%RXG}kltk}rJ7>ftTEwif@|G+&z4%cYmBTosx@&J`J`3LVa zCk^J_ZpYZ0S*%Q4&)?oE_M7AS|0uS(?X&N~eK-^BSq}3VtvXDEd#%F)NPWbdMJ3T0 zepx~AzMU)S>8fDqCW8A)=L^eKoM9{f&@Z-I`P$4RM2MB8m#gMAW+#%fP|00J zo&a2kyse!q(NIF1y9HPO8?3E?j7olUeo#$z(mp%^_2hGeZpHO)1P<+yCOy zze2F#@t?sULqUeUJB-y>kT@@!bvoy@UhjnaXdIKu*y^2yDzJ2nk7`ZY7%bcSANTZv z*`1cm^Nf5{GG&Q5c}w{u$EnClFTI-o3dUTCZI2O4Vs4VYK{-LxnLCc-g(JRr#lfjn%giIjA?%S2jtg| z969#15f3CLGx!pa&VB%Sbx`g&xY-WG)&*E1wr?uW!FPS$%Op~GN_{M7y>@6n$VJV& zJ5PN7iEPIbxAoSYV+@$zZkCdj1TFh2m_T+U3n{bjW_P7SPgrX&9x8XZ@Po2AaqYO~ zKdzI8k z70lg=>!uYd=p-4u>Q4N!IC(wE@J;XOZ7^CdnY7T)#;E=CDcPoLj+!3fcqyBvEq>9sg2K!<6(ca=q_$_wJ4JM1>(p6A+7}^r65^Y-DWZLI!bViTjthcGHZ%?(BvU4Am}YhAeRgW@ zmVzP8_gzp=^Cn&&NE!Uh7GplotesTzB{Q=3^!){a`;J1UjbSff}<6<>nkgH4Uc^?EJ$7r9(fXR%cycc$B8s4rDqc7Iy$gUUB- z(Xixp=!TNFFLPaakCjrHvi3Y7X}ip%$h5G)1Gi^Im^O5<%q?T7HZ)F; z+BqJm7O|XvX5xI-E|()G5~`syE8WSG%Szl=fyOh~PZ5fA#cVCNj|xR}Xf`qx6U z=Yu(gZ35bos9gicCQqX>bD*i?Y3RipoiE~F+_>{5T_HBuEa-5tX{O|q0;9~)OzxPd zmoU~^acV9WXsLe-imDH4ecmgP$?glkf9MAg3q2VjELXbcp|WbvrrD6$_f20@Pp!eX~$7`xryl_rYge3ULx2s zY}p}+$;~l6bJ`AL@u6V9m@?+CM;m2nJJQ%5Q|X1wQkLugD#S`sKwyaKRY>EW537qK z5JnxI>#`ELNQIv+e}NRW_zkV&*!>7^Pn50h8$7Fpm)s$l)bl^y&ho3tKj8l>8ph}v zqq|18Zge|36eK02J9RL+QxHKZDf!YMAnHa)h;)gdq=KS!8oPI&^ZOTm_p_a|2RqmG z_cvLNF7?9zBMLr+L@D()*uK>Y0fPI9wRhQ2Sr9WYGD4L! zfHDSvSb1BRr2)YF_{@Ix3atrI6BnuyJXLo^nq_MO>rn1H8MC8IPXi!@Ehgy&brH({ zqmF?g5@-qm(Nk_X>mq_y1fl^+H}UjbZuKaECLn#zd^LB?I*RdMMb-}nUV7e3ZDh&U zyx_@>WRzH2x+kqk#!71-casOuj88Fh95+bl3^tUVEavj zE#9sdPciG4I`^rdV#|S+s;zA|tu?^#5t3p(J3h-bw@RvO(?~Xb=XH=q^)r1*9%PLy z^qxY3z;UFAu7uA_hO0s~=kt1F16}dEs~Zsd5;_l+Ly#D90|GC>l5;#lPL9?(Qo)uX zdf@o*JPbs*-`3P#oP%=wzC6s$#cz87K;ir@LB4DP;)F`pm#nW`nf@Y^4NPLnL>H~D zifZ`rXWc~dQBDL>X=Wc$a8>}hb^)`>821GAX%P4Ajls`1%(IVS0B%ChAb7eW-5|e- zL6;pT>_a7}@qnNHpCtrtcS!lrj*eS2nuz76e9U)3nFdyZgT-cR*%Riq+ZCJ(WVVfR z19As6L+5jauio+h*Q)&(awwQ*UA0qR5F2o9v_4N#e1DbiO8M+NR4UY=TKiRcsio zEeR4SmV^_;HY28!K+wR$wCnVJCR=>`31?=O26H?x9e)~58JONiaDi_~>dXGaKqxBW zAHEWJtoHPXg8WbA{kt(gCBhe%EF;5<&LZEjm|%d<(FZJU>i}r%OkS{maK?8pW_6U- zC;o;HLAoyF@Muzm&RosDf?Zvy(GilkVi0UxM==!swzt2b#W~5HnsFm9UbZZOqo#Fx zw&Do{e!9+l#;uREQ6@TRz5P`@rP9Jbdpq;&!GJ%$lLFZpC5E$7S-$vikT1=ZO+3{6L!uJTY_lHK z=7OP^P~C_23?E;8WCfsOgR#J<;S{0mE0(Of3dYAO06uoJ+k1 zX-$sJ52Uz3{IdZ~da^2lJxWcB-R%B~9t8#aRcb{Kab_84ksTv5BM#j|V%W^g31Y>fXok5#3IK{S0JI;^l8Z(_ z?m|uQM&|Df&fZa?;u)9;lucIsL);$DSbU0wEGIHFn~@8~ zE5-vT@7VSg8RV{_VOFSq5><2>%cDT{{4oCR^V{mqI?u{R*#8iiqamt0K&Tf;r4=#8 ztLqa_!a`!#f&ermSm|Y^rmq40^0bPapmsYTIgv?&nUeAl-M~<)naf0kD{QOWL+M8w zsKpJvAKjAV9oz3upo*kaT7HDe1u@5hlsdI@oN@eu)W`~)G(KKlYl|g!Kn+RvV(*zS z{@F1DUOD$OcW%uBL*glczz)|g$Ad|bHp&kohdFvOOzlu@m4Ywh4CA4 zI5iR_&Il(?3zpIt5W%{r>g4M-M(v-3V7$2~lwzj`Lz^Qz*~?8J#@5~!_`i=y;| zf>9JrC@2cZfkZ=f3`hw!xrsdqH^zX8uR`-PDF9c)l8Nplso^@!dK?E;JO@4!E9Ru< zxjan>d}lzW4=zJJ(ZEUHAyv``?Y%(IG8CdS6OmpkM&jL;B_s?bVSR^Xy+Gfu2m-qa zH(2d6T6t>>Mz=)=Bx}HmoTh1sHj{^F%g<;qyM4)Y?Dg(WP8 z0{oTmg;W&x+{x)sB$qZC;Y*+_!;(O*lvosn=nU%}0{b?QQv=OdM(RtmmIiT<0`1`Z zT!ss1y{3jkP* z7OY}YsO&T(0{Oz@rBwnTBcdw?WhXutyuk@(fon@W)v@5Hi91%Yk2HpC5agDV3LqX) zkW}Vs9)3_Ib65<5Q&{(%jLz|9&BgzH)r)~t+D8uRWS zmN`#p74utpsbh0KJOGD7EW;ZeN>(81&V!P%35q42s$TnIqm!kKI%=_l4j;8uYw9jx zQj<=0^TA96DgD3LK?#k757$O(*>EKd+!$2Spp``4rDv}iREC4wRLGU=?;AIFdkV zg7U2YIB3T~(Rq*9VFtL^0dg3iVI&&6uK*o8f%X{4vrS+kF_@k4fez%4^X$DZ%f+7Z z<6Dh4qTXEyV_*MEu!Fsqy-bkK)DkE|(ZdD?$bRC#x@h9H|8810s+g*Ef)yEs&?d_P zhQsxD_RlBiaSI~#n+O8qV-3f#ZN1M(%AUsP3Ui3RF> zX*PjKjfr2Q%t;ywfpG(Qf(!I{3@hU3N#1++ARV}W;~ysawZ{|wGsT0+pD}FCKmWVk z8otcfkmy6+p-mNmq7xWmwofJWVb(OfH_qOM=B0-H`ww4@JQ=;@LA%bH z$V~42_g-w1#wQZr*7wfTRBr%QcX`Dj7Ar05Oe+Q(pn{+Uu!4LSbP{XzUm1pts<=os zBOYbH2JalXyMl_wAqAxk(~Z*pjvc_#2DyNfv%p&5jgIcWZPWQr92I_oUrDR@(|o?H`w(>4A`+IvfU$!mzhA@gycLEEC8Fxyv|>rwv5)x57a4 zR{iqta{w2m>1e$!6h zo}#r+#VgGu%_~W%UTbi8h^i^rV-#~=JK6V^1SOnsWJrMZ;3=H}{=s<4Z9I!Jkma&C zrc-XS>;32FKPc1i!PF+ww_dXS0gBawBmmkGjRT@yT9zV&2I_WV+OrNaoL|gHm)+F! z=oii7|LU@5?%Ln(ih8LS{WgMjD%-E2_u0+11*;IXm@sSO4mIuU2lU4(E__;=sUC6) zy9s3SzO)XfqPQAyB=h`}`Cr>tUOD66e(ene7;0N3wx++hZtPIgOY06xodDr{^l+>{ zgOe0sIB_@+^R9pX2SSLn^K!SdR|O#z zA?J!0%F0i=D5t`nPN_%p^f}O6KX~<0*`lkGr&)?Hs9ujGswq%cBh&w4N|ca;NQm|| z%GinwC%xbG)bO)pAT@G#KtclnER$A28rg;>4!*pen2Y@oW1Pum)H@NK8M9Sm2PRz! zODMm8_B^-~W*G#a3Pn+{qY?pHBzQi2`2Noq@B_a07nfTvK~(>G*#BMU zgneO>E4w}B1(v91{K)GHc2d>r%hF(~1A=LhM!(CxEtgN7(P;nV)QU7lCbX%y<)s)5+mc9(`3gZxLk_=kx0dk#Gb9J1El$j$GfHIc4%;dE z6nc^sy6#d=cd{`BI+MipY)Y~0L9W9YM2_OqPfG~R(Df#lIVC7u>HcD;y=75uk&J1n z)yyne=Hsp)D35aZU(Rsfj~(7i-EmwO`fufbk8{--&#-gC5fzTuZUSV>PG04&wkSP^ z06OrG)f<4sN(T*05QPQ2uy6I^K$3c|L*@F7T3~fy)6i;liDrZQOKK4h{{FtYxFGVN zio)Hpgh#y^MY#QL#3VA$#d7Fz`rhN)DfFb=mcr92uI3IxHUGedGVe9kJ$*}Aum3dk z-Ar?pdpA#S6|QEuU10(b27JDH{W(H8|Ku1Lv+A%By@18c+#*epb2bxUbX;Y?E+XR8HM zH#|==h8TY~q#&Zd^Pv!-fh$z$Y$mx!Dx68Ks3xZ79szn4vl2iGJh%dgqir6L?j`T1 z9&g&pHZ~R&F}xBSca@AuE?QR^Wkk^aT`gL2iu=3J1^N(cV3+zm%5yj%na|^q%Tpl5 zve)zSM=L(sIvp7F->Q`Iv6_YqTDaV3x`9QSuk(Lw!OpIU(C(fsG0{7`z%}!ZS*T;^ zYlj61+JCJ&Ow>6udAeb5nTq-)s>y{~1?_33DG#jmu z2%QR3^Q>$)a!wF2E62f5 z>hLz5%#I{=w?ODU5X69~e!Y*t^{aKeXs#xY zoZT_B7fb=227KG>{^?YHw#awyiSNraDVYC~-&^jBRkFmGX_WnqklQTJ%y;rM>P10` zWv>RB-!;ksTp(iau&y*JsW+~Z@I~?m{epx|-W>B(G4c}6Y=$*96$1b;JIEr(@#1pl z84v37)}uAE&wF2p&xrr*zm;Q>+f#0md(;9Kz}&ObL);bXOgn|fqVK)&)X6AKg;k(h zM8yCs5S2h%Hez)*3j5ZMFUu1EPHJ){lN|+gsyEdtHlBQ;^|sT-YrK2FI=1m?-BX+A zA1u{%UJwq3wBDz+T7p9&<=1Ex89&}h2v;B3=;UqEC0LskMZe|)f1_h)b}n&hvmof-)>xa z70?bntjn1rQt-(MzngIgag((KBZU73iK#;eq=Uw|=6r+h4oolNWOZ_1k z^++yISfQ%?>c=-Dd$lP9Qk(dGbg8HMg=iE=xB@_>}o*GuZNN+S^1nUJR=~rlR zzO5h=w*qE5v?fqpMTV~$$Zg6ZMosjQs;Gb`Y{ zoq-}h+5@rJRg+2ZKgQAeqM3G=tDOyRJIp<0?P?e%jcQdz!wLsY{}+Xj>seNoCw^Ba z8VI*KqPg4Z%G}64Ebt2hfm%7!JcIfDwEA@C+YPq9nH?d4f}SVEhT1I0-n*1HBFCC( z$tc`OLU%nr5u4qF$iUnI7Um6_uuPl2qoRY@z1v^D&;<&%mzh~FO zc5K4-UdgZz3P>JNn#O|Ii)Zw9z4)?%M!|2+7Y>tES6%48QJEU=)4Y$Z`;SzgC35yn zCkke%50fR@GQEjRRMz^`vBMA`d2D?{T&EDUF(>ONZlF)E|$7OHiqv zHG>$V!W6)l;wd>I$8%|&(QXI_VMS?x|`hJ&53~;g63g{ zn1QJ`*U1YKLD1CwEk^5S5anOn^!9dtS?3<8-JJ9fd-*DEA6?V8&?X)BYGjCK7W-aS91)+@DZBNDN$d3uZexhf0yx^&Hh^v@#BA=X;SS5 ze->dWH$(^#^>;rX*`)N-ncqyCutl7U@@Xvb)Lt~!t?~WC=W*n-& z7ILCzcmQzv-D`XErx57+OOD@ZL&_@^-p!ogKbwr8K*r$seg3N7mj`^lw-_~A1UOrM zz&HPZ=&$<^Fe);KJ(d4@pv3lDME_eQ?!bSD9O8sD`dhvJYE+3Il=MT0o9mi25{zZ7bPbBsr-_?1-drA;PZCE5t|P7I;(eo z1weEi4o~LcuLNN6e3$V|)Bu151At^bb*_La@`LsQ|1Hxq$4s9N9e|8yV5S(_Pr3j8 z0NE`901X5e)*}jm0otS^_V+Ctln1Q!GCAiiY(HRUPUdXZ^e~DR@bE8+Df)lwGE_YL ztb2ziL(*Kz13X`4e*J0wE(+w*$OXV*M8xK?=wa$Q5qUNXWq;X5c@e~Qf10OrgEn9T z@sa`YdIs{JG@Nf5c6a9A{tOS#Q7Xv-Mm5V%$^$55_N6yi7-o<9CUxG;@O@|l;bv%Z zyx5p57$uMSO)dDP4u1l2gs9dJ<}s&-Ge`dM2-iHu`ALBV3}4_$@d@5Dp8ZX#h6{eYSFobA>p0sFuLp)q?On;3y7|`_v{U*1=21$aEu@ zM;|G~Ll5?DhiqhX?E*!yrbtXOX@mzb7@e24JVwCc?P9-9pS3;=)t*x-7SG_=w+A=IMZ^0YaQIZCp>jovc=}qU*r#ctz;RX`ws%% zmQ7TH=jxqUEyIC;?_BwlR(nC=3g1Jo^{SaLN2XL6@rrfhf0g= z)Gr{_l;~eRLlGH_L#QED4f3Wrs*VvzKMs?hGMRx6entazb9CnCPxs@00sH>yW&sCgC!PG9VM07b=SBr^CdI@0O0E?koHmbf!g9a8^TbHb>aQe? zQ1wj-pd?3_IGZ)U84I_CHKzX7LchFKnuiLI9_c8Dd0uEV(~OBY!ssvDpbIt>Xt$+c zvHNRgJB7CR)MEOj)9U@9iO2%t@YF!vm5HH(ymlS%h?l?n45)TQp?#!fe8j8>u%*It z2^MO}R_X5@>f;I#GsFYdhyxH2WaAMg{9O(i!VEfL{_SAxz!LU5Twx2 zBgNZX^cejDe(9EL_<-2o0oee{n>QB_%$Or6E62=~jqw5Zr2qc+4HLQ!rzQFm{1ou{ z6uUqd4Nn2!v-$62j7pe|t*a98mxY@tvz7gc+kevTp4|+C{+_P_kp+*S0eRk@uH2z4 zZf%8jvE6RJLGH#7Z>}SoUfAK`iQeGkJ^l0h=5oID9zNC`9?#DGeDVceuzGpBx}}_d z?_BhxMpBB$&XJ&aV7sDD&KWlTID#Z1P5(ksdoRY0|2lC-GNT?(5cgsBn zHW#+$-&(A?ZzqqU8ENm%AOdX|>(RDRq?JcLPt=H`> zZ2n6w*-PIGFE0L3hUeuu(}bI*SaP$pM5WLZw=20<(D(ezsVi+OYG2AU*&e|Z9p1Oz z+_;e0E`A`Oh;86|@NMZw$%1fvD}B~;c=mx&^@&2-*+UU6-G|{qFBL9k*>FE?xioX* zw`?M&7BymK5r=GUr!S)|kE7Fy1TN2QtVUA(bb7!jJL4>hjdwR~x&kCN7`sUA=ZKZ2_u9RmEE@t2Rq6-L%t(N906T)J?g>jbCj38*r;uzv4%} zB1gFk-4txSc_-o6z*E-ivm-OrA{mgp2)fuhP>tA?)F^!c-c^<9d0qS`aquWtc zTL+Y(>}YmAWc}#0WXcw7211E4Pvqb02d$(|0t?I1nd@ z*8<&@0P^+Uj0&B@1f4&R0mr})#icu%#pyx=Z~&@PhQCICrMx#%_eC>c#=ZsoJGDaY zjI}+SMhU8WUVUboY=7D^)ydY#cNmO*L3+oz$5$W`tw@Nj{;O6F{8a0ydiZs|M<4+) zO%Hk7)4n(TuU0jXDW~tI>Z^sA!Zj$r)y2 zKNerOu10%WQa)B)u>I|iVWiY3`_Ihx_G(ds(i82L>KK(*`f$R@Zvw|Ezjzzq1`)5b zx&h$CL(O8+7zlj*1fVc;h2y6R0aq?4Z>1D}@0lEqI{|Sl=b_nu%QRNy;ZcJk=Li|I zzWSdYnr0N;@gvjHA77!*!7cF6J7H%B@F#^jIjPA!0|s<5_#b?9)h`7u**)4?epbEG zz4~+bs5HxQA&bKt@dkJZ`$!zGgljDdtDVJPoj%ZZoYwD}rswXkXSG#+J!iZ<_st5W z`g-B##)3YJ|Ho(#U=Zrd^?-TYtm(q*;mFB_;@Os{((<;uB!zv~Z=;~{`HcDbnAb`S zngWR1C@}X*+pA%}(3IaT)PrEH^KO)hG%R^X29nM0=fD?g41 z{`#Ek4jx~J(`T&o@{UX|(Y?M`F>&0m^)Qy5y|5kQUPh%GdC!^t z8VOEjSm@n;!`$otb?d;|!wDy!vq`k1_RCp{__t*k{K@;=H|gqK_0tb^PTat}P1~s9 z*M;ADq2H8QA3eU(1(Gxcufbx@ zJf40Tn8{IYdN?cLdY5qHNAg|MD|+hd^CQ81G_bzF>oeW(=f;;m-04 zM0^TNz$kX~7AwJ!PDJa}^N7DIWUn(!Qgnu=HDgn_v_BGBIbM)2Ts~*8zBYPCey{R} zO4<|cQqJF|s(_)L!5A)BDq2(lz@K{FuWEqDiRzkBD3}!b0GKdD5Q|K(yiwjayNA?N zHsTRb$CZTR@hZWJljQ-U22S6 zUm}11^F(jQx2X#441{T4=ic12tH$TWB~Kj_Uc#Gy*okdu8NR;vBCaQ=+x+1orISzn zb@!2BLYQ%%`<7p*KFRr+p?29mJ-6r{X4-GkQzRs3pBI2E3Hazu5eb zey8t#%UklXxgLcNoI&+8aw5JYM9w$&G2x{U=~uswzTeMvw+M8%0(fzJ&A&1+M*&fH z7VeX><8|y~`z}afT~xxIBgdu%OK8ThwCLt7^F?xgSq|52$+u_wG(vUGDN^Ul?!|uR zAHC}S6YJ16au2w5G^>XVJ)Iz@GF-{m^)gw-EW?A1vrjT~i%s&4mD8wdY#yG(eHUq= zasN{i3gG9SOWEh^u94&q5eSPBl3kIx_3PsatB|y=r>RtNr@zXk_}{v`n+Z(+qBp^7 zH03)ze}&Yv8asYnZ)DH*On(25%}hgw_7mk=Y=X#5Dx%^UR^WZ+`mbL-2Rkd;n_A<~ zz{vEqhcaawoBH$pg3yOgx3pt=9V~vnUwaeyYg=)0dN@y6kALKD<=Xo9ml{RRQpmRV zFyX#)b#6YA{SrsHEm+48d${hwG^TGI9WKx5vS;!KPYuwc#DYywlwsnZpAE^~;C`$t zcBi%nyPVl2p!-ck6kY7oQC+9c)hP1tTYd&6RgA@>L&9oDX_(m5@!Dmr zOCWtDg<<*lsf84Lwq7Cn%7|@nS4lcwS2P^sqSIdA>C+p;@5Aiom6^{jr>B<`K0nI- z%I%#>_(aY_lj7NJ(L5=wy39NKCJ4iV5oPJ)jKEH20mREueR(}d7Pe`T`|qxvjM>+` zY~XVpq}V(01oB*~Q+JMMBBSWq49V>IO#z^xfP>!Aqn?T9(h+0tovx3I?~aYo!CZ`- zIZsMPYYLHRk0-_?J4!xe)+*E)e(-TPDP5lU>T$_HLzb!gWSv$-v3Jk(ws1k&7v?&( zrLoEIzLWC9Oc6}33vhnytK+FCi7Li_i*t8A6)F!LPk@q3+tP2C`>*I}(CwNEv1SEZrw zJdhyzL4(G4;YX0=Yuqo5ajYGtiYh~$<||};&RN5IG2cRByt84hj+TtE#K@Z0igb*e z(PnGDuNtmQH7=1teXG2~Yp&5+eV0)&(xpYIGi7qtp}T4RZ?%Zue8nrD-!QG`QmZ{d z8*juG-<8NJ`7QIyLv78t)x&n)XhKtS@Tbj&ZcN8=0UAMQwZDpLRqo=LCa`B$jc{3`qb1zNEh)EFX< z%xhF)2<6pJ>RSjDKxwxl;MwQ6jg#G<|GA0uWc|TCA-aRloQ~vxA2(=@j z<={PKm=o)7j_9wjWkl3j6z(q27`{CvK1YT%2!VKytR+!K8Sn@*^@X59DO1g1H@GyG z5g@st3s@wX#rl@E_?!CN4Ayrl0szJIo(V2BGg|<4A#dodBuyQA@1C}WxzM+=&_(ZW<&j?-zCDdS-~09qOD?`!k;tl6Zyg}qSg*A` z!COFk%5F8KBoGA|N`!o5dQUBpISqtSe8k;iV(qfR+_>AMFlVBksAi>$J|aTqZnbi5 zn>`m88ZXc(C%K2K@ZB7BWvRlAEE>CBCv=|sk|}0VIq-;8-uglT`da@*98_@b>)9>M zJ!dyVp4r8tQPE+Yr}Y`!Y>Qf z^1ZcEQK{s6VD87T$sXJwMc1F;3CcW^lQFTDKRMWKDgZC~s?~Ng4I``hbgoPHuiOIq zl?nHR98;pnhb=Muht$i*sTGr#RMRx+S`SS-Q^6K>1HtFK+Ri}obz*{JvWBHC>IH0! zeQlkuV?Qh{ge$RoE%JvW;LC%h?i_)Fx-n&;puaf5REj-~wTJ2S+~LzD6wpdw*{4Re zF#B}LR{?{ZKEHqVd~5#wtN-FxO!@Gnw1(Ar&HN8aLCK)&fL~?n=2WSnPPxjg|6yhm z#jHaU8X)Gk7;EdBA%hA*A5VOmO|EnbF+Ja@^K_W`TH;R!mx!33mSoR<5_Ux2`}%Eg z+WM<~ZF9g%1_f8@tL}r40StoNUC!%6Q%q)4wczFM! zR>n{S2%Ux{0${IjyoN?9+Ns;Tq49`y00kV$k;w1NSZ})F1+c?{-?>$>rZH&QcUmVs zWgiBm)upS=nFCk#U=K6>&;d9j1lh>Q!^@eQ@tvDo=!<--*rN=2yDcX5^eV30~_q4YeA%(k&5tk z;k=;-+J=hH_MV^Td^~^DqScd;-jw?g0>cA-Y{f6B_Ck#I*U&Ur?kjosFS z?0G>=*#-luiN|8W>m4?_j~A{j=HJv_3b69lk5ao&4@Q?3@?HwyHO#GY;O7DMr zzei*dc{(%BU};$eIv<}NXv$dYL&uM7AgWnt8uvH1H$XFnoyzPWy8)Hnt7V5<n_RjRXNBT+?R!_N2Mq2|QC|9~o z+r55~R$Q3j{JRiic|Ea0jJ*_J&{a+>(PX3R?KOoL0~dV%$XTsbQ4me5&OI<5q{f4q z@gI?Qz`=^uC`PMxYqUQUbo#25?Ng}+3zj=7C6)koC!NA#?7q7G=$%XRN7vF|zyI3` zrf&xbOroE}l~if@2~v`v6^=N7nOd>9Zxmlj-{s`XHy7nANVbu&qvN79v8=j85t9w- z+mV>z(bi;ZwOk4k)&_w_ix|G2E;<$EJ3IVL*)(EVpXUSlbn^A)YCNvUi}xjwS6|yU z*0r*JJPvBkqo>+8<7isLFIe&nr&(5C*xaegIp;!0dNhPq@WUK6GlcBSGt3J!n3oMk z@-sFq{S}e*ZyQEb`0bj}yoyA}_p{Cv-}VVZO~#Ht#9dU!9k}ja3Mofk>Z&?l!m@<+ zxmK3tHJq0%niDbHr^cxofd#g?U1QT5JwI+seQ>YEda6DB@R4hrDZYu5kwYT`Ww@m7 zvzIGvIb7hd|3_5Umi*M%S|hB{_HWKDW0CnLVZ~`$<=g*s8UP={sN0^;fANE>f9&(m zY2?xK9g6b4L3W8h{#VH>%$=(GU{$fUOht9;nv(={2nhP9!$nppxkl@9@B)|V<9!nS zE=2OB@g(=U_MSUfRR>;C8@X6M9)2H4SkTQU+dxY4yQ%6|e9K)N|cgmAT z*&UXHTn~sM5vgbVpE_lYFwe1!HLQ%UC#%3bJLhZuDpBMw}dE5&?>FG zXI}dD<4F`X?f2~+4JX>yf3e@clk2#Asi*pRBWJ}6R|^)T)rhpnnae!nDzDVHYj214 z{*c(Gh^LTf&tx^mfRD`@M%1tC_Eu4@aFcIi?Nc4_2ly(6`j#Q|q$zN>M@`@b@hAI3 z52)edu3-1DbOv?8XL`w$vt|l>zom}+Ed9x8!_6M%PhXYeXd^d+Kk@@g0_eZJoq464 zuL*F-dA4!$j`s311d(;mhM!%Q;&LtJHM&1Yu7p8QySDsO(RlSw+ysx-wApB{@oU@D zw{LWRzPv>QJp6@L@M@3q&6iKXQ$%4XUcy)}S_MaIh4N55MFnwqme|1vta1wMx)n=z ziJh_Hn`e%WEeb*uCy4hXNT!PL*17O|Cg3gT6)5l1%ifdpkkwHL{s*If1E6`pOHm?% z^WO~3U<@mfHTE6rJtjy+<(G*=hDv za*k{uN93c3UvkhNNUkn(=vx?xEkHFg4b^C4dE6%HF>Kjc3C&J{I$Y8puhU2ra>XCg zk$5Dvvd~Rpf-M3ZtuqR{SaOuAAb*0QTOj2k7Tkp>{@EF4rsKQ2-S8u4S`AE~bfxkR zUkH7h(CJaya#%dXJk2CH?Qu_+Ek{jC;Gv|GpxI*)huTvhO#1nU++Ot$FWRMo*8bou_gW>*bd7S-g{Z ziPiwBK$1HJB-xtB-2ll@Nz<)2ld{Vfj>;FiOc=(y@PEvgPBRNW%jb7XOlJ)HQGpaD z7D6{r-VtqFF5!&F({xzdl()H1+$gihVp6Lf*CC4amR)%DAJ zgDi-o1^4KUw{lHpIY+Xlxv(GS!hT}eksdxYX!;RUcmxBb!xFp`ZM(rs_Y9DRZPStC z@U@UrEhqqJA*p)Lgv3$zkLq+QyRse&#Kw2tr4x>3$uDWL!&c7u?C_Pa+m~p|Ig;@L z)#tdcD-6kyfRdAF70QxI)zT77X#uX3Y&MHoj{DJLB~Z!Z>gorz%(3nraeVg7sSPD1 zh7JUM;3pvj2ul?N228jcgq@f;9rHH#z=}B@(8!h*?>%^z#xpwR`2J(r1kpVXHXDCn zO{u(|hqwYCp-sptF+~=ZLBB1QtFVV-`)# zr|zquZB!Q@%ctP1WK^q^Gbq4N(1#U8T(=j@fY|k|X?|k#R1)c)92WYzL|uI4x)XU% zULPmddG8*d)VvnmbvrstNh^N_{i7ASe+WG|OimXO3*(dO-*`lo$8uj)>pK4t4AKw=@WJnNmHLAVGY1(cJki*!=;;4Kb0E$?XFlv@JMB)0x74DSMdd~KG zNKjovVV&Rjtrh)-I(|iWH@{$)2A}a-*s)*vxRE-*gaQD0Z>^hecw2tSk9q|52NVAS zmqpFjSmMz5CaJM;ym6;UsA|CRV>08*VFxmYhBBepmeU7YBR*@&jnO`hDg#DiVd5i3 z6)r)J&(ckqsadF2DmK-cw;M(1IdNY~o4@xpo9g8c9ft-aBvLbZP90LpMzi5~X*MvX zJJZkQ(y2=+YpE(x!5_6ei&;F}>3^c=s!=H;@f43RH1il4jXr4DB74jt@^qd4bh<4r z0=CymRaocIn+pw@u~6gC+CzDf^U)&?X7hZv?d2&efW8)K_;Z*+Rp;w>j#Y|$X!TBAV}$e^ zV-A1S>F~r?H#i2tj{pPcl71LBTboezD9|do(&Rn+93gla-(~WuYh=go{IF+0q&J0$ z{~yM$*(;-Fz5%Z&I2rov=}B({S6^CJALDXg$Z6kT(SP3jdHdAOzZ{z1#q^IFvwWj& z8T`~g`MaOeq5o>I-;clL-wCbu$6}d8vCzENl`|AgL}$jEw_%VMg>M-O&U2yj>o&7m z#cR`?8SkJ}+S=*&Z0yC~P!OPRFs;6oG&Ka6R2b($0+dg!wWN}L>k!JF5p~0ZMmU`{ z4oNwTe8X7){X0m@{XHt*pt5rY*BVG^hU{&$zdbUZDFQIG7;30|0+2b>RYvv}R68Ar z=q`NJ-wPbvgYk3^8&L)hbQTV%EE0|m34FeCYoqD0AvE2bfE1YS{U6Y;yM8kfD&!SI zwF^TtZD5QfV)^Bu($=6nU?}sWV>s&OS~#HgnsIU2&URy1ICFq(pkYneX(|a|n5&eE z<-REP`&6qq&r&8ZYV>Ou=D#`^_-BM%b_7YZ7>V$8i0XeC{XKo{T+zzy2G2nE^WnR# z4x`SJ?_N0o@>da8NiSz*pUEq~+2d>;do|wFpYWdMbu0XRdn}BVv&CZR<}xpx5GQ9O zfa)zEg_4i{;RW8?g{pg+OH_{aj|8WuC;o@=1k86rNe8D2;j-<5{zQ58^{^?>c;y_@ z==s1-vB+DcP*H`}WLx%t$VnPfjm()2`ulYkz$Umd>W(?BWuG_siuZ3`O22h7r(E*5 zmpsShydb&SowmpHu0e63dCdlL^Y&bF7QDX3v3Fv5DWrs`9q));IQ^p~jg||@{OG$J z5Y#ZJ^k60nQecfwH7S}!$k9YpQ*=n^BJ!6exX1gw&qZ zW)-lZT;-6<2sdp&7FI&{n_%{6Iu1DJ6K8F42iphliV@m$(jxf*YfiFh&q^Brr%3{D zIh;zlj5~~C8$Rh5dEKw-Hhe%7SbN)$-Bpx6zp%=pfAQZ#P$!JWlg7Ty&Gv={Wtg5Q*HI43>2Y{<7!rpY04eL>ksK7RdhJr zY`^|~w0B5Tjp^|4qrD0g(T9_L z80GVNBMV9P=xorKPcJ1=g7OMh9X4Q#`jppa&>vDR$vyk^yE+WI-!(N>xz zZP3_Uo_{+OL(}$yOKy+wrduT5unNj|_HA`S*<_4YajAU2`+7Ex<>&hwG{I?jGq*5bNIVrc}0N z-4L?gth4;%LZ0vnZ#zVOnW*XrT3~sI)o1hJ2$q-|qLSnuak6=LIOlI`3 zmKR?KW`||~+^?4K@prKa)*y%#|2*ekA=wKt4yf?kJxS(V*`mmz8I-{eOu7&P92=_L z5M<%lHj53lO=jVO3L~o)mY@wo|B|;ZB@^%f_YEPWL#l&=5LBJ1>bBG}_7dkl>;{{=Jj2-o5uTcEs-)Dc`+ts#65jeZaK>E`uu zUl3u>tN!&NTg^O|j483C;bFmkvHK8=5B76^5|#{o81l7yihG|#03FbgAW%pDw#@=o z9te>7{>cI{a3P(45Rbp7lrQ@4NBR@mEzp{$0x z4f{uUMT{73;kR)g&aK-wEZVYX5vy&8tgHcC{y0%aAm*RB17ic&@%PW) zs>*h`Y9`CsGicGI|4pN2Om^{Ox&R8e&W!eSYKQ)i9R?8kA-_mt3m90dnswx@Z5zw& z{rj%*!_T8Lv|css1M4k7z?&D}S2hvCVNhlrn44nXcb z@h~B5A5IJ`3jrDGxy!%$8oE!rf9w&EKn4%&%e@W%BX70V2>Yr;6HhcTfdmL(u|*eO zgfT`LXQZ)48*juhM;&+Mu}2?&1Tsh)iy^W|0#rOvNF|qKvPmbOgfdDge@t=37m+j( z$9mu?rSGga z+M%Z%phPNX|EDr*tmhmr)eLjYbX?pL9h!SwSDh!`g$D}r-a^ai;CmUuBA9-LF_ zMSUD$FaagF;q^GPjD-TEEZD(V+$WN<6c9&5vlN(y0B-@{jMRO8O-_s( z+kH3Q>3pNtUgYv6wg7Nn6qj5UncEDPQXh`wU`(u?qB{k+VVB>~Y)p7z7aLxdx$XpW z(Vlzh>!rnQJ_H~DHkQS)S(xDs`B<@%ExBUfP;OD>0^xd*A7jo#4~0w)6KrCA3PCzC z1JZCc|L1Ub9+zeUjE)*HrI}ur0GnZskAQuV`&d`CS*&txx8H_4Zn@`{u}CAa?22x^ z_vX8AzoYzz?X6UV5pS+|YzLcB@URM!ayZ)2moHP@1RZ+flm{Jc>|_bg9P44n8cS&X zvyV~Ap=ZuR$4Td%O>I=1^rZsP<(pFJ`6(!Eh`JG;bjAq>n{afZXW|&`k*3x<9-*fA z9b@HO`Q@ouN1oUJ{(Pov=5V5d0~VNo2s5V1Rob`0b}=8o$l92I)sP#{TDL%)nAdC$ z`67ewFE~PvUN$wKZqU~v^}UN@1gMAhxaU3aiI04x`paHOHLz!4s5$Jb7XhS&7UP=P&ss6q{{Ply~Nq7f&C!X>_lSNqt- z7rb|X3m{<<=O70Zm;eT?v4~Xj5JdMJFaZ~6;f?7_q5zH8MFR%SA81q~f!g@SIL?t~ zR=i>vb%-w>VlPO6BLG(jXGu--QZTMnzkct#G-~p>}RI?oG|G3oP zWZXge0L`mdgLtcyr$5Zd%b>~Vh=at@5zWY}7csP<$6FLc%caniS=5diohXb*1GF4T zRGtvk=tJenBY)J-cq66ajZ&J?h;p=CAe|^qoitNB)--55{b;F3g;RxQ6sJH%sZb?4 zR34cWp_hb;E1x=5s#Y~fqAUg}p<-38cGatUJBn0U1j~m6sT{wsC!hi$4RqvcNAwuS zCIY&YJ`92wMd=Ye-cgQX{t21<)T^hgp^MSg$|dhq2k=CqPp8HRbgW40|1mA`3)ZEh z9OKYNIIby=(brl%A{XG$i99q#s+q{69hRa-F)TsQ zI@EO#kuAt0q*0D^p!2K8rK-t3pi|`5NV&{yZgizPT`KiNtklJBcISpwt(ru;-vuvq zt!t%MmeRXQA_i$AHI6#!$R6pSMw&`D3T#Y@NA%zlYwx5GnaYD5o|1+&o>AD+J)#!j zkceW(!49{|lOEytB`^cgPT>V5C-2Cn8B<~nUyQ;MftcJVG`mY1(IXwG;O#{QF=13# zgBs}|lswMyI}Uqz5OX!iBSs5cf&}6jrwwnA<7SQxKqs|ACbE%*|GZ=-M|ZqUhH{j1 z#9gvtQp#7xGFTsS-6{)-9pe~9iV4yORD7cyK$6HWEP-PcqkerY@DuTUKaS+uA(ZGI?9n{x)FRIVQ`FK;OkC|AdEjo+HCInzMd8 zcV~Wfir(*($63?e5=%%!vlc$+jq0HeYSfeCbs)qb9x>tHe#zDq7YcDXYooB&A`o|f zyF~^q56Ir#z@oOE(4%Y*cf=qNy@+#m8Si+=E8g;!C;H_z&&i)RWb>cTa^|me^dONc zDQiMSI#?bgX)rxiff&b`bCh*(Z#~}pyzQs3@y_DG|Kk@`Nfj=C43dx)yt!ncMrrcGK&t^fnLbRUwq`fKYk{Qp8V%uTj#Bee)eP6{M(+k zkRsA{;0|IF)F8Ez&|!_*cWxBcXg4l-H>>z7dCEOdNfZdFhqKZI!wM%%**-#%IRr|H zN0~l@3$>8o9hpiAU+BLJGzda?iQ*wVK*P1XTe(g6)OnJQh(18814|%=a!|tjVnT%AI(hmD zP#K=?D;KyzE5kyCXRwCd(WePyku50)YmmA!w2CpQH2cyLe=@?rt1DI5y?rXdKUpg@ z9G<;1#9}nYW1KETL`FWOvP@dPWrRkxQN~wtMj>IQ-C7DE3y2_ z#e#4`hpGuo(=0En!Y=u{*Bb?35FT_$LH8m;Y9NM9_{K7P?5%*c+sq$81pE6F4!i8>w|xqXt7 zbU21hBnVXK2HB$#ciY5sJf7bH#Z`O}dFX~(AVYyVMNFxlrYe)LQ?oZz9=SWka!|@o z`351}5mM{H@Rujx$cm{AF#wScL zOdAPyY(;-s%*CWM4P3dttjuu$%vvx=z#AyJvjkPcOUCp{qOdIDD~AS)C@35UYe38$ zv$fx{gi*lDW1t3Xs5eb%MR1UY|I6gGW3YyCAif1-#kN$=w6;c#MhjcgxOJUCewUK(* zE2iYW83oZYHBEbE6e7=bvI(>Wc17dQen@PzhK)3`}f7a`FS#T|4& z2a?D?RicUD5jB|f5jo+~;n|5C?Wo+bCPJ}L8UfRJyNT0+QW(K0)j`7rD<00|)F&J& zy#k7qi>GJ!^ue zO&M4v)H7=>3U6%@|5G)mF{Rj&Qdm#XKr*$*#6r6##n+J~*^+Hn8dNr1rPq~>0Yos_ zVpOI)!z|4r31vdq{(1*OMc0Zlu>ifWY>J2p>{(E0N);U@bod5JqsM8DM4A8|3JsDd z+`gT7*{ZeLt0hZ!#WH(%(+il_5#Rz%5L>ZT1UP5{I+X!E#ab7HN&qbfjAg1GiHK>k zo{a6Ny)w?X-L;#FGn!Z(MG=xpkwV_HTbUw4#Zp5c2~(jM2a#Rd$A#R;?L)1-GJC+) zuRQ^OfsuH~gbs*P5UJpnslD0`TPCRl+uZ2?T!S>v_2VC7bi z{Sp5h*M!a4LFHCR-4c6S2L}7zFICpX!luHVk=3OKiC|oP3KAF<9)`r;{MFz6T{g*Zg)krUQMrP`V%)PmHxeTOH7)RQQa|H4uXb6**e6M2va0ThYiLfE5lMuq^_q;1N_ z9N{81;v<$W|6RN{9f5gmUW>|yCiq$yXqg*g;1h6|9N7mtnBFEPftb@Mf5?VH(ABRk z0Wb(*|0I5@^yQnOk`o9aSnm~8815%^SO+APtr~VL*@B04unC%lht&1cp7`N^P@S95 z2KrUwMP}qi_BrI`HOoDN0FF}vc9DI^gf2b-ks$zlXadh&ffP_%8gU04pi^Oy5q{W( z8(7&1#sv{}WMy+Jo7H0*feK|xo%n_0T`AppvnFm08E~q52m*?Z0X$nu695dk#M~_K|uv=_cujb@1c!oe6l@*F`Cj zE%_bZ%!zs=>7C|jl0IlAVcn0+V&ik5+H z5V)Hnhjeb>8B*rF8Dv66Kb799DA|&C;8u$zU!pI$Oars#Dh zfflH_1@>GLh-e(y;x0}BSD1k~?Eo>j9#5WNE)rw0EzPAyVz6$JvOYhu_F=P*-`Vm{ zw*Cs!yA<<`Yq}=w(#~JI7BXmFXF9c4iR$J!1?L(m<^=@av?G?HRFc63_q$!3XY+(;WcXSoqraE)`rIYWlYC z`=)ID-tYXDM*r^PENxW-m+=`d**|a*LZI$mljHy%;2FV(!v^mZaG}=*Z1HZ9re(Bjxu^n4Q5Cl5?;!+{@=qWwvgQr`~d&@O7s6!KU5{ewb8{(-K&O zT=9ow$mU%w0UVgueJ|cc7kNfkyetoRe;1OI@A8$0`lvTz25(}I@71GT=#{1TP#=L{ zhY>%Y*ADRda+!xYVE7S;fkp5J&n5cNrS-6Wby>}l8bSFdae9H5`n=bB$ldW0AAuH0 zY9mmCN#IvGZ)FKD_7S+(7-8Zjj)6*2rV9oIDCmI|$N?nK18$jzJGg^5aA>!Wb-0)H zq_1_le|jgmdxzNj)o1<3O`zAOX&C;~tZtHlqy%UY+3Oi%$PF&xvXjPCQgwvcgD2m z(;k6(^yI;-N5E&jpF5TQZ0Zzf)1*(G4&-T-W=@Y+Wm4R#b1T@H1iWS~YxXSKv})I~ zZR_?e+_-Y*(lr?tYu&th+unuw^QcgIQlZ)#Jk{q>|EKkm`aP`Ja9@~v751G-7G&hG zW3Nu`?D;e3(4t3^E^YcWYRq?2vu>R*^S{4H69e@txG+7zh8HhR%-f#i#Xk)rq^P-@Mbj*n;I@Z^sE6@zLADfybUt zkDWSo?TQX3{2Qimj!lIeY06o~oNCUkXH|O*I`|-j5lT2Ag%wt{+Ckr`*ByE>ZFpXX zl7;Bug&?wLVM)$4MSy(t*h3FI?VtmWHr6~-j4rIOLW?iVSOd;D>F`$=ar03{+khC3 z7T!w;e#9ApBZ`P3l~r1KC6-xgxg|p!ei+%8|4K4gB3DwHN#25Ba=DR;Pt_xji|v%7 z%`u-40>>Ck1c3t%Jrr@p9gV0WO*!xgINWVOA^DV-p+R@xm z?lmfqf@F4Ao~R_I2_mTJrK)D94=LEwaBsGg&NHMmlE)ZSKyk$tUW|bT6})U_(d`6CjX55MvNR3Nr+tLx3)gz`+C!98|!;6>!|~h$_~g<6=<4 z33TMf)UqntwXSxnmAhbuOfSkQtGqJH|1G0ca=Pl0SSnUf()96}q>e~4y63tKo^mrq zB@~O# z>?aSLKgnqgD~iA&MG+^M(7_5rY>~$!tS|%QI8d|mtWr3GmTf~PlRO@Qi08dK@4fr} zyOxm}u5;XlziRH3X7+tz%a01}rah!|&_DwmoWKMXfvN(GH9@+F6g=sa^9?rA0Hewy zgxmqg7FRHlL=sGl0f!=_0HX~$|MI9UyS2L4J~!N87Bt%duYd+TAOaIOJ9x!QUe9S@ zhHe(Bz~L@t4(yxCoM)B7ya*na;6MWwuz&Nu7;;8#P14YxWgYBL5f)r!y4Zx2Rru1l&N&=P>UMKUl}M|2JwYi`7aaE>VOVjS=Kc`7uhz=%J2usDmE4JSH+dH951QXAl~r!Xan($-CKlIXZ;F=NyY{e85j zKFx?NX{MQOO=@rgOdd1i=tfzt%$iI22_D-qjz&y?df*fx0v-@f>Q(ide&p))#_)$v z_yQYHBLJKt>JxT=|3ep#xWg5K0D=sVAPH!w-~Gy=4tTty9l0@ST4^H`;z%@B^RdZl zmPtj9cJ!x?T}w!(cqpN~Lx%X&XZfsQ4Iho;8`5}%FVX=c@zrRv$FPPrQVNc5Xd|`k zkR&?P0nCh8^s%=6T~L`RR0%GxsK%?HQb*=Yx;gc!*{la!2a$nqhR}}>5a9xt+W>O* z5uDWn!3u(aJz|AT7u{orLtP{fb&LZW#Lxx$um%S-c%i-AJq0VAR*s!EbXtWi4q@Tr z62@9nQvB`jZ3BFh$m(}0!h9V%R61WtmhTzQkj6@ZgpO}mk`%!%g5kjGR9zR`kubLR7iq>gV8qN>qlfL6sR!g4Zq zgy00HRv(~bLH6JZsAB~&uiG;BzCuZilIksOm7 z!e-^aNJWX8eWv0$Lw0EIuqimKAq{P$V;tHThAx0HjAzU@KRX`ACrF_UY4`#dt81M~ zt#J%sWH`jy7_Vqie39DHxzp8LDg)&luQfJsZ=j|nfPV(y92bTi+UT)WnM>plHg|*z zur32~J>BUhIRn_m0TUudh)?9zo=uU*YbjYHU|jMKXn4Y&dLX|%G-7Pvu$&|NGZmpc zX3b-~|4E!%66cwDy4+bAjy&G+jy}_L7|bz%dMiQZBZYRrfpa zL(F#!Gac_p<+nGjX>&6iT*5VVx`+o&qnb#gZPO4Pv-Laxslyt7n82+2n1FJYv$`a& zZU}*VuWu zxm#-0GM;6N5!c&_2Unxh^!vClbg#_-MH+bkxmLY8@~03#2RbzHwjp@3W7k;X>SJ6z5R8_%7$X zQ~mEYrq=_LTAzBP;~0l8XW|n8feRQp<+2W^4g`h@I6h)n&5k|;x$&25p|DSkh zkf{xT zqAf}Xxh;gLOiB4=$TMw-c!&(p)C*AcV&GBGRbU}HyaF6dfC!nB2S@+}I9?e--pLVJ z{x#QCX(M#OpO8r&2aEs?1i=tM0Rd7>Fbm(OMZ& z&yd+#b=jI5`jH{U|8C1$#YH*~-VbY==n{{uqsLn?qkXO4gj zyoEV%W@)Y_Yqlm3_`^>f4^jkQCwRe3#-9Y_W>(c?t~p*!{!!u?88%LrAN5g?F@PH0 zTH{&Q<~epCwN6pkQ+#e{Y1l(7tN>P>e$-KtTn3RRdf=ZbHB}DH(E>p>;h#uGv}}n$yUs{~VAdng5Z{$z%)O&QgLOG*uT`P`Oyfu5j&CVWGHPzHQnL}Qf&Bu?TMaVVC&l57am z4Bnt7{J|r%lEJOgNXaRv#)UVm=4X~DX?7-xwnb{XD65VDjKZdj9#1_?6%;Jj2u%QwN`MC> zfCFp*^&r5=IRNG{fCB_6{5@khC8?4*fCD^01rX^~jgV3HB*~Sblun)q8Nn4)6$s>j z6x_ieumUx#nN%E~Zj^&HsKOnrKoQ)5HSm&}79^X-|EZh0XI@}bsJ6-;ijOMr!LRti z3em!!1_Lk@EHIEl{k(!MG#W7I!YgP(K=DD={K_3jDm+kXMahF_{h1~d!z6(NHoTkC zfgoh&tI5`cJs1NBkbq~3L&6D!Xr8KRx`jQgYOA*Bt2&l!3IsS1LK0Mfv|a!N^ytVn zz_a3CO&TT1)nBqAC(9{kk$P1Z9_LTmS~dP;24Ddhi~!~p5)PE({5;t+jO2^tMuK6( zG0?&vBmorML4;1|Zbe~7v}q*b>wD7c6!Idf0N2#TEBA#=_}yJvs%75V*qb(?-Kt*{ z1}-%{+;5HFQ@x2{?o%*)m^Hkco;_G=o!u!Y|4TgWnKq!0BAkMQ9YZjX!XKytI3&?T zC0uQZlwE>KsUAeko+!=EgC%H!@+xm97=mh! zKnx7R@-A;K%vP*s#$bU%9`rzvjoi>m00xX)S0$^oE}oJZr8yZ{9}#6xs^J>;QF9q( zI3XqGfxy?C!1x+%8BPEQFafoVf;8lZB<0zS5JMyIirdy=;v#Md-VVkMF5uC{0v9e@ zmI)Nb690S(&aC7EJt5sPuoF_D;$qMSzu2|(*WTsg2E`6w+*A0B&o{8$oIFEk#nU%L zk}7lpDOf{OXoDsILn|T%$9N=3!LATD|3wXbgJwyCf+`q1T;EXFtF!3sRr$Qi)*PUAFU>*6u1ku|G0q3=~Ko|8&z z{b`l1{gE|ZE#`GV3Y`E@7G>9Vz?U^b=K4a0ahNq|0xy{rOu0$LU1u%Bu%OQHy26?ZdA1g~e3=oZUt zs?LRn(tz-4u}{SrQfR{+kU(!H|G)&~W{*naG+ylk6svRP+H=`jKTB!(lG7dUUy)kZ zV%s^>sz&Q+rXoB?!>;SAj#AXVwI4i_ir}bL5^;^gFin$pn zVgnq&v&iMD2;3w+Ph(Z-|C;$mSCWyCv;u24>TyrfB$58#t^ws%xttb|K?lHZ8-liH zPXHXK0xS3eYALZaSVJSwfd68{VC`+q^#(RA((dbrUHD zI2`OLFvBuOvc!lo{JHLozlK_#990ufO4bU^uc9r-- zzyyRZktJS`{toV%`XB0U3aRj;?RC0ul#QtSXdMYjM~!5JLa* zfi?uUs@xKBd$LXUEpkh+bIYx9uQ}lOtxM}Pxv{hoDz2T=c~a@3cSkp*#Q99uIgJIn zcFR(Dn|JbzhsWGr9@^%6pJa0J@fIk?+4TLDpjzAQM0~DD9i@K@|V2o(4 zrdUH#|W@#*!)k$-K-2@l$&`gMON^A5P{6~G*w-`5w^L{X)--}I1o4ZE zm`VXj`6v`|usYUn1UPr*^Ri|Kn80e5^R)9itDb-iz(+nXdlm~sh?4+dFM*{;m>=mMOOyUz#mw2y)BxuJi{MU023%e!m}{>%`(J`{KL=w1WWwH zi;N^v3b)Yyo0DHov-C-KNl&j!N&|nMzdX+jWOYwmb|-yf2va+*7MZo(=viplgb_M) zPutlLymeL#f5SJhF49AFfjxyfV8bjt!YK$mq!)eJiJg>H+0kdc{Z~ZFuI$aWXgM!C zK#UMLqD7!w;H1I&VnX1G5@P%jAiysZ2!SmyNyOJ=;0O{j;MwyRiv)=gCG6CbxRPZ{ zmfkuHOfk)+Mvemu9!$8f;lqeEfd&;ilxR_-N0BB~+VWphr%$0q{b!G=y?XTQVY^Zx z|3QNW2_Q(2fFVIw2{j~my%1JxTeJ`$lx=Wf!h{E28%*%ZpaI_p3l=1JQ1)&EzzG5e z{_1rElr2{-6#jZwZ~_JoCcOAVjF`1?+BhGR_U8eUM%u7e{l`*j>(vrn$Cf?2byC{5 zapzvToA*%Hu%jZ)T^soAmBWieB`Ost^WnjD^JZStIqss!2~2lc{kc=tvzc}$-m)sy zdhqDgd#6qvy3g3Yjr&%vJXHc#(Mba*kt#ZD`lcLS!~h87h#N1#u;g>(Z(Bb|D3TN zZ#wGH#~x)^i6WB(O5ql(2=K?BeNu_ZBN(Q!aK{q{5E4xT$GKnT}LRNhX~n0m>9}tkcdMySuO|YoPe6s{}3(>jJqT5CMX())LDDxZqN> ztUx4d$e^pf65|Wi2}U5qnrAwc1{Gb1IVO(= zu6X2|)TpyAIq`s1PPkx+1@BH6^E4{h?~MD^*zAH^F52y&1J>EqwA(FPW}kw#S)rc0 zwz+D><5o6vjoWsm`rs)iop!*%1{-a(c@-RV*hx)7s>%Tdn+fS*hn;aW|7ipp6WK`z z8)*vE2ApxyK~c{X>$`Abb+qy2lwghl<{JpF8b{uF=T!&7V^L07<&{}(+2xmE&auoD z!u-)@fr7M&NQ`RQhYl75LP;e8=4pb+ApJ?jq!OF}x&=fC$mffru~G^qnP_rpqn$Hy z$!DNXN-5^CWA4tv`sjIv2~EL5tE{rv`iiX>EVy8;Km|>}0|`7RYXZ1DAnR024;yUL zz!I1Mg9$!W42LbK7(y>q0b6Xa1u}Ty5paHa2ApC}q19Ff#vlcpdMJdgJn)Kb-8*Gn zk9|C{eM|N_YmbXAPj!3kc3jz=6}Pu(sa>{qU%h?3_t??JmiTa!|5u*8s_IFnKya)% z<``xY1gF8(T^dJ~XCQ1hopMeg1)GQS9cP?!+z033_t9wwbqXu4aNVi`wnmp=iZP65 zU_%`&NymZeWesegqiVEs-~%BTK?zQff;i$4)_}r~R9FOOD>26fY9<3ZwZt4w8bQvy z1f~(JAO+(1l1WnF3Kqm94feRl2~2VVE0M`eG7-lJuLMGz0nvjdL}3My_#(5_rylGe z#@aU30JbC`0B|$Z0|Eenx75u5c54d+@Fsz>U?419h>Kh*fT_w%0C9f9KnE6A76f!9 z2xPdz3nrkdN$tf_Bw&Ii#z72VSi={i@WnHVaR<_|f<8pd|IX@ub1m6n=XR5{1ApjDG^d;%B{%Fj675wChl107b8M?26_4)}dT8pk-8zF1Nfq>KZR z9P)+f!pX~TEa+hBKxQW48Bcl6lb-cliam@00wSd#O={ZUKyp?Ol2qxP>%zwk2BLwG zNaSiGKmjg_RuUN$Z3G>V!8tDIP+T~YC=DIKOk5&REs3F^{5fbs7iv$Hni4nl;TJ2C zfVjYf#RYEzi&z}cHVJ^yZWn04-uRY)w!lpSBG@V8{{R&hq%zJ=fg$6f%Hn{;4B-w; z=s*P|Rhhd0Mp6qHLFuf)3SC&E7NM&JE#SZaH~^!O6tmA%R1?Wt&L*z0sgEmH89PV@ zE3V=^ieCYHGNAZ%DJ`Xn^eh%0r`V%grEDcF_eUoSHHERhljJOm_msm@)~yw)taoTr z*VolXvyPOd>NdN)(ry;6f`z5;L_6Bmo{Y3miS2l7%i3w(rmmO`k9y8GqE{88d-6-i z{aniu@jc@{5*gTtgc*#3q39~`z@~ggMj&?`=tC|YAz@ddj&XGC8Pbr3E_A^#_qnSa z1>&YO8Wc{Ku9Uv@weNlL`=T9n1f>4t;0Yy?|1^dOWQR4`h(JitLX+MECGIE*3DTes zI)n)Zy-=D!6v|Pdl<7=G${I@qT&18K*dq$gFFjqSnhXVjQ;BoI851X#GqS}4J++$! zWGvJipT(#W=#<`aEEujF=B7LC$_5ORfF$IhRF`2~VEA$v1}uOEchE#FRKW^s0K<^F zAO#v2a0h94Rzk7#E^iMD%GKSqwV(A4comx`*Pi(~Y_?Bw2MZzZ!r8mi!*gV%vS-~2 z8i;nDEL?>Jp~Y5=uy>s=W~0JbKj)UvdtD7<*}Q0%%683tP2KFmbJsZU%hCLatcD+( zY1z&;MWUoMUEj)TSD#YTsRgxF;NhNl|4Czjyw(N-&x735v7}%B;-5Oc0XkBg!Ww$6 z3Ohvfjdecb8J_88IjWYw#I^(;TlPhVNYRLmjSL;S1_v!(0bgfp`^4>b_q*Xe&zaS% zg^twVe{(jH0k43hKsl*EB5;nC_-q9dB?$>ifQY0y%@cGOa1D3kQGU8a-wo-vfe{LD zfyX9n? zo{#~?)P>pb1^D!WUasg)dOih$}GQ58p7ERfIiPVYT_Tts!Eqxz1VL(h|=R0!YVLe8N1LZY)2Yp-SzT#O zhduGSg;uB6US?2-das%!HRL5*_Bg+p?v}T-usrW(;)tH{pyv+bFZ=j(JYyEB2*#@h z1fX_QP1qEI3ObnavGUXd9Kra+BR)Ysx0**D?-1EDL?f>Sb%-8hhI>uwfoxv{gBh;~ z9X8-4jbeB%UaI)SDWs9FiT#=5%qTtWnk5GYt`$Pq`9aTrWk zqXaMql}LaLaKLH0hKD+g{U}cUJc9me!v0q1h|fQyw5u|Go$V5Wp)c;0f{|2=qcQ`l9D1!!Q=W1qk62Sb-LRp%{Px z6@u^&)`k!~1a;~GbtDPa(r&dN%g^Xc>@rP%sIXj|Z|=^l>nLr|)(t5F>+&>D&`zzg zRHN=lZ$cuX(jdt^O6v(@O$q_;vj(pTG0E#Hjm$#pu=Y&s_z<$B@X}c8^DHZ}A_Naz z!}cJ_43kUp7;WqtOEyFcwH)yeyM+rY=JYs^3@a}-)FVJ>;S)507UqRs=tmunNzk0f zDbT?)T&f(b;S@AM6K3IIOr*QYBOOMBWE2P+%Ih1@;S^D=CRWiGR6!SrYa9q5K&TBH zm_ZlPM-`Z19NZ}w|0A#(t??SMF(~j!pFAvs{;7lRgTx%F09oRN1VV>e;-Ity!vv0^ zIsj}&AmDgI;(mxc#1RF^ao`GpNYF7G$7TYl;u#3x1r}g1G>|Y1rvlRGQ92N)-hv^| zqAk7%s1BtpxI!>`ZUO>D1kl3BPUQu%pab4!0sMk5{6bQS0Qgh^7=S^neBl>VAqE$q z5#RwH)=Dw>O02(9rxiwgZpJl@XFJgc>s&=R+;D85jf9t{e$ZSThK4B@WN z?CgGY((iOK4!5%O262`M4e#iXvled;TkDZn%Ui$@?0Cm1qcG6UMiMJa5s8Qq-EtD^ z(5@U$Pwa5)|3s_LFp=ycuM8i{DF#LweBl*HLFphSKw$6JZgS5w31ixde^w6`HGveK z?it3xrRV`3-r<1Oi9m>v6rSNk$PXya;}|r-7yjcz>Y@0?AsE6<6+~k}#=(C4aW{Fh zHzRPr(8L?@O-L%jBS=68x}+RUK}*JjB_yn75Nrn|Lc-Q@1=66TjDo{3$R#MkB1!@| zTVfxUb0C`2H(6$qsKOWiU<4$^Al*}qY;aPFjBmb3E)u{1ipr?KLIi7U$`YUg3`bHl zQX&Hf12152kYJ}Or7O1T1|I+lMnS9)Nfl7x7@h$Y?w|)4;1NDEG8L^^*z(nQ(zLkF z?gq0d{}GS3rjpPu1S#`S^r~|BBs0(SZbrxOF8c}#yUx_;QWMQG41W~!_|8YavN$}= z&EC=ppAatR%S8|ILusQXelpT}>#L17Pk|MvjaoJI5$r)88mKU9ixNvTC<*cJ=#WLtkUw%GONXs>BJm3E z(6bhHDsL1FpAzo+P+}jCD$)=Y>#jucF6?Tw&75>x#L`9uOJ#?2Vl->~LUu0IGDu19 z329XFzH}-xu_z@rMT>L`@2o`^YYAzM4>Jo-r$s88D+!_PK&*k+=4H#$M-%=)5lG<^ z8sQkU=@p5=>f%b1ift&cffQ)r8NMMH6yX$(0b;C&83L#ntRb7eVHPw*y4I(D{~iQL z%i|rw?c2%$Md%?Ne4!DB!F>cIfDR@dJd_%tHF70)a@CK&>XAFY5x`c$ABKv;hbpMG15VN}9)JN5LsIbK zE8d1Iz$kIph%W{-=E?#;$8}PE*C5+S#wtbU!axENbf?II0l2qt7T^ke0T_;fU(@Rs zMgb0RpaL`j>wt(T>naMLk6{HdVaw1ebM{Gt*6fC(V$0NFQwO|&Rt#knNVB65ue1?o z6o4DerAAh={LUvzIqa4wQWrEZnEZ%X4i!&nDWt-=YIn)^ThCg{~h*~dPfnr z4G?Q*gGm%N{_05igC5W!7YT%33}hUn0T@)_6;weJK4BQ-7Gl6b7Zl+YwBhOsm{~G} z8HOT2c<~ipp)(M*7)W8P3orV;lFW{aE7tz>z=rVHYy)W==o}`pG3E%yL&k97jMpdqd*< zcwGj$kZtCW6IqXG1U>EHd^_MTrtC5>C0)D9rc7Bb8o&X7w=5K8P!<3Kib^aP^vN24 z=vG9|Zxf5%F4ly_*=5PuJRo;^Hny9~c-U-oD8@OS z+b%T&xP*ID4ZRS7`&pl1#E$QS9@GILmNAF5X&kJ98JL0E#MgZQq#Tan6Yk&?a`S@W z3LHKm7z(y3{i7JA4Kz-n5njO;Ym!#ItPw~-ffnQ$hT#}KRT?8xM|TMwuvQaPVHTtT zV#p~NWA0;Y?tCv0UmdNPN*|z z5P_h{qlb#*a$nb~;ju@udaIopStf84$bdbC*DvtmZHSjJ|1M>CQ(29483GKzE)oEi z4J9r}@>94MQ;YF_rpP@ZONG^w90(E}vsmfa%$s;}=E4sbz<+x$-x+ML0&WlPPId zp#6@6S2R+Gdyh45W9ONk^O>OM>x2y&M+_RFKSLUJ(HHY2UaSEe(t$nDA!5*>Q<(v4 z??4yeq4sizD#Yg))S>xsnjS(VV_L7L{iQ*Y5WfRN5so;C9U6e9)*9v`q{ojQ`qUa! zK@n6zUdUS;fPoay7B#?u8HNEEd;uJk`mI4c#7T83|6+k=iX@Yt0+2OVEtRAiKmiJR zUSO5n|!L*_Do3C3kqXHfT<~~O6%o3*dc5+(Wqa3DDPY5wsVv_*g z8xHUJpTBS^Q8YER(L6#GpQ+G-ui_l^<%FBtVk_h-=t04yRPZYJK4SA6&H+8TP$Wuy z)+MvkF&#DSxhMmAgi%eM*V$O#A)D%FXnfr${|-pfncbhWTZAp79nt|S7+f3D;hqHR zJkAHZ9OixAK_2A6Ps#g!s>h*$!TNqr5oWQDc^0nvg&Dws9f-Rs^5Yo1>=cIK*Ybs8 zblRndAwIhM8GcDWA||9CtsOuP4qV#x+y@)1j~29n0LUqrib2~`-N%=_<2^pV)a5Bq zM`vqEo|6Je_J==?`>&KxwMd?VD+#ZbyjaTP6W&~nZcfV673WFP1^fE05yQ+AyN&#& z=CIsvusksEM&|hD0?2?At{?*pzym~}Z^pb+0%HQCKoERr@p&Njk@ap3y>JIOcTkqt-6rGDdQ~w{w&+b=auEQ{w+@glj+&6c*%_WzpCbx-d zq+F}rToPGQRI14(>84Uis?FR&HIk&;+`j2PMd|A2_b;6DIG^)*yx*_a^Evi7eijuv z7RA%oxj%2`uK40<^<&|6;mGm#W8==p6lrba{7p||&TeXzT<@dnk7$p^dgvy{2fvx* zgltbig}QxRrB^zsc8~kQ*ZkRx*-2vWea!yFLm)jNMqf;~v8Us83<-}8sBZ>oyI*nF z|D`=J`Q`jsb~UPT60@adlU@Nx{r(qSkD^tMy>_pA?m1HR8t7`hfYN8VGT;$@HRIEv zhj|W%#MIQDn$-N}N2k3GKrJ_Rme|zymJ^-x{vd4|`VX4~oNzf{+c9w8D;n1 zzaYiq+g@`-`)&~y!Pw3zCY4DB2xS0y4AK$!iQp-H*ObmEFO$a&|9qe$ z!xu|78o6YZf36+zQQi~&L~FJ#e`eL=3t8{l-u-GgKU^O?p}YIn!upe)d9%EC=%PoI zp!9}+lwUrNn_OqrUX)860*^MiWdC~e)3elmP850AWp?gsu|Y27Y^lQ>ux@#yx1#LZ zfI+sR?t#^tX8vKpDk3bn@W*R-+FcBFr+U}4q|wd&QKf-K z`x46S$IFfcm)uKEtZ>SbVlKnkqg0k~$+ixX@u`=l)R*jr6A*;*ild zBI8g)_D{#k9NCdD<)KwaA!W}uJcV)Sv@zIz*v%eeMx6ZFi?ZFW5+r*iN4u_L35>I8 z5RLRBDZ zgtO(5L8PpF&4ZHlL0wwuJ0>9p7bi6-qevFBq27LmTx@A|7QdH<+E+VGtRhXJEiw-7 zn!yD-@MJcsqi1ZaDqtk07)$^V8%(G4_2U=^sm2|?G=2##>n5$1G>HI9R6p2CJojmoZXu#mK#IQmqE;2nAnOxdG8% z38-0QEta{eszpzT;nacoHG8mD6txvz;^%Kzc8QPPkgUS8CgWNZIl<+IZIk`I&_jDz zm0Z6I&E9KEhs(BQ)$3Z9dLR30cZ$8RZ0zajKU3x~QdPOo;B~m)z=_Pg=)&BF5`(mB z*u3U+*lJ9)c&zEzvCBz4=Qd~$24D5iY$z>kQUivdFDp5>{l#cLmG|=N6bM_AWSKT8 z#(Y+kZE^9`61NtuvC2Suw33jy1h~x>Kb>P6AMd8*l9VhNP;ZWLjeK?A>d&&CVJ_g^ zV(tO!q@l-P#ikOZ9zw@ZDZskV^!54*ztv#e267!ZJI8yL%>?6GNo~pDZy>f}a8NUn zu(`d9aM32}T)@ovvF2DKQ-E>@73XGAtcQTqV|TXCAUUf}XP0kk5t~W&;$Z5Wk$lG-2iO zmgpW`318ixZGxmSZ=w?cs427lebpe=n+Afe?xm~nXnbPYlo;B9be)(#U<1_zjU;vH zMGPPMyVAJzS9BT6>ikD*19DHSOzc?!6aGzWArwxRMkny!9Lu9hZ_?xv#iMTXS+1rL zy2uC{%Yj&tAXEj>$+_ao+g*r#NmsihYZF7{%$ zC?2tFr(+|`iVoN55cQZXDUi&vt9^Q)AZPE0ZD!>m8dq}Qc5Za^7Ig^w2ejCpCt3aA zUyai&P)upac&ySWO<-d6O`R1+r zN_M9=KpPBR>9r3kQI7m7d-*oBafiv&SF=wnzes9^zn4Cg1Lw5$i#h1k`@pB8 zR`RUWKNhXSfra))NK-QXn>zQhi)g)uej@X#)f8=4BG^^Fhe3lZB9;;N$UX}ST($zB zDiA4S>Jti-E1+GFiCA|G%8)@wtpJGwFBPF0XuNZxH6tp4hqva>u~W~Hl$!V8$3;lG z0?1p$ePQ72`ZvR(p;lrLLxFs(q9bQIVnwLC*YH6$xLr}8{4VV28Q2+iG7(RlK8qVY zYrPLnEO)?-4Wl~bWLP7*MTCLxLQ8<$WnZhceB6W(cM?+E*5~|2)#$O<;1rqH0@$8t zQW}wyGMmYZ3o75CsrY)OUN}y{!Cz@Wl>+)53T#d?ULnMN{!0D~+1fU`<7EGVQ*#H- znA_=VL`|8NzKvX|0+&v~OSKkvxY(@8R#0}@ENft8>)2%U2{Q7hDa>=_WKw`5ud|gH zpb%qw%q?KCNh9Ps5Mm$h^VB|TSTod4Q%#|D08h|lXXukO<0jdIROo)1c0GW7tiWDW zpelgqKpo9+peci6I;yqMSVdbjbeIg`Lticu|NDL62R9Ftcz+Rb`>~L3k zfE9ok7ZR@;;@>N1?#;+Cw(DyzprbX#l)So6?jI;Zezdig(<*xfN^>&fJtYv53N{eZgK`mlKxoC-ny=6;Yo*xzG>A6G zeS(=*&W0&7!3h9XHQs>T3V6$qrM&u_F2w~i=9 z*~BV&71uv{>r-3GT9hDC-SSvp&E_i9u|&Dvm| zGdNs%gahBqMl4mY>7x~E)hlJrQKj)|kAXEm@Ys*nto0)B9~DX`$nbq6Ud6c*t4i}X zoWNN{ycxRTf_Y>3`o<008ofhx=8o++&)Pv7Zk*l|rk_z7pI6E}u_Lm@?oy4~0()id zRc5n6Lk$4?uo1a5WH}A_%NL$agGZ^X>^?zCiiohQnwu9i`ujI1{m_s!M?~W7V|QtV zX%Mu|ZP*Rcj5!Qq(2!$SS3jm>GD-0G(@k49XufV{Q!*RT$m-Pt30C|s&C?qr_rbL4?J>wD9?$SnMVNQor`X($jgl7?A^avKoMU~e);H{yTho!bCC z$*a()!=#)%(VCG&6~}b68a-Z!qH+LKj&(N~j$tF7IR%0S1S}eQPK-cW78(qze^s$D z+hzN-EAQrykP-Q|J^xZZ z$x!3gtxn#WMHAs$Ov=2DiqS8Do_0yrq$avpb880SfFYO*+VG-(13{iRW`mybi@YI1 zu>f$C(AR$C&>#NgJM|P*n^+QX3A^HVp+U}&7*H~XA#`IYcq7bcu;cc7GRTVhC08Xx z4W!&3#wIFOK2cqIC~glQ02rWLHg-7|AB6#LW?<*!hmk5(!jz`l-fB}55Dgh}98hio zVfVFyKRB%oqNA})a2U~W-{O%d8v3k>QpHLQ4nSOIGta0%_fRm(Mte*FaIPGqU5BJ7 zfGDQYXz0~*SnLpc8BG`VGUQgbP~9Rfrps*Ay4YQJ*Lj44O;(Rqult}Jtn0Db#CT5V z;qO)0TE}F3xK6Yg8pfIw9YDf0iz~E;42ql`uX*eMn3#=&-$iJw7!)Xv+~9>_v_^K& zI^7m*)w&QcfHxu{YS1qPwgM~#dOQppB?h*8-2(a%FLxufLG8{iR)#G_YFykIIc#GY zkWI#Z?RIYwgWO9Vd|&ydlEH19^Z_pJF@S(^AO&(#?ZJ*zWDeS~#l z*DYh-0A}nZi$0N(|9YEOnb<4j!BUjrCwUqqbW5_ec>AZZol4KFxQ#=GrEz&pKv`Jk zs-`XLo3@rb@n+=;cOF+g#2vr6$W`n76FoOw=VxHSCJ6Gijr7OTz zWUw&+?)KBfozqO9hu7cLj1A2QDAbJ40QoSX`T*#<5{O}M&zcAH$nX^`>^(UqxetBK z0m=1&T_iDLv?@G_-QR2~G-NLO7;!$|QTsUo+GKd6Gp>zv8|)t#(FZm8ggERSI4w@Z zs6dmR8GjtOJS#&nguNIUByUx9)Sz(hR{@d@tB~KyEz?o2foiB!_M0vnXdTaf|32G= ztJ5L|Q^oz~Co%620Q;Cq_;}?82Emm)*o;qDjM@Vgq5MTzQqhQd9forh3iG0KbiUyiB1Hlk=GPK&OVS5IR1CMg4z z(<-=I3qXPhy|WoVOO_S)+G=IUcmbjRvhTKjl>uyEm9>6-{IK*L<{jy>VlQIb1>&R7 z-NfHm)~QP$?Y0?OilFaD$frcMN;>a3em^E(Jjty5!Y+BtSjOJd!}fkxk<;|_CIaz} z7UG#vBTKy2k)pGQbQU;DL!=Lbjku58;x_SJ!?bN9%#h{Mm$W-KpTeit9!V!noqPbj zc3Xe^#iLKJaQ8j!?ypL^pY-e5rh%~hy-j=X-k3UeTAh%+{WDWxR@ScSINBQ=C83FZ~b;W4%X z{Y8l2Rlq;W_d^-MR2pO-fZcomK71VEa~xFCsFd=0=86268&Li5mSbmJbznrntjv}c zr~FYdqeHnyc|G0MdEKLGCfsC>_in~nfA;&0-@To<^*3)8I&P8cOrwGyMUev}lM4=e z&=c1JD~fQl0iAAJl^iR8ohLs%=*3kCLF+j1FJDpqB>Lm)_*n(wkv)8E4qn8U9X|U} z&udQD;1)>6gtLYzq~U4BQ2IEsA!y&}k1=1<#;>?nG;PX_v$0Utafxnaf{!>?=)d9`&-RpR=~1(Qx=yKZHACd5 z?FoN)%qHgY48dj+#Cwg>H(`>O?@4~bu#c{oondDGf@4|D+%7}U!f&WF0~$@-bF(miYKJ)igfr+?S^f0FbzjJ5L$1?Xa`0FL|2faz^fubbpz2kuPa zw~rdqPKK}m(4iRKdS49+4H>GHo5htvaWYb)ULNJo0qL26cThBxW^M!_s>k=94I%h> z;BVA$AzY(BvYzS?zvD?nlj^Utr3g6#w)W}-)KpoM%_tl?`0{KclGvM5bZTe8a3WTR zz?@P`Gf70$Iup#ND%f4B7=8BTe$D}(HhMkJL?^XxxOu|D6s01f!t}yqOc7XiH2=9>sJd)WAZpOf`ICC^bnMIK#bdiW=AR-$9@QZ(it_$yoQf?_k(BQk108&F z{?GBINP`{Rlop4>tHft^ozUQ_?h|^n=&lTq8+4<3z9KfI?0k45Ht$ntAxKS@)AWKV z6B$CNevUpmsS!VC)FRvHh_TLnTbqzL8lkeQe$KEFX?AIzT!LQ8`R`Q2K&nXztdm;Q zz)QYuJnHje+mVfY+0X8S2$~-cqV^BjYqWtnH(8O=_Ol)dd|iSkoN4LEO(fr7-!?r+v;c*R5eN4A5qMIIwS>HEQL*BO*2;3I!`kD;ZE-SUuIf4@KMJwIFeC-0=V z(E49Lzs%(`rwjS6W{w2;&z3M*sFl}0S!yk7H_oHpthtByk1S{MUiA;Ibz96z5Z_%S zlo%Adm|Ozx!!_ju~vAERX%Vm~H8AH3^d>uQq^a z_YZ*SEQm2DR)(t|C0Oqo()yt#1mj*E+MMR^mCXbpN@?irZI=suE&7ZvtEhTILD0ZC z=(6)%XhoJw7pN+%<`|CbMHNq?qd1=AQTo+0qG@f4uGDPgsxSY_FNVGK4bCfu0ZC4L~DE z$P+RjS6qx)@ZHs$(%QYvoc#~PSOh@b=6o!kDK6xC_vnB5`n0`c*vg>YkT@kf`c`G@ zrSRlIgO}^$HjAIG-hGN64#P)wjt$=)xH}S4((ZkG-?f0vrH%RuQV)d9My%Lty-$oI zahJ(%?qzf*){=B}snPBB^V1q6!r3)4e_&G?7h;99-SeUZiE*3)eQ{k>OBh{*(vu0mJ7;5W0c4KW2zLeS%+%QkuZW&<}zZ&i!)UJ-# zffDb@V^3|~TXd zTbI|vy+)UhZ%SfEoqRfjBi~W`$lR9_)oodHCI3dCk4S!hF@gyuQY9!ht;n7E7Po%| zAHpWzRSTrKs?`9yCCvUa$&rBN4I!9OyLJT~m%HwREP#c2%lBlF_{mxD8Ot5_Y|bwon_cYXs9qKu9JTsbh2K z+=Qpz8}d^P3KvIS>F?QC@hBYwt?^|NC}u@Bc2BJjLS300vrAt7TM>FJ@mAFKzWOW% zsN{87Q+n=E*LxWVH5VHGow)`C4FH;Ai8P_GW$=AnAinHcWN1_7(Y-2G(H-{`}d_idj#IuN^O*|>UUARt=2%E~6-!||5%C+jJ7=2nt2 zz-2?XFTRxtC)Y@D9I2h=9zT%`LOjz?t2_ry%_mOdY@K>me?IxOtU%{{blS3}-10`l zFtW_POUL2W#^B#y)pm0{b;ra-ls{PrH`WyUtH@Vi_RKoVB&xxGy94Ond}&MA<)QE5 zq9`}5TSc?mnaTw%8=qUh&s!BKhpaSpmG-gaN+FYF8``%KEUvX0&D*Abnio#zCibrVB|R;rL<fAb>VR;7WlUW176JEKpRB1!qB}T7Y=Ne443{ezXU7+$6HpeHfD%pQY z;4l%d{~QDzv2V0!_PJcI#D8Vd!mcf{rj6KHR&6Y(|>^& z1W$Z=#X0ZI;TmOWUaAC6;~vU!y@K}nqk?`T+h;%f=#fw-eGm)*0DwlcI=M6~B~Y_r z@KLGl&CbVvQ;w=06U{6mUg#}a=ajD|iiaZC?TJy&s~U->9o}%M?PJBv^?b`ow4G7y zfvRlDu~@Nt^VEHpfYlslbk0(dPiy7+$?Hg7aRN)=On{jB@k|up`FJowW}eQp&le)L z=Ro~O%pO=ElNAt6fE&&z40&SaY3m$jeuL|T=6f^;bXZ35Z@A|mi01*K44NiHq%)xJ zUo?K!n660-X-t;xClnFuc&QGzDpd*wu1!>co8jodaCRG?(7ag>A_x z%AC6u@bx4wr+7#B!NP0AbW&kw?1j8g#CB4RuQUB_3F&lK*G@ul7WvjWj<_03kKZL- zd1Af=UVh7EUfo?6I*l$C9cf?xvVFYn)Pd>l(&>Xem0p4;-9zT*4NIJsMO^E4aEYPy z_w(APUhqg{o;$nVjU;ep@*bc&P{NC|Vy+<*Y|DXY&GkT;vQu0c( zZ);jgHNBXo>;0-jrw~a4$3PbmEGKl%Jje@KoT?CncEEmIDBeY@j&&?sm` zMGpNZI&YYw9SV!gkuW@OX%_(D*Cj`}JRgahJEbJ5{ z>5%Mg9$W96h!GZt_<`T&!%;EB4YZScL8S@p{)qbewQV==F0-zgVg?^%9Ea7yoSeD~ zE8(i|k5#K4%%~|$@k8V??T?rr%xr~kGB>nZZ|RkO>!zwV#FYUJV!#TqFP?je-(Lt3 ztjG}CU;o4eG<1)cUxWo&g|(HX5RNCs0mdczw*4UUaqzp$9z20NO8}d<@*Z~Zjr%!T zLhxD+SQG#}7~rV#58-Og{0#M3R4D(g;o!)j##C;-nlg5rw~-`JlXL#aD$=`s;7FdY ztZ-xWn*WU8kurg`n2TpXKXkS2fj$rl`ic(wn&$wGPeOdPk0TUdw%^^M97Ni98-&Sq zX2N@18u+6EL0j=21&ksFA&wNqEBG!tYI(~vgg1?|I=85gj?kh%dGV89!i9{~7pElf zjM$Hie-?+R7@0?}Jz<4BnRp_cfUxTJNF~9&{lIESaG0#{Y$8x04+1Y4t1-E&+x;~~ zh5f1a+f{5d=LDG~w>7EIwM$xRqJDOcZqd~e_Tj+TcMVb31{c#-tz!m6j|70zkL*xD zQ-%Ywv>RhBs$bUckUhPxu}tB={}gN#r$<`_sMml)*-(|UJM(3 zqOCbob`x?fVj}^fnKQ7RZdR2pK(~W)E@*keK$_-73BrejbhYDL9;byaYL}drKi&WP zAz}%VpM$V|$3-te(pt}<72pla0OCIi*V(-2XB%QW6?ULfHIGr)@d31jLsE5&Am#}6 zh=gAfPlOPP^8gf=6ta+bfgI=cU8gvq6%GmzJ6Kp$k4T;rAlOK_la9qtD-^U6o=)lp zG-Ryx-T86dN)Kc2zKXrKy&Lh+D;WCnzQ#-OB`@jO_QDsKppUWb6J?HVh^_s6Ekeb- zInTL0j<5=9YYv`et+YIWktq%y3AP~dCr)wInNGee`it1VgHql&tmH=rqG{Eko1jRWV zt?*$V|73p{u}t8vwLGnr06v$C$v4;cW`eux%Z59_a2h`(r_h;6NhTfep#keBbxmWp zj4cUChDWkjb~j8wMJ7n7!&*?dHcPY%`Z# z9DdebB1&a7CT}c`C9H~ZD$WyWq)avtW;D$A+}|aAc0a>z>$}<`%%Nx<@y1^#7w%}_ ziYP}I#e;DGg#hoKe0nzr?pE>ulYn_}KAL#)NWnqU24SDmi_h;NN!s#kF)iF}9(YQqvAoim*Y6qVfNpYkuYRyR6Vhu9RY?U;d9 zwgJ7n0|EU;F~=!t1bjXVswszPWAv~36}x6p7F|ngHr|NeS6bLzggAUF_4)ZsF+7=S z>7r@h!;0;_o1FeAd3)q3_-%z**RXH^2RluKYc8^BczP>RljeKg7D9 zJKxW-R#6FP=MxDdMZwC;Il$;s!A4H(_MD;=VbMlv;c5cNdCK zP&wc|XV$B_&qt9!{J9M0qhecXuiHmI7pS#E*^%tw;*K5m|cXxsxM`*Tv z-g?4@d`{B`pb8Pk`DbW) z6bnw(Z4xnyefv2KN76>t6PxHG&{}&Ha=Nh-+Rx2A!7cfc0;01_;{@zLu%j(B6=3v5 zjtvVP`Uo&*dK_VtcnBR%xok6Mi#-odZj4KX@R?tGhLMw|<7|+6=X4r|uV0(U)Y>j_wyR z^U}rctefrH?in)e^1h@MgeB)?X2nPzNb3gggAidfC`YQ&_3f# zg4mJ`jLpH75YV`uG90N~zUB;x05az2Tb5LyIAB|G&l&;<%3>LM_v|m?eI2Pup%!ff z;9Hn53o>^#3AS|dMR&O@*M);nK;%tWQ7>lCvVO5Idkdv~8)FoUhH#rsH-(FyGTw0^ z?feAsd)Gp~fcJz~Bk|8IVl#^jHj)7aB%M|4Dd{JPO74L2L}*l^0lr zJwjLK9`XLg50OFjoZ%b2|AtYbS} zi}n69v3Ex1)f9~$TJ>XEBOULq$Ul}jd4EgBee_=H{-r$~f9~_mo6<8rqEZLb{fD3w zR95rs&%$XpXAH0X-5~Ts`IOnVpT$ST<^fWy(5jfpfp|~y`y3-zr<$C^VXS{ypN7j{ zJm2w(QkDtWLgjqTuG$zTPY3+edwEA`g3w%T33?%~ID;i9;qv0i=rkErhrDu8E6Q4e zs5Apmb70|ad>$#tyq&@(z>#)8bt>Ak?okJU;uIiO-}6bQwz=QnmGg|^7eaVWKl$qR z;=;e@GgQuFH)NnbCF|bL?|l6GUSod8k7Vt0dRqH4?qA8)QGOu#p{MjT{{iF4iOXf- zfK$?FdHsb;P%76b2V~yQr>o!s7_fkTzFu|MvhX5GtUna;E&mb!t$(I!GpAX%!U4e@ zbnSbr2ln9b7w0%y?K~~vh{I0K8)fB10=L`;mbL`jN`h}9!6Frf)+CUtkxN4nm42TW z?Y7Y7hX2}=heH*UmYq1hU!)l~%lvn4L)|lbcf{?&_be4oJm(43?`B<;2o^NQ^=knD zc5oH}u}J~u(B!ibj^OVf@qW!Rk!$LHwhXw*n527C^2E7?aL|eHITc%%<_Ay+@%ly3 zol3*{PCiNbE9k1c^hVa~*H#+)t-<5{;}jdZ&jwo)2*}X?fVafg&W-J_<14wY1+CFH!rcqr17WQH+FPfs?Upv4>`U5S=baJ z)AHFZ?k1g!h@B^NZ|~@O`ps9|JSb5cJU>yAOz3#9@59yWKI=F3-&=05uneOgrsSw^ z`VQ^oN;S3|iC^@ogr8aBcq zyf8^8IC)^HO2zxujBOS1LdU;XSEfLELI`X>P2KQr%fhKQZ-*V~mzf)Nw3^tZK{ z15R&GQAP8})sI!`4OgFO_88P$EviGOZ{P7eyyk)BNfj!CsNfhJ{j>qEq+CV^qD{u$ z_Ms8tx*#W&^-D@RB%%y?U>0lV149T92)k2wSwDy*stYO(Q|f(UQ_A5;jZ1StU<5l3 zM8oedFjg|4Sh0&K@7k6o=(tHH*kX3n4)0M~!;$Ju%uLdh3nH{esOQ>ayE(IE5MP+L z`N*M?31Jr$;ZF&}xy&jKKM8iNGcGqEama9oPgdPcuCK_m5$hC;-%$x}%Yl1?qufZ> zf&)mqcMXnJ$#*m2lMgQ*Q;rIOERN4HTn&%y4Nba%+=0{_+p_aj5AJ@z?cG1DKa75x zx~FFufwM?pcR#;c=L&|U8J^I@5=|3DD5r&JmnrwhyQIdum!TrGS`wTLxh1o`wgbv-0Q;F;+7eEYMgVOwJr{oDz2)vE6If>dQE$xE&j z!Uhs*7ey)ZLZdU}P>DuV1mL0CQD!$t0Lb(G>##;%$rZ6v$mB4@RbwT)>E?RdZPySb zwaK)6rc_JL^qp+>b_Z{S=uWKIr&*MB$@YVGgdx%ir#Xo-Z<#DGA{wFsSRUq+YlF6S z$kFz5t5%rTMVYZI?QNzGpF-5MnrUDi1qa@JAoxrk08!y|Q{zR* z#GI!W`deZ2aymMY3PPI7z5P#-5RCCE43&A#Mei!O{+Cq6Nyx=?uT@r(({RXnq=PN( zK;Gz)(>gMU?Mh?)KC);k3gU0cA1X-adTl&NuyW&;oWJQQCGE)or?PzoN3*TTKT%(6%1#k7vW?=Y5XRiS%ymL}EpI7pPN&PXAMxwdm(-^H~9$jxpY`-0bT-Fn_>^ z!+~G#ZvYA(6zc;d<)P;PB5us1vJZUJ-kZCUF_DL4-4y809*%*D6r~wCpGnt+xZT2u z`svhS=Z7O+cztoh7Z995{R4o0i1{oSL2BA6@Fk_ z-Hg(Y_))Es31$&buby2!%P6)TlK=ZiugHk@)ZuIoPa2rV9-9Ba`AX}vOB}Sm{Zmu_ zy`RXw0KVzGSLLmW8N=*5A6|Xot?Qi9`|?-Z&_x(&ExL2GA@@ms>~^VMKdDf^efZ$v0UE+d z406OTiIwNXdjDue#6Gn4Y1{;jKlh4)DuVHx=aQSq9Y)WNAOmlE^*bTm9GOKMcg5 z$blM|e@yl`%u~<&v_;jDa~mO}(XY3IF*Wr%nq_pYEl+e$k|Vh`1!qrSK*ei1g+o4V ze9hf3iC(eo(;-PF>iAvWp# z2q8rMs5jO1opsaRV@U~FXMf$mhD~yn+~sn>C=F^699ovy$=AQ)qod|Fuav7W(HqZ6 zgK7R;#%|8X>2>5(aH#c%wo;~QdR#7>pcLidqmGa75sL4{fDj8%I{ug*-V^TJIYmDn zR}%Dk*FPAqZ%UUq1O=)2fpB>R#&(ps)fTN84D2iyuH6qHZ5e_nzj}NiiKZOwe9|X< zjouimTf;40X^;4s(}RIG===aqcEPmC?<5)Z5D51|U$$yi0gHGy|FSSpgZP-U&8f}O zKXFy=-5;-<-~9gk<38l|y~U@_&ob`B{^(Vo*QlPX*}+E@>3{+PVSuCMVW&WBTX z0H@itfRQRS#0OfB$x{&+#>Hb2+21rpa-K$(97?PKPM6i3LuE0c#&cZtuQa5`vY3u$ z^-GO^(N=bWlQ>07+764Xlv5aXaZ0T=m<%9j5)B$%xrPQdC1J=Cf=FVf z@EYO(5F&?`j(z{}kt{DqEIhw16!b!4{}nZzzNQ20T3zAtWQMM%tO}W>6fNl9%9(t{ z=(1*Xtv~$GX?!x`Bg}~?UESPeVZI4Y1X7P{>L?^;EXdxaE`s<8q5YU;a~C#`E6e3R z)I0b@ET#4bi(RJ7W3Ka7Z*a{H7=U^P0D)1TF4w+VOdmE?Rb@<0ty&5!>k0&97x zcI#r#1YL4RB-!{>>P*pbkPrz6B#K>)mVrD`nEduuw_}7c|n(P?Kmonc4<`qZDDlDU9t6Pk-Z2?j^>np_!2YFp&cx z103(BM5C3=yBLxvmWe!PTxcLNAZ?Ro?)8w=h-rV|e_KsGnSme@kXlDKrtpl!bX6DN zG+wZ^%5z&Hkb*k}F?qP$+s|JY4>4ee!LXZPC336uLjfWw-j=gPqi*MM%z1mB`Zd(; zpsF78-i;R})=Qq6m%Zb}g;BuS*Gqi&2K6|Ou8UaebJSbsv-D=S`Yo>D)~ld(wGgij zKEXCVan0pX0;ywF@L#<`3d0D2)q{aKE5H67$s80RU~kC;ig2%X8i|cgO?Z5+P^fb)kuz&6XWXIF8Gnu$ znSdZ-E~TLR-@7gXnN#{N8E(QgWkOuD0>fldJ998X(5ImiZ@W!1dKfTZLGH3VjfobR z*EqjSljVX&Svgz7;m=c0&$P{g(N?yu3rC8wojgi{Qi)O9n zzY0O3*?d}YTl;J~=Uk^)<0bbpg;!WE`Er$@Eu?FSB$!0t6jD?^T>9U0f7P0e&`^lO z9B&Pgzh$%Fez^hs=$S(z2*r}OCSo)5xs)pF(kKI2usr!*BGZ?2AK`|R|M=#I=*qPo zYp(T6Q$2iYD_uLm>SVeqRWA4|5#!QNO1K8K;1DsN!s;UAfQWOv?el_KH;)w}>++xI zKE%ypqcV`%N20POUAdKJnMY6ZF1$(hymw7g$poZh-nDuTb0_p@(*X-Lim^3S-Mdvv z{zHeyaVtu7L0;#KTs&+9X|J*%37w-4_V@*d^2};ugKczgZg?>&>pz$di)jaq{xa*B zpR^W99kC5BsU-ncy&GP7a9g&#GVk?4X++XK$tjF5vY?0dn4nI7{oYz##D)CYZli!Y z-#w~#CpE4}WW@4$Uiz(^|%U!wfGwWOLU zwP2xvrdr>9rmvk4ulDKLHOPBQ=A5gf7Bk#F9!(_(?R;meU#&w5jo`Ez;{p?X=g@-1wOU&^K=|FR;X}X zsvt32AyjtY&fz|Lz4!c1hDpY@fA7Ei`+CLyvXsh@g)Uw>E_w#+s#Y#4)TR1gKjIoH zjVHCr0u$N5u1M2OE$7p$piWp% z6&c4z<`0!TF)tFI>iW53@YnOSo(*gN>9B)dECfwcPJHCAE|8#vw9n;Y41v4Cep@rM z5bACTE^c%05I9BiiNn!>$67AQR|*&p&O6YqUET)!5sIh)>N#W`&)0 zXGkqTOs6X|X%Wv#_3aH*_a;HoSI$DP4GThL@eQwf7^h2ScxgAAWH?|7)qX&o{iS5A)b&7fakE_% z7h(sEA^S<6KiuWPr1l*^?p^HOxoU<=Zt#1icZ&;mAoAC`NWr%qZq2<|IX%28+Uau| z4p228mBrSrKs$BMQ_m|obn@=>|GUnc@dsKR&_Pd z(Hs91R2p(m46#bWcW#EO52I!zv0KF7tS{)(J1+L44T5OvzK#FpLCC}@gE$F_Cb9E# zxF&zKcVyvCZ=5AArhamaqd!;6DgLT{v= zzh9Ih_xUGoD>U#vbcDL^*r%mD%M8QgdXMeg3|?y*6c;2#xhGrv?k+Fs=daBXJeiCA zzE=R(gMQk|*D;$9EB;MOUReHn+UaEMpPqzH@BgG)7dglCJ3k+#>5#Yg9{B^hlbaO% zj;`{x_Ra27vVn^<_9;lTzW1A!9m!#lWL3jZt?lgKykYLJxNbpQ469Mi)juEhtK9Ig z@>$;6XwRhIybZ5GY8N@`(VhdV=UcvHzTTVPqP4jLah`A?Tb-Z3&p1YCV0|wH`cdq; z?p?>k7vyU_6(x&|iz$1f6>&nYBE=dsUiWlhkng$>Wv_ zcU+BPZhXwUP+@)hjLRF0DZMD|x;)=s^R+4>_jNVjVMXtW{9`8yzk0#N!B6`1>Eo2d zoZ@A;%Hm(F-k!0TZ4W;D`~1yq8TIr35Oq|+pT24ip*7=+@qL8FjS}WwN0wJ()PI3% z4xjR3!QXarG@|D&wFI8t7WU}I$lGx};($uG{UzdIm~Wow$$FPM@M;ylJ%evA^Qe_b z>dk{DQul%C_dYZD-VNz?Uy-|OQp{E2JqnSZ?AuaQwtDe!s5NalS4rLnbRG9BEZLl; z6{F1@I{RfN>+_e<{{kFa8`mF$dR-R0lQnf!o8co}-aTpbD{}HZJsSNr-ltXxC7+3D zGh>`}tnW2J*-Z8~Ssdhj%)xJadM-ZZvmjUTKI));?&YHsds?K~(?v1$|D)(${F(m# zIDqedH*=rcnoBMbb8W88{gTVvB{Y;<%1G{M!w_-{xm9z&BoRu!(%dE02uZh%lyn>Q zEnU9(?e{nAan56(_j$dauS?#l7BRC6QvH6hfuxxAH$Ht1qAw4`%Ri`#Vf@(EWznS<|0i=UW@q zUjwET4>fLM?gK1Fvi|(O9rpAUgZT+R&A`zZKkaHG7$NJDp3~Db2)VC%w*Jk$KDO(@ zz9)j~Xqy?X%_GX6_JKLarYPGhoz9UqRitP=yE3;zy|KrU$9ilAXmwEz1P_ddf!ygo zTXrHQn=Vr{WR1|PCrFdGTuAjl+Qk!sKk6M=7s}5wv`I<_UNvQk1|Q)L_ts+ zE7x@H!T!pN4*mD-gS*#%oI|nRuFt?+&-a7Zx^fS06NNdcvJD0k!jbPEbnm~|1;Qax zCS^jqm2#wgy+fcEFm3~3*3-n_1s%O4m$(&`OD{GixeMi$bJ1}xmL4jc#awcg8ToJN z`e`2*aV`3TGdHIab+yX^``Z-7gJ;~nRX!K}vj0a=MP;Ug{E1F0hkC946!qD2+#Vqg zJ1?uLcd~mfr~8diwGKP`OzQUY5<5cmn=)6+YGP7wmIyRZ`Q~o!RqxOvRxpakujfXr9BjRc zEk1apxt5Xb(6rTD*p5omkJk?$Jv8B6-BjFuDRsQC z)b(ENv2;4)-&eP6rkah!Pd~s;8ISkt97&2zI}xKGn0gna(LSwu*-jpPUE!VlJ}m_Y znG=SVor))`Qr^~%mZaWFI4!HI&{&K-Ncj1t;^-B(BsUGi%+to6CbxvyNn)jJ!t*O> zvc&CHIqDF7HCv{rZS3Mds-x-$K8I;p<(tNbbPz545|19Rt$w|GwEuF-EeH8@$I<4T zTUS52&>$|1Q5;2Jc;vW)cat+^F30!E*X0i2%s!BW8;Oa+TS**A<{+8`aD7{V_sxTL#<`*;QeD0gf#)wn5!h3 z4S*@!{EaqEcxRJa-iUw9nItb;Nz}Y}81AQ_{HAc~po67&S!rR@m7P8i-bJO9IjE#* zuXjEtrV+ez`sxpqez8d>FJq87qP!s{_WiuRv7&~RT$A7KJ^3c_bE@2{swtY}MnU1; ze>szinG}lmd$^AsaZH6^h0tX1%qo@LTRfBZZ61Rk6vc_c3xy#|ML*AY|7o6l!jfc=HctEL+>2T9_Kt?lqX$+fE~hkF#3KPVjB4%a`U zbUvRj^8%MORmN|h%ilB7R-`?pqV0UDFwZ9PwPcEEJhUrM@>8h%+IC5e;hT_o&g8gU zrbCVqgitUCGyMxHju+0imo(t!uIh;E#mU8sXYu58Y)%471EmA&q; zCg#q1$2$i_PmPo9*W>k?h`*JmQG@nxgLN7vphz1txfj^|P&+bz-XL5LJIw_jI?$hM z%HX3DR2>NGTszWaJ@((9w)*ZJo&h>D)0^{BBS>FCrbRqHHjrne>TiXfr51chQI#f> zfg;9*4@Ax_r-dk9^K+*fP@0W)jrY72;QZOOd+I8P-w)~KMsIZ;e9>&$TgAW% zaMJ2j&-^hCqKlFrR}NNKqT){OiDRMIA(B6WuuToDm!YuMs*TmEVUxk9i-wlJ4D%8_Wn##mRmsq2YWsHC(E8E?i-T@^x0P{m$hF;YU{2=0l ziku$GwM0p@k~^X6&CCxdY!K5O2=7uG(1g{|Fl`#zMhua{Qm+nRQnxPdC+5aM(O-FR z%g^&S{*7(D#~OiWn9}K)*o3ew=hTp#%FPgwqvc?e^<;ZeQGHSIpV-YPzuzm*bi}Ie zG$03#9f)ybWZV8Zzx=w$bpSnD?2=#vy}g453V)O6YZV8o3VVh`q%872W?{8X0M%lC z)<_Kve7bA?XtxNS0mc1U^xTO8h&nLyW4{B|EreMw_3q2aItEfheGF&MSdmUl?=hJM zD;escdPBv*xl%$vDde0=)wMysxXk+{ zmd;Lf#*5j5M>dCCc7Hl#UHqe;C0kUVYm{G)J$h&jzfN@+QT8ngNrHS@b_c*q09R4r zH~F|>&dNY5be{Ny^RS|ZO;vMOCf=A>p20?bx{i;9da|D*D0?>8R4V5{XiTRm5meR) zxb#j_dA(U~Rkn%&e$)txIi5Kg1}fx<+4Cj3IM7T6hR1{M0=^z@A{msSkPa9{0j3n zc^`L1bfBmR3p@#}k3QWLE&8=YIJNr31MYJ8E=@}Kd8HN@QX$bHH1N~$4Y>Lrse~d(m@hc~eQTPYK`0BrL%c-$atCtVoEc<)Tp{ zKulG!O!d&bsz;arF}i0JC^>l&LIp_Z-&Y*W|I)Nyde9kTh`aVp)!2~XY)mSrdz8}v zG70gor=4ZoZ@T@-{ra&UAIS!JPDJYSKokHZ9)Q&z@h`_k3+V!|8#_IdhR9(cZxKZaBjN2C+Jo2>t4D*7`aq*I_^0O}UNH}p7~OOvZ^7YkhXp?=oxr=dR+d-U1h@fdVI8$2k) zjVN#bI-BLZwP*rgvDS^Od8>1+T~VHcHWUtjMr0=I@kQ$rn~m0U^@;=)7X#-3^M#GK zRBxLpad$~WTTiL;U>`3Pagh?`;Kf5`jXo-)t({D1OD5W>9^b^5{}t+Uyuv=B!oR@h z)1R(ugWk&1%*!+z@ZW31@c1voxl+O}{^)R(*?P#zLn+zf&yg`{rfg{b&FvP+fOAj$ zy|Uuy*7on~73`Ui(JZj?XVK~1Ua>a49fFmF@d;euadeBv{`)kv91u$)X3^GB@qmA~ z8OW8JH38F#9;_RNcA-oc4>7kI+al?7zU01&b)k$Ybd&Wd5?rR@$2RMsSnqqGHecxV zw*ANdb20EfKN*DbzsGkUR9*~9;dkY&`+TMs!Pjo4p+^gGw*V-ZRc^-^bdor`O?ePZ1bain zo`!`s&njNCpRsoLd9_=LvSbntGx4E$QdBDmA(QKPOOaPkC~`httK)r0%0TJj`%vj8 zq^$7AMMm9keV4OBU>n<2R%z&z&4B=E(i*>DO^Vg+bIlOY-{5Jl%NCE$}v(aF`;$tRcWQ=Zyi zHcl>G4L`SQobvoe((eN+$BY0|Oz9F|v2>h~&0O1KLux~t>3}^hQ-WV&r3^M`vE^tc$cj~PE`8&(=_DwCPrU)w| za)c1r&t9-|p1Dy74wQr&D5>U^<2c$EkwoU>G7O!TnNPDM@T<2yBei8t>)r}AkU1?O zMd7m7|BCw`o0c&Q!K5-EjzHHKy!V9%4UtcCk=OsER@nk^c|j8A+b=DHxOqx*wwL^k z%4PTVRF%kJ@=r=C1oOp&3oAK5*J$aQYlrKms@5^5Yy2 zsMy38^2bt!Rx(}79X%_Zj{`hP!U(IUt{=;)(ARW&FKb$xxhHWXBji2gkL`=hd9c!` zd^ikIIByc7$)1y2D6Fx6|3S1w)D*{yw1-A@tf3Gi;-86YpU0SLL|_cg?C-ATdIA&A z=0)ion2u&u91Y0!lJ_|H87p{?7rd8AXG&G!P?-Q!Wc@PH!~W=*<3}qKEyAkK%IEG8 zKY!lL$3eWBwLCCpQgh>%K}l_mh`etvs-+W%4+bjC@WtHtiiJl8@5v9bz$U9BlJuxF zHy-@d$n(fD6(QKV!2{iaL-Bm@wQmr?9ZmbW01t-v%;GgicK6sn`lF!p7gZD!ltjB* z%of6aiqk-_#1oF}%-*Qp)9Z|(_oCV(GSiGKi{yTf5GAn@7)~i|lJE?ZN{aj#&6Iiu<_t!v0%^heRJ;R)F zbVMejU%`@ph~ZOHt?;0?u5CADPck1Dod%tGhgblJ4>AeV>jxZYUFr>jQTYF%)LHo1 zO?i_Gz0W@??Rhlta-1g9?_CZue{f-DZ|WbCYMIcMhPgI-ky!_=03vN$y=2b8)~sHe z<4yNxYd0DZo-6S-1I-@4pB#E_=13Hc=7)xF$opGKhGn3lxm6d(~bW`6`OZ7KA*Z|ZdiDCx^$)E;*keG;H~rZ3a_*k1t%1$ zgk(9eCA!V?>YZneK`(mDwL)cL^Ddk_khMH!@j^ZG^8Nn~pW0nb+_bWPVkKov2HO9w zA%6yv*oYQ_|yHwTmS(7otTtDy0(8KJJf>vV(<6$+xNeiJN@IEA?U@3-p+lA5QPN-V^+z+ClXW!Gvoi(Zu<_<7F`k15!8$ z7xurI3>>4yEQT9nssl`=?3YM_Qtg^WAH8)mTMZfPv*IC3=47t$@fkqU{t-Dx=0nT+ zGs?}Xk*-pgRFg*Bj|9Iur+#&Sa_(&!fr!9$J5bq_%F$%3j=8IT^N|)_5w4f|Fy2MSmI0PTb<8(BP|+Y{6CA8BQbK? z{sQ($)*a+qH+-qp=e+%fZ;kPF2dn}|L~{&N7Z51;oe~*a;}=Ao^_i@_VL3x4I^p+` zj*d}HhorkB=C8c>-0S)Tq1)8=?3%h*$lX-5(u%|fAKI6qq20R}ow|Lom!|xd)DWUU zn{mQ!w@%mC7q{a!HFRz}xW62TTfcc?cVO{~`I+^V#f)Eb#;Nr8^S*m`y6Vm*JFkCu z?SAvh;8MOugR@@K&~~BjV0z;#n{~+78Lij6+gDC0ZAI`|`0zG12#bs_)ai2!d#F1;y*;Z!Oo*E~@En6Q`snzITESTW-c}der)z}dt4){9%%RcR* zl5ZHFzpo~8yGLhjI!xc9Jp9i??Iy>pN8@>Aep|DKPh-A5B(G_=TA983`1NsQJz3s* z{SOlyD5`py1HsV%%tC!(7bRFi^{iir?*SfQ(I!UEo{&X~I~H6jmgrxsV|`0C{7~6R zS+LHe5lBwhAAM;5lH(YPG=+PDKt%577oGg{Y@c^+X!}C%YJtH-tvRG^)Io2@=Z!)b zPwELmfiBp(Z}26qZ?2`5T_terY3& z8zHRZW~$(Op;w`D7-a+^87ZiD+9m0tn;sbuPrt~U?x3`tG@0Lt&sS3rmL(`AvFD~q zju%@0r~|j-;0j?2UnaD_m1nuOHI>H>E7OI-P;gu+Y{Xrni94<``!vrl@PtAW&*p0t zDaR~5Q}%aR-nQ}6JMNB+iWQ)%`@B7{`C=5gtGp~_Vv{u8JnyXNomZNK5zL1W8=3#m zxF5k=5-%1S6&~1(NwMira_8ej$j?f{$=18>l6Er7WJxYLL9bl6g8Wz`M<-Yh9kkJa zUnZC6PU11)G_b;JZjK>i3w4xcWBumNvgA9*Dbtm$q6C*fyKft{-BsDeGD?s91&-6b zh?B1OAJ`O?38VN<08q(p`buG7xy+zo+Fq1S2`m~1>T~$eBZwnM%Owx&4T?W`?9lUz z%8jz^CQ+v9Dmzdp66&&VZ@hU4P||W22s5 z@}%Al2Z9xHo5B8jfH6Lz0fwux8ywe$g?f})dP9Qx&!zv91rj_qTzg=2PjqBSVxf&h zBnODjEXh4Ah$lXrgXzj<7STvd*i~}y5VyX-oWz8ZIZPyR-{VFc$E5Z|uvirjN`9dv zI!tlMlGD4VCCP+Y5tSt}IhldOp>!!_$IqVuEY)r{NNSp4R?W^&#MnrrAZX%rT=u&l zCQ=Om+{IefOUG!8qAdnMazg;t1@RuSkK9R3UP-nxq#j{`$dsu(U!-~qj9=($@qg-v zU7=-3zE5lCBg%?m4RgST16exC%3|Sf_}B}a9M74!d^1(PMB52l0+;$kS#k@TPMtVF zt|&VEC!{%8#9EZi$@OE~SPREkDlGv%MXBG^=-N$(sh$%TI4VZ#JNA0vA?(r8q-e6WYxqrRtb~FUu#m)0r&y{r17{w>l zpFiQrMU$yp+LUEQOKl(d68Tm&0sy{w8A4dw$wr1dplOjHtWZ9*4n(k$34Ms9ZhNau zJ#1e`gA&LoNUV%@Au-T4EM*!X`A48vX3c~-?Wh5bjlJJVg*zjUU?KpXei%{6z2Jn$}79d<^Z59VpM%69~VTG z5}Cz+RG$}O z2A}L%{c$f4W(=#F@)_0=VptV}s*%YshWg>h_(|#8ZRg!TE*&p9eS1{qks#;s)}6C; zUDk$$VxmVcjbR^?9ps=`GUG=KnxdP!mj`qV27nFZT)=7!pzL0!yZDk(DKZYCZ_bCs z9D2Usa^84mI*C(VKYP(|j3L3{OK<>_x(c270Sapp$EG=oeWlo=GkRlUy4V17j08^N zjieu96yN4Rjd}xwgzb!}2(3{=b7f`<1B8|AkvNmS3l@>$LW)j;MLmxR@esh26L%~B z%PXer26gJl7ZQfGGurJEX{+*wa#DOghtS|^O$byg4HeWQg1dv9Vb}Atj&VdY!LPLl z{M_m2EI{vojfdIydqoy1ifhR%ho1nr8VP_>QQ&JO)L%%_v{T;T=9KQ@vY~9gQarQ0#bhaC>YN^3dR-{S$}zJHNhrR0jp&T>?x2U_Vln4rqukPXvxwNtU#P!$L&P zQ6VCZ=rFEND-rjt1bcx3?gbNuX{k+I-#vUZ6#z|QQ>C^)%K5!HS%z`=DY2(g%JDzt>D58jSvUbrWH*efd__+M zN6CGAJUBkNia-O1&~xAS=axf^4%vY444~8Ly!<>PmR@l5SL3=7SxRf31qIQ>K~0q$ zxYwOsDS)^9fZzLCG~*wadM9v5tRjhMc7dbmXBh1QfVWam@^+cg%A$RAxTLCxArLAn zKs_AC&2rP`RE4K1(}{XuqYArBhfA>$vuy0rJi_58awp`1C>7}R-3(%dqLO?+W$A6O zg&ic2RCq0@zR02kz7=vNL$mnXMmelU0amZ~bh`Lc3wC!SVm?G{Ovt~clQ3x{6OvE4nxQ!iyKd3Od~~g-b1fV z;zUg@p2HQB&%@R@rvRxQvs|}9oEt<*R6YPgr(^7*8ZvlnLL6a(*Z8yN(tHXzSsy!3 zY-kmr`fXYB43T*{CRp5lxI6YmtH>-5JweCBKv==6XhrAdc+=K|j(`-C+PL$rvT>JE zR^%r)WDAn*XjR9L{>-^&@f36+zmE7zTpahx$KvMN! zsFH?cF?2wQ_6{4X7o8-$M7FS?=u@o}QFG*}<$B!x6|e;xJ-lkk!Yo=A zz=KO5!}M#nmcU_D>>X>ABMhWKGJ8$LUFFu+;BH9PV+VQgJ5AWmo8>=ILe#dO>YqL= z*$uu{=$F)uJVZdJ!EcayK~8|$92hJrO9GvG4#%3MA0rd5&J#s99l`1BAy|Dfd}6Q| z5VhONm75I*^|V~r0ALpuz%^|7BAH>sL9ulXX6^)2!0VObK$-yAol15ft3FxW;gAm0 z$73KVUtj7G?_v_V6@X#4$!`ddNmTP5*)~&u(aJ@=&Igzk63hR7#YA_@6!*xIp!T0L zle4(n7ibxw`>5{$x;bf6$#qlybGO4bSRon%9K)Q1_Nm+>xIG?NPNa%%=3u!Y9$3NYc8%&4%*^qzynXLvZPaBcv#92j11C1omAE7oF5>hV z+^w7c1o1gi@dZ5o+33{9)W1%FuTucai(TM zaT7c3g|X=iZD|l$p&cfcKy;oYebDf+c0&8KBCY5NpPa?svxg0-v%RH0H*o2LM3Kg_ z8wwmy`VwN8+68dtBr%EpXkdSh1YA4}eSFjy!pLk&nr90r-)fe@sp|Fg*>kq~M z6Y)d_3RUq~Z4tAV_Cn2hiXk#WmArw&EYY)hjEC8EPgCzc-Q8awa%y!d0Xdxx$w|Lp za8?tyMs>>ts``EfWG~;@^a(C{)>fJy9A5<}|IbmTBpyo)USr8PfjXkcs+(t2Ev@q^ z7F62PQLP-*I0d6xfSODJDW9A@guL|J13O5EbEKmT^RXYf_|1q}2>*JDisWohLPa z{y`;Ozo?c5Z>46zVNt(pu0;F({=7Y`vPl|xdxIO{gDF9rSbPjozt(tOXPY?So%>Vgm)Qtl@79~Io z!|TUGNU;Dz9LIiKfb}jD)LcVqx(l=gs9F$qcZ|M-x_G=N8UD`kg?bahjsy5C`C68g zxBnW_G`~xf7)9kGKT-&`M*zi_y>!wf#Y4(v833~@kPHrrv}j6ML^=;ncz0ZVt&e_P zo;(4A9Qxth5fcK0=&s_bixzlx#Nn$W5&JC1wNt^lD; zBy^`hPv}~=@z8zTG%M1W;Co|QiXLStlnjOLeY{PhoH}}40=^0&pD0?i7M%Aa0wv{F5&?Yvz zeiYScInfV*+W^LIT~-S$#7!_@YE+;b+T`zax3CK`jPmL#r^ZEqkrK{^7>l&|`s<5t5GQEtR%mF>R7AyVfeWvI5gYJAnoFz-nXVbgG=X&r&jZue3 z*PajU;Hgf0Z#>T}S}V6mmPA|O-fe{6sJj(0aYYZE=X zuC28SrEapCg_LugTNhJ1MTG5(+RL| zP`=j!ADnLg=(X6-4>2!$v)*|EK; zGfKx>YFg$s!FFyQ&0>{h1J)ABh`tEC=_UQIvyj&7pWOXErRY5f4eo)-2klZv?Q26B z$hWd5I!lEG@K;9O%Af3;6PHgJDV@Aj?xw_&bTvfg2Atc4l4(r1+5jy})Y7$M$wlR1 z$5Ziea>#-*>=Ug(x8-3QP*=Gr@7pr?(e2mVBkWALg2pM6QZTp6RFqxtIr9Upl5K*? zICNtGKKOyytd7{_R zat;^uQn?UEjXy;3D-n|%APR?%)W7Tn_jHgsNMNWaN?+LLAfdafFIa1^_b2x5OPde; zitXU_X{Z@ib$`_?*v?)p^4l=(SY$Gop@sLFL%$Vy=_uxw>$zxHOGK$wD+^gvQ7qPok^QW;Me zp8@-U0uL;B$cs>Mztcp9#7R7s2;6j}nHtGgg9+WeyAUD`sP44}!tvx^)fECys6Kj} zQOQ8o(a<$ys8*yEChE_sw~I=#f}a}oDN?i1&} zT0?OhRrRx{67{w!8nl%~Prj&6t04l64T1mYzbs0O84Lm+X*PRhwVsr^>h(0^e#PO0 z*c6YSwq-@7MX4X7@!H5y^;cU+!$@2Dra)DgsgOQdXqA3@-0A0|OTz`7vCJ>OAqs)< zMn~xkwVmg+ZZ338^0EylO29vpVV=oum;IjTh-j>%Ut-_LH*u-^3;G@|A4U>B zQZ#_W&(tEsi?x<^#-uVS`SImrLxI360)?ODeheb=%O8ct&eo!$^02)M(_mx&tpJcU zg7BIQRdAu0B(TTiU`C56UjHI}OWnmHBd>Z1^#VOEPYlw&VP~<3O?cs{u3chp_hzKf zJdla(h;*>9j`uX|4?8S42q~3yFLumI#sdraA8)_lsC4P0#?35e&Hy7>DVsnMY z2~B%W<5Ec{h=WAo`7vwc3#4sJU}Z)L1A)kE?#m?)Q%323&r2- zY+sW-N8{{KbuiJo3pzDn!AfcLDUJvfw&Ly70*~s!usn{8F;eq@NqbR14_N)TRO?p5 zaj|etJzR}ytCwFdvc^YVKKo0;+k1qmO!2?Gm7Z;=5mTadRv8>dh8j4=xpEGZk>rgL z&D~V`tyfLV{(eycI4%~GS9X*rA~ae8>o6& z6gmr1oS=+pEdv8v+ZMjGI-K3~DeiHI?Vl6<9qk{xI=18<^Y875w&tGB{QoXHm@6ia zDo)d(nz%hE6CQx>@)EG~trSY!xEB9yh4G2wvP8<_JZO7znV*NTC|j>SmQ;BYMSO1G zQ34}#whAv6DkId1HeXzd(u7TR#|K_#WY$6fx|T8?q>Vt zb@kr?2bI9XwZ#Pi!}(`8dn zAORbd;`1;aTez`ZqKDJ{nfkn?X^j>YdRukM`s-pZr#6VZK>C&uk_+by0K-0j-5 zcTBr`KI(2v)4?t_{0ttd4FDeSw1h+guwT_9a~h03Zxs2R09^D?xog^~-l;S;RKL#de`% zB1BNp!F=#q!(?I}GOwycZzs#Q2~jd5RA3-GiJ~#ztpTKYS+pwoG*TI1 zps_Lg(7-XK(tC|$h8T_qPBYU@189=-9yHD}I4)&ngUFjb&P?thgA}NQqj-#?Nj?#( zLF-A3M8z;FlmV~=E|gs2R5Jwf^v~tIzrAk(vR7dwb0_ETKfm;x&0}O^0Lit!?TNb;}od(45kvPEFlxgqZqAEJ76~$Qqw>UB3Nx2 zNO%vxPBT1D0B|JGzGdUoW0`7>!*2u^kR(Rs{b7GCmBZI$MXA$#$0D;;**E^zzDF`7 z+R7uiES+9hr~vKCVM@z9Kfj7mnIq2>7bOGS6)CJac0m%sxwdZo1xsgCgPPhg4u z-K51FKemnrEt99jvJI(x{0~@{l4T|=GV`}{tx!5DxOzFsth+h*TFD2dpb40F9;2G|B` z40yXWKRpP@iQUPz=R(36^Yr}o|4YPjP}K^>rzoe;y~6rj5sBN0YbX~n?827}5MkEI zby)lyOvC60v1pYI)WCz(rnC0rnG$rS6kd2J7%by7fKT|M>0ec=4DGw|OpJl~3IBsML4gAssIZe2MnY77y73$^fs`9;VOZ0M ztPntMtGIL34n*V+*wwMT{LOBS)6t2mm$=zlN%Lisr9kVnbS#EkjV19H6`eW^4! zeTPD(2`@9o8=g^vl@XRht-lPAp9SleWD&dHUUlyq*v&YZ7_<*s613jFc);6_HSqkZ$Y zkw;Sb$HDFD;Y!|4;c)j`Z=A#0tWM@i$>CD+j-8?Fhi2ULSPC0j%t?2Bv7-vLTrQ5l z!&t5|QQYSAdRD~ra(oZ(%jK&P!@5V5a%g0w@Eu`mN3MC}Y?RBI#N@m5rFR|6a8nvn z46q@A1Akn3m-+oNP)`dK5{9*Bxf8PiE}3EjqpJgrdmb`mh)m*fkXCZQzGYB76o}bi z5R*Z=!iLX{Om#-4DuBr`l;tNEU2m>t#mH_7b*#mrd%r}krg#vtjXl}4&`3E?p`MJ$ zv?sb`y~_8|S^Qa>?~1jF*mh3~kB+vGxc2H$TI25K)cEG}{&zzUH|u&gJHn$WzaNt% zgDd`#xSrwpp=q)2^U)W1N(ZU8+=WM7HR8C-rBJ}yJx+VrPR?O}pU{y@wo3lSX#f3Q z_aswUUINc5$Af2fqMKVj&P={b;{e408)8J}9&&Elt&cc2K5$EN{(E`cz~P4>mV>KC z-fR8e92rF_0fzu1SW+h(&y>Mu>JcF#E+DxoVFtb0*qSjcUagVCAZ@QexLAetqEZjb z{h=VspJ-cT*kL@>n$098XMYkod7_qL<%?-0Tn}rxDf<2K@DYU<%n$!|ZI-8gn1Xz1 z*Ezlo>-(v8*y_73H|N8x;KEy{VymzFdQx{GCVN@#WL5|lhW*Y0??Qseu&I~+0c>_E zm!(-=Z=am)H&76y%t}+d3*uM6e>iuOVc#^reDU3qI{3_=2z>Y|Mv?=O-V>r`y)kE5 zF&c8vbtg-YmU-dMN6W0-0G5Skwtiq#b^+Eh zu&)OI)ms5bVx#_GwRdd;CK+_n7kXSfr$y|3!xcAw{g7Skhqf!xH>AHvKK;7=Dw_Y_ z=KYp0eQw8|IW3gSf3Q3^?}`1=oU!!H{*6OrtT3H#FDekg5{48JB^?E)56j#ZLE~3s z{xi>^k;-o&FZo4gdrw{R!WTwF?gk}q>7U>%hY0@_`M8}JFynOfl{Ie#|2X5f05@f9 zJyc^F0zMs;;ocN4sX6{VGp__8n|Ce`eUchX&=jJ}?|D^?#CIYp4goka2v?q|Bs5z& z46${F*fdj%1KLN@7fE?9kdWQ{8lW!@l)qbj+48jR4%m|l^##CGeOMk`$R{^YzD0=X zxr7Rdnd^^E|Hi7T|KUCMSvRaq2KXg^4ZhQ#lVIof<-+Sjll?Ed!oP&+ru?V#?V@dP z-oar z(X|6-JKp{MT)Z#C5!$ByU7C~q=|{$ip&AFZlh@sMi}R{T{YYYii`HSLe` zXg6*4HAO-WM{~ z;`+Ro#;KCZu+J~=pgqocsQhn-e^1C@RRy^9;ZxGdso=90BW~+%E_C?yp8E95=;QLu zh$mgwO<&81tJwF^M?-()8Gdtnu5;=SdHW6HeC(&6UrZjS{>y9E`tebsj-Vh%^6zGk zfXmcmT>zzFnBDq=bkiY*0c0HVSyVaoYI3~QeVByBl@}Wz;rx|Y!f=w(D*-ALm#m@< zhPkT`G_wu2r%*0jPq)*vdv7b{3MVpr?^r&x()ZYfjfGs*E6JAvwHlIZ3T!6w77O=9 z4}_lAj$T$OP7CT6w&Nh3L`%Od*c6*C?^w@h_9{rshP66=pV7QQ`dX-*o_=%PV1xTa zr79%fM6LRGP0HK2Hw-`>X7Z1*HC!{VF~rh!1ExS%SFo}t-d*r2Ke)(PWl5+H2@A-t zVARXaw7P$;yYI{b>R|71xCc$i(H-rW$kbm^9*@tPcC-aPQ*k%>9{_7Wl)u)nq6r~r zFtI{J43LB$ff=y>$Al5@4RHqbg5kZbLu#{C^7~O9AqRBcp8D{ zT>=^G`UfF-kYPj+I7Ad5)!-qk-+%}pu-`}o8ps_8cRZqszrY+L&A*M@vBDM7w3B1d zef#}4;DHPOo*GvOb5&0|+VHF3z@SNkO=YJ%gYe*$TYfp_gU@5u$wk@Lzm?*{W}lIqq$rS`bM?rR z&N$i-b4nuw6wv{FB!##AwCoLW1sMZvu|fhIaKNmr5>X8{+GuA~Qb`!(VF_fc5cBvk z)RO_i71q4Ncku!!zyT7lfUPOqxJ-qldVK>N;E=|ZbP=UjNP}_)ydVZMsKLB=12`nm zfRW76vK6FY8d2F8o=!jm6}|umcj`b4F!7Vty-s+$Ie`qS!m>NzZZ7U9funAgvsmCj zg(`&q-3?c`!k=vraL6N-RD={A0vPEZ@(>pRS_Op{n1DXtu?R`XGl3Ia;SPC#!wDvU zgB;|51{lb|u)HHRWXWnI-}%l1!ovXhk>V4ODTZO5!HT7Epnvd4Q4*by&j zaElBF!AO0kW)cp(AO}o<(-!W)D=4^t1SW|iMZ{(jlOPL^$il!METIV|9fL5>&;=p? zuD}5=VB?TGiY7u6s?de{=r54`P>|s94tS)a9Oy`gI^e<3jdHZ3V7lc9JXaRbiEalf z+X_fizzv|d!-Hw)3Fv~Cf?EWM0RHgDK2pImm%(5fXEEjodbkyu*$ih7GS%_7Agzq=C%WoC{N*bD_eWhKX4X+oXwqZ)+(P6_PblZ{5(Y=M;@NTDk0h z6Rco{>Vpojqoq&kWU|=82&9?{-tAUrjtiJ9heI*PPJ>!Z+XWSw_4pz1gcucakbs8^ zCX->OdD-X)Njf}9-c!Cbj%TRi5qY3O5kSDzdTuXR8Ca7P#sGyaz`?9(eF1#plOI{3 zjRScY1u=>NjAtA}7rO8T97q5HI2=qT`!(~Zesbm)v$@TUO>>&jY*;n_AD3t|Hr0Tk z*pnH%xzBz!pgUaHIb75-Vxsf#Pg*Iw6U@#h^^hfSAbi3bQ0kBb=q)mBxl9u9PPoMk z9yI@)oI1~#xy$oMkZ_FWdZ0rZnz#cLU=<(gmPCCGSiumMjD|a8?G98Jf(tXio%?w8 z0r+HvG@b#BWwXM5WDx5e#_u1;RdwS0_ROLg=Ee z&2F|Xih+g<;2;ken#-IiYwm^)EpS9_&hD-w(}wo;^);S z+TByHddw-E)cB?5jfeL7YpO-+L0>)YbAK0d0MCYadYNfZn%WV(QYZe1$1W&+yR!HL z#JhRfjz$YiCcb?uC~k4WSqf_1uO{y_2E4@q5AGv9HAt8LJqJ9{F%D|bf)G*|!LXqw zt&DsXjxTt^6M{fbWl@CZjgSR=eV!`#0x=u|8Du~bC<2Dq#qn^T13uuowBEzLUV+(J z?7>LwA(HXj9t3va>P3v!*$@ecRD=zmN&!VEnG6c_!cKq`3fLA3iqZ|0l1>oSZh+8f z*dXsLkHQg`2kOO~iQ7|P98aJcH7(D#MbQw_!#LCeDJTLNT*3834FgyNevAhPoWMfp zhp`aL1tbCINdqykf-0bbFD%;_WB?O10)}uP>ir-b#vy=7ARRuDPjKK~Or0F=A-0{8 z?`aARwx9{FmQRGzop{clkd(`ifDW+WPway!1kVcp`o!jx7B1L@XZ7C8xJBJD93Nsu z5Z0jtnqQ59TRZGaK#>3(J&mkXp-GI~9eEW4i~s>V0xC$uFVF%ir~)w50xM8K23)}- zl*5O-;U^v=GO~s!E~6c$h8`v(H2#+e0S5^Ng(7BH2?B?l*u_31-}9MPS)3RS;7JVV z!7r2pHV8v*+{p>NluzixYXJugctSa#qbUg52<#T4Y+p1g1v8G~Wi1c9JP<38!XKbP z4hWg8b;km9mHK>#8g0RX)PgQF8!glV0ce6iNr5I1qg7CroXJ_7^&?64zQ z-BZTp4@MqA9^jIYq>@%;}&2 zCEQ3SI^|x{SzQX@RF+?mRL2A9!Xv;zkcm?`&67m5hbsJnFR;QWsKO{b!W|R=2UNfo ze1cmd5L{lSZmM2p_U5z+U0!(GZVu-nc>`n~=1>^g^9h_i*jvx&08IsjKV(C0^$ZFy zf~WZeKNv$3a2=jNXHmEVKklY)3Zbe0U>s-KgH%a_D%g$njDWCxk=S$x4v+yU=)x#G z1}o@7kHLWyT!A9^f;znAG!dtPR-Lt#CmjmKU6xy39w>wskRj3{0muLznpr)N!wl#| zNMXXC6lMw?ff`f-V9v!&3Cgd`z@a2ccHR~&90H-}2^ru)E-2UWxWi9a=t#z;f*z0Z z5MdO_!^IJaJitRcu){ZS%NUHnRy|EalEe#)!6R70BWS`W0E0F}4@}U4G>n63T-I?# zsFa53n_`anwIrI_So82;O{smzD1Ma1n>RA*$6?E8G zjg?QcceX6|U2Fe7=E=bh15dfF$di5e^Dz-j_QSuWK;?rzxpe}I-IG#>cJvM zxcX_2lIyLa=ea8DKaii^rGqqlLLQ7k5!?YOlmn2yOSw8-!zL`sDiy*0sloncNTTV= zPMd62e}selF`4Z!`@ZwaTu*0<2Iw|X077p?$ze3-#%y@?k@Mz zrSpDoBJI~Q;_m1FnrhB!E%>JIP>iqguIcConDu7w>DJ-)cCYZMZ=B6;C=zc2Pw@BRFX@J` z2BTj5%J1KHYwYSS1h4Rddaw)kO-fqu!;bI<`!5aG?hAu12tRJ025bZ3u*C%R_wndv>)^U<5QDA460(E-X2Y)W z%LeglJY$3Z3UVGM-5uhc%Z8%CS}P>Gu_3GJCTFkgu4E@$uqJ1+0!K0_9|ircZ;U}P z8!vMECh-u*G0M&{{620hw{jOlYvYzMf>N&^_c11evDIF$6c21D<1r-jGU|#l<8JW6 zKJ#7HF#wCL20N>_nlNzcY2mu@)tWFI%Pg!eF47^gFgJ5FlWLhx@i8m!A+NJ5t8yj_ z@hGn|F1IlUV=MMbb1EydEQ{$L-|`m+@Es$wE(i3<79BeOGB7tq2}^S^lk!1xax&Yp zIXm+yck=~%vnMn1^}=a0f^!B_?=@SkNNY3FG4ukTX+pc990Ka|`oxKS!uRTeKc}vFtxSyD}$s-Q}iGwFeCS{SS#_=mNF3M zHTe>AUw1X^!t+E6GC!|zC>N|*GjA@hbP69e&C>D>6ZK$|@INm$OY^W?uU=LA@l{i_ zBfIWalXFg^GG_ZQX``xWk1|=8cJ-ol?&f9y_v|Z!bNe#0Wy7&sGq!6RvoC-0Snu^& z)AY>>bVTd)M*FpKr?qO^_FOwLQ2Qo9r?O)|c2Wy>N<(u{yYp-l@$yP_?rpXhcQ$YT zzq3ydb1egLVjplxpY~kaa9!{5SBErV7qMt(cWS41TqiVnt93TVGDcUle4BG{R(4PS z^>b_YO=ol&3-)NM@l&t0b9ZxnQ>{ct@O1ktWD_@C?`>sUHg~5nq zw{w6ecPW#2jrS%;H+N>Dcnn|owu&=T!!iRucrefJKzpEwLok$Ew~1qOdQZ4_uXu+8 z_D;uc%*uF1(>Pb>WfE(6)q?c&GI=`xxT=OVj9Yn;1GwQTxtX^%m-G2uM|5%jCwPhr zFn?1yq_cTFV|l1%IBGBXcKbJ2RCi;C_?SQNsoFH7b2xgp_azTHGG{Y2|FoS4cdGmC z%L006f4cN0Zh_}^>GtiGuQ@B{`XH-uk|TMT6S{)Ode=&JmCN~oUwO0lucfmprn@*5 zC-$a)IepVLsE4}!j(WB?xRtAUanrDq1NNg|b^^aTk|VoLr#RwGjMAUNrI)ayhZ6vO1>ZP$1E*EjWKgLe4>yTbeX ze6#UK8~t@7Zx$bVZ^yUZu72rfcJekp-1EDUZ?RT0e5WIN;~)3Nlm5~3JgfKlvM2oG zXFk;Df$}Rq0W}Iwb`A^zPMw6H@CaN7Za(*Vd&dud+6O&$OFFdw%X)3^y_7?^Qk#E% zEAF1dB~z=Ja)&!~1H9|2cj|Mt+erCh;ZRShYuk} zlsJ*1LxB=69#puIV@Ho4L537Ll4MDfCsC$Uxsqi|moH1^kvS7)O`9U!ofxr`XHTCb zT41_4)TKRqO?)OznnD~=r%$0qC0LPaRjXIAW~~TQW5b6T|AD0{w(Hob3^!`ss<12B zuw@yly-FaiRk~`)-i>%suUw57`@WsX(XU*wUJFxn8}@ACz=Y|9qn;>wR1d#ozC zGUUCNHAfDe8M9~8mJdr+y_$7v*RNs6CNPtxY}*NQl2E$;8->u@tMehMJrv`}P~ntRB~bl0E^kOb{;v?Lx9f1^**a%rVI<6SfKSFq5bYM<~GzP2h}EPD>!+ zM$MFhm4uQ(OKQ>oQL4U4w32fi+UF8PC*j7PgZz;t z(Oc?i^s+|*qw&Qap^R_AQUBsm$+<{X^2hPo<7-GPUtR7l7zyCV(?o#iUa6Z|W*Ulx`d zXO(Rh^Oc95k?F?g%a!rRS{8Qg6;Y10ZK1!tmh&m8G+XxBX>%g>@nR2%j5P z_;4pN2KqgC;fWXM9-Wdp;e{jWsKlS4<`o-}-a(4xc%Fcmejt75(2b`S5b4Mp=11s_ zBY#q1VW$)9fcPk$M64QNN&QXy-+d7U)gXVAQMXMQBvOc~#7WAdzsCHna5lTqm0Wi$ zrS)fl6~oKu8knM4b%$|kp}yLi)p9_+xU@+?N!l=!Z|?%`c*Z5 z9OGqq+nfFzg|JEtka7hpAX}?pZi7tKlwGG10z^L3Ia*Bb^NLl#6Z*~)|L={5G;}c@rOYr6%o1_P*8WPoUp{< z5Py{87nktpByyptho~~62jQP2k%uZdIs3a;OC;~w8qW!B! zrx;qui~_ZCm&ipo=<$$uSfdsn{Y5SU$A=HS9j{chafW1F|*$)F?;k3euWxORosw>*2PVC{{wPs+h&9NdG}Og&izylp-ow znTA-QBBZToRqKk1xDP-S00ClvNI#}f01BK#tEr7d0f3NKP80wD%>_UKCIADw1(7i> z#VJG)T3l5IRF^ar$YL8?Sh!l&AHYZ~2#fpLrUXc~fW?jsH+ReD1T$OEwC{cIBu!^( z%}sui(*cVIJf56@1_U;6fob4P0lyEy2PSax>ajdD5_o$(S))tDSb`|{S5AR~S1fMe zlM=-5yQxUZI~8hT5noRsdE6sGj?&K&01|5myM-bXVvl{e45tHWgL3*xkzn(^T9542|d%fa+4Zho(03_ z(U!TVUEL{cnjcCRmP|TIP1wE`w3A{2I)QEcPT_BARNgI}ydF5)9 zTX^I;Cu+%xd?Z9sx-d!`G9sK#Y@iQ4u_E4M0|hvM2JYw(;PQ3}+C6S^Q_G11EFc3M z$bbWyTL2B*If0C^u_8xGQ0@}ayO%C%s0}i(QU4Fvjeghv(wsL&b;a05MrJSLo5J}D zQNH*!_`x6lq+ceo=|d~%UVx7m0YOO;;yaP}y*wh}ooGO({E&tzLM%2uwuGGE#LybO zae)exUks z!kgLBlh=AhW(w%iRXU}RS5)53j3`Xd1IGgC`^%QzQp>BYJ%bOnEz>PpTKDDkN_Q>0 zZ}02>zGBL&UWu_4^v7AtZ0oY>f!9{0dCySQ&LkFkY5O(9^ml* zyX24G@{PD8V%SQG9tgl?*2W*&P!euI9_-;APRefJFf6v~And_c2xbzlkN~vsQkjPk(n6!on}NQwaH z0Udy^5~A%6Gf^V+>K1eHj=~P7>>&>0&kO%z9S8=%IL#5UFcSM`68p}O2p|?iDaZ`3 z5}WY~vv3OqCGjRD6e9`Wkg?c$vH8Ri5Id0+Nl87v0=N*M2BzQumf#`a@d1R(tN4NY zyl=TQATtcY8?aCNs6q&FiU^Hx9Bs{jxGR8YYExgd*?5Fe@k4tdcF zwL@D-i{M5nh7j;*8t^1hGU3j}z9MiqNMHilD0n&`0`3STq-Z8<(s#hg1NCqq>fz;% zM?*YfA56gsh+q*wP+sOo1%qy_Vu1#df_Ln}9FzjZ211UGCk0$#26mzY!~lDEE}wj^ zkNQcC)(T&k5LCtxe~=E-`p_Ypa3L8h@WL>(3}}FS?Ooo*=<4qET+tp*>R~i-(+KJq z^X45qB~$954fQP}(54Z=h#*#q+|;Wy)XO2VERu+drTXep0L;tO&7v4mFYSRZUlCYb zu^JOaFe|gzkc=}u%`@?1GkIw<_i`DZ&La(C5ku22t1K|@=rU`h{kRMN$s{4lT=P<3 z%Qed}HW6jCl+m*65;ns^-V}}L@P{-_lM)q$0046}ckyH7veGCeFZFUe!Ag;KQ8*!j zJ^O+-IpsC)?Q!_VBFy0cs1N)o0RDh000w~v5MT-XA+PvRxenk1yyqbF;SG?hD$)`T zO;IkX@eP5mrihcxj1$bFv&Uo+180ge+4CVn6k}ZINODM3=(8kkC?#36MO)(mk*FoJ z2_~gz1!ArzTCU=3bU1SK4ex=DIF29|F%`r|pE^Rf4xqUZ046y?j8qT^1!5ayET2TK zS5(ZMXmB9nX(vb^4Qft&E^G&f2gZPI1*t}r1oQn0qOwr49t2DO&+H*HC4m~2aWMZU z7b_|qORvi6K~8U>%3e<~tx?MOCvPfikszrTK6EM|F;VFBE)(KHL$D50W2ZQ>r7rSe zx=Rv3NT=kX9onH^kwU#!uQ|W?MDMers zZMwj!FY2KjNQgTH^%7+<3hgp)zQe}qk{l~>FA|Zpe2Q1+?K_AQEmG}{Ow}P!^-};9 z(~6bwCP<;O(U444Nc+@VOOva9!C~-f*hIBGFBKrGDpskXqI8wM5Q87IP2%n|00@#U z`V$en;Q+FaK)cUCHDEiS@8T!|P4DRarn4a(W>B_khCb#0j;xaz^KHG};T!UAfZ!D| zMz&gfs7XwcW>iFnT(o6fRw`ihh}4B$+{Jq+@J4^4M`IF;bhZP7G$FKyOP9bS3YNK= zi~1;zoW_RY6v7^2;RM8I3*3k0{Nd$xA_l%d#;npxd7?MiCn&RYr`o6I_Nkx#=`7JD z9tcVhcPb$Pu^_C=qi~A#FeNUxi!tj?L{DltuQlojM*oZsqH^k{1T!nbE>of-V>Ac`!lZs8nyQX?iaK9w^H6Ay5?N^t3caD%gQ-(_=u zp>rpZUZqu7Ue|N+FY>0$kpiO_qitO=1$9-o3@f+){uuIZaPzQ+cl4+e98XjKCN?vM z@qqf)cq7mBCINWCv$#k{a(QipM5r6&K~iVvZx^N>m{3yEOaAN>bAg4>To-m(7BTPv zK;viHc3@Kkb_xOj5%w`3jVocZ?LckzE(B5m{tqJ5b_iw4ZU0n4S&-c_#bPH{bC=Qe z@^Ac%v(Yq4eaV7-KSdKy)cU=#TjajH0Cyq9uaIHyW9hdv$kG)$CpREm(3vr|Ll-^bV&A%aN5;E~)c0 z52*6`_>Tjb@LYAOiV>50YEpW~Auc(SSvh+5?^$K5t9%!y{J4Kg`SvEcePxPN!$OZi zrk6k1-JTVcOEE5wu@aFEfAH8LgjtkvnUn>&+`>eakTWjuxGgP4&S<7B| zmBovM6=E9-U;tR@`PNw+254aaAs+x#K=%=V`SsZz!yEvBohyQj%@}<>dHxVZQ;c~+ z2|$m%v-NWKqM+&`@bElNam)r2h$OoI;8HlFHM&ApxOS+CW-cVh)~R-~1Jq;1w` zdvYM0mX6YZ;=2NzTL&`zm> z9tg^>6uDt4VWO6fAPSWmz1yb;HWIMZx*qtft!KHiCD<9Fdr)qh zV^i-lrAPp|O1t@_Nn8zxyl1mS4drp9l#B>CDuuP#eUK&r$?m~?Z zIWf!Oc$fL2kaG&xud257A(&8MN_(;PG%FH0F(2ty2#Q?IYz;>bp--9E!X%>qK_0$= zd`qhw%0V#Yp&VE-ZaBIBHj~^TmONq!%1uA57aZyw6>-eV{Ep5%%@f8gHmV#5z|7H{ z567@qksQi452KoV&Yg7@E904=<%16^-(LICLvwa5ms%Aq_n3Jg6k1Oq;>{QRWuCnG znlH<dU~6{s z!Dr{AlQ@br@B}-eMmG>7Dx4s|M|{-BBl2MmHsAulK;E0yrbnzKo{~$`03Wz=1a!cO zM*s%8fv9)FDz_B>i|So$@ySSk&TNHFYBE{rE<%q%dl{oS(#;IWC})u(LXiaVc4=zP z;+$I3Ce^KCEg4GBBuj02N9yXvk?(rvxC;LK`jM& zI=gyeh4kz+R#KqedLQrXtG-}x4TeD1WoX{%lhUe*4r1Isql~YybNkGEQR`=S>rUOC zpf3SdfCgBA1!!Oc2!Q$oBE08$3J_oiH~|388$lmpLAy^rK3;%?H*&Lllf}30Lq(yh zo%phy>#v^wmyTQR7w2gR2c6aZ_>uo5*j;uM{DozbCKr5XaWeYv-Jy&D1cJvbKcWo1 z6KsxH#6?0%dC+P{fCXes2KFHnsF()xh$&Uv$GUh-iwEe!SZdHz2Z?S|)VPsuA(sI{ zQl)?Y{K=ApFrh+8lg<@9mavjTf)oiFOgM?!xpdkNA{0hkMIp3@1lq0XHCfFW#Hap+E?3@85M=TYLncOE6>a!3!I$4T7k z0p05KpFCNYj%wsswNlQ1B1xJ=sZeD>rbt~{2P`t#Vx!teSBn@QSeM=`* znzP@O13>I$zqbK_829P}Afjl`n}Y;A*c0T($pIR)q@MwpIQJi4+$A`eJ^sKYP&wzI z17Rid;P0MEJ&KCPJMRZW(v4X39F8?RYH%NBffTv zX}Sq?TtdC<3erB5QRI&`2wkGmY(06#mPcjvB-KBXMP=Ns2$@I_GJhhnAc7CZ#hta4 zl%$ieAE{aFvAvMFnnX(Rw5%k#-bPV|xGB5rxN5e$nYr-_gxj=kH5->jRmFRYZ2yvE z+KV(TT%5qXGPv+f5?4|g!M+*{ajvVyJ4tgY+IH}=iGI9n$TI=U62C(!yqjtN{>B?E z0l-#!Ft-0_JA$S))>~D1ED2|AzMEynT1)WuB-7GN!~CzlJ8zp}jpiI+;K=&`azF$> z)puXLoD^_?e@_MYfj<<*W6A~v>`<$4EzMdhOZ4En(#*@Mgki}GshktAygdstZcZ!I zwBHLQ?BY-q$vyPQEyYTC<(6NLdFGmL&N-7$LfLufH&%Hi2^QdDD~@Km>1n7Vq%ciR ztCP@rsIce6X6cdA?&%NQFqw~^f70%H@oA75%MG83QI9vFwtxvgg{*L8raC$Q>G4W& zdgTf*^nzh3VE!q_P^(H>{GT$2ZlphWr%nLf1nd*hKeIK&a<3&W7|*l+7~|WMn@Gza zMN^2>LP9Ol+;18)S;YYoAchuI1ZrHV&c|e;CJ3!-DE&KE-%vCZr2T7Ns38_#5>*du zMD0}{WKl)xp%t2uOIHbe*ijfbmyXpVg)4j<Rkr#LRT-AsW_Y~TYUXhq3o2#3yb z&=Chlva(dLJ0q+I6qhBFAR3J#4uqf&l>(pwP~cTv^acR31~%K|V+sW*01*BYpac+r z0~~Nb*#vYBGP%TkRP0v#B2ue*lw*n*~}eCmpkMq{EVy^i-xVrO$S;Bf#pW`Kj9xAa~gOla}CDBt8kRo1t35 z^)4_z=6NYnDd0w>>}0+9(P4bhLk~Yv@u?Clq9pz>6{_@fzHY8>nLEl*SI{FduGE8N zz@o=wAi*npEyy5xV;9%-$^8nw8DQ9s&^8o?x5N%6--1PBKI_sz*T@)atZ^t3^F3SSd0_>U7aT8}({N>H!Y_Sx9A#CG{0nJ7y1*9qXg# zsG?X&hF85x;;VhFNLp#**QK&hHvV&*Q#m@=sHSK*1GB1KVT4jRN)C(&p=0DU3fZrQ zbdQCIap8RVl-b_SZcQzlWtAUVUd%Y zFXKqi_{w*_^sO&JlbHwmR<4<*L)~oAb4_fLK$`)c=76ioO>F95gTNanIftjcdL(an z%+tpi#y0}ERq9eBh^ISn@F@+jP$%S|o~T4jfO}&9xO}Q=0;>e7U-ay7#?XA3dxA;; zE|n&`(cK|S)VtCkPY}rX*#|K9d-_<2!f zeiYVThS?=Rgz|ZkeB>=x`Dg6)A(!#vfpUNWVthR_r%+?4Ro=!9OGmwd)drx_KooC z>?JibOIzZzQVKjx0!x#e+DtI0PVj;w)Ilx(QWEEb%c+xC(161JxF@K}w~y&nPgCyB zo{jo(hT+8k6Fc$e2u_eH*}0gU1C2J1=p5*TD}3P!&&LfAfoX=XS4vr4v!&a+>KkLV&zgtWtxn2$Hhc1tkGjuu?)a!zZgN4xTH~+Ybj?ZbaEPls$UC?8j#f_V zW2bzxIiCs5GwpMphg?SNZF+oNl<<~I-*GhbLC<;TLt3ehGJf=`AAZf7 zcDkzr|5swmh~$SCdc&wL>AK%tl#!qRT;TUEcpLS7=72Z6jWqweApQ66C+G9h86S4~ zK3?KIuXy9%j{Dr}e)rE#Chrp;_1_DB_&=Y!@sBS-WLN;G$Va;3ll1q4$391pKV;H< z{v*?uKKdZ%eyK0MYLVOC;&F^S%CW!rVqaeSIZ-}Pcd7o*!(aYE|9+#p4|Mdn|MJ-< z|MWxedYw00-giv1=Xv=jdHF|t3&?;CxJ+E7 zf1>w+M;BvS7JbeaBZ~)LuoreCC?p-HB9_K>sCIw86nge2eb1+Qk=KDXRwM){gP`|& z?8kK0CUY!UgB7TROUQ&$0)Z9($Z<_5h0!K{8EA!9sB|GXg|=9h^sD2utMi$L;;l^BZ0M~eOze5c5CyI4#H$co8mey(VY z&FGBJSUI(rfiuE#&}fa%Q;Ky@RM~lXGeiMj|nuCnWh>laojOECV?dXoJ zHjX0~g?s05?`V&lsEx$`7lx%~Y_vy=!#0ffNIB_9kj5FG6lQsEyP-lv637Fm}myJnhiwT*Ld5lz9ij+5!s3@74c}#){ zg$h`YQ7MKDN0?3j8JUi0nt!O7si~TmBYrW-hI~nyt0|kE^9P?p2ulc>Z8&&@=bHa` zeHSU4r`ebvH=8fmlPTGQ=IEDGxtz0za4boHmZ@gcSe(@vOrP*MpFj*s$c>B%e%=|A zqgjmINov(8oO2nQ&>5D<34A&zf_-^=A4!x)GM~=&i0+w{S6P|IX`TH^Im7S?e?SPD zu$|mVp1OH{;OULyc$N(6pG$e3J6VlJ8FDJ1A-sQhZ}05!eo;)Nq_tqq(^#^ zm{@W+nwX#e8GgALoG~h)>A8|MI)Df2ntjQhIog~a>Z8U9q(~|{LrR&TX{2I`rbjXX z1W*oZIFH}Sq`>)`DQAkg*rsc$6l>b1@+qa~S(H{9mp7P_Wr}QMs-->prCU0qY09TJ zH;QLkj(5tayLSNuAPsJ+kq*k3@wuXg`jEMJsgkcy3=imSQz0tBE7XvceX8mG?(oV&@98oH>F$O;7D0_YK} z!wM^_hpHf{tUigDBZ_~98IG98npL){7s{nw`l~r9lsNgU(R!|3cLW6R2*f&kpBkR; z8K0W}s(yM|t9#f81n{m(@viY&t#Ns+t0;K9dZONnrS>YW0yvb88m35sf=tqo2-~i3 zhmscCjQ#qr7mIaVKmbf2uflhwI%=+x26%o4Bqtk)MnC{+fF2+#vI7gB1zV8G`KJmC zrEnT_Dmi`;OP>u3v^hwO9!smnhqDvuvM_73R~HBqkO1h=w1HR-ngj{x@w8D(v&?F< zbSS7&37fS#u|3;@>xrluJAeDCUm>ckUn!j)S+xXkwNqf zfF5>>w|cvSHQTl5n2BN;wnjR(s=A*%dbDUuwvtOwY>SgHIg>2ew|~30(IyF8kN_|L zK)9W|g!XU(37`gms}!Fbx})oLgnGEiST&TZi&^-k_e!sjtDFn_qsxkWH_EEXs(orJ zi>8aZs!O`dh7cE!0H@%($?JfYkN_Bf5P>TR%!j)Xvwj$mok*to+N9qri_%NI$P2wOh7h1T0s&lx@X!Ir z3&1%szzI;m+6%GV>xkYvw1z0ZpW33xDxJW4zFh0R$@;+{jJ~!DbIf?bvP!@AS%k)# zq`#!X2C2IOiNFeMz{!>n37iMdTf@Ic2BDh})+-4(ti$~m!4fRHc}RpDc%vBq{J!=( zef@Zao2tGeJeT0AzZ1NPmixjmOp-nP0zbUN_LUHUkN|ia#!~nQ2`~YH0LDWx#$`+j z1IfNd+`UMAmFs(iW}3u#ERStQzI=>9uc5 zytql3upGz|naK&T$&h@>%d`+$P{yMW%nqmtWt_U4yt)cO%n4x3mNUv$n5}}ymTl>_ ztmm_$iOqA2qfR%5-5i7@3XyaPk3ENS6l}`dYPhhfpN2WRgqnDfNP2kxJje){%nA(5 z$6QQ3(ZdPw2Sd!y%l6O9%*<}Q5dR#|IoZn7OmaKxhW?1TD9n`9yvVZbu=A*^E}YBo z7@OfplPqV^HutCx9fH7nhxL5OZz_-l-4g>X%srt7Q0oG54AZ&y38#wzzq}BgoDehZ zw>G_qbL`MjJczcq!Jew3D-6H#w~t8MtrrK*aY(+Pm#M($eDzCt3E0ieTFS61hxeG% z)63Hbebd7fFM+_k32*|BAhl<0b>+|q7*NJ808u8>%srvjW!%8cnYm zT+vQU(uF#KP;IYLO`?DJ#B@rqdyLdVtJM#gvAmmzMEc6?DA#oV?YDRR(r}H||H1`O zTgFmw3eo@$eofl*g$~~!4VC}}Wt;#VV9JBF6LuS=4Ec?XO8ASUgSrf0F6VPj=XGx9 zcaG6LEjmyYR~ zF6omX=x;7MnhxrrF6yIB>UTcqrH<;UuIj7K>aFhTuMX?6F6*;S>$Psyp1wJ@uIszb z>z97&y$E$ByjD&g-}yI?C?s&o1o04(-!U?bUAW*N*MkuI<~N=gi(Y z+z#&H{^-&!?&WUo=Z@~_uI}s3?ziskm(%X?F7G}6z2x(5@Ar=H`L6H#&hLEw?z!IY z0gvtEF7O3!@CT3Z39sICocAusYH zPx2*i?Hi9daSjQ1paplE<}VNPF(2eqe&t&(^AP^vHqYT3PV*Mt^EVIlK`-<}PxM7^ z^hb~MWc~t3fCr+j+bB;t>dgf%pY&C4^+(_HKY#TSZsq?y6cVoWTQBxwPxfVR_Ggdw zY2V*2VBk*=^{}!qKwaK$i7|;mX z5NRZf(jLqA=-SSHFTxAyu;0A0F36XO|C+6tw$y#ihdQ4tihseV`?i{)JUg8+49k_z zobG(fQ%I0S3xCE)CfLvjYi-x=e)>$ZEOh|26F>-!;foM`v9s@`w*U9vt<8N1*}Z@L z^B?@`2*|^~&gf5uHJHK(2oV1S3M5d_Ac27d4;~zdP+>xa1tB(cNO7UWi3Ss1#5ggc z#*H2~awJ*O%rNFvJ9=uxCel`du4 z)Tv3LQ6-T9YNVXKr&*20)Y{eSSFm3HVTx@?lb~6&Y1OXv7}o9Eiz7*j?D(&u-MVAr zKCEdoBiFlsBg$PE5@KP(CN1VINl`Dy#ULXmZrrzGN6eB>E{>d+Zs5U=55px5m+k4Y zFH5gxeRA9oplXV?rd`|i?XOZLX#q+G_glcfg%2nGIBQ$f$(1jcN!WzK%Pd* z=s)xPf)Bd)ShSD688?fu#T~c*vMk5&T0&OsgYZ30LVb@WlKqQW2nBeaCH&ESp%5!355os2uPE?q6m;tn-+tsq5J zbyZedb(P5P&P?^y)^Z>q23m8~l_)L}zyO_GY2tKKPrEBNG*E@rRVz}ROZHS~UtD%t zYOA&OS{XkK5yL>S&8i$L>$t>Qa-oz25-T;)Rax;uJ+{M6Wi8jw=@=X>T72uBcVB+{ z^>@R2Q)8>Hf3vcOkOWHqD0t!LBr6wAJZ4)$d|t)8ZLNX^WM42_$Gp!D{;BrXV$;_DZU-C01M)y_`eq?1m&*-|ZX`_v=#-AmEdmSv8yS01tPsXSvRHJZs3=Ml0pXGxnTx-h1~w+p=pky!U|+_U(7M zJ0PH#)K^`-XrC=^S4Gwl{{_wO+BFYVwcI@}6nXH&7yrfq&z=}N-Um`80U^duTbp1} z{W*B+cYfabqT|k<(B}H@{&uLjPk;j?9>(go9s=zSYXf0M0w6{}rU8pqr@`CUW|y<- zQD$}v9G-vvcQgowP=uIE%!&wB!o1N=Abi8X2wnJ`h#S_=Y&boYEp30=^WFzh z^Fkm7k!dLWlikX9x6CC3C_-c+ZDQy;w3)A7@oL-wr?x}>QOt-w?2Z+i_(d>|Oo6{s zVw1vn#;^QPh87ds6y1ow{5`INqOu?tbBIPf=24HXD&rpgm=r0#kv!b1815VwM-`gy zQg+PLA07EfNN%Z*|BkX{_(92bcvMzT_uyW}Oa2C~FnmU4rLlV1hd!>$^B&X$lGxff|8c9JH05beo%TyJ`c$X_w5dQb z*rgA>t&u}z|7ugORZ^!$^>0Om=uzpn#x6-!t6NnaP`Ub5Wr7o|Vc~-Z^bzfAKYhCS%M!4QpuMu18Uj6#lFy0+E~a& z)^dWCY-JxrSIcHrvp*GxOgH;k2VoYpqa`h0I~&x}rZ#fpRBdZr8^6=OR<=cY>}+j& z+cZ%Yx4XSiZF&1!;D&aw!6mLzL|a_sCO3`4Rc>>Ehe+o}SGvGq?sToIIC)-IyW0hx zXSsXb<9=7X+tuxOfg4_i-D3j)U~hZdi+~1n011%bMm<7^4;~c2z59Ld1-MWN^IEsO z0p2Zo{}-lS{w5dz2>^pQAeavxD0sj6EdT;Ea1H`Hcfc98t$_=MUeYle=LTzt+S50&$AjJK`1#5W+U*ZvgDzj~Ejd#z8hsF&{<2e$CilHAa9A z6!Bz59O4TbIDmTtAO;|h&mJhgF$@|3jKcJsWH+^-tj znIrr_MwQu%fI@4T%LPb4s5!C?5eonpk;W~gSuLhX4+_qfmNU~beP@m&`o;x_0ERE( z|Bq}4q6rl^Km+_M316FJAF!B11{_d;3b=p^xk#NkJPm*dEW{t)=yQ8ZToCn^Spg0{ zNsUvygoW@!7=q{l2M(|R4iLc%^(BeA+3jw4%bVUS+3}}MZD@12SJfN=wy=q9Y%U-h zB?TXLv5%eXg&>2!DzH>Prm$Z-qZuC?DD!?1aDgMl;T9gwx6E$mcp_jE?{l~4RQ*!pInn2lj0|E{(;t{vk0%?HxMfed5Dg&V7BSruU zP<{|=-#FU_*><KF-FxzbKsAg*ge>s~%`3hGH~@-k9(Q0q_9DEC z2)}EaF!i$?WNJOv8!On0JwVF9oAbbO$vxe}8G-0MxoE!v5Q7Twhiyo@{}eMmh~o!N za6kns09C7ytdqK}>pBtByMqur0H{3fTd(&z00c0)BQ!z;K)Zf;1COf!uVb$R_`W85 z!YBlQDNKpJyRlNch;^ujOz60i(-IbRLH&ccGOWMmyT1P8ulFkmeu#wn!#n~o!0h`p zB}{;N}mxds}1D9IbkhMn#2q2E!Tsk*+ZoJ z86(-NH6gLR_%Xqeu()djf(mhmI|P6Lh=N-9hG=jF9=Nt8#JVW705iyiaEJy|AVR6r z0E5WE>Epp0i@S>eLLn@P8aqakFbA)*fJ(>`dzc40ps)f^0J&pE|D}7zERjZPw8p(N z2ozL98oaVBD+pBVxK(V$SB%B?`aS|U$M#A`SA<1b{Ju7vun)*Gi|a80vCmhj1WV#%%ANRE6HNzA5@6v>YC%xyUz>~bY2 za*N|?q|Z2{pg|^hNe|To2~pe#nq)7VJU~^%1cB+z15m+#0M0Rlh&YT#;rxfDtiDg% z0ebKZV-yFOxJv6R8e~|ssMH95hy@%7PZYoff!NL)i^_!f&hW&6@vNWrvoQmp1bf&B z;Os+>AWq|~&*oel{G88w+^>@p2(7fTeoRb8n}&hd2cmO3P@4#}1b_jE1-Cl@AP5Qb zlsfbr2=x?C@+`?uQ7TT{CcO}(@t_lS0ZmWAAx)8`|2o0M*a;XdN-8QcQP!)e>Ke@= zE2z`dDNY*69feWaM9JE8Nm$EB6lo)n%%2$zjzt_&l9Z0!YzR_pFH^LK0cFS%wbEVF zfGqKbYoma3@CbewhjJ*>Fm=vrO919W03fh0k*Ln=BtkRfFD@+zFKw>_umCmigmb8e zf0)k_y;CXFQ$DpXKg@{MRu`IdLEJ=+?H9r3oOt#xffs{kT zM9c#;!x2kB3hT8)6^I5bvmJo2Dyv2WJqtm_LPG7+KPAzW1ezyJoR+kzEh^D9=^+$# z9VcC!rK$`hl^h^-(O|KB43pS`gq_znWtxEoUd6BA5R6x)C0uU;eB zf%V#mFjzXR5a&$AU6VSQWrH&n2y@WfiR4@Z@LZiqR6E&cT(s!W9X` zl{&?Z-2#|hfvMeUG_n5#050g*0T2felYlpHJ336v;!}WL@Y94yNHDbrRBSH|$g_k9 z-TF&9{VLrv{YW?|oZKX+k5U#*gxjjMTj5bwBZ8+{!LAp5U$7P5>p`3O)uufvTeBq^ zrgcf(liNN4MI`fHA@$ZI4PUy=)^YvN3v3p34O^5A-;|9RL6hkY-SoS`gaEp-w1-6V zG%mJFdvIYGzOe)>KgxYu15%*vaTmT7+hZCeBGo2c1yaUX(NDbF6t3UB(CP{ANOjeA)4P!|4wJWvWk7z+i z?b2(D+>eL{ZD?g}06R4GGgIic3IhUv@CXzJWCFO?^0-uo@CRV#his5C2RMKUm;qD8 zLNRb&VD<-LCT3$s<_TTq|05!hL~T&R5W4~hP`emqElCJdHnU1~uLvOJBMN71gGT?$ z-IB}QNT{*^@Pv0}ujB>JKO+c#hzCBKNDZI|Kz+~(JHo>w+=u{X!5!u=DCT2M=Hk>~ z5Cz*#p4vyoB~GSeIW`YWnp*^V7lLVDE81W6joRe{=sebAWEE*YewGxyo=pkTh!&wj zR_R{N8y(dhC50|$s@w666X4!t+RN!l-sw$j(xt-H=@H=Uiqd_M&_#p5eQ@l&+=zYP zgrpX_n>=1`BiIt`SPO2>rku~9m0++Q*glTx#9hC`$nF~}OQIDtY&!?~mOA@Ri1t(E z^tfg*&}(|e1V6n=?S8;sfQat??jYW81uu&RZ!e)UY$}ae=8FKK^t5{3!+TB$P?p)| zjNRgsNd&KN|KkLY|HiQ3#@kvu*ZMV-jTRdBH8TChV`nX*9)V+vmhHfpUy#P=q1Nq` z=ItVV(wBaWa~1APtYqn4a_27KT_)EV8G&xU?6bQfTbKY1|>F@_x64t zaNZ+C`}-#ck-7w>5I*!GO>_85=jkp9)3zTYB0_i(Lawe?6S&k+F5KzUDO z|0&05dq?0W2UbM>+F zcA@rq+D;}tGIzOO_wHAj{#{$VACR`qO^|Y1_}6GE2mHGie75HbfcPhH;6DNe4;mz> zaN)s)1sxVdC~@M!dm8{?%&1Xg0x%K@+Ve;5&4B_NF&aoikKjRj{9;`^iP1tO|9kcZ znmd58K!lqD>)A6Gvt)#X7EQ{`$g^V1q#6fIv-ywQ6a-EMEb^z2s@0@ewGx2X5+9F@ z2*eBwE6`rPDJBaPpfIi8z>p(L%1pU(p_WDiHsNvi`Kso^guw&34 zz72n!4!9-N9bNzm#4*eXz$6862f1F&Dlj2LhO8B;bxm=$!`ZQ0r$s2c;cnh6Db^Ni zdm?P#tAF3ljokR~+PZN=f1MUOY}d}6e=I(HJNNG1zk?4iemwc_1QR4EuYNuI_U_-q zk1u~d{rdKaW8W^kd4Af~Tf;|PbOPdL9DxSrmfULh=?CC?{RPKTbP6I!|6oK1DtMf1 z+Sz82QwTKB0TPhRwV;Cbz>|$2Gi-1`0wP{=&TcmC(}qQ3iR~WJXY_6%sUp+~B|g3|wFY8IznN-9J`hsU??Qf=L}h`II$U z0%$qJ&nkZvutY>vrnq8@FCq~mfMe##qKh!f$QNN5Em03YkqBw$K9OV;03tR~W?51T zT!6$RKZeB*CrA|lL~U(Fib+cZs5pa}U4B`pi5QB79f$bMnw^@@EhnahyT+QUt#^uf z8?MSB*Wa)S>iUp?$qHATh0OBmD}&QgTWxsfrDv_S+j85jx8H)h|LuMa?h37g(aIO? zZ|Wup;eQ;KJ8gmLjccxk=fbOQhWlOjF0i)QL*Z-o)I-;++WAA|g1wC?kXB>fr0|B- zEqm;pKvHLug8s0E@xK2&yq3iMg_ID+y;4k2!toaA)5jtcsIfsn19Af9tL&PH@F^M+R;I)`&!SvNogHGg4gFZ60 z>nU-DK+GZ+yXeIxZqbV`{3034=)r*)(Tr+bBOBZ3|Hf`%@s0Efqa5pK$K#={jCs5x zANyE9fuzxof*d3v3(3Pc8d8FZTqGm8wLmpKvXPQ>;|C{c$xC7~lRq?}COhfLPl7U( zqTFF6M`_AaqH>LhOeHH@>B?8aGM1%`B`s@dOSG->mb%;}FMH|BAkOla!W|!|A z>CSh;GoDNQMp}{~Rbm!==xHA~c~2^(HzO>d=RpkA@JP zC`BtO%!XPtqZvJ@Mmy@!k4h4wARQ?|IZD!#|DrUd=M1PyTRKpax-_OTohb-KO4FNm z6Q(%bDNlO}N0$0DsM^%2P>X8Rqhb%JNL?y2iOSTcLiMONjVe`B>C~!XHLES1s#d$I z$*X!btYV!gSI4@Z^i0vLBGj2$+v-+}Dx{uojSpJqDny0YB(HkiD_{HS*S`Wbu6!y-1ZiaqRL7wg!^LN>CJU2J0~YuU?U7P6JiENAm-*SnVWv)(~#T16{7i1D>x zs$DH>TkG1_!Zx<5^{aUND%;!QHn+OnEpL14TH1!kw!R%Maf@r*u$D_zsBHMH0r4r#Yr!@aVW{~qEUFL}#r-t(e2z3LS&Yxn9M@UC{f@|`bz z>ucZp;`hAm)$4op8s7W@IKToPFoD;*U(a?2zN#%SgB$E%`yN@667wp69@Zu^^Hirj2k%Y6^u8d<6pZFc^V23*T?B_oNI?#e1G@%R4j&{5w#xoZ4 zMC_d7Jny;ClAbiBD{bjZW17;3|4uYK>hUb3F~oas}eI@PLPwWT+$=pw5b z$)bKVJW9>#TjM&{nRa!jKb_&(I2zBjjImqfPt{ zKBog6+SYbC(9!L3d^_CU7B{%ZZSHcTo808~_O`X14t202(VhJI(CGv4uydpzVI z$9TixE$?K5+91`gwZ1RT?~lV=ssGB*SqfZuYdjO<;MBLQC@GA&zkDo1~=H- z?)JCCJ??U!yW7RyZL%lY?2S(QwX4o{x&uD&f*(BL;cj<#mwo35nR?&Xe)YmbKJt>6 z`{D5p553#F!fGG)<0oJE%BLgoNss#19O7)!dpH4mME$nX-j1Jl9vtBK#y7N4du`x8 z_qyLb?|bk2-q)V?-;jMc#!>Efx8w3*-n-^spY7PsKKQ?%KJ}|_{p({t`_m6T?TK&v zZX;j$G-E!F;o*F5XI=KRx4rh;@Ba70KmOF`{_w$3{Nt-5`6wqpJ}dlwV1qTdpbJVv49egP(qIkR;0@Z~3%Vc++8#J8U;`GJn3bUap`Z$~pblCC z4l3aiGGP-s;S)k34k95B4&M)Ipb(Oo393U8*4`27U=)I37>eN-lA#h#AvW}&6)GPV z5{wpd;R?3k7nb21(qSD+p$<}^50)Dcj^55>ArZ2j5ys&Q+94F4VH)n?6{g$>Y7x^h zqC`BMv^^qyWT8B~!xlc?H?&|3J_9o_!!dwjD2n1Jl42>E;wg%vCqBb7>|hmkTfEI% zl~v*;qTe`Z|6&qKLnnSBD)M44`r+tiI`ZN+9%C{thQ)q#UHyuuyOKtxL9L{el$TI5Ay zWJXrx9lU}z_#oM>VK|nbLNcU7LZn8bWJ;>!O0r~2x@1Ojq(_beNHXK%wIMu^WD1(( zOY&q-`s7anB}>NSM}}TV+T=(sq)t9$P%>pxIwemISCYrQS>p3GTPo&dVkSm1W;r+}WU8EGQl@2Q zW>0QrX9}iSK2TVGAS04xS)%52-6T7p-#5HML{@qBr0fa-Q*UgAT~f`6%c5K=4KUaB{qDdI`rosQYbiBD0FJ*iJ~Zha_Aj+ z=uCnrRf;G&ROp4KXpP$Fjn=`6wkSHhs658#jG8Ep3h9vgrjCASh)$@Ck|>Q5sd*Zy zizaAgk^9=9|(0nHry&W*C|#@Drd^+pwelY+Uc4q zs&F!DoId71W-0PesaZbg7;S3%Kn!8FLtbiwG(=>jPG>|)gGYL2ra~&InkuT&|A4C6 zs(P}jt12g~GN(M0s$rgLs^03b+GwtV!>jrzo&IV=(kih!Yjqkcvd*cj0&BBAD{n^Y zu6kvt8q=;cDC>PHmWC>B#AaS%!!zJOtzPSHM&vVi=qs+_Xa1+TqN}>D>%I17yS}S3 z#_P_6CyCZ8z6vaQ>g%!cYY@sSPSR_-4(z}dEW9GDzs{>+o-4x&?86@HX>zO4M9a6L zUbwbS$cpU9l5EME?8%~R%Bn11l;4P+tFYp0!9r;eu0_i#>C4({!``dR^5`1YZ2!6J zGr+9Q60LCZY>)axl2)kD=4{at>(Tn`nAq&n4(+-^EzPcM)@tq6a&6ao|Lxa`tjCfb z$bxOzn(f)5ZQ82s&%(oqS_3mw?Q{}An?@uv0BX--t~c=#s9wh;7u7 zZRx7+>auR@rmWH$s^(rS=LT-n!Y<@W?$gq)=i2Vn#%|x{uFg^}<0h@|;%@M&>hON< z?aFSD;IE3%` zMlSN|X+)YY`lf^Wwylh|FZsgn&eFjAN~Qf$X#T$M{x+%np6~zW|LxQY@aFn&`eLp3 zLU062Fxq0T(rNDmV{is*u)2V+`0DT9_U{2Zu;q5J`x5ZvhA{mCF#dY*0H5%)8n6l{ z@cJ(B3&(E?BQOaoa0@fA2-oieZ*UL`@ep5cm5$|=5^)kMu@X;cmzwbGHt-MYFwi>j z2itJ5;_wI;FBRMA6JN3OMlk?au?v53ipFpbZ*kj>aSzL|XDb2VGDg|sppC?0Kb46P;(?~O&QS(J}bVX5-HZ;@0(J`*iNe{?VxG(A&CJSc)bW2a0<@;INT9281D>_a2)W*l(C zP4ELdFSJR6aya`lO{1qscXN7DbVpnDRXgHAZZuYN|Me)(G&uujM8kAR|M5xxvP#>i zIa7x}2t(2Gv@SoiJliyN%!5u}=Ub;VRPSa$4@5m=!&ujWK_fIt7cySMb6lsWSQ9K$ z%W_M1^ISSobDS6GTGqreOa= zLL+LTGJ;ZPs9`5JdR8}eZZ=gPw;Nk_c(1Z#vl(TJ_jzORS8sDjzyfOXCL44^Ja~6m zH}yMbH-W;pd<&;qM>kNL%L6e&~YEwd)d-)&qWACAB6gL5HxVMIY02ib%QvhXEt`G|N5#6XN})@qZ7Es!Z<*As}VaW60156>ZsxW@v~`*T%s?l4m3KlM*!hy@<{o6& zse^f|OKe^%cTv-`l@zp^i#w9nOuQF*nC#4_*Fhy*l2I%wOjw8+7@i$APVzb;LTmgxfnma6_5L15pQdmrHkGD>_9Gx1qE5xC1x=>;pSv zf|~=Ix%*~~+XFqge0_#_x(oTb^Cry8yl@u#xifpj0=wEEO^bIJ$Oip*RJ>-JIdCol zr;Pf1-};~m`;h-;(+AAc?{|{Z|GPQY%#(+FqtUsxZ+ai}fgF_kZk9Sfgo4D^x2w;% zbzXZtocV4}`o{NW8b}1g@3p<#!#hYcC3L;D_d7+zdqC5JZD4&JD7=@$wAmwsvhOpx zC%vTG`#wwpfZM~V8#ShPLOyHyY^Z%4^g)ehc^`;9x7UH41I)}9wZ0QTJ-qaN*8JpO zXB@ab>>oL;m-vID`_Xr+YI>@#XOHhA+0^5_iL*Cq+x}#{^pW%a&z~mkAGqrqJlRVp zwG;Lpa7yTleb`GvmsdK-&pF5MCQOSx)*E!`vpta8{Fq~BZrcQJ`!*^B_hbOPZsNf$ zusq6Jf5HRAIRXO-#A{Ti|4yZW{9xg!6K9$|0{axz!4v4#Kzs4}AjH$Fp2U5x9tEl- z&z?Ph*$~!|Baq;}P6#VWBseclOPxD;wxmJhm^5wU%Bh1#FQmqL^x&y0H%^8TbZF6|NtZT#8g**bt68^p{Tg;` z*|Q1$vwiz^f&{dA_xAl8cyQsvU+czwn|N~N%b7QK{@gWTrcR+srE0n7A_9|n;UVcLWJVLr7h3!B8VSe#%oCqaR&Nty8~OoN<^0GpaeWv zJdCKIgFGy&9tZ1K1f_yb)PozdW^xH8wJ7^AM7Q9YutLB%8>}$u5W8-|m(1$pCBks} zDl8ijRIn;7?RiI@w)i<}2 zo1j~i(MBD86w=y`vrV^1Exi=eOo20QQcXSm6x2|m%h1a9{w#2^6TtwfK@(5yD>Et6 zBY@OCvAlCt|217*ERM1?N(opJ#q4#<$^v0^O^Y9dNIjg7pVqp5$8hJtB>KwT^)IT#w*vPt_RVog||dO1~_uR@9bV zei>%gCapB)nr*&WHcpSjndhE;ZggO5Pc2kTgoq5uM~*vIS=NuQHTBP~?)IglsoffB+?R*JfhaR-$80ekM2^hCSx2-MJ&n&YNPwkBY z;YQ72eHB~ZxO{a>+LkUJ6gwi3V(7`xnbz~|r%QiT_Z}P4iRiX}PxR;Joqs;K<7kGS z`sy{+**5F7-=2FB`3(8glgFzhq?!+4A(4re3|u`Fm%(-w%fQ!$H3qDb|42g=ewkoi=Q0QCT1x#l5&u{V;c34iFOF^4Ve7Pcd-KA=xil2gPpD;7_5gZ`Xv?th30>D z|MA>pdZ&}ykqJA!5>)M`bwGiwPk|hhqTqBQzC&5DGu;#87@LQi>5&nQY0OyyaHB>y zz7bRj9NvVIS1*yk?^WrOW5M3TAep>JT~w<||2|`nb+Cz$p3$IA*wBp(W`ipnp`vB< zh{ZWZk%6f)nN7ad5_uKQB1J;mi(tZ$n)HYoVY-n>6vwqMElUy7k^``+(Gd>HYce46 z2e_PMKpiqqeQ?VndCGN`wB3R*oeN7RI+93&EYgYcQ(>FtLZB!HZhy-AB?2wU$3JZ` zn=PrMFV6!^IGz)ojxytJ(%H^->dc+-lqYfa=)*p$gkDFh$2y9}u}TW_lH}1R|3As| zFhRm+SvtbQBv@EE1X;5u@~RW-2+&D#uI!2c^(L>*hBZRj#G!S-3fIDDJQN8;e}{{q zqPP=>5#sJHkF>~lrq)lIq+}&7EafCZf(_Q~0}?mvTgtYXQQ>WrF9%CdWy~ZjutBUY zpY+!t-Gs6C97|27m?R~^7(CJ;^{U9yY8UajRlcNeo@rHUY}UC}w{DM9Zsy*MMSHAkyGU_UzRUQ_(I`Aulc55sYvx5>kfl{00LOSqnoj;Lh+|6^jviw>WWi!AK$^>m*wC*(=Iex7LP|jb{}HawH4!`i zJZfk8QcNAu1Zf;PR;T#jp*qjklsixKW%m3Cd3fEKS`4D8tGTHf+f zik;?FZ_VJjUiYrmu7C2P6Op+T0E$<$M&<6S;!t0D+!rkdm9E8>r64@GsZM`*Dn+uZ zuGx+SzZey45AVbzl|aKTu5@jaLbKF->8~SrkZO3<#o#z#Bt()eOWjma5{6oksY11y z201v?_iUHK9a1Wp8fh-qnI)E1X=Ljb;al8IS4i32NuUaX#~kK&!r*%qlg-zY`94{~ zy z4i5ywT_lJ{Gn?f%vk#CAtOv>h*h|ZS4k3ioBx?QU$ay&gaemgwyjDn%5djEJI(17N zFcG53a1gj$9q*xsi5=sf$X)Xq%fmGN84SmPE1!GFcidvJs|!4);~U z7E)ExOjIaqxy;e-o|mOvZRm*E+S%sbnLBi4LL~**7j2qXbF4JBI0m8w=5$>qTbU9& zOn#xc?<_^aw>Gc(*!x}J2ZbRm4CW}(jB}t%@G>p}hVw@(5~0;VQzD+|p&NhRPBf~E z>R4-~#^T;#zRUfd9iOOIHd#|M;|&^?ym%ryGLt54_v=va{{`1-sU@+`YHV%;GK4c< zP+229Zf*a(djB9m0we)+qi>1;V?O%QZ+7$dG<(T&YGKbe?(|ayYU%;5^MH4PXUN2y za!(aaJp%38QTx;8-6Sr|Gs)=M!nnjxH0Vqy?IC1h*1-gkM>*^_NJ!*jPV_*B{bVWB z7xDqs8V9D;7gJ2i(i`t3S0ps#5b^B*kU=ST;;*ZV78-WzuYi3vs{Hs590@3am6p#V+>nR>^ z?Iw@|b%GKO3VrmC|NIXF$3X-CJ{PJ%M7w`q4EeGR}HfT@|>(CDGu&%1a41bU@SkU^S&<&?B z3D3|A3sJm`a0{uB4-JtK|4;-2F%buG5gU;b|Do^^FR%<1aS6@M4~Ys9VGs{PQ4~j! z6ibmbcF+W^ff*)o=UC1WnZX*qVF4FU4^wd!H?b0P(JFod7G)6~XmL7tF#c{)7mLvV zc`+7eaSDf#6^&6Bkkp>Z2C zksOK98Qakkwec6Ha2>7D9qSPRX#gIjQ5|@29?j7n8xbAjF%kRmAD1Q{StcA4QXvYk9^|1N#xg2u(g}Y;D8NA}+aXOx#4hntFQtJm&GHy&;4cGnFb9J$409;=GAb4G z85vU>023VqGbAAMF7t9S5wkKa(-9kUGavI;KJzdWlLP%SGaa)t=~6allQwJf{UY-n z(jfz_;U^%>9o66`lCdbzBsOUUH+3@=dy_OP5jbf;IMsnT3G+C2Q#qHjE1UBxy%0NPaX3-aIPbDM|C94O?QuK-LpyB~KI2n9=QBDU@(yT#3ha>zXy6V~ zQY59b7K!pc^D{gRaXR(?Ksu;V14CPxDky_mofj)KCAE6kfCch!Y0olsoBk zGVSzF7nM;P)lnZ6QX{od{{vMs(}7UO#!z#!P9>F7JJnM^6;wHuQkBwD)1*-8AM^;of0T*q}>wKXKup<6}dTc4s>!lIl46<`B4{aBPc_wgxA5F4yP8lK@9n1LCN0b(Oo zVkeejE7oE!R$?8NVXeU$u;Cjn(kjs;Nj*(E3f4yvR$&>|VKJ6vTh?V?7G`5sW-C@> zpMhgN7G#%FWZCpe|4sH_zae24wqYN3W{cKnj}~c@_F`-HWlS>& zSA5;eE?XB-|E;z`iI;ErRvX&aecu;;<5zy?SAN&`8$K2s!htAA6?&0^XH(OBPd0t; z*Kz6BfDagf6Ig*4n1K!0e(_g-tGEC9S8TMbe5Y3(&ev+eL46Cjfj=08Ls*1I*nu7Q zemOXT`B!!S_dEmmUJ`SskDj9>%tU;V_lyVU?q}m3w)YahaKQIhUWgnW5R4 zqnVng*_x%9mU+3Cj~JMRd5n?hf{&RUlKGW+xtg*0oYVQ5)ft`F*`3=Nnzh-LxjBrz zS&{FUk;R#u_t>1@nVtXHp93160a~8t`IqbYl8HH-S^131S)d7;nhSb@yE&mx*`hBR zqj{#7jTs)GxE;n>9YR{9N1CKd+N4h!rBRw4+98aCnI0;dZZ4RkJsPA_+NN(Br*m4T z|96_FZF;3!dTe1@G&XvbX}YJ68mW_7sh4`Ef4ZZCdYDg9ri=O=KANeo8mqIqr=8lR zg&Lgkc&4kmrnQ=>xf-g!Iiu5Bt=BqJfJIK1!kCM?qvx8g>)NjG8n5$OuY>ulS2u3A z=B-~^9^`tj3)`>{8?h5xu@{@J2m7V{%&qGxmEn4@8QZci8?!T8vkTj?{nxK0yL>5| zus55uOWU+LyRRd=G~C+H1behkJF`0*vhSI#YumPOTRGhNtr_{Hd)v2v8@Pj8xQCm# zAKTCT`mcjGw0XO@o7=gc8@i)gx~KcMj~lsBL$|G)y0@FVyW6|JySc4fx3QbG|BoBI z&l|ndJG#YNwLyEi;aa`Vo4sipx9i)!?>jbhd$O&Yzx&(2{~N&nTfawnwFf-F4;;Z0 zT)`Kd!5h542RymSSic>d!YkauFC4=U9Ku-x!ZX~%KODpte8X3x!$bVTM;yOXT*X(M z#39_pUmV6`T*f2(G-lk!Zyd*ST*r4j#%Y7ce;mkzT*!wU#q*oUj~vO9+{S%e$(x+U zSscovT*{}M%B$SUuN=#>T+6qd%e&mmzZ}fNT+GLu%*))&&m7IuT+P><&D-3~-yF{4 zT+Zj5&giZ{~XW*UC;-e&q<$LtWHIT`oU8(o50QL7miBoz+u=6e<7!3P9Fpoz`pJ z)^8oxb6wYWo!5Ka*MA+@gI(B%o!E=r*pD6A0RR9@fEhAqG}@vZpg`G?o!YD2+OPfE z2Lju-o!h%z*Z}|m{(y0YIwdp#0b_WF6sK9^!p| z=7V17ho0z*-smg-Z4xjr=IGM{s9QSQ4W3qD&PUS-s`^}?89E{ z$DZuV-t5mF?bBZE*PiX$-tFHW?&DtW;l2V8;Ny#c0N{b?2|y8){Q$Ur?gL-&2cPf@ z-|!C~@e|+dD}VuF9RR+8R>*xEV7&ks0Pqzb^D|%bH=px6Kl3Z#01f~E;2`fuL+^_q z))C4x20UDtgd?6Tm-}iqX_=8{ghoAV1-}sLo`IBGy zm!J8Y-}#>(`lDa^o!=LV0S-hz36@?o{zDNy9tws57^YwR|Hq&F%isLZAN|u`{fi$M zhJh3^K-s||@{uU#VZ8!K0sPlr|M#E&`yU{J2^>hUpuvL(6DnNDu%SbRz=mBZ000gF zc?2?Q)QB+&fC6ZW`FcpQq{)*gQ>t9avZc$HDt!%W^x)&hn>cgo+{v@2&!0ep3LQ$c zsL`WHlPX=x)F{OV&zee|O0}xht5~xd)pP(rl8Za(5l}?&j@Gkiss3Bb_MgtSZF9n% z>vJw#oOCzZU7OKv-MxEn0%rTRZ8;MF0D${vPiNzD6##%3N5HRK%Yq001zZ?&WzB={ z_6)o;wA-|(Qzy-n*dj)q9RVC@q`J24+qiREwN{}({{h{=g9{%{ytvN94}8^wSFgGA z=g^}|pH98H_3PNPYv0bjyZ7(l!;AM0k6xp$Uti}GOSWP?dE?{DpHIJjcmnqG>;F!# zo;DDPEoKj2H$4^^2iUx~-*ota*WiK>MkwKg6jDbIJ$JMQ7HkA~RDdGORVdA?R=;Dho##q!-!Qdz3jX36bTRjAvS3r7UjYW|~JnCrVWuhS&mqw-~$z+oR z_LU@OPdeEdlvOsVS6c&u142duMyZj30C4aPetF@Qrj$^gwq=`dde-KgN?MtvX-DQ+ zAOUv_xnWMR9iRvSV(Dqgc18{~k%BjgeMrX^cGj2&7Kz`B~(pE_#+( zUUL$5CzhWrsoAM+mPTi)sKUBdmtPVPW~&*IY34umtjQ*3rHUD>o2$wy+OW79yX2^` zg4$wZeOB}*PJs?usI%B+YuloYYU}N{;1V_Ir{R`sE>f8u@Z+>Mbt)~n=hh}_oT>&( zua>{^MdiK8s%fXcbk0R!*6ub|{;* z7>6t}Pu$ux^2sP0I&R7=W1Q}~9JedvyDgtJufq_ZwrXH*Q3)r&rt)+%vvGlT*FRno zJYdiV698G6-|)Jy!#ev++Rj*CE$Y0X{{c-{u{B$zv9vL7R4t)lr|oUYEUNAH+p4V$ z_uP-Zyy-O0s<-a?P;$R6dy96nyOFzk&rVd|oO{0Sy_x@8@n)!Y z-LJq%I}T3MIUy|d#laU2cIG)34?Wcs8?Sp(q}$Gs$AY50{rJGKPX76-$BzE`Y1Lk~ zMz~YTzN^AlU%y|WS7v$re~TBp^~)_H6&@BzyJGlofqf2p6fi%eSe?N zr(4)@eLqPCCeIQGlzuSp{LzzEY97lyK>8^^(wke`7>Cxi&72Qarj-sbJ6|wen?3sR zyvOM4J(&Uirh5gAG0O}=u#lCQiZI+@K!$IRyWl@wyJxGTGe)dPL6{l*N>&0j#b6oD zQC;(t`RXA_E$~LxN^Y0HdW*N791z+WuS9YW5$f*zX_-{`=G%j&bYM-^Ix_S zqsVC5ynF8D??#$~_swss!XLUb+!T?%U*~V$qLS7vY56V1FuLHVT4^%h`je#1otxiW z)T2bMS^6+n7R+U9{@uGAT(j_l=+39NQk%};pw$*=c~5YQSBHn!wDaV4GJ0D;cGp|f z+9{;)>7M7m40_!@ZR#VdR%thrl{dK+)|nogo5OazR#H7}Ewm!eDbwK7skSgB;q9g& zaSkm9Jw#0Q-ZetmllU~=m5)xaEQOD`$bA=)`H=7$J9pAGgWh7IcGvvKe> zGy?5HDFERh0hEP@DINyGLjVja(>co70rAAuGWp*Xz5oxs1X?Rcu*(2_9id;s1Adt~ zNyKvO8H#9RXfa$VibOg$wMbQF+W>{a+-+GyS0b%ZSIJtlMgO3|r9<&1kTsO@wrqlt z5B_-zTR+o0wU{OOO~7mF;E;(h@mA5ShDLyGkK#MSSO2|KrL!2~683Gy`D~Ur&J3%G z0gp@*zuu#91I#t748e1yK^(5*?n}pJwBDE^F>e5_fzk3PzRM6M;kGfQ55Vn+aodOO za(j4K_E(%Qmj_vT>I7WwFd)(pCBvtc>92jYqJi-0t!O)Cf+UuH0wZE)wo ze^vqLJL5ed+~dL$L;jx?@Dx{yc+bydG~y+kd~LW_G>$Gufh;{-)WoHd|GXkNYjEYF z4DZXAOARke6!ha6pDxM>BA4pz;~x3`Wv!At z`dBQE2-D++@LI<_)awyO!0Z5w%fEDZNL4Q|LgB2aur|ZK97Pg3FYarRzWE3!IKII;P$!qyy8t zGw-g&r1XLU7r8Sr!L;Ym=~NER$r2CSV#mqsd}0SAz1f2Jjb#xUScfk!_^ z;0X*ov-~dAto4?_O|bw!y?}rO{F0bHXBED=E_L$DT>a}U^_o%k;D=p8H?$vPMJ{s=gp)exQi(}x!bEPPvn3U;MXHm)7 zpgjQ2u?}0pqs~z0kbEoTCqhDdNHv*pg3PpuM;#D7{Jof|Sx^`S*me<~JQ2Lt9A1b{pMoZ!kl1C~OwDSQEPs#(p|Eh=&^HHOmL3G9d5( zdInMbkrkkTEvp%rPgwyX#HZ?Z5**NIx|1JZc6(=98fk*cFpKh!+`rIjc^*=PQkCUQn)c&)}#nP(*;soS~uoM`OG5`iC z|G{VCjxl+jeW<^)e8&Lu36;Lf7J7na0>JQcMQ@X3=O3QT!z})5c+~b9E6Q6 zct)~h>>38sCo(kxV9#t;XDTZp3&l8svZeU+b{N{JT%*qOIl%!jGU?5RfUS!!PZp{& ziyMtcW>Oh+9($VmFmF@-;{=dU7p4z*)IB(0i)KDKBZN>9SR89y4oVFUM3R}h;IM8j zRvEm+4h8-a1o*7wsUM{Q0PKj0`ohiWp2Y2+VsmcJ?}SWaFj|Xe(+659{{b^`*AUra z^AYSRTCcV)X$6*r&YpW7pW|Czc2nrwbs_U~cJ%x0NVNfJi$0FEpXYG14>m`|pvUY3 zM-Nsb?P54`xwfKIMw5Om%Kqgcn>XiX44Zus@^o7l79$Aqe*>Hr1roFw3g`fH1WHYr zE-1`mq=-H8C*btVv3d=5ekY5msF0D!jYCv|~FUl4{R$$dnuiRJ$<03I{gP zOv@vnH43jY=w<;IbP<3#fxvrYlwvkF0z;!Ci*enw2Y6=g2v^3WSfga{04I?NcD3|; zOjtG9(+4P?y>BckqQE9ee*2m`I`n~-QqIC|&7DUNUF32LRMnJU)IR96Pt|313I`;9 z**mYfWD+nuu|Orpo4kNXk&r#XpvFg_M}$X%_su*83n$lOWYB&mL~gzrfi!5b({o_L zg}Ha;{Eb<|4mj{+24!iF+M}QjD5xh3X!Cv&mP#s3;BadW7Q>@Dsc<|s?1N!QaTa$p z(d-li|^7!H#HCTRI{F_=SbP)IkbrRB`t*AmMKv! z<81{oc&N*x)ZRdzz=AJ6$sqF}y9(it#F#RP;Xgb4<7zT$;?qh7gzM}8ECKJu6TRue z{5(oMOZlTmP6&>9e&#?cO-W1K9jLXvE#0Gf{y3V0VT;Y;?k&#T9VuSFn9Uaaw_#M;ih z6Uupj1=<`Y_>~yWJagwe2BpskFuKIe8ZeZc*vl)6)YR1pcGW!BDN`&_7596<=!5H$ zRxM&^?Pa7XD_rl6Mm$l5Aq$4!vx_$0n}YdRI9FJB+^I-YiU*R6AV*s55btrK|4Vmq zI4Nq$aAiJNW3^1Z>|_h-C0evb0F<2=_*$UmFJwwDe0cdkL&OV!Encg`*QnW1XDk>& zgb>K|b5!2%c%)Mdone7=z?<{#1Omvr%2TC~nanut1O7V0T}cdz)6UACg&dO=VY`}%XDvFN7-pqZLvjdkNbbJo(`RJghd@q->QZ5)9x%j`Vc#vf z6N6BToQ`}P%3Wz%l3bn3{|UG6kN&lV9Ul!EMO26(bS%uRq6BJZ4QRXmt^kHu+)NVf-uJ=u%?o#d_BJo&<;WxrH@ zZDK%NY&!q!lpZuyytgRPIu&%m%C0*(TMM%J8y*h8@5wTehDx9_p=b&`<8@!S%lzsc z0^baR0f|~-Y5MqiXbC{WHI}rKs? zaE}DTF<2oss}Xo!B`wbE^d|5K61+l)j{0SgQc0svIE7CRL2H%_Ri0kFmJ-g13)f?l zb#~#OTI>^tKa)N;i|tJgW9W1HoMmr4U|-V}sv+ij3wf9Q4!xE>H`(^Ul7oPsahoV z!gVqM9K#W@MyP}I!WP9?%kU*6P2T|6#57sfF@WyD86=+Uad)|RGIvs0cb8s(289pa zBJL^Ev38p&>t#N#M-l9ymyhi48nZ6V_*aMdm{Q=C6yz>|7R$PMFwe(gQrTMkQr>^# zx!=H+#)mUg_ePpqfb7R9@SDiwkDr8SAN(`)zCRr_ejca+z}zv&suv&JdppgOH_~Sa zoGf8{5dp)O7AwvI3Du72~l$W>c z9Z!f%?~>@W^<$lz)jORsV(tW|H;=*BVA2;HiPv5Y z1H(;Tp0x<4Ug#5-m(u5+Xt?>hvmgr+CpD@_5JvF#rY!Zl`UoMszX7|Ks@nT%8h zrW!NY^E3cA>G_@g{l#Zq@4qYweNky^aeOGd^Uu_kS!&<;geT<9KAv5}%*sK!DC03h z(jC?Y5=wu(|K9bCKgVXp5?s|z9q>5TaRm5)dc&=G4B^7$fZRhZXYLv>HsV<2O)J7( zeDQ=wPCtOWFXpC$H?IC>AYJZT#3KKDvIeEn2S&0V^a4FusOoncEv@H(= z1U&)QO#T>t05{+2oe6;Md`CEfh~#%N0B|JX=)-KLCkCyw!Qw$n+KD6-M-4h1P!&51 z&Fc)9g-6qv=yxgtrOI^(B=d52Ll?eWxgC}%HvnhV9}lUD!5aDTB`1?+My+g-V;}&| zD;hudY?hL+b3}lVlYvq&a7DCql%@O$4EVxAy?S;gDc&2h_BfEn^QLhp&TtD$&c^2?tsO)^Z zHo+Q1j4QQweZc@=@2Wk${xj&~WSM3Xzf)(QT9sxUU0G$FL(AODXt;p$pNL&lCg&xb z^WUhGgZHnJ8aof-Tt=pCKYDg-{M{G&moM9}Sx> zegN%F9lq?0#l13N{Ut>Ou!9a8l5^}(fO&w;(Vg?7i=fYyF0Kq zdRy)5M54x;$MB_LJ_j$`iSFQO&FIXPLGKII9q2tRA2HgI4mmrjuXe;(aQ&*c5#QRf zobUVKlaf~^U$<_j!E;y;!tuuSzuJPj4Oikz*ITN~)TDgs>O}Z;-aiP6#kzo4vdn)8 zMeJLCLb0^HGvd5713cmPvm0^Y9!Eszor{P)vJebuGkX6>t-FKP$N7ayirJbL?49Y5JWI$PAl$-2Il7b76TSu4`w}Lqnpf# z-QLLaM+QI56vEEiG|9I9FTbrKj{u+d@s8^O&vw;#;fjM-##fmt(A_>HP?jZ{F zQV~Y+{F7wkKMENx*7~9Ha@o;ibXBU^e&R+Ic1`!VtW#|jeY82B)LmROYB(bmeOWlfyknN%m>wHHfwVI6p?Pj{m z)}1xhUs9_XT!%zC%MoT1+Ps@S@F!PQ%;A>oN;S))B0M%lWh0f6+iDPe@q#yex#w%n0!nip`Y0%*Ic&-@v_=N~>f@wf0(w(98~ zuJ&NFJU$M3a@iQ`d{brspSGZy{g`}pc{B&&a>(KMOX5#HN`-faaDHV~Q{O@$#n{T;}y^3h#7ylvPv(?s;Ar{p=z2f$pWGbEA7*x92-b(fEyz8y-*e z99|c26`60y6}?Q|I=*E)dHdw4k}IckZ$@}OVdz`Fl>(k?b9q`>o%z#0b)VtcqLlbA z7fa+O1jU4lXYi={ys!H^QlIVZq;B~?lzi%S>GsO&m-1~vYe7k8oT}c38Pydg&$c8V z6^~^-XsUE#@;0$Rz1}ZVDpV`;bM6wK@6<}ZOlr+D`td92$>RCC)PVidzF$2pUSU;c zNEw+%?266m_h-*8l->9=B-kS{^{u^3&*Lkew!B%;+{yzB2zlPINSbVU{PtkgfBNm} zv)#+LJSs?)5kAX5==fS_a)j8|n*wS73^Wiughb_c>&!{mfqeErlI^>VbHfosNm zoIkCx*%)|tOSCa?#NxrWo45*g>>r_xx&5$!#{9w$rx`U@;&@!8`CD@z75HHIE!B@d zs?}NZP7cs>nJhR7^78OnQDZy|563R>G!o_?l`0Jy+}paIdpFJf!M@k+h))6EBR|^S z{kbswZ?Q4+Z>IwPDbwwj&+afUM`dd6v{y5I>8iN)4bGS3XZ)u>VOn|5Hd<+U_|=I` zE-hK@6`{mJBVYK+zdIejg((mZ705)-mq)L@x_3~=+fEefk8&xIIX??EK`s0qnCTk|e;T*qF zVk;=A#l|&?T-_;l68@*si_aL|Ta^zeq3JK-&2MZNADB8Go(GJG}|HJ)1SJ zcqYS=YX5uND{+?+ZPyr`^<3;-glWTh= zt=_LwucFi4dl5?6N!6OJ)0Vf^)m7}5x7Jzsc4aZR|A5$kWnWzNc)+ns=j;u8_`YgJ zz0*^j(_owyhnAE&MX^#>H*ZjnuZ#9uJC?EkHhO@we$alR?}j7J)E{Sdw;yY&Ckh_) z_|s;2mq{cIapJBo{s%7MKNx#w(AndPD|G1mmOh8afFoar)BF(opP^g2y}_nEO5H;- zzkAI~hvG;YTB*Z6!TN6`2340|M$tU-ZA@cv1N!l)y8BiJA-a@U5ei|e+n}^3=2$NW zGvX3I5-+09?>{`Crhl)#!gGE^t7~`>NY`j)x85J2QVocF9a6-J z8mj`f6DBF8 z6Q%oOBweF4=s3m0bXag=mX_Dt|4t!cm!S&TB(GqWtUlT?F_iByI=N-q)nVj}7Jgo>5xQc-}^DSS~ioo8{K&cf?Py=1qJM!F|~3 zdsk|N@i3IDGz&(We~}rO+A_|70rL;O>ec$D7Q{ebOX=Wl88it!qZR1^p53E29M=f4ho1MIR;2e4R3>DNzHE; zDa30j$?q7p@+9R1%g*B2;riK;?pd^`AzDKV#yLGP&?h)(CAjc9G;ih=(oF0x4yiXU z8+^4GulZhh^kSJrf9g2zet$aPph188+#Tu+0jJlv(acbhFwhaJw=Qb4!^;kUSTHfI zDaE$<6vMyB0NQDyv)jVV+0KI;gEV9STtG!ZHrLIVLYn9t(6HdEFcC=%7@*_gwo4ra z6mh733=LZa@!FPH(9 zV|eo0>&~|2n+N0Co)(njYo5D{6=gDnzbqf^fw=rB-nx_^AO;)(SP27RMG0~v#9Rb# zto_p=Z0`Px#($V|bQn;eLmg2P?lb~nsaZ;PA<9uClDOj-FzM_h{;Pi>d^Lb-Z4tPM zEzFZa&oGS%8Y6;0wnYFAMGpgKpo(^n^^@}-2mukqI5>_7JLNb(_RuUL$toi8FvTvE zCd5XVNenuxyI+Xu5g}Lb3E`Bi@U^o?8BOma%kUSI)9iW6mfg2COaIz$n_MI1jh3B( zo}MnR!8F!H=Y;}vD)by~+05^R%2g$#HsOe7p4v1#T<;WWEqe~!!SVX^oqugnlq*Pr z7$<^<{^RZ@MM9&q=#wH6)rfKNo4CKy$Lb>zgR*1~EVEk!lLI>{ z+rNv@MF4cz+>JxgJJ`g^2mo7ybXJ8)jS?#zM3aBMoqUQ8AtsYXfq*7>7)x!SHk1FE z`ji{)UxSbpWbCL(3SyD;kAN+Df?n1n^9!cBkiif=`y%Gp_EMd6Edl^!C>Ck2Ul-EV{-;eh>Y z*$@d7R}l+0h{)hWb~h|KF9m1ErND71YPIm0)3|n*$(RTUpr!zm04M#t4xGld>~Y06 z(LEu?B?3w5h+^bUjPx4BjGEv+1FKLG>{UxiC5ncPq=FH`k=S+4>__}Y7b1M=VBSTg8OAb@WBSaBtC~4fq5yWg9Dc(hH9J<8Q;44goIVnE zb?2e{J15lxCpEom7}VzaOWlh-#sUXsVb{E$vb)a>X4S+R>IQeh4!P zh*u(3jd~8i!oU%ar8!AZ=j0-l6u1N!8v*q~Y&8!i-%BY|PC&-v;B=$JkO)|>3s}>K zkE70-@vuvuHDsZ^G1vn4JG2^B6FMtj79^KpQXnQqbvOGpVfI2@(yIt! zPz{`9Pl`eK0;fKtmZW!Ko$oYWM`4_bz)2()?=wd|LOPq9C;9eB!B~vsY*Rx@yKGWZ z;zko&{e}pb;zM@|<*rSmT}bMcCd#=WUS9-IHOP8HSunMbVMZis1d`kfs`$yw8$qrX zB6|Czf&q{oI^nE}&+nUeehjklsViCx(Z20`$XmEE%J~Tyr>eQ;*PmnebSlAaH-#>S$G5TUstOR(5PVDm(5o`xk@E{ax z*qL3E(j|cNQxZ2?#5iLh_i0UZWLM&CJi>tmnU%nJf8@aMiv5i!y3O_^%`*kT%*{j~ z{goY&>0iA3{e-dnq&L?vw4#;$2NHL<>0T0J1^6NNBa%)RQGdh$s4L((l>B@4Bb>r; zr6=xBds0UXxcONcETyb5>h{b!v>sms?w{yDK1b|2^%a8#>b zrF9H^w5MAzWgE7)dT4By+07~5!BrS&W3+kwLv{43M;CVXZ43Ny335v!QFoU62{ASt zd$Gi)_^*p6#R)-p9k6yUfn@m2_$j!2^~nTsMb zV7)m8l9LCx>HqR~GteUF{0vF0KWmY?^uGA=)aF{ZW_W}l!?%kp@N$7G^9p=<}kHNZ_qLz;CL2l`ZLZw zBGH8kbIGEkJ}n6Wc*BPqy@?;;0Q@mAHBSq0SxSc42{)|xfDw#eYZ2^(PP5qXE6INz z3&G^+((f|1~%fw5-=~Rf)BV2rx8~4}TQ!P0j14$PO z-+qz!4EDM4H}uRV2*Gy5!Wxrvaa(VwnK$9Y(&Zz%-n2|==#RxSN}o^?a5ez|PzCXs zfOh=%{r{x!YXBgzhgj0Fvph#+NVnr~(VlhIBOUL{f$(QzpCX&cYxUUiEphNMTdW8b zA>?Be>}Zw}pG zaL{5PF>LQ%k#0*D)B(hP8wayhf~u_ViP@{pF9!@y=YeRpYI{swev^&%HGxCW1jv-=? zqvlU^QSZ@-*8^3fv6~@T@cVMfB$q`4g~LEc7{ZzbiYg|yt(gFdv3Qj>MX*7%A`6w? z7-E#bW(zm$XA4ovj%AZPF^ps5pxm7s5ePqB9|QyMV(|Ru!A&@r5!uQrfHPeIPt$_i zdrWKL2@;QNlzhPe0zVMJkjXXa!DovmD%>!ED_sR3z*OFh7Rk^CgiyowUu49mwl`1n@_HL7J6Re^?nc|##C-y zx6mhVZuiQn@;MG(D0~;Ruku@_ZPr-rAapgxK(>APW|!>q_g6pj-__1ho-+e>Vn2ky zl?FIbYW#|4J1Pv0ba6NhGNmREb8GTuK%7(F zVe_?M9ln6qGG(+3!A~s>c+YCP7kO-^o#k#6X}O@ZtENZEj7vH2cZDt2uZJe=Ur%9p zv(wN+cjxm;j?%}Ir!S}Iu0QQVrM|6hb66<}xRZU82PoPu+w<0Vq!IohESlG^DKc&^ z!Ynwv~Ga@lunGE;C9w*5!L5mpg*OU0IrzLCX>@2Br?C5)@rv z(=Mh>*6^7uC>Yp^$vPL%r(kC|aX}>AJG1-UoT)np72uPQw7Y8-m6aVM;wpBSYN1wa zfT2_G6JS$IeqBHR^8O6bsQNTcjK3VA7cYE8w_;e*4hIpVYO%Lrhr~PN>11Z(_`j3S zxRA4`sD1Nuu_UJQA+FB$q651mcjVS_yNV$!+ltWo*443}*O7@;NpHfDmFGtxDNl+} zy)vPxYK4u%GhDi=c!8q?TRbRZo?=p8%34;WqM*&H{7`KXwJfjdbw4BQjQ7a@XrYt3 z)tq_nk1%@Nz3XY9w-)mqit$x0p{%?|kpSWTEb52^M&oFl$Hd|3W2FoxSu`XZKZw0M zD}b!fy{qWEo@19alClgz!CbVaV`GGz&Z5Q@2?MnzITppH+tEvYf`@>FCU}M!p!ExY zyk;NrcY{TJg=PS>#rc+b~P7tSxC^Ss9FPKS+5Hv~bQ7qLO06 zs!;4Ze!H#Xi2#FidZ2rS&TaOqt0ANml533tY)mEpiR{JOrY3yD^22kmmdBT0`UadN zzb-p!s}AS$h(sM_oWzj%-c*{KJzy199NCPqrm5jXyPl(OkShW7NWa{`AZnVd#V+1E zG<~c?6b)#+Gg*sJH?9x{kIZQq4BEjMFv8#n*XUiAdC+|Yc1zyZac2L~A^46Mo`Bb` z43>=cb5r0TDX^DfGhD404nKqZ{dYL9W!mQp4tY0K3gEmCT^89w)P>y?>BSf~=pSeO zsh5Wl!D_3d{Qq*&le|>U-?mf57qEqp(Vp%GoV+vd69dy<%<&mB>gZAIIc)5$ZG5cR zb+eqMDl$Jmb*@0XD-bHI>>g}j@BKZuGIl6nUGd1`b)EClZph0o|6RJf0I@zIid@iV z=+os;X$}!te-^GWqUF=eX;!%_e92#wR(MLW|BrQ4!F{PrX;0;us3+hVdB6%=7`r5Q-k0U|5@c+#(5aNf0~SYHmfdpa&vEajLOlFzHK(3nqUPg^Y z1E2n4V$kjieriPd>{zn`pEb|D6K*)Ak(^PoyvYN+ihJ!tR*X!G2gYQ>*-G-400T=xu_;`}>1 zAXt1+-&-ZH{6XR2khP3LKtXM5L+DO&)Msa!s=1}pNSu2Ad(#)@dV7aWLfoN(jG*BO zRnSH}F^;SCRQJ~x7Xqz2w(?bWs^uOzEF_pTmzif+^rS1AQJOu>V2|&g<_wx ztKW{{aOTFY-^!ckv79b+CO5Cz(sge<5F;|{DY8DgDgF@C_B6^4KQ(*b;MSalvd=AP zSn#;q%ior_L(X@l;@_J-t}qrbDQB$a8diUgX?pULXZ96-@WmgS{$E$dK`xsUum#_h z$WY!T(Y3|UGVolq$h>EncXmB~J&<^Mm%dv)ew`JUj;3JJ`lbJ9 zu`~e)4*=0b{3|hM7{Lin&J>#|`ehp55Xt$SBTi_56PTe4uu?D)Ly(ZzT`j|bQ>V1u z3?swy8f~kfCV+3Nm$QjTPozjvUUNITXz!b|p6Y7<0qGXuG|2qM)&P41h_TWFB%#gt z(qV~%G@6}I@;7(>a9Qk$z(>WhneVV4^x5+&sDPr4sad;%ytxVV=I}I&^NoYGuM|j0Q`z(7I3cnY zD<*~}L;)d=lhTWDcD1>zU<&5|BLMVU$_^;oB@Qn^WU;wl)fd&8aCCe+dh-T!cayUa zBk2+)8aNO|gYqid!kPnj1vF&(4hp7#7;!LoDVX@z6i<%#1mT#u&5H;lkR}`}6bVUV zFCpTNmLclLZy@L!%TANx)_9hAh-zLxCM%ZiXN*v3pNZ;KmeSbEh7evH6jExk(+jdS zgn_BO`SuTs&&(_N85KSogn*5UM_gqo8(}JC7dIY0(h#M6e;8y*7i@&&`upy8nZWGw z*dsLEwLT$9A#m3I=q=pOfGgMx}NV!}68^W;uMUFaT1$hgzO=Hpd* zw8iX)vz&TCxEKpQT{UYKFi;xp0WjTVV;ae~H%cqQ#K_B1Fnl&Y4qJ4sp&qyK>xZE8}&!Jl&!Va;f$XE}^QHrKFE#SS1GMgN#|GJB(;hL+mn6U-tO);7R+Wp%`L zEntz8x8s7*YK*ssA&XP^QtV~&{Q(yQswqyaG`6nRO64g%AoA9WBs@XX>F>5M zq%ay2$cmU4&!`xo8gRDI0JdlqBnwqN^YYFBeCQiFOaZg zdd1asY$Tx1-RxBFg40}!v^rQE^#+^{$nh^%7#twHRIM^TsG52|@6cyP6|OusisaU) zq~mI*7`;pUTcs2ewQikG-lC4Jg`m0kMN020St32AmwQV~dCQh{@sd z)5J5R%Yb8(Lyf~&)sHf%=GBCh_Q3@e>1X$3pBYLoWys1q_&vV{jSd~i81TRM2iogA zDDux?xcOifmy5kU%7NAS@zic($f8a z=itGqG_9VQ1AEDf8lLpX^|#ewU)2X6-CThhi)g*tKouC8VuQYBjX)0(;%IaD&YbgK zu8(VU>`(uj`7`DlW-ThEH^#xdtp3vnkb1~;`Cn3V+ zxa$h(-Cgw5`;8(d`oLFB40UWMx4DDiEWsEnE)1tYAm@ib`;BI&&JVZatIAoM`QJA4 z+cu-UrxpurzeOFKzZ7K7N(t{k2^$lr*~oWWPVH4Qmbpz!+Px&6@ryMN zNaJw?ck6k-_kTO<$!s6wx(d}819w*s&k!Q>p>4SL!BR9i&A2v$>H9`%49eHbl-0g! z#Sye#wV6IQ(6*Ia0l{n|Vt%ePJqP8U{vy;GakpAF{JvU$4|D#W;(5SQ5v8!i6!+xn zMFsUY&6;Pn@Tpcqc3zGT`wG=UV-ji$i~#@C_5c;r7-hrQkoN z-4T;MD{&yB_AS+hx0i>vdRT@<8w@e+rBiUX8<#@V!iyP3u@kX$ zDQQxKYa)WWs+fL~M4xb0Y|Bf3vl$3BPp8Kp{!ivh@Q+XGzDKi$^e#1!lYK=mgYRm$ zPuT8!_l-W0NNRtY({`ogB>H-B%nu=)pPc>p$#KQAID?Lmnf5s?`Fg!Kul0cK8ZeQVjReI32v#_^XuTlwTC{>&O9FU>gqbe zTfN*kEn%U@_qKlkeu@e|!ea$aD^J6l5D|8|1demqQuo%<#>AV9ZSm2v@w6A@H*^Wo z7JAlM^riKoWQ@BrlQD*~*a#v?0kO{j2z4Cn9Z0SF$9NW)@p#o{-bt7Y;t&C$hyWbz z&GRHqjMCdR=Buh0D`Z#ncdqy{N96a8;!FUlH5B1 z;2?rfwNq{WB3#VU2zoK@<$#NoiW!I;7f%M=)9+4?=eu5Y9)bg-~<6!wTZ&Lm8;aT%9MY2{VhabKh2teW98@ty#xJyGBH8d91x&r zGp+VA7)ASF!BD12P#W)QI{8nXrqL{em6bMlW%0R3xra=<)4viYh8u{({0>pH86*Ig zS*~iFo(GzMrcA9NgTe5ByAe0&1<*u#iSt$yP~0`5;589r4Dfgp;GGw-Gm7)nN-&48 z^r>H+_%Whw>QU0M#2pk)VTOV+F^VodDZkx)kBUEOTtZA z>wQr)-U||0TMxUV&&jz}{;;qF0fc`V6WAONqg-*z$A8}7JxvNPxen#2+%4Pcbs`*mJH8xd8-J7hHdbwP=0G7NX(3j{v z``D(dAmIA*+v`L5YK6C)y21}XE?m!~$W_9Q>A2L32(JA}tm4>5qYPf z8kD^_*v)|>zYzS}ez%wY(v?w;BYJ>$?8U9phYTZtgxFHEI5XK1}J$`COhX_GG6rUG-P8Wc}k#(%?DQG&#|8o|PnVNF48&$fK;QHwSs`D_KVbQ$mbK zgs#t#q}gBn60dI_b2A;2tgW9LlRn%SZ`^L$pBul_i?lM8xe&LH?UoS6y+Do~HY$Mm z4{KO|V(TVwd^4`=mq&h;Se!daboWw-C$oG$BWBc4Gb-y}+)@TB9!jKqyW-lI92Qdd zsfFP|ivPu)p>mKy09OuOE#!e@dWw$9Gkkf}mf%`T^H|^v;~e2>8a*I?3Y8RFX>NKD zwKJQp_zcIye744ffHEi6yoLuyGc$>>%nAsdgx*}P%`3Sg>WHc;Es#@IH&H(?S*X!i zJJ2XQD{XfqV)y9}p$Epf;?EPXPXRs z4rh{V&yR;stvw1wng)c%>*b6tE^p_-x1Mxt1Tl z#;TMI4NW!KvqB~4sDXLy*NAcm2?JN?mB2Q6tZ0-AU%M zg{O){+U_#{6OFqx{CvGUS+i)pocQ7CkL-{xAG`EjGj56Uf*(H~KH~ppd0I%MIsf79 z7r5b`(WOf7Az_fQ{P)NDtE-+DHyc0v`+a!H|D(d!xdR^fELy3Hs>hq!1vwkHlmO5~ zzgA#OGB2$DMQ^Y0cr8U)C@yQ&n!>-?VP4*@uMpqu20DuiJ&ko38bqLc{5+6@HErHV zaybA4=zRBjGX~E>JSuvSbHgjsPFCc?Jr`!+9}e*UGvK{F_O<~aCb|KlDahU-Y4aE* zud+IO&@aTf;Tcut6?Y{dB3^SxD{~b9xQ}+2AU!leUBhPh?be9Q>0gk-w@*Lo@Wm&4KI)Eh-MVqslkp9a?^k_i6yAv#lH~1$D@LrddcHuY&IMko@L)Dv zyuOst{zf>N>8fa~$F{V17}qtaTKB!+t0NV8n*XEd&f}SW{5XJrcG)o7Ft=&WT)D|@ zbB-KyQ_|c-8Ih}FbKf@!)!afwC@C6pB-MzLuDME5xug2FpWpwV&mW)9AD_qP^ZvZv z&)3Nx#aBw+2~ZNn?EO%$F8<-Q4dVRJR_uIyw7IQI7e02q4+@wE8ZX2_A8m0DPpS zzXDvk-sdvLRX1cq=%Y%5DOU$Nn!tIXsUr4;ATB%`1X=JG85)ARD}qsECWz0AQpJJO zhNPB(6I=@jbkdWXz=l$t(Rcn4@LsJH2f`E`(L{xNE#kWWpg&9x*Pq`nic4|hRXz5g z#KLq*l+3aWLS`8!Ff1DLwuQ)|8iz%FpNQuvf)UEpC*qatL*Lmc-1-1mP^Y$NLrZ>_ z{M6)-3A#na_Sh+q%ALpH;_|QIQzckUDSx%{jw4lvG$bUvpE~Mkj!Yb@H0^W^<|_nV z?{N!`Fll*r8)Gk8kn})=?6-V5r^2+v5vBtNapZYiSgkmU8zUtgU#Q-@;SZat=}KGr z0vau3nYq`@iYljK-D5k)b53FA=G z@g14T>oPJl5&65mjJ9d1em2kf@u<#(L^Jb!j>TIg;5d~H6PcSI>p%=?u8I~#8$Cxf7i-eP4P)j>z< zhVLd6!NrEBnhRDp`rgRgx+Fyb>*sEC!StCB);e5&!n^z29|gT!E+BaJp6;z~xJzvV zE~#*V{NDV^31UFONjk&%Opc%Vy=a;f$wH`dZ%FioGQVOe7mjn!S^c0qJ!30AyJqtY zpP+aehAKA?;*BS85eif7?|wg#fe{}zZR8n-=oeLEw`*Seg{dAy|hnIs!a=m!g0W*q4>_qJ@ zcsb`x_(@-6TRSfVSQ13koM!-TPwK+d}(&&&Vh-@r2} zzww#3Bi66;_<(pkX(@!`&qN}q45ICxE??q7E_`qBB{V)m&9R0zJoT*fJ-@-VspRmB zBi0g&EBlS(1Nk=sX`ccZ12xPRz69(lXoXd31GS=!d=*4x?>&*Ffh_Jt7~OP0$+-?3 zG3|+Xq=ddHNv`*kMuq=)zYijWBJg(c(3;qFj4hSNMmwTI_O%qIbK{5&MsSMZGz-^i(cn|Bu7<=)IRW{%M|jaFWzH;1yIg z!0r*oZngo*Y{6PJ2l2xZ7z&6A@MN>m?VQsq%7Ek?(Evq|z$TwQu7WF+;ZBv0T&n}L zp3iL(a3AXs?W@;6hWDZHkWd;oixOoIq^!-GR1hpJ7xyHgs3kwiaX(2G=wuJ~k?aOZ zr26XnXF2Pcr&d9@Lk1Y_l0y~s{5_TN9#Vs$!i4J8c|{%?S274n08pm$@GN!6lJr+e zFbYLGH??x;g8GL?>ekFViY_;kMhgFa9z>qHiA=NkZ#o0OJo|6;4p#oyKYL9f_sL^F z3e@TwB}-)yxh-mdr5lSTMdAz)X<(lCW2d{Qp~(Y0uWBTr$f()xa|i-Ixh+eh(EDH} zblc)+ur%roZ}n}O37akUPQ}Q25qr8h_6H4nfhf+Dj!|p|CljUZ$T*7pQ8~CY4W#q~ zAD!CjlP-VSdPv-Eg@>%T@$s1Vl%ng}y!W;e?sh?!_zScnJzXvjAkj_4=l9t|ICL?V zt5HfU_g!<2G-=`8NP#ajMQ|WQ))WHlv1PP0Ws`sIG5`yJfyj=M*OTE+mz6UN&6uTk zD=Y!xL~-#TX%+|`pXQyp#$TJ+Z4Psu^^;$a-=kV8x@_*KIS!^Cmb20dXuIp5jJ`-f z$&1K%SZj`ZaH3QbxP_i>s!qCGK0ai>J1E7olB1U+{4Cc%_+WivjUb+?p(zhxbL?aeG82M)}Eb5BSV=HPTy9bCPfW$`&&3*I{>l7mt<@t+YDe-~l zI=R4hJ>qoh8S}tYI}(2_*C(AVYUQ%v9`EPBlR3zYQ;If<(y6B@i(=zN>TX1tm2q+5 z46bI`?vXlU{E)+#y=;c!5e#^csdmI+#2m5Ky})yc)N8LL zUi7oc*Q#-vs2Id=Vhxe1uW`Vdi`5~HcGMHFT#^fS)wit68cPge(-*Pei+V0cm|B6P zD1sQLG-%>3QCi1bqE_e&IPH=1)ru|Gh_lH0Mkx|#!JZb5SrEwqc~H|%;S0l8Mr6x} zO{Ey#Zgi7PTCa5-j=Ba)2T9eoN#2I>sR{y&jmYvGAQKHGEld66uc9sFPA|znwA1FV zmHU&PFty~e;Cm(q$L37-S8pMsRU_hysoO*8m>^`}vd7|OH zB@ERy4+;*~R(NVoa+m&C1C@p9UR@TW$)K^xdx>oLA03Z)A)q)XCni8wKh0VRA}tOA z5y(C}rDD<4POOa5JYLj}boTwEdG@@?y7kxoN#6e411|2G##nW=P4wSMgEumU``aG3 zo|umi4Js%cf}Hef8TMmMs!aJX3nXFL02WTRkyygLSi*K|n3n z2E_AUI9J?jSRtjL0tbF;dHkgqWc!7E!76&O;T;x&z%DSg5oR*nR7}#^GnWvCqi#D* zO{F@v4}2At(TO_isBD2tOgX1<*m8QN&)DM#;a&~tO*m}GhqnO?%_V=I$AxZ!+CY-C zLr@**k{r4fzm9kMbr(+JpBX;sy zjcoNV)j2=OS-N!YNCcNWqP9H?ci_*>b-><(avKW~nv7`--8~r( z@zOwyFnI;eNh>0@Ubm)J5SSPl(ZazxItE8M3~{Wv!GxB4x#GPlQh!XWbPIdr_IYC2 z?@JH#T5gI5d0ic78zAlhdIrzlUgGc^J+!>5%(ig0#|-SeGL)C0>4>{S6!mG(*ZiFA zneK`iSV!rE4%t}w!IK62iUJr)9qU@ZfzGd?|5oZG#pz<{4U%I;%~|@F=`u0RZl|+} zPSdSm1WR|uTza~O{|Ak3k``r_{6kn@?W?TUcR#(ZLWtJ=Gb{5|ES~I{XV7%7cj6Is zX6N%S_O^Vf)e6+UniQ9VmjJZ|%%?X>_JbtHYcdeKrjZc_<%@tm9)Tzl6MmjzJ*Kw@ z9INX}*J8Mmw=N0}HS6x19s2B+@Gku7@zNW=FTXMhZ~EQ0{P5WA$|I_lCnm-`&4TbH z00@~;W#?tar9Bd?`rAhXx5k-2fdKlC5swvB!{e+L^3G1(+({|OAs z`YV=Mi3^_R#}Wm7IRoPFtGrj}Vo-Sthl@U2k{q44(-w1iCh|&mC`bap)BDma%ICD) zCMf?u{)!q=k=lFt$Lp$os~RRwqW_z+N`n-?IIiGw^j{!jRZv?Q+S4wGh*$)vyhl+PmM=&XaU>6{<(bhgx#bb{-D z3)h;%zC;LLT8}y$cInp1@rJFs*1y$*ToQ&PH(`><<{7$SjcG<*_p;ZAtt#Q!loL9> z21lcvQM8||fOqdX6W~b6up67rNB1AmP3K`c>{tG*=a)Rtm%e{6RTGvP{b}M_;P%Mu zQuTy<0bos=n!f1p!R5PY#Mk=sfP(Fo)QrvbiWLh9lAol&(e)jpWW7rhiKh22|NHKD zyYUcFY7pFe@v}tY6McL`tkflA#wEu}-k$#~PUj11VQQ~sNFoM^{BEE-qp6=%yQyh8CiPk;D>Tk-Qr3>{AHz*(dgMKm)OU<}XeRdY9w?c{ zq(gbdjWacB203X+2}8Hg0_HU^z{V6_!2}2#5Lf(+UmEpeMRLa~jkB~G#>-TlUdvM3 zz%=lY@VQ4>+D$L687KY5k~WAMV08y;%M1um8nc`I?*fl*i(3-^x5+v?y#Lcow+H1H z-mVbnaw3AsZkCg^t~VpzZPp)u`B4;z0U5JkO-zs^`XHj{`LjXo@z5Gw&JJH;uLBjI zyjJG^%?4bl2!3YA%=s8q0Y5LV`1VLJ6~B`FEkeWJ;HqT5v@oC1y|uR;vW{(D!Zp_U zQs`Iz_>6m~rRo7MB=e0QY%WjmbMfuo`S|$jbnA)7|6YE493=@bimu=u?rkhRt1>Gv z?fbp6_Kx%LGTQ84{8zux&!+L^3e_u{fBtaL6xvGIQ4|6pNghz*P%H>10psFp=eL16 z2cJ2s5VWC=;?7H1I9|g(^_A{Ufu661X1*VX;deY<_H>4WY~@7sOd9xh6E3Xr$o9+A zK-b8pJad$7V3D;{mR!=@hhTo|UjBAx8xE@^u*}0ZE2#YVW{9N2^NZZU75@J$OUT4~ zHVgVl43Lp_qMtjYI(ppZhF73ws&G}vi>DzszJxVhGwur2a*WS2#$&|Y<}z_vmCTyw zW}hyYKQmIxZdy1j*^arH7j-dUkZ`#f5t5JBi9a3+@7R5Q{ZcBdV z>kH0!_?`Y;rIYs1c!S`M5viOAiy-sEACl(6EGBU>|Lo3mzdr8SbkT7EUV8nxFYoOl zn#Y?NGp1rK!k8aCC*;0V93uPh$7xTr{?r4bYcWj8^?A^xgZk5(0ESv=Zo&gyx<9Wr zK^t|dFv4|<&F8J?Jqn|JrB7hb22yf zjc>r)jWPcMhkI0uTkj&%<- z~wvy*BPMV+v$cm6IuM?aOn?|6^@4>|JcWz=tnVO`P0uZ=f;$alUFAj_QW zMIE{EXr?TMPy2QA!`rb(t~`54_%5ZCG=2HD(Vg`lLO-LYY$P07GdBcY{@qkBICeee zL-x|@o4KuV#fcN2yg{d7T>X91p1qp~NQ*+9_3d=vH}QBi1SsR&>I3MS9@8^ph0d zr<6djYflCxD7jf|o-HRTCU9JXp8hS{T{YyfWIkV{I-P;KjCg|QiORH8t>rHuNwhsm zR^#ODA>gp4N*gLoCf0y(QmgP_N>+&9Cc_Q!d&TDuzRT7a6jHU8zP2(-_uR2Oa3q2s z^MV!kXX_-a)x3w*9&k`#ZEc8uGtfAef~Jy$EM-U-9Yaj2KwuzR#0wM82#{P}krq%F zlSJRclvJS?w(AIyZZ@hq;JFxCwo{N5aIHE{Zj= zEM@-{!rj}~b>D91hUj?}CW0&k6V|~fdjLGr)`|C=90v1H_)(2TxKS48iI&-7j?rJD zNa7YBh$Wrps6Y`|ZD($UpGp#F>*@mTR3Po#!qDpLyr|{%7GuteG&-Sl2ny)CYa{~6O8>S& zWXd3}c3;4XnhMcTB!DVIEt29_fO?j^zuX_$HeV~6IJo-mZP#-`8Kn! zphAoVCo}-IBBgL62{djOyRz1H1n^^+$B@kgxR5Can`<C0`mvTZ`PPOl7&of z0eYs+S2pu&_+P5Rjo*8t97uKP>L42zFF>HrxdC@>vS*Jo}6m0MOjQv6$KP%5Uo)>x|?sWa?T2{qEZ5Cg&FWE3Vco{v>;|10C-73&bJ41 zhyP0Gc1^w*K+4g}`gYb+#c%31wn;R3cvG+l3r-yfPgAhJU9J6)K!U9WQSt9@ke zE3>AE;630}}oNPfrXoakpyeMz+TOzL?Of<%C&~WJ*ee=?W{HGO^U_?$uK!tlt zOduQ!utV?H27HRY^W9X)v!F+yE*FYlg{TQ$>6rju71~P>;GxkRB&^>f*viJpV)x$KM-!AkDJsF5jp{;JQ@4Q59Q$J6UBD8a4A%>tMCdT~Kn^jdT|PQu&o|d)c!k+u z*36ffOE3nRA>d!p@d&PI$Q?F9)g5gSv86uUan0l5jlnw*G#^BmyrR?_5c4LN4UN}*r z8xnxw3E?pySgf!pR0Cx@a4@ok`?7ojSRT7<-WX6+lMT?h4(uKTe>S-9)EsNV3(Kt- zd2S$ggrFa}(2&m;Y~useBbB0K{!=bsOnV3h-Iu4;;I%I=sXUq&JZL#K9yN3vx4ZA_MjvPT*?sx(~ z_8bU)$ehP@!F_!_o|nR>J|L5>AcmhrU~BO9ilm0myc{MRI{ZJd_FD z8K&+sQ4#|{)u^FzaRGpFZ4nUp&qm};n)JDVQVf4|!vOftqA2pWOx+txcDpo|4iuaV zlid`kXVwT2sF$fc^$cDIlKdTt)md%c12lJ?f?m}Ko@W)K?c{}44dO^Za}SW$9$6Td zhL*w15?rm;5uR*H>;OQ@)OHNL=CUEMq7m&&v31UF@NPM1Xfb5ls?AMu|H~*_Ou>B; zyRNb++sT9~dH~rBRHQ6!vprIuilaKCzu1KD?zoDPQKb3H$_Awh)*^BH#!&+iq1Y;Zq`q4joAY^2jl-=_J`bw2qy~ z_1H@$G!(5xhYf258;q=PI}`*Mtk34vh*pLW6IEG|gmu)%lop@g!n^Az zaSzZW_S%cnx87vmdTS?9F_l`t7ODDrXdx?Zc^zHP&U*?)eUm{KWI)u14lR?#yMw{{ zOz@UCG;}={2_RS2V~LbfONb`K;`Rp%87U%wJm@)0Q}6G=L``NMP_P_8>W?`94Z+81 zVm!$*PnPiq$Z&^UVd=cc9iUj71SCBrbJj1>bR8P#Tv|Lj;%-nOiB?_}+z{JyMN6<} zmwSLI#`){VH*5!J?ZO8rN*@i%=8g;E^acGIyPSBtomIN^=NnG_Mt54>Z5KSWPzhSp zXt=x%cvwP|1ezk>+`gjarR3@RppkDGK%J3j-S7e`fjdx4$KHZk?!4LL7V%r0cJ5$1 zkF@9|`6F7V&t4t|Td_SoL+a1dA?8)k0A<{fZlDDy4sFF%{3_bPX9IY?IaYccRectG z%hnm>fAr`s26<@);Q$5thKsWfE1f!8GX+TT>*y3aH@ZGE^OQabql(RpKO8#tXt=d& zx*2!a9k|i1@-$QmxF314N}{*D9*;P?W@j9~C=IZDsuy><@C z)p(U9Le}uCDe6l8<00I{?XiJgvPujngx>&=pJ;p%g8-+!S4a~zR|xkf0-XCQrGI$j z7PR#O&&F{})iVJY750f{zj3AYc0yA;ymR$8I-!<($r_l&_?(r&EowvuP&1mJ89fYt zBnJ}cXNk-T4IRxLGMH#^xmqm)4noUxj95q++2Yum(HF#Xr)qe|-Sgc*muURr3)#RN z-iA&r+y#08Hf)nD{x92fU^W%I!KXc|_Oo5uo{8mI#PlwS!U=c1szFc|WL5)}cQaLD z1K4HozHYeuN}BKE9>C*|MqaS+K#Ke`5b?s|cJK$@AIKy2?y|WW2iy^fTrUy`v}IGk zg@^g}4)dj0;nXM7p4JC}={k_rzKzx)-Wt6*f-9(dyhHU_XGE^CYTl1xvljTcedu_O zq12iM@MRRFD{wHO&%k_*+5s-HNa%HTcyL&&|1Y%_@+mTF?9u@0y9;`qjIJ0})vHaN z8$g9rqsE(a`RE5JsjG8Vf?N`%%pi2+FOhzN;0@+kF>4Xegl^fY>QA<4@y4XLMRk(= z_x2CBESbxHOawexC>LAw5Jp)tTB3;|RPzY8Gz_hikcQHA`bf_05hdp_(@AE_;3BrFIQBXPp~S$mG{`=7h3g0Ra5A8}RS+3-v+Ny{+AzrQhO01h$a63(67(7L`8A0Z^9#cs*lsDt?MyE!K&Gu~)I_Fb!YE){!YPgPj+iJQ zfQfpfh)a6PUoi8bL>1Si;eFXXp0tNfj|GrqMSDfuZ#}_fq@qYitZm_Qf?&^09RDh1 z&SY%v5Nbi%)UK-*C(Q>_uxK0<#`hEK}#EJ#6XTx@cls{^p-YJ8& z9v8RZOFyu0^>%z9?vNqDxk2g?dI==puM?dH5k8z zUgeXo+RYofh=&!H(2vZ9dAiOLWMWsaOUF5~-vE7p0_^$*gSi zca6ve$DP=wBMW&yRtoZMIqpd>_y-T3)li6v@uRhC$-hNru_B|iyiXV;nG7PY!z%$~ zj1TJ3=O!4rv-g#3@bKX7I?ossyDL=Ld%$*kgYbn=Dg#lELCr;ZmUgIod_Iofh_9KF zy<>bNZWrwba{EqkDid?sp~BJYh@Wh@zdl#!fsfBXHkl}5IGU8hug~Hoc&o)}LiMOmHRo$;-94saPNg$L@=l%2cC0?a{KWHntPgb$*d!*G&J;4!8EkenyVt zkH1a4Op1kmYi_Ak8*G0zJ82u;NkH+$EZzJyAp+CRjPS1AGpsoc`*FCg(cr@ z2fn!F;prdv?)CQ*JyFa3-SGdEBIs&kfu<###@6zT)HA+Rc6b>olo4px{F_BwKz%e_4O*gE)O80ea=+weE-Pl z_q)^J^L}q5Yj@=XjLH@}wKUn_)a3i&ckJ5R?#M46Km7TX<;5-RFbZWRM_SVF+&?+P zPMp_W{MN{M7;t7z>r+9&hs52L4W5ZAz(!dL7zI)l64&;J2Awi1f0{yM@1o6`5%2j%{zeNHsP5Wz-su;7RvTpl z4&bHgzZG8k-X&1={N`XBm@kihWt)LlpB#O`{B)|H(;L^DE{Wll>@_Bm4 z%|!WFN< z|0g-(<`2dy0W?44?tW-}iAQ2sW2;HrO!c_i5)JZWFXVyyBp>Pp{X9{(dDL1^N7$%g>8Zx4vEVdb55LU{fT)rkj7LPXs+LM2*}R zEHvw6-2?zk*Hw)(3Sz59rt|uG8fM*IsDyLZPFQK!=1cfL-x3>kj5(ZyooD7m+v^IP zISRXY;&Xx3m%a@J`FkN15P%l&z?SZLDdBTf+`ok9(iuJxU=PVG!1kfX!@lWZ9f=R- z&cFVSJ$!6*^O{YVDE$4$H|L#p&dpdgzqg@( zu&nih)~1)ay-jb%T1ygJDa$aCOv6v-drv0e0Bw2A7%Br$0Bpb}@f>q(BRNgwZ{bhu zX0fpsNpNkEn-?7|kQiSBls&t_*Sb?|Qz;ot#8z4gS;)eI8!N0e97uK} ztu{UDdo~0vmqGw4u8|!FOOUh5I$xSj5}zz1UgFMx>JKyR83RVvE+thh@B`K_yfSivf7)_^F&pIOg+t%4K|iR7DuLN$uE7J+Eqm(ND<_ z{wiQ8cvl7(VF~#uyH>uc57xc4HJ;cm%WWasAY9aA4RGA>Ch46D84A$+=WaA=wrYsc zhkeI*Elq_R6auJ%H5~dc()@K@+T_AlTrlc8>g3-LB3~jo)z{KsTf<4>PWglo*j@Bbu9s0`pI?aEUVJqeT1-G8uZuIQ?wp<*hyXhKHF91BV<9FZT zE~dk3aNEslNmr6zF8=mpLJk(m2mJ+tpZkN{lAycbi0Kj%H>h&OFP`^;A2P&i=$w)R zIOV_us|Ht=bi?&}he4XhN<3<78H-tgoi|==ZTzM2A`MNM&r=Q=-Xmo$zWbk$z zR9`yYZ6%wj*a?AmRcU-*Qx`NZPfPYYwcXnzwatz+xBfn=a`aBl#qGvpq%%D=5rw#A z@@QYR+%VsqEN(8IOXGqcAC+Pul6R1a+hoH7I7Fe>ilauA;BYJXh5~TSsD8|WN305f z+>8LQ6acf5gj|KvV_PIH{utlR2;NnMyU-t9`5heXo5btpFNd(1>f-x!jQ%v*RJxdS zkY5sAR*flJlhjlAnN4eFfj1-{;eCl@u_d zf(c(tHZ<29nA0Z}!Ji!`eXbL)OgpW%#gj`E?2T<7w~-qzzYOLpsY;j(%1<#1H5Zwi zr97JaZ+lJgsoR8dMk!Ar{R`ob3GeZfb9OdMe*F7q{v_OBd<-n?Bt=Zu`@ZN(S-|8; zL#x&`(BQi$QEvzGOIB2LLw#O%wDF=)LE*JYermM4SN?+b>yX${={%=+X>NTDI(I0L zW~{Ry^huO7@STpTe^Jf7T%nhRa0Jd@FfZ3SfX6Lm&b0{9xby+y{a|0Z(FI-lCE>|y zH$P^M9&ZMl^nk_xaaftw@BNT?4MRAK$`f)$V)a#1KJeWtcFW#YWbGVoKNWkgs5>$e ziOoCfvfGn9i+Z`YFmra%J+S;kyL~-@0J^ zQnnmS_eQVbG@_BJ*<1(@(}y{*A^NnG#XqTjWOzrB_MI>bi}{ko_>AZAfaYeS-jl9q z=S(}Kk=lM{^m;NZo+h)`;!$-KRr=8Q73SSWnhI%eDIm&$&Ko9gILW zY4)U;?WJfk>2O6uVH!k}C;c;p?oY~ik=YdqiM`9zd(-TSF!L!}Ucgl$@c#)O(GThn_>%qgd(wdnsJ`m1+clS~R7ssKkS_Ubg6LY-XQtAK-bE zV$I@;pT)-$;M927+o(}$GI$H2NpH@0csj#1se`7I&rQtG6s?4;gH`1KcLv>+0zWQC z`_I4IRU$K*41JdbI4BMaTqRQD+aQD#fm*#ju+CFxhCeOYa|v({?WFrSjA#sP2bAkX zppLeP-4DBxfxP(x6OCEi578+$jeie^yuQjONrV(>7fR8Aj!3_y+1cmUh07BneV zYGk~66GAx0hr5~#j~UDQZcy|y@XGpRXK^zIwMSH-WTXw=Y*fr}rGUBOt$2wv9vbAs z;6%uK6BjSF`G;UC<>kS}L{XS`%;7F1@H-Vik!^fS@J`m#ek2~&=A0R~4l9TmhBXh$ zU=>rmjQ;UF52-GUBE8^Y9!d>pqJYPeKu5q#t^ffU(PtBvWN9ILL_y45K|YNO%6*Oc zuzf?C&6LV(NtYq&b8UNko_HCgxz5x)JMXEPK?3gFyxI1*O2L7wN;>@1SPDh%wun%* z6b<6SOpmMJj@h%&Vf5ATXY#P1XX5V^Uv)95=C~@&R2n?E%AU0Z6X089=$U3wE(R>J zB_lV9YXM8lxk>X0q>XJFEQzY07rk9`)9Hma$*gtY&9ftSV{*g;y8HiJ<#vYhKBb*| zqz#eFj2=soVcXS7RA^SDdFpdT?CBeoWT18RncF<3-55cpYRX$}#kyfiTE=;-a{Izj zh#cXmeiO32P>QK)cK6OvSy~jr1R$pd$h(~3%SA0#-t5eXqe0})KyOT0cswnN1r@)a zsID|Nx(<4Lee4*W1#`Y@u>S;P#Y}IZJgx@d4n4`i-569T^gM8-sr_je8*x*kEd7Zq ze!fz_)Omtt{|^j*mRKLT*AUso<*>&|F(N?JGsj;`%xIFKt>|pBY6l<-**h_%}J?5Y)X?O+@l@(Sg*Gh6h0z%-@6SpK39jtSS5>RhmPMho4u#!;*hc4*WcCY>FO~8h*KFLUhd?} zIys%$x^(?_3t{b{A3T`L?d6saZ+jKJewZTa^K?`2Wh$aI2C(DSaA<7-kOr0SD4O-0bOpv|jnTyd03w{6S>=*ubV*+c95V9=lZ9vq;g5 zo8!+Qxq89;mEbW*`9ojhpS-SGFdk4KG~R5kNvylBfAVBzM^~@3$R7EA^h~p;Teos@RtF?<-p#MOIEDptpry#H z(509lVE|;?NS7IdXckj?mIatkO(QTa>6q*>NyPb{Q3@l?i44`jk9y?VD#WLCl;tn$ zr~OU>w9XmcBWNUM3h)v?u04=m>(;aCNyZ`11g1xq$>(VziN=fIx_6l~V2XZ&L z?)fIRr~jztX17UGu4Y%(WVqrDF@;$L(Ylsk|=n*k2 z;tc))(yQI0`T;z1IApBbbz2}fA^j;4V*5bLRp>)XVaCoyu2XoJRS!f_19ax$1DF>} zI=tnt61?{a&E{@UkJrto+$Xs7#wLp4?ucZby#|knKG+zb&-%orn|npHO~w3ph}4}J zQUfd=2JdXg>9%E=5JLV1udKfA{!i%?8_>H5`_|?1D=W0`fzb1}A{jG7#qk+yb)ZMD zxl2f2UixugevJqt$sZuDtMv|VCUssJc7F(k$1u~qNv8Vi$tvr~)+|^<*Nd2b%O4#a zOCJA~sJ#@P!j~%M?`o82PJxaXmO(h;K{C1Pv6edzzqaSSvv-!;9_iDjw}a1KcRoYu zmp>T}yFMTw0r`CI!RwsJ{p$wEL>Q8va>SP3y&dB@qU%vN>glR;7^30S{W*~g_e(ht zs-}2Ex&EdjX&qA43Xy5z>W=_mYv(LX4v1%_FXhbb8#`gV0^TP&_Nvm}r!@|j7Z$ho zW^XQ?*yV9)FH~7sPG67g;+^}ZaKF(vYDD1{^}28B=LetnQet|z?FhA;g|=zY&X*w(>_Q zW8}quDVR!rgbTt;QyZj6)^p#3I41mGvzPZwAnc$z81%dj(4y?8}3_BaEJ2E2D|^E7|M zcTEOm6q5z7{5)vfMYf+;*XPpj7E8Zh0>4U($&}`;0qKm5I0>&Co_JS}P*x1hh%7+W z5VREIGr}b1#Y($0GkyIMv*Pxk+fw3^h-96^#9rho4`x7)(PgL3A1ns1|fS>*hZ2s&d?@B6lJ}`|+*dEP}@8t(Jg`+$TjR9yK3! ziJYlyH82H!Kl<^hn3NGH);Z`Kg%^-nyZ8B3_@p%ff{7ePibBlRlcgw&#_?(Qo-JKG z+%CQw_YohmP+9Z0rgbv!Rs8i836CpRv;7XTQb3nl9C?5^+(B=a2-Xrq342}(v{XF5F# zXeLQe(`2MlwA|BT1*cm3o5l6kNpT2;$=wa7bRHpLeYqY0nkVBs@_s)i_vBbEt{~d- ztFtUU1kZI^h7uz`({lLg@m4a^(xBesvD(EfHWrj9Sv2@?3t-YA2&%c<9v;CmievfA z106>I^{(O>QZAEjv@i0G8;Lu0YOcLH4a0&B^v7UtXMD6tHBbmM%}_ zIMq4cO4R-K`u3@z{3A(v-{R!=$ao-%gr+mj|dwW9E|B&${PUo4ZFY z8pf_3YWU?VCYiLe`sU){i|GIX6T73Qj1t3Lh+#7y{;~e+#D8#Gm77jEom_m}RlprD zECPy(B7-0ZHz>f{|F?wy0y^=^i8Ca6ofx1%+Tu6KIui8Gxf7t#)Pih##9hglZ5!{e z57MV)p?M&uAk~Yd{6+!5!5*(KwkW_tXK$WYJCC60YXKpa4ye48qstwlm5Bz~+56SK zNqcErClq?(t~=2wAXLViMCu@kxi(>-X@(qay99Te%NVS?wbXe_9%44WvBG9WqsS*Z zN{9?Xku{=*MKeB5j>%>-Iy{JQEF0!bo_bwmr~|A62d^^1RW>_JX9B3V%k6WZJ$*5) zOk{zwRBo8a6_y!Ldd{Qj{z7Hz?T4Fltq1$QIaP6w-FGA|e^ms(fdu3(RyhxSh5N;= zdW-nj4cR^Xa27YSg~lGFUdGLWuU6vj{dD-^drqt@MH1*L75h$o|8EP)d&%4lg!TQq zLBbp=+O!cs8bc4ttTfi`QX)M5yn8U9_IdIs9uou84|@LebE+6la3NEI7%^o%(FRLS zzzuqM8;D`o3F+tVP8S)6?jgi9IQH$a8h}u|X0GA<1%Gg{L2x0x?Es!YU98oM_IM!u za%5UnXv~UQznBX_>CbAMn^4MQYFZ1R@jad})%BVjV|>|M*u)NVarlMSz*?)#a;T8^ zyRyV>B#}DX%Wqh*dZE6V`>y;q3xwOj#JWU^9#8PHoa1)A{dIjYe&~1^13MGyv`B5Llak}&>jdS{fi1~2`-pFu zYP06bo$I${v-nA%%5fn-VQyqwGeA(7vMBr?!>o|PI>Y;(B#SUtp8UG1 z7z$?M>Z6Tby9G-MZ49DR>hh)dj@VrAeh-nNl+@0oM!=peUOOILWjwhCbP@u_^^)^O z+wnNN_Y9kr8iXutUho3T1*8RJcp?{t5*VO`p457|M-a1PKJqFjzK(kiZkC~Cub=xD z#S_QBgc>b`b0R119{JXO=K?Cg34BaO{VU%&{ozT=6Pql2sL)p8)9TMji2;vt84x%k z{B>@v6|-$Air~}YWTAZUsXO@v}kJn;raNS0I#s(x11PR`rFf^hcUpH}o;(1~Lf zQrpcE0jvCE`q@m28?)X5#F2-2p%&^w%{bYsD`VXn#A3BJWTi4VW7O>lw2Ao^q@}^7 zNY2X~-6I+75j5{H=XnsK2t<1kJQ+&2h|FzpDX+~+f~~3_sh=jbM`aw?GO^Hkz>ug% zF3k(G>cS(!l(SU|SZg3znK#nhG*q7k@x~WFcsAyZu$<;W?HdJr$Z;b#@&W|6M$RxC z;cOuPN720pGWGv|06)7i!wkbP+T3rs-!HW>_uE`@Db?KPQXv&mZF84~w;B5j0UPtmf|Rj~W$mUQkP$ z^V9$*jFg}689znL2t3`eRWB!;3c+roHeVQvL4lAx%O?|Ffe5x;bK{QI9?hn4^MObI z%^wJLWjNeng@xe7ePeXzAfL&aTre$oq;7B^n7V!a^>g(eP5cWxLt=sDW;{cBk^(zy zkmt(;@n`ZtnzhzEG${}>qAqIO`6BPD&aZ_x;-G05Uw?6QauuD8 zfvi7>2fCE(o>jgxY_j;Yb^2sk&q(&!n7$IEYxB%Kp0;52z$7F;K#D$lo!ukzLHEPo zi>9*D8P)zAiJ+;zUX~UG^yw>taWXLAovi^+K?04opo6#IFL-U1gq~LzXjDT_|Am zC~u0mP882&ll0(#Dxel*i?>ANA$Eo8o;IEjh0=7eC#3m{FyV08X}%9PabbExvyS_G z4&H&c)r#!JwIBn5_gc5|nDzX?7^@K;DfSyTTIGY8Q5Z|DX+M6l) zf1!lOE7z-@cSFL1Re;0t6kR2~6_LppYVLD-Zn%(*M8iJx%~4`@5EYWTL4}SK%u62W ztuijXo5?&=BXfU0=rENa4G~}t5~hOI0JTAj1{d?ePx|tVJC;w7Y~T?t1wRisk!{Hi0?nSn51pIb9>i{(Yx#)8=484B_$yh`}U= z9Aha~TRW9tEvbxp8p}tNP_yA-y9{zH1a^WZ)YDxubf5KudEBHby z2r;aYOip|Bu&NNWhQ@v=N;9`yEI;Wqg#`{_Q_TJNjQhd$>s10V1XnFuxGvJ2t4lvL z2{zAx*g#PL4|v+W)r3lyw)LNnnR!AZ6jzLBO?nS5&l8w*rDLavEV^-ZWzj*&YAPJR zF$Si{+{$`)2poh%1Zhnbo$Z+UzH5ICI)q70eOh4cOS2dBw>xL$i=STFeJgWL`G(c5 z*cIL5hkG)T(6=m!GyUu#=}LmR<%{@ksQKO)h(({qv;J9LfzW{0$)xUa7#x_^rP?T# z(+YJ7+8-PqDf4xPTyO3XOOEyXkqEnLdQ1;>(=!bY;jknE=u+M%cy5}C8biU7k)UoZ zzbI>b3It!yUrEhW*~$IfovN{eJ32dR2OTen*F03$648L9nLJr;V{PQH+=r3qxk^SW+(^i!50z`{@ zvK|pKY+*PKCeQnK2*zPqssTy>6>PQ7NJI0SE*mq;!8^llq~8M=Olrw8$SH0N*SB$E zFf_p0^;5~aO-dMAP`9u%%p1<+gPAS(kWzdj|nx#vri*lDyyezmInyB&kmHs zl#x~Egq_cor-dcYe0Q+_xQ}UYNNv`oZx7g>0S)PK_pKEtPxGn0w8s&o@UPt$_-QCW z94f6ZcIZmm9CCIN!{j$)psa)-;%d|25CTeVP|wnzvIsGE7*b6b01FLUC%yjcJvvwI z;f1hsrly1~s#NV)Xy_6^zpv}$s2*b5GersVV~G2PjBQ<-N`n*Q_W(hZrtLRn!>0M{ z+?q*z*TjMI84rAYbX0l7)ILwlRH`+NY9vW7pf5`UdxbRVjq^?SXsF0j_8;g02 ztR6&tav{u{z(=DAaCo-rvO17rNa4A@kW;lFL3F04u(0cE%6tMeLyi`L^SK@kwb7!v zY&v4Vv`cB}+VeI^pO+PRBOObih>JxQF&9l*Z-;Eyg7ygJ%g%i3WvS0Y%d@x2i&`S# z`DcAZl5s(Y2ZmI2=^LMxF=~wUGomBBX-C6LU~lEghIk;BrR9DHb)D%JY>f!~lKZ?mC##U_NuOay~a1XsP0 zI+YJ~qhjY8^CMV7mN@C~6_%=FQ5BZr1aDxDD}MGCn+gFM-cjaFJ%p9tw@{&0ehZn! zDfP!wUd0lwUSZUi6ZFs_HoA0;eKvtbY&1JWY8?TQY(?^zK@oOGVzaY`<(>b4)(J%2 zRFd_B$uh8W4K=Kdi`7IV4r{I#t!xDnu|ja>z$Jehvtk?bv9a`Gs5xMxh*D(&H0NKM zpj0Qm`Rt2!EpwSe%A;yynko|$^&=5tT z;X`}A6~A_7z-QPRA9i1Ebm_g1+FE*K#Y14}6JjJ0CQ;sSP}5<^q!{9n0}WdINd8mV zqU5z}Ds{>SYfcb6FYrF{(X&96g4!_XGLj6IMYR)Z;1j3y8>0=$^)Jim+L%oaI=>|b{(bI2&Jid-eHJ@1YQ?Z@&6XD} zT5WilB?%Hw82E3H*zq#*T-m+F*LWYStA7M49-BGITs(ph4>%J9`&?BPL>YBf`%a5q{=-Gv{dk zke(r9_eg4Uzl!i4LF_jaYsk>B9J(pE+6b18yc`X+Y(4b}Q=s2|xRt9B zS*L%;xPtI$KH}Hgc`%TYFo_sDJaK53o@q4zEj8 zbUe$-Zzwo^C2W@FLbC}WjvlH8U%rR~at11)Hh&HzG(I}oiqWugTbh><_Ot?{olk@i zf=DwGzOGdM&dJ#lChYw&HJNmyH%FTjIE5pK?g5$*1YROfJ#ohSr}U^(X}%L2bnUhg=zj{b)HRri4(}$}*(#q-Tufe0#+Q`HQz9(`cHJ>lJCLaX7o0p4zAg%}B=E5T@kQH0TsvbCSJ_xa_cegaJ7M$jCZdYJPg-Y`P}IpeYe*n&7SXaI9&kKx178;ILl&h?2Q5?9~Cx&t_Q_ zL)_Q|ivqU(eb|jF3>|dJQsSEFyR_N>khl_21Wgp>@?uP!E$?i!r@!buJ4S={U#~yMsZIa3zA|5 zeY~J_uRE|CG7>|OmS9O_Hopa7WvC48j*3(>HA0V#Ig|IIhNzQu0{XQ8C1R4D(V6fz z|Az3ZBc>mr>Vv5^J4SLvG!{(N-j)*xQyVlLgBaux9rRg;l2eXqzbw-qv6f&dHm_f( z`qfh3*B){y3$q#cCdE8C#b^_(?ouf(Gv)#cZ5L0Kn(VAn(<6F+dzmZrGQ`dPxSjp- z{Ou=kdKjg_0HWeP5w*V#X})OqkHc$PdLBT_#wJBv7&fKa!U|xZ=-2IarqR*E29~4d zf_?jqm$Qq_5uqf7#PfE*&I2w#Qp7Bqglf`0YJIb1NEJ$Sh;tO{=n8cCx9QV`(-~$T z%V8PESWW{u8XHk|mbMxfEnFU)$z(GOTVdGLioAk8qh#+J1~i+~RVuu{on4R&Q{#cN z4`1sDL5L()U~S8B9Q8`Ob$|g1z-8gpb{ruHT-SjlqSG`&vPp@(KkR;hFRs~{&5z&^mW|X(A zXDAl3a5+EVG6-^a$Y7Z$R!&PiA)|5BY%?)cYY24spJrl7wD0CP=f7-!3WC35Igs09 zMY{~50alc6S60mr%_FUP)my~++YbR~2OGWJ5kfglWfR7k{~M&lceTr-0}KVxAp(+y z2^|zG@OCypVdv4TvfcyUQ1Uw6HdjJg$s@jrw}UT1gs#*(iwj@J$p{orJxL0< zE7lvyU10WK`t&?EivJwvP5jzs=y$6wNpAt15WHi$F8DG!!EFIB1BXpT*0m!x=F{3mn$ZR>|;%m%o zMNQk)!2IH-e!$=kNrP~o*A@w6TU->^OR@KM+HGuX7#f8FE|{pJEu(Xdc9MOoPEyx3 zxEz+{blBiodQm$qSO~89oRfF1?^og7IGH-4-244EMHAXjev3`&j$m)N=-o3nxU2u) ze;%z#n~7dErW+AntymEoEqlxJMM!f%=)U-!{-rGtfc&PJsTnN^;Ep8pCZQi@(h{M0 z3Yp!Lc$v}tHSsVuKC?oIWSN`xG|2mVZ~uO?OG9bo3n%lF`sTLI-mx-wu~>jM*zR>9 zAX5O4r)_Gc1MoU5c-%7+i26&xKgc%Jya)cKdwAv;;Y>-kX2QjkL6tDbNIuQdsmiwR zjIfOJjU9Qsl+PAZZAuEvMyWfeIlRtoKp#yEEe~!GNH0FhVc{V!x@0B1_zby0w0zvf zV-6=8lo+aukkQWEH%r?PK)4K>`Uw%1Fh8RC%smA3hFg_|WUerXPm;i*^JBTX!Y_pS_t!){ z9i*qaoTP7lQ;(ZE%n@(yx#M~x+taH}biw`pX+_EX1Xy)>#oHOPLI{DIBV_@RN6`hm zIp8yCM)wmAtNGb@&0;dumgnZclbN99PubtlTs*UW4H5@UIJ91hwQ5=MI9mncL~KcTZM zCs-*aVYPl(0hLIz5qBZW{k5~M(~k^Mx*;nolD1lMd6px)<#cH0RHvE>cKg!)I2_4d z(QJ$<1i-(cpd~#WNsfvRcy?5=zo0|mCO=4;Hx-hpMMN>V5N$}yvnSc!(2@q#EGOyf zh8Jxh;8^D?66&M*a3=h><6V-nH4Bmy!|&>#C>P>UN<0;(15gx;qtPF9v;19xec1Gf zY!2j}UAM3syTax&W$uCT6w;cl-t*Pg4rM<@j}fkV?^3CMtEJ!)Gzv7nim2TFDzfPf zgq1*qG#~eNo6}*3dk=;$+O5J8sKV9ZE!ifTaOtg`bb$y>&excsjBHkPZAj1?_4R*; zn{zg#a~x-U;pCj`bz&{Q|I*d@6+zns5LCLE1;OarO`vIzb!h>lU&7?gf;3$T4Eruv zS@QHxmAb&~+a2sQ``79X7<>!Oe5W>#LZk7+D*~Egwa#CzY0YtMV;i6h&TiPK0#SR zcV->i36hqTpcZ{sollN7oS7Sl++I&*7dILyN4bXmBAL(hx{3b97gCY&Oz{vEf>D*! zWk6BMm)d02kyS+r1N*p2D%a|q zsOGoKg6D4L3yV{bUz^X`VhZJB=eSiOWxRZ@_d2qvxX_oQr?VS3(gO4<{+jMu} zTM}ZrY$d6Y0}+PpdIuFJ-z>#luPcaaUI%T*cM)#vOlp_;;FB>~8c7z!q~G;+I0wo5 zMF*~_4s0z1=-Gu31Q3>>?0Wi0qxEN|nL7SM9Ta$mjzIM>pD48tF8Srn-oc!gBgpJy z&+)xX7vK9}`w(VU5Q=1GRq~m!1{K{h^6Sbk?SB*5w5Z90T=rv<()Cm}ZwZAqploxL z1oFD<(?Bf7N7t>Pfv}}`Zm;Lj8@cQ5NBG)E>$P|Jae95iSF=PxY_YuQ>!YVSCKzd- zj`TYWmo3PB>m5IN_PnYt(*pXO|FPx9c&YMz=MOu6%kqfnZQBfPp8^Mz9gYJFs%gG%D8`eE^X}o0mdQ2j_t7p!>=b4tv5dZN* z$MIJSPM@dP(&8L)AW=1Q4VUk)*5q`%o|}7Q$(bw2)umwKuw5kfEDA}Ue#!p{J+SzOPev~QtPV!z+ErX@dCJaxdF z|9}?40pfr4BpY1ceTA8PdL=Y#+aVwI%xHl@nd?A6+GDMBfQ|PvW%{CLpzbJ`*Dkd^ zLM?vmEg13dXcqTvP)C&3j4EqV{y823XM!7QzdH$jt8?i=r9EWf7gopiB#~3mAwL4X zq(aa3sEl>Xe=3yx^b@1=Z@kW#$l;5rZgz7Yj0ltk#IE!2q2G6M1IBjW?5r%X+&Wa+ zl%v5cI4cuDL;q?3=Q#@tI^n%Rud;(h#z)&@C{wul{dJJ68&OG1^{ zc-o}*T2I6l3YT;Z$lopHVTh5VVc))IWNSDnnN5{M^Ztb#mhu<6j+UW88^I^eD znwm@F+%o1p9Wp{wQL>N7#m+x&Q^8D{pPQoztwPpVGP-qSG_{*sQ zCgmLl@K?K(l%34`DF(aF$S3X@NfYuaXN2AbGF=3*8sJ~#32nMHK4*-iwF(NGS{}0% zcY#0`@nGLJ`E|Tp5dg9oy|TR`ZAdhJ2m$fbzaw=2ZlXwdxULJNm=B!Nd{6T~lr@Hf zv37cmO9SR=-7z@KXqcUy=I7QgvUy6700C=47XGj+9z3V&F93CQ4MH(Rfpbo}nV@o3 zprx>e^mBPPyoLOp(Z@NPqi9l!N=5qjsogG_6+OLLy?5D@q+6}3U109aPPV{&t=pie zyg!;bJjh*$lthXjYHGc?w6RK2HTaQpzj0iXJz#!46~ItttMxj2!E#AVps$0_)F97* z`7fx&l=8_reE?By12m!@Hjbw}ADr^G@kMda$=+qwyXMjME9~xhI8M=I6(qCnBs^xe zjhBPN01oFxUQxhb)|cnRbA4br2avEv3W>l$@OVWQsBnG-$&>1nY|^pT7&ZCJbB_S%!o9D5`L-=9$qZg-MBU%Z;3_VE>T8YoR?u%Ym7nH$TNsk=zC3=<$c3++`!z3K=f63Z!(Z%fb?E#f_WqsA zo@KbwH$eaEY*%!=;gq%BCjJPx=lf4c>JC1EU{`B>|71y205|u&F#|y2M7E9W9lF=P z4VIvoku^VF_9>heRb6@jn~r(mrdh}T!=PtJxT-&AVrfglI3@q@lt%xm+=nzdu5b_d zye1m_-&JH*w)}l3tT2zyKuXdNjeq7{IUqvbZD`9& z)F-qxih@~k3V{>6JL?U#cLiS)%`|Wif1c3uL6Dj>>&k zl+6W-ZF05I$IOje*LxHOyC&P&RjeN_$(i!rb&$7v8qxP=kd)|a-Ejx*c*-$F^C`h+ zQ%A9P0Jul+8#Qlxg(JhE7*`5tl!iWqSM&osUcEdqRu6`E7`KW;X|@K@ggx{1Az|&)hs;l4S^n`G(8j0PMwgkLK6d~B&O>O3RHu9D_S-ia#n)pn*uG;v9LmiAE zU~;iET^{&>;3$~?r&vf51E>U%N7{1F1Fe!BrC4B$i=x0!Fff^Y=2uQs;F`s)v+g%j zfaOxd7z*a^$C~m+J4J?c5~oCXZ5`SxPcnkY#HO7OSD3OnBO#4f!O-tzhP{v{nN3;5${7|uRji@yIMceA4{>JeY| zZK3?PsRjZBr4On#7MYsKpd;H*&Zu;C^q0v75ERbIDJOUv4?#PK7w>s=7BofUhX0+! zcqpv8PUeH+rKt+-)LXT7)H-Z3nuGp60sVC-nXZRoNnPE|d=!MGaxz*ACN3IBt+-zx z`3w@~bmlOFXhwzWwt#4aB%T!+)lkJc~OCXKMARF$T(j{fbt%p<4?+F;CMaH53JYsU96Y z7k~Uf6bo=o>)qocQ!X0~7Au%(RJ6f+jgMaYRi${MOR=hc#9t@0Aj8XWhC!B*OVZfg z=byj}@I5G5BsL5rWK2wc_pa6dOgNM0_h`XUE*`eIZj)j2<-LB6p)mx}aRzjXo_FXR zuW-xVfG-OxsZ-o1>N2EvF)@6x%?v##lh**p{F1%4mnS$~#|52-28q8e!7WALcB2Y5 zK7H8yE}hqK%Nzs!JGtwv=m#k=3H{Khs|)>_2XYXiHHT=W*RJPV%n7WLXzRVg9tO0YAU?EoR_ppgmPbRx}>%SY)L0!%H25mhGNh1@o zjF=Ny6Cj_{Wh4!nq|nDaOP%r9wF(fx|87`qT*O3QgMj!F9*ruZAL|Dxg}r#@<(gR(V19PWu%F}QCxOS==(6y^AvQ<4 zM~)_>dPG7@u#0#G0M%EdPZ06ek~@*;M=3K;C+yk`2chK@Ar9{8X8_4$Mu--0LG7&f zk#84H*J(YW*`+)(Qc^fS+g$YLrwI>+GFuh-@ZYsK=m2z8;?5uBU|MiPFt$DAn6B{= z3EAVy3UCAslwCAVbWJrBt5^|3UxDwwn&K(5Ljp>%ix9mT=d&S5p_3(rX$2 z40!CwXnrB_8b~Oo9F;tUOsI3Q{dIDGpS#xj=^e+Ym8HEgGzsSEAY@%DmqaSfNw2Xxr+WUMRC2PYJft~VO$ z!;RG6=HC13!W}7eeB*%%|)8qc5CW(su$L1t4UNR1?KMQS>Fu? zEKNhJC@&P&j@$oS(i@}08jc@*=lZn&;5+(%V(j$a02pa3SC!X%`N*&T_P_u0e&&Dw z<8lGMatS+CfAni-s6si;Ng%BIg&UuBGt*7nrx#}jEK`UX)Jwglv!kl@E@6$O9yojP?gm0$WSB6 zOb@Gt|WISR!5)()=z&!g6zgk03H`bUU-Xv9yJ) z=a>TrcwFJPY~zjYdZg(9m0`yh^fo<3W8hR@W55E9j5_@A7$9-RbgWtaQOPd{THbV| z)Ti-TnXGB=mn(oJR2qoli^*l(P*k<2V|{#hL~2vU?N0AcUsq#!N7u^=MmbB5rNASkiqneS1%x83O) zFV9N>LIpvE!4fMAlmB03r(8K>v;MEUv9L z1I8<(4@jQA?VG-m2Mma}qGK6%SRHzIZPximfBm%Sy#V5y(=I|r5rtWwN&89IoMD>E z&hNvW=M$ebPGMZ-$X~+95v#8ti{)4QW~M%k*cUCVu;B)r29arl%FIO#bQnI=+y08^ zdaRY>ZkumZB5Ho@)VL!fm~v60bkj~@#$h^hUst=$?>5#J2NxfNn$8$CnD|KZPpn_a zprbi}6~UtgKtFAtWu3leMnfFyt?2Bap_7Yl+3bjF*&5nPRidh-Dq*k~Iga>+Sl1-2 zPzhU92uS{)*Z-EnRl7}RHSX+lB;r9CU>Zv+`UNy@eFM!GK$Hk%EWj%qM)fPd=1{d} zX7ftB9}BBTA(O~;++{;E;kRdUz0VhH=h!`h{}@;1lAkHkJgX2&fkIS=^?!=@n%7ZK z?bLegA>}f$yP0`7ILF3JOCf){bJ*zzGb30_A8BhiVP2^L7e-ra{a6>ZF?0$}j8_!q z%h?oJ>%u*@cBI7$K>>-~w0}b)daQnqJ8>z`aJ6&R02@G1cWvbV#_;Pz&#J@V)`|)O z4b2hIibXZ+o%Y@AOZ}u`EBrBcl7I0z!#aQ07J`Jy5Pf8M1 z(;(Bm%#|U&sK)O0ASInyYy1Wibj+K9I{AA8i4d>`W#g=w((EjFtdP18L_#JcBizP2 z-&l)}3+xz@vu>?9@Ct7b_OYVC()s*9lx_DCa=P@?+?J~W8)DdBXZSi& zZ{RG^EE4ieZQ<#!ANOdXUV3l#>?}On@Tz8wxdjh!Eid7DS5r5F_10a5dX(b!5}-0l zNnTAIfN(B`U*@bAjemXHp7?xCM(TN9LXWq^c5k6t_`bT_L6o%O zfPJ6P!+IK~Sm{SN;*MAOpm zmWpnCB#F?!1k{J6HR%*a%I~KaXnLl6Csj<VSa&hY_-~C`;|p~=?J@Be;fkB4 zvVzqT9y7;etE3T|MaKMlIm{R8hYqF%~HPTrU$~x-w$6byyg%rbm5mTpC21SvgW03DT`jv?S@@#4ko?c`@{dN5_9*~<-VE|6n~l& z#;Jh~t2FulU{8(CUr36vtbJB3xl0V!{*7+Jji@Kb=9Ha;zH7Pd@injXcy-5`#B9qH zWE%lS#V`*qewT9rv|kcYo4^GZ=9QhfBP;3uGlKPCtUcx7Q~5B+5agZswTR~;y-JmFf|+u z!wGBFUHP`+L2j^y#`5o?F4e9(YVMo)gp-7J5kGeY&iCj&{AQ~G7yZISxDaHqtN<(g zC85Qj#|pw$q~x0yylmO8djW>CX)8 zkKZuT_E66KDs+v9Krqu|Q><&|&~q@rv;cZJ%u#gh`V~KQ*+5cHpl~gTP-_`yNV7-=C*sy)Xc5T;S(Pa#@CaE-bLfF3)Q#F+_#V5tL&G zgA88DUhvTT`yzm3RvNn2`jLe0{*LP_$6IFX|}aQ48L4i(Unle3Dpxn34)Jap;Z8+ep62StY687 zO27@tZxrEM1Xo|S(vd}f!Chf017lBuykQYO;9}GZ!IqIzgB|j<- zX|DLFmx3&~m&~Bd;HdJ##cu22e*qU=AzTGB*i7o_x+Ik;XtpmC;IDm_Pbg>rFu&BylcV1Cm!vB%9n`zuIGNm?!~@$z*CjbYVng4Z_B_ht z8vG<@;R->r*}DR_Se2*X{F_X~+w(3Ll**zF>(4(^ekn#I6K_~ONT-Vm1xgfA4KEiB zndfrUuf;n3N7A_YDEXTm{<>|AFkKkONkRY85kaLtNI*OOsJmq&UAfB>-30dQ4oPO3 z)eURA%_Hm6R2*X>IjbxpVU)!<2Baw~O(h(PJgD$v_@Rp0H|e2a2$x)41?$2#REFev(-RF}MK%g9 z<52oG*?yU74L4qiLU#pjmxFFG;lTu*DR1CrA^#%<`Bwt1yg=7> z3y+$p88WqZT9mgvkdOhF`)oRlmSOTw*p{wPWdXm-2biyJiLe(hxgz(l2)P2lM7Yda zox4n)bPF|=^iJsRU+Lm~B7u^;cvN3ETi{LwKW|MXmnry(FYwIswh#rW3dGS|dQ;TL zoA-#MgG&XpH@$iPHRf#`GJS5h)F--uJ9$=AC=Lc>Q{w-_cl|s@>m&O#=%vrBp$7d+ zXN{5N&M1jp%9A~z)UW@~|J_HWh>bmf{H$oXFSZ?{BK;5liBafQL00iZww^}Ak;tfT z1VlCy!DC@#bk)A{qD$6Q`Bh@Y__#&1%wFGJp9Rb_HawW7`oIntBIl-wsX99VVxi!- z^^d^{QUf$!{ul&@Es5PlHZ4h*5b141k!MT84#NBX3#cVf|dlhbPT>eF=YJP z;QECjhr4J(r``Zr=)o{>XtVLe0N$2}knx8a`f4N`)CsH{`zz*Ba$H-{Wzg0jvq({j z!}2`6Aq8g&+c69cvm-Y8+WjCki^j+XS}Hk~-!SAp?LTZ~N_NUO;MLehy3kL@X>4X*(2Vf9ffu9jI6OAl_s01ItTTIx0nL+ zQs@7%9&QYhs2l?QS=9+9*w~JWePR^}F@-ra;apn99WGhq6HcVBb>jB*C+5ox$XB2* zQf6xQf9nIsu91&dM~s*+Pfqva(|$}U%{v?XCly2Ib6tV0&K}aFhcBiA`U?Mh{a9?F z1LH#Rl3+DLiu1O->&}N)xdkiD#Av2}6=>LP9*gha4QL;;sOOs(N6gh~qO)WVC z0|iPBnS9~k>CxoL9cvNJE?kQSRCxeG1W5M~sH_6|`YW<(0_rU(wM9TQr8-Mg>%&)+ zV>&Rs-V*?g_q$o@3TBd!++h)BtdhrcvPtoTUM0#}vAduTX#Bk>G7k|hp5r@H=M$I) zkna!Y5QT{%n@r&uf}rFje)8@$=#Q5wTrxB`hCi2pxK9>Z0tyeWVD8~04Ho8OzgL_<2?+=)3QX4cc2&d#nJOUia)5qYKl^?PNMEnF#lQu z1iI#SuDnlSOV0rKIn^$&aB?o=Zd?!0w7X)P?sMeq?1Nc|>W^jZO4Jh0Bat92`m^Od z0dXk?7UAscT>`z+_%N5e<#QQEE`VaAFHU~K@ayS6tQB0D;xzp2HP_%J;2%?8_m*Bi z0V6=<@FM?9^&oNIwWF$ou)vG%BinbXPz0h@A6eD1ZZP=Ksh#6y@Is{I4QRKnTH>yV z7=l!NxFbBrB-|{3jFAHK8gx4_WES%Mi6PCxNmHXH-T`u#qKBpUoUrxq!3*DEYOk$G z_G&4{hrCFJ$JKuVleF<~Ps9j~LHhP2=q|E5hX3rx zJ{1=9N+V)M7kS)Fbdx4LqAQromK5o5cd8X2=0Se?ZIg9gHGR$~FH^8}o0<#6bht^6 z=qiYCaoS(6WNNvI#;r`X-xVGg4btZJ)|&}_d8--zJV4UD^j&svm6y=eDnAcY9;ai( zulH%?t<`00AHTiRQ^@b-0b1<%xz;aA6~SyU6?xG7XF))^qedlr_w1D^R|E~}m^6)3cU$BdtB5^(HTxkNxbqX{d@ zWb9|(yQxIE#70XKm<)TA@xVVGr@4pCe?*3ilDBW4mF@z*=Ch76U@$R4IeEo8U6?C} z&@yGOkWx{?NJ|HgS}QPzz^kzYcol&^xBu990W_&ZiBF;p3A&25H@FPIj|?KD#a%*R zakeyhdYO!JkRg0_)3ed_=8=R4TfN%P+ z4EWpTm0`Nu_n6eZ9V>I@#fCdVKsNe=!4ozD|Z zWCF{a?|-=5FRk6k1mz=n^RvoXJ1URYB+eu|H_Io{3?_N#S5c&fz|HS48m#9s^G1>e zw1Xt>PSUfL@D1s-O{erZ=yYk_QEO??9sD|)`pwg!F}uLisSa~3hpN)Qr~eI)JL6I` zrXadHR$sCN39P;*q{*LpO9tewh`C~Try7A6qw%gTq@T6v9oM+yAaf>O&#m(LuS;cnJ!ZX1c1h?j~;eKd6Ja1+iZ3w>MNHs>yP#^>K?n*ctlJM{a!cJdb}98 zLKCXNa}*^<@tj_M#!74LzIO{w?Q$zn{w!0@z0UMVk@=@dQ%p5!kY5R9o%UWic{RXI2yg$P@Q6ovJAdW7?z4}tKgpNB5U;_Q zhIytG;4f!BDbokP`;bD5XPW{~=8}{}4)=uBK9{$({7qKw73dJ5`RbAuwWH^QkX2a~ z-+iQd*uma`@7aZ)=;!b5MbMe)PG(2K`u?E<@w-sGoa-LiDdy|++$g=IVO#`IncMP= z`&aQczi{$^di2F?38HH4eM6NA?e72^_9Nlh-G3$6G=380IYqLtYj~0_wI%vmag6S`Swki4Iwl=1cr3cE)hWK!Ud-V$KJo+=O|?h*c6=4IaZR83M4eg`+Ak zn!8IAJ~5HW7NeqX%tMeG2iaE1crnv4VXl@<$gF?EN~tD_rAGiwgzCR|Byn>?`j>Qy z#!8u)Vk+-dL=P9EYxLfJnTTg=r#oViAX?o44D7@ zljYt(cGS}~Yzw*gqUt^LqnG5^fHZ8%0VNb{N@)@zHGFLQL=Tucq+@~#@{%NHMRh9Nl!D& zZA1K{z^%K}MV^57SLr*KPd;)uwup>O*is*GpdW<1Cr|jkr=9VJa#ENVA6gco@p50b>&_*3 zE&BGttd=NJ{7#-r2bC~Odl(P`X9_-y$pS<}@yDoxqOMAKqmQ|QsZ=7u+aHd9s-8|N z%TPuBPM2RO_Y;HDn)uhEzDJ2~`x&;xDQpf1- zRA6)?r2?Xk4iN!S0TD-tfT)1z4;AI!ea`(y+|PE-o_)8oYu9ys-mkZf0{j4;;>MWA z??CDvmaGu%=-VnOQRu&8P+rf?ALpm>c4clU;Y-%l^I+>6t5KEECoWe5=@fMzXH`+* zoG`lYOm+^7o}nk7ER4r;FwGdI{Hw3-w*Rc%j#w)GfG0mHabtSJMo?lmihMB}Tg)m@cKP`;F6-h zHG=}~I``4qyjGP>HT8`V|LPvyH=IO^Mk9XFF`CdPGDOu3Yfw&S*_T0l$5Ru~U3ef! z>8Q;rKR4qNb5-uG@5l#AUUxE%vMbbWa_+i=28B8>(Q9kM41X_R>mcvA%nPo(_f^6D zoX7CZ+W{~rs6{pBXLvj$XDizDW_(4zbG%6Qd2T)Iqr_y)+_!t5x-Ih(;{5PX-ze*~ z9z~N^4|cVJ{|xIY?qO!ts)XTPZ?-v7fj$z3w*ERxB++KKI`{&hyDNCbC3ETW zqW}KfTcsTD;v37??#tsxWn#M8=1RRPFGU}_(K-W)4}WO`=nFfNk0zzDX1qCHX>CiM zh;shW5s!l!V3fMryt#06hr3*Z-O}5hOACx2rVLnx7Z?TOx7rroCn3I|3CgR9H#bc8 z#qXnD`D?F>k3z4@7$VfJZ+n&r#0|Tpif`H|m8S-G)MGw`KmQ%Q8kR#!^oTW_DxxF5 z&%gf>FKBHYY*!bf7Qc-QsW>~ek}kS-@4Qy~%HGTP`0H6;G0eaAChz>KnfhM!NhQ%x zx2Xn#Q%w*Tr^ZUZt4FX5c79h!u#gL*Q?|NuUoazy=-fL5qRg<8{%09ddgdK9VW2Ao z9-q1W8x|Lrx|c{YC~SJY$dzW0D7>Hc5|^ly-t}lv_a%1*4xu3G4Gg!TLZ%o?$`n~Q z3Ptn@0+K2633T8?n#!rF)91tAc`~-t2&X~m>aOfvNYDLxoP?dpaz)^Nw3t%Tip!~snY3V~Y(@9`* zda)uNrm6LMX*bn4XHg2#>Y3+^>2fd16gYTV{hhUR&(z`qQb{w_Rwy>3W<%b)BV#1V zBrI*$M!{VX#x^^|-9Mv_OXD7fT;*za|NW8CeU4^gp(=plbs}V1jlqZBdTR<3L;`M; zC(o}&ARCl&U@AQdpJ24p)EP;S4QMd#FSx4C38=5MB_z0#iV%zKNT57;yRgG{Ujk^P}$QcRKFA6;K* zTm!@s+AjWrFgRj>k#?1(+lEJB%1u%)C2P4*d?RS&b7tSQqq~Ny;J;iE{{2ibiwm5$)l2|kn9pQPS|0x z#jM^j8t_}x*2%Bd+orF^5v)k5HD2&>Fl{K6eB+`G0cdGlI3AdS@j#|Ao*DY7Lu$An zS1#e@7JRird|^rYMlWssaA`yy#|Kol;tXSK`#kK@9RI$MS50?VS}xcD0cFp*VtKa) zdl4XMJCv0fbmwShOQhXHM&;3$hw!gY0U>F*E`UIi4RsbUNs|k5fdCexYL0T$MgS_q zCq9gIJaI9DwqB7q8Ex!(1bJwQek&%k4+q#` z7l~-Wzsud*=Eeq)0;Z*UgM=QZw7!o$BZ`|E)b!4yyGW@>^L0JjP)W_@dm}g*6T`}f zm3X5%D6gjsZ~PNFh5=4siXJ?FNnkUJi}ljb2)L*C|D1{*y^Abfn|`0~$tK){wv?M*yLs^euI=r!HH#bXohl_J(z-IsFf>LFiW7WiQ4gdY z`dRGncE+q$D~z;{(WfkbbTcPHrlIdwLS=4<5Ihgv*46DEOwkvk2HIXcJ9Xy$5r{wx zWYr9gDri`(_^$jrVhA~f^Wclhwb=rH!L{}0b{J+3`WsHE{?iJD(Bf;}z|IB@C(r=p z7&sA)1@lmlOf?`5bQW&k{`w_%@bSYydHHsJWbz4k-Im4(M5nW-4CJvtc|doChJapX zr@Jkx(_Q^keyy(@DbrFQ+imWZ{v`MGo#z+9uBi)}e8~H=iLqsLFoOF`Hs|L6d`0$J z^h)!=R4dcN4fH>o$9#O;qW9PhC-E4MIz`<5QFjr6+4B6bl&MWSoQQvL3S}vu5Fgn{XI8)VzO3cYDSvdPK9K*u4UL z27YgaGBf=_Fdfj9^wD=t3LANqNNlF(Il~bzf8xL)`bpE8;0;td5|`+`SY;hBO5YFp zDO7${w!D{=8YcntoMbm4mT7e=aw!DuufB23qI9n)sh~GeLV=b%8AXHoWx+dV^t#Zp ztt$%j$v0R9HAP%cxq!yP~5a+#}e$6L`EA;>m zj&fd`F3i{}Ge698sKn>|lf$3KYWDZ`^Tn5ofq@kBOLSsrL%3~7l6u8wH@OdGMKXP1 z2)(K1->gZe^o(6F=MbiwnM|>HSzy%R?ZUixt#B3z&!4{&dOaH}fg40M06 ztjMO${}6o{OaY?g0{HId|CPTc{5Q2NHlUO4m=+6&srf!GbD}7>^v*wgRv@W4zr=5u{g5yb;8u5vUZ<(v!VBYBl}D(( zeF*Obg8Sv~c?$1Nbk%tzJsrNJ*o1K-?H9E*dEQ=J&tR);Xd2ke0fIA#M@gS^Xmr%H zt21h309LpwL+Vk`Bjw54+_#bs$^$p&-8W+zdEz;gR`e$?$I$%kCl+EWZ64dH)nw@1 zf|ZH=ck@=d#CrN{_!r4XIAXIQddkj(a zljX9)xIX-yzOMc33#81fZRBf96~7zzQ3_{{0+BwW_WQxI^F-Pc`2jH28TH%P!dpQ2 zIJ$&l)f|O*`vFIHervPT_(VHasq(Je)0{rqjra!rFy_w$xhc}LRixjcX)5&lRfZ4i zKX((x)`OU?nVZiM5KU1!jNRNY{bJT=3$M$;PH}?=3n3<Mtk+u-xHI?uC*(_>mle!Vv~`9550IO~0{*oU-f!S#LcylRddlUqKDixwVt0?*U1 zAzM6&{Rx-GP!5I0(pb1zY@B5w03+oC_XlcPu(vrr`hZ z?7v*X#k*=@Plw7Cn?|c~$t>(VO2P}3W{LlNR_*s*6>4O2beKO7NXP^%n=hrM;AjHR z_Z=LX8K3}cRgz;|{is?y?)(^qCG846xzhxo)l@kA*X}GM0bJtiy`@TCikiM0sUManc0Q+*u?Raq zQUW=&ev`{;L&;=k2&l7=Kxl}{@0Q34N9nH7D;j##oTCikMoFHDiGxq3sgj`Db+g`-$QgM-H)&4Rsy_L8q#XbqcKxwkCLJ_@Qt zB>S9`zcb}=YbiR~j{b$1-)G%gC7Z_FGlOIkkW&Uwu8#s7Uuc{1oc{L zuecwQk_~)O5=-yXnR@E^CBknv@PqbFy6~D!3`O;Mp~fyNQuJ(5+@pIqkgz7br^74+ z!0BxdAhSmkTDQ_tiY00JCT-Q(IfblEc3P!h#WuS*>B)1I2HRx}YS{oz{GCIJFSY-i z^)?0=JG`o}>M+}}N#Mv^g48Nv2$hEp?=HZUrYj~*D;i`%s z>Rf()gAAjlD}4rx$38sc4k+ARm!?Z9L3~J4LG@3j`>lxgj&Ken4~EhM@PqobM&bBt zbOV9cibp2}_qymFTQoH!a={L=(Q_CfJhF$onv-@B(EH&!qtzh8@7)uR(_-DB>O;WS;ciQ}N zTnxMUbYPbk11ndj8+-^2Q>6MF#b$w$HLj$x9nl7(i%EeqZszmnNnGR2W|ls~Fxr2k z`FEgoUOXUP+XI7KCV2u!^siSon4Vhgm?qXAd6UkAqhLe%WZhnyivq3>?v7C}+J~_nz&|yd8KH5!%CPj|n)8_;h z<>30RTVf;5!P-dA3IEQ+oZsz7?uLudAEa>XK#of$*+4DJM^m)jnm3mu?K_-O(zaIS(%Ay|<(F$)t66n92NNkagjd zU1P~3)`{Mv&ur=QvNU4N2Zq+7R0bX{*M#{?Ydc*8cQn=GdbsfdtB(OR^Za#_$==u0 z4wuVL6?5S1deN8aYuD$vOCzH*ASeBmu?IrcNas!mwwMWjB+7`cwlKT(l%7wrj#uM1 zv9T#(@5buGyA$}2Oa(Qs^nY(qE*?d}~!TI(%9MIn2M(@-o5{<%h)?^hqG+ZN^O*}jJbcGcB2WJ#2umHS*_ep$9BkTJR8Heu0 zN}7B6O%Rdo&#UH4ZX@j0PjAiM`X`cYGvL>9@dhf!{?+TH0teL(BoZQWLJ*5e(V^8g zdmiBGnS-|Gty!ECF?@KzLng@?9&I$F63BF+d54Q1oEmhBHcRGmxFvtJ;3{EZ<6T2@ zI80sI4{#AgUQ(9*fLdXv3|E~y0_Eq_yb7p7(edo3X%|IK3jN*Y-o9>@D4{ADY128OQ3?wr}?}^|Ao_9FDIKR-FoKHEHxWTtzRZz z0W$5wWA%hpGvZDAqvmVz6Lep?WZi^2+7-O_&AVQc^p`y?8KM0hKd1N^H!JwsPxU3-dV zWmocbSG#;!psM%A8UAaTvoMZ9_S7!W7kUAA2$VqXuKO zsrgaRg^GY&GDTwp~|Hex2m-3Axxpr_&hHh=pIGcf3q05pnIKPFXaz+ z&?~%*=Xr1NUShHC@+U}7DvA{k`;tYK(lCbF1|qm&=2$xxV_~zMdaL8?7hinB=Q(e#^FL9Kz(cmOf{?_u=qmo~v_@py?hVe53S} ze`!F``4+(vP&FGHSTrSVd2~3P9zw`q87vJ70Pj*>;-vHHyV=hIy&o+bYz{CAUVg>m z#RGQc-twfW<^zl^OKr_JFLRWf$gFIq(}PLumYpVxAV4C`_cJrDp5eo-Cl_I3^oJ{n z_9MK~RWJ21=}HgYnI^b|L~|K6L-Onaj}fS&JIU{?%)}2UaDa9%XMgxr|AvFkUoivpMo4ZFfMMG?3?JfObAjiF;CBF@5Dn~Q7|Gb zN8=tCPOVFa1%b54?7PIjc`lV=t+j(3tJ3>FP8WO;v`+~i(@#If+59gHdZyGc0T(ir zHLQ=}LcV?s?6mG(=U<-!NPH_Drl zkub-PtB%>!5Q@#mjZxA#P!{NTk599E#CEnSU0OQIp zJpuF06Ae^n5+gPZF?WCfKIWf>7=~i}tTuXdQQ% z0K@$I|1R~*QgGXi$7NC)9cj5bxLGu#12fRbYz&JZy_54%f0rnuO%@N(x1KgQ=gWV$ zv#Q)(&_uvJ>rB(mGB~A4zs169MNU-hLH;}0Y0s;{<&~tX)iv99B(b47gYtYWd1dO; zhL#QF(^xc5GAdkxVCuyQjrQ$5%$m`|5KC8%RRjOqVA;Wj(%)D*)TN%MVpjshT>k}^ zsk=kJlx9B(h;)~_ZYPRD?!}WmC;=vaC2K8a0u7qpf=FfKV~3)M;s z&||6AUb?vKdpD|!;?EOuaop%>N6PeW3Y%cC^GxEdy&^PA0#>B&9)m->;RM{|g%#1iS zF5L8^!P&EzgGY`oUZ#xp=Bx6{JvLW*ely+(9g3tGf=ln^rXSMCEh*XgWWr zc_s`QO_Z7zDwP;}*9GwWsPjER(%H}E<*f#?`I9=8-8j2EWvMYIGS`}n(GsNEhb&H_ zVT1eG|Do>S^q5ZA?EjlfH;1`0bAyF<6Mb3K@X$VAC2;pka8I>EjMe&t4Jzy17Ki+n zHrpr(BBey!I+(mxo0!Jef)}+UeZ3nT0ETm=V1}vBPX8=Ptj{pdxU;yu+1f`y;#+6I zT?O)m+p_#LsL-zSf;*A+0_XJ}S4@T~Q{u^0K~VwnIo~4gP*>xs`;_{KZHcI8{Is1_ zsAelZbUXdb!Wo4d#QC9kAH*@;c-fj~)8>0Wl0n7@24T~ixqV!|{pMnpNs=5cHg8d1 z&cJi{vM~5&ffixy!Ob^Fs9K11+bV?Xib>LT0_!EHwp>DMfPOzaz=%mmgDA2R2vc&P zk18y2Ly5s8J`McOqc5^VtXC5u5!0&3c*M~;` zURwxbN=x|anpTsjlEkh@HjC{y_e~%}LSkTR!z>rZoyy{PkooE|Q%Hs+==6rO4+BwYc1OHs_zj*;?IJJwiW?_D!vQ^J&CvZFr}eBbgT zBP-!WvoX_JhvQLlwuh=23taLXq^aAd%{O?%aEbknG`v z;O0^p+D4G@9BmejkJlut-{bwnx3G zIN#*bK|3CPP-yzoQ1H;Hs#)Bhme)e0a4l$dg_Z{e^T}pcW`@z)n1&_|J}s7s$uW7K zhEMXjXJGiKJ8h_i^OoRm=>-o3KkQL-bK)J$F#mz-r<^2>VIy1Hod+l1@j|=vsxIrs zPPjK+N#F<4*B3!lVM0ignU$b{e_VKLL?en-%f@CoUHhO2>sn>JACfYr$!C-HKJe_O z*`NeCD>iy}Lf#bS$)=aEZ~VEd5wm}5134+-J)+7p2HF6KCRQIEK^9b-!#lO8NZXG!k3LhYnXB95V<&@W&wuCt zCRQoD)efS4xL%>V{m*+z{g*5w97_s|(k9AVCxzoQNLAs{bvLok-$`n%vjIXEq<=#?8D1m+vzSL_%AUuhMo>9kL zam=7tdU-#0QveC@?6LTnkaIOzm1DKJTJ2Ed z4Y@2he);0Vv^XwHeS>v19Tuj0LC$jluuvD?xfc*%tf@Kti8EwBvQx4@o@FGnLa%@1 zDdPqW=n$y%&O$0bb5K^Q8}VWX$jrY>wI-5(I0JCIoDKQ@@LiYl&wpikrh`+Xw7Poz z;~#!o+(LH@%t+0XAr8n^YQ;O2#0<{BQWBh`g(1&v- zr<;<}tS%u7^#j7J<|HS|Z^OcI^LN1w_oL5J6%GqXlLMdO_`^=)w8aIjgm&9)_T-{S z+nGWtUQV9~kN#4(X6)Kr2?m;Xg|eY`0r!Z<E!{7{D>|uQ|5jO2LA~BZ#V04@;n#)&@fxKS(Q9*gB{6@?i4fq z7CCQpv0Gq73<8iSi$kde!1dY;rCB5&4?w})_i=NFSEhFodhQVeDD>|q1vF?nX_bd0 z`1g=pMTi^3R)u96pU1lkiGMY632q>)Fuy~TIq~r|a{IJRlKhhZ z8Qh~Z0+kF1Bl5-j%tp!a1DR|OO4?Hs#{t~=aaVy_W$8BRM*$TJysAxjf~Bb~YlWTs^mQIqa3td0*;U zbl{wZ2e=BvihQy^uv@HW@Z6~(H9lcW&qpyalP%`tIl3}=M(9zh>HRXs`s|)TW`Z|Y zhGoqx6S|=?SdmLy!GQDk#ae+f#I63uoqcSgzkVzN@ZS@g6S%?FLNVi~(f_pCHOd?I zE>?jS9aU}NzFS_YubCy##z<sL0bpJnZ)%~Y?fdF;_4#&l_rDeqX~#1LW+PEUU$)}9PXyC zB)9RIO>?hU3sY9h{$f(#gWPjO94Fgf5CvI{2Y^MNE&~T&xy40c6tfa%+)=$E6Uc-h z%c7s(CrB&;{lVkGSj;5}IE?_vNy2olXEsX+oDy0#^2q^mN{IN5Y8k z+^RD?pDXaQJO_w{0>{ccd4j8#3 zpeCOSCeNWGw1^iMjNKt*E`b@beic*J^~ZJ9*iR-LBYg&h*=-0CPmEX=ajqDgb_dfC zXrC5!SN=Hg*Su?(pAhA3IaoX9XKo4qioM4+^zkyAf?B#7_Co!SJXqKp)VbgG*M@n%<~!v`Aa!%FDS{ zbQpGL_R6Cn((=*Nmbo6*l%`$ta)KP3HXL~6^%dnP)U7DWRG!St;4K#60ZQ~qUJ6!@ zIM2_~B5{>38n5?5w-Os(pu4YIU7{IlvD&y~{H_&Q)-F#^|M4`Jlod8jP3=B#`B^8B zU`N(^)FU2N{@g=g1xmN;E1|v3&bl{!l>^Y=3}&+q6UE7BHgn1snh1?HuO>d#>r~2* zR_kQzQEj`?ab4q+Uvyh)z!!T3N#$+EzpX8{YT;Xguw?%Dsl*D8GZ$ioD14UQOm4Qo z?zCcCsDgSp8V(VC;DG0Q_znU2lCKWS+R8Esl=?WO42!Z?#L~6%upT>X-_1@4SWK{h zoe~~D@A1JlcDCG^uTkMhd({0ifObIgkTFF&yqk}8O0!cr^z3z_L;vTW2^_~cv*+3r zehMDf8udc`vVZKHkFcUoCOIee00!h9PWp1%t@~F$UZ+t#9savH_f`1Jz#s+z!Lmui z2wzi~r70|r*{Y2>0n6%U)F|jWv)zHA$`_j~T{C+9*mif*1h)Y#yukP3U{|50ev4`z zVSd)N9U)Iyln)Zo(n$oQ9PTDJOG zcxs8jb~Ff}JDpHl6cKo(g;`~2o0F-&W`vc)Hh>=cYR_&ar&9d`8g&)E?FVe!r51~N z%(I}U-K*8QV?3&#L7<`k(&7t3geZVDvzL8Csm=CFPbJpG3^daXwVrc$VZ-mm;^R;o z+WEDrW`qpW6k2gj|V@@8`Oe{V-`a;<;F@ACbgV@2@;>5I+?{^ zO(yvFbpoF-(ZsT~m47n~cLMUv<(D?UGq(iW7@1liI~+wDSbfLdev5E3|8YbO-{v!w zC2yKt1n}*z<=pj61nz&r-h+!xfI?6>p7~CI3U*es3qZX=;r^z58-4(RZ7K(plxzPhU7k z%j;OfP>7Han>O-?ixPj2Nv@}s>+8tbK@Bt6@R`!KP`#e*Innd&l;O|Ia)^O0y55u* zu`lVoTltYA&~5!t0esJ!gU!5`TJafMo0jyC4KH;1fM$erFrCE(U6%VbpZhV%QIo=l z^$ff@VPCyyza((X&WbBZ|G{;dM3nu%7*ZG(>c{%r))BZ&{&d9_)0r1 zhc2LA)g+Zc?ksN(+SMHhP>}!d91|OvDd42-L&0;<;+>h4$8dSHVm@*hvJ3|pJjNx+ zHus{%?6~TIsF4QxV94!rio5_v|G_cWTk|!Wh|+IYu&5P6$0^gMVKhK0C5?TO?}RbBv29pi%ozt0$ENFY?VgFaFh(5eWV6; zwI0qT=$qmK6!x9QxgtLnF$Y)?0)0K3pSr;pqmMeYc*6ZzS^X}1hu zknYX!3ug8;kkT*QCGA315oc_|zx|AbIz{1&V71DZSrj9=XAD{aXpPsVXevD`iELR< zH~=WO^{>6{8&=?G6=vH&>1|3p2k}CU69qPA9g!WW+u}f?JX$IfFo*IOdE5#W$vpFDoj?^qE{NWcV;`qL>3fM{mO^{PlI< zr8bEX`g^T&0+OR`k~aU&fn%Ww6Xu=~*C|ttx82WppgjDEkd|itf5QR=*9~R$L)A#? z2Q?y=059~_uM{Fjr>U0YRoUaTO)JzfkDCi0ssad@0FPiRtg1K1|TQMOjbf1lb|zMShd=okpTD$05rqLvbe^e z;9!GI1J1}U#j=knQv*u2J8h%$_orDc7)z^e%cu38!|>uH1&6xqCpmWJr#VGiY++F|ZhKKeBt}-B9rkf_Vn;acx;Xj1`CxLzQ|y0iU|zYXm0clc#u1bA zuZAisN%ftg4QB>7XKm*OyUzQ}pTB8)5`qdTo*QL5k9Y~_t7^((sz69F z;uelfcYIAyTxK_k*bAmLo;wW^p$QwT)&C$0B z%XDg1$^u)J;0hfydQ3WUgax5aAOfpMk08I-$J@=y1W)>(-r^ic5Q)TGR---oC|pPl z!StU8^NF8Yw?H1781|LWqfD>-Z*nA?JhIOv9Vhy>B+qT5t>~?546;&}uf05Mkqb7z z$!j6BTa}6y`1_Xq4a4~2smm1_BKN%w)vt#lfOu4h z>M`M?`h8eOk2Vgi39=%8X{z<+CXo#r;w6ScUq@0@AQ9LJr^{@c#?B1qjIwy-_uKk~ z0B{r(D|^KP+S!%kH<1u3nnl;^HQbfdh7H!psPVpWEEEZHzz`v)xS%dav%xPv8I422 z#7t$ybV9xc-C??IdekDjX^vr@9O|eP^}3xlDM0?>Aj*-OY9Mg#SNv(7#d6lR`pGPB zm|xy$kq$EfMl~Xn%vkL~TqwDq`3+vb8s-Ur_A9Z55$NH_fGm2~WRMIrW9rSW*O5bt zZ?QQ>H-kw8CVSAk{S9aG>1Dx1tCC$g9tKd?r`zVsbb_0qT)Rqk0h@-grOXW?O67hj zV6GfUG4E%&TB3K&SoB5o&n}K1Ln1J#np)Rilo{FQ<%IzMxz2#m&#QKlINXPDG!G{6_?)Wi}1+fdA2q}SDhx;@cb6T_{AYM~XdRRl)H3AbM%ItPI#@^*#kAB-#UywTo`hy8)*P8qcNQ>hn zz&1>lt5KbEv+%W$$U7|`$2Ef#Ve?)Zb2cJ(T32UbB^GDIt5a?wR%d!Qajx#(s-V7( z;C8N&A(2SrAVV3d%p*dN04+w5UH9Pg<0f=0x;nL%^nJy9b88qxX7c+aRsS3tK(=GN zn2vfkDnKfWNEDb4H*?Uw*fiR{0ODdxK;TGVg^C)rtJ|YH?{zAL*@IsFR|o8ly|VoK z5yW!E)@RjB@yb$yo(hk<(PQ_=b(x;uPfHB5F5(+^3`=?A{}H%l9UIy2C$oN!vaYRJE}%xTq$#{yZ;Z3{7)(Z7{Rn!qHx*YVBReA7pugzTl!Wo~ zx^ZO|D$L*6a5AGbx#uZG@wx={GP3&JQr)FDuZySD^iYb12STLweGi{s`6gtCjZBCI zsK7?tIg$r+$W%j4rsvg&hc5_d$Hf3>Ky_YVESpbL-?ACCp-Vh0Lq#7RT+vRHc5-b4 z2-DBfg$-iY0xpP40KhSdWJapezNp2{oY!>JxY%I9+Sv}LESnOgn^yl|Z1T-p(R8am zgEm{5WqOp4Y-uMs=i}7oxxrg>s-5n+>K}io5eQA|PvSv*crqG7ixP9DV2OV86}lN# ze_O%^sTQ!}@0+RZtvcA}n|dt}p)r9uE1fDfJ{^5M^==b~>|(-;_DN_~l_cyyBn zV2oUG3A=N_sZO~ne6IIib1MMqcvLBP;#y${C2y1}-&^_qUa%~`fH|J=cH@HXYY-{@ z*27!0jC3??wgOI_EyhfsRyC?NaBuj(3RB1IUUK9?*(X=4y>J{rXUdGR$q1L3Gy&1( z3ESR;nijqd zJ{65C*ZEju*$=7mDSZlr(F`X)!F5xqHeK?*7F8Dgf~&V;F1v07j35D)+Y05}vtK%xKN-{1oY0G==-2mn6^5O6-zF4Ax! zoK=$Q?FxBN~>>LzYm_XhyD8bdL=Tf!bx5A zN!anjw!1evUdf*ghc}qKy{M@5yD{R{P2T9Uzo~Z#u*J!D#KOO$+=(b->_!rsW57ma z>&ne5SH8=alo9{#O)TH0x!g}mDIXB8zEg$>D89DJKK@>PWRJQRWGH#da${b-$RTTz z2A`^1w{iNxwY%e!VCIJw_@=2!e_xB-`X=wvkT3RC zY#}l5;oi>O@Ck`eu^v6Ni@iFhHhpDvXhZ<`E@`SRgYS48 zMvG!6aQ$m8MUw~)zna3iX6)aaE;Bd)^x3%IyF%A(28(T&m(RVegVc-Dy*fZW#Wg9( zU)dX~<2N%J8l&d?1ric3Hb`7K*yG_UsjT|%W0zpbl6O^{SX%q_T^h-aipm(Nul?I4 z!B_j7^d3u@;ALS4ebW&Yb$y@S+-$y*GGik3=mLxe2Lhp4Y_)%$^;%0ZqLj%>W2>hU z!T%}n9$kMc>+>>KpQ`=nL0L&JdGB*{9fp6^q1*3v`R(|nXL<3L)RW=gJXJYZ|L4?J zj;HS5$7FOZ{W=R?@KvXZLj0vdj^BLd?l)Kca`MV1u8A~g*h|+OZ1x!;IPPLn>Gt-^ zN4IMkjEWBe$lOPXmJRwsXyehf+YIu3HyD2}F4GnNrn=oC=Y82NV2Xav^j?qq_wGxq zvVEH`a(G&sc+KBk-N65GC(UX5=X6$n&uRX?jrM$UJXrAjtn+PdZ~E{3_D6FXxoLV+ zF_**F4>X3FbY)d4W=g)iS^@i?blXfD;p&Y3`G}aZvh&T8Y1~aCwA}xY6-;1^Y&HpW z?%N8%?mJx!IB4y^tz1=&`Hp*&%#KgzQI9yaOz z`^7{M8E}qTeWRMVG|Fd)Sko(bG_<3AA=c9cPE-C#YuD_h$`mC7iR8$?ZJ7X+=qI)R zOUPwl1CovO$TT^qR5$x%tswu~-aF#BMr}sSem6b0UXF2`5AbrxTqfUa4uBe|hI7mR7v3@rl8Rx1!8Km}(_uvUo0oOZ3|mYY78i0klF>r^frcg1 z#r)1#Z>Blo)F9fA+x=1M3%pD2pn*D|{p_CEk?K$O246Z!QK0ly6{DEsk-7*?Q? zLOH+^N?2U49JeUSo#g^+*}#FUqZ*m`k$)*4+tc5 z2Y#g)g<5SQZl=RA5J^z%!M2| zkd=^?J?24&tt3YQs{FE0ED&Z{k=g&u1wgYn4}w(Ujkmy2y%doKqT^o%pvONB@{o5* zfIia^&_EV)Qj7c#t`bEcAIQ`{ObCFm0w7?rn(wO?wpD(t0?tby0#Wl5~!W;^@Y z&|ck(o#q3*t0;u zEpBq#!`wp|Krc2P?vRfgBIW-!X~^mA=(!T0-4KDMrG*5M`ND8yEd3>pEpo>KRMM*z z0c)k*wnB&_{9g)p?C!jjYyIFTagDXtXQ9Z%+;!I4E_RlKW!zw{H^+0P!?k3Y9qqE4 z{p@Hr(XGZ7IKWNZK}SqL#NOyj>JI2p zl74Ub-$7LfGD4>BNyY*Pm`4FFAToL4>02WHxP0aXXE9QH(g2j0bKWn#_k#4jz^29f zj`dr2*gqV-1OYl&-z&|rYWiQgG}sg90%}9#AamFwb@qhzy zf+@IyjYe!sCw@$qbs6?_yjCpe_kF+?P;3}F?iX;`B6kDjVd|%JNHc!v=Ny07eo6Co z(zY1~g@26Lh>rjGi2cN3yyJ%D*Ew;wIRRJ^*by?OAcm_}BsM_wpY06M6J{UsDTK+=Y5=WGkZ=i=7lBvq%8uuw#mpNCvK5yH~``RBNFfirbKg72$YXTR|?Pz0VEMwF%S`G z4>~p!8bB~C1(&WSltejo>R~PArxb>{b#l0Vg5^(E2a#MPVU(zcAE|X!=Z8?SVT7p` z-3MBMm5&tZP>QILq*YcHMLy^ zF{wpXQ-R}`5z$_3GmaRzFz~Q8uhIaR@)J%vlK%2)iSaQD&_}Yxq;uy&#S?MsdI0TO zl694%2vKL)c@T>drvwnKJT$G}l#=Wdcmb03M)d18@t3*L#_^dT>>4 z>&Bhm!-cE0Ni_Nf^IES<(LV9|n;X#<(GeM%k+NrjBufz$6mzmB;S?@Q5{Ca_6KaH6 zHQRmceWzDck{}f@8yC1lR}h7}l%|oZuA{q9+q*1QqP`ov!aKYy zN{5<-wZ;0H$*X_K+BQE>jIH8UdbU-2SxNz52DUH`K-L6A(R?g*g^B-U0f|5j=ztBo zAXgE1cymh<_7IgPB>-^?t>t+C%a0cFnzW}qp{rkV(R(jKA zOZ>WRJXpQ1biLWTz1|_bSgE*Yeu|FygKYgz`Mgf{KGmdwQ%>MFlww;o3+IAQ$?Wx@UTwy zpf;~mOy1>#e#=xp1-|UaZM4;w50?*9AY~$FubxCcF?X)h8FJI0KxRgK%~KR!rN*bk zC~Zs>Ue&ls^|%9}Q9KC6YwSy0QJo6Q$EQS(HEEn4%$r1|U#9tWOaQZq zW48OY0-(av#l}SCx@wZcs3W349Lm$u!=hZuri`LOe6^|ksuOj@=6Z4J!yL+FNLaib z6yUe!Q&OIk0E0AJKDt(pyp<$WQ`%8m@(argQ!t4KBt*uf%N!%kOqu$szy^_(4fm9^ zyvZ_h%LVbo%BRh%$jvsAWUQx(ap(@ z6-{RlEzw;;(e%*G=w+4MI0Zxj7K;pzjjYaG5wQiwvFHhekhB%z%u}PJ9Wt$PrIF7g zdcy%-)`UUIW}Vh*{cHto(3LpEMC{56ozY&=03Cn?kg(J00T0SE1C){gcYO&Gm=WdX z3SYnh+0y_ezy*~MscY5InA)tSa%CiqQYO97U6ITv=MT^z2seko0=Q8BV3co<1e4&{1W=U}Y`aXYcYEB|pe@>@jk}n|vuFR5&}$9Q{v6)qUEY(`){{xrQ){6` ze3(Y4g@j!Xpjs3DP{Yh}S}6B$YpC9JfsZ%g-_s`%0PYd)I^f=|u=dRo_5BhHepCtG z%{@dgvjWx@6J8D>r9epG7;fGiexl>u;UFI3VT9hS{2Owe-rzkYOE(tQw%-Si(7Ogl zB0l3ZzLBF@<2at<`h3u;OvJ9KyvNGC3AtHt?c#6U;xT^WI=oo!&*#c3|$_8!D16>*Z2w z=MxI&Yrf}vZXsyi=YSsQ1U=?G&f~*MwJ872v%HdhP=e<^j^{AW--15rlnzn5TIrac z>5-U!3^^`_&WFV-=~=$tp)TWvuIZ?r>JWz3s^02RPU06zE}wp^rT*fh{(rL`>5oq3 zuHNf`{^!2F!+P%Ou#S+jZsnj}>$bk>L_6rqjuBNZ>MIuP)ZXgAUhTrG=W{a^4``e^5as6?1%2j=g#i_PTuSO z@4)Krs^0HW!`|Zl<)>a3u6ev|uFCnY@B%;aG#>C2kIH!!>;}K%K%Vf@?xIOstPa1= zS5D{zeeo#&>NlS9*)E|H|LgFMM&tj!HDnW-F;DJGQ_wTd@;u+qE8p`_yCgfG<{N+T z5C8DY;(s5X?1G~6`VRC^U&Y1C!+69&-5nV@gBeQRDbru z{_|+xt7bx>@$M&BKD!M?8Gks1ZbXM4^o{?+UO(1C4EdEm`j)Tuq_2^te&qCI>MhUr zKK%KhfA^h#`n1o8lwbR7El;W+Z0s^@Y47^9zxT6``^1lSw_p4=F5_>_PPJP19zOi1 zFZ{rd{M7Gk$6x&=7Uo$$>U;l46{aluXHW8lh5h88k=I}R#gP8$zqC@qs$c$C4J!Vp z3I65p_|9Md_-|t8PyFh?{s2Kh;6Q=}4IV_8P~k#`4H5o>7%}2Oi4zA_gy<0C#*73w zUgX%(;YgAtO`b%VvSi4ADqX&W8B^v=nl)|ST)7eFPM$q|{sbCS=uo0XjUGjsbfLrq z36wsC8dWOIVpXjcn`-pqLyRCRYGf(Vt3`ofvz|@L675>HZQY*S`d02-x^?Z|#hX_y zQ>S|U{4i5nXx9QiOrdzCF;#++I6X3m{E$MhUp^k~whO`j$W z8ue<{tzExHts3@h+O_{%%eI}{vSi-9ebeOoTlnywg0T`O>Db^_{5g=Mj2mt>O0A}ia`vL2gM@=1F* z#4^jM6x6ay10VGALbWDjOd&DJI#Vn!&*Jeq5ap2v9y#Zvvraqj#4}Gl<%Cnk@QhTb z&3fL9b5BDLMKu3WMHgk%&OYhEPRE4=CA3jXFU2%dO$~iCQa}@;lpZ)YCACyj747s- zC?}QDO;HOymDE)0k#tR4Z?%a_Tz3Tw%r4XHO2aW9Q&U(n)8zH3R^OEKop#t!Ct7Kz zrM6mYuf;Z7cG`J|Pd`63XjxI4eKuQj&qX&~b=PGV-EF&tN1kt2MM&I2orShtefQ7unhdTXz{2AgZKzaBemvWr%F>878CSZaf*9=B$7ZeF_Qv(3i4 zY`yQ^J8!=K_SRFIyuXfMG_XW3MoYP^`4ehoE^G-E@vF!hbO*xETXa=j-F=zkmO`pP%#UhdT42uX_4h-~Zwl!12MOe7b|6mRc7<3I-*1Seji+3bL{a zxlI2gz^dR)@YfE{B@i6o_{KN1p+ar6(1kCAVGLzBLm8?th2J<~IL0xwrnSR?f7%@S zNO&_7qR@skL}C(^xI`v4(TPa3VG47&!=3f;hXf1apx`k?o(=DWDO}+b#W+SXmeGt! zj3N%fp+g?3!-s~;B0aWPLN6LIjAz7S9`y*t6-sf9RCJyjuXs2DjF67P`{EJz=)^Qm zv5jv8VhAN^pb1XWl2j4Qnu7I^rPPFWCTZCvQz9ifk}zoFK%q9UfemZ4vX#<+Wh`Ym zOIp^_mbG+cD_6NfZ~#(}kopuU=XlCgt}>U_xMebxxlCp@)0xk_pwIZt{ zZ7LS;S2dezl%r?uDO;`TR;7M5t_r1SVB6wQ!4~!)5;bgM*@8`Y_%3+h(8m8O?mz>| zR@SnY#cXCZyIIa+_71PmMlS{U!8S;x@UuovR#s``qbvmj>0% zty~p5Ua1h4yoE*VdDWYg^VQ>`M1<@oygOgYenJ~mR7Y6Da}feu=e<0OFMS0(;OW{I zzxt&W;{5v#_-aGG1cq>gA#7luI5CoXD8clC1HiH4PKS zY7>>%m~0gqJ!&9V;k(!ntvZxTnf}Vr)8GI#mPtKpS~uF%cR)36RgK+FqvO+|u63}5 zJ?uK%I@jpfwOo7sYgrT9+0QPru~RMSWy2cS&~~%5buH;lcUvWv_O|Xa9d2^($h{0! zvo$EoXlxIfveqc`hzm)X^Sw9S>uz_xovns<$6LRvqL{sLs&4-puv^~;M>vrAO#^uE zaKr$wH@XLo?}S&}(fxM#za;Vb zU~Nc)vLW9xWu+0?auA>$7p@Gw-8*v>*Zk%e8 znVpVknbUmgRtI~Rv95JxL*45~54(`Z-gNQ8-0j3#`P;?qa=F(%!`cNfHlBe4s;6D; zGPh`plKI=?XXNe83cfK#)@^Egv;2{r8$>SZxlu!KS6`%RX zvm^4S_59&0Z+X%Wp7VBpIk;het8vdh-2QyE-qAjKz#soR+4d;Bt9^a=-HYDuq~G@I zaX)6t}efs5p`WeNCe$}P_`_987_t$rR+P8mt+m~DReB{mIEEX9!DFz7 z`*NNYJRbrWKy4s^Dm+0TJUGh2LM=>(85F*8m_q+CBtrzGfitu&HT*&K`(wd+@Ip`fLrBEKJQPGU zq(e-6#7%@gJ@mvrT*FKh#e^e8KAgZ)48;qSLqc>hMw~H3q($La#9K5h+)Fn%ghff@ zLJI6TkMqS;EW=J@MILmuUIavA48&NR#8&h^X4FJythH5?MP;1Efh$JdgGTa$s7+!S zW0^f$)WzP&#d8cSUSvaQ=*HuV!<}=uU|hy_d`D}1HZzn*5&Oj8skwW^N2}Av`{GAa z+{S-w#(-?Jft*K!R0n@_$Aq*vhAhZg49EX68Aq1+B)Kz3b&QO3^vH)|M}(|KoTJF! z!@q~LM~PI(Ks(8PT*;Db$zwc*eH=nzjLDgFwwH8Bhy+L!tVx30Kna?NVks7l%%BX4 zJ(1~)kZcf;bV^Yg$%vH6BdY{^@CR79x_A^ydOS#~)VDb31rPd%cNm9g=!E{`NoiC` zl6>#+{OiS`i(Y%Y$M9&H$&g(3)$ApF2yhiTy%G`8M zK@&?g!3cj4hEb%?p3F%%`UbAuWXRdIv`BLM9h{%(0WwRV1v&G zJ<$K8Ox6+44-F-h2+>J8&-FAJx-(J5YESG$%?U*^JYWS4{j$}pL<{B1MuSlqWzJ~; zK7WV?Q~*+0xP{pKhj<_a+vL#d4A3weP#={AAVmdP$OYuI2jw(SFRRe6EX^c4PJ%eh z-7HK3I82aBI7W!hQOi>Mgfss$HO&@{%%GgiB=k@a{ZN@0QAsM%6nzWz)YI2lQ8>%c zBx8eah=(_|$@;X;Q5)1kO|ty_hc6YfMUV%NfK<^-(?k`}xJ1qV9I`HT(<|k&OI=bh z^GkxLhk3w*AZyO&JX4&jgmrLHmrT;d#8fwX)mSyMK;2F_rOue4)6C43@+48F>{H_4 z(_&SfKYg?8#ML3w18$&)dC*a@OH$Sx)jxaIXq{G7<}&Rn{=mS)NTYW;N8VEJTp`Rm==l4SJ|NMOL&p z)~6+zpA9ozEwVj02TMd%%&XQK)zacbGOVqKf7n_ib5!kA*|>y={^VD~2+WOjjD6^Y zI7rw^t%E&~7@Vb7UcE^h-BPoSORR*3!9-WPRaqWIO~b7NPqhb_t%FKPSqMekaCrw# z6*4{O1xu8k**sF?WKer>P#|N2cRm7U#Au*;QAhysp-J~+*G?E`)V zOq@+vP)T0qgxvn3OCy<7O@VgB7;N#F)L)>lV8SRt!T zAwJ>51>ytlReM!nC=OhEh=wPH(kTT@%MCI-xCP<$-v=dG*afmAKFm~Q*nI#_JP3qa zC@~V|*96;#S9pX#s012*+Y%;--+f%^nFrH#v*nHB)kRL_Oyb{NRfYXA9WLY|)8W8e z1i4&cZiQekTLdWiO+fSIztys7PG8`BPu;cSB)iS(-D2@16ED6HFjl#yEaSf*<8`)` zGnQua&E!o+O$YsEEu&F*{xVG-+rVsNErZQGp5!3C1$u}G^(AC(4(0pJVLa|+t9(wx zOauQ8#^epf;?#X)E*sF@@={)qQ8^F?fe_&qeb9m}F(S6a4n|y1zT^IaR7p+W2Ypt7 zz-5y4*NyJjRPAM-P0(NVvKR*7b2y(}E@ntY=6^P_+|@5Jy;wz-*Us%Sv8@M|ma}UH z+aZ%`s*Y57W?=*t=av{}5V8>K7147Z)^v8~UO`c!Y(u~FSwS{cN3XZYTC>7!KzDWpD)#1lJYq+NCneOkN%C z*l9g(t?sgHt%p%|a2;>&Epu`x53={(>5Gqa+#c9dG}mC~xy_ zYoy$Zq-3c3Ml!3d1X_s)=BDo!hT|#ERXVqGv&G~6TnC7STaNGtY28>Oj#OHa+b-2( zi>~hke&Q`_QcT7JK<=*$e$WX%@IKJ=dLUj;od-FfmB3u%h2>ENZ|p8T)i`L*MefwU zJXKqk*J-E+x&7g9K+aueFVpQd?sQq0U066~+bxJ19tOxAt8AhkDoOZr$&54GDW#hciWTgYa|{Z`XbMX7zK3`1ee9=-9=B zNjQgpi1n5>SfnR1nVo7OuV9+T=tu|Xz%A}%e_0FmYylsLC!bJ8N7Wx62*_mhQ`hQg zZqPd5XZ^<2tHes2_0)Kn1X{rc*WCw5$o1NG^cIG6o8PiuN8$g!Or64}X~Q2fn^j@s z4%2!4GQ_q-emI4OcX%zoeLYVyw{6D!bS4z)vHH~8tdk}uRg?<_5{MTuqe+x% z>WJjJv<@3?8~1fOC}(TEd3OoiEF0)t&Utu@7Ig_zCQbjFICa+J=@Y0>qJ&rO<=7}; zC9C}E)?ql;W6?b$383pnpx(Qb3gb-UdUTp+llwbQ@3RtnZ?{0onx=oT3Kho zwg^2r*$HwTQ8y|phXfbQw%h*R+wh5U7acF)*iA^Evgk&89lGU0yLjS(!&|N6kxM@L z@B)$^-DKQxG^5txwATNYCEcsYjK)emy_zH`j_@cWVA%{tGIbpj`Dre% z*-MCQ1}3z{<7f&Kn?L&Huf9dke^Z)O0I!5W4X(s>5`d}GgJ{^S(Y-5l;aQjIwv$8`E)Iy(THW24!#9Q8swDG(UjJZK zI{?}ZZU?DiUI?==d^rqa5CKyq1a`$cVW%D&1CvI|_dF~@Nrfe|UG=Vn6e-#!E>yt^ z`-BI_pw(r7Z;JzoPJ*dIQAHl*h=#661&LgwiXP~Iq-~N`nRxKQY5c1ruID z(JeD{GXxS5m&rL~1`#~{p(Zx72}B=ilR(mZW)q!hL}<1vJ4=iv>blvWUpC2vyOfQR zT1C4S;W30>Jcw*|x66C-v!5XYrPS)##ex}WpZ+{3LXG0L57v#8tukmr3#KpkLG)iK z^rb)@>YR!4VxR7m=S7dHPGKptnd2nfvSKJr&5aa6IBY3QV~Q9WMU1)2}7Gs z^Q4}uDS#aH4QpuBIm9#$HQvU-V^~8b=txJv=t;ey78PWANNPnRs@2IDrm5q2Dn_SD zRNQT~tY$@MSDgygfQtXMs%L%cN+|I=ex~)SYn|S#s7lt`$aRV;IV%6W3RaN<)tf6l zVto$Vxy2$2oia>kVgK{e$Wpel0HUd71$Wbv`c$VDDyKQid8{I4);k+Q2T;apy$^jf zN3Y20b6z6YyRzuCsda0?;_zCy@|LTzRcly#f?92;wztMTu0@#&T(%1LwtGb`TqO}n zy8hO#!Bxj_i`yjW!lt#noNXveE7`*W={<@q9AiuREXRsYyxy6td*dr#0$_H&>`kX= z2bZ4Ff>yKB%&!dXiyhk%7q^oEtXAtfSlvmrxdnbMbR&FE1=E(H*)_0)GkjJGU-!Zg z)-Z^Z3tr}8*SY_zMJR%oI^yXFm|Z447cQYvs7dK&`KUL7OZg ztMtY1T_TZ(=;Nx`cBstwFk!qKQI{~o8sGS;78_h*Cqp^JUM38ct&HUkkAur6{xX^m z8s;mb!;Ve1#*@#S<~hf<%4~Ks-B4?0vr73xYaTOUmy9@QX~(=WR@{*T%vnLh_?nD< zv^Ie}-*b9a(Kt2qW)rPsBW}*pOSUaI;M`>p|GCXk1+}QNvBy z)?O?%o*jeQP}ADhzIM{9O-B2_<`~r2c*dwT?2>0-101lfZJx&gj(5lV*Yc(T zz3naRSc|f``-Zow{jG4^0KDG!wy?hWo$!VKJK(TRcD@hZZwb%a;R8>$5|>``b28UAW`RQf!}F|@x;IVfnG5(g>_A634vvF~ zhq&Y5Cl@4bf`}!3dr&qWVVA_@>F8*OJaAIm&VN4Xp&$F&k4t)Om>%`2uSz{U4|-{c zKK65-eeF|EzLK$i_r3RhS%D9A+vg-a#dkgLVV_~;pFZ{QIeDi~NAep>e$XxdyWh{t za~YF%@B1aRpc(J@^}`GD;vM>90jy;HQri6Ump}M>yu94MBON~(s!K2ltEquYh#5`1 zgYc~$|M_2;SwjFKpO+CJ4H%$0AmHs$#RC4H1JZy1Lg2zlAO%|B@a>;G^q&Skpa*6c z2wvF%3SY8yo(VP}3JzcavS0;TAGPTR;{DzIZJXj8xOD1aDBIe&CF5BQSnjpeM)s@*RxI`6n;FqZZ z7}CHiu;A(8p}-g&(zzlm$|4`06)n2NEzU$P_J(hq22Zr&H@qSZ#9}ZGU@aEo@&Tf( zDI+WPVl)0?G{V&|+9EEtgEfBLGHRnULgSo$BQ+kQm`tMgVcNCXhbaQy_f`K}Dl$>Z zS>hGyqdU@^5_Td$X3HmnBK|cS5@KQ{&f`1!oV3{-Nh~1fk%CK1Bt=%FMP4LEW~4@L zBq`7y)TM(3GFa_Er0YrKMxG=}rld-)BulnrN_M2_fn@5j*u{_}IB0`Ox};9-Bv1CF zPqrjXeq>03+-cY(PW~iPCZ$sPWKcfUP>#n#mS8$WzKpvr!AV zC1eqLUq0$15lUi^{bN9`<**E-KT2Lo<&+ST&JQl+<~5{48XW`P3RO;nV@TFh=C1W-wQU>N=K2>2RBGv7sHuR-qW~OFpCS(d+Iu!pVQDP%ISSDs} zrfHrgMs_A)j-%*QW@29EVxlHXs-|SJWIczP#y zT7xxU!#CI)*C8M>9%f@yXD?!>c5KzsD)lAhGyt_7U+S#r!lg_f;Qi_)#p1{=Q!Y}gzl$?t|*JPD1UNj zdwOVm%0pl1rZPI{i9%?8PN<7sD2yWLhb|~%VP1LdoXA}WZvy}4_LZBG1}8rbr&=1P zls1T4QkHV+-FiVM;qjfOHKGwt=PI^?btdLFXahE6CwsD|G^{C`wyB%GDV)YBoTll4 zVuLowDAcKgI3gp9?BZ{TDbkUtnWAZ$%Bi6qDxxAP0VFD;HY%dhX?xl!p0-&#@P+CX z4f)6lpq7K6o++d{DyW94sE#VBIx3`|>7Bx7p6=5>ZGaz0RW;`VxD8+l=k7{bC#SvTAQ|!BKnQu=u|7q ziJL<>+LVUtae50A-X^oyRJjlffNZ5^b>jYMsya;Nb?W~cIDA8ymZ>)6tG@0lzxJ!Y z{;R*&x-Y31<>zx8D#a67vUaU531jcSG#|G@34s5|5 z>{BJ|O)w}`>xo9}y>_h2zAVhftjt!dz`ke5a_Y#k>cUz@!@`4@s_cmpti-svqoM6Ta*D&V@V@BS|EUM}o*uHSwpFFV6Na)cG&}{;vQBF#qZ={*Ek&!UK(7Z|FX*-qJ7M-Y@?C zF98Fv1rP8AS1<-|um*Q<27fRIf3N}LuhS;*0$(b*VPJjMuLS3B2*2?D5&#T?um{hu z4c9RLlEwwg@D2Cx2p6w9m@xA8Y0IfFJwX4k{Yvfx>n{yAaSuN+4m)ua&+q{Qu@Eyb z5i9Tfvak}n@DzV>6aO#*GwumvFSX94SjL|t-dFgNt&)cCBbslMqK>#6sZ7N!{K9YD z<}n|uPQxBCJmhXW*snSivLPQbA}6vUFES%DGCQ;b<0>#c46%I3Z({(mAQN&UZ!#x$ zvL}BsD2H+)6Tl%qawO9zC5NREWAZx;vM9eYEXT4e&oU^Rav-BJ7Q^EmT{8VSFYqBuYGBM+FtD0?dRvQtu@ytbtS(Yu>`j;HfakSL&*J=|U z_wn8CF*%dUFx*>!PvRjG>vuhXO-elc}|vwGY^e3 zI*Y40FSSz#i#o6KM^7?USG84NHCAV}R&VuGU`#%@^gerZKXWx%m$g}+HCm^&T3@wS ze>M79@>s96Tvs(;%(Y$LHC|VBTSxWzk<)iXbz56?UFS7n7q($%^+p#!D>1vm=`wqB)V~g_Uwt_D>gEx4C%b0^lxP(vmgqIBQc}bE` zxPlXnghRN7V{e7G_Q`&DgtzwyQaI6YIEhcU8i%FwGTDVUxQdgwg`0Pbhj@nP_Kd6Z zjYszI#dwP^X|vU|gYWCqW zfirc1f4P`vNEK>}H=p^L%OkX*xqVZ!XD=sYai5c-E&a(in`fJ}(YK8@7JpNBoVz%l zC#f6vwRB$VrP-*p5*mG5nq~htTGlt0UiN%5rxBuGmwzjdjd{4Hwx)MFJ+AR?-npoc zr6TUPaC+t2HhCJW+!y zq(ix-|F_`5x%f6a-su;wM`EO_a!zx0OqsT)Hy)>FJGW0cl~0SVhkItLIcTH#W|LM< zQT9)(dY{`mtf&8Cw9h(x*Lu9yyIQlmPdD|(?j`Wwq-wX?0C%lc=p zIlsI6da2jLx4JX6y1Z)+5~e$?zq^szI}%Z0x$C*4*W-SFI$o-JJW9O3bG)5D`KKd$ z$lH*`Z@i#oJk@i1u_O4$Z#}x3YsnSM8yEbYBfZ$Ge9N+mpuS!*`Zvn>^an@y^rz%MW_nc6Q>? z{h?XmygxhcA70P@IbFW~&l5Yv7kkv_5aUC>fIYtQi@D^3d*w%ek&!#zbDH%}Jj9!R z`C2*HZ)?MkJ9{B|f2S+yOaJy+Kh6s^w{EkZgKy`rdD`ZA@Aot}C%rUd|I15u-2bMf zV>v(&An=c%K!F4iCj4iRVMB)xAx4xqkz&P&2@@o+xRGN=j~_vX6giS)Ns}atrBr#6 zWlNVYVaAj>ljci>3Tt}2xszv4pFe>H6*`os!Gs-m4m?^^=}m_|jUIhUle{_^(~Ue8rOeO1JUQwoL~I2Aq>KQiK^hhZa4Wbm^8VSDIG6nssZ}uODybT$pxk z+k5erB3sArT2{Z_`lnP8x!37!g@4C+3 zi%>!db0bMP-|7=iJpJxsFS+OxJI=8Sxs$Cb{FXwDw&!fiF1*4xVv0Q!*R$$DiO&Cn z%){l-8&5r_PSmhP`XIdV#Sq=IuQ?in8;QRLTlx>mDXFZ|qXUbvQp+v5Y*4-;Ck#`} zv1EFZMH|(lh(x9UW3ELOkrWEW6+NuXyd8Ora3kWR>u^5j;LC9#x>U^T$T-uq$gLm` z?aR;C7A?`a^&(YF&Mv2v64OmNB@oL_K@C+@n7*9N%`s8clfx*pN-s?r6$LS?He1E> zJ0UqVl*}FBENf1-%Cpt0Jx6pj(YfFZwADN%Yu2#&&;)6-U|$rLPz+tG6xTHeO%YpI zM;%bpaLFwZz%&+UlDDK;Vy~ z?cvEDdkD}3ft0T<+w8N^PFroYg)Tyye~#{!tfZ}>q3N~p&Rg%j`9>Rn2Q;ziQa_~CyiK={$~_~&%F-;##_FMR*+ymsQLuipCW zvCsSg!3hG*@b5=PT&BersNjL~(NACf_1SOV{rBOIU;g>&uiyUr@y}oX{rT6w0t7}^ z1OmXLC(cuZ&<~LKni1s!3YMCh($Ew5#v{Z1uTwx z|L`98pr|hK#bk5~Xhbo55ezMEk&9jQ;upafMlp_&jAbiDo$mmNO||jYqz=QEf?-Ee!Rk@Lyi*>tCv5aDYbOYG4L?=e3B$ znsnA`M%5Y&xD02F3aBiXAS32QG3Cpb2<-vBs0Tdi5mJ$kl%yp!=}A$VQkAZhr7d;o zOJN#Qna-4^HMOZs;X#i^9FvqcQKl&CA&;95m8eBE>QVoZnpCA8)o3fFM?JIw0!I=+ zgdZBzBmuwyYy=glOswPw4|?38pUV3u0Zv%} zMSK*lef8^K#R^!#`W2+ZFkwY8n%FLB)Fr?ShS3USD8)|JAxYb50qodQh5XcpkR{bK zqZ!%>O*1aoV$!4Vl^^ufN+Dnahg1Oo4yxvBAXw!92#;o~KY@0)+nSU$X9XyI&4{+K zYAExbHK>9vG-GO7sK(v`wmXQ@u2})-0Te-i)ICRF2c1`Pqm!VDS*B8XX|Catc8tTi zWL%VW?}8ZH632R0K*M^kVl8_B%p!9qoP`5@KP&%Q0l%k7F~KIj_M;zWP0UOTaV>0R zTUEE%_8S0>Sd0$rs@>)@U(`gBQlJZ357*0AfNIoPF81AZez-};%8Z6y>?7w$SCssf z%XPE6T|4bq#+C}MRexk!1*!9%ayoC}(z{+(b%aZvft-chU_dnI|8^_;g zImbFS2ZxTC?48{?_TDlQ4zdX;vros~93x5Sh%(DeRyrtq9I{CV5s|D)rF?z=gZJb8 z!+qb^bv>`=i#J+c=BU$kO!Vy=POoo-p3?^QTNB#a{W)>mx5Sf@@__o1nuG`1c$sqL zm$dqoMI{@nm6BYg23iWC&eP5`5J$Yc=;%Yo;)e{M6Z=bMBz1!8uA`0|41ZcRrjDW= z@38*D=_g%0$;}v%QTR3dG|4RALViR1+QKwRlzc-Wec;Bw2g7CzN6+z!n^tG_YLh%K z2ID`*aMy@4-gs4V8+W^Sgu;EiaF1tZWuS;(F?M$Bn_MhUJ|LTu0tiF6) zsJ@!7FRSEd&7GdVH|OSetfD8(U!7P|tWr*`flObFx+gQzXzs=D@4RF6nR^cQ`MCY( zS7x_?JM#er&15$IkoOTwVJs}K-cC;QCrGQ5(7#=d|3Lr(iusWQ}x;0 zhw>@G(pCl8Dg&mToi|WV3vI0>X1*)BMH~998@=FfA?nN*5Z0@`Nao#V< zRtG)X*=m2x+L?<~T~Re}^mbYJW(n{5tZs3VgVMTY5&9W-CEz2ox6>N&>}TDFpxk(S z{?V{fwaxJHJ09tLKgPmkxBN}Rl2Lr?k(K71H@in>M~bJ%e|GKaX-DV8WY)MUy!kc4 zqXYAo{ z`U%bGNgVQ*V*S^`i9baad%c-^#y6J*$A9aa9{d>p&{DshpYi9(IM`$2%bB0{X>L8B zP=C5uFW^iBJ}~7{nGT?Wz@Kk_5rSv4+5aLa|C*kh1q8$Y+-yZN(S$R9rF?_kGlSow z2!_f2^$DiAyasgNt%@ z02X0r$k*v0uCKAf!#zA&I2MW(3lEN?4#!s|UO@$+t>OF>5W1oaWsYMzK47B=B*@Ao zeELFjC4-*|;-6X#Q_BG;0=GF?f?Ud2hI{z8V&NaN*=WsKC-G-ylL{~sXcY0utqojnEJp;HHW>m?5=@NQ-%#;^;0HH( zUw`ASl;PRl->sUoYsf5Yu)5r0B^CdI_sSYC3roORKaORO$`mGW`}iC0KcH3DJB*G% zYZ!aV4gyiJEd3<-@kmHv&xN~j{PL{4S$NKIIVOr5LqCRA5hvK0#P$XRr%>fp8~HcI zZx~lrd-%`04!r?UQunnBsbZ$L=d#};xn)os3Jd!mj5$SB}4+&%XK}7p|7d$?IGy7)!HG!G_EO5z`&|A!Y8VLeXpVhB3E zz#~A?|IAbv%klBxLL3OW+aJ&Qne88rL;N#Gz5=bP9IB2zmN*R!@(szw2y(C@RR|C) zK*uhiI+x8hfM+Pu_bDXvc;)~tIOA2aRi0?YC;Y?0RJNC~ST;7`nT^TKDXu824~oim z`i&(H2#vz3&*1fO0Aocy$ZrefMwGxm-)Lh%4OybRUuc)5N(xaVxsj~*Lv-wI_chq3 zmUAH@S=t7+_T3^AXXg3P$Kz1fZw_oP^wi^IKI8!>82OeyD1B|wypwVx9aU_5f zKm{H1@{^KkSOIw|UBZx{65fI<8T7-J>s;?mM@S-(w7yZ1CsYjHSsO|dC6>`V<~VeB69M}P{IJuH^H z1&lk@-~+30@#} zJC6&%VtJ>O`$0J-VBm7T{ecbL_y=3Pz#e`kF&xaD^%L-35C8@2J@twH@hAEce zc){AY?6e`0!Sq4Fb}xd{Zy&|U-IB8nSto{kCOZE7sx4?g78l`EBE9m@{7Z1#jB>b8 zo02aBJsrowB|IvQt=AJ6u%ZeHI00ZFx610ujr7n8yTJU-o=Zg*{h63hZAjU&AT~)-9}P`$8Ay1{K36|4np$l@1`#bj`6qa*g6| zpm%Uq$^HB(hq#xkbp4``saW;|8fe-oi_5BvgiX-bGBi&$m=Fupt?~{F*cln{@2*~B zqOt_Lg*8d=%_=gr;8RK1C;G{-R(ie@w|O;sQum{<9T<*hE_E*Qv13{fwjc z{I&wLpMGd~$GW|{deafL8+QB9ZC?9xXi}oxXG$(N#~1DOp&DCAY2^K%%85l4mdO%X z$(I|DzmOeK8B-~3&|mw~d4($l^MY;nn|Ty&OOHT5rR|*yDoXu24F%LTIMKUa3{Ey2 z{_kj6;&Lvyp)Ve?cVT>Z*)g<)94>&jzmdp-rZ0#< z8){tD{R{`8{6J^0IlA3r)aE0{a`ux|xCokG^}~4GD~lHrn5uw7swixYw`&_P@8KWi z2(JJUQ~>k|Es%><9}q>iHuqmE$N}q)a$&T=UlnZnTnf_VpC2W!NjIN>VmD{BgY^cIIporGlEp7 zfMqMiqo-H-q9(;Q@XyOoIp6Qx>|wSaYHu>yX}UKf96vLbr1VQIdSL38_QS5leP&Z@ zbv=t~FLh)eU%U2OE6mYqf3WFWx8$o*3(Hq5PB7m%nLID_?lbuEfxd4C!B-VkAjU*v z$it7fl|tdJydu1&NH^^J5MRCF61>f>23ZbTdj{1#s!`CjCcXd zwKxY|0R*QF|;_3y@S$R>A2sCjd?s*h&NOOZaw!kWb!+_z>9X zta#-~p1ft&7bmZ#cin7mDgMUyaaE*wHS1%fw3HG9RiI`7W54A0iE5^PQLr?a-35dC z7s6LcNfG{WFw%OddoBFYn720bq>L#DYaY!S5YVnT3A!PVHDJO(PJqCndbOwNGb%HC=#L&V5Cr)4%4`cG^=P+{`~{-=9gkzKu8DbpL#cj+3AO8WvKp5 z^LK1?066P)EEI97o+4YOodEkf**pLS2oPA5kAxu^uL;f;_7k+scGCxM z`ZIVBdzU+yUbK#>x9zV!xW00U{D9EaGh)VXsf&?0*q*MXul!p0BXDQAGdjELV15hy zflbtKU-R|v@4HK#KV2ldPk#(vfT~N)Z*)pjn04+Bje>yXRaT^fk?tgF{p}2^rm1Pd z83qjQK78c<{Zt_<)`dNvi^upb!W}eA5u6nIaeAvvQ-Dv1<-%F9gN52w#rtvfZ6E7c z!bX?i3yhu3ktGQXz3q#)~gU>hG?{g659! z>;yoe!ti(~m9Bbu$DL8NMHpF80VP8!+m4AEMyu3?PVvR^F~|k+HHs_5SNrG!lYH#6 zBI&?mIz8}r%X5l}A5P#pRs;*iF?nKHkZ!Fo3DA0>C6-3|0|Qn_V208DDQr5i+GT83 z4c$~BJsz>1`CU@7BNsm4=lvKY>VGfAzw^<=eU3ldL2sWGJdf^5(>g2hE3;UUY97+$ zb!eHuk4Am1SM7fOwL|BJ)YVmf#l5{=CX24yU-}JPC-;!E*0O9MI(H!!4l5+c_9})^ zE%=<;gOg7Z&6$B?S#EdsTgv+Sd|)C@4KZ{ye)*fmmvlh~$MQ9t_!1Lv>5$=zQZl(u z7$Ih03Xtd?M10lj7&dp_?FRvaW*p1B%xcpQ^7$oGFc8{Q>4shar0E`{xnO85PC*=G zg3L63Ss3ny1J+d@Mtb|{g~L7IPj2ftdJ+g3M}}$<? zSr(=NEgYdr+ZCGfA-z)BIQO~{{rz`qwBJbxZ6X@DN6tV&!cQjAT!9>_gVlR?x;yUI z146u%+u~V+f?0f@efqz*jXRDC5Nc6KG|SP;LG;8d|E{h*FTBavm^6x8x=w!RpiMHX=UC>eHxm#0^kTS z$a+=sf^0!P>?F>ZyDeqzQ_oWd!*YR=(UD8q4mwv1D^M1l%hIkoM55dJ1D}0bbbc;$ zLd-0VO0=~=Smr?@@QOv4>A9^*XT3x{dxE+?4jG@2aG*uw(p2*~h2dhnk zB>oxN==G02{hcHzpyd{TE^RM%gBr9+@<^Yl-eefR(3dimAD5O>!0xi)yfNv(Ldt9r zuWnWOSvbM5Q}J>7>CNM+()aHs9b6PmO!*Q=azl2NHlNkc5!X8Ri{z`#E30mB)Pg|h>ltn9tKpoSTRWL)zTD>jNwuDtoB#T-;kNM5u8)bj zJgLUdu3}n$#)8Xs{*pER9RWj{S7xPn~qCpBYDC&&4 znQ#SGoT#hKd!8LgpoJ3kv&8pbCv~*~^Fl-Mra)F&ufI?Ssb}&n6scFd7N>>pMNwE- zUrTTJ+U3z8#I(~xf@wf$*kp}qD+V!yk0>OzSCF@0jqod+GjAM~zIf)QQQwHQ&HMdCHtlE`eCPa6WnA=TA{Wyy zANy;Xb9*oRK?Fin^M1)^#n@u90H&4U%M&^svcwb~Q!|jrwrS#4f9BumcuE*3*2 zLN;eCGxR6M-hx|YrE=6phTQv4Yyo=T2C*@$mGWW;Xyhe8c4 zeBwtoZJx#_*qrE9^{CJ|x-^Hx$Ji$tM(kD7#S>SCkZV`C_d!P{ONji zCP|Gp|3R3>^~AtC@4ew{qCT;a|FI#Zp4duNAm1cF_Q^4U9`^?kJdp>n_SR=g9{Ye1 z*@?lLiRJ{rSRuVaGvCdyehr3m0Ag?=ls!~-gBc2M05EQu7*;3AGGsUaR+~LMD>nL z3UMq|9k-A}I3}{F=BOVrU5OA#tIScqFZJI*_=R66ais*2OS$8z0roz*o8NQCdJ|3b z0^Csfo)O_|v?X0VdDTY|->V;YvL%0%OO9n>t-*3iC`Xm(o&oPD@=!7|27r$eEV54A|2T{gDmd2C{o7ysi}3VCLtY6z5AmC#z{{Ef}QrId=ct6faZ zy;^9!-mbzpRE2R=+pf0W8RGhSDZmu=7<=jLv8vJIEI;m_)!_k#we4xreI(k1efVQ$ zIdrR$@=KN)3`^>dEY~Bt%6$(@9tnId(t|+rm`abdL4KhWeFvDn$qI$*U4r|8(UzLd zToP`#;Iz78>u!wmr1D#N6*m=Qp*;+jYY=G-Y*VtxuT;e=N9GK@*O_d!n;#@MR|>wI zaUQRUzV^eyuDk-)?|9P+xhRV?;Nttf&yW`Ugk<#sR)+jYV*D!JASY6F*5*6ZuJ_fd z=F*N^$6{^)UCwjC9JOZV2TnW>i*mMUODp6bXDie;7d2}m5;N)Ss=k~bG&Mb5{tE4n zC4N;2RM*-H^LIBVY5i)k8hy`GPZ99vjvm3eEOM?Cn8aMWEPY%DG7NR!Y3L98 zFY*s7nAiN6;(R?h4&+-kJj5?P(%wPi-}1$E)~H0@zXa-*gJDUuKB+cbE2$_q(72JH z{Ln=wQEE{&{;^47Y9*h5!`tZ zKGO8c;*S2-AFBt~s_1&+Qige7ESmO6eE$=!q}=pTqTBJABkr{C&Pd-)pSGE};*vW}(p9}M$#<9OJ2D%|`5g(0ysqTN zY7ysNuC5MVqZU1%q!fcLI_|{f?RIUIp1Ki(x||+YQ?i1;TkY@Lw9mTeufF7paZ%aj zvZ6Oqa(?}v>0o9>pZaqBmC?KAPJ@W$x8PrI-zfCk#1Ij?DEqE>$C#2z`W}ynnn1~c z29uh4^%`NL&Nn-kN<2FK(8J&L&PspYH=tD=qH`VyCMSl!?X?&g*xVR+|H$8VX|Tsx zBRPOiUvjkL_uxa`A%B!){&KM@_iIwz(B5q>r;Lu5>gVH%z6;AG8nrHM*9=5shW!J2 zR+fjWcDn*4M>1};yxNs$U+&FV98o|IW?dc}$e5_p8GS#=8qN$Iz`Xg@^>~PZoNP=? zt?B)|J30|*Ju5LLQ>#DZHC7_oxu7xpX=rS9dn`@oop%6{QY_(OI{rapYOQ#jjxSv7 zIoWBjG`v`SzpLdiqpv&TJa>|EIZ*nKDO#Y6@mN<(C3Ey&Z5-@*yWLC5L`>e}+PwJy z)O!uqnXaKA;V%BVag5l^g=buvO)LAv_a;uc*#^V!;I`h9+$#_1g^&}eDOyN zgLb#=uu^lwPu}}%(U)5}-zuqvmN0{2C~p{MW#>n$c_(^Cuq+Q*B>s|pi*vQo`;$tB zJ8AH&&RyBYvy>fGT4%qfbz=bm%rqfga*oWhAG(5_hZM{vg8$}4jV+_9<$Tm7SN?rIMYO_#zKz*>jBgO;-}bm*A^&9j}*Yx`ZPc=tc^~3+`-Z>r1 zz4hP1Ez<>fadV9MLZ$hR<&Afefdhl!-KSrR%QPs}W*fCqUqKeYXcq70rT~I!3a-C1 z-975@-`9EmK8Z)0A6=SP`KR}dLy zIQ{VNg{@mZx9DWPLbJI?tS)-3ZYb8y0C+t$mzKJT&Oz!|S}|{{FSNb*0p0FN+q-?t}mMH?H_^;#QWvt-OOXe2%{| zpPX~pS@7-VeEWqD-}-|l&{{tOZmulj_Y1?fAK$~@wpfzS{&~0VXY}aLT3iVxkU7>> z%i7|kwB$hL(r56$&pgW~CR-~{pZ79auRL^?KMz-fBRs>0~L^o_;oYO@rkI2KAf zyU^pz3525L@562T2K>9MF(cAsEZ9i8Qsd6c`cH0RTsM8yIC z5af>|Lx;bA+LsEVqzSV*6`PXeuRny?ySr4W9^M#{q`fN27*(+~nRBTY$#{hECqAWpFf_bBHOI}LUodk1#)XKGyL z{0&!06>}%HWhj5yDhKsIf(<+4GU_`@|8o*o7kU(SXe4IBYVoE*%g?hMKiikuC)RnK z`|KCR+Qgt>KRso51KDMwBe)dyzEx&5{oq|1GrF!}eDm~k58`4mTL;an;&h#Q=|9an z%DxFU`g#@&$L(C(p8J$}b7474Q;EzyZEal3s60B6_l3%ZobCOjkg#&!5gXBHMx-t~+V(Ybt?HlbIdUw5;T)`V6MOJrx>3FK1Ccm)1y!78lwrM={ zU&v;?^m9(Hx<~G)PKTE}Q2|Y>z7^-pX=?lG@As2LUxBWx6k??5eJhl^8Q-bw?-OjZ`G5-C6my zMBnkp;eM{(EvKI5j}1p#57fG3KXN;vwFgf2{+*^6CDRKLEia<}*3AgZUptXX`>@)u zGk5P^dZ+~*KbQ>CTtv7|E^apBtJXY%JP^mr%3XE>H}yropa!V=Oi^zcBa|1@4b@uj zM|n1Qpfaw3=r6y{dur+kVSVtUY2Zp@%r`I0B=`CYxDGnX=q?v+>Yq?Cby9n6#F5&^ zv%mlSU|RfZnc8~v(P|fj1w9)`c(5~{P&&zG4gD4Dh{s!KI!oCnE18+fkLpv0G# z%!N5jZNph$_OS+Piy>s$0;|I4mJIH*A6=hcn(@~7=<=HjWXt!nMhu!h3ursk$nIK0 z+Pi_-yGSW3&y$O$1KcFxaRX}op~dm+AJu+tnFlORVzv|!bl>s@IfjRHGQ+Nl=bf<{ z-ATK7?f$Vh?oaLz{|_HGnwP1clrQS;afDnn0x#{F4_Ri6``y=TOy(&^WnD_MC=PO_ zUh#brb#YKBEj?NV=TKbLMS8e9uj2g{x zF?cdb^aUZFKVp^XwSuejmPb=`4Ux38>Wx=OV zIEcj=3yU}QN>MLD5%v1Ookwtuw<~7)sSYZ5Vrqi67s>W%SJyT1N;=qah{`SHu1*6x7ISz3{Y6q^KcMyL zcz!K%KUJ3+LdUt)dLG&YVy6<_;PotEiKtelU_z`v48}Rk?HOl3ea@KqcY5P$e0J zm!}|0e1stR(&X4%3(R58xL4eiB+YpcQg@(9e4YS7_Qx{zD)!or*BYn>XJ*>_6vAMn zdQsEc42qKEi_9Q^kvS8Y$@~m_&VySsVd-k1)1{GYl37+9LR?qq`;E=(G6Q|~LmqHWzOuzql5uTj%O+|I;xNuAyqyZM3}A0|h)u+5Efnl9Z#g;A_l$n)se`cQH-< zRRV2{3QdWeLRn}b3E+qz4?Y$UNIL}yo}oOpuh`-W56;6q7-Ql2x9M}Pkm42i(;q3( zK$2g@LKySSBbZ*0;btdms18b^D$HG^F1*kGUmKr(L+ zN{AC6Gf6~X%Tm_@kWF_Z8E{mu8?%aIAwOCFlGBECNEh7V?0yo)KVJe6|J*V|^F7e@ z7(Hp6e2{KI=erS;pZ8`NKiwHQ=?8!Aau0di$8Ymv#rV!bN8ERvdrXYf67RqEh#5JRR$ zttDkyj}XEl65#+Kx(`Vq$HE#E0|<{k&~}Dk05QY36<;l=Y{nO$6K0tZ=A(rqCQYS@ zMEN9iK?uzradK@CJ)Z;wG+A)JM&bnG3c$TA6RLgSXfc3>SxLP1b<;_$P7QyIpX4@4 zBeYs0!S^9yr0dU8*Q~#0R4q?*^o1#i$ekR_D7T1^f1!}^lZ&Ul6%ntCwhF@{aA*gW zq-MA@gmA@BD4LiA_KXcf!Px*UGi(ZT)XOWqZE&&Vs0LLtONCts;R~d+jr*-T;+5Yo zQdFVrGcdgO%ts@#sz#*-o-jhlK1q^YM?Cw&z^bivJ&oRfEA?2stnVac(}Q3^Rspt3 zuJ9&HTq4NL)2T=T$SuA|OZbWq;h>ffwx6QmpahU(pV5>2(#bWHRBu8`uMN~Xf+qMx zFOFF@g#@yrRNMl?*?d}nk*D;%&!UXav-2)u`~G1s zVd<5`GSB-z=+q{pw4{hkf&rn6Ru0PcZVLp6ffZXcOB#|G#0W4-;yplI5zvCUCznYO z^ivGm53WG*iYk^u{^wg2ZiJirC?_%Ums|WwJZ}s82Fh}Y-YL4#ClDwQ3wuc1dM`bF zMptQpB|r)j?-AgU%w-7`O-Y33){4f_C>pQ$xEs6>rKn`r3V0?d77>G^DO6Wl6iKeC zclOi++8~}S$>@Z*RX?J7nlBaD>3>~CZV>nNW)b&E0018b20KbE+#Kma{AdVv;01ZHXZ~r+A#EDcO6l z^L!Gf6eA2VLBa?Gp} zTpvi2pLF~?6Kgq{cY<&e!UYoEg z$cR}c=S;!a0upX`fNzINM`Km|OyU|f7?S;!I{Z_9(yN=HXaY`Xd^Ivc274q7lfxQl zTvcFscWFu*;9>i5SfLIHViS~O0JA${^R7rJ#`1jsZKhAw)a`cNTXf31UB>}ItITTC zGT2r8OnEj+H(2Lt;wjvVBn_pGu?PZnDg-(#feryiBi?=vQ2_=AHOmt93Go$AV$~It zp2WX_5NT-fFGg!H^8s_0g&D+vBnzK}D{YV~`(WQ4Q?P^12PXoZA$a9cQxXdP-%Pf6 zF4?%;zSU3bJR;Orp;6-87P>ab zE-S)%@ciFFw0xjiZ4e$=88^hc3&JxTHWd%?Gh^{KoOup6j8peXuu;jTqa=~Exjy@LZ=S;4bfjJhbtnn}R{|6CDbN;o8t`wIk_KC4 zbZc;561Wa%VSex5lzcP@-Y{~3ER3UsSgw)Lp^y?;KQAX*Xu^SySh zSEZpHn!5Q%dE)ds2Yp>An)?lYrdZQu-)MzSM0@x8lg}GvTbb?|H7*keb`nU#uY9zl z9M>=YT~TYoc+IE$<$W>L+YH->6&Oxf^S1DLy|mw-mBYa3^x;=x&Dh$E1SLch$Z2#c zssUB_`nVBcY&DnWb2uS+!6#>6 zANghkMGaQ<)@H5NB0Sf4-fK91Sc@xKBfZ=-?_K*S=M+dYC~e+%6hT0+ueUWNhgzDP zKVi{Xwss^q98&)FX$x$Spl+EMvY%KHccYh*cB_}PS=$EEV)@Li&Pgq3^H;oH2=gU1 z+#x5~=|Ex|p2ErN7BNbfMF^2&pNvEaj)pb-ZgYncWm%In`GOx#b^DSmldU`B0@MMO zh8tj_65EL$`&rhb9u*y{`xo!H!2!XPz~i_q@bl9604y? zBjcW2iiOArzSDTwyt%X<6v`IbnP-u3;JsIHx6bH}a%rQ@l-)wiyvL^M2;- zL36r)Q;ysKE!n}WllxitWNV08kuZZya6>l9w?v3ZYj|5Du<|)J*&Bo5PI@HUX>#vI zN*hZCm;hFbmwhN@m#}a0==PV&tXEb4xo>{`a@6=m{LY@i+Gf)aukF3A`qtNBgeDBe z;nr1l`7_hFk4ai36j~>2x;n#z6pzKkZ2PO4yTj{G#V~7r7qegO>Nnm*_`T%sOClzhDLB6r1pJAuhW+?CeuhQ$ z@g{fVFQ@~TTfOJYrJ@u-0q3FKeoJRe&~BI=o~|g4ERx=eBq0JYO-&XUw!?7C0)rrEX7a; zWmXxblC5`k7-A^yU7qYsh44@brhi(zt9~{SUzQ7HD2Gdf_Y-L@n@6LPHTL7rj4v7% z2Si7xA}Ms3Mpmz*#3ZUb6qWSuPyBgZ#ykkfr+ckm5JrCkspz+Lb5<om#P&sH8A?jMqgf zd>$`lGC)d2Df)sdEXwu&Mk?*hzHsf!`b!a1i3P~qXIcS`|3^@Bhmq1TDhF%**+Lds z%WEaWnMxxBI{pL;8+;Tp4@*uz0u))>^sdvX7iOoT}e=SZV8%YTeL5$&5+B%?c%4edUshk`=gq|UfSLYs8))ZHS`IP=& zq1^GfiqrY(0xend0o-_XCY&a1Tl!G2wVnp&z6#U<=~eQfzUxgi_q& ztPsJ}0Sjgpk|B+!02HiTUr0_iHF0w2k>unn_n_ep2DF*NeXMaHj*OljbBBL8tZeIK zmGM=^yY9UYF|r2?_y6$C=D5RTH&MQMXR33P(MwN%Sm@+vd+|KYb&9(5EIahKSYYd_ z{+4Oy_aE01N}d$e)YOU&6yKV>!TBL<=K4U*^H*y{wO;=RM?F7p^VBu;vFPG@n!NFa90{pCqsZEk4DyNhy4!e&B??8>~L$LCbCdQmZJNtKqgZnhnQ zm@k>i$_kjDw-G$%4Ss?w$F-+q%Sc>lRp20z| zE~oDioDD}DO}H@c<70(8>}txvue+6xsWh-ERhlr79`-{}D!OBsHhFsc|j z6+bLXSGvPf4mfz-Y^=Xu;Om!nrj_*4he=QE<=p88eNEry;U;goYk5iQVr@I!_gjs| z1|_#IJiq?xL-^6}-1=-#^sA5eApA>>6T?@THG=_5&@i^A^>LdU2aSbn+UdcN!dI1w z{HmYNj#5h>ezj-PA<&v;d zdIfRbk^^bcJkRH{Ni`<;BXqA$_Ns)K1bS^iMZRNHvr(3do^IW?QZ*?*p1T{Bq)cpS zU!Z&yc-LIW{>HHDt*n_Jks?vQwf}b{tyR z{cZUx`hVi_3C_Yosq46P2TwE_Afr}r0~1xdcbJESi4lXkknb}v4& zIhkG|Rck`lGweyU2;y=z$2v|v#h7L7$aA~br0Ln+)KI6>$teZYcMP zC=|u63qhFHu~=h;M`tv3)RljemjmP2inHr14Ek3^Re*OHE<*3Y!316_I`1U1=MpJc zujTr)qr6RVp^$`M-AbIznX71@4+XU3=mnM{==G|GD%z4Ou^&4lFGt$cgYE&+7`t2b9^(C@s5D?KGFS>j7wbv7f(FF%ZC|U-xyIj< zjj>^Yo-6&qPhuU2`j|(bGyL&UOZ+oO7Mn;OpW<${u2Vhn>J zj{Zf-CG$LUJ=+*qZB{M}sI%M8vl7QYwm#{!(-KcgEMJwnHs2Qy8@`L&x0UKUls|0f zmoUW9-O*eZ(#jQ#d3wiM_?}VfAx4hQG4kyt{>W~%j0f3EBO2fg56+vux zsdo7#aOL^_^N__2YE1ham80385ZA^)(5pD!MQ9kV!jKIWBHa7E7e86)-*^Dw?buH= zavfrhpe6~)v3s;W1u+CWK%=ZPJu%HcgXYbsUJ+3%H`G_1m3 zkfwwqGJ20pCVB~$LzycnkpUZhR|F%gHWo!*njF5C{1f^f`toy!xLSu?BoAi_o7(3S zw$k%S^r4Sz`0EG|&JZAp!HEjrDZ6j1XTZdBp5jd<8H-H;sTe8%MJX0)$=!!rlUJg6 zEluk?DSmcvTY+C_i1f#6N*6IiGhGHC<-j?mODqL+ZE+kKKLPL`rGBoEPS-jOPc?O$ zN#l6Jpv^^r`b-6MK?#QJ;j!OEfpKwTL_VLc0-xKPlZKAAwPHiI*<$s8&keV>-uQDK zzV$END3eQ9Lj#1y!#Gu4@a-!+1bPP=)G(_Km%IzwgWbZW2=^bf~hJukx8R9GigXct1)|B;?ogFbi#fm@@Chhd{MiiNmrqW$?`uWL- zLbDLwlsn;oP=24HS+YV%U$*do=5^mE13C^6gm9ZN5%BG{FoM4yc(~>%L0beT?hPCLVS{ zAx?zX=lQ$$LEti6&t4hL+=(p2!k8m02qzKG`y}g{K?=qg6F$#M3lA(W@v*$`w-X+K z2m_W=5M?MvmuJnNfM+9 zzMN!Stoi0bzlt3LbCs=WqruO|z$nR(4Mkvl<=D+mU=1XL)Qst3Dc>6*I%J3z>LaVd zdwtzI7Y98!;e~ARCD!(95m$I^ukoq{uHib-mtQTbKP%axIOGY#A!B`Kh%J|daO5>3 zZ7T-IT)$Aq0K|$#TF3A|odJz(I&t&7lep4xMS%H*IbD^3rdf{85!o`EB6dU%mVz!R z8iS~I-*(w)vYo;PM>x%~q`&qv*A$rySOoxYHm-NVgu--slt~`tlN#aOD*$`FmTdY250~|mbQ0h zbRq{UF#=BSr-)^^n;(f``A}y042gClj^Zgvq%nI(a;LBj9c&a^I_s`Tcz@9+3`JIf z(sAyj1a6yl8#AmrnQETT;FY_xve2I$K$bkB=d9!4e(m~Dq~dQ4(Ki~ZH8x_K3x7%? z($v}kODU+LFcgoRSU;O0&IWO|r+n@VD&Wp^LN5#xtKHu@*ya0iJI~+9famYHSFHxDlNatcw#nA}h&3S3?;6KJw}e2teFIq8AX5qYo}s#)ygbO`p8Kp3BeP zgN(g8^asVC={Fo#TAkSZMNOH*?UTL#rhuN>h)CsaZc}i8$BT z@4E~g9RnLw^<6O-FeT$VddwXXQ-YmwA|}kX7vC8ch-UfaOT zCE9;-27bJ+-T&Rs6vqPq$vUw-kVL~H1VI96oIR1W>wf#NNvc>;KD_l#bUm6P*A`y9Y3|dLagjkkph2arFr)xD|Xf> zOvJZ67ah5=hEOtBKbGW+nBG(S+%}MS~?nALptZAgyy-e|cGd!B7iG9(!iQx(IpNJ#I+u zmnL8!n~nBPKy4iHo+1F&A=|8OJX0phNP$r}5PS+?&K`u2JT(VA>04xV7W&2ZWKvQ> zXBPW^{5H_l=`YEqXk;g=x*4u^)ql~YA7T8E#p)f4BT7gGjgCOHklzrmgO;5|+DtBr zae-j@E0$aY#sQd68LpxXC)QGVeRJztY76?J9L?=i0Ts7%iLkS$JU6oK_Ods{%lz^+ zk7S$=8)Tr>(upj20?|E59@la%UzT=qr-LPeAzT3GD~OYMBLfHF?_(hQ1lrntfv&Ef zot@mFgEK~c25)9ix8R_BgUE_qZ7Y$v6T_|3D~K{c^qJ8Io&o**U5L*lG8>POQUn5U z|55teRs{i_D_=fm{iQRR1hwh@G6+OiXi~ozw;Q3O2h?8(F*HKbjn`9!aY--2dK#vC z{G1;x&8uWnq)&J=+BsICpn=>`(`<@U_BZvG0irPZ3*u~9fQ5d^yQ2tvE&ysOnK$3~ zcWFN9is|=D;s@RKd-O7V>bxB2LRz2~7e7PEfm*)q!Wt-l;INuqgX@7M_6wv8KxISb zFFhK+59QBiLy)n1M)PnFVx$($E;-(I}A!p z!Zs#JoKTRjzFFY#cBFp&QV|9+p7Ecdu7+Z@4`s90#Vw{#EmnzzGIk zV>;5=as}W=L(e&IrxR(?eujzzVY(s7f0gjjCt;uyyy>eX?!QC7sqMrqMW5Fdb}%DE z>@?N*vGWw5!ICTy?%n;^!B7vUr~1uWs?Y2`M7yzXY3s4lvXI8!nryofJr2amb>S{h z7MZT3)~y6Cf2?kDM1yjF4@QL<2XmtGGCRk!G`^nirG9p!Zocm5_h0CjqxGxnU$Cs2 zG<7r1^?(653a5F(7D0T$mIOJ4Vj{we(M6b_pwKw~uH1}-ZvaY1!XF3>58N>n@i7wZDjNjmoe3eT>2sCPaOu)2UC%bsV10bXGH9V@RE zlfy}xQDsS((3Ek4i3zj1as>85Ve`uY6H{sg2uCFH;1G#Poxs6yuhGY6oLpQKA&l~5 zlA$(s9hA=u`iM2EGYrFk9GIq-xN$PcQRv3xU2Y=l45xU~^ky;S{LhYO-Jf1bWO&5#z)1ZaqXMOJxc}TQDMH0PJ&YXj z5uqVhkAog)T+P9DYMeSTWd~btPxagUle=2lPuqV^%qE%~EMz+Ywz3D{IZxd^6VMd- zE&)I#f(uVB(C@hGS=*i~?Pq#>&a&lc+_#w5yGQ2yTu$h z)E278^uzEe1E60KnW_dL;VTwvf$UX}uJhYpdEP9F+mw-URl3#3WSYki7Miz_E5cEq zf<8EVR=zFen@2xp8gSGoF%um~Bt$rQBw$xVYt(d`}uc8gwEAD-+aHn#@Ok(#Hm{S6%&@ zrhVKH9a1N7wu~*JcI6;5FeeXg~{8J<_;{Qkx z4#1QFDrwwX7knK6@=eIqx?nN$Qmm$fe=UTr@N8fJv7sLi<>Cf_G{R7k_Vpp75zY|1 z8p8}8)%dwDX7?D(hoBylXf*`g&=^;oG6v)(=JjKp z=!=`T?wRv)#|=x^#Nk{eLE$+2_cQf|lh1AlT)(>1rHU4CBdd);8Dn_WZ=&KNKfg&^ zOhk-52})3*EhIW?JT(cA8a{awi>S=VHJ{3un~QLp$QP-xp{3Ewt9{?r;2I&xn1kTU zU;l|YQwg>KNlYj>Ieu9CyYiFZsxIo(1`%9_ywcOhlbDSuSpMA%i&5Y*uM5_S-@GRb zY=Z7?T6wf;0Z!(M5{;+0ujRMa88guFrx&3_aHid4b$xU|gJ_kJMLVT3$(<^Zuzr!P z*{_%1zfKnV^mUd1BOy3@US>9==Ou2PCS70R5pQl*;o!KhIBnt&pHRCiN>bA*>SJn- znDFyc?N^3289OZd7FrZi@eGw+GomCE&rX8rg984okW%LN1?j27Pb%74_(0k6vKw6f zEWq%|iKB8>Z+6jJ7q7v~O|ItJSH|DQUfS(k2r7JwQIGq_z2K9zz5ASs;I~-_DDf(F zU#m)1a2R{C+DI5R=&=&JGVt}P?jQ@4%7z0a%9_Ui(QZU1Qy-EmQck{(K!*x(*G&PQ zSn(R+3oE02KTgd#;6#9QW(HNaNSfZYksqtLO_KV$ID!C3&9_?Wd{Jtqk%fRhRF>YP z47&;gc%~TLi_mN^39h>R7mNk*3?W z{Xlq{f-@EQ`~Dp@8Hbd7Gk;-Vgsc+a2$wh$JGR0-G>1UBF_*KgpmvONQ|m=dtol%_6fs%QSHnsi2nB;b>@dXpZ!;hV(seFZdZDoTg6cVgxBg~A9F}R zCz#EB@P^T9}AE(~1uJ~FTut-vWspUK?J?g)%ddHy0W8TTDfjMpaTOH+HJ9c*>Y49_^K`FceTc>ZqK-7&U9JNUz-Y$be4pa>1JPpTmJLlke6$m%r#cxHbn3 zA&RH6xzs^2L%%3uJN1%WA@cY_A_+$72efYV5bzb^kUa`rWyaKlf;V zLiWOq=2Eg!+=}Go`;5Ih5k!GJwn9ISOJEb$62RMr8ZI$!ABO70$62 zVz8K&T32ien?-b<1e4D_e!MZha^vXTPUtIp)s2^o7TkgN4VS_99?kxx8DHt#y*PnF z&-ScN1S@@r@v;<(?b)$b4>^1|vC=ggzgPUAO+nsc@1LhM@E}@)yUHdxIe{{(aQ#TF zN}oyc$c_2RuK{WA{laJs6=txBDVlh9XF=>S440f_F>k6w_|g~=`$E)V=-Ca#(uG4vHcZx%eLD-=r0vd*u))EUftSf}sQ4BM~FJChYU31FzxK zhJxa8$-FXC=`XPrLn$BS-ePW)!z{JahIY&o$FsB(9vn-4+pVSzF(lFFADIeLe{~lv zUP=nHx*_VI#<)8A>m27aj`x$)ur_@H;ujaGXm9VV%t(qOp3DHE*wy-e^b$z&{_s*! zuCjFSgY7M?PY3HUpESw0)OBi)0Cg-61_VdBGAK{BeRWz_2AjGs*M<-)bBj&VXp!|*C?K?awga6Z? z%a7*`5r&-2)`kGPEh`VnmYg>DpYfA{3XD7K^KyNZ7%{GaA zWt6qWtHhZ07Bjoc3XEV|M1H%3nc{#~;X2b0044d9mC|5RI3uw{N@M9Bdl_-WY*o-? z2ZNHoB%HH<5=<4fI#k^Kho6 zS_Z2oxvb|;Dg4O(L$U;>VpAwOj}2-#8Xu-5%m5vwcx6ugt}s39rT-l>K`pa&?jHZ8 zd~T)VdpBHej^|t1DjQ|_(Z>P1KNwrq&+-%x`^uq7uJ5}-f8K~6$&;f~{;gV4yBQ9V zE!3Sn*1>Zti#aEkB7h5nG&94RQg;5@$L>sf%1=ZeA_%z>yHbgJa}z`SnV{wu4W2xk zMQVYl$%5cmdZQt^^p=O`)IKj0L8P|7hZ^$9Y~oJ)>s7+iFX=z07Wp^mc9I4 zc*cv+@+Ym=v?5-m6i_l54os#iiX&zx@=s4M%4Y2UnUiNVEfkx+Qm`{FO=0Gp4l@QW zS7XAi^d9^fE0hzs$n%;NDUi+m#=NJ_UbA9frJ7xlc~;Rgm7l%;r`iJrnEVw$&hhN_mimVfcDGI8w1=&%@>r^|1aG&tk*IO21sx$O_-K5Ut!e+AHZ^m+ezlT85$$i>qY9U1C- zo(FIF!D(hSV%U|aUu!~7WTXODg$6A64d^jsJiC+c)zT*%u9mXTAHKv!ynMEMt*Y?e zyF#RXgjmn>i*6dj&~n6B2&8#<$MfLD3gFOep4?o#qf2g zt5~D=Rk;5~OlzEC}hS%srI(%ZmB=RO7CZpMDy8 z{l|%uo1qgw{lJ0mS)s$V6*a6zQ3Usu$MV;d6mD?x-B5D66|G=iVoTxhl;<}3XYG<# z>#Vuve4#Wblt(J$trS6y_-DZA?lm`+CoFl+*AruC@lH7$Crp=L}j&m6{IZJr3x6?NeeKs!{ME`o7BHIrnp~|F#{6Bp*|z!u{%V zR-QyVB>b4MyJo9NQwveDcMR(@!MU)HLNxJ7dXMMrUf$tybm8M&ut;D(zm%6ix8PREYxcCnb1O7~IDBGp2CP7? z5r0%eW&8{7n5J?O8L z{ioMhkFFg)NwuW;$M>|y-{JM+`-NnPNp+3UpB|3QD+@GL^yz{jx$x|#V;83Oi=NTH zol^q$XRi|&kZ?jOoXmFmGh#eE)BMo(#uTCUwV&tpT-G0HS+UnL<{bX}Vb}UX{ckMJ zQiJ$AB6^bT${gD@X0CkG(%9zjDK)Wqc@brI!`oT^RN3LM!o$cMs1Y+|1%Z(~a<7;E$)OjKq)e7;fy}b@++_`B_A(14X z1Cp*R{gL_$V*2~Z&zWD*_tOJ-s8{Lc)16&;N*F)vXxQ;SuVhp|LC3OYy)6|ixf`fi zc<}v{P*zBzJ@Ml#|L;=$M^rhl2w&n_oQ17QsqNc{&bQUX7sdDbin7FuWEO?r znpO~WIbF;l7B`H{Xr}W?DN7q+7V+E%xXW)wlf>MJ?hG>hT{Z|c4+*zS0o7Ecg@A%* z5rS%!)v>86N13Xz8q8XCym20%B0r6A8h&_x?Vy^v9Q?&J+v1hQ zHU`D}_Y^&~3|xb-!L#flqacAY3jgVt!9;^lKN9;v%v5%gf^aa8dUhe+BcVw8@i`At z8`vj+3|17odTnZ!8CE_S$uD){n_XdTx9}l`eyC2NJEm~2} zrY*z2GenOa4@CE;Fz9kVVIT6a6i~m*BSLz%|E>F#X|yAGy>AV}X)cgo7T+tdJtUp$ zaxngKg;w|}>HO;=$ZgNAwmYa%zUE#LL(DN9&^-FcT1**Tqh}|rs3i)qqEm>h!)#JA zu^*HdK?2o8L2MvZ=FplnHU5;vFyK&-88Xlrp%pT_W_17l6(<$^$7Zu6!9SYNIE0^Ku(Tq_Ae0^nzW z`Y9n@>b9eWfgryn`xKR_41mwsi1kvK_okH05-pwZ{HL(-T@Xq+Xu{t{?Gadpy28am z`#7PVI%Ww*kFN09P{K}y*_>7;#RivX0W;TiB*`EoR)p;pz_2=ac={3JZN|$(0nb2J8laY@Sh59G}=IHbcHEg_&nl-y^K6}Icm&4 z8M4{ZVJdo*S##qN?zuw~!}f}xx5%z?6<|hTruy9M55NTBd2t2;iA1hb8g4~EwB+OF z5CM(}N_q&V9&j#Anu>luI~CCHD)`-g{ffk1xXq1Sfq$bOyutHwQ9ci$OWFW2d+?lB zZ-$`9%c7ebp?XR#|E}fJoOAVoxMg8Ijn{WS{jsdvl-=oTyZ1M0ZT>?6Fi{JfPgn7H z!@PimkAlS4DL(5pr~&_TNi_^O(i{6N5Q$oHY9{uic|HUXX5tDlB3D!5kI{k}xKXq& z7`n|KTM7cwl8~QQqyTW0ZU#Lo&#Necm{vAIBop;>gc;7s%>vMsmyDEV|tNZ1=;9sISZ83C~@g1EO!9>gZ%x8$;2@ z-V?974!=y@vDD#tNw_-1$YJzpqUYt$?`OkViHPju;DQQ3ajN81wB5OUcCnMj61KUK z=1XXwhzHY(;ahboAETp{?8f90a+0SFy<5fK8;%8p6L^uS#onL_BTS*ucaq2~r~?p3 z>K-SG`Z_Vl)(8fNB6}QhJqctjLI$dU_7-H-4 z=%Q#&x)3`6hXd_<`7XtLa}!7vC4{4gcgGrnpFxMjm}viFz`)##9%L%^$V~;VwI`KU zADF^-8|j~@#dFVSg-&LZloFFxaS3RTdEnzgk*JJIHIdn>D~>t#Ozd}d`53Y5yuI~+ zWTWMEZC<|AtFf`6dAqsfY@(Dzs(HYpl0Wn(U&1cJj!pLnV44(z0|c`348iWqxF;OK zTioA6@^~-ka!d=Vut(?X%7sUZm9p78;Q~C2o5sOFwn&2uM^pcR73>82DIHoh6G&$z z#o5hb1wa0imu4w53?Knw$iC{LB$2I#3 zwW9w-I2k7GLOFq*#}Fa-)*K{Pp{^=&RB>@6iU;ifE6L`O`=!!gP@4Equs>9X=X`66 zMC;K^m0-6=sFl_zEGiFFQX2z&;sY27m;j|~iHaa=4Sn%mzz6yv<>cg@Q97O9R~ z+YUgi<4s$?{+89TiOJ^;NA$yuRP=!C+pzIM7dlnR{dYxhd=}Y!ZynFcuWeK8vH{y& z3^l_vFkpOOx|nl7W=d!`&1GiYnW6&47J^tGi~Hv3oL@z_1fEBSzr85J*C`dK&!CH) zHZcu){^4l;zq_*;20bNnP9MJ0Xj9V_;pv9JT4HM?U_}Cl`Kx_hr`KL|CqX5V(l5qs zRoom>zJzeAO(Ro`xFJNXc6^oz38cU#oNhFV7auiF5!?nc%of?9fDS>or+d0zD5fE9MXApT6!xQ2#AH z7LVBniNYxKeJ8?s*A<(E+4l3T04kj~opGEM7vrBom0G%hM)VeWh%;C;CqCs7YU`zo z_Pb6(lDI>B7471u>gAto`hvSjTw`^?`RVmPq*-reHe1#DsdT=$cu@R+OW5zMQlP!& zprpM6)r1adh7BE*zQE+r={9nIA`;>{85gpV03D+JqJ$l6ItQi*mx%!2;d@}NGDUj2 z)B#=C1XX63fnHxO z4HU_X|1V7E@^c{6EI>+?8<(ZoIGw2Lj8OXd6d4of9cM4KpPSVe(Mi)oo|V^!gH+7-y2xj+9X9>#g{o zjuwI9543(Q9o)8P?y#zqAAhsV7^LcgV0Wi)pZA&=D3D-&-LFyn)HY+PKZZH(VI`Rc zD~@(b32d_$1t!dZM~YOLMA=0v@A=n}%}ENnc2Fm{;`_KD2@8oSPi=xSJdztEI3xyy zXYN<C7{L91^JyS~~7EP=fX zcB!JTe88b0#sbN;2+-Vq2Ih=Su$nR%N_3eG(|c}f{MRu-g^xoo9JoK`>>P8ed&%M5 z_3>D>;!Gv+Wk{j=B!QkSJ_16)2`pauuFGchi{BQSyU{DXJ%c>xJP-bLmV|9L(F{U~ zpWnA+zZH@q`i(#@F_3cM*e5Ll*UA_$B!0PrtMor8=?~EK^>YYV`_WOK7acuQa~({%>_OT(_>4 zIb@)FInoL+%K{b@UD(kPsSl=7K;)0vQPS?Ou@?@efMS@I%tmUV_mzqJiLBB+OnbK( z!Y4hyK6MndiP&KIqn6tCV#u{*)A~|9=cSskE8pG_-4#I!XDM zjdxgzA%ae$Q!V1tm*|KMfg<0r2LBK%-Lw<3&E9RoLIf!#9pd1_~ z4^xPSV*P>}UcTjcexmNRP+Jdd;_WkaP*Pk}kc&5$f!@Ad;R5Z~8Da>6C)Sk2eys<~ zZQ{|(1)*a*m4(wihePgx`PXCX!D6{l%?O*hRLkr8WuGtu42@0TT=hfJx$(g(Mf+2g zH|+$Ua~Yv)(0qASfMFBP&8)zsPkL1Npj{A-&M1i#w$POzgP4bfSmc}V&Xn2$PN;8@p6|#yM6vM?Maav^!Y$9{&+Mt^- zg6M*nDu6S5K0iOe=j^j9Bf{Q~SLA8}fYXe}a6mY3G(45n zjyBgB(SwqhqazqfgV-c$dFAY&(T~+{{sc7k63lTI&Ic-X~EzWGbbifRW zbvc@W{tgFhAMWG;O5@~!v9m-^!BNFq)2nO0Vi9f{0QktO&DhTFkPj}YSAF$jq$?tVNIiyh#)$9j?7 zD0SXQ)d}>Mfom`XTS1No2&@Nyoj{)zw+j7MNBVZrjk_A=TuA+z^eo~5qBo!SU1X*~ zy_ZNxuuNCdqXpIKFTtwjNgW~l&t4P(cNqLdipOiRy5EVZh{%Kd`TOma)FhQSYM4=E zL!45!)HA7{slXyxR{e=QOe8%T!`4hmjFV!&FyfNYk^Vhj-O5g}rHp$m2B`CAGkphH zP=t%A@eJ()$0TMj#fXLwVZHbRxT$&>=#ur)6oOIU=Ll~W`g@IxuCF-$xzD7zpQXD+?!Cr1Sr36+IET&Q?(y~wJhh%>md ze7>lDzvxwYun{AB9NBNow^*owdvMQ~WX{iKZ-}DaoN(me1C)NWE3g4~_Ut5SKVs6> z_%{)pc8GEoGW`4V%L%_^syj3=|>2~uYJHKm05Y8@k0{w zmdXX%$jv)=Hg6HV@O9%rF!!y2TWpkghH$z#O{0EtIdJxSzRqOAUNPsHp?M&jdK%2TURy@za_tc5re&&sqRi z?gNb-MGS0@@r;yR@L`>_V|heoqU4e{?9_IEE{ei{ZzxfO=$U|6{n=-G;UFA_91+l>0WnNt>ep}c^Urq6`iJo zt%jHCKK;2r8^tvu?y0K97ZJ_bz$bpI8Me;BjhccOPeIN=TP0tx@LRdqKi0JQU))zY ztc~}?*uoiB9`F|60kSY>98f;WPk@r4VGp?1a1aI`aF>fsZ!%D3!8=oErcjn|F3hT0 zDIu?rwOOs9_;HBx<^V*oB6ErMhHeG(%Zug)9GCe3Mtze zl1)M00)nzwjn^`j${ul|FJ2K`IuS~(bIc*00{mW;Jjl?9McMkyIV14F0+o!S3CYMe|y*SU3(;;$g)f2IC^ic9?5X#U&Fpr8D_BbA>j;( zBv{TKBesQU?CgL?VzN{=p5txiHrqXQ>)EzI&Zr^clLWK_wjaZvqIl4VJ)YXT*N#reZuzC;J-uqsQc zC9rDQ>#se8v}c?11KVly=iFzS+*4}Gx`U{JuK^E=_nB-&>o*x>TysPez}L${F@BNZiUPEms2D22Ofa5rw`kBLt1$8WaQQx> zA0bf8*z*LX>hN{^Q((`-;-stD6WZLv)k?!En-h)E!>ii8FYSBph;Z;n1F1|;pRos* zzm(rulyf>VN#BR>0%Nz!#1&#%}`C33z;_b%?(3dp1g z{7IZ1SL3XMOnH=a6Dj6-PE!>sjt=sd-Id>x1g6}t4BEH8ackA{7;g(`)pYyk+w?HS zZue~)sQa>Dgt7k z)4P)iR{VP(@}2(8i8VP_ty8kZ9WUy>{rl=&aqIh%aZF$j%Jtv72K&YQrHsYw*yw*@ znXS&2t2_*Lp6i!~2>%w_u?sudA6`T+R23||YQ-H_0XeM#=JFP>eO8fDXaVoXz}m&g zo*DVwkJkNBryn~S{bt)DhUQw$y9KkBTFrY~`3wz*S9aC$<#ahdK;~)mTOeDs{-uad`kx! z$JbXB6+(WDFQTrl+B?8i`k?vQ#6YW6Q19B+wf*Kr7Nq<-`1N%*S@m0)kSDs zpj${`K9ljmdvW@bw}G_?H&ZHI=LUsy4=K z5x#txp_;nJ4e~O&xsE@VmR|{S&AR|dmCcZw>nhzFF;~~glsJv94@IZz`mD*(ZPaq_ z&puhh1LMf9$6pi~*qjc4khl%UH|CtJGCo%~^>bH9{@8xf8t(1|06F&T9q!hU&K~P3nH{#?|;aGRYuspYaw4wz;dwhw@+Z_t}onn@374 zKYgbe7`A4ZzisDwU6PBiUfwJ5`-UKX+fvvs==-+a`sGdaXC!_l*lGP*3-_*~m~r~% zipbtSIF<(Y`q_FQgXZA+rjQG-T}E%QYXSK9XM-+VQ>FspNG zi`sL{DRgu`bbp)fCo$-!UfQt#$0>U0+~oJV>Q5%b zf&s@vHKC$U6X7xX(rY(=rzm`hwEAh#`uh#>=g9_N!sO3I9IrXmtmU*tq{awFzV0qG zcXIoe+@oLnkmF*bC9@;eyrO#c$=HxvvzOTZtQ7nnu$79~`8}Zbd06OAO|{^t&_Ba9 znHT5&odmI!V7XAoZ1leWmTCW}LZ_?xr|V(=L~59HjD$Y_cRFqR*L>>W#*<$=`n019 zwBuW}V;VaRFb>B}0sFR8ToN5C+NjKK#US8aOHZ3{VvwPDp+O`su&tcuH zP~5uOsNCVRMX9{N=}Sj|22|ZT;8;A9lL+^39i2ag@;hzX-8at3J&CpQ2h}oiAPD@< z+fL2St=@wb&R<>Hyn1fZ3ApUIJqc{xz*m+M9BY+@pog0?)jfG+IPgL=tZlIN#=p~l z=JVB9D8TQ$&g}O2tlFLl(^Nk7K(rjIFEdo-{?tBA&sI~--ezy31}QCt`C~=f*pF^!ZXsC?#CGjJBEeU3fWWTiSqCeI0>W1ALmL9@L3FHsZ83QX1TBGz@KpE`q7@ zAonN34_tWwLdL&$U)xPbD1 z&I~_am7;8=l=d>Guk!RYWB;e2fT!c{^;ilT*`4d2+Gu|tc&f>B7|w3ON3k;hFMh#% zRa<(=h^ua53Lqtgne?-n|HAxDdm_O(*dZlNQL34aKsdD;%CoUJ3!mc~!#X?Ps#1K; z#M(Xe+&Q>jRa~Rsjf$(+_0K;hbpO6m7}_CJym?@Ylp^jf7^v-Tc zBhdL%{npzgzj3?3a?T#tiNt?{n!$Gy=zb0Q&{!_D-2~6Z7qqWIJ=f;@yZ?T9m0`Rm5P&BS)z;bO%{1tL6Q$c9sI7MDwb(kWx*n-N zL*Jtv^Kt3&*mIW3!*eCWdK%MfyYd@5|K-X5Ai3P?Nj#iPlZhdw3VPP>{mO?iT_Z6F zY22%R?K2`PD}lZ;l=q+0zkwt6Q0hon-^-5|&91dYd)X4$oW_o0k{iCYvL^A$W&R=< z=p9{~O4fG#WJh1B^K+a|P-D|G_I?`PdYTTc3y{GbkM)nGave%%c$hUY;up-;x$-$U z7m%?}j<=@LB@0NYQjHB_YLCVFPZ$~WHH>8rWKs4&Rp#g?zy;|H zt_NM#S2@T9OpKNoNq14s4JcqoN|V=oZ*3eISs3z*O}hHG<=y%N-8UVhvi_PjF~_s_ z9Jc~DHW}@}u%a@WQHXw#J71zpeR)rLuz~pK_$38#Iog@M)uCyhTm8Kfs+6T+-Z5eB zM}z1BvEFB}rv3c*XJjs;f%az2o4fC$N?OMx<@iQzOJ$0S-groJLozE!2I6Is+99?j zi#A{>&IfRDf=W%7Q?t$E`@+g^4AeZF+YY|gg6(t7Ol7d(F+UK423f57_iWqfZm}Hz zfUzRx&o;&y%tNG{kGf``9sjsyc-PEc`=VX-pSSJWo|{$&S|w@UF!$3^Tf7*3#y?{M z9u^E<&ggxQdMp}Mm^Z};v3dNuJE-(*D{aE7Da<RBPUB~l5P9KWM zLal;S(+loxTVl7|YIWqDYnE~-9@&y1nbpUE>{lbQK6p@9kDKRPcJKddOjB4LWWAee3?%xYPOUtLla5G)v2+gJ&eO&RwOq(q6aV zZr%GOqr|P!^M4HLyCzw)h;Ku=SDASJbLwe}VtKN}eEpZqCoh}WVVMrg_-Wqg&i1ss zPg|nN+(4r6Zpv@f3-4_Pdq-K@Gym0JSa}DDm)5&*D-cz(9J&7d^IAk|;H!yW%H?;b z#j|`GAF9yLmvz~vZaRsf)}a6Squ%A;#`YHEGR_8?;@<7+tF-tgg=>s!^{z%4SxuPt zCEG{P(PyTeY;fP1!%=WiZ6P}ri>qamC;Z{MET#VD6Ha%Xxs+3BUp-A;mUQUBY2i7j z@xX3es^Dk4G<(SSn|rxM`irsjiiy6g;Xa1EIn;i^11f_%4bT1VY!))R`=0%mrqQv1 zC;pu~B@TH-=(VX-(X#flVZt8(EEeG6ieQPhN}Y%4byP@(PJik69rS)823DgIY+(?n z|5@rh2u;rJJm&v+{`Z!wzCH3mNzBlro(CmgJvYU~uD_bU8rqbW!)lE+V9%KvkgK-8 zQrpb+;kP*9+)o`hfYv#;eZ^FBXrDDaJ9%Zpgh$!){x}!x#7MWx!PYrY$+nZZppj1q^NFN z%M7+4lZP?vJCYZmOK$V1anc}|Bs?`@n`aX|M3af zjybd(LQ!)bQOKEU=6uXKr!>cqBvh1Y&WBV;rBcl)ha{x(>09~v{R{WwzVG*azpm@` zeCk`D1u>WqWMuef@otFWgqgnu#On^_Ory(_{w3SeIuYz(oNya6?FhbBBt|MZDd0H> zUqyNIraJabZuyVTv8Vo|=Ut2J*Z%lfQ2>x8>2P|~=hu8-@t2M44)$^RpeQcijbfd| zhia6?hoyxLF$CC2#(u*HqzO{lmYz(El2N61Cu2sL{rMRIFG(Z$84z5O#w671y)t6g zD6I!N30Z%7%o0A!QZ-l$jE!m$gfa&Myy|K;7Rp@uJ#375CP`Eg%Fs@ z>;FsfMi?k)Sgf|B$E+5^>9@uQ#2($uI`ltkkFk-CI}?rt&v)LU_GXFr)qCxvYOwny z2hHZ{_Cc07gX75rv0@_1PxhV+T!%x-9PKgPOFkk6LB}#1eL)2JE&3#{1U4;lwPtLJ z-{cQQH9_msQ>IluPh8j$6&lPS1RhF&VfUadHt-+@^y`--Uv}HpQ!VX~_NAvCZA{bX z1N`p`vDr(8rv7HURvA`VfP_GzgR)O?5 zxY_NuMEN2>da1nNGwR@!9!P_^mcatB>1AERrGdN>On38cFbh(aMKEJbM{O1f@-CS(h2kizH6PI9KhJ(Ym+e*8dARs;?DDFJYx^;Agd7>T6rf*@t0yu-)0YG}vtYs0YjD^X!B3PoHge*yK1J$=x*=vVR1T()zCw zdw8xs9Fcac8*;`5?u4P1n=;{}fY9i{X=YnaWy(#aOhcahSyYN@x>t_sx>jXPi?o}n z;qw4QgA+$c_b!P zY3mV~$-39|0G3Tisvz8(7?Z6u{q+=Z0tT96;b#c8bEla4DU`4pzIzuQz7gnfJe0oP z3dET_d%%)Qi`1*}Pz^zfX6_|RQIDBOJ2W|&-->+{h(n5zZXa^(Sq(N*FikBoVOp_o zHvMt<{?_56C%^5e(;q&^`Hg}5tF-Mx48l*}ox?8Dy>&0}Pg$a}*P^H)vA|y9}FMwu`p4xvpcGhlb9dDVRArNM*;@tjh zB3S{jyKx~$w=C6-a6l6!FbmTqEhoIZH6p`~h+$lS6g|j*<=NEq#EnC!L)l9DZSu<4 z8{m72mQFJhhY!kW6f=E{^H8{r84#uo`|G6sZhHJ=cAVF3oUEf>=!@myIugG_VWaspzS3Q-fA{JdEC&<0F;=mam;_WGStG!E24 z-ITQMS!PfFK6>Mr*#iOP7Qu#BdLOR-l}gW`?=$z_-*(g+ZvxVfNhM=eizV@<*w{fw z0?ak`;B92zoH5;S@oCS6I|3xj?*F~6dwKf^!*FTPLFt3RfM%zq??JWMZCc3$0cmuE zz-96?Fzz;W!On{^s!tyA-<@_({L7Aa70TIhc>b*Q%otYG;|VHLo6-Epw8^U3tLL>k zoUmmE-2$sLIjHPGN0mJ51dPG4X{Kz73T!5^qw~<23eQsX%ctk1 z(xcsJ;7;onLCu@XLp?pO-aUm>KjW*f+;54POglE3tib_EqD~00K`Px~0t0#y<6=hr zXxgjj(sUhhX&sq}1edZKCWaGUSW=bw!)T;1heOEdS(r^#O_U}ojMbmizc9I*t z+u>}79l!C}ZhgT0)hW+BrL%J&eUasoEX!At3m4N^osS(csg@hXd~^`J)L4uT)@k<$ zWs`sSo5tqXTQLlI_Pi^mof2s9#|6BHQpcAM>41?I2jGeCAvUK=vLYv84$NeQ)g(C% zNCHT5ZcI`bg}gR#UErtw`>?OIe~TdC0RJ_Rc6jkr4ew|ZJv~W)=j0yLk_0)3L@WJR zZjVhxEaBm1GhUdqVsI0d2%`L9Zx+SD1o~oSbQ82kJd-9QGn1*UoIv_HD*nF zTAos8ckjGAFr7t`uE1hb?@~@1IzyvYC7 zGtSvjCjCeg@Gs})lafp@c4z|%y4IQYvE;qJskUPPiiZ^N>)tEd9oTzQ=KB;^pPPQ6 z85t0F=Y-vTasnq!7jwSy<|A0(R=EZfb8sq-hmJwMKo4p>&x#_QV40)7d zFAUz56%V8xhJnmSq&o`#pTy25^>IUDt|y;|?Vx%|!8Se?_Kjv+J_?xAQo5~@HEh5t zSa7yk|CC-xLE3z{e_+nN9rT(^-duJ}20~bF-J^k@Q40^7gmp)I;F-y$tGjNKJYLD^ z5hVEKM5(ZtudlVg$C!T4DgJujVm2J>i{%;{3Vug*rJoODp3_O|O8BArO(_V6B#cJ9 z%=yurN5NuQ3WNxrBTT+gAmJA{W}@H9XzkJWF|7@JBvvPr4Z{Kflj$SU7}b zzz0-5^@QmhP}U9og%0<2>e9~a5*uRnQh=+xXatz@jr3%2osZP3G}`HQ^;Nt1&pUGP z{U*TSs45wrMlXYzTuL#mhMllGk)QmNq5AIiq4ds2EKifzz*_~PFX!S;o7ZF_s)*yx z)3D(#Gr#R9?^`_;i^**_LXP|HXehoJ_$-_ezzlr;x#Q{u%tg~!3zMd;a6E2Ta)PP5 z1<_eeI`TZ(Ew*9%Pwdx^hONQ>J_-D%>u}+hQe(<+eNR9AxoR-j<`G8rCu6hAhs%V} znPvBfANdb(-(=4Dx^L|Io{+R6Oe%f8(b%wWVRL@r`ePp?fN(PytdW@ zKlkT$Ab^s5Vs#2TTc<%u*A7+h>c4gbo}xz^oLqdKCES;UG{M!L057XE{=61ZdDq4G zs@toG&opFR)^llUXEsm5FbveT-sk5xd^c3|B3DH>tjp!DCm~vzm3{6Op6O7g-=cuT zmeG!<`KPp4&c^Z)X)!AxCIpV0i&Ebu=Rb+rWcT#I!UfrUbS{s74rJyYXd$OdR2Bis~Ky~UzN-4r)nX95ql zOt*tAyYSp577bP>?v_e{JmZvo+X6OYf{?8X&@mQE__I;@8i^{Vir5;9Sx4+ z4$+faejNh(1b-b5A5k7DGFzVnIFQ*Yn0lFP-*FP?LA!rTMoH45Wxd@(zG_Zr-VMzX z-(u>!=Kt0oe)IToXH4f{>xYQz3l_BDUgl9)J>DnjTAHVD%M53ABVYdAmY;wqUN1WQi-1Y|4{A>Q6yWbRaRs4H|Jk-d0$kGgVO!i}amNyv!_kl!8L8_y;&`?o z-$JkT8}(Bpj3W+_RdOEPxt1VMLeR?HwwBXPmO)@B<=5?&{pe!Ww|vfCAuw zLWEh|g$cD>j;@uc@Jz-jnC4c^)2WrbYf`7SVvomo28;cfbccDaJh-fFrsxu8_UeJw zhxo#?b=emy-9T_Ww)w`nRIfkCu4z$gW;h%Z({MtlaJokF)6NauRsd0-p}4z|kq9Wj|VP=91Y(Uat!OcMNxNA{L`0h2GIZsbVj~eK>y^7QQVIWK**hxJ7=98UJQ}SVw0;IDX1#K zO*4z{BKhWpT?}15JE7+Nk%~xtDP&eku(dq`Rl_J7AWX~U|cqDNPDvM$kAs` z>fBrZ8kW!_9_Ykz@twV_F>+)mlMlk46uD`l2!uQyd<6pct%7>kDD zv!C=WKZ}I0(|Bhr>g=ox4g#Yw7>!F3z7acY^f*ZO5eA?u4DVV3-P`ty-9Lfr=ZI$a0sz=GbO?6v*>fH%Ye$oD!kQ zx3cYY?>)>od)GUcj#8AGZXd=~*9eBO7aQ3-HqWYLYAx66ty`eVmzu1E31K&*X|nu` z+uT<|g$kMCd&%0|{2K>Ugwv_hdOcyZYiuS*a>rl1hA(c^;+1PbHZjLq56mR)_lk!* zNTsl|O=MsMvCuz)) z#XqqZ?YN*E({@0|Pi`bX%Fg1W)8PHFUIev1yi)YEeU6f-v-C~gf_ube@%juG*n|z> zO22>Wa@mj?N;hrA>nMJbtkYGe|B>PR@ZIX8mH2O2y8Q7xZh4y!QndOsX7y3gLiC z23o+JpQvX#1Fg-#3%U_r<0YbIkJY1XTT9z=Xpr!yFB;ZL>1SPob|Njr3*zh3@!^I@ zRLq^=wjY+O53pkAr{q=-1U-7(Tastf@$dqK@;6QhdMime#XN_)heQRmM$iR=)ByF( zdCMd9vJstl5M!HJ{WX*KGTmxv{kTvF(O0SkGo-4w&+CMu9&$V2Dm>^=eYHhq%)I~l zqvO}9`sVZM>H2L6=q3Icws(lN{aRaqZe$HgzV*dcf9X6oJA4u>sKq+X0@0wcxT$x~ z;bUFbb^fl2A>Z@*(gzPkmuWOCiXSb%%{xicHC?>QG}$lzTlH3sawTjMx8>jtr&fU=J=U z&>MM`=ctX<*PM6a?w~uL?r}NJK^cxsl=NOX_cADGm69IDNn0i#c!Vyvaulmr%XnEL z1Kh!6mLQp}YA;;o$R`@oGlxp#ldi=pIsLTFqY?*P46aAg9FjTLQ~;NEeSPeUN25pc zjtW5E-a>&ADYVfn3CjaXxwL)I)AwlLFdD)kLk)XbcT%c&!vHT$PArB5+klDf^=YyP z2-sAiAgCc~cJ0>5b&sdg!zsxda>DZT;r;eAPnjeG<5A6t!^T6rGPI&?K^U5meE+|< ziBs8e?k*rrW~Z9`506v3cNH{;6*%tKFJtY+g0K4^p+x9_6iQ+uzn?vna^_Agr`;hF zk*W@O6`EPQl>r94uX@;!sxt9+@}$4T3lJt#r^m{$AEYLbY=~#^F4=nD$?UhSwZyWK z4JeV+`OC3VMgFAUTs!+Is_v+l@wl*%XPP?N=m~DJ&(8Y%hv40Rd^@ z5@Z>wy3(wPB0XLlYla9$jPK&0Y!pYc_?RNyO1KzOBs-!%V;@Y*F~E+2Bf*(C2pn~6 zB$n(v_P#vvgQsqdsmVNbzx`k+!y38;JLn{t01!0B?!z4Uh9`|`Lru@mZ2OA7t;>AP zuB+n;1(QGq{uVS0M>dga)-<52WC_!(<{9RPa5;yO!Zyo&s$^bW<0^~plZu-%pjBC5 z_bLlFXbOyjG2%gJ_sT@pF)&kQGFb;}3qp}~iw6|Dp8h2c9nJwAw-}ctE*Fh1>^`au zh;9u04cGdauC-YYdFETQMCKuig4s#h#Z*&d8o5_ll4qioWS8phA4nLDiKW%JT3KQF zUGn+GV$YnNl*FNvb@2VL0FtrOn96p!2W!ObRk^ST=}Og%i5^#L2QJ(5OsZYVL3|L0 zOH$J&@$5sB6wp*$OX^$O0oB+(Fx1k{>LjSgVm@E=+~;C5#y|{?9AL80-e7@5GIi>q zhs$i*mO+nb_KF-~2qHytcJy%XHEp`1^CS?E$c9RcFSILccD;=bK4aZFW;MCuTJhOv zt8ZJ2BipNTDrNMri_)L%?Br1g9tH$)R0hNtD4U_0=6I; z)%Zd2AnPG=s?jg1J>MF6e!lS53bacy>9Xf(buYivxD?h{qta5_Va?bXVT_A?-2VzC zCW6J#XAWAr3If+N4MrWtRCIslS?BNrWtKIKsg7(}1e2OALNXD!O4~}MaXGjN@Q7xr zWb8?M_W?y5NRar<$&VybtXM9q5cD|3q@y}o;>)E-Ro+|a?>La_{*po|Vg}bH`3fy; zA6HxcdtuPyz|+*yk!EKsmHxj5{!^0!k@FVD>=pw}Ik?NHDkhs3HDId^6Km?11;HZ| zg>f~*AS_xwis8s&bnl1}6G!Y)ngIXTomT{4k24;FLlc~@JF&upZ*-J_U`71()4ku36)=Jh!Yt5#G+ThnO z5!Z>wr((-=ha$y{vlJeUg#_m&uCSQFuu6BTjaBp#j4k^wmC7{1#-0_8c&Q9+cf}pvM^knT2 zsr#ONYP~8IbLAV)H?Qe_%0~hE^`ju&lv~*A&v!z_?xZ^54it2$jyBY&GE(`RKMlzr zRi3IH!e4>~8{#PsbI5M?uFXiMZbp^G?_Ud>-j+z zM>U@4e>vB8N+O4fUj$XVQ#U>;j#3}CXR5KR55%8^5+JeIB=A7eR2dm*>42yFPdJgb0>J#xtfb zQbd*e{^7)D@cdg@Uz-!PkivIn3vXR2(~9kTThcqAiwFNSg!N!Z-*-u(doVPfrA{1( zS08Cp9^8oE7HK|jA_@=_KYa?wa3mG;ZX8=8Ku>7_xUhpL;KSe_&|w=7XCffjRi$u1 z*kn=(IRk33eZ~Ioq++Eu$k(GJax;!Y2lse3 zeX{?C$s{!gVi89+Rq7Bn7~DWHpYt?EwH>u{r$!x+wdsC5)sm?Z_=+TfJ92B4s(X1O6^o*req{Xz5&O{uMoHU1;;CV{0PY(-F>zn*V zy+4#y^;3!c3-Nuru_A~;%dk*eSRyq~G@OT5*ZOi-jZF9@On6-C4ed(YLevxXk)-e!zn%WMb5rI6F!8BcvzKsrod%~;=O#YN1IR`=&*LB49{cCTFG#N=- z@YBEYK|h&_kGW7<29<3F!`=&gBI}(t;^E)DR$nmTHAym!J#KP?hkcQygBn=oT_R8O zw0nZYl*qydtcLc3&ivfNNkNFcr6J!?M7R~tr|&%PHGd#dD~6+d2ngDr)@ueQKE?KF z{?Tx8-HB)%TqUsQt;L`H`N9r!hgKsW?NM3%S;Bj4ln-+AP9tE8j%d z%YeG5#>@d6V#y<%1LjOJI(fkarpq@`op5H#1IH6@nS1ue87e6bto_#nsr0XB^X~WMo#(C7r=jhEK-%89;--8DAdsxX?v) z+YjSRigUyT)>doKGK_=z<;jd*hQnQ|37cw6gsAnNKTFU8lt8ThyLR}P^Yh==)n4j? zIiXHQ$6^P!(x|^zKU6cBf_9@W0%0(0KVcN2p96Bz;~Y+;+Q>-Mh#FT$wyCe&m-@|r z@C@DkazEbdx;by$TX{#RfTu?8$=dm>jt}!W^{+gtAD+W>+%3IB>)ol16ZA-V(di*} zN|s5bTI;fxUU-rf_sGcNWeED0>HV=a=7vk;Sm%oo1xSIXghhTrr&$gpz=g>`GV5G# z7JWm2hzECZSL>A*K4G>ltX?ymGwEUFDE|vx%)ysJAkB}X$gVI+q#!X34f{$-x<=`l zS+~=(u6YGLG+K%4%FusHKoq%>+?xeW=XI#~G<}snO7D{AFo2c~B$xwgxNEy|65={! z4B_CP1hHn%9+0)k?Gk@3_yfV1(B`6kmr=e8b=5qVgMOj!`ihv8wWrSE0K`j(MU?X4 zIV-Jal87ZTZn9r?ZynT5k~?5?v%QY~d}M|ics~0L>z2ToGx~h~U)&9=egD3%YDY`4n!oit5qS1> zVxIVZM8|4`YW5^H1rJSC_qvqmV)dd~?Qwnq)zp}T{sLlR5Ij&`xvibG$_Iflg=GY0 zzK>;!*a(sxc!e~Qhwe+lAo2j~E2_q&Hv#5=5%`DWaItYwfJ3EGPz2gYB=1o!A?agR z;O%On7@${t=yyTg82ebw$9iifkKI*VU4Vb^dCycZX4OEUDU+!Ug#laS8{1-HG8j4c z;#L0|utPAFqd?`T#!jiz>qq;QG3P%$x!zBVmWd5t94SzBdt4QF zp*)Ul9peamO{VMI2!y|jWW;>?@a5G7K9`RVqnC&8Ca)a7_#ph-ONV>LUDc9Z?~VrF z58QJM2+|p;dvQ|(SjuBY*z_oL9ry;BNxkYV7+!+;ozK_)sel0xFgaas`jH;I!~_>& zIJgl6Ed{sHRm4j?aJDuvt^d5m8Z9@Ps6YUlvD=oPN~Z&?31NqB_tdQRPzJ(x7MtV< ze=47GqEXw~)ES>vHiGc48zLy9=a;VyD4B{VgDEm&){?@W&B_v&H*yuD5aTw)l|hI~ zn?mBwxo3oMg>gANU%TVvn&EH10o{$HoqZsL@Y~M<$YMaBf5-xYWxvXH5yi|Mzro0AUkyXV^1^x3bP2`C@c=@a1Q$1YyxeGDV$> zvC39Q+78299)k09RV>$qu9og}q9+)%m1Cqatr(N}41Ko`QEx-vczvubdfv0%Hn9F7 zsz*_s7{6CCawe{yKX!JjB5Uor_i+~QQQ#kyVEp@?bOz**?*gI{28<%ASr>mJ%B;EA zevck0ws+1EbMFAHD`jI`S0NA`^yH9+BFRGZyybDrQ(u)OiRKcTn0wdDDjlwNJ4*lh zSTU#phXd@4D*>N1eZfq);rGpbJ%B}9=jOF{d={2KQUobkd`*~%o=LfPHu?3+WAnvx zy}@f=5zIhqY}glRVVQYU!%CHHyxNa~yen0Le1aF{0YRam)XZX8exDyjZfV9= z6?B{bAVO%p+4h;Mwv8Dea~AWUE*z{S;N~S=8QfUIz4MzHZcdC)Gy@$75{}Ul=wEww zDEuHKryg-INLgD|y)o##vJHD3F}wBko8?vNW}onxKif4~k`LBaQ;QN4i~c_U`wglc z`#2X0KZpV|mAU1QUcoB?R~0AID`oY^ua)|HN%pI+J^}f^&;_5ds}JB)6gx+ z5@c?Zg-FhrOEizvlYP)Sb%F*xEL4~tKig*Pe0(TP;fC2}I8@HpM(~@Jjb%TA*|POOZGxRm`5TpypuEto$)7JIwjzT*sbD6zjHWQC*)A->>%J zUa+q{+g;|Os3e+Atr{X@LG=H4!Ci~tnq_pr^v}s5 zf}SxzU#uSNI{WOL2lL@($?c05vviVzu4(-)xq4{Z($l3$cDr{Vn4dPzK>!VW7RRpr zw?8fUCuLc6?QL?bKZGgy`ny$CerK`)S@p%%kZjpT2Cs~W7Wzg%oMrLt?yvQiY8G#& zmoiqQPZ#7|&m!la5xwP8u$y6$ScA}EVj$wN07Ndh033#~XY`Q`vQG_ZeAKRsu4}OU z?VLnM(Tsl=p1l(MzOBK26O>}Q_KEJ4Q{qCB{YguI#ol^w_Jk<9k2a(#6V7+CcR_q) z&&ou-k{0CmR3U52c_YG5%x*I)HS8K6iVyb;d^{IeYnK7bnI3xE5$bwna!8-1nHy+B zRdf3)(f@nqde7^Ub_2sQt(X43vfpB_GOxMe;7@(E`=+_};cTa&JBfiqRLA`MB&SJ`1mU`s@vLHCSaEG0h(3Lk&}Mab+xF7&2R zTIKcZ6vVydR8!>H)PEK1KTQ2%59E@NXKr8&ce~s4#aOV4WyBGPtAE0hPyplM1todn zD_-B7F#ostwweFKZ9{#jG(_kn36)0ORwwKw(YtIqesP!YzqXGrHSYJxZa)04+j#9} zSNGM|T`fe+VB|gc;Yo@^xZ^Swvn3Nj2MaxMkpw0jG`*ci=Q^?wq_B{K(teYVT zRSYmzFk{avFLp1uS1hV!O|ctdvuFyP)W0I18Qn3&5Hie^N51cg$b`;TTvkq za8f|g%N&&_?Le-hN+oZXwLJRzU(WnU;pQaXv#Xm1_@?m$gN#|DSHRZ*&f~&)0Z0ryilX&0`3nMT&LJlHU3Y# zI!qkWu0J@0NW#U+VKe)ckix)<=K?U09s!07qA4D1_0!%4qNKY(kt|Us1VQ5ABfr_J)QrZu9f=-Xh{JV=1;6vKDgg@59_(2aL zI^(l|4FZsDO@q`2fPV#p9CXE9r&KUBW2G?h?S`P}dhkEUmZ$m=PM-$Kk(LI7TH^TC zeAV#JZ)iFSJql^*7m!+1%F6@iMCerG!B!;FD$kTB)KZ}5wr|Un$XD;c2g1BPw|NZm zfz@Wf#@kyR5b_pqh`zGCZY3=kXgDnl6tZpZZ4X-szl7MiKB$Z<8!0Lw2p3Q7z&hU%FIp7Ooerc^ z+H%6;qwON_N`}!}RS0enf&L%rn59Z>K9VBN>X>y$N}oaA^$EicW`PuL{J<6nj}1a{ z7Y{E*Xs>l>uQ+K``F%H3I!LjPPEW|qCZ)?UI|P)v0nEzmj*%e)w8;$u*kD$^Lu>x8 zk9XuYcJ#hDJsNHL>4Vi=ftY6GQ>%mG-B%BAVd8rLwBJHcG;2+u?$W`gYN{IZ6fPE>YeOdMP z-eF3fFHrQ+4*0FNOi(CBCBqgL__|*b+Jmhpxs9cTr5QVB%SD^{qQ=D$=5NO29?NS# z*fcsXqVoBUoa(j`ax-{X$0){EeWL#cz~t4t`4rq%Wq(t1XhZXBpA7D^FrrcUxDVDw zUO()m{&ldvt&8?{gkdjT0WD~hbsL(#us950-|{*j`Vp4+%F*Mxy*r>RXTA3Y597b7 zAMLVu+u)1$rjnSlJb0-y6uD`#TZ*;9mw9QtyrnM`GPo3hxv0Nj*}l)lxHGfQfRe$)V#|dcW5Bm)%QC z6(4J&kZh6BvuZY(2mEFXZS%Z(yNlEht8Fpbg1)nH$;kS5!e*y)NstOJi+3i8{;yMR z4>z#6@})2f5VdA3eOuX(7f5i3(tNI{=&}=_AYF3d8s!e$re6NcSLN2mv)toGX~h;# zkb5~Rpuzy#pdac6NSi=!M41^OL zfA5*s2-#MzZlC`MG^Sg7hA?xvy-!1ei#i#ou!leL$3vQcrDn#Yf-vwo@IItw6;x_r zla}U_%Nn_B9&PwLPx}(DcCxSAsY!MIO}9=6agYzRnI3GNtKWSh)l-}>A+GOLtZ0)d zakE+Z+Tfy!PXndJ^y7SZ$BuNTuuAph&y8kvE%j1tr{}kydaqz%jy0J`pjEEe;Rg8m z?mUqsNQsv7|$i4O5o z4?*mMIMWg%HkWaqg>1(BYIIus(oJq=`M>Z>JupyrH==Y)W)x7MH17fSQST?bAe@NI zTe7V>Y25sEkhs`LnC-<6F=eIq2o*mscHTBM$LpBbD$HXoCc)6K6EL`qq6Ou!h-4nr za(_@sqbN!xFP!o+Iw-)`aZOiGtpF&7Ldz^d@A^cj#Tef{p}gI0naa{%tx-3bIt!VV z<5>iZ?}_FUucHj{EATU^oot=WlLGXaC6SaCS`#AuBUaVT2&e*i=A&Nm0fB(90tfm zhpD;LSj|VP2Aw!56#mjhC}PaDE_P3;)VTaHhykYf&T`g~elo-4@vH+nx3Hf=GYhS8-?22nr2UF}%X@tpmdv*E!Us<%EJ zqv+w5{Kccp&E&7UKj?>&bv96+lzW@5)uKoH`E-$Q?LI9Oo0l{d{D$_$$QpjKlT_}h z_uq}w3NMrYjLhSjj-h17H)H+=R;WTM^U|oqLH>sWlIu{{z50mxw>Y)nL1TW@=<$nGA{Mv~;VQ_YaFY2^J(y+xsqpof@jVgf7gY7x*{ z(KiY1vU#9X^Tx#M+xZ}Qd?8aQB&FqpxSU)cD0mkEXDIr8@wlg6og9u`szD^)KRqqk z9FD)uO?aI7E)lHZxK?R0TreNXxi-)(`vq(D-f$yAbI3N$Q_}7-ikOu zp|n0_g|$b^zH06Be6#sHD6-^ZkgT4LEGJ3gUTkDCv*PGm%QOX9PZbE_!lAVRxqES; zll=$(#r3{E{*U6+B2zH-Tob@^x-UR|xGxPsC0g0g&|;yrKg0yfBoGUHe#MV%bI&9` zAh1lHq+T=5dS{duKf5gL@H^pMMgA?19^ZAcm=qJ&{$HJ|EK{cIv8NPKNGT1}4rYK- z?OXb_Jh`JgN%Gykr@g6RoHy4h#v5zz^T9yN6~j|+KR)}>kVQU8;z*A6jtwM^pG_PI zI&mnhiih&`@M^`_g))t;_&6=`FNTXSy zb^nXoFMD8pZL~fW^pE?r@^N=YfAs03FW=bb3xf;~{#7LEqhFyORmNdiY(R?nqw1g8 zhb&U)-`M3tZ`D2-XFW2?d$bekL#xZ>iLWOq?F{{a9)ecbx0ne(s*^?Ptz3E(>;P67 z?+cbf@vX{Bt*#HqznFVkaaF!s?PAP+!KV+Ayxc>llXXw@5Lyzsu#e;4y&OU7!KnG= z57xsDT^S~MK-oNY+DgXhqgr&LA>L_zA#7Onm#Lqph!hhL;wrhX=uR>B>9yLGL?sh2 zy6Mb(wua4_{*NVRmOv~f3B1oIL(FLBa*}ut$$4f>o_-X+`wt)hn9-Z8pC-|NRJX2M zU)iso$I#fMy34y8NzfkL(v$d~FC*))Vgz-D7gf;)#~SiF^hv zGi9>8_DYyz;%GGGVf^1r;K1;F;tOw=Q3-P-n#_mBG)QQ@>vFO_y1Vo8EC|Y7sC@)M z37u%(K`8Y!WdI%z_?Ij8hj=WpC^|Uk-47dQZo95Gh{@E@4YqTDOK`?CW>O4qMy%*H zX1(6P<(R$mzm#iwfAd3c!pb=1Ek+m?M&$D=*Ai zF;FU@>KQNPd-~-jO9Id`_EC#y*h>CEicN8Yi)8<08=NXgMmZbw0 zATVzf0LsOY0mS}a5!BQXE)#V{?+I^OO_z<`pzP=m_LIcR7~#K$U66ZX@6%+L@-eZl2DX{TIkL;$#z7bvwrM^OZj0$Ab_ zuHNag`LjMxn*C3hWZ9eoiM7;QUeTrzB#R|)8b960Ittq2s0n~wElMVS$GpxY7xP^8 zzb%)8^Q{T`z6nBvwV$&av`Xa;>gujkUFAJL5k4Y!dE-vZry5ncxIk7;#CXtKJEno9 zI|6|0+fLLzeAdu4~3*$?}KSv=XR}R??4m}Xj-xEBm ze-3prL;gOkV5sJvT#LX>kLv*`LT7C?Jf%Tv7N6htdIY{vbup~{FVJG?-@tR(M$vW> zvV!ql$Sn3Fp~xU+X+;s`5tniQ0RMea zjU4H(^K7(S#i60+J`%Bv+Ztx0Qh;bOJ0vt4mqyOi0TD}w_qna*c7p|OaSm@4_T@+MS|uzfi<9$lj9Viw)t47pTL*1V zq>`@+<=^r2wh)UU z$Qi1nsv0~COXz>^nHB7I!}M?4#rq-Gs}tea#Lt~k!72W=WbmTU7H`+&u0ft|wgRgIkQ0r_^$u~kNU7u7zwb$w48sBlg)VD{-Y**I z4_NBcuY2x(Ob4EAE1VL}o*ittlM_c!d~Dx1JLU4cn}kFiCS`xge+>CFZxY9yr0 zakD`4mujvDVEB}XRJYzb%$;i){wkvHdlKtJ*2HXJ>lGS8y(>aDW^bueUYdY=^R887 zixCx-9>@K3ynd){#jeZrOzP5VEmRr;>c{7ox$d*U_kM@~dSS5j;f8Cn<~A$lmcU77 zJ(}O=rA_3vSk}D;#5(fh$Xr%cX}*G{R87*8(WBa6hVQk%!OiqVKjCwaSP^IBZw#>d z2cATZo~7QxbZf6xzRpjTUi+Wk8U0BJz88GA9ZH&CZJIVj-3dHQ@QiP_IL z8+1%5zg?Cqa;ZS`Et)DEhab}^C>`-2)6hXSZeqDMlvv-=Bmo!h73YczcAc*+bB*I) zwVwMCE%jw~yMF3b7Y{dn@HYalnQ@!q4U&=36}s-e3Yx}V2~s=Z8m-xmXxUry@ZtZO zI#VZ=I2#rFp|-HtoEAC~AQ1LYMSLO4p?LpHYnF;c`+MgwQ$~ggN27bkXMMWs{Y>-w z9}zL%(({)TzhYnt&O2*u0x1x;$rL*V#jMg`Q1{$JNb~J2UL)_IcZuANE1b8dEyIv} z+|d^gCZSfzGK25Bu z;!`G?XJU2x1MI)|etYz-27I>AEc*2moqsR*9GK@1cG|gMsMLG|L$ z_ZeQ6f8*rto;b!AB2@w;D8bNWz@rB3Z3P(ZzK)FinzzHs`+l#CZWwh_!Dm>Gl1Nhd zWTMo$Y~;Knz_2?1%KNYmpGT*!;_!Y~!ucA(XMVEz(tN^{K*HKi z(A6#B8#EAu?odkhNQ?3FtFbV40T@U{_^SN`*;qLL|0uc-e=6Vq58(G1oa5j)IAl9! zRMY<>&Vw-1p;gkL$kf z_v`tBErUrv_mOuxtgIojb)4w8d+ZnzWPxa>XXLA_=Wt#9HfC606C;J&N7yUJeD4(j zC$Q@!FzXE6R$#_+ble1Sr=j|yb@NQQYEsAV`j%g3FC{U*aDwWfpnAY9Cz=aK{%P+N zV3Q2Vz_GUS@GMc`cc9>t|851_J2y*bzQ$(<@x*T=7#}-jm;PsVwg9=gm+cZR`W@gH z{>jaRx_nY2k|xbwE{29vKniq7ITI7s6D$jr9z0Py$J7B#5T#WP+{)2c^8D^l)j|T* zWWG^#V03u7{+Uly_!BR)PpHV}$-*ptNgN4zVky=z6OLQmK!}*f#b`tW4$;71onRO; z4<(2uB%vZOzC*|d3>|||?J8#QX*QHnt!()au%Ka6jBaO6LeVUikJmI+B?-p91nINZ zsIf3&SDr0P(Xq6bnI8wkQ*1XG2$;NjfZ>=fNPbhJg_pfFLjf(=p-NHcvCBF?F+xvp z+-LXX&A_E$y*0jgh}q>%*0p(f*?U`BzN(@@{+HHy;I{QLsAztl|Q* z1r5xx2e4sU)KJl{fT$vZQsp+E*AH#cqL@#d*;R6_Be5c{Sw!BLwhpHHJR|UKGW@l; z&*w){eVBy6L&ztTKpPxHng*7pLp(_L^=7Los`L?&Oq({!Q~{m?{*WK0@t-b>*!Q02 zVK5OXu-hkec$5+|Kj6qigta#5mrb zdaMylwy#SDdVvq8xHjhQ0o#t1A1e0dFql3_nE`AVHEE+Fw?)`vE$?_W_LO z=?Qotv>I?jP^XSFQ!1Ta(&~pAeBr6S-F_UU%x(OX)cEvsgO74!R~-hA0Slr=Olhls zvG^LD_lV5gPb$IWw@mV0g92Z?xe4&8vK%rhtvIDt!?Z@MC&sUcY?@ zqS;zu30`LpF#YuW+j%2CzeX3!1y5kd&`ZJ)q8zv~9%k;>kCRQ)y4)HqRi?Vw0tQ$G z1~=uqfA$bl3}(l4B^Zd2KSeH&=;qR&pnces?2+CUNhH% zx0n*Z#}7(kcguVDvh9I|ez?*}2_Q6z`q3IguchtGEn4ASx ztE=+pCBf?|#qFh9ifXgbc3PNFFUah)LEcYv`k;le|Z!yK!lE zAHQ-GW5P)p4&+D>%ITN=K9TM##^RR59#v(K`94^&Bod((0Az49?OL9Lt} zEQxu_ZXHm0$saaOeES8LhGDPYkx)BbHKvlQ5TAx$IWc-=8?_ZI6Pj3oCywd7XMPr5 zIqHg9K3fuxRdV9k>cDu2qwi2Gw==6WhGpc3t4}DpiCqe3_0`M{U`qh^1VvO0hchn| zsj@{Xf<3xv#Y`RLP6K^gN^GSRSo{W)6VQS#$>k%s@l%ki022pML;dy8kBg{+&4%tt zq+X1SG zwrnM4GDJpEnXPdHEA;6ev;!l}NK?8cqQ=Qq8woT3NXjti8=bbsC4c6o_yiSE{fQ@v ziumS4_OV5dVXiLqG}u%<56;vR4pmU*ZrGD@<2teIjwdpe7(pt`;nS^TK@#S`)M}_!$}89JZk&$?rjWxA&>s_i(i3)lm?n@jBJpK4D~ZV|KTLvA-zER$q^S*R%!E*-!>C7o*Bm(Dl1KRvYQ zQbn%e5S9^M01@VLS<+;o`@vx~m)o0thbJOfb65AL->08Bk+^o5z{mT5Rq#_;*iF^( zt78;&ps#{4!=mc|QGo4cqQ#5A=F8xpt;ud%o=oGTg!Z(&XMESVmhyPnAl&XBL zlFEWK1$I$_1?=)g?!K4-)4EZR5LDIsgmP_TRpASUou39Q0mub9e7za*gO2oU`oyO* zG0JXmVO5;NbC^m0eB!Ofw4bo)%=Y%#cOG9qckwOHD=**3arQf1bpPS5O=iX=Xu86d zetO1!Nd_(ztjrNsm^8+d+dm2u*uM=y3++McL!x@ySJTT>;7__s<86O>zT)?ktHdGp zwca`|h8<*M@2PS!bxs_wKmuQA9ky8oS9i+=zEKT$rdPpW@q3Sd#&v>Xv+BO*hvHAP z;#z-B$g1UI?7R-u;))wy>#=n({T-A&)?0sZvwAslhsCG{z!-nI7&Gest8?$X4F+`qAL9X+yy?2F&eT=widm>K6 z%U3_&e-mLClH77TozsJ{asE#9!hzS=e$&fH%s7;-w&gZ@w~P%35wze|u4esaTXy!w z=x=q1RG^s13NoKjY`GW&$F4AjZu|D3)dNr+M`aAcp$0su?9 zp)+YHZ$t3;t0M9K58mtAL6K<89s>X_L0zVzT z7cl4Q@Np{k=Si)j45f-Q0bJXvjG?WI4pzB7wUYEyZ8hrHW>5`dNTj=U5iFZt0FcB| znEme)$cFT74Mu#$68W2ca4nVa^ctY_nFkDHu>AxmdZjiqO`N=jhkR0*u>^VV$k++x z(=@)owiTE`@{4We8UAa}z}4tx7oeSqQy#?CS$0kL<8nY2nj`#+FV*#T)ZXe?u1Q}$ zNnHRqfHqhOw-4Q@{d#5fPl+BgH#Q%aFw!u4VtjyGL&)S)K}iS^1}ma(Jv4*kL%8xw zDmf=Td|fQxQF0A-6z|#vHH(w?qI$q@#>&Q{(Vb&{DZqKY*M{ z*h_GMJOOR5&141=S~@ucO;@(O(O%YWN-tmc9* z{7Bc?3dt@2NnU7OXVk89b>{2`;Aqribf@x_tfd-zz01%AQ+>Tc2L`eh%d8&$pFpgn zO#-42rlWAZ?3L0g0xQF|S2!lldSU#w;JPPF=ZI30H)*7n`3h#~r~VW~Vn(Qdw9S|l zfM~s2Xh%uwqHeO&yVm(|(pzu*X{$aTP4RBYKs z-~*p2$JEeM-eaVcH_-$1gs)iZc88{$Hch_t6FOp3oTYc2ChSp_JrX*d&?WYXrZUmS z{9F7sWy>&VGFgS)*S_+9>(|rt7wYc?H~IdRY%H|fOwJ=wwFt5>c-BqcpfEov8(H%k zL|RU$(2W#Z30!^(+(JU!HeE*ha}J!IQ?R>k_g1!1?6^9=eEn?dy zDMll}Pb71aAT1;H(l*s}*8B#C2Ut<=$urQ1NeB#+7hq^0X(+C~mF6_<+EkkdYOF`( zVUM1<$hobs+rpHkWnfz;ijHT344GiMGfj6@8su_=_72Y*8+@JjYJJ>9 z(WY1FcN-Ij44YR>_^|ZXp(sBMjH4m5l&~Kb_#vdBOlnMqgBI++pw1+aBBeCutdi2!}7|pz@*9B*#@;}PX--D;HM+%Q`3-bCB>tRsb zgei`a^GCR3>c}-+T?l31kL3U?O0wcW3QFF+DPhoKWiu6O+Ue0%d})4e9ll>DXrBh~ zJAAD?cgw$9?;=(1w^F^1PV?c6x(-j{JxlVmPh<#OQP+beQDOr;<)YcaBqUyGYCcpJ z91VDSrPIS(_2fb4;>Z~U+2Bt4vA=O9lbRET)DnyD#UZ=qXRka{jZ|TFB>CPJ1(9wl zU9n)F$Q!ZQ-|NxwyFaLe%YP0bE&F^aJHB;{8FG!z~GS)&LekPg1swU0io;+!sk1m=dxOtS7aJ^WQ(N5%BiH(&oFbw%@q!c{x< zxOb}EzO4B|fTw()DHZlC1{%uYxWS#{Z>aI&R~vDXb8${_@@&psBryvL(xWlwoM9L7 z_Lxu}o4n!?qqSAY?!My|l~-?VsDJb3U_VnQv)>WmYBf@a`DJ9s=bo(yeg84P{dlY7tdlY86!{Z_7tDCmAw#_VHNmsUiM9F>Xp zfQNznCr#4T{+$|@<#QMNa?8wh1h`=~@{#;E2;}TJ0qlI9m=L?lH3iCT9R2-Wrn2<| zr`>1otDh;z7QhjwF&b;r^A-Qk=GyOQso=&rY{S0lnjX3=d^0;TF#E+GchJ(~%}pJN zf`Vkc;z=A14&`{j&DoJjGk4P}WIzrGBt=>HPBfQ?E$nj{S4wOLk-?@$tO~=h^TLHs zplrEMrZ04HHd$q2qk%R^nh@+*8A@fMM?(+0X|3X<9~p9B62+3h8E!)n$EQwa8axft7#a_Ev@5H0*0($mji6N;9``E+Hr@Rr2t?*o~#2tiLQ%Qp$q z|JIZjB?b=)^u8BdR9E2n;N8XGOZ{O6jwYpE%BU77Y%Bs&hvDEzI5Qnfs)XO;MC%(% zJbtRzC-H7n0D(+pRaXhaxoaEysHL&6PER9_frc`O$IaTu>Sr zGa&h!d4Ls}>z8FbHMXCocU(QRuPW1kWu{ZA?2h3=9lc;@?dw8C9RTcwQUb#>i-`{& zq_1@q|CGBaC!CLkmss3Ly&ns|RHQV~y*eD)QgeA1v%@#4o8N!E8}{a1_lRbh-E74I z?$MzqxYCqN*T7ZLm`8DtJ|OjbA2^b)ZiC3jjY}oV0+xKH(#_r1+*rF@5;^hAiTJirVG zFUXI^1r1yjuRPk9{&}QpZ;CMWy5t>XKDge04Vve>Y)+PgpZMa^b&r%cy*cg00aqC| zWLjMWv|HFvJCK;A&G*cnq0!rOAvfbe^S$#P+}a(D9XtuFkwBX=jhQ|PiKFQGBxTxn z^bNTJzLVwH%)#IpN=HfZFivE+yS_AlEhuK@oLaM@!r=MQ>U9=orbnDBL>^{baR<(j zQ?iEC!WQ9|N~Wad#jsu4qqPXagbCoR&Xhcx=Z|D_Lc}jV;xtcS$*h2oPM@vRpt=rc z!}F-tcR}!-l0I!l3tw2(4S@X;WKe&5v`A3eX3n|+mpXwcZ&M(lwat&>&;1NV^b|;L zBqi43MZruKO@(T)e5v+)>74{?H!bED7~_!9{*(9vn=^wwPySGz#?JlzhIU}Hv%m_ape&#O zbBX05Ev0>yJ&jEX^QI6h%iMJ&4&F;{bXMhN>LyMP>Wg1|?Jc*15q&Y6y^ep}3y_)* zkanG!@6D*;eGnls#1~#8){?8N)bjJF6|%_#-W%+&Q){5eLa9yG*ov9m3Np}!pvd*y zd&1#>3{Z(EPw-^&XbwjB3tiGMMIOo)&J zu}wb?e-KHsqv7x5}N04HPTwoC) zScRmB64Pl+}J0t1!XnVjVUPpK6A7 zu+_ITb`XtY^iIm!Ps_jqR`SDaQk{9SK0Hfzl+wMzE?q2v|EmV~)FV-5+3k~ThGL&y zTyx#&g2@R%5~HWA7`-R;k1wAY9Lf74fh{pdg+3qW!w>Af4ZF2W=9))}IZZySwBxtP z$MjuKRBPBoQ>dDrwb=%)4=@;#mkgE+N9J;|4>>+{`=1Oyn{!T^jieq4;>XA1nw+4b7J?#FMLS-M2K5JNWzdo(Ui$nB}H5 z_*3Pl6-o!@L5ohVR;C>+fpyBB<6G8zM|8>|e_|{ywUa&58(TTBGw;UJ4Oww~?yAqT zonseY4Ikt_DTFVB-@fd7jc${y07oZvS-zU8kl;}yI}f|<*t$=6uJY9N2#Rf!gAb(4z` zc5$Amm+Y2=cCy(P%9agTK8gVm)MVqnMCCoOj3-#gGvUvvIjRKWZlroDXBG}1W$0Xn zyjhV)DG;*PFB?;OPf^Fd^bnMN8P(cBOHr$`(T&V7dIimzW>kn}k9QJ=l;~I7-$9KE zPl{xw__o_%Mvxd>{`kUWls|7cK7)_PJ(&qRwU#t41M9<1CocHEsYiA01FgWP7NQ7K%&U_4GO$ulWn^{`J=S zk7nSlJpAec%XTQGg93|oA!+V9$Ko&Ekv+W%)CwtbH_N9m<&y5fk22Nol7Hr(%qG)= zdsBnBU9gw0#!;D=2;eS4%Hb;HyYk-+K!7m*GBH&pA3U^UjEAx zvdG#m-f;{Yg;#Dr;=gp)BcV1d)$w^%^HGvRpaKZHI>lHoK|g-oi-U-|c$ z0Y7~uayZf~er}q~Jq(E=2Lf=i!w_-#2siq_IiCdIhemX7ca~J}`IDehx8TT(T8E(P z(#;GK#he`}*E*x*1w2;|_D#ryUzcFLkzvP@Qh6jE8+k=o_khHoVtoYBrzg!y2d5Yx z_)TU1ubY|dM(P-yP>;xxr-U@VUccl8s(n-FjkAdJOWm7&%rUh2RANo${Nx5{I)UZ@ z-h)u6h%Vx}h_^;jF=m0+V6PfUcNSlMh}(~j@EevC{F+l>H*1&pLdl5vVWqKEiWkU( zrQgn9W<*Kgl#XVG5rWyf*~#Br8}HhlWdoF`_c?Ot{r}5e0UxsF^V-d1@1L z$-xPi#Z>BgHyY(VJCI-NWf%E^rk2LhT>lkb^I5-=Zrf_nL9sSm{xC(e`stt+VM9US z5~<$Z){VJreUO4qgBv%VYyfRw_%eB~{fTex&OxEhhGU7A0rEknfjB#A@~D?5G`YiU zDJ^s@I_dB8&&>ZaJMJC+X3eA|?^cgk7%ikT3=dBGKVi|Uz;ngj?IUKUtpdrm>rvK! zZU;n-ou8EO$vKY6j}_Jbm z!?Qv*Y?tVNJ$6+UVww?s(J6V1ck!L9eL{B|HqOP#6qY%BFRRZFJz|megmDzV##h#u z>WXb+MEiIULs^KA=`sy>kdagWxa70zB>+#_xQ>M5>6cZ}qxOlZ;k$|Atz9g!N6wlN z5;dQJTX!<@h^BA1YQSkH9Q9@-42FmS#X$2khRNUrjL~JMzMaQYwZa4=&|NlNH*}kr->JlRKo#R&Y zm3hpjD{^_^1uJlVceese;#>9_Z@P0gyIJmYWfpsc@Mnk{=CyU@3Dx)UanaY07LMmA zi|<5`0H(v}Y(J+Ed}ZJk_p)=leCmzWgv5xfY(3C?XdtuJvP_7>go}NM&r9KcSubme z)R-|7P24%=s{sNR3=v>pne)Wc(hp5ZxWK7=9VLKmB0I(lWUGpyWvX6RocYo-XCuPW z)WvTuxI!rPljBdKJF=%c6{rhEn{b#3MmPWhdrGIycIw|z3D=y#H6x1!KZnl{$J}ICnthAR z?`0hbyRILeY7?3rWI2 zWsq;KIE&HvC)>3m*aucwdykQ5s-%dNb28?92#miH4fd@@wLJxsy&|2~8 zhOcSgX;p5XC@!2Je2qF@mjvupZKhR@hNt>%L2U)KIYVR2A{%B|F`x@zqCm6krxLop z6>{v_058Wg+bB^&Q4UMm3a^sO1p>r}BO^5WHR!O5vT789DDSCNd}9x-u1-<7e7)aj zx6OtaTi5f}?dHnEinyHZhYM|C@CgvdrZ~N->Pafm5h$1O9uy#O@ACY|skB&M>^}z& z6|Z-c^SfAI8}N*v+i0sX6EL!hyO5ChKvbysbz+F>n0BPQ;NWXv_F(n(i$J%bYn_hi zpNCa1t{WAdoB?!{EL!Eby>>)Z`yFL|*+KneLuwO?rbYU_Zcgffgo4tz{8`fbe>-Gp zYKj3IeqJ_rOXqiLJcN|ks&p)(f4SNu-AX)oT6mrORlFeR zz)bd=jEFsxDDI4lm|YZ=CSFf^X-8s3riMXCV8>_DOfn>CKf`=$6l+|mcSh%Fx;)lL z@shLb#7~+Y-v$dbFzgkE)opW_mwYbZe7TsbioQNjf)nOHrhu=NaQ+r+4pq5g>fqr( zD&oXkjN6$r?%?EBn_G|7k|14Yj_OL~L;8d-rF}ryRJkiRq$|s!I<1t&ptyiEHK9D6 zo~n~FWuH+IW@YhOx^;XhCxgBigsdckfZ6XQEOcH9xWx}ah&6> zPM#FMfFx2T)#gIZ>Ig`BG@<7LJ|l2>#wX}gNmgMhGwV8v9iV{rFkjp*mGz3 z2Pt!Hy?}V8>kBMyW*}EZxzg>p!+mx^8t*JLQ2Ee^9=zM-Cd@QBF;9SpdW*m58C9l_ z)79rX8`HCOfm?M?l6EKD)+N2n^|{($X1f7UhS}RG|Cezexi2ZtoYgHFE;Po_GNGqR zlnTWd_{&kjisk?<4Jm{#u5mIEfjKV&AR;{Vd`^oPkEIb-fs3k^YA@j~^cu-~(wA?x zl`*9neh8<|8FE$<64Z}gTQ~WwbM~8_t${OO59a1BCZ!7j8Pth~&}%ptRoZ?g`rP$d z2`6yYCx_@W?MCe_c_TXlskFP?F3)BguzBO(1iYnI&|-~$AIS#ohBiXjrj_?(ULLm= z>w_#+6U{=MakDh)uQ&C=IsW(_B;`f(=WjJ5+G$hyJ!r*2G6>k)2~*F{v6ce)U65ri zkl`=S${LA|e`Nih>^Kx#xTa)8F%eqaZW;5F(BhF{PJG)`y7pZ%^+ono|fy5ZrqW$^R-f zl=c8C{+JXWYl!h@hRH=u|1@)%IzgerM1$VH!43+)c&U8QGCg4nONF}$rFKOTicKF* zQ{~)W3_~R<7q8Cn+g{@xF8K8pizE-}aaF1ef z-6x9WjR>Oz#XVY%o&=>cVFn^1shh1o(9~j{UO%s7QC-$veDdcm@d->hG5FqqUNIBVT#>7v*1PuuaaQStN(Hl$?Ub^T78HFTK-V zvEY;qr+k0GcE$DcScd7n{w$kFrOatM1VHwm5p+Hiq4%ly`U#K0Im#VRot^JT6OAXf zxvhyhyI!JNi_^%+gjz_QkYCim7v+11y{0y3^mr12wsi+Z+l~F8_2GYCe?9%?uEHI5 z1HnQMyvoqo&8gA?q>nwSfqy$nvN(xZCk)xwSV`Aa=lgzm<^D``-P&3a8#xk_u z#+WwJpg@XSfM|uo8im+7{SCF0Xp6Pa*H(Bz@!*`lZ=R#|ZnvS0zn5-XR8%;+>lLoN zji}fJec0BU)E&)~KAkbfqu@!H_`f3~0Pbv%35Vt?_s{pne+;q}XtI5y98b7qvBnFZ zgmoC1hoR0pO!%1cd+402pT|Z&FOKMbpQr*zU)sbzv=O$(sutP^+xr;w_UfYS^z((> zEFv83F!SpeBiK$5{z?$nCpakO@T-qXKr^o{IwrEg!2`oQpR3*-lXogOF;!2Q(4eGK{ZJy4l zg}|3DH_# zwHG&2#y-wd{bC{=pANmeMNHFtYsFqK+E^iW6k6ersunMHH||J$O{9Ivu72dt`dX** z=dFtKcwRso{9afbXXhhsY^c-2^~(?{NVaLm4e9!RKu5lk#U~va5{&U9gmP;ksryzS zk^u7u-E#d7G+glKijYT7QmXj$umU1xyS@lfFNDEpiDK<1Rcfd-LxGRFY*RjYQj1m9y3HRK@+x!C1@I}+ ziif-epQ$99^gD9~#^=_Z{YEW?IBkf6AnJ0$N@}44O-bm@#oto(RR$s!aEKo`zsJqx zM=AvcsK;aAIQ9ofUy@_g&$LWdqi29iSh)=p)b7gfC}_3w{=sbRAO& zzi%wF5%qh;H~{hl)ll*%sRm=_LavAcL%x>VnEmmXyv6(@Som$;hh8)gH7-VQHu&37 zD|Fk-O8jH&KZ9+lv(Xu=x@spGAw4gFw!0nxP+THLwrdpe9o>^1Q)IMCKmXT*e~;TdNzeGIvs|@5sX#4^Vq1Io$@_+me@RA@LE-0; ze=HkxX4sxF=|>}rLw)irWXe6W!0arjZ&g2NTw%#fAr!8OWrtH4Xh-+ZjFr&hENexn zp6Ic<=#9nf)DY+8OcAdROB-e=r24X7eV8eatbSC$D4A@AXKVB>VdWW0vI-1pMm3A_TmF6aBQW%+O#!f5jH>`g^;pON7w# zDxvB9TXqAd=n1StrBNM(A_>xrULlpbJH$_cl(u;_QL@fbZyj08?g8rIEw1C6RlRi! zvyBCud0qJ8CObEWfg;ru&Uyz}#T1uj<9h2gBLlSWu20g1?`3}&YksbiR*cM$&2h*w zNKJ(uzUZh_k{tpanuTs$fA6AmZ)-Bc_g;Q$1&Ud<$4Tg+LElf-XXmDjEsQ}lJ@jC@ zPOU-pJ(MiF)C|{n>QU)kvoRu9zyiOVkf$8(@-toS5rWc?)~;MX*J-x9lE>qHSnNu& z{SO{!m5BfO ztf){4SM=Uz%4$+|u{P>`QZ?Z|!%EERir1~L>yO2Q2U1oB#_Ob4nZMcy22Ccu2fvx} zPxM(dp1JqNYPsb)f2;grwa%Owv%>r{6?7`vpj;9P!*js16674XwX_W+aG;097Q68Z zlVsWNr8iVccaLwgI9{>J_k)<}*bcvG(aAEHRRUlE`JG)<#eA}P_G`~1=TOl)d$x;irp8QSdue0{<<#bWlS1*?n7$qB1||lRW}ye z|NHbQTwd?bdk#$|QIz=cVq5DJ=e+F#^N5Uaf8c|#j>n%{>!YtK+!hA5n3h^YI3zmX z{vE;d6*nllcVKY)LyG$K^#f_uLhV(W0s0MM?eb&W37WeA}=Wy@Fn z5tGU(#JZM8vT{13wBNYvo-G z9*?i~5^*i$PzUY2lA_M6c5#80EP?LV;hNr8JIr>%O_+ROFjT8|S|JbDgJ?CVzBVoI zp!2}X$TDqTH0y!13B8LiOkXHRvm6Y^=Z zm*o8KDjv&rPLU^dA90FctBKX5>g*hZBx%MD)pC~T6hh2c1cK#~LElus@}cvfL+jWE zz7eIxoR#?>HzCbu--bxqJ{t{dzrsL%fADX&Cb}U?Md-8(Qt?RA@8PR8uMKQvt&X+< zGa7(XM8%&3oK1$XkL-7UMUY;oX1(p!(PAD`3;#Lz{vy?ZL))MuD*fCFU>@m#-Z>}kLxg!_Y2M|h72{uS@9u8#8Qsr_f58E*1gY}<8s zhrgjS`|IZAaVVguc*?p8IllnUfC+tG9kd~vJFG=-UWQ1S5}L1E@l5o9o+SM7yD(8? zE`N&cE?7D{@@Cek^5zeiOlDJT?iw$&GUbUjBdX*3VB~;WdW=h4>v|_gP&;A z&ia8rJ{xJryB4vAhr*%=cf`#SXy>KX{)YJLmxJ-KXSFxKTp&kwhpe|?8)Ee*!LCe8 z?Hg~~a!mp?thTpRIKDno=va+yFn^_gVeO}{>099r11IOT${QLx8UIDODV236p3w%_ zzHNAKj-SQ0!E?QK_|#a5EyZ`Q4H<^cZ?BW$U;L`z;(2AbUj1vg`Q(>r_pcl)XU}cE zcuta_ZCYginbh!65b@>LuSM@3I)y7Glf09S4bvUfa&m60wH7972zH5XGI7H%_tPPo z)Dd#|LRRWnYC&}0gW0sqxW9{unp8CFx|2a;;`H#Fv4=(fWm+)Dj#d9{)JZx+e9M1V zrii!t-Sq=(=)r}zvU^vZ)}5YmzWd_yp2k{$R`2i`?0Uy_Cm#~M!-;e9fdLCWEf1>BD?N1jE(6~*=R$+f(FtdkPrL2n$G=rXA@Lv? z-)j$6-(@9u5CsVH8j%n08n!?32{gPoc7YvYIC$qaAOujqoKz0pVdZ|?ZITHhDgRuT z^@-lE)+b^B0Jw{iFi8F+2Qc=&RMIH&F1_K$T=hmpyetdd$KR|$z}W8KcB9NE%Myb# zay|a&wdXa;+=}O#(X~1W-EeIzrM7%78Cj+&gk$h zw&6|_>&96v0O$Ey?$xStV$|jZ_NKiYE9}Yo!=Un7j7@B?tW%`jllyN_yPCy4og+_o9_0X4=+)K1JI>_%TLTP=`XaJ-)SmbRx$myG=1-4)IXuv z@U7SW?^-mDXF*>)!mF!N>jAjGU7YBJ^JSVh-=0jE@#0TJZpR-VZq5I9NA%9^zyAx| ziAS}n{(}lpXkh;`g+4@l-jtX-AVb4INwzO8(bZ#xLz)@FU&mPv@8Woa}KnOmrLfJ>OS zQXU!efiFK6I(ppuRP25`M&ktVVgFnj{KC35-(qvO(HP-Lg+q~;d!K*LjI65V?{D7) ze0w0&yx8LU?1$YV)PMjqlWXVL8JCREaYGF$IVzM6>EpUEqWv`Si z8!%%!8HT7!Tv`?(kiU&i9c()3#>3ZOKg=$$@R_{COr@*20_3d%qV650%VOa@RSimZ zC>h*cz5jlv@}opbE+uM>EAQ5Oqh#QS9A;j>2W)@j*hDPl7M{F#>)mCV2lGFkxSMlC zig!_a;BeJ4Zb@twYI*TO29xlkk+N!NuAdGg_9K|}(afikJGjq4KEdg+gFP}*Xzb$K zXPkgq=;JR^394%H3-Awzf|lXyoFT_-f#G@lz;~LN$+B zsL1cm8{8Zp8N^9rFSqm+qfwWi*=2L*fbGL+pZ(1h zn|I(lcE2h=wAJ1jUd2Y;YcW=p-(}gS8;)mN@f~0;dYf=s@|zL z7`|&OFAkxdC=GDQF~p!{3NZ#f%-lqY}8C*ixW=|f@ z@FdYbj=ILvI${r4;vSU)I37BBGBm95r@_{bs4q9u{3Un#uZ_#+htJ z(cpjX$NWXlU?1Mua`l2h;CO->GReFK-D%R}oCE}ZOxB(OZiH#ybdVNFZa=l5)Jf4y zv8@{hVau|hg+xQ{4}23E>THTL&hs& z$xA?BZ)b9gkeNZxu+eV65Y%xiAD88r5VpJuc+dlP(A7CZe-gup!ISQ6k4;XLKkz#& z+fsCTMtw&6p--%q2)@KU>wlU_Xr^a3*!0G-zN~hOHwtG41THSQeY}^;^o|vBd%h$L z#|*N#CKbT%b2b6G3t(j|a{P!o1AaB3xssE(FSR_W!LlrBlnJb1eZ}>q8lmi(xvRxs zdsIAGOL(7r;nFqJF{G0}Ni{iqhCDRyv`{mzGoX_-D$|q6 z1b&3*&YT3PKX6((mc^@Ld;**6`QT#he7k{mkzi*d?$V z4Gi0UUkno-%*xYN{QR&4X-}vwN}y;c3hOst)=Im!;pvhgaf7v=&fS8FErh}zzcXhd z6RzWSPK%jJITd98m-;$-6ST04CS=3Fij1?sykeUDoIY|ST@ zO(x%3Z8^^KL1mD$%y6!H)H&N&vFMnw(?RH*eTCXvaZAD$tb4FYkhPc}*3#6f20r!7 zTlz)s1YS3YBTxC;py!7#x*b(#Wn>1$IOa?Xi`t7q?yVP4&HjUkrFlki1HuaZX&ssH%24!BTEo)C2TvL1LWB3#hw;ErQjk^d^;ZW=cFf1px`h{axLASsz+JE-% zp8TmA3H|-yj{0t5iCS0^Ao1aPdv7W_+Sp?|!O$y5d}-6rE=M!6eR?ii?DmVVUlk?g z#4ln!e;~Y~7G~^{B!p>00=0UA^eSPcVF4PeOMMPlc1xzmL>#Jbj3S{ASfty}J%N%b z?a~d+*Or7f5b>7Fj43x)%O1Pyul)SGg8acw^n5sjKOBsZ(+~K!%A@V03_OrZVnULA zq%T{Vt`B`s!CXO%xy9lP{Wd}Q?cM)CB{>9n{q`XQ8NH-ut>P)9k1YKswuq>Pm8`~m zZXZAotEn)8CR-(1pDp=3Fb>iee!{vTGA2#evqpHvoy=H9>*u5ZG!6;a3Ows*u1@LW zi01t&#Ra?-!b{IA=+dObEa1sI_uwk}K`4<#`7NFy^zjds>a%C9`~JB|4`@Jy( z#v9)=HZV#DwAQwgJ!=F6h9EKHTO?{hzi4FsuPGp2oE9$)#K!`qqk|(bc1gc=JT5a^GH+b@DOM?QJs{K(z zy{)Qhrh+KNnrN>7`rDM$m~gGIvXu4cq4fyKes=i)^gOk-K36=(2nUvG`^*e1NrrsZ z6Z)5QH^Epkw^oz`|1ed#sC!gKmdsziWH3qYP4SSsqmR#wGxTCFrT;TkBzO2v-^1!f7K~pdF+Bnfc7DFBntjY!#!C zYOsQ3L;% z-N#LP@l0CVo0fc4gfyf$4mkHjtS>`Q@#=_2&V1OYK$82WnxTeiiq%>3HN=dCU%DZQ z*q#Y4{@1oyx;SZG=;L2VSXuVTN>#laXGBke)bp-m@*U1e#LLfii2UJJr#q;R$vFvm zU}&uOhDTiA);rp&inc2_Ju}2#y>3nR^}c&S`)|0h{S=PV6Lfh5Cy@LQcr39RhdQLO zb=+_i&a%npaO&y}DOXme&}=IuF-l`bOy9+O->c|4h+`A8Wr$d&MLdCEPf7tzg0SG} zi&ry{;`&3Ik4I>-K?zd|rd}f4Rmr^xsBtrQ&(T+Z>|Gb)vYm(!S&IOZCZWMP@LS=d zIjFyVgNf|ENyfbSmkpus+X8 zK=lAXdpxG;!4s&L&To|$HTxo(z60@{e^B>l+{q>$Fw6o`)MkH*HgLvU0qb1#EgmN- zt;3T-ca+aH?PS>X3gIEzusNx0cqEoPa+`tsz(nq=J;QEt%LHHgEPPhY*V({Bd&W+t zbjk5wT*ah;MS>#YN`drl*HY{Sifs|FbjUJ#B()|?{@jjm9~C~i=h8DFybaQy5_VZ2 zYjF@`^Zh`>?u--Ryqg^UDDl;`O@0wDOZKGE=AOi!u<{@Q|F{Yb_O@8Z#|0dovh)mu z`^&ShFKHf|b&m>|*24c)@toQS`;T;!t>xya8#M?3YhI05-#?pP2RNjf-$Gx>sb{EH zgjzZgQ2(gsXAR$0-K5)jVlAl*XQQA(qcxV1;a*5xv^_VsoMYgee_Axgq$CwV)*`G6 zzWt?Q*_?AwBXVLTsfjp|OS*mQs|Z-t-^l!IrJitKymd&CG_^Vr-ryYb#fm0+`dXj( za)fQ_ltJqH-6e#pdFKjmgzP<|#Jqjow8)@uumcHcVU{tOHXm^V$^$oU%WL{lvg_Q7 z>mnBdupTx7xqScwGA;K2$Jn>9EQ)l;8LBy#V8|~Qem@ZLARqodHCcuJUMotX+I{Vn z*1w>9f??7cW$Pa;sesDo!zDH(m2opy6SLf7mfho3bkapdmOqo6<0XZr^4`tk$W>>) zg0(TU+V?N=>8wFTy(Xpp+y;bH)!LCS6i^g@fWc*FO+sWt*+8_#%ckIIiM2S<)LC4} zfj!2>5BhPPEFc`g^28|0WJ#* zwd8^-kI(FF)Tf5awhP+~kAEKB5?ljCu2o^f;uzRs3sF0%g$=Yi0FsN0&(p`B=K!vu z#`mkc3%4cqqR@g{KMD;62NPj`)b{rx-h9Q>HN^9vzn%3d#u&8{rXj_4DJNl@JQoz3 z?>(rYAD$I@uLx<0iwOKbau?uT2i;#s`M6`RmJAu)&@GM{{3U2rRr=^sl6GyC7&sXS z;lL)SDH|DXAi?)Omw60F`Mv8XnR3CCq#&_liY0-y6X_bMc{W zPLgVHG*Fwh(}Eo<^QYc2c$vxNIaei`1F&@}GcFM0dXAYa%5vI>g+W@Np)`BV-;NB$ z0g028jH2eu^P`D~jkcUKSguPbH0L(l6WD z7HH;Y>GujHH=WnZ8^4)|Ao3D`i;Qa3eJU3jBq&yY#pRl(y^D|a(IeMOs()WScdV}o z@5140z#b|5k3jC4oBs`J`u%rPJnW^t5Jd=Y@I+#)=8a)B&#VTwQiB7isz%@3(kw`F zY5Z=##F`0Hq{L1A-4NoSBdlyv!>Le7>C(F@F%oS-?X?8)st11pPOMHe_g?373qd9F zU8)6oU-P3#8@7Fe-=Qiv8wwgEwAVuCa=bu6RP@^_gbb1Q?YMnu>manZ;Nhm4*>-#C ze`}}x(mou3&g`C2m%DbliR*`{$jiWiI#Cdp<4~H9()kUoqMUOC13M|(A^Mjpj9b_{ zHzAeU*~@z)U5~DVGz@trsR&D2V!9XTJ^`KTj^*U~k$qP4yVgn@j!qQ%)KdzG?WMgH zJ}X0Zx2*4#ur>SsYvi_2k*Gq;h4!srGkl+0U2m`CguwiGq0)Me%g<^crL5wmajXCS zmuFr|h&zzxCpgP7Xh_u92d;L<)t*Tm={2wj1rdJDqh6`hcKDaxXYt1`vyGO8W?tzD zpHDH;9r*1bgE|4&2WkB>1avouorH%dk(n0OOKOL(x*+!ZWM(Q6d9u!Z!?!9eZc|XU z3}t}N#Q^LMQu|Op28(v5TxwsR@1j76F^eLTs+&%`0|z+4#05x3wfhdjwAQz+ zS_jN0e)aWq2QJQ&2jE^e?W~>2ld^Aio9V2ZEmH7&TyEA?|D;SkkQdm;V?bFN@hn2- z-Hm3qe(Z@$?^A`AL;xAu7%9JYiYUy=7|G7yhMFbm=;If=gg7z!_Fvc8!qY>yQ*Vs^ zc5G{X^DyFQ?@if*${}BVAY0!YsAL9o2G_P``#QFIIDcivSoU{L+_2%i`rm^-k%xF7 zDBWP7`18}9zl3c%2xT!V0wQxc6hPXYEa!X68bMC!0>^} ztJKG=DxH$^8e3`adOM{aTy#vVXhST-+Y{#=-u}K6Dcyebbj@Ci=P{i8^OU;ZQbOqc zhkakyZtT|9thmIsJ}(Ilw5?@?OXqg3gzkG?q+Ls^NFus+tLAcq#=_z`1jd|y&I^Uq z)fKsz0YPMu-8(QY_r64l%f^_Pf|ro76GKtkTIVhvEDt*Sybs*4Thz%^fc{HVZqpAX{&R1*Sp>o{$t2YRWai->Ka$3!0SvP#(78w|rjb zuh)ml=#`IX_2dpRTAO--xL9_jsgrEVY}@Z$?m^G-=5>K={M5E{qHJ-y>7~ zEC;`eOP%_+T(1E(QlCSiCrpGO8gB#ovLIVpm5V1prpdm!_}yB8S>yQgW&RvTfNNfb zViV7u0VnhAFBkz@79euH$vnZG_ZB|lU`lRl0kZ6rY8!4lp5xba%?^IqRPYYP*=yZ3 zCRMM*`6J<#Rjj46{J3-s}qx?EHm~m!z7fH(ix}@60AA1RCZf!A^v6PI|eW z_M)4=d6a+^o97>vjeh^QbJ6nCC;(W}%k#YpzpD@CXm0_^lOWP;GQgdoke6wAwQ}6& zqQi^8UvDBlSV>mu>a_fNN1hGLQfUdlG_RFt$9>awT9vYYz9B-@x7NGD+v9Rk;W3`_ z;%c;?{?;hG6&McACyM*HH6+kbFpTOl?DE+Jrd&D#h*JeT2dh0*LQ4> z&(W!EUzm1HXgZpao^G;0X|56NpK4tnxoCH?#GhgL*=8@Qs5#X$2hoJU?kU-XbLVha zskB9n+d69WO@Tyz*V*i(tb39!R@2K~iu=l5UCfp0lmk>|<(a;lDq?~P`7ca}L^2Rx zVZxPd`|gs>*)Hoz5!_k(3`2JN)T!=Kuu-(}G`t+H43psuU)TJSa zWVM98`mBYF6q03)z>B`KmESWmf@)oo^_3Wfg<2a&^IVXUiOLv#) zmga**FP1w$2{07bMmL4kkMhOTxxv>ra%2uOX~p<31-ZvY+c}n8B#1Qk;`sSeqY3r3 zR*^46HiW)O>hIz-CQHni&_62k1;9XnL31S!E2bHzgW!Ai(;ytj-N1fJVI#zv`TO@0 zSpq*AO|ABfkLxAtG<#&YBPSs2HXx~eJs!Jeg3dN*EOQg8A*N55X6G0;8EMKcRCcFu zmPlLJ8COm;v1$(j00$K!8m=b}$?WL-Ji?QIuT#8F^OvK?c^^dsmuVjsLjj^#0_uI5 zkZjXY){oD5D)gU#6UcHuV>mVR0^gmSGxDPrg}*tAOT4xp1pIyxxmJS_{QjcS9^Sb(n!%MB|TMBzAn z)Nc+buNSpJ!V1A!ybhCk?XQbqRJ{Zir&`H?AOpvFzDZ_Tsn<{JA6rL?Nq}VipNw&- z*gGc0BSs2`P$`UPjm=L}a=Y#m+dM&w9jUsaxt#L9 zzSh$bMOPxuXbk;b9TRXBeHZYFlF?eFce>wONcNWjSwGHG^hXLCICar_#3Ng#y62)_ zl_d6o@zwUb-mT&O%8G2Db<}M1d8676DSTw84@Z|p9P(ZfR8!7#E-N|pD{C9KR~FvRZYmqfU%W1_1dKm#dAeb;FE<$J$>`3B<}07 z^p|`1>lytTtJ7@M1I@nHf(J9Rs&ejia;uYWpHz6`Q1_WvOH%Q9y1T`#drr5mJnZ|!hv1cM}&-XjaGtf`IH;6p=)IJlVMB(;~5ZZ{GFZm>B4qSU*DT z#wKjy?|()-C1OCnRdI+I7xbWz%P1t7d|at6G#3FC2-+tmlIp-%LJ;NbZ9s)YS&rat**_IM3@K(+@m&CV1SL`%N%Q_J+;U1s;ki2%zPytYpamrGzhIEx-R%=2wv|YC6lEE1KXr9>5?nS^{96Z2Q6~oE^rv)Hjm! z%-$t9F~%T4S~$w+IFU$lXyi-UGfvpcw$u_og;a3oi1UGpd4A|IDRHNREgV4C4NVb6 z7j=B1Z}7%FHW6%uUVWm+6E^~Fc%O_rdp^D{g&-N`;Dg_FzcEiWZ|~rl=OC>V>0Gap zy3H%%WCDSaA=1fLdF^yI@ND= zyqdDwrRY|}o46B)^g_hSvGOdUBqu0CcCM~H z;7na)W*&)ilT!8U(VF#1;1L$*s~63Mm?CMHy)fL>OaiC{M07S3Nd^$_P5indnVGWF zm2No_6|RKAzwIZT-bnm$oXv6PtS2VtU*fG@Z`8L1NPaB?Wl0x0%mGDGS!$}#?(w(U zlh`drpxoa98ZpSXAbC95w0J29K?<$tJ#~GN-Eu!9jmMf!hWIYt;PXhIZg5G*c$-AV z@Y<8Iu_-z9Ov`FUxPDHK4%MzOD)h71xN+92JG`vkRl4Z8_-YRX(~0 zH@QEmE-yl2#j+*B0VECJr-2xFNjWmaXd#faPlu-lvD~%+t^c(67zEQ=yj9Db91?%6 z#<6U*q{3V&XYHc{-v-~uY(Ifui7ItihSc#jRetk(MMBXIdDVkNS z`I66}RYQ;!6~~gOHUrPOY^ z@V%qfs1pbU{;0KeB}<^N63Xw%+}11HwrJpVzbm*^s>ZyO{q-2QD&DLcUCL09WcXhe zk|AC1!0~YC*P-b(e`Id#ZCd7ix^#1cF~{~8ne;4sV3NW`2r+>h6IBkFqkKL*fce}-HXJCYZiMuNk#C&s}h;b%a0I5Op zDzxjf#t**u_5659b9&f=v^2yivTI%ibH+PgLsaVU{CHa z(Ewq|b>m@)u5n(Zb6%aQ8*??QCD0fCgIPFV_KvX@jHoxKC1*HuTYRk0l)rYRYaltf z} zdp(BQNxy=PB6|+r_Uq(r+qea@XnQnk+H`>0=ipSQ30b5IhaXHvwqN*T?%L+f>q+kG z*Vl_^&Jh1JBxz9(_^NVR1k`<0S8bj-t0$mY3Q})Gqss+T9(18jDsUZ-PF_7yl2zmj zZb0HqWAZsH_btR;D6^c<1_vA1U(ep&Lhoib>xU793UO`gFrEbu6{1-5AD*n=%x!p1 zGY)iPx|r->^5~lMi_Qn`X~N%#YTmxLap(QP13|F$6QqqSjC$ikjb-@#@bpv;82LtX&d{4;ePWFInLh^475?jKjhJ!ZG?G( z2d9di$0Hs2_7)JX@w~NCQ>9k?v3h#&1)g(A-7g%RMjR`RLrN1*dn)U$K_c<#!Nq~G^nGU64IGOJdRslTp+aXjkxA=d{%IA) zZfB{#qNK4g`i#J~L_GIv2-x%c){kGjA8*|m{ABv=!Glj=Q`@*3-cRXN*)hGe=ac?= zj{FMm9(khn)@^oeKgZl{blXJk8XZ zS~MSm7Wc_?11Nglww`lyA9?NqsDez$`MT~q{;~P#HLl^kP&>wRZrN=9uIC0JYqZxC zt@J7w-9|8YboN2RQ_h!jcT){lOJ;c2ZLZtw+aDePj{ESobsgx^BWl9su;+Dw_jlIr zlWMv+s(R;bdsLI>9)j59!*iVYgO&nE`uj&f4|Z>KTM0Wo4W$f!37xF{wm)%8QAOkc z@z3U4qj2^3gkW=!ygJRAci;qsPYuS~=zKEGXPRXgUZEGa<#eLLHv_PaA4K3Jw2cwk>14y_Jq+?tQ#? zq<_kzRrkC3CZF$d$TN*))x&zV`GP7mntg1BAOC=Ga3rnxS;_gc>p#9!o62OxQ*1f# zR2uTVIo^iPCqEFi4TAk<-~Wl*?gj~9+nr(#PzeS*GBF=ySz)JNgiAIO-mLG`@X{ zZ?Sb)jmF|bbFkp595`8#PpUEh^a90;%gM1lC^hv!Z@>YgAV)}olFI(h#C2|$bG5SP z=SyBH9UX)?E~xDQ^ScKm{u<4?94%l3`sUm%Iud7CY_p-C#3rPhfUy#xBvjuDM;4Bdw2#+ zHA|;LH^b>5Yr*)(c2&Y|FxHsE(pz73V39A`SWKr`(+0?#_nb(jB+dqTiUP35YJpCR zxB;roQboFd_S>C1gZQG=ta(U_#4&Fo@T5mCU-CYjr#fJ&7q54F(Yajq^{)Gi3`_Gl*#2@GetK$ z-P&uQCPjUk%F5j&N^{1D9hqcl&eGTUzlkk%zyYNN2}PxjlP#qHgv-ZF&{hjv5GoU7 zF?nV-{c3v|1~5MVcvsJp;K!Th-+^bE>zJ;7T+&Smu8(fS&nkRs7k;V@vFhIW{un}r zg*9=U9op3ki8Fus>JHffq`vcDcTfs|`n&v)cXIbD$RvkQG-(N9XI$Gyz9GG`w2zYN zdR_e6Ce&O5ncGq4R(oM*U;lFw1!mxr9X5|#>K57ABhy(?*mQspkK_L_wttF^m4T+0 zp);eG6{|K$Si8bMw(^;B;nS0pYA-!YeaU+D>Ngw!8C8#MW@f*@C4>>Cy>FQ|2f{X` zCvRs42Ow84H%u+6QatF#QVQbtBQ{gtnl&fiOwS`J=mG=+j~w$4(=zIylOMxV2*g#6 zXg?*I-7_>m(_6DQ-^B`oJFc~K z1-Nb`KDmz;&oo7UEXnA4KkQNZ`Jj)~E8V=LY=`$IZA-FNPi?_*Z2cnP2{n3^`S!Ub zv!#z5uKxEma+$uUh}kb@x4kYQyEyLsk5H=wN>NyeBl!3vb-{cLlz5HSTgucz>m5}18A9tsx zEP5v$iP%ijamC?o%h?KG*H#}$Q(FbQG zaX~X46un}(>9*;ZqQTm9-o69smfx7-<<+t^5+R$Y{+`<`K7LU^qa%YfDz2hkrgPaW zKF%^!`DgaVC5&3J2lkm{=tJSgkd$np!qn@!jJ&Es;rPT({l&F)7VgEaTu*!sF07mF zG($$Er*u9G79$#MM?!_;KPrXuFGzx=Pbo<(SMyCYeqJrM&HM_-LDzX8nN@~~7Y(_Z zo2I&GNAuRmAW#Kj>tL-*afko#3P>>LbQKu0e`3I=FAS3k*Icd)I4y=+MM%=C*f!S5 zxvaLQfZG&BsYcO4_zc%#2u$>(Kg2?%YeQ~q`&{);sKvD?n!+TX@`?i-e(qkCLPH20 zP*^btG?PMH;%LuzgnEm;{cdYif1|`~Qq^4`dJPmiVSW;h3?Arfw(gan!W~kh!t5Iw z_l=u}DjwJBqu)Ht?aF&J#EgyNp7*FfM!1KAF>?Vg3> zY9qn2_e5=%?1_!iIa@8W@dkhu+NzCRc_1Laca7EKC+|AS;a- zUcRD9ja!5#@?{d+gBszFzpq*Ps&d(1)fQHA=&<7m?1QSLGd2~xyvn%?8l7BCKHbc6 z?`}r~fUJFryC5}uvOMe2ZdOh@3GqK-jzU&%pZ)3N|I)k{Rk7v>A% zbs|J?iDn$PHho~PqK{4`CD_x1w$%H-;U$)`lfxo%7XA8u<>C1MoX!CrzAi;oeClT% zrzQN+_%K~v9p9PzO851#P(zv!SWYvNpoel8c@WQ+^IzXD@&K5TToBgyl$+e}5fmoe z&npH@F_(V{$vR+BeJ`xqy`_!9VpO;4-q<6a9VfQ}z&Scb+rA8aD@TAkKbgl+Ujmd( zWEnoiKQv%-&$$c!7GL>M8L@opxP4|(?Uf5ZWcT!85#c`-yj z0S;;cvb4?~bte0O$=d6NHB{!Z1sS0Yt&dziHlRM#Nmc=n1Tq&{++^HzSa^3c^8{N{ z`)V#?^i)cUmK{EP4bJS1T7+%J%S8ZC$o?# zj_S-2#|h_5!RhGKNGNE}?vdyIBdxx8WBNiuOWvd4h(zOchzc1jMTj?!5b+c%FQ`s7 zpBpvvf*b9Nq=+ciD{D4epjhW<8Qaq@UlQh{MsC``BZ%-ILQx*||9HY6Ao)7N^g;v^ zi(+=ImMEl2Z>JF+-q?9P^3l&@Nq_Tl(|el9_j(jfWqhF7$y_V~yX@7VMoyVq0>T0#t4_ay_$uwBy8_m1FR`O9`yN zP%^8pH>TVz6~4`KMkFa>Do>!GMPc9y8G_WAGW#JSdMx1b?N8!QdPp%5q1zKA1&xTv-qL||;1j3Xv>9(1obORcKIBowA) z$rRazDXrsp6Z$?xeLCKl43S_k^>#tn-8cqWPrX?5OlN35O4dU2rUl##uh3?o;L#rC{%V? z-tC5>>ag)f3GzdEWyYppdAzCAK1BjXh}n)e#>9*D+3^qA@h)1tVI6**pw6sBrI3TsiU&R}=TqkrDY8$NPM>D* z|4j3TW$!qorxehVK>G2e!1!HD){K{RtVb!DAi#$_?7?6YHr|zXNRKrzh$l5Hs2AMc zOYc^)9&Jjo?nCP00b+Ef*;WBd1k=}TrB%Xs(Sqa|)~p-*iN42@2}+qw1mFf1A{C(o zH%s>BX91IvWleK#6pH{iPv+1DqtJf z7eGw;(m8NM(pzS|Gpj06pd?k&uraRJX zSGgq=<}7wzP!Po%b#EiL$yCji+urHJm~9sI>2-cu_GnOpWY6LD~uvCu}d*@((#IY5M6S-;_(`u8iyx?1*nVwK)gLBi5LO1 z!^4&yB8?W9E|DJpBC}n>P__5FUa_Fw&J_C&vpxAOc?GEWfqWRV^d{|1+1re}p-S@W zULbyg9q_XT3YFnzaEMpVqmlLf1K~)GQ95#u@Hi=OW z+bE{VW$NT-xzcLVDUR8>FFwoM#UxucIre*l1&E+_V+a34un|6S{^VQ@uR=iaz%Z9M zr8pJ5kchg*X*qgFi~oE9En6Uo$m7DC*R+1K3dwajCB5LhV;q}5^;GMYZrDPmNZ*Ei zFXNVkR7u(35C_5#6fgoj8&Yt)niZh;sk~@Tc>yEKHYO8;Jd7gv6S!D($r(fpUN@Vm zs*$Xx#%ov11`t6vg33Kpuu&0-8#9ogAZe>UmL(E2(lSjeB6(3N*|>N}mGQr0A7GpboVEJP;oncOXT^84$XgY|5cPeE_z;Ed5k;i^ zA{T9kB4^6abD2x3Vg~&3b$?gBf$%?uTHYsbdQ(`hJFBTF}FJ7$!&HvqcyKw=o+n(U z1eJ;Edu3-1_o3S)M8=isj&&~L;64#$SM1H2McBfLOjCM*5rNYxNZo${x}XQB99O{4 zb|s0uSYb&rIfk^K)`=L3uiV)ef8s5m3gRV#Zw`SUwZ1uVfI4Lq{(1VXDEasI)$5Fz zpZ|YbEVSQ903;vJ627b(k8=8JzN|HTQEWsZ(Px>R)dG6>>UB;X)*F$9~K;{E~M`(lb!J;cIE)T9nbL6{&>VFV&>8JgF zety|8CF5lD>F4R!eIXx~TK#{Wc{>>O>+s8`U-Ij;YvQ^HW1`&a~=mm93f$ZX<323%AxE0Q8--}L1|MJKs}|^|N7@s09+<}^lQww z)&GN1e@lKl_3z~O$G`Ss=%?p??EcEqfqL+v0STxuzd*sI!k0dizYm>B>!yiM)pr&| zQCd^lV@L?h?Z8q4#@l$;^~2vIX1!IYIzCZO zWD{jm+nE-%*4U{%^3!OGeugk;TSYWxz(z%Jz;O95oby%Q0(LIu%p>ng$o=2eii}LK zKBwa`6C4|@tzPbv5v`wEm!W-V7CNt5Bnv#e`0`#W{dkmv>=@!-rpbuBKaKSH8MSkY zvq{OnR5G<2kfyKq1;)bO9^8#lep{3fm1?S5WP7+B1*osQ@m{9OBAL@KU0x{x0K^)W zw2@mQaBme)HGa_Uq+9DPch!Ufd}dOO0QCRB422Ghg5 z62#uz-hg*aNJn~gmFV0`mG923ek=sX2R)v+-869#^o~DPee;g&u=-Yp7CWDNl5io$ zbcbw11K-BlpVzX7t;9#+zpo!{XFUsFcDNwKfh-rh>&@Nj12Qmo-Z6b9$@+tUTs7G3 z_5*9B&!-u6vGIiE=c7c)t6*3Pm55wzvwuKQp%G=PklMDIA{yOU?{#Qm8X1^~Rw=q_Vqxau}Z zVSD|=$K7*r^7d;kt$s4Iw@%|zky#~KD}`-3mvQ8*)4IEHj!u@`sxS;p)F+2@&yXto zpaQ8hUa7$rtcq!gX0&h)n41cY+&9u7P_k`%(}m$g0-76*EW{e(T_b5iq!IQez(6Mx z1j1fEKr^UkJV;v@NIimVtloBBorVTYj!?iwCa$Bos6aEX&a1a88yt;c;-CmK>1Ef+!})#)u(jf?GM5 z;NF*C&|&n`JIoS5Ne5Vhy;sG#<5sS_3kjhV#VYX_58hSMlpY6#BPABhzKWTWy$i}R zJ{f`H3H+>${Kd)LHP#aJ2>2ngq1bJMYWQP(HA7%A-rcQJezC^-k(XEfr-=@!T@1u^ zxyDAKU6e2&N>ftJ0mZRFSeQDP1aKRuH$wpzlbhhDT1KtV{0*oLZIIHB>;2JRTDq-*}2@hYn9~ihfCd7>q1-Bd^P7CEGNof3oTmTkegS*L+ zc5}%LrFSm?LiQ$CbG9+plg>^ewF>i%$Zeupm4f&Bl^)1*hJIhHk_9OmyG1F{ z5rB|SE;h9H+QC;z`whq&tU@YM0IQFse$2sa&!2-W5HxA2&vJ+7Xr^s{&J#5Y!Xx?} zKDd85NNq5LmEYl?mBy|-&wA-;3nPv`=2kB2kV^o4tA;HuAMu><8VQ`$Gtd#yw>XUG z9Qvuw^jM#n3{x4+d$5>tA?f)YUou1y&KY1G^7}<*Mq=~sG&%rRo#_?{Qhe}VXO5{} z8qw(nFPpBB;$)6}#p8I~Rv+Z7Mln3{xEk&0MBu=Z$)39_mB(^!=Ao^hE*%ZL0O{0h zr_e3Q*Dn=;Mw@HD5|af1F=4T4%K%PewKQ1!lGFjn0!E6taA|%|P@OE`*x3mf1)RQA zBsy_+?YsS15h_>;0@BKzD{{WX4&`0@X{Wc;Ad-%Jcj}ouekY@-P3_gxe;-kg+yXqH zrvVWAzPI9d04n0dQ#cY&Akz1<#+l*>Sp)*gGFqHImkjdJ)R>&CX1N0uC9quoe1h9- z{gR+1+v89WNIzh!$`I|qQj_QTv*T>e-yvJe*?6#0?;OXeQ)HXH$kgaUjw8vlfK9^O zGcSpt!CX+#)qzTVb$!{tTm4B@Qd z?@i6Ai%~Oc+NY!d^cNYqher4JH&oZ+;{hAkv#BXhog`J`rx2%XP)UdVRlzuPmX)h;37{Amd7jz zBP+%52x#>c4lF2aW!4$>s5X1(`wRX>ifZ(jGy`*ntrWO~v{s?K1ra0(hM)zq<_Tn# zI+8{YkSn?TyO{E)BC6m^n8S6WGd9FBu%Xz8e#mD4Zo_EnY? zUkWR6(s_;HavBr;n#LTBk3~$MJ+{(-j#;FX^8awwY)o$6PbQxT87Ke>1kacmgEB9& z%JSMZwrQu`QLDMaJBwK*bKvuH)y&(~yqndS-WirN)#L?c;3Q5nh;YyYc?<=Cor=^f zy=09S)U{zjRuf8g=XIP6C%P}UrWBMA4MzKM>FQL@94eVwQL?>=gNd7-ygkKMVm`uS z&4BD!rT%hUE!_y~}+l_EGb~VIjLvsAC)Hr#kC&fm9~tl&nlI@v(+b@633ciR&^nBh8)Hn6TehS6Pk6 zu`*4yJvL#QevHe6sFMsDy;9V)Ar`?j{ec&nJu|Y}V^+j?75x7IP(ZK001mLg838~B zG?ZZA2ufr?c^u9|#3WQupOS4Sz}b_0&_^M@1r+{At&K%hJU}sk!#B_Z0vu=HtjR%P z6dIrr0f0yml*mCH9{5ScLfixg2;%>h5kN77lJQBM9uj~i6#zqdj%l4|dX@t=0D~7C zzz@M^F`N-Pun6$ThZjr?$|S+PB*w&P1PEY*U(v-Ov4!j{=3D7F`%he5dbX|SZmGOLyXNfAt>_Q*B4QVU5o{MCCHPZ69FLQgSrJ%2A@;9g#ne{ zqbcggU`PB#U^Q0XlJyA)G^YPtU`IK$3=TLUCYk9gLb7((NL5_ z5r8yYW+7fd0q}wKZ3pdO1NNCy<(y}Rge*3wLZ86FB~8WHfWWX0Y%bCtLquS*>IH8K zC(YKZ&EBkD5a(eLz$=VI2AF_R-NY*#ghT0$IxWCV`w0zIGs3oyfU`GPKtK@WtIVNmaG62L(G z4X!RsQ82^Ho-qGG6@{G9PRzFOVu(bnOlz%5XyKa0u?m@2PFF-~p9rJaVIokN*#(uT z!b_mR-M)^E1`Pu=>$h^<)wK`JjX~O$gMNZQJHV(#m~7D+FBELCJk$wW9fM;uf;~tB ztWXTCtrMeM0lJKZCP?D@jD?P9usR5)8+~b=6a<#Z(*j(j?y$p+LBT^Tgyjtq08Ae^ zuptdJ2po6;6hJ`|JPPa;t1ixMoWgtvGcuM4 zt@vQ&l!#fN4D0>xzxgCo{Nd?H1+0h#HUpxKjYpwEX+69HN>l(n6HNB{$@Y#?_uj2y zfK66ZKtU4Bqx@i1_D361t=gL)^?^L?{zf$0xKKOGxn@ zgcJ?K^dF4#dqmXzX~Qy=g*BiIQ3Q3i-V@=#GHutkZTFfir-+S`0x2-TFG0Z_yuv9w z0&3mC7(l@lTmf=JL27bHhkLx6agAE!YinP zDgeVN(1LKEf;8#ZI~emb1Vj5igBw1BeGh{wG=fE#z_i*EEub1ef5%w(0s<5O9N1{C zX|r1#?t#}+QNROl`*sD4fgdm!QTf3gBzJN{ffq2rEIKy_K(};9N_Ag196SXSh!p>9 zcL!OnHCXrUdFTQ{J-`*ffrF_6D?G<6r~-880!t`HI%tD5Fat0YgEVl8ecCsA|3QHp zVT+ZiMHWDQku@VdM0(t1e_w|^d^7+|$%@~`*znyFOHxFO&_t^#zFCJhXu>0~Aq&7k zBj^Hhyp7jxcyjl^hljX`mnIWXcy<2)6fBXJCXGD2+r4o&QaF!Y$~2^g(-=5L4~&5# zn74D7_bfn%DoiCvz{5CLLwtjVG+0BDKf^H?$&DSrlhwvpyaL#Y-@LUm@@Ygo@@*jT zP}empt=ur;PBmHVu<(^BJk-epSVNUY4D>O?BkUnl6TldZM5`V(cJxhHwDbR1e8V`E z>q{KKK^?#tkdjp_D zq6>zCqXmOAq<6&M=QWB|SUu2h1z#$Xm9A5+gf^@vj+ha^YkZ$$GdoAT0w2^@f8Q#sy_(kJji*|c=JC}tyY+A9zTAB@2ji~$qm zA_IWHf;>QhV})ZhzSaW(6Fg})1M#bGXWm1!Jvh?Kta#E)1+1_j6HE15_fN?BVp#U0Rx`1hF)JPGWD`TJ( zp}~Md5*!r}94J|`zyZI1^_FA+?kZNphY=?}T=7_igo+_YmOPnqWy_Z_XV$!#b7#+= zL5CJS8gj%3!HQOH$uSAt3>6rBy{VUh7cW7IK!LMc5nDxQV&@GE!UPUD?Fy4tei-VX zhyT7GlIMh6NcAs{dEOGOdkq(011 z=Qtd6E64x=+4?G=f-#uDjfvgv=&g}I#`sD&?m%Dx2Sxwn5s$K#+PMONE8f|NJoYBr zDT(Qz(+FBc6*a5Nv zZS<2&D-cQoN6ExED#tMnzKIgDsO%vHJq`ja2|m9HzyS^1f*6BAwi>yk2=4we5Cj^M z&_zVWI7){U)G7jP#L&Q0C86g~O!NTj7yz;S>%yPF4^RhQU1&{KxgI89&}Uz$C_tm>2xmyXrfG$0jc9-9Ih^1Hf7aT8^;Sr zBhs#b0fT@84LI^Z&t9Qy$*y0beT1gKJI3331Q0Bij`K8q{XHqn4iO!No&oE8q&J@3=#1 z%sV;7msx001&8QNz&o9wr6j4h01cq%{!(2k z0k9JBEVt}3_`1m>3K(XzVFsH&UId^Apd~A(2k3A(2B>0}4f}CS57x|Ob?)eUy8=yc z8jYx@hC>ljeDUQKT?CJ=5pBwGxxBIW#5VGbqY;1$Rc2aJk9RHnfpbpy6D*%V1$V$S16nqa4NBP({8mhC9@#b`+rp9QJaDP`%?s0AK;7l7lXF zp@9!2JRbNiRgOk{q8%a<9{|bL4r|aSeD-)j_Bmq>xt2?L%D~=Rj9|I{5U1;JIns^wrDqtncj3WXFAH71>C7ROAzIP$4a{0;)@@Mj(P?01I77 zB2AS;6`D{5_0R+W9AHKoXfQ!{puh~ntTJ^pD1ZroXTF#4p(MzRCT9dPy*xM&fi96o zMSfMc;Z^BMH_{RSxOB_?m@P4yNCF3NaEB7Y1DK3-B?I!`2MQ2o7Ld-e>9vGMMg_uYL9FUn}#+y9$pYjjTvLwDAp%kn=`Y zkz=^Z2iWl)hFT@L!Yk?l4|vFfvz`6rFhM1&aXiBsB~<1zC5y|#qLyv2eA_G&Q_GEg z$!vzLh&;5R4LLeBqZ)Fma)R7zc#xt;? zj-o_1keXlt9H25&gxUY&6ndG6c+GdCRw7q;;2@syg!j*Y4tAj7GAsemfsOC!P4J8nw2}rKAx>lC;AwY3wOVo71Imi6L@mB-P90JfHHfO!?$o!m0d%Qy$x&Vh&s9My;ymVIh zE#jfER1t8X0SEt@u=0tgYE<72ICbvj=MUwpycBcnD#!CPR<`=-)Sj7<;PAyWPKRmV z);G{{7ESZE%TW&7(!+-V@lSo7;x>zr#!8Bcg?qh6t@5~Kt90Qb(E*HNlu*_h1@dyR zoNRHAo7`FcvZ#IQ)K61!*}iV#x?Kj~a`TnWaHHj&=eDT?syotT({P8@0{m7C(*fmZt$^jH|Sfgcd-$MZ(Gv0=w%yvyQOJF z6*nEIrk?*es*@*BsLd)d#P_O-XY>_P9gI>!y)7Ww?`fggO~ z51;tOH~#UFpL%=z!|I}p%s*27`{Ylb`qj7o^|3$wWH%P;*ZfB@Fd{Xj4TLk9kWVF5Mp1W_;rfiM4F%g#Ko z|5PvrWpD;ruK=k;T_ywiu!2iWkOqD52UBqS*01|mMLuA~0)a3Il@J3t@C8Ni388Q~ z;?MtF9QyG@Cv=~3$f1zHG>DK5Dd-m43jScGvf%u4-MV$4TY}>qi_!C z5Hwh(4)L(B+(Qd3BhT{i4>4&<#_-|*u@F1T3~>=#3+E1y5g~C7^{NER5DqQz z5?v4Uu;K$PqYE+d6G2h*3Xn6t!4pIA6fJT2_^>h#fB=vX6=4w*(=QTfu@-Id7IFVE z7j{diLn@s@feXY8I^GvnXwt2@fo2p8l`a>sj(WZ@fxu)8?|v8 zxv?9)@f*Q09K~@Q$*~;G@f^`H9o2Ci*|8nn@g3nY9_4W!>9HQ|@gDIpAN6q``LQ4U z@gD&)AO&(D39=v!@*oj1Ar;c?LeCXX&msT8Azg7IAF?4uCL$qnB1I!2MNcC?gCkMT zBUcV2M~@;&lJrD!AyslES+XTva*s~ZBO9_L52GYcvh++6Gj7r*u_7idawdBcGIr7= zS1%8_ z5d$bM!y>a%DRELL*ODTgk}Q*w_2TmRKC%-f5+~JCD{GQ3s}dyh5-`iMFUN8yfwChN zLoiV?FT=7i9rH0EGa>mhD9cjy*b*siaxU5O`FQdt=MpL55-}6=Dy7mab5JWSQzN&s zBbU-MQByS)lPt3mD;JY81yeQ^vn~HpFSjx>ee*YgGdRt5GVcFD^0DGBdL{O)n?e zGdz3qDP_+&t1~%wvo(d!IlU7<(Q`h{Ge8A&KnXMi0RSs}p&m-iwiy4kK^fG(95g~D zR6-$iLLW3jE3`o~)IvG5Lp}6ELDaT3bfZGlK}WPiQMAOc;y^RwqEPfjVKhc%bVg~k zMs4&)akNB-2}(GzGPJ=(b2LbWbV!M`NR9MJK{VDf17tD_NuBgbp)^XRbV?QUYzlM{ z#R)(OlR1|&HP4bViSjt}(>VV#K5O$VwRAdZvP;*qJI!=E-4i@#Z%Z>1J8O~v9$_=? zKsv8_g{6&q%O12iK8ULjYBwOO6@S)nyrrFB|0b&zb;G78`hn3Y<&wOhUQTfvoB zXY~^vKvL)MKnoxP3Ta*0wO!ryUEwue<#k@^wO;M@Uhy?w^>ttQwO`$p0Q@yz@6|iX zl|>&*Fx{zUKhcm0~^iV?j1#MRsIGwp0w` zU=u@*iogROfMi|vWnngEW%gq^00bW95zSQu8Q=gTW;%E_Vt&?Vqa$d0wrGj=Kq2O6 zQDj9+LTQWkX`yy6j`lF1gK3vmYLixKf7WV;wraIDQMmuMX}dORZS`p*0tzalUYwR} z*|u%n_HE%dZsm4v>9%g|R&FOvGBRLo@3wFK_HO|t_j#c=dZl-I zsn>I@=d5rS=Q^c&xwm`0_j|#YdSgUwE7$#aQcdYH_`p;w7qcnR^gYv)QBN~9^^!D8 zvp?f>O!GH?-&a51^n82MC++fl%hyjg6F{3%ehdFNGz8c!33!1WRVg8u{T}#zC74Xp zSAQ#*DkV5fnbR+=^M6CKGfFcmy)!7i6g^G&fS#yU;Bqo8F@^sjPVRL_JQcTmbgWFVv;g>(<^CQdjfHf0-Khr+<5oM@YKe1CeQTQRh zRDp$3PK$FkOW1zl6oUb|j-j%DLDPrBn2y&tjv4rX*|?1<88jOBj4?TrJwu2++3a+f zk)2pHNtlH@c#o}9mFxH}T^N7A^FK)wi!1*#Iq&m>xp3)9Zj@t>i4*yW@lubi(u)__kXcxmfBBa6w~w`XmDv+b_qdx)nLlB(hkr5$ zjX98YS(&4`hJl%#m$;aV7@l{To_$W9?-!O4SvQH9IIo#5J@}b>nNImPf!i0CpBal+ zQ5I;aJCsU^#u zNm)Ok7>_MlpI7>(-FJ)c*n;6Sp#A?dI``R5_c@t&`j2;0ChJrumD;R3*{PYjt>2oe zH5#bdTCOXatle79@EL$pI)(w+rI!P;c$TwMn^FJRep4HvZ`;35J22bZvVD7=K^nbF8@}s$!ZRAU-y6e~ zJEK*azWJFpKQp%x7?lUPIi0zj^Sg=P(y^J?HXj%&@0Td^d%y$OtZy2t&630w9LHn2 zw}l+TE!@I6yu3FXo{`(b0ZYC|dZFjjzi*R+Q@p?1n#3bpz**amYZ|*tIx3Nwx8<^a zX83v%%NH2Xk5C#Gc661sDHY+BfP@rT(~{_&Ntk>Z+p+58pI{~IpufJGb5$R8^%8w zH0wO*%G_}@U8v9d($oK&(3Sbs)%(cD+0&bR!($oJ@jO6noz{=J$Yp)KDgD>)y2Ew- zuaG^=Cpg$web|fL$T^+YD?QJZecAh}*?oP}2^88hecFp1*I_-w!@bkBov*n4C=J_O z!JWv(owP&y-Qio$)4h+@{VA^<*pJ=YEnVI*9p2&m+;jcjVJhF*7vY0*li97|9sc1V zKH??5;4p0BE&k#$KI1ih<1_x(IR4`|KJB`W??ArfOWxy6KIK(@(4=J9CjKbq!$lO(CgwjQaW&_3Y62@FBnPCBG&7 z9ox~}>-h-mH@bX5a`6G5vo!1UQ9t!nfAv|v^(kxc*faX!FUn`K|x@u|M~p|FjN`^r>GS zvLE}mKj?S9+PU2GKY#PX9P}ZRBNNW{HR~PPfgRML{_X$%@jw6dfB*Tv{{ezsyLa&5 z$)iWFUOoSN3<)@V2$7*Zg$U&peAkYhx{Vw=di)47q{xvZOPV~1Qk_781`#Th2r(uB zi4^HsgojaM%AGuW`uqvhkh3pcLZxpeE=y<4~JzrAPi`uz(yu;9Uj3mZOMn6KW!dik0~ z3^}so$&~Sy-D>fj#&qa9cP@txbUD$aLzf8Ud*A-OJNWV9wL72P(l%~} z6f^(t&fYt`eDd?l*ALGd-Sg<`lU9H4nRfQkM_zND?U&wBxAj$7gAP6jVT6{M<(PyP zUWj3a8g7`BVvh;d*j^uUNMea50`|{Vx?wk3Ipe$tV~jG+NMnsQ+UO!``auVebhpK% zqGl|Pc4Lu79*Jan*bSg}dyJbIuCwxtUViuCUx53$D0hF&b&X1{XZ&!3rp^Gr6=iZhWq^USi*R$q;E)>{9JG&V0U9cR-R zL!EQSA6LC~+G?+TG|NfDjGD{}&N86L?`7_V7tTbrQ)y6F4mPebp z&(d)2`RTgv&U^2^{|@}wAjM} zld#4WaDf_n8avYAB5-Kq6?dS41uuxf3~F$L9PFS6HF$?tXaiO)pSXjd#3UP=;ETRl=NJ2fCkca;%gy0V;Xv8Q= zaf(4iVh)wK!}#^ki4ue&6~9OWE9ww_3@l>-1!%@Js_{ezMA73$w8l6>$XS)Ml>|Ql z#ync^6WTzQI==Ukh$y6vp}C_T4~a-B^3jigT!YF6lE!ec*;~dQjWA792#qh%UnXHjekj?E`Mnl2U_YI zudrYh)KG_HDs!34Y^F1x3C(COQw>zG;48ktDs%v@W>sRxFpEipV@h+JvT%LwATw$YvRiLO#lUao@VuOV0 za41UAp;DHddCn z)TSs*=~Q)!ReNexs2Me>Su@npv#Rx@B5f4o)(Y44K=P9VwT1;J8dh|w!GhLsXDX4x zo;ud`u6Zr2RrgARzOw4CKME{ep=Vbb;MK5{t!y$8t5{S560j2yEMy65+0a&$uYTQZ zV>|oUZ$x&oqID)_OS{Sb#dWs3d?Rgdo6EM|g`{q!5N`kf7ua?bQXA5+U~9=~L1~Qe zov}SFB!w$U;u`n3)Xisdm#fX@a#J4Am0)pcP~Gq<^}66-Zd5zlUFm{XyzDI}dCkk& z=MML~?QQ0JvrER`>K9@j+OL1hs9U@6R=~DZ;C~f%8+l3+8_&SOdh4r93qE6}t_#~L z6+G1jKN!LsW~PKGj64g^q??6gu!B2{VtjtMydj?1g(13N4W~H8E3UAMM~q<;Zy3Tg zZt*M+3}m{bHONG^S4`F$cNM1@w(^WQjOC|_ zc*`n%hL^vL=4gf)s*SA@mCd~4G>3Q1V|Fu_s~rF5_R{&rMeZ|OhV17+A1uI*BlKG& z7NQR+2GI~g^rGR2q9;Gvz><@)SFOQ}GuPLG%uuYDwQOfxVOrC2t}drN&E^+hI@5VB zb*WE{%}>vg%-|Sxt6d#hSZ8_Gp{_NnX-tDo$2!%5F1AbnZR}(l%FuFgG~^bSz$ZV1 zL5!pHfY)-C3LV?G1e0`z)UGs?XOX+YgxCM-8gkOsc|jZ zcoUn<_P#Z~XRPl!(;Kqy{`YYM4(fsT8`#3$_41T0XkF5A^UIg^>J@{j*FX4<~pcFY-tZfD=T<~ApkrE#haYaHX= z;WQr21ieNI;!4utZTisQujL8$8q(i zo0{uWS2~|5?q`X^eeM{tcmO+Y;B3E~<&yTe%a;uJKZ_hKI9EBhUp{h}8y?&x|NFBy zUUR-bW>Mpw7~jL)p_MCs(&`>~+OtmGvQs_bOh>!ZK|gk@ir($K_WbEnpXSwno%B|J zJ?twh`?G%@*j*p}kLgZixdVUr4zl~9ubq`XLC)ok$9v4hjd*AC9QvETIpt?w{pSPT z`jhr{nDI{Ck_0!b;qDwi&b?lLR>glfLLX8JBUg> zXoEl)gzPnheN==9_=5_VgcP-eJm`cs2!;8^bwo&P66jyT$Aw?W7~eKhEqH;>XM)ei zcqqtQ(UyE?h zQJ7Ry*o3X8e@{q=j96HXh=~7zc!XC-iTh-UMktBAr-dR0hQH;7qiBk|C5CPlcx8Bo z7*~SL=Z7LEeV7M=C4$wPnBQ~{s0U1 zXNXh?i8ZK}=!t`PPjP??^?(-ZKumqGiTBirRk(=d#0KZ! z5dM%2%@haI;1K-qjFi}p)2N7=xQxxXkL>u3()e(v2v?4rdLScbpIhrZZ> zlh=6D2YDSRks3*DXgGqE_mLY3ekuryvY3Y(_lmU`i$Fqy|2T=xvWF6j7=ZsSIgaJH7V)46>!?mZscJ%LPjVoS1W*tA&dBr|ISser57B@M`6&yxU@!4N2tV1I{#c&s6q+&_ z4YH7*s2~fu@Rar-m8E%3?pc|iIZjRq5&F1Hu}J{>$Xb@g2wCY;5=xEmsZJkSPUmS| z0jiV3sZqhnqQA+Of(LRknsa;Ef^cX!DTth|SeL@shHVs{oF{(F=aCnghU0f^IEstd1We!rA>-X1*)0NWT7%i zrVt8EBAS}$w3@6r4|t$VRe6;ldR&#T4sXhdW=feON}=QAr+~^#Pdb)XT9z-mQ7-DJ zW*MU-2c7?vT8wJAc+zQ$J6e(DhnU&fA%l0AbZLHvDSm^;fla2QBshIcN}}q7qS2%W z+&~ZW0Hy9FsHmBx1~sd-daKEllV3`e*a(%n>7_EU4xyBx#F`aSi3i-^5dOJLU;wQI zAgxK6tG0=z=cJ~($xL`atdQAElpvb%@CVJbn*Z>i%0#Zh3Y+yABJxlU+z3sQkPGQx zCiBXt$<(GYxtYMqtOP)s1j(qLd6UZ2uk+}wbwI7M39xD5tiA9f0}Gp!@DTCP2NtUq z^$1Pm$`8B{qS^YMg(^)R3$oG_s{~t%1gR~HkdwNWY}l3}$eli#oIT2^6ltp3 z)^q<3$(&}GsvX&ivv{PK%Bq?gZmvqQ(xj-*vn?Fpjc~8z5BaP zE0DiBPLm0FBbk#>o+X85B=R->OSELACZIr|oM_ZMqMWAg1=fu~nImouH1#niLKk2YnEeFI>R%m`v?jw!oXAmEaKd z(31#N!^B%oaR9|oImOTPzSt_fD+;}F^s-_6h0>dRG~1Ta`MlVfy@*+yyNJC+>a&PP zcp5jPgb9(?i*llRetO)-KFhQRyG&2}#Pisb{3}gWe82XD#fFT)-j{;_9XAx=cPwrN2b!R$z@YQ^xXOeFw~)KF`^cB87pR*| zi2J2@y14srlz0#bw_q0bz{23_Nc->#j}Qozu)|8+!VqD*hr2wU3&B@f$~Fv-PbrmI zY`c2;rO33&8thD7n+=N~nlt>j(JId4v||@q z&n#-j=}W!HDYQkKy?L36XDpI({DR-xebzg)kJrcL+luAqcb?jEu(-7BYsDw(rp*+~ z=17mVT($aqwTqliAuW@xiO9ivp9rd;x1ho=+`6@E&$$f1K}@U%e5?P==&osCpRY`} zq^zqQ-KAmMEEmcP>?sH0;1Dw{uF90I!_2YmO2Y7p%K-Zi_3*Y~D!;Ees}2#(2@9D8 z`ViNE^DZz>1I7YPsg5we^tI`V`M>y-a~U z*vr(#X&u4;TuWo@*u)pmKMSxO@;fuX=th8&$hjCep zstVen9msb($jLjclDnZxZBT^`+p}$sAB)HjTQd@2FLW)|wHyevjg`q{$v1u1^2o!v zEY^+C+s=gBLpjSbG14$OkFo&Q0?W0}+!z?D%ZiKDgb>PpfaJQMSv23Bs<&6Ea{JFsoa z4)Keza^Mi}pucF{o<45MH>}MFY~{op2&U_3uB6qw34*n@6hRt8J^u#?Fby zci5aJT#O?p;>mg0EIG13PRNz85b?0!CEehiF3$np?9bk{0z8lFK(BdFK<` z(Y>q+k?`n#iT0h_#3bnqTTU&p_u?w(BT3=jke%&Swd4x4lK2-vHqP+&cNunfvMN5J1aJaMKqB=FCo#5fui z#%pA-&LV~Nvem(Jt6@Zw1uNOJ=Wk^liUQ+JYKV4vZ7i=uv|-XdIKKZCp8Z z@aS<|SdSh&b>+rslXgrgQm`fw3f$MHPr;lH3Barqrx#g8VGB|cSa%>&jXDX*MH;AA zy|t&#@(rt$sZ*#@sWQBpb!*qJgbDiv%ule%nf_o6mTc5;)2C6VsJKsi7c|O11QqN|Bm(7f3oe7e;D&&D;u-8i0?Oh{KzSIdOd<=OtTeF0?eLyiYjOkdQ{71u(AFzv5qwCVU8`4oQ#Xdx7LD1 zjg#cjX+<_hOtBNRDynCmoTefmom@%=@1iH~N|00VqrxZ&vsFKq7A+xP4 zRSav7770M78xr4vF{ZrM^fUiJJ$@Q9$Qb8*(8dVyq%h8yDg|txPJ$dzGf?GR3N$*Y zO72xyW0iGQT4yt_R$Oz{byr?{t#!Hlej|@PTjArbK47EkZa(JjTaQ@vo=xxA?~r}2 zJNNP%mc8ki6|dXvtd%dm^0;kQKLYs6QO_MS+YHiM7`rJ|RS%=F&Z^YSv%*y4h}Wul z`9hJcuuwFVrD;fv=MOC5!W7bJ)H0DvP&KX5&Q2%PamOAT@&_8DP+Eu}ECEZ+(3~zh z3lB<|L$$4l|Jg^8KH><(C6AsYw5oVic_ffYh9Y3eG6gC!;)k-~v&c9t#`jK**2(@HeLtl)?X}y+tfqIHUe&>i zef9fqzymk#R>2E5{BXn*xAnW`j8!%^X|tVAJ!XS_&)H;^TQ+lQw}tj{W$k+pyz?#} z-MU~sFAsClt@Re%a?3T{uKjS_H`P-gH7SmnNUY}U0N>^`?v3f?J*D3XHs??F>iwwF&U$x-!zGmAKz_KXRNu42u_Xa z`Nw+w|54~4g5gAHG$~Cy_R_v0VZvmZSsI*nBs}riPHuY|%03#gBK2u)OFJWx^-KdY z-qnR5{#qZ|61M-QD@g`PBLSX;Aeb)+7B5aKT+`Wdm#P;kPKP_>A*~44Lm&oGh(l}+ zKNED?3#fnpRVcP-Z4hl<9U-RLNHEG;@Qi(y>W?8G%Kb7?C& z;89KOJSD>zxyyzeiAM?_xVL-3Er#R+mHI|vN4#VyfPo~7)nKL&QZ-CTF_8lS_Yn#s zRSb`<8r~lHWucDML>NIzLtVyJ2ly?ddnRe5LfDtGd2j|v9(h@njKvQPnM4oWxZd`n zF)0BW4G$UY)6yd8!bye?hHvDfWTVPSq*3H3NqbR}i0fo$J5lpPcg9nm^GqD)e4{!x(q@fij8^N;^-d#d z5q0_09OqUCM%FQhbm8e|7fZ*+ZD9+FtIHe`?YYG-!me6vOqV5b*CC|P?MyffX5YSf zJMS4pq$DdC(wGMp>ZK@!*(8!8QB#lX83aX4b6ZKDmN9U~$$Zoli5lwrlNR0(o#5*mJsta4!NC)ldIl)q?8ZMS^KOG-! z>4jUJrBt}XC5$%-yH-$P3b4dwZgY$4Q#}&Xw=r6-b5k`FSXMW9(5<9&L4{pjaMQMT z6fC|hdtUS&N3!W-Zvg}+hgE_`A7Bh~!Tjn#bS88Pb!c^xvMGn<>(>Ta_N7l?nY~ z!US2vfoAcb&0J_cr@FbMCiADYtZG=(nbmK0b*yc@YDV8!(0T^7a77(hJ3E@w!*;Bs ziG6Hj5AL+3g)e}2IMHMS(bEKGMz7_{pxbZ8`tRe_O8bvZg|UE-(l7^x9eT%cE9_?*zRV((=E(sCwz#;R(Suz9qyV- z>oe02r?_oA4GwpY`_||7x4P|(ae?n!0X`0t=X>S)=J>%s zo^hFPyyPx-RmFWCIEMdR=naqfYKsoJDGyt-*;%@KFOH38q&(J2c?LGXVRBl71L{(r zIk~BBb*$t0%36p&5rh|(?IQEALiKIj`pvw9pOXgyRL%XcffP{ z=txhNv#p4qNAs6)k=yiq4Zo|@eztb(Ku0;qj)S+uI`8E`2RlMcdCNl`^Ki$z+^x=e z&$Afxm(M)u&%XK2f4=gpcm2#^pL#v6Ui7U`_3ecnc;F}J@4+Yjk_Z0}oBBSUp#){R zLp{6vX^oa!u!45;u^26C0TgyjUpB<`d-&+f4xiXk?LrtLk9N$SD_mE#Qknt|&bLDz z4YASr({K6p^S<_ScE2{@j}G~xKRdBM^^*qn+dq}-zyAwB0y4jPK)(V!Km>#_1&qJ> zYe1TK!21J-{42fpvp@kXJ`pUA;Tu5{M6ct6xQRnPH9{gM+K%iLUp*p5X?Y%*ur~zLK=udFGN5v6hkt^z$I+LH0=MvHY~R{>^3XJ!U5Dm zIwUYVltL=h!!hK;6FfvAygo!+#Pmu*6*NK?WIS`pr*J`|##2PrB0n6wugCEx9!w+p zV4~NtFX=lM(P}y@3ax|^49Oh#K<#$g-{XFNt(q(xg~Mq*?{ZzMcL{6=vsw(gU- z8|1_@;=U;Ymmpk4i#n*}L%ta_LP@+9Wa%8&f}H77tx2qwPuxe^xe?I2w^vY#Dqur- zQ-fNhfmhH&0PIEwyo!PRhJvJlgOo;9Q%I#~$ftNnYwZ6+iL5+=G)RQR$dS`XhIGhw zfXECCNgb=mi!{kOLrIQ|Kb90ok)%kHJjsQuNskP{aSTfT0v4ex%6M`_)LOwu6c=~2 z5Ai#rD0@C|oWxOt%EF6}cRELWtVDnO!K#!G({Pb9Ob7KN1*JGkv`kC2TuZiWOSgPW zQt&^{O9wLSIk9BIvV2Ru+)KXfOTYX}!0gMo{6D&!KfAP^vCPZBTujDnOvil8z#PoE ztV`0kOR~g2vxH2|+)U1NOv#Ke%A_5{#7oTVOw&}$&n!&qAq}G}$`Wi%*eo2ROv-Z1 z!O2m_dK{?JvC4OZ#2gGou#_lP#7(9gN+WW?-t_;XbQGw@Lk@g}SUk?*z~BY)|)W&+=TmbU@F5jF9Klis+oq z_uNnZT+8^(PKe~r`-Hjg)X)C>%l|yj0FBL{d`$*@&|aC%C`u#w;!4FE&ZfLj7!=NZ z^iA4y%G&Ji|QGihIKbYmkO#cm`%*hGWQ49o=Q#g%N09-($zc~f}(k~5DB<)CcDAVmc(SZ;;V7 ztL{X+xJ|eV7*U``v-B8LgC{^{Wek4k%RKgo+hZn`qZ_oy8kkKM7QfVkw zV?9=6O;%-HR%IR5FvSLKP*l!Shn2L(^xV~6g}Gl1R%e}2X8l%h4Oej;S8^@aW$o5r zjn*Wc)@lvG-k=F=tvp`^R$(1hbG=u5%~yTh*Kb8vXq8rVYgc#;$apP>dF57T{O90S>%w=tn^SND%E@B z%2B)`)0#dJ?JpIqoSA(n-PEYy{JvSe$6CEra!IlbtXOrp%qWF9aQKE_{Z(yfTBm(l zsEt~wom#0~TBQXCa0rKwjWCIw3N!6PqBYtm#ag9}R;oQ)v`t&JU0b$o+q1P=B+c5b zO^2>sO(_XW>$wVE6$R%6JwcNJF+{B&Bx}`r>HCdq}S=N2sB8omJ!_cWDD4@Mc zo5fjL1y0&kj#z~#3;kK593xWPN-Bc?Ra=#;$Mc_|y^42uPIQo07(H6*tzPTBUhK_Y z?bQm!JUjSxb`HkNB{9dmeSY0Jw^Nn7Eo!$U`UbqYKm09U{cT_ghTs9N zV7t9r*fl}d9bps3G}%SrjWRmqwWozb&aUiAmJQxbOj((A)fTp0tL&mu{N3bhS!eTz z@wEzh&|uJwUIwl_d0k?~ZDP)IVkUlKDUM<$R$?UP+B}5^Mh#&WZQde&-XlihC#GU3 zF5@XSV=_KtHBMtTMq@W#V>h<{VkD;9EZ*YqjVKJx+b?E^Fiv7P{^K?VF3RNYlugz-N*LlHl>Bp`7LEX${TE5+1#t$Gi&K+*H z7=GCx?ua3#2YM*t@@)q`RtId(W^LYPZtiAp{^oCHhj#d0EtY03PK{`uW_YOPYX)a` zerI@&XL+7ydUj`VCTB){#Ee7fEg=Ae7YH5~- zqIPPm&T6gRYOd~Tr6vHawrX?sAb6#Zpyr>dzG|;tYqoA{w|?uehU%bZjkC^MqK0d{ z&TGA9Yq9p)sHW>79%`%JYr^hp{t4<7KIxw;X~k}At(@H;ZH_2wNgP4uk8-H@VP$ks)P>ku8IvW zaT7mr{^@WOU-1T?aM_q}7LRcmpK%j+@z{WI8mDm=hi~>yJX-E?AV+DDmd8@vWmJ9H z-TdLp&f#CqW!{b9AuJu?%<2E$=~$(5fCRtjn{Y1gaxedKFpuyT4|6gvb2C44FUR2O zR`U<%ayw!Fb1A{>HDVmKSaSo1b2LYDJjZi|$a6pca|r(pKp%8MFLXm+bKf|0K<9Hr z$HyTLa%5X?NH<{~=g`Dn+0m}VAJ-Q8Uh)x5M<);M+qE1?+@gIlZC$otoVR0NAUg=4%G*~}v^!{~V-*jRJ@=DKLBe!o=e@agjMJ1;} z7pz(P{&Z9CzUp(lUT>Dj3GmG3VU{ksV6WvHQX_HPfJ9tQVUX}X^E^<(#OaewT1 zKQ>9PcacqY&tdnPUg3A_Wpqz+TTj)Q<;Q_H-b)*In3Z9jPW9X*7R=u1Ay@cPeDv2H z=6C=99Eg|Ie}77t%@uc#!N|sUVxxEf*L9L-uX|5<2-Wv^B=8w#JWX6Yh%fS+#d0zt zPEpL=#NPKLLPgRN`4bf#R$TS#yL6Lxbd+b%ke_K(t?ydzM1aSYrjPGoXL%$``lQEt z<1==yk9BxA(Xik48ANi4n(`($X3=i=gQ|F`r{Qbwc>yPTPp8MPG+qwPd7;1blRs&n zS7y@YX&;mvAL4buzxuCtFRiEd#BZ{dZ+zDrd(e_~eWZ2XO!EDv`O`{KgZIsjkNbwF zavtYOP}wz$98o`E!_VvfcPhHAOV5|4kApb@Zdj& z10M=3h!A4Kh!!tW%xF+yMS=|%GA!s3B*~H{PohkzawW@_E?(VaX2l z+GR_5q}tA&mC_AOF>+v=e%WfyIJYxh%#eY8jxBpO?Wk277uH;RH}BrQb8q}Dd^qvq zX?4Fm>>6%K#6M3b?MND^^2Uk@pI$zhsK=y!vEp=Vd2`UZdE>Tj&G(}A+s(lnkIz+n z&idtf(jS>xwCD8Xy~`J%fCHxF-hbK=n4p3IinXAF4??&baxSHZ+e+x2SJZm!%>^J+ z7)~cwW*j=G+-hrCN1b!8apo9&5yIG9evyH9+h{YP*5YW`q2-^8u*DdpkZKwDV~ax~ znPgWDD%qryPabt7g@Mh7V|`G{_m-3>PKZ*G+--@af})vMql(g5X!7HNMHy4aU34aQuchQ(Q^Z~2ubnT;g6hg@(LlJ(|@ zjXK)tgNNQ}r>CQqcoV6oqPirfUTTPGs;^E3DsXthDqCoSR)*J^a^(tNuC9KiX{e&s zT5NB!GD@ql%g)9pv(G}iVVhp^7p=95Hj3=EZg%L?j)D!wX>}XkcwDRh5xcFrUTLfC zy6AI`0RL*sWp=lw#m#k6U?K^Of=Nh@HzYin&;-=|BT=9jb zTAXo{_EL)&Dg$KzgaGpbk4x&ry0y*Yn9rlI{&J+ak&=bN>%gzMWi;)}HAV@FCA6LmCwIox zXf8)F+~0N37%7jTaaNRTpaKnP$OMM3f_Su}pWMhuO14prQpBX3>d49XO)_|)%p;W+ zI6?36(KMBc8|ny%#q62VkNKM%$ij2RTNZFHVbP@j2|uYPOODc)SdybKN9D<4_AZ!F z+oUKrQpG~@5m!3uA1YBO!2tfSSE_j+r0&us2>MWZ&|DfZk?AO4GSi$$DyKUCbj)@x zPMQDfrRj2b!?eY%lvn|y{JOLINh)HBR883FO**NR=2L&DQfn?XoWq)%pjg+@cH)hu z$BL-Ijylu`{q(F(5~^BlR#a?GG^*S5)<_lqcF(4o35Pf$-9fWTow7bPur4FsRn^qU z;Ox??H#O&t;tDph%22FrEtO(L*w4YIh^ELtt z9c=Up8(Zb2RkJZo&`xbT-15~{vfl-7X2;7k&VDsiRQ02ERasKZ@DpYr)gtJS8(*eU z>6((Wstn~z+iZ2Vr{m(TZXs)4o%;5`L1L?d=~Z0er7)neZ0bo_>(S*{*tz$8F1`@h zR{$xudxHvab}zf#*A@7Z4MuTzf4k!Uu?qLaHG6P+6DC{1ZWET48L(7cd$9@QH>P4N zQ!WqdS0bCVG{;qzaRnS;7^Ba?GA1vRpFHJ9VeHB?PUliT^gs#QwY|#~b9qhIS^}1` zhZQdJh1I;{&uZzvRjzR{2h8Fqt60mqZLyvS9OFJijK&j8PAzGfO|(_GYT~WwccVmPrEQ_ndc!%+E}D(iIp*t! z?Hgjk;^w+k6Y_2uEm!Y0w8^~b?xIi4no%2j&!$fHyT00M&nj8Dt_h$+@GYW0eA zl{S3^2-^bY%|BO6EPz4nOJRHe`jXFPc5F(_?#KT5-Rcswe^*Dv>;4s{8}{OeQPf)L z7LUyPF7Lp*%{|yCncQ<;EMq$jZ#YusIaufgR;K}@0hwhpHav0aRDc2WH1&APbGt>tVf|9HpuhBRWoRo`-{`d)hd zxYR&Yxl9k5dZN^!zP&Y2!Q>pc(H&6Dd;ai+Th{Br;4dh_q5l_2 ze;T>o%)xuXp0nSAkIQrad#7ETt%)wozx>z5hG)!ae)zCIer z)qPnY#I>LcGGP(_DqQzbVU{4?%3%`S8OIblS>6>O6z1R+24L!u;pA1{8GefN?I0Yr z;cs~1Z6%zaiJ=e{VH~O<5$54KWg(-D-ViAv;3!}T#tqPvC$m=4hK1YQkPj_yUpW3!XQ9WAwK3~j~L@;nIa{^p*^ymxQ$FfE~Fw3-bKEk zMmFC*Qrj(}T}0}lfE}YehNB%0Awu3^19Id)y5eD-NH*ePS|Gy#0KiS+WC2V-48%b% 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�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 YhL)Ne6#gqT_nm^?b&(;+$Zjb8AFDC-82|tP literal 0 HcmV?d00001 diff --git a/youtube/__init__.py b/.archive/youtube/__init__.py similarity index 99% rename from youtube/__init__.py rename to .archive/youtube/__init__.py index fb5b9008..46fb7bf5 100644 --- a/youtube/__init__.py +++ b/.archive/youtube/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + import json import re import time diff --git a/zeal/__init__.py b/.archive/zeal/__init__.py similarity index 93% rename from zeal/__init__.py rename to .archive/zeal/__init__.py index a039b486..83db8f85 100644 --- a/zeal/__init__.py +++ b/.archive/zeal/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + from subprocess import run from albert import * diff --git a/api_test/__init__.py b/api_test/__init__.py index 6bb95d64..ee3a48a1 100644 --- a/api_test/__init__.py +++ b/api_test/__init__.py @@ -9,109 +9,132 @@ Synopsis: [delay|throw] """ +# Copyright (c) 2022 Manuel Schneider + from albert import * import os from time import sleep - -__title__ = "Api Test" -__version__ = "0.4.2" -__triggers__ = "test " -__authors__ = "Manuel S." -#__exec_deps__ = ["whatever"] - -iconPath = iconLookup("albert") - - -# Can be omitted -def initialize(): - pass - - -# Can be omitted -def finalize(): - pass - - -def handleQuery(query): - if not query.isTriggered: - return - - # Note that when storing a reference to query, e.g. in a closure, you must not use - # query.isValid. Apart from the query beeing invalid anyway it will crash the appplication. - # The Python type holds a pointer to the C++ type used for isValid(). The C++ type will be - # deleted when the query is finished. Therfore getting isValid will result in a SEGFAULT. - - if query.string.startswith("delay"): - sleep(2) - return Item(id=__title__, - icon=os.path.dirname(__file__)+"/plugin.svg", - text="Delayed test item", - subtext="Query string: %s" % query.string) - - if query.string.startswith("throw"): - raise ValueError('EXPLICITLY REQUESTED TEST EXCEPTION!') - - info(query.string) - info(query.rawString) - info(query.trigger) - info(str(query.isTriggered)) - info(str(query.isValid)) - - critical(query.string) - warning(query.string) - debug(query.string) - debug(query.string) - - results = [] - - item = Item() - - item.icon = iconPath - item.text = 'Python item containing %s' % query.string - item.subtext = 'Python description' - item.completion = __triggers__ + 'Completion Harharhar' - item.urgency = ItemBase.Notification # Alert, Normal - info(item.icon) - info(item.text) - info(item.subtext) - info(item.completion) - info(str(item.urgency)) - def function(): info(query.string) - item.addAction(FuncAction("Print info", function)) - item.addAction(FuncAction("Print warning", lambda: warning(query.string))) - results.append(item) - - item = Item(id=__title__, - icon=os.path.dirname(__file__)+"/plugin.svg", - text="This is the primary text", - subtext="This is the subtext, some kind of description", - completion=__triggers__ + 'Hellooohooo!', - urgency=ItemBase.Alert, - actions=[ - FuncAction(text="FuncAction", - callable=lambda: critical(query.string)), - ClipAction(text="ClipAction", - clipboardText="blabla"), - UrlAction(text="UrlAction", - url="https://www.google.de"), - ProcAction(text="ProcAction", - commandline=["espeak", "hello"], - cwd="~"), - TermAction(text="TermAction", - commandline=["sleep", "5"], - cwd="~/git"), - TermAction(text="TermAction", - script="[ -e issue ] && cat issue | echo /etc/issue not found.", - behavior=TermAction.CloseBehavior.DoNotClose, - cwd="/etc") - ]) - results.append(item) - - - # Api v 0.2 - info(configLocation()) - info(cacheLocation()) - info(dataLocation()) - - return results +md_iid = "0.5" +md_version = "1.3" +md_name = "API Test" +md_description = "Test the python API 0.5" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/api_test" +md_maintainers = "@manuelschneid3r" +md_authors = "@manuelschneid3r" + +class Plugin(QueryHandler): + def id(self): + return "someid"; + + def name(self): + return "somename"; + + def description(self): + return "somedesc"; + + def initialize(self): + info("initialize") + + def finalize(self): + info("finalize") + + def extensions(self): + return [self.e] + + def handleQuery(self, query): + # Note that when storing a reference to query, e.g. in a closure, you must not use + # query.isValid. Apart from the query being invalid anyway it will crash the application. + # The Python type holds a pointer to the C++ type used for isValid(). The C++ type will be + # deleted when the query is finished. Therefore getting isValid will result in a SEGFAULT. + + if query.string.startswith("delay"): + sleep(2) + return Item(id=__title__, + text="Delayed test item", + subtext="Query string: %s" % query.string, + icons=os.path.dirname(__file__)+"/plugin.svg") + + if query.string.startswith("throw"): + raise ValueError('EXPLICITLY REQUESTED TEST EXCEPTION!') + + info(query.string) + info(query.rawString) + info(query.trigger) + info(str(query.isTriggered)) + info(str(query.isValid)) + + critical(query.string) + warning(query.string) + debug(query.string) + debug(query.string) + + results = [] + + item = Item() + + item.icon = iconPath + item.text = 'Python item containing %s' % query.string + item.subtext = 'Python description' + item.completion = __triggers__ + 'Completion Harharhar' + item.urgency = ItemBase.Notification # Alert, Normal + info(item.icon) + info(item.text) + info(item.subtext) + info(item.completion) + info(str(item.urgency)) + def function(): info(query.string) + item.addAction(FuncAction("Print info", function)) + item.addAction(FuncAction("Print warning", lambda: warning(query.string))) + results.append(item) + + item = Item(id=__title__, + text="This is the primary text", + subtext="This is the subtext, some kind of description", + completion=__triggers__ + 'Hellooohooo!', + icons=os.path.dirname(__file__)+"/plugin.svg", + actions=[ + Action( + id="clip", + text="setClipboardText (ClipAction)", + callable=lambda: setClipboardText(text=configLocation()) + ), + Action( + id="url", + text="openUrl (UrlAction)", + callable=lambda: openUrl(url="https://www.google.de") + ), + Action( + id="run", + text="runDetachedProcess (ProcAction)", + callable=lambda: runDetachedProcess( + cmdln=["espeak", "hello"], + workdir="~" + ) + ), + Action( + id="term", + text="runTerminal (TermAction)", + callable=lambda: runTerminal( + script="[ -e issue ] && cat issue | echo /etc/issue not found.", + workdir="/etc", + close_on_exit=False + ) + ), + Action( + id="notify", + text="sendTrayNotification", + callable=lambda: sendTrayNotification( + title="Title", + msg="Message" + ) + ) + ]) + results.append(item) + + info(configLocation()) + info(cacheLocation()) + info(dataLocation()) + + query.add(results) diff --git a/docker/__init__.py b/docker/__init__.py index bdd40a7a..d21a3561 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -2,73 +2,85 @@ Docker wrapper (prototype) """ -from albert import TermAction, FuncAction, ClipAction, Item +# Copyright (c) 2022 Manuel Schneider + +from albert import * import docker import pathlib -__title__ = "Docker" -__version__ = "0.4.1" -__triggers__ = "d " -__authors__ = "Manuel S." -__py_deps__ = ["docker"] +md_iid = "0.5" +md_version = "1.2" +md_name = "Docker" +md_description = "Control your docker instance" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/docker" +md_maintainers = "@manuelschneid3r" +md_authors = "@manuelschneid3r" +md_bin_dependencies = "docker" +md_lib_dependencies = "docker" -icon_running = str(pathlib.Path(__file__).parent / "running.png") -icon_stopped = str(pathlib.Path(__file__).parent / "stopped.png") -client = None +class Plugin(QueryHandler): -def initialize(): - global client - client = docker.from_env() - if client: - return - client = docker.DockerClient(base_url='unix://var/run/docker.sock') - if not client: - raise "Failed to initialize client." + def id(self): + return __name__ + def name(self): + return md_name -def handleQuery(query): - if query.isValid and query.isTriggered: + def description(self): + return md_description - query.disableSort() - items = [] + def defaultTrigger(self): + return "d " + + def initialize(self): + self.icon_running = [str(pathlib.Path(__file__).parent / "running.png")] + self.icon_stopped = [str(pathlib.Path(__file__).parent / "stopped.png")] + self.client = docker.from_env() + if not self.client: + self.client = docker.DockerClient(base_url='unix://var/run/docker.sock') + if not self.client: + raise "Failed to initialize client." - for container in client.containers.list(all=True): + + def handleQuery(self, query): + items = [] + for container in self.client.containers.list(all=True): # Create dynamic actions if container.status == 'running': actions = [ - FuncAction("Stop container", lambda c=container: c.stop()), - FuncAction("Restart", lambda c=container: c.restart()), + Action("stop", "Stop container", lambda c=container: c.stop()), + Action("restart", "Restart container", lambda c=container: c.restart()) ] else: - actions = [FuncAction("Start", lambda c=container: c.start())] + actions = [ + Action("start", "Start container", lambda c=container: c.start()) + ] actions.extend([ - TermAction("Logs", "docker logs -f %s" % container.id, - behavior=TermAction.CloseBehavior.DoNotClose), - FuncAction("Remove (forced, with volumes)", lambda c=container: c.remove(v=True, force=True)), - ClipAction("Copy id to clipboard", container.id) + Action("logs", "Logs", lambda c=container.id: runTerminal("docker logs -f %s" % c, close_on_exit=False)), + Action("remove", "Remove (forced, with volumes)", lambda c=container: c.remove(v=True, force=True)), + Action("copy-id", "Copy id to clipboard", lambda id=container.id: setClipboardText(id)) ]) - item = Item( + query.add(Item( id=container.id, - text="%s %s" % (container.name, ", ".join(container.image.tags)), + text="%s (%s)" % (container.name, ", ".join(container.image.tags)), subtext=container.id, - icon=icon_running if container.status == 'running' else icon_stopped, + icon=self.icon_running if container.status == 'running' else self.icon_stopped, actions=actions - ) - - items.append(item) + )) - for image in reversed(client.images.list()): + for image in reversed(self.client.images.list()): item = Item( id=image.short_id, text=str(image.tags), subtext=image.id, - icon=icon_stopped, + icon=self.icon_stopped, actions=[ - FuncAction("Run with command: %s" % query.string, lambda i=image: client.containers.run(i, query.string)), - FuncAction("Remove", lambda i=image: i.remove()) + Action("run", "Run with command: %s" % query.string, lambda i=image: client.containers.run(i, query.string)), + Action("rmi", "Remove image", lambda i=image: i.remove()) ] ) diff --git a/jetbrains_projects b/jetbrains_projects deleted file mode 160000 index b7157473..00000000 --- a/jetbrains_projects +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b7157473cc923fe4f15023c85a032eeab3627652 diff --git a/locate/__init__.py b/locate/__init__.py deleted file mode 100644 index 5316893f..00000000 --- a/locate/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Find and open files. - -Unix 'locate' wrapper extension. Note that it is up to you to ensure that the locate database is \ -up to date. - -This extensions is intended as secondary way to find files. Use the files extension for often used \ -files and fast lookups and this extension for everything else. - -Synopsis: [filter] - -where ' searches basenames and '' searches the full path """ - -import os -import re -import subprocess - -from albert import Item, TermAction, UrlAction, iconLookup - -__title__ = "Locate" -__version__ = "0.4.1" -__triggers__ = ["''", "'"] # Order matters since 2 is prefix of 1 -__authors__ = "Manuel S." -__exec_deps__ = ['locate'] - -iconPath = iconLookup(["preferences-system-search", "system-search" "search", "text-x-generic"]) - -def handleQuery(query): - results = [] - if query.isTriggered: - if len(query.string) > 2: - pattern = re.compile(query.string, re.IGNORECASE) - proc = subprocess.Popen(['locate', '-i' if query.trigger == "''" else "-bi", query.string], stdout=subprocess.PIPE) - for line in proc.stdout: - path = line.decode().strip() - basename = os.path.basename(path) - results.append( - Item( - id=path, - icon=iconPath, - text=pattern.sub(lambda m: "%s" % m.group(0), basename), - subtext=path, - completion="%s%s" % (__triggers__, basename), - actions=[UrlAction("Open", "file://%s" % path)])) - else: - results.append( - Item( - id=__title__, - icon=iconPath, - text="Update locate database", - subtext="Type at least three chars for a seach", - actions=[TermAction("Update database", ["sudo", "updatedb"])])) - - return results diff --git a/python_eval/__init__.py b/python_eval/__init__.py index c91e1c5f..792bf52a 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -4,40 +4,58 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + from albert import * -from math import * from builtins import pow -try: - import numpy as np -except ImportError: - pass +from math import * import os -__title__ = "Python Eval" -__version__ = "0.4.0" -__triggers__ = "py " -__authors__ = "Manuel S." +md_iid = "0.5" +md_version = "1.2" +md_name = "Python Eval" +md_description = "Evaluate Python code" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/python_eval" +md_maintainers = "@manuelschneid3r" +md_authors = "@manuelschneid3r" +class Plugin(QueryHandler): -iconPath = os.path.dirname(__file__)+"/python.svg" + def id(self): + return __name__ + def name(self): + return md_name -def handleQuery(query): - if query.isTriggered: - item = Item(id=__title__, icon=iconPath) - stripped = query.string.strip() + def description(self): + return md_description - if stripped == '': - item.text = "Enter a python expression" - item.subtext = "Math is in the namespace and, if installed, also Numpy as 'np'" - return item - else: + def defaultTrigger(self): + return "py " + + def synopsis(self): + return "" + + def initialize(self): + self.iconPath = os.path.dirname(__file__)+"/python.svg" + + def handleQuery(self, query): + stripped = query.string.strip() + if stripped: try: - result = eval(stripped) + result = str(eval(stripped)) except Exception as ex: - result = ex - item.text = str(result) - item.subtext = type(result).__name__ - item.addAction(ClipAction("Copy result to clipboard", str(result))) - item.addAction(FuncAction("Execute", lambda: exec(str(result)))) - return item + result = str(ex) + + query.add(Item( + id="py_eval", + text=str(result), + subtext=type(result).__name__, + completion=query.trigger + result, + icon=[self.iconPath], + actions = [ + Action("copy", "Copy result to clipboard", lambda r=str(result): setClipboardText(r)), + Action("exec", "Execute python code", lambda r=str(result): exec(stripped)), + ] + )) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index edd6d131..8f71676d 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -4,6 +4,8 @@ Synopsis: """ +# Copyright (c) 2022 Manuel Schneider + from albert import * from locale import getdefaultlocale from urllib import request, parse @@ -12,87 +14,101 @@ import os from socket import timeout -__title__ = "Wikipedia" -__version__ = "0.4.5" -__triggers__ = "wiki " -__authors__ = "Manuel S." - -iconPath = ":wikipedia" -baseurl = 'https://en.wikipedia.org/w/api.php' -user_agent = "org.albert.wikipedia" -limit = 20 - - -def initialize(): - global baseurl - params = { - 'action': 'query', - 'meta': 'siteinfo', - 'utf8': 1, - 'siprop': 'languages', - 'format': 'json' - } - - get_url = "%s?%s" % (baseurl, parse.urlencode(params)) - req = request.Request(get_url, headers={'User-Agent': user_agent}) - try: - with request.urlopen(req, timeout=5) as response: - data = json.loads(response.read().decode('utf-8')) - languages = [lang['code'] for lang in data['query']['languages']] - local_lang_code = getdefaultlocale()[0][0:2] - if local_lang_code in languages: - baseurl = baseurl.replace("en", local_lang_code) - except timeout: - critical('Error getting languages - socket timed out. Defaulting to EN.') - except Exception as error: - critical('Error getting languages (%s). Defaulting to EN.' % error) - - -def handleQuery(query): - if query.isTriggered: - query.disableSort() - - # avoid rate limiting - time.sleep(0.1) - if not query.isValid: - return +md_iid = "0.5" +md_version = "1.5" +md_name = "Wikipedia" +md_description = "Search Wikipedia articles." +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/wikipedia" +md_maintainers = "@manuelschneid3r" +md_authors = "@manuelschneid3r" - stripped = query.string.strip() +class Plugin(QueryHandler): + + iconPath = ":wikipedia" + baseurl = 'https://en.wikipedia.org/w/api.php' + user_agent = "org.albert.wikipedia" + limit = 20 + + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return "wiki " + + + def initialize(self): + params = { + 'action': 'query', + 'meta': 'siteinfo', + 'utf8': 1, + 'siprop': 'languages', + 'format': 'json' + } + + get_url = "%s?%s" % (self.baseurl, parse.urlencode(params)) + req = request.Request(get_url, headers={'User-Agent': self.user_agent}) + try: + with request.urlopen(req, timeout=5) as response: + data = json.loads(response.read().decode('utf-8')) + languages = [lang['code'] for lang in data['query']['languages']] + local_lang_code = getdefaultlocale()[0][0:2] + if local_lang_code in languages: + self.baseurl = self.baseurl.replace("en", local_lang_code) + except timeout: + critical('Error getting languages - socket timed out. Defaulting to EN.') + except Exception as error: + critical('Error getting languages (%s). Defaulting to EN.' % error) + + + def handleQuery(self, query): + stripped = query.string.strip() if stripped: + # avoid rate limiting + time.sleep(0.1) + if not query.isValid: + return + results = [] params = { 'action': 'opensearch', 'search': stripped, - 'limit': limit, + 'limit': self.limit, 'utf8': 1, 'format': 'json' } - get_url = "%s?%s" % (baseurl, parse.urlencode(params)) - req = request.Request(get_url, headers={'User-Agent': user_agent}) + get_url = "%s?%s" % (self.baseurl, parse.urlencode(params)) + req = request.Request(get_url, headers={'User-Agent': self.user_agent}) with request.urlopen(req) as response: data = json.loads(response.read().decode('utf-8')) - for i in range(0, min(limit, len(data[1]))): + for i in range(0, min(self.limit, len(data[1]))): title = data[1][i] summary = data[2][i] url = data[3][i] - results.append(Item(id=__title__, - icon=iconPath, + results.append(Item(id="wiki", text=title, subtext=summary if summary else url, completion=title, + icon=[self.iconPath], actions=[ - UrlAction("Open article on Wikipedia", url), - ClipAction("Copy URL", url) + Action("open", "Open article on Wikipedia", lambda u=url: openUrl(u)), + Action("copy", "Copy URL to clipboard", lambda u=url: setClipBoardText(u)) ])) - return results + query.add(results) else: - return Item(id=__title__, - icon=iconPath, - text=__title__, - subtext="Enter a query to search on Wikipedia") + query.add(Item(id="wiki", + text=md_name, + subtext="Enter a query to search on Wikipedia", + icon=[self.iconPath])) diff --git a/xkcd b/xkcd deleted file mode 160000 index bf88a964..00000000 --- a/xkcd +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bf88a964473d65b39c9e09eb48dabb847206f06f From 2b42bd61556519ca8fca7d57c236c5250fd0fec5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 27 Dec 2022 12:50:58 +0100 Subject: [PATCH 058/355] archive rand --- {rand => .archive/rand}/__init__.py | 0 {rand => .archive/rand}/rand.png | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename {rand => .archive/rand}/__init__.py (100%) rename {rand => .archive/rand}/rand.png (100%) diff --git a/rand/__init__.py b/.archive/rand/__init__.py similarity index 100% rename from rand/__init__.py rename to .archive/rand/__init__.py diff --git a/rand/rand.png b/.archive/rand/rand.png similarity index 100% rename from rand/rand.png rename to .archive/rand/rand.png From 96a0bb03c7c0299ad7f67f2cadfd948e2c6c291a Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 27 Dec 2022 12:51:34 +0100 Subject: [PATCH 059/355] trash 1.2 port 0.18 --- .archive/trash/__init__.py | 29 ------ trash/__init__.py | 48 ++++++++++ trash/trash.svg | 190 +++++++++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+), 29 deletions(-) delete mode 100644 .archive/trash/__init__.py create mode 100644 trash/__init__.py create mode 100644 trash/trash.svg diff --git a/.archive/trash/__init__.py b/.archive/trash/__init__.py deleted file mode 100644 index d123aec1..00000000 --- a/.archive/trash/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Open virtual trash location. - -This extension provides a single item which opens the systems virtual trash \ -location in your default file manager. - -Synopsis: """ - -# Copyright (c) 2022 Manuel Schneider - -import re - -from albert import Item, UrlAction, iconLookup - -__title__ = "Trash" -__version__ = "0.4.0" -__authors__ = "Manuel S." -iconPath = iconLookup("user-trash-full") - -def handleQuery(query): - if query.string.strip() and "trash".startswith(query.string.lower()): - pattern = re.compile(query.string, re.IGNORECASE) - return Item(id="trash-open", - icon=iconPath, - text=pattern.sub(lambda m: "%s" % m.group(0), "Trash"), - subtext="Show trash folder", - completion="trash", - actions=[UrlAction("Show", "trash:///")]) diff --git a/trash/__init__.py b/trash/__init__.py new file mode 100644 index 00000000..f28bb1b0 --- /dev/null +++ b/trash/__init__.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +""" +This extension provides a single item which opens the +systems trash location in your default file manager. +""" + +from albert import * +import os +from platform import system +from pathlib import Path + +md_iid = "0.5" +md_version = "1.2" +md_name = "Trash" +md_description = "Open trash" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/trash" +md_authors = md_maintainers = "@manuelschneid3r" + +class Plugin(QueryHandler): + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def initialize(self): + if (system() == 'Linux'): + trash_path = "trash:///" + icon = ["xdg:user-trash-full", os.path.dirname(__file__)+"/trash.svg"] + elif (system() == 'Darwin'): + trash_path = "file://%s/.Trash" % Path.home() + icon = [os.path.dirname(__file__)+"/trash.svg"] + else: + raise NotImplementedError("%1 not supported" % system()) + + self.trash_item = Item(id="trash-open", + text="Trash", + subtext="Open trash folder", + icon=icon, + actions=[Action("trash-open", "Open trash", lambda path=trash_path: openUrl(path))]) + + def handleQuery(self, query): + query.add(self.trash_item) \ No newline at end of file diff --git a/trash/trash.svg b/trash/trash.svg new file mode 100644 index 00000000..9764f7bf --- /dev/null +++ b/trash/trash.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d626b75bd5f1dc926213ac3e1233dd802bf48d6c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 3 Jan 2023 02:46:43 +0100 Subject: [PATCH 060/355] Port 0.5 awiki --- .archive/arch_wiki/__init__.py | 73 ----------------- .../arch_wiki => arch_wiki}/ArchWiki.svg | 2 +- arch_wiki/__init__.py | 81 +++++++++++++++++++ 3 files changed, 82 insertions(+), 74 deletions(-) delete mode 100644 .archive/arch_wiki/__init__.py rename {.archive/arch_wiki => arch_wiki}/ArchWiki.svg (97%) create mode 100644 arch_wiki/__init__.py diff --git a/.archive/arch_wiki/__init__.py b/.archive/arch_wiki/__init__.py deleted file mode 100644 index 006de12f..00000000 --- a/.archive/arch_wiki/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Search Arch Linux Wiki articles. - -Synopsis: """ - -# Copyright (c) 2022 Manuel Schneider - -from albert import * -from urllib import request, parse -import json -import os - -__title__ = "Arch Wiki" -__version__ = "0.4.1" -__triggers__ = "awiki " -__authors__ = "Manuel S." - -iconPath = os.path.dirname(__file__) + "/ArchWiki.svg" -baseurl = 'https://wiki.archlinux.org/api.php' -user_agent = "org.albert.extension.python.archwiki" - - -def handleQuery(query): - if query.isTriggered: - query.disableSort() - - stripped = query.string.strip() - - if stripped: - results = [] - - params = { - 'action': 'opensearch', - 'search': stripped, - 'limit': "max", - 'redirects': 'resolve', - 'utf8': 1, - 'format': 'json' - } - get_url = "%s?%s" % (baseurl, parse.urlencode(params)) - req = request.Request(get_url, headers={'User-Agent': user_agent}) - - with request.urlopen(req) as response: - data = json.loads(response.read().decode()) - for i in range(0, len(data[1])): - title = data[1][i] - summary = data[2][i] - url = data[3][i] - - results.append(Item(id=__title__, - icon=iconPath, - text=title, - subtext=summary if summary else url, - completion=title, - actions=[ - UrlAction("Open article", url), - ClipAction("Copy URL", url) - ])) - if results: - return results - - return Item(id=__title__, - icon=iconPath, - text="Search '%s'" % query.string, - subtext="No results. Start a online search on Arch Wiki", - actions=[UrlAction("Open search", "https://wiki.archlinux.org/index.php?search=%s" % query.string)]) - - else: - return Item(id=__title__, - icon=iconPath, - text=__title__, - subtext="Enter a query to search on the Arch Wiki") diff --git a/.archive/arch_wiki/ArchWiki.svg b/arch_wiki/ArchWiki.svg similarity index 97% rename from .archive/arch_wiki/ArchWiki.svg rename to arch_wiki/ArchWiki.svg index 5a193897..61f55ed9 100644 --- a/.archive/arch_wiki/ArchWiki.svg +++ b/arch_wiki/ArchWiki.svg @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py new file mode 100644 index 00000000..1404a561 --- /dev/null +++ b/arch_wiki/__init__.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2022-2023 Manuel Schneider + +from albert import * +from urllib import request, parse +import json +import os + +md_iid = "0.5" +md_version = "1.2" +md_name = "ArchLinux Wiki" +md_description = "Search ArchLinux Wiki articles" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/awiki" +md_maintainers = "@manuelschneid3r" + + +class Plugin(QueryHandler): + + icon = [os.path.dirname(__file__) + "/ArchWiki.svg"] + baseurl = 'https://wiki.archlinux.org/api.php' + search_url = "https://wiki.archlinux.org/index.php?search=%s" + user_agent = "org.albert.extension.python.archwiki" + + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return "awiki " + + def handleQuery(self, query): + stripped = query.string.strip() + if stripped: + results = [] + + params = { + 'action': 'opensearch', + 'search': stripped, + 'limit': "max", + 'redirects': 'resolve', + 'utf8': 1, + 'format': 'json' + } + get_url = "%s?%s" % (self.baseurl, parse.urlencode(params)) + req = request.Request(get_url, headers={'User-Agent': self.user_agent}) + + with request.urlopen(req) as response: + data = json.loads(response.read().decode()) + for i in range(0, len(data[1])): + title = data[1][i] + summary = data[2][i] + url = data[3][i] + + results.append(Item(id=__name__, + text=title, + subtext=summary if summary else url, + icon=self.icon, + actions=[ + Action("open", "Open article", lambda u=url: openUrl(u)), + Action("copy", "Copy URL", lambda u=url: setClipboardText(u)) + ])) + if results: + query.add(results) + + query.add( Item(id=__name__, + text="Search '%s'" % query.string, + subtext="No results. Start online search on Arch Wiki", + icon=self.icon, + actions=[Action("search", "Open search", lambda s=query.string: self.search_url % s)])) + + else: + query.add(Item(id=__name__, + text=md_name, + icon=self.icon, + subtext="Enter a query to search on the Arch Wiki")) From c4607b02dadf31a841ef039feb44eaf4f42b0e43 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 3 Jan 2023 02:46:50 +0100 Subject: [PATCH 061/355] Port 0.5 aur --- .archive/aur/__init__.py | 106 ------------------------- aur/__init__.py | 140 +++++++++++++++++++++++++++++++++ {.archive/aur => aur}/arch.svg | 2 +- 3 files changed, 141 insertions(+), 107 deletions(-) delete mode 100644 .archive/aur/__init__.py create mode 100644 aur/__init__.py rename {.archive/aur => aur}/arch.svg (97%) diff --git a/.archive/aur/__init__.py b/.archive/aur/__init__.py deleted file mode 100644 index 148b32c8..00000000 --- a/.archive/aur/__init__.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Query and install ArchLinux User Repository (AUR) packages. - -You can search for packages and open their URLs. This extension is also intended to be used to \ -quickly install the packages. If you are missing your favorite AUR helper tool send a PR. - -Synopsis: """ - -# Copyright (c) 2022 Manuel Schneider - -from albert import * -from shutil import which -from datetime import datetime -from urllib import request, parse -import json -import os -import re - -__title__ = "Archlinux User Repository" -__version__ = "0.4.4" -__triggers__ = "aur " -__authors__ = "Manuel S." - -iconPath = os.path.dirname(__file__)+"/arch.svg" -baseurl = 'https://aur.archlinux.org/rpc/' -install_cmdline = None - -if which("yaourt"): - install_cmdline = "yaourt -S aur/%s" -elif which("pacaur"): - install_cmdline = "pacaur -S aur/%s" -elif which("yay"): - install_cmdline = "yay -S aur/%s" -elif which("paru"): - install_cmdline = "paru -S aur/%s" - -def handleQuery(query): - if not query.isTriggered: - return - - query.disableSort() - - stripped = query.string.strip() - - if stripped: - params = { - 'v': '5', - 'type': 'search', - 'by': 'name', - 'arg': stripped - } - url = "%s?%s" % (baseurl, parse.urlencode(params)) - req = request.Request(url) - - with request.urlopen(req) as response: - data = json.loads(response.read().decode()) - if data['type'] == "error": - return Item( - id=__title__, - icon=iconPath, - text="Error", - subtext=data['error'] - ) - else: - results = [] - pattern = re.compile(query.string, re.IGNORECASE) - results_json = data['results'] - results_json.sort(key=lambda item: item['Name']) - results_json.sort(key=lambda item: len(item['Name'])) - - for entry in results_json: - name = entry['Name'] - item = Item( - id = __title__, - icon = iconPath, - text = "%s %s (%s)" % (pattern.sub(lambda m: "%s" % m.group(0), name), entry['Version'], entry['NumVotes']), - completion = "%s%s" % (__triggers__, name) - ) - subtext = entry['Description'] if entry['Description'] else "[No description]" - if entry['OutOfDate']: - subtext = '[Out of date: %s] %s' % (datetime.fromtimestamp(entry['OutOfDate']).strftime("%F"), subtext) - if entry['Maintainer'] is None: - subtext = '[Orphan] %s' % subtext - item.subtext = subtext - - if install_cmdline: - pkgmgr = install_cmdline.split(" ", 1) - item.actions = [ - TermAction("Install using %s" % pkgmgr[0], install_cmdline % name), - TermAction("Install using %s (noconfirm)" % pkgmgr[0], install_cmdline % name + " --noconfirm") - ] - - item.addAction(UrlAction("Open AUR website", "https://aur.archlinux.org/packages/%s/" % name)) - - if entry['URL']: - item.addAction(UrlAction("Open project website", entry['URL'])) - - results.append(item) - return results - else: - return Item(id=__title__, - icon=iconPath, - text=__title__, - subtext="Enter a query to search the AUR", - actions=[UrlAction("Open AUR packages website", "https://aur.archlinux.org/packages/")]) diff --git a/aur/__init__.py b/aur/__init__.py new file mode 100644 index 00000000..51f69f4d --- /dev/null +++ b/aur/__init__.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2022-2023 Manuel Schneider + +""" +Search for packages and open their URLs. This extension is also intended to be used to \ +quickly install the packages. If you are missing your favorite AUR helper tool send a PR. +""" + +from albert import * +from shutil import which +from datetime import datetime +from urllib import request, parse +import json +import os + +md_iid = "0.5" +md_version = "1.5" +md_name = "Archlinux User Repository" +md_description = "Query and install AUR packages" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/aur" +md_maintainers = "@manuelschneid3r" + + +class Plugin(QueryHandler): + + aur_url = "https://aur.archlinux.org/packages/" + baseurl = 'https://aur.archlinux.org/rpc/' + + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return "aur " + + def initialize(self): + self.icon = [os.path.dirname(__file__)+"/arch.svg"] + + if which("yaourt"): + self.install_cmdline = "yaourt -S aur/%s" + elif which("pacaur"): + self.install_cmdline = "pacaur -S aur/%s" + elif which("yay"): + self.install_cmdline = "yay -S aur/%s" + elif which("paru"): + self.install_cmdline = "paru -S aur/%s" + else: + info("No supported AUR helper found.") + self.install_cmdline = None + + def handleQuery(self, query): + stripped = query.string.strip() + + if stripped: + params = { + 'v': '5', + 'type': 'search', + 'by': 'name', + 'arg': stripped + } + url = "%s?%s" % (self.baseurl, parse.urlencode(params)) + req = request.Request(url) + + with request.urlopen(req) as response: + data = json.loads(response.read().decode()) + if data['type'] == "error": + query.add(Item( + id=__name__, + text="Error", + subtext=data['error'], + icon=self.icon + )) + else: + results = [] + results_json = data['results'] + results_json.sort(key=lambda i: i['Name']) + results_json.sort(key=lambda i: len(i['Name'])) + + for entry in results_json: + name = entry['Name'] + item = Item( + id = __name__, + icon = self.icon, + text = f"{entry['Name']} {entry['Version']}" + ) + + subtext = f"☆{entry['NumVotes']} " + if entry['OutOfDate']: + subtext += '[Out of date: %s] ' % datetime.fromtimestamp(entry['OutOfDate']).strftime("%F") + if entry['Maintainer'] is None: + subtext += '[Orphan] ' + if entry['Description']: + subtext += entry['Description'] + item.subtext = subtext + + actions = [] + if self.install_cmdline: + pacman = install_cmdline.split(" ", 1)[0] + actions.append(Action( + id="inst", + text="Install using %s" % pacman, + callable=lambda n=name: runTerminal( + script=self.install_cmdline % n, + close_on_exit=False + ) + )) + actions.append(Action( + id="inst", + text="Install using %s (noconfirm)" % pacman, + callable=lambda n=name: runTerminal( + script=self.install_cmdline % n + " --noconfirm", + close_on_exit=False + ) + )) + + actions.append(Action("open-aursite", "Open AUR website", + lambda n=name: openUrl(f"{self.aur_url}{n}/"))) + + if entry['URL']: + actions.append(Action("open-website", "Open project website", + lambda u=entry['URL']: openUrl(u))) + + item.actions = actions + results.append(item) + + query.add(results) + else: + query.add(Item( + id=__name__, + text=md_name, + subtext="Enter a query to search the AUR", + icon=self.icon, + actions=[Action("open-aur", "Open AUR packages website", lambda: openUrl(self.aur_url))] + )) diff --git a/.archive/aur/arch.svg b/aur/arch.svg similarity index 97% rename from .archive/aur/arch.svg rename to aur/arch.svg index 5a193897..61f55ed9 100644 --- a/.archive/aur/arch.svg +++ b/aur/arch.svg @@ -1,5 +1,5 @@ \ No newline at end of file From 40c05f981e78f7540aead94cc78e6c6b60984432 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 3 Jan 2023 02:48:10 +0100 Subject: [PATCH 062/355] Archive docker, curious segfaults --- {docker => .archive/docker}/__init__.py | 32 ++++++++++-------------- {docker => .archive/docker}/running.png | Bin {docker => .archive/docker}/stopped.png | Bin 3 files changed, 13 insertions(+), 19 deletions(-) rename {docker => .archive/docker}/__init__.py (77%) rename {docker => .archive/docker}/running.png (100%) rename {docker => .archive/docker}/stopped.png (100%) diff --git a/docker/__init__.py b/.archive/docker/__init__.py similarity index 77% rename from docker/__init__.py rename to .archive/docker/__init__.py index d21a3561..b2e838a7 100644 --- a/docker/__init__.py +++ b/.archive/docker/__init__.py @@ -2,10 +2,9 @@ Docker wrapper (prototype) """ -# Copyright (c) 2022 Manuel Schneider +# Copyright (c) 2022-2023 Manuel Schneider from albert import * -import docker import pathlib md_iid = "0.5" @@ -15,7 +14,6 @@ md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/docker" md_maintainers = "@manuelschneid3r" -md_authors = "@manuelschneid3r" md_bin_dependencies = "docker" md_lib_dependencies = "docker" @@ -45,7 +43,6 @@ def initialize(self): def handleQuery(self, query): - items = [] for container in self.client.containers.list(all=True): # Create dynamic actions @@ -72,18 +69,15 @@ def handleQuery(self, query): actions=actions )) - for image in reversed(self.client.images.list()): - item = Item( - id=image.short_id, - text=str(image.tags), - subtext=image.id, - icon=self.icon_stopped, - actions=[ - Action("run", "Run with command: %s" % query.string, lambda i=image: client.containers.run(i, query.string)), - Action("rmi", "Remove image", lambda i=image: i.remove()) - ] - ) - - items.append(item) - - return items + # for image in reversed(self.client.images.list()): + # query.add(Item( + # id=image.short_id, + # text=str(image.tags), + # subtext=image.id, + # # icon=self.icon_stopped, + # actions=[ + # Action("run", "Run with command: %s" % query.string, + # lambda i=image, s=query.string: client.containers.run(i, s)), + # Action("rmi", "Remove image", lambda i=image: i.remove()) + # ] + # )) diff --git a/docker/running.png b/.archive/docker/running.png similarity index 100% rename from docker/running.png rename to .archive/docker/running.png diff --git a/docker/stopped.png b/.archive/docker/stopped.png similarity index 100% rename from docker/stopped.png rename to .archive/docker/stopped.png From 7eb4525e8095bed70756eac19506d58f4b3506ed Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 3 Jan 2023 02:48:49 +0100 Subject: [PATCH 063/355] Remove obsolete authors from metadata --- api_test/__init__.py | 4 ++-- python_eval/__init__.py | 4 ++-- trash/__init__.py | 4 +++- wikipedia/__init__.py | 3 +-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/api_test/__init__.py b/api_test/__init__.py index ee3a48a1..74692205 100644 --- a/api_test/__init__.py +++ b/api_test/__init__.py @@ -9,7 +9,7 @@ Synopsis: [delay|throw] """ -# Copyright (c) 2022 Manuel Schneider +# Copyright (c) 2022-2023 Manuel Schneider from albert import * import os @@ -22,7 +22,7 @@ md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/api_test" md_maintainers = "@manuelschneid3r" -md_authors = "@manuelschneid3r" + class Plugin(QueryHandler): def id(self): diff --git a/python_eval/__init__.py b/python_eval/__init__.py index 792bf52a..9e6d39bd 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -4,7 +4,7 @@ Synopsis: """ -# Copyright (c) 2022 Manuel Schneider +# Copyright (c) 2022-2023 Manuel Schneider from albert import * from builtins import pow @@ -18,7 +18,7 @@ md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/python_eval" md_maintainers = "@manuelschneid3r" -md_authors = "@manuelschneid3r" + class Plugin(QueryHandler): diff --git a/trash/__init__.py b/trash/__init__.py index f28bb1b0..1a6a8508 100644 --- a/trash/__init__.py +++ b/trash/__init__.py @@ -5,6 +5,8 @@ systems trash location in your default file manager. """ +# Copyright (c) 2023 Manuel Schneider + from albert import * import os from platform import system @@ -16,7 +18,7 @@ md_description = "Open trash" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/trash" -md_authors = md_maintainers = "@manuelschneid3r" +md_maintainers = "@manuelschneid3r" class Plugin(QueryHandler): def id(self): diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 8f71676d..52426ebe 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -4,7 +4,7 @@ Synopsis: """ -# Copyright (c) 2022 Manuel Schneider +# Copyright (c) 2022-2023 Manuel Schneider from albert import * from locale import getdefaultlocale @@ -21,7 +21,6 @@ md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/wikipedia" md_maintainers = "@manuelschneid3r" -md_authors = "@manuelschneid3r" class Plugin(QueryHandler): From 52e4555427394b11aa619e58679ecd30e8f30e08 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 3 Jan 2023 13:46:20 +0100 Subject: [PATCH 064/355] Create README.md --- .archive/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .archive/README.md diff --git a/.archive/README.md b/.archive/README.md new file mode 100644 index 00000000..0ebca9d9 --- /dev/null +++ b/.archive/README.md @@ -0,0 +1,3 @@ +# The archive + +0.18 changed the API and most of the plugins here have no maintainer. Please volunteer as maintainer and help getting plugins shipped. 👍 From 31493d4109cf75ba16b147cc1f9a56ea4e2552e7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 3 Jan 2023 21:33:40 +0100 Subject: [PATCH 065/355] Update README.md --- README.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 29f76e64..993425dc 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,7 @@ -### This is the official repository for python extensions. +### This is the official repository for python plugins. -This repository is shipped with albert. If you want to have bleeding edge extensions or share your extension clone the repository. Check the docs on Python extensions. +This repository is shipped with albert. If you want to have bleeding edge plugins or share your work clone the repository. Check the [docs on Python plugins](https://github.com/albertlauncher/plugins/blob/master/python/README.md). To install the plugins in user space type the following in your terminal: -To install the extensions in user space type the following in your terminal: - -``` -git clone https://github.com/albertlauncher/python.git ~/.local/share/albert/org.albert.extension.python/modules +```shell +git clone https://github.com/albertlauncher/python.git ~/.local/share/albert/python/plugins ``` - -If you send a PR I'll invite you to the reviewers team (if I don't forget it), I'd appreciate if you could review others contributions. From 5629de316f9d0a7dfdd2969751c5f18356c459f7 Mon Sep 17 00:00:00 2001 From: Oskar Haarklou Veileborg Date: Thu, 5 Jan 2023 12:44:44 +0100 Subject: [PATCH 066/355] CopyQ 1.2 --- .archive/copyq/__init__.py | 94 ------------------------------------ copyq/__init__.py | 97 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 94 deletions(-) delete mode 100644 .archive/copyq/__init__.py create mode 100644 copyq/__init__.py diff --git a/.archive/copyq/__init__.py b/.archive/copyq/__init__.py deleted file mode 100644 index 77e26824..00000000 --- a/.archive/copyq/__init__.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Access CopyQ clipboard. - -Synopsis: [filter]""" - -# Copyright (c) 2022 Manuel Schneider - -import html -import json -import re -import subprocess - -from albert import * - -__title__ = "CopyQ" -__version__ = "0.4.1" -__triggers__ = "cq " -__authors__ = "Manuel S." -__exec_deps__ = ["copyq"] - - -iconPath = iconLookup('copyq') - -copyq_script_getAll = r""" -var result=[]; -for ( var i = 0; i < size(); ++i ) { - var obj = {}; - obj.row = i; - obj.mimetypes = str(read("?", i)).split("\n"); - obj.mimetypes.pop(); - obj.text = str(read(i)); - result.push(obj); -} -JSON.stringify(result); -""" - -copyq_script_getMatches = r""" -var result=[]; -var match = "%s"; -for ( var i = 0; i < size(); ++i ) { - if (str(read(i)).search(new RegExp(match, "i")) !== -1) { - var obj = {}; - obj.row = i; - obj.mimetypes = str(read("?", i)).split("\n"); - obj.mimetypes.pop(); - obj.text = str(read(i)); - result.push(obj); - } -} -JSON.stringify(result); -""" - -def copyq_get_matches(substring): - script = copyq_script_getMatches % substring - proc = subprocess.run(['copyq', '-'], input=script.encode(), stdout=subprocess.PIPE) - return json.loads(proc.stdout.decode()) - - -def copyq_get_all(): - proc = subprocess.run(['copyq', '-'], input=copyq_script_getAll.encode(), stdout=subprocess.PIPE) - return json.loads(proc.stdout.decode()) - - -def handleQuery(query): - if query.isTriggered: - query.disableSort() - - items = [] - pattern = re.compile(query.string, re.IGNORECASE) - json_arr = copyq_get_matches(query.string) if query.string else copyq_get_all() - for json_obj in json_arr: - row = json_obj['row'] - text = json_obj['text'] - if not text: - text = "No text" - else: - text = html.escape(" ".join(filter(None, text.replace("\n", " ").split(" ")))) - if query.string: - text = pattern.sub(lambda m: "%s" % m.group(0), text) - items.append( - Item( - id=__title__, - icon=iconPath, - text=text, - subtext="%s: %s" % (row, ", ".join(json_obj['mimetypes'])), - actions=[ - ProcAction("Paste", ["copyq", "select(%s); sleep(60); paste();" % row]), - ProcAction("Copy", ["copyq", "select(%s);" % row]), - ProcAction("Remove", ["copyq", "remove(%s);" % row]), - ] - ) - ) - return items diff --git a/copyq/__init__.py b/copyq/__init__.py new file mode 100644 index 00000000..661e0b96 --- /dev/null +++ b/copyq/__init__.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- + +import json +import subprocess + +from albert import * + +md_iid = "0.5" +md_version = "1.2" +md_name = "CopyQ" +md_description = "Access CopyQ clipboard" +md_license = "BSD-2-Clause" +md_url = "https://github.com/albertlauncher/python" +md_bin_dependencies = ["copyq"] +md_maintainers = "@BarrensZeppelin" + + +copyq_script_getAll = r""" +var result=[]; +for ( var i = 0; i < size(); ++i ) { + var obj = {}; + obj.row = i; + obj.mimetypes = str(read("?", i)).split("\n"); + obj.mimetypes.pop(); + obj.text = str(read(i)); + result.push(obj); +} +JSON.stringify(result); +""" + +copyq_script_getMatches = r""" +var result=[]; +var match = "%s"; +for ( var i = 0; i < size(); ++i ) { + if (str(read(i)).search(new RegExp(match, "i")) !== -1) { + var obj = {}; + obj.row = i; + obj.mimetypes = str(read("?", i)).split("\n"); + obj.mimetypes.pop(); + obj.text = str(read(i)); + result.push(obj); + } +} +JSON.stringify(result); +""" + + +class Plugin(QueryHandler): + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def synopsis(self): + return "" + + def defaultTrigger(self): + return "cq " + + def handleQuery(self, query): + items = [] + q_string = query.string + + script = copyq_script_getMatches % q_string if q_string else copyq_script_getAll + proc = subprocess.run(["copyq", "-"], input=script.encode(), stdout=subprocess.PIPE) + json_arr = json.loads(proc.stdout.decode()) + + for json_obj in json_arr: + row = json_obj["row"] + text = json_obj["text"] + if not text: + text = "No text" + else: + text = " ".join(filter(None, text.replace("\n", " ").split(" "))) + + act = lambda script, row=row: ( + lambda: runDetachedProcess(["copyq", script % row]) + ) + items.append( + Item( + id=md_name, + icon=["xdg:copyq"], + text=text, + subtext="%s: %s" % (row, ", ".join(json_obj["mimetypes"])), + actions=[ + Action("paste", "Paste", act("select(%s); sleep(60); paste();")), + Action("copy", "Copy", act("select(%s);")), + Action("remove", "Remove", act("remove(%s);")), + ], + ) + ) + + query.add(items) From 643ad723d7fe827bc4d5d42e063f1acaab6ad771 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 5 Jan 2023 12:46:46 +0100 Subject: [PATCH 067/355] Pomodoro 1.1 --- .archive/pomodoro/__init__.py | 139 ------------------- .archive/pomodoro/bing.wav | Bin 254670 -> 0 bytes pomodoro/__init__.py | 125 +++++++++++++++++ {.archive/pomodoro => pomodoro}/pomodoro.svg | 0 4 files changed, 125 insertions(+), 139 deletions(-) delete mode 100644 .archive/pomodoro/__init__.py delete mode 100644 .archive/pomodoro/bing.wav create mode 100644 pomodoro/__init__.py rename {.archive/pomodoro => pomodoro}/pomodoro.svg (100%) diff --git a/.archive/pomodoro/__init__.py b/.archive/pomodoro/__init__.py deleted file mode 100644 index a9b8ceaf..00000000 --- a/.archive/pomodoro/__init__.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Set up your personal Pomodoro timer. - -See https://en.wikipedia.org/wiki/Pomodoro_Technique - -Synopsis: [duration [break duration [long break duration [count]]]]""" - -# Copyright (c) 2022 Manuel Schneider - -from albert import * -import subprocess -import threading -import re -import time -import os - -__title__ = "Pomodoro" -__version__ = "0.4.0" -__authors__ = "Manuel S." - - -class PomodoroTimer: - - def __init__(self): - self.isBreak = True - self.timer = None - - def timeout(self): - if self.isBreak: - duration = self.pomodoroDuration * 60 - self.timer = threading.Timer(duration, self.timeout) - self.endTime = time.time() + duration - debug("Pomodoro start (%s min)" % self.pomodoroDuration) - playSound(1) - self.timer.start() - else: - self.remainingTillLongBreak -= 1 - if self.remainingTillLongBreak == 0: - self.remainingTillLongBreak = self.count - duration = self.longBreakDuration * 60 - playSound(3) - debug("Pomodoro long break (%s min)" % self.breakDuration) - else: - duration = self.breakDuration * 60 - playSound(2) - debug("Pomodoro break (%s min)" % self.breakDuration) - self.endTime = time.time() + duration - self.timer = threading.Timer(duration, self.timeout) - self.timer.start() - self.isBreak = not self.isBreak - - def start(self, pomodoroDuration, breakDuration, longBreakDuration, count): - self.stop() - self.pomodoroDuration = pomodoroDuration - self.breakDuration = breakDuration - self.longBreakDuration = longBreakDuration - self.count = count - self.remainingTillLongBreak = count - self.isBreak = True - self.timeout() - - def stop(self): - if self.isActive(): - self.timer.cancel() - self.timer = None - - def isActive(self): - return self.timer is not None - - -iconPath = os.path.dirname(__file__)+"/pomodoro.svg" -soundPath = os.path.dirname(__file__)+"/bing.wav" -pomodoro = PomodoroTimer() - - -def playSound(num): - for x in range(num): - t = threading.Timer(0.5*x, lambda: subprocess.Popen(["aplay", soundPath])) - t.start() - - -def handleQuery(query): - tokens = query.string.split() - if tokens and "pomodoro".startswith(tokens[0].lower()): - - global pomodoro - pattern = re.compile(query.string, re.IGNORECASE) - item = Item( - id=__title__, - icon=iconPath, - text=pattern.sub(lambda m: "%s" % m.group(0), "Pomodoro Timer") - ) - - if len(tokens) == 1 and pomodoro.isActive(): - item.addAction(FuncAction("Stop", lambda p=pomodoro: p.stop())) - if pomodoro.isBreak: - whatsNext = "Pomodoro" - else: - whatsNext = "Long break" if pomodoro.remainingTillLongBreak == 1 else "Short break" - item.subtext = "Stop pomodoro (Next: %s at %s)" % (whatsNext, time.strftime("%X", - time.localtime(pomodoro.endTime))) - return item - - p_duration = 25 - b_duration = 5 - lb_duration = 15 - count = 4 - - item.subtext = "Invalid parameters. Use pomodoro [duration [break duration [long break duration [count]]]]" - if len(tokens) > 1: - if not tokens[1].isdigit(): - return item - p_duration = int(tokens[1]) - - if len(tokens) > 2: - if not tokens[2].isdigit(): - return item - b_duration = int(tokens[2]) - - if len(tokens) > 3: - if not tokens[3].isdigit(): - return item - lb_duration = int(tokens[3]) - - if len(tokens) > 4: - if not tokens[4].isdigit(): - return item - count = int(tokens[4]) - - if len(tokens) > 5: - return item - - item.subtext = "Start new pomodoro timer (%s min/Break %s min/Long break %s min/Count %s)" % (p_duration, b_duration, lb_duration, count) - item.addAction(FuncAction("Start", - lambda p=p_duration, b=b_duration, lb=lb_duration, c=count: - pomodoro.start(p, b, lb, c))) - - return item diff --git a/.archive/pomodoro/bing.wav b/.archive/pomodoro/bing.wav deleted file mode 100644 index 1e9ef1037d7c1e4fa83e1cc326e41eb71cd916cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 254670 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%0A7n7-QP%*c(q` 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 t=c{?lm+APnvg{PslX$OY$M1jYn696{n;k!XA9 4 or not all([t.isdigit() for t in tokens]): + item.subtext = "Invalid parameters. Use %s" % self.synopsis() + query.add(item) + else: + p = int(tokens[0]) if len(tokens) > 0 else self.default_pomodoro_duration + b = int(tokens[1]) if len(tokens) > 1 else self.default_break_duration + lb = int(tokens[2]) if len(tokens) > 2 else self.default_longbreak_duration + c = int(tokens[3]) if len(tokens) > 3 else self.default_pomodoro_count + item.subtext = "Start new pomodoro timer (%s min, break %s min, long break %s min, count %s)"\ + % (p, b, lb, c) + item.actions = [Action("start", "Start", lambda p=p, b=b, lb=lb, c=c: self.pomodoro.start(p, b, lb, c))] + query.add(item) diff --git a/.archive/pomodoro/pomodoro.svg b/pomodoro/pomodoro.svg similarity index 100% rename from .archive/pomodoro/pomodoro.svg rename to pomodoro/pomodoro.svg From 3552cae38d244bc1407dd6e0f108b6ba3f7ed1aa Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 5 Jan 2023 21:33:01 +0100 Subject: [PATCH 068/355] pass 1.2 --- .archive/pass/__init__.py | 95 ----------------------------------- pass/__init__.py | 101 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 95 deletions(-) delete mode 100644 .archive/pass/__init__.py create mode 100644 pass/__init__.py diff --git a/.archive/pass/__init__.py b/.archive/pass/__init__.py deleted file mode 100644 index 90452fcc..00000000 --- a/.archive/pass/__init__.py +++ /dev/null @@ -1,95 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Manage passwords. - -This is a 'pass' wrapper extension. - -Synopsis: - generate - """ - -# Copyright (c) 2022 Manuel Schneider - -import fnmatch -import os -from albert import * - -__title__ = "Pass" -__version__ = "0.4.1" -__triggers__ = "pass " -__authors__ = "Benedict Dudel" -__exec_deps__ = ["pass"] - -HOME_DIR = os.environ["HOME"] -PASS_DIR = os.environ.get("PASSWORD_STORE_DIR", os.path.join(HOME_DIR, ".password-store/")) -ICON_PATH = iconLookup("dialog-password") - - -def handleQuery(query): - if query.isTriggered: - query.disableSort() - if query.string.strip().startswith("generate"): - return generatePassword(query) - - return showPasswords(query) - -def generatePassword(query): - location = query.string.strip()[9:] - - return [Item( - id=__title__, - icon=ICON_PATH, - text="Generate a new password", - subtext="The new password will be located at %s" % location, - completion="pass %s" % query.string, - actions=[ - ProcAction("Generate", ["pass", "generate", "--clip", location, "20"]) - ] - )] - -def showPasswords(query): - passwords = [] - if query.string.strip(): - passwords = getPasswordsFromSearch(query) - else: - passwords = getPasswords() - - results = [] - for password in passwords: - name = password.split("/")[-1] - results.append( - Item( - id=password, - icon=ICON_PATH, - text=name, - subtext=password, - completion="pass %s" % password, - actions=[ - ProcAction("Copy", ["pass", "--clip", password]), - ProcAction("Edit", ["pass", "edit", password]), - ProcAction("Remove", ["pass", "rm", "--force", password]), - ] - ), - ) - - return results - -def getPasswords(): - passwords = [] - for root, dirnames, filenames in os.walk(PASS_DIR): - for filename in fnmatch.filter(filenames, "*.gpg"): - passwords.append( - os.path.join(root, filename.replace(".gpg", "")).replace(PASS_DIR, "") - ) - - return sorted(passwords, key=lambda s: s.lower()) - -def getPasswordsFromSearch(query): - passwords = [] - for password in getPasswords(): - if query.string.strip().lower() not in password.lower(): - continue - - passwords.append(password) - - return passwords diff --git a/pass/__init__.py b/pass/__init__.py new file mode 100644 index 00000000..aac808f7 --- /dev/null +++ b/pass/__init__.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- + +import fnmatch +import os +from albert import * + +md_iid = "0.5" +md_version = "1.2" +md_name = "Pass" +md_description = "Manage passwords in pass" +md_bin_dependencies = ["pass"] +md_maintainers = "@maxmil" +md_license = "BSD-3" + +HOME_DIR = os.environ["HOME"] +PASS_DIR = os.environ.get("PASSWORD_STORE_DIR", os.path.join(HOME_DIR, ".password-store/")) +ICON = ["xdg:dialog-password"] + +class Plugin(QueryHandler): + + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def synopsis(self): + return "" + + def defaultTrigger(self): + return "pass " + + def handleQuery(self, query): + if query.string.strip().startswith("generate"): + self.generatePassword(query) + else: + self.showPasswords(query) + + def generatePassword(self, query): + location = query.string.strip()[9:] + + query.add(Item( + id="generate_password", + icon=ICON, + text="Generate a new password", + subtext="The new password will be located at %s" % location, + completion="pass %s" % query.string, + actions=[ + Action("generate", "Generate", lambda: runDetachedProcess(["pass", "generate", "--clip", location, "20"])) + ] + )) + + def showPasswords(self, query): + passwords = [] + if query.string.strip(): + passwords = self.getPasswordsFromSearch(query) + else: + passwords = self.getPasswords() + + results = [] + for password in passwords: + name = password.split("/")[-1] + results.append( + Item( + id=password, + icon=ICON, + text=name, + subtext=password, + completion="pass %s" % password, + actions=[ + Action("copy", "Copy", lambda pwd=password: runDetachedProcess(["pass", "--clip", pwd])), + Action("edit", "Edit", lambda pwd=password: runDetachedProcess(["pass", "edit", pwd])), + Action("remove", "Remove", lambda pwd=password: runDetachedProcess(["pass", "rm", "--force", pwd])), + ] + ), + ) + + query.add(results) + + def getPasswords(self): + passwords = [] + for root, dirnames, filenames in os.walk(PASS_DIR): + for filename in fnmatch.filter(filenames, "*.gpg"): + passwords.append( + os.path.join(root, filename.replace(".gpg", "")).replace(PASS_DIR, "") + ) + + return sorted(passwords, key=lambda s: s.lower()) + + def getPasswordsFromSearch(self, query): + passwords = [] + for password in self.getPasswords(): + if query.string.strip().lower() not in password.lower(): + continue + + passwords.append(password) + + return passwords From f81e8a0bc6dc0663803ed35efb9854400ac34421 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 6 Jan 2023 11:41:51 +0100 Subject: [PATCH 069/355] [pomodoro] Remove debug --- pomodoro/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 7db54907..b5e9c17c 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -32,18 +32,15 @@ def timeout(self): self.timer = threading.Timer(duration, self.timeout) self.endTime = time.time() + duration sendTrayNotification("PomodoroTimer", "Let's go to work!") - critical("Let's go to work!") self.timer.start() else: self.remainingTillLongBreak -= 1 if self.remainingTillLongBreak == 0: self.remainingTillLongBreak = self.count sendTrayNotification("PomodoroTimer", "Take a long break (%s min)" % self.longBreakDuration) - critical("Take a long break (%s min)" % duration) duration = self.longBreakDuration * 60 else: sendTrayNotification("PomodoroTimer", "Take a short break (%s min)" % self.breakDuration) - critical("Take a short break (%s min)" % duration) duration = self.breakDuration * 60 self.endTime = time.time() + duration self.timer = threading.Timer(duration, self.timeout) From 4bd084b61cb05653f6f471d0fcb1802a0ccfcc8a Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 6 Jan 2023 11:45:21 +0100 Subject: [PATCH 070/355] googletrans 1.0 --- googletrans/__init__.py | 74 +++++++++++++++++++++++++++++++ googletrans/google_translate.png | Bin 0 -> 51950 bytes 2 files changed, 74 insertions(+) create mode 100644 googletrans/__init__.py create mode 100644 googletrans/google_translate.png diff --git a/googletrans/__init__.py b/googletrans/__init__.py new file mode 100644 index 00000000..8c42c098 --- /dev/null +++ b/googletrans/__init__.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- + +""" +Translator using py-googletrans +""" + +from albert import * +from googletrans import Translator, LANGUAGES +from locale import getdefaultlocale +from time import sleep +import os + +md_iid = "0.5" +md_version = "1.0" +md_name = "Google Translate" +md_description = "Translate sentences using googletrans" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/" +md_lib_dependencies = "googletrans==3.1.0a0" +md_maintainers = "@manuelschneid3r" + +class Plugin(QueryHandler): + + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return "tr " + + def synopsis(self): + return "[[src] dest] text" + + def initialize(self): + self.icon = [os.path.dirname(__file__)+"/google_translate.png"] + self.translator = Translator() + self.lang = getdefaultlocale()[0][0:2] + + def handleQuery(self, query): + stripped = query.string.strip() + if stripped: + for number in range(50): + sleep(0.01) + if not query.isValid: + return; + + src = None + dest, text = self.lang, stripped + splits = text.split(maxsplit=1) + if 1 < len(splits) and splits[0] in LANGUAGES: + dest, text = splits[0], splits[1] + splits = text.split(maxsplit=1) + if 1 < len(splits) and splits[0] in LANGUAGES: + src = dest + dest, text = splits[0], splits[1] + + if src: + translation = self.translator.translate(text, src=src, dest=dest) + else: + translation = self.translator.translate(text, dest=dest) + + query.add(Item( + id="googletrans", + text=translation.text, + subtext=f'From {LANGUAGES[translation.src]} to {LANGUAGES[translation.dest]}', + icon=self.icon, + actions = [Action("copy", "Copy result to clipboard", + lambda t=translation.text: setClipboardText(t))] + )) diff --git a/googletrans/google_translate.png b/googletrans/google_translate.png new file mode 100644 index 0000000000000000000000000000000000000000..63617cf578c9f2b502ea30349dd61b0a7604d8a1 GIT binary patch literal 51950 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 z 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 literal 0 HcmV?d00001 From f1340818fb8156e34f67b53aa3817df5f8479eb5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 8 Jan 2023 23:18:03 +0100 Subject: [PATCH 071/355] [pomo] Add default trigger --- pomodoro/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index b5e9c17c..5d99aabb 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -83,6 +83,9 @@ def name(self): def description(self): return md_description + def defaultTrigger(self): + return "pomo " + def initialize(self): self.pomodoro = PomodoroTimer() From f5e2d5a5235077024fd17e84c1f05556fff08278 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 9 Jan 2023 00:37:40 +0100 Subject: [PATCH 072/355] [wiki] Smarter ratelimit avoidance --- wikipedia/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 52426ebe..da2972f2 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -8,11 +8,11 @@ from albert import * from locale import getdefaultlocale +from socket import timeout +from time import sleep from urllib import request, parse import json -import time import os -from socket import timeout md_iid = "0.5" md_version = "1.5" @@ -71,9 +71,10 @@ def handleQuery(self, query): stripped = query.string.strip() if stripped: # avoid rate limiting - time.sleep(0.1) - if not query.isValid: - return + for number in range(50): + sleep(0.01) + if not query.isValid: + return; results = [] @@ -98,7 +99,6 @@ def handleQuery(self, query): results.append(Item(id="wiki", text=title, subtext=summary if summary else url, - completion=title, icon=[self.iconPath], actions=[ Action("open", "Open article on Wikipedia", lambda u=url: openUrl(u)), From 49a03e30d2dad16a63a5d897491b8776f5a8f786 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 9 Jan 2023 00:40:11 +0100 Subject: [PATCH 073/355] [archwiki] Ratelimit/Responsive UI --- arch_wiki/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index 1404a561..7e892890 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -2,6 +2,7 @@ # Copyright (c) 2022-2023 Manuel Schneider from albert import * +from time import sleep from urllib import request, parse import json import os @@ -37,6 +38,13 @@ def defaultTrigger(self): def handleQuery(self, query): stripped = query.string.strip() if stripped: + + # avoid rate limiting + for number in range(50): + sleep(0.01) + if not query.isValid: + return; + results = [] params = { From ac7250a4bb579bf33378b713d87a52f23539b06e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 9 Jan 2023 11:33:32 +0100 Subject: [PATCH 074/355] [aur] smart sleep --- aur/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aur/__init__.py b/aur/__init__.py index 51f69f4d..d35189d6 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -55,8 +55,12 @@ def initialize(self): self.install_cmdline = None def handleQuery(self, query): - stripped = query.string.strip() + for number in range(50): + sleep(0.01) + if not query.isValid: + return; + stripped = query.string.strip() if stripped: params = { 'v': '5', From 1a5261766976db853c06284cc04f8d1d6fd3811e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 11 Jan 2023 00:55:26 +0100 Subject: [PATCH 075/355] Remove redundant description --- python_eval/__init__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/python_eval/__init__.py b/python_eval/__init__.py index 9e6d39bd..d7265751 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -1,9 +1,4 @@ # -*- coding: utf-8 -*- - -"""Evaluate simple python expressions. - -Synopsis: """ - # Copyright (c) 2022-2023 Manuel Schneider from albert import * From b0095d90a369d954696af59d87d0794c9a624275 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 11 Jan 2023 00:57:15 +0100 Subject: [PATCH 076/355] [aur] Fix missing import --- aur/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aur/__init__.py b/aur/__init__.py index d35189d6..5c2d5ec1 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -10,6 +10,7 @@ from shutil import which from datetime import datetime from urllib import request, parse +from time import sleep import json import os From 03f36fbdee8614e288f508d05c8894d3498134f3 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 11 Jan 2023 10:25:26 +0100 Subject: [PATCH 077/355] Use md_id instead __name__ for item ids --- api_test/__init__.py | 2 +- arch_wiki/__init__.py | 18 +++++++++--------- aur/__init__.py | 22 +++++++++++----------- copyq/__init__.py | 4 ++-- googletrans/__init__.py | 6 +++--- pass/__init__.py | 2 +- pomodoro/__init__.py | 4 ++-- python_eval/__init__.py | 4 ++-- trash/__init__.py | 4 ++-- wikipedia/__init__.py | 8 ++++---- 10 files changed, 37 insertions(+), 37 deletions(-) diff --git a/api_test/__init__.py b/api_test/__init__.py index 74692205..9aefb1aa 100644 --- a/api_test/__init__.py +++ b/api_test/__init__.py @@ -89,7 +89,7 @@ def function(): info(query.string) item.addAction(FuncAction("Print warning", lambda: warning(query.string))) results.append(item) - item = Item(id=__title__, + item = Item(id=md_id, text="This is the primary text", subtext="This is the subtext, some kind of description", completion=__triggers__ + 'Hellooohooo!', diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index 7e892890..f6474431 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -24,7 +24,7 @@ class Plugin(QueryHandler): user_agent = "org.albert.extension.python.archwiki" def id(self): - return __name__ + return md_id def name(self): return md_name @@ -65,7 +65,7 @@ def handleQuery(self, query): summary = data[2][i] url = data[3][i] - results.append(Item(id=__name__, + results.append(Item(id=md_id, text=title, subtext=summary if summary else url, icon=self.icon, @@ -75,15 +75,15 @@ def handleQuery(self, query): ])) if results: query.add(results) - - query.add( Item(id=__name__, - text="Search '%s'" % query.string, - subtext="No results. Start online search on Arch Wiki", - icon=self.icon, - actions=[Action("search", "Open search", lambda s=query.string: self.search_url % s)])) + else: + query.add(Item(id=md_id, + text="Search '%s'" % query.string, + subtext="No results. Start online search on Arch Wiki", + icon=self.icon, + actions=[Action("search", "Open search", lambda s=query.string: self.search_url % s)])) else: - query.add(Item(id=__name__, + query.add(Item(id=md_id, text=md_name, icon=self.icon, subtext="Enter a query to search on the Arch Wiki")) diff --git a/aur/__init__.py b/aur/__init__.py index 5c2d5ec1..29806300 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -29,7 +29,7 @@ class Plugin(QueryHandler): baseurl = 'https://aur.archlinux.org/rpc/' def id(self): - return __name__ + return md_id def name(self): return md_name @@ -59,7 +59,7 @@ def handleQuery(self, query): for number in range(50): sleep(0.01) if not query.isValid: - return; + return stripped = query.string.strip() if stripped: @@ -76,7 +76,7 @@ def handleQuery(self, query): data = json.loads(response.read().decode()) if data['type'] == "error": query.add(Item( - id=__name__, + id=md_id, text="Error", subtext=data['error'], icon=self.icon @@ -90,18 +90,18 @@ def handleQuery(self, query): for entry in results_json: name = entry['Name'] item = Item( - id = __name__, + id = md_id, icon = self.icon, text = f"{entry['Name']} {entry['Version']}" ) - subtext = f"☆{entry['NumVotes']} " - if entry['OutOfDate']: - subtext += '[Out of date: %s] ' % datetime.fromtimestamp(entry['OutOfDate']).strftime("%F") + subtext = f"☆{entry['NumVotes']}" if entry['Maintainer'] is None: - subtext += '[Orphan] ' + subtext += ', Unmaintained!' + if entry['OutOfDate']: + subtext += ', Out of date: %s' % datetime.fromtimestamp(entry['OutOfDate']).strftime("%F") if entry['Description']: - subtext += entry['Description'] + subtext += ', %s' % entry['Description'] item.subtext = subtext actions = [] @@ -116,7 +116,7 @@ def handleQuery(self, query): ) )) actions.append(Action( - id="inst", + id="instnc", text="Install using %s (noconfirm)" % pacman, callable=lambda n=name: runTerminal( script=self.install_cmdline % n + " --noconfirm", @@ -137,7 +137,7 @@ def handleQuery(self, query): query.add(results) else: query.add(Item( - id=__name__, + id=md_id, text=md_name, subtext="Enter a query to search the AUR", icon=self.icon, diff --git a/copyq/__init__.py b/copyq/__init__.py index 661e0b96..fa1104c0 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -47,7 +47,7 @@ class Plugin(QueryHandler): def id(self): - return __name__ + return md_id def name(self): return md_name @@ -82,7 +82,7 @@ def handleQuery(self, query): ) items.append( Item( - id=md_name, + id=md_id, icon=["xdg:copyq"], text=text, subtext="%s: %s" % (row, ", ".join(json_obj["mimetypes"])), diff --git a/googletrans/__init__.py b/googletrans/__init__.py index 8c42c098..c89f7c54 100644 --- a/googletrans/__init__.py +++ b/googletrans/__init__.py @@ -22,7 +22,7 @@ class Plugin(QueryHandler): def id(self): - return __name__ + return md_id def name(self): return md_name @@ -47,7 +47,7 @@ def handleQuery(self, query): for number in range(50): sleep(0.01) if not query.isValid: - return; + return src = None dest, text = self.lang, stripped @@ -65,7 +65,7 @@ def handleQuery(self, query): translation = self.translator.translate(text, dest=dest) query.add(Item( - id="googletrans", + id=md_id, text=translation.text, subtext=f'From {LANGUAGES[translation.src]} to {LANGUAGES[translation.dest]}', icon=self.icon, diff --git a/pass/__init__.py b/pass/__init__.py index aac808f7..7bd3b62c 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -19,7 +19,7 @@ class Plugin(QueryHandler): def id(self): - return __name__ + return md_id def name(self): return md_name diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 5d99aabb..24cef355 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -75,7 +75,7 @@ class Plugin(QueryHandler): default_pomodoro_count = 4 def id(self): - return __name__ + return md_id def name(self): return md_name @@ -94,7 +94,7 @@ def synopsis(self): def handleQuery(self, query): item = Item( - id=__name__, + id=md_id, icon=self.icon, text=md_name ) diff --git a/python_eval/__init__.py b/python_eval/__init__.py index d7265751..5834792b 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -18,7 +18,7 @@ class Plugin(QueryHandler): def id(self): - return __name__ + return md_id def name(self): return md_name @@ -44,7 +44,7 @@ def handleQuery(self, query): result = str(ex) query.add(Item( - id="py_eval", + id=md_id, text=str(result), subtext=type(result).__name__, completion=query.trigger + result, diff --git a/trash/__init__.py b/trash/__init__.py index 1a6a8508..a1fe8ca5 100644 --- a/trash/__init__.py +++ b/trash/__init__.py @@ -22,7 +22,7 @@ class Plugin(QueryHandler): def id(self): - return __name__ + return md_id def name(self): return md_name @@ -40,7 +40,7 @@ def initialize(self): else: raise NotImplementedError("%1 not supported" % system()) - self.trash_item = Item(id="trash-open", + self.trash_item = Item(id=md_id, text="Trash", subtext="Open trash folder", icon=icon, diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index da2972f2..949e5e7e 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -31,7 +31,7 @@ class Plugin(QueryHandler): limit = 20 def id(self): - return __name__ + return md_id def name(self): return md_name @@ -74,7 +74,7 @@ def handleQuery(self, query): for number in range(50): sleep(0.01) if not query.isValid: - return; + return results = [] @@ -96,7 +96,7 @@ def handleQuery(self, query): summary = data[2][i] url = data[3][i] - results.append(Item(id="wiki", + results.append(Item(id=md_id, text=title, subtext=summary if summary else url, icon=[self.iconPath], @@ -107,7 +107,7 @@ def handleQuery(self, query): query.add(results) else: - query.add(Item(id="wiki", + query.add(Item(id=md_id, text=md_name, subtext="Enter a query to search on Wikipedia", icon=[self.iconPath])) From 38894138ef134bf7f9bb1d1afc7acc88a9b53190 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 12 Jan 2023 15:59:06 +0100 Subject: [PATCH 078/355] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 33 ++++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 14 ++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..8f227242 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,33 @@ +--- +name: Bug report +about: Please check the existing issues before creating a new one. +--- + + + +#### Description +A brief description of the issue. If applicable, add screenshots. + +#### Expected behavior +A brief description of what you expected to happen + +#### Steps to reproduce +Steps to reproduce the behavior + +#### Source +e.g. ppa:name, repository, built from source, etc … + +#### Debug output + +

+ +``` +Output of `albert -d` when run in a terminal +``` + +
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..bf083087 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: false +contact_links: + - name: Start a discussion + url: https://github.com/orgs/albertlauncher/discussions/new/choose + about: Post the link to the discussion in the chats to get more attention. + - name: Chat on Discord + url: https://discord.gg/t8G2EkvRZh + about: Bridged community chat. + - name: Chat on Telegram + url: https://telegram.me/albert_launcher_community + about: Bridged community chat. + - name: Chat on on IRC (libera#albertlauncher) + url: https://web.libera.chat/#albertlauncher + about: Bridged community chat. From c34a5ef85ececaea3a72d05433396729d1da6e36 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 13 Jan 2023 11:39:09 +0100 Subject: [PATCH 079/355] [goldendict] 1.1 (0.18) --- .archive/goldendict/__init__.py | 28 --------------------- goldendict/__init__.py | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 28 deletions(-) delete mode 100644 .archive/goldendict/__init__.py create mode 100644 goldendict/__init__.py diff --git a/.archive/goldendict/__init__.py b/.archive/goldendict/__init__.py deleted file mode 100644 index 7cfe4b53..00000000 --- a/.archive/goldendict/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Fire up an external search in GoldenDict. - -Synopsis: """ - -# Copyright (c) 2022 Manuel Schneider - -from subprocess import run -from albert import Item, ProcAction, iconLookup - -__title__ = "GoldenDict" -__version__ = "0.4.0" -__triggers__ = "gd " -__authors__ = "Manuel S." -__exec_deps__ = ["goldendict"] - -iconPath = iconLookup('goldendict') - - -def handleQuery(query): - if query.isTriggered: - return Item(id=__title__, - icon=iconPath, - text=__title__, - subtext="Look up '%s' using %s" % (query.string, __title__), - actions=[ProcAction("Start query in %s" % __title__, - ["goldendict", query.string])]) diff --git a/goldendict/__init__.py b/goldendict/__init__.py new file mode 100644 index 00000000..6f9c516f --- /dev/null +++ b/goldendict/__init__.py @@ -0,0 +1,44 @@ +from albert import Action, Item, Query, QueryHandler, runDetachedProcess # pylint: disable=import-error + +md_iid = '0.5' +md_version = '1.1' +md_name = 'GoldenDict' +md_description = 'Searches in GoldenDict' +md_url = 'https://github.com/albertlauncher/python/' +md_maintainers = '@stevenxxiu' +md_bin_dependencies = ['goldendict'] + +TRIGGER = 'gd' +ICON_PATH = '/usr/share/pixmaps/goldendict.png' + + +class Plugin(QueryHandler): + def id(self) -> str: + return __name__ + + def name(self) -> str: + return md_name + + def description(self) -> str: + return md_description + + def defaultTrigger(self) -> str: + return f'{TRIGGER} ' + + def synopsis(self) -> str: + return 'query' + + def handleQuery(self, query: Query) -> None: + query_str = query.string.strip() + if not query_str: + return + + query.add( + Item( + id=md_name, + text=md_name, + subtext=f'Look up {query_str} using GoldenDict', + icon=[ICON_PATH], + actions=[Action(md_name, md_name, lambda: runDetachedProcess(['goldendict', query_str]))], + ) + ) From 1967e016827a7ee1cb9cd16a2152d2bad51e6366 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 14 Jan 2023 11:13:01 +0100 Subject: [PATCH 080/355] [apitest] 0.18 --- api_test/__init__.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/api_test/__init__.py b/api_test/__init__.py index 9aefb1aa..1d031847 100644 --- a/api_test/__init__.py +++ b/api_test/__init__.py @@ -60,9 +60,7 @@ def handleQuery(self, query): raise ValueError('EXPLICITLY REQUESTED TEST EXCEPTION!') info(query.string) - info(query.rawString) info(query.trigger) - info(str(query.isTriggered)) info(str(query.isValid)) critical(query.string) @@ -74,26 +72,21 @@ def handleQuery(self, query): item = Item() - item.icon = iconPath + item.icon = ['xdg:albert'] item.text = 'Python item containing %s' % query.string item.subtext = 'Python description' - item.completion = __triggers__ + 'Completion Harharhar' - item.urgency = ItemBase.Notification # Alert, Normal + item.completion = 'Completion test' info(item.icon) info(item.text) info(item.subtext) info(item.completion) - info(str(item.urgency)) - def function(): info(query.string) - item.addAction(FuncAction("Print info", function)) - item.addAction(FuncAction("Print warning", lambda: warning(query.string))) results.append(item) item = Item(id=md_id, text="This is the primary text", subtext="This is the subtext, some kind of description", - completion=__triggers__ + 'Hellooohooo!', - icons=os.path.dirname(__file__)+"/plugin.svg", + completion='Hellooohooo!', + icon=[os.path.dirname(__file__)+"/plugin.svg"], actions=[ Action( id="clip", From ac0526a7525fa22b83b165e5e07b4edf291d4531 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 18 Jan 2023 11:09:42 +0100 Subject: [PATCH 081/355] [wiki] fix typo --- wikipedia/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 949e5e7e..16ce1953 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -102,7 +102,7 @@ def handleQuery(self, query): icon=[self.iconPath], actions=[ Action("open", "Open article on Wikipedia", lambda u=url: openUrl(u)), - Action("copy", "Copy URL to clipboard", lambda u=url: setClipBoardText(u)) + Action("copy", "Copy URL to clipboard", lambda u=url: setClipboardText(u)) ])) query.add(results) From 49345a7c73d0a2e539c4b2b5b08f8fcec333fc92 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 18 Jan 2023 11:11:54 +0100 Subject: [PATCH 082/355] [kill] v1.1 (iid:0.5) --- .archive/kill/__init__.py | 50 ----------------------- .gitignore | 2 + kill/__init__.py | 83 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 50 deletions(-) delete mode 100644 .archive/kill/__init__.py create mode 100644 kill/__init__.py diff --git a/.archive/kill/__init__.py b/.archive/kill/__init__.py deleted file mode 100644 index f6f87516..00000000 --- a/.archive/kill/__init__.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Kill processes. - -Unix 'kill' wrapper extension. - -Synopsis: """ - -# Copyright (c) 2022 Manuel Schneider - -import os -from signal import SIGKILL, SIGTERM - -from albert import FuncAction, Item, iconLookup - -__title__ = "Kill Process" -__version__ = "0.4.4" -__triggers__ = "kill " -__authors__ = ["Benedict Dudel", "Manuel S."] - -iconPath = iconLookup('process-stop') - - -def handleQuery(query): - if query.isTriggered: - results = [] - uid = os.getuid() - for dir_entry in os.scandir('/proc'): - try: - if dir_entry.name.isdigit() and dir_entry.stat().st_uid == uid: - proc_command = open(os.path.join(dir_entry.path, 'comm'), 'r').read().strip() - if query.string in proc_command: - proc_cmdline = open(os.path.join(dir_entry.path, 'cmdline'), 'r').read().strip().replace("\0", " ") - results.append( - Item( - id="kill_%s" % proc_cmdline, - icon=iconPath, - text=proc_command.replace(query.string, "%s" % query.string), - subtext=proc_cmdline, - actions=[ - FuncAction("Terminate", lambda pid=int(dir_entry.name): os.kill(pid, SIGTERM)), - FuncAction("Kill", lambda pid=int(dir_entry.name): os.kill(pid, SIGKILL)) - ] - ) - ) - except FileNotFoundError: # TOCTOU dirs may disappear - continue - except IOError: # TOCTOU dirs may disappear - continue - return results diff --git a/.gitignore b/.gitignore index cd165dfd..1d4436e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ __pycache__ /.idea +/.vscode +/.venv \ No newline at end of file diff --git a/kill/__init__.py b/kill/__init__.py new file mode 100644 index 00000000..a43677d4 --- /dev/null +++ b/kill/__init__.py @@ -0,0 +1,83 @@ +"""Unix 'kill' wrapper extension.""" + +import os +from signal import SIGKILL, SIGTERM + +from albert import * + +md_iid = "0.5" +md_version = "1.1" +md_name = "Kill Process" +md_description = "Kill processes" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/kill" +md_maintainers = "@Pete-Hamlin" +md_credits = "Original idea by Benedict Dudel & Manuel Schneider" + + +class Plugin(QueryHandler): + icon_path = "xdg:process-stop" + + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def initialize(self): + pass + + def defaultTrigger(self): + return "kill " + + def handleQuery(self, query): + if not query.isValid: + return + results = [] + uid = os.getuid() + for dir_entry in os.scandir("/proc"): + try: + if dir_entry.name.isdigit() and dir_entry.stat().st_uid == uid: + proc_command = ( + open(os.path.join(dir_entry.path, "comm"), "r").read().strip() + ) + if query.string in proc_command: + debug(proc_command) + proc_cmdline = ( + open(os.path.join(dir_entry.path, "cmdline"), "r") + .read() + .strip() + .replace("\0", " ") + ) + results.append( + Item( + id="kill", + icon=[self.icon_path], + text=proc_command, + subtext=proc_cmdline, + actions=[ + Action( + "terminate", + "Terminate process", + lambda pid=int(dir_entry.name): os.kill( + pid, SIGTERM + ), + ), + Action( + "kill", + "Kill process", + lambda pid=int(dir_entry.name): os.kill( + pid, SIGKILL + ), + ), + ], + ) + ) + except FileNotFoundError: # TOCTOU dirs may disappear + continue + except IOError: # TOCTOU dirs may disappear + continue + query.add(results) From 7142a7877202aa0378095401740542c4ba4330b5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 18 Jan 2023 11:45:21 +0100 Subject: [PATCH 083/355] [yt] v1.2 (iid:0.5) --- .archive/youtube/__init__.py | 112 -------------------- youtube/__init__.py | 192 +++++++++++++++++++++++++++++++++++ youtube/youtube.svg | 1 + 3 files changed, 193 insertions(+), 112 deletions(-) delete mode 100644 .archive/youtube/__init__.py create mode 100644 youtube/__init__.py create mode 100644 youtube/youtube.svg diff --git a/.archive/youtube/__init__.py b/.archive/youtube/__init__.py deleted file mode 100644 index 46fb7bf5..00000000 --- a/.archive/youtube/__init__.py +++ /dev/null @@ -1,112 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Query and open YouTube videos and channels. - -Synopsis: """ - -# Copyright (c) 2022 Manuel Schneider - -import json -import re -import time -from os import path -from urllib.parse import urlencode -from urllib.request import Request, urlopen - -from albert import Item, UrlAction, iconLookup, critical, debug, info - -__title__ = 'Youtube' -__version__ = '0.4.1' -__triggers__ = 'yt ' -__authors__ = "Manuel S." -__icon__ = iconLookup('youtube') # path.dirname(__file__) + '/icons/YouTube.png' - -DATA_REGEX = re.compile(r'^\s*(var\s|window\[")ytInitialData("\])?\s*=\s*(.*)\s*;\s*$', re.MULTILINE) - -HEADERS = { - 'User-Agent': ( - 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)' - ' Chrome/62.0.3202.62 Safari/537.36' - ) -} - -def handleQuery(query): - if query.isTriggered and query.string.strip(): - - # avoid rate limiting - time.sleep(0.2) - if not query.isValid: - return - - info("Searching YouTube for '{}'".format(query.string)) - req = Request(headers=HEADERS, url='https://www.youtube.com/results?{}'.format( - urlencode({ 'search_query': query.string.strip() }))) - - with urlopen(req) as response: - responseBytes = response.read() - match = re.search(DATA_REGEX, responseBytes.decode()) - if match is None: - critical("Failed to receive expected data from YouTube. This likely means API changes, but could just be a failed request.") - logHtml(responseBytes) - return - - results = json.loads(match.group(3)) - results = results['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'][0]['itemSectionRenderer']['contents'] - items = [] - for result in results: - for type, data in result.items(): - try: - if type == 'videoRenderer': - subtext = ['Video'] - action = 'Watch on Youtube' - link = 'watch?v={}'.format(data['videoId']) - - if 'lengthText' in data: - subtext.append(textFrom(data['lengthText'])) - if 'shortViewCountText' in data: - subtext.append(textFrom(data['shortViewCountText'])) - if 'publishedTimeText' in data: - subtext.append(textFrom(data['publishedTimeText'])) - - elif type == 'channelRenderer': - subtext = ['Channel'] - action = 'Show on Youtube' - link = 'channel/{}'.format(data['channelId']) - - if 'videoCountText' in data: - subtext.append(textFrom(data['videoCountText'])) - if 'subscriberCountText' in data: - subtext.append(textFrom(data['subscriberCountText'])) - else: - continue - except Exception as e: - critical(e) - critical(json.dumps(result, indent=4)) - - item = Item(id=__title__, - icon=data['thumbnail']['thumbnails'][0]['url'].split('?', 1)[0] if data['thumbnail']['thumbnails'] else __icon__, - text=textFrom(data['title']), - subtext=' | '.join(subtext), - actions=[ UrlAction(action, 'https://www.youtube.com/' + link) ] - ) - items.append(item) - return items - -def textFrom(val): - text = val['simpleText'] if 'runs' not in val else \ - ''.join('{}'.format(v['text']) for v in val['runs']) - - return text.strip() - -def logHtml(html): - logTime = time.strftime("%Y%m%d-%H%M%S") - logName = 'albert.plugins.youtube_dump' - logPath = '/tmp/{}-{}.html'.format(logName, logTime) - - f = open(logPath, 'wb') - f.write(html) - f.close() - - critical("The HTML output has been dumped to {}.".format(logPath)) - critical("If the page looks ok in a browser, please include the dump in a new issue:") - critical(" https://www.github.com/albertlauncher/albert/issues/new") diff --git a/youtube/__init__.py b/youtube/__init__.py new file mode 100644 index 00000000..fa7ce820 --- /dev/null +++ b/youtube/__init__.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- + +import json +import re +import tempfile +import time +from os import path +from concurrent.futures import ThreadPoolExecutor +from pathlib import Path +from typing import Any, Dict, List +from urllib.parse import urlencode +from urllib.request import Request, urlopen + +from albert import Action, Item, Query, QueryHandler, critical, info, openUrl # pylint: disable=import-error + + +md_iid = '0.5' +md_version = '1.2' +md_name = 'YouTube' +md_description = 'Query and open YouTube videos and channels' +md_url = 'https://github.com/albertlauncher/python/' +md_maintainers = '@stevenxxiu' + +ICON = path.dirname(__file__) + '/youtube.svg' +DATA_REGEX = re.compile(r'\b(var\s|window\[")ytInitialData("\])?\s*=\s*(.*)\s*;', re.MULTILINE) +TEMP_DIR = Path(tempfile.mkdtemp(prefix='albert_yt_')) + +HEADERS = { + 'User-Agent': ( + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' + ) +} + + +def log_html(html: bytes) -> None: + log_time = time.strftime('%Y%m%d-%H%M%S') + log_name = 'albert.plugins.youtube_dump' + log_path = Path(f'/tmp/{log_name}-{log_time}.html') + + with log_path.open('wb') as sr: + sr.write(html) + + critical(f'The HTML output has been dumped to {log_path}') + critical('If the page looks ok in a browser, please include the dump in a new issue:') + critical(' https://www.github.com/albertlauncher/albert/issues/new') + + +def urlopen_with_headers(url: str) -> Any: + req = Request(headers=HEADERS, url=url) + return urlopen(req) + + +def text_from(val: Dict[str, Any]) -> str: + text = val['simpleText'] if 'runs' not in val else ''.join(str(v['text']) for v in val['runs']) + + return text.strip() + + +def download_item_icon(item: Item) -> None: + url = item.icon[0] + video_id = url.split('/')[-2] + path = TEMP_DIR / f'{video_id}.png' + with urlopen_with_headers(url) as response, path.open('wb') as sr: + sr.write(response.read()) + item.icon = [str(path)] + + +def entry_to_item(type_, data) -> Item | None: + icon = ICON + match type_: + case 'videoRenderer': + subtext = ['Video'] + action = 'Watch on Youtube' + url_path = f'watch?v={data["videoId"]}' + if 'lengthText' in data: + subtext.append(text_from(data['lengthText'])) + if 'shortViewCountText' in data: + subtext.append(text_from(data['shortViewCountText'])) + if 'publishedTimeText' in data: + subtext.append(text_from(data['publishedTimeText'])) + if data['thumbnail']['thumbnails']: + icon = data['thumbnail']['thumbnails'][0]['url'].split('?', 1)[0] + case 'channelRenderer': + subtext = ['Channel'] + action = 'Show on Youtube' + url_path = f'channel/{data["channelId"]}' + if 'videoCountText' in data: + subtext.append(text_from(data['videoCountText'])) + if 'subscriberCountText' in data: + subtext.append(text_from(data['subscriberCountText'])) + case _: + return None + + return Item( + id=f'{md_name}/{url_path}', + text=text_from(data['title']), + subtext=' | '.join(subtext), + icon=[icon], + actions=[Action(f'{md_name}/{url_path}', action, lambda: openUrl(f'https://www.youtube.com/{url_path}'))], + ) + + +def results_to_items(results: dict) -> List[Item]: + items: List[Item] = [] + for result in results: + for type_, data in result.items(): + try: + item = entry_to_item(type_, data) + if item is None: + continue + items.append(item) + except KeyError as e: + critical(e) + critical(json.dumps(result, indent=4)) + return items + + +class Plugin(QueryHandler): + def id(self) -> str: + return __name__ + + def name(self) -> str: + return md_name + + def description(self) -> str: + return md_description + + def defaultTrigger(self) -> str: + return 'yt ' + + def synopsis(self) -> str: + return 'query' + + def handleQuery(self, query: Query) -> None: + query_str = query.string.strip() + if not query_str: + return + + # Avoid rate limiting + for _ in range(50): + time.sleep(0.01) + if not query.isValid: + return + + info(f'Searching YouTube for \'{query_str}\'') + url = f'https://www.youtube.com/results?{urlencode({"search_query": query_str})}' + + with urlopen_with_headers(url) as response: + response_bytes: bytes = response.read() + match = re.search(DATA_REGEX, response_bytes.decode()) + if match is None: + critical( + 'Failed to receive expected data from YouTube. This likely means API changes, but could just be a ' + 'failed request.' + ) + log_html(response_bytes) + return + + results = json.loads(match.group(3)) + primary_contents = results['contents']['twoColumnSearchResultsRenderer']['primaryContents'] + results = primary_contents['sectionListRenderer']['contents'][0]['itemSectionRenderer']['contents'] + items = results_to_items(results) + + # Purge previous icons + for child in TEMP_DIR.iterdir(): + if child.is_file(): + child.unlink() + + # Download icons + with ThreadPoolExecutor(max_workers=10) as e: + for item in items: + e.submit(download_item_icon, item) + if not query.isValid: + return + + for item in items: + query.add(item) + + # Add a link to the *YouTube* page, in case there's more results, including results we didn't include + item = Item( + id=f'{md_name}/show_more', + text='Show more in browser', + icon=[ICON], + actions=[ + Action( + f'{md_name}/show_more', + 'Show more in browser', + lambda: openUrl(f'https://www.youtube.com/results?search_query={query_str}'), + ) + ], + ) + query.add(item) diff --git a/youtube/youtube.svg b/youtube/youtube.svg new file mode 100644 index 00000000..8d07b9db --- /dev/null +++ b/youtube/youtube.svg @@ -0,0 +1 @@ + \ No newline at end of file From 8b217a2cb33cfb696712df14f39606e01b1e03e7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 18 Jan 2023 22:22:17 +0100 Subject: [PATCH 084/355] Remove datetime. Migrated to C++. --- .archive/datetime/__init__.py | 85 ----------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 .archive/datetime/__init__.py diff --git a/.archive/datetime/__init__.py b/.archive/datetime/__init__.py deleted file mode 100644 index 6aa74de4..00000000 --- a/.archive/datetime/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Retrieve and convert datetime strings. - -This extension provides items for 'time', 'date', 'datetime' and 'epoch' respectively 'unixtime'. \ -The latter two yield the unix timestamp and also accept a unix timestamp as parameter which will \ -be converted to a datetime string. - -Synopsis: - - [timestamp]""" - -# Copyright (c) 2022 Manuel Schneider - -from datetime import datetime, date -import time - -from albert import * - -__title__ = "DateTime" -__version__ = "0.4.1" -__authors__ = "Manuel S." - -iconPath = iconLookup('x-office-calendar') - - -def handleQuery(query): - fields = list(filter(None, query.string.split())) - if fields: - def makeItem(text: str, subtext: str): - return Item( - id=__title__, - icon=iconPath, - text=text, - subtext=subtext, - actions=[ClipAction("Copy to clipboard", text)] - ) - - if "date".startswith(fields[0]) and len(fields) == 1: - return makeItem(date.today().strftime("%x"), - "Current date") - elif "time".startswith(fields[0]) and len(fields) == 1: - return makeItem(datetime.now().strftime("%X"), - "Current time (local)") - elif "utc".startswith(fields[0]) and len(fields) == 1: - return makeItem(datetime.utcnow().strftime("%X"), - "Current time (UTC)") - elif "datetime".startswith(fields[0]) and len(fields) == 1: - return makeItem(datetime.now().strftime("%c"), - "Current date and time") - elif "unixtime".startswith(fields[0]) or "epoch".startswith(fields[0]) or "ts".startswith(fields[0]): - if len(fields) == 2: - if fields[1].isdigit(): - timestamp = int(fields[1]) - if len(fields[1]) > 10: - timestamp = timestamp / 1000 - - return [ - makeItem(time.strftime("%c", time.localtime(timestamp)), - "Date and time of '%s'" % fields[1]), - makeItem(datetime.fromtimestamp(timestamp).astimezone().strftime("%Y-%m-%d %H:%M:%S.%f %Z"), - "Date and time of '%s'" % fields[1]), - makeItem(datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S.%f UTC"), - "UTC Date and time of '%s'" % fields[1]) - ] - else: - # TODO: how to utilize dateparser even when available on system default python install? - # dt = dateparser.parse(query.string) - return Item( - id=__title__, - icon=iconPath, - text="Invalid input", - subtext="Argument must be empty or numeric." - ) - else: - return [ - makeItem(datetime.now().strftime("%s"), - "Current unixtime"), - makeItem(str(round(time.time() * 1000)), - "Millis since Epoch"), - makeItem(datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f UTC"), - "UTC timestamp"), - makeItem(datetime.now().astimezone().strftime("%Y-%m-%d %H:%M:%S.%f %Z"), - "Local timestamp") - ] From 1e5f654c4c11e07a050ea74b009926d4c64690f3 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 19 Jan 2023 13:59:34 +0100 Subject: [PATCH 085/355] [trash] Drop. Provided by files plugin now. --- trash/__init__.py | 50 ------------ trash/trash.svg | 190 ---------------------------------------------- 2 files changed, 240 deletions(-) delete mode 100644 trash/__init__.py delete mode 100644 trash/trash.svg diff --git a/trash/__init__.py b/trash/__init__.py deleted file mode 100644 index a1fe8ca5..00000000 --- a/trash/__init__.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -This extension provides a single item which opens the -systems trash location in your default file manager. -""" - -# Copyright (c) 2023 Manuel Schneider - -from albert import * -import os -from platform import system -from pathlib import Path - -md_iid = "0.5" -md_version = "1.2" -md_name = "Trash" -md_description = "Open trash" -md_license = "BSD-3" -md_url = "https://github.com/albertlauncher/python/tree/master/trash" -md_maintainers = "@manuelschneid3r" - -class Plugin(QueryHandler): - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def initialize(self): - if (system() == 'Linux'): - trash_path = "trash:///" - icon = ["xdg:user-trash-full", os.path.dirname(__file__)+"/trash.svg"] - elif (system() == 'Darwin'): - trash_path = "file://%s/.Trash" % Path.home() - icon = [os.path.dirname(__file__)+"/trash.svg"] - else: - raise NotImplementedError("%1 not supported" % system()) - - self.trash_item = Item(id=md_id, - text="Trash", - subtext="Open trash folder", - icon=icon, - actions=[Action("trash-open", "Open trash", lambda path=trash_path: openUrl(path))]) - - def handleQuery(self, query): - query.add(self.trash_item) \ No newline at end of file diff --git a/trash/trash.svg b/trash/trash.svg deleted file mode 100644 index 9764f7bf..00000000 --- a/trash/trash.svg +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From ab6d81b1a76a554a7e8cd688550f088b90ad0952 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 22 Jan 2023 17:25:01 +0100 Subject: [PATCH 086/355] Update issue template --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8f227242..4b860dc1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,6 @@ --- name: Bug report -about: Please check the existing issues before creating a new one. +about: Please check the existing issues and discuss your issue in the chats before creating a new one. --- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 24c92928436c5c06f0ff8ef28f25d71c901ea4f6 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 25 Jan 2023 17:16:02 +0100 Subject: [PATCH 090/355] [timer] v1.4 iid:0.5 --- .archive/timer/__init__.py | 120 -------------------------- timer/__init__.py | 133 +++++++++++++++++++++++++++++ {.archive/timer => timer}/bing.wav | Bin {.archive/timer => timer}/time.svg | 0 4 files changed, 133 insertions(+), 120 deletions(-) delete mode 100644 .archive/timer/__init__.py create mode 100644 timer/__init__.py rename {.archive/timer => timer}/bing.wav (100%) rename {.archive/timer => timer}/time.svg (100%) diff --git a/.archive/timer/__init__.py b/.archive/timer/__init__.py deleted file mode 100644 index 5eafee5b..00000000 --- a/.archive/timer/__init__.py +++ /dev/null @@ -1,120 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Set up timers. - -Lists all timers when triggered. Additional arguments in the form of "[[hours:]minutes:]seconds -[name]" let you set triggers. Empty field resolve to 0, e.g. "96::" starts a 96 hours timer. -Fields exceeding the maximum amount of the time interval are automatically refactorized, e.g. -"9:120:3600" resolves to 12 hours. - -Synopsis: [[[hours]:][minutes]:]seconds [name]""" - -# Copyright (c) 2022 Manuel Schneider - -from albert import warning, Item, FuncAction -from threading import Timer -from time import strftime, time, localtime -import dbus -import os -from datetime import timedelta -import subprocess - -__title__ = "Timer" -__version__ = "0.4.3" -__triggers__ = "timer " -__authors__ = ["Manuel S.", "googol42"] -__py_deps__ = ["dbus"] - -iconPath = os.path.dirname(__file__)+"/time.svg" -soundPath = os.path.dirname(__file__)+"/bing.wav" -timers = [] - -bus_name = "org.freedesktop.Notifications" -object_path = "/org/freedesktop/Notifications" -interface = bus_name - -class AlbertTimer(Timer): - - def __init__(self, interval, name): - - def timeout(): - subprocess.Popen(["aplay", soundPath]) - global timers - timers.remove(self) - title = 'Timer "%s"' % self.name if self.name else 'Timer' - text = "Timed out at %s" % strftime("%X", localtime(self.end)) - notify = dbus.Interface(dbus.SessionBus().get_object(bus_name, object_path), interface) - notify.Notify(__title__, 0, iconPath, title, text, [], {"urgency":2}, 0) - - super().__init__(interval=interval, function=timeout) - self.interval = interval - self.name = name - self.begin = int(time()) - self.end = self.begin + interval - self.start() - - -def startTimer(interval, name): - global timers - timers.append(AlbertTimer(interval, name)) - - -def deleteTimer(timer): - global timers - timers.remove(timer) - timer.cancel() - -def handleQuery(query): - if query.isTriggered: - - if query.string.strip(): - args = query.string.strip().split(maxsplit=1) - fields = args[0].split(":") - name = args[1] if 1 < len(args) else '' - if not all(field.isdigit() or field == '' for field in fields): - return Item( - id=__title__, - text="Invalid input", - subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % __triggers__, - icon=iconPath - ) - - seconds = 0 - fields.reverse() - for i in range(len(fields)): - seconds += int(fields[i] if fields[i] else 0)*(60**i) - - return Item( - id=__title__, - text=str(timedelta(seconds=seconds)), - subtext='Set a timer with name "%s"' % name if name else 'Set a timer', - icon=iconPath, - actions=[FuncAction("Set timer", lambda sec=seconds: startTimer(sec, name))] - ) - - else: - # List timers - items = [] - for timer in timers: - - m, s = divmod(timer.interval, 60) - h, m = divmod(m, 60) - identifier = "%d:%02d:%02d" % (h, m, s) - - timer_name_with_quotes = '"%s"' % timer.name if timer.name else '' - items.append(Item( - id=__title__, - text='Delete timer %s [%s]' % (timer_name_with_quotes, identifier), - subtext="Times out %s" % strftime("%X", localtime(timer.end)), - icon=iconPath, - actions=[FuncAction("Delete timer", lambda timer=timer: deleteTimer(timer))] - )) - if items: - return items - # Display hint item - return Item( - id=__title__, - text="Add timer", - subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % __triggers__, - icon=iconPath - ) diff --git a/timer/__init__.py b/timer/__init__.py new file mode 100644 index 00000000..a6ce8ae9 --- /dev/null +++ b/timer/__init__.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- + +""" +Takes arguments in the form of '`[[hrs:]mins:]secs [name]`'. Empty fields resolve to `0`. \ +Fields exceeding the maximum amount of the time interval are automatically refactorized. + +Examples: +- `5:` starts a 5 minutes timer +- `1:: ` starts a 1 hour timer +- `120:` starts a 2 hours timer +""" + +from albert import * +from time import strftime, time, localtime +from datetime import timedelta +import threading +from sys import platform +import os +import subprocess + +md_iid = "0.5" +md_version = "1.4" +md_name = "Timer" +md_description = "Set up timers" +md_license = "BSD-2" +md_url = "https://github.com/albertlauncher/python/tree/master/timer" +md_maintainers = ["@manuelschneid3r", "@googol42", "@uztnus"] + +class Timer(threading.Timer): + + def __init__(self, interval, name, callback): + super().__init__(interval=interval, + function=lambda: callback(self)) + self.name = name + self.begin = int(time()) + self.end = self.begin + interval + self.start() + + +class Plugin(QueryHandler): + + def initialize(self): + self.icons = [os.path.dirname(__file__)+"/time.svg"] + self.soundPath = os.path.dirname(__file__)+"/bing.wav" + self.timers = [] + + def finalize(self): + for timer in self.timers: + timer.cancel() + self.timers.clear() + + def startTimer(self, interval, name): + self.timers.append(Timer(interval, name, self.onTimerTimeout)) + + def deleteTimer(self, timer): + self.timers.remove(timer) + timer.cancel() + + def onTimerTimeout(self, timer): + title = 'Timer "%s"' % timer.name if timer.name else 'Timer' + text = "Timed out at %s" % strftime("%X", localtime(timer.end)) + sendTrayNotification(title, text) + + if platform == "linux": + subprocess.Popen(["aplay", self.soundPath]) + elif platform == "darwin": + subprocess.Popen(["afplay", self.soundPath]) + + self.deleteTimer(timer) + + def id(self): + return md_id + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return 'timer ' + + def synopsis(self): + return '[[hrs:]mins:]secs [name]' + + def handleQuery(self, query): + if not query.isValid: + return + + if query.string.strip(): + args = query.string.strip().split(maxsplit=1) + fields = args[0].split(":") + name = args[1] if 1 < len(args) else '' + if not all(field.isdigit() or field == '' for field in fields): + return Item( + id=self.name(), + text="Invalid input", + subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % self.defaultTrigger(), + icon=self.icons + ) + + seconds = 0 + fields.reverse() + for i in range(len(fields)): + seconds += int(fields[i] if fields[i] else 0)*(60**i) + + query.add(Item( + id=self.name(), + text=str(timedelta(seconds=seconds)), + subtext='Set a timer with name "%s"' % name if name else 'Set a timer', + icon=self.icons, + actions=[Action("set-timer", "Set timer", lambda sec=seconds: self.startTimer(sec, name))] + )) + return + + # List timers + items = [] + for timer in self.timers: + m, s = divmod(timer.interval, 60) + h, m = divmod(m, 60) + identifier = "%d:%02d:%02d" % (h, m, s) + + timer_name_with_quotes = '"%s"' % timer.name if timer.name else '' + items.append(Item( + id=self.name(), + text='Delete timer %s [%s]' % (timer_name_with_quotes, identifier), + subtext="Times out %s" % strftime("%X", localtime(timer.end)), + icon=self.icons, + actions=[Action("delete-timer", "Delete timer", lambda timer=timer: self.deleteTimer(timer))] + )) + + if items: + query.add(items) \ No newline at end of file diff --git a/.archive/timer/bing.wav b/timer/bing.wav similarity index 100% rename from .archive/timer/bing.wav rename to timer/bing.wav diff --git a/.archive/timer/time.svg b/timer/time.svg similarity index 100% rename from .archive/timer/time.svg rename to timer/time.svg From bfd82c69fc4c2067228625db239f43afbaa2ace8 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 24 Jan 2023 02:03:19 +0100 Subject: [PATCH 091/355] [pacman] v1.6 iid:0.5 --- .archive/pacman/__init__.py | 109 -------------------------------- pacman/__init__.py | 122 ++++++++++++++++++++++++++++++++++++ pacman/arch.svg | 5 ++ 3 files changed, 127 insertions(+), 109 deletions(-) delete mode 100644 .archive/pacman/__init__.py create mode 100644 pacman/__init__.py create mode 100644 pacman/arch.svg diff --git a/.archive/pacman/__init__.py b/.archive/pacman/__init__.py deleted file mode 100644 index 5f4edf66..00000000 --- a/.archive/pacman/__init__.py +++ /dev/null @@ -1,109 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Arch Linux Package Manager (pacman) extension. - -The extension provides a way to install, remove and search for packages in the archlinux.org \ -database. If no search query is supplied, you have the option to do a system update. \ -Otherwise albert will try to find for packages matching the filter. For more information about \ -`pacman` please have a look at: https://wiki.archlinux.org/index.php/pacman - -Synopsis: [filter]""" - -# Copyright (c) 2022 Manuel Schneider - -import re -import subprocess -import time - -from albert import TermAction, iconLookup, Item, UrlAction - -__title__ = "PacMan" -__version__ = "0.4.4" -__triggers__ = "pacman " -__authors__ = ["Manuel S.", "Dudel B."] -__exec_deps__ = ["pacman", "expac"] - -iconPath = iconLookup(["archlinux-logo", "system-software-install"]) - - -def handleQuery(query): - if query.isTriggered: - if not query.string.strip(): - return Item( - id="%s-update" % __name__, - icon=iconPath, - text="Pacman package manager", - subtext="Enter the package you are looking for or hit enter to update.", - completion=__triggers__, - actions=[ - TermAction("Update the system (no confirm)", "sudo pacman -Syu --noconfirm"), - TermAction("Update the system", "sudo pacman -Syu") - ] - ) - - time.sleep(0.1) - if not query.isValid: - return - - # Get data. Results are sorted so we can merge in O(n) - proc_s = subprocess.Popen(["expac", "-Ss", "%n\t%v\t%r\t%d\t%u\t%E", query.string], - stdout=subprocess.PIPE, universal_newlines=True) - proc_q = subprocess.Popen(["expac", "-Qs", "%n", query.string], stdout=subprocess.PIPE, universal_newlines=True) - proc_q.wait() - - items = [] - pattern = re.compile(query.string, re.IGNORECASE) - local_pkgs = set(proc_q.stdout.read().split('\n')) - remote_pkgs = [tuple(line.split('\t')) for line in proc_s.stdout.read().split('\n')[:-1]] # newline at end - - for pkg_name, pkg_vers, pkg_repo, pkg_desc, pkg_purl, pkg_deps in remote_pkgs: - if not pattern.search(pkg_name): - continue - - pkg_installed = True if pkg_name in local_pkgs else False - - item = Item( - id="%s:%s:%s" % (__name__, pkg_repo, pkg_name), - icon=iconPath, - text="%s %s [%s]" - % (pattern.sub(lambda m: "%s" % m.group(0), pkg_name), pkg_vers, pkg_repo), - subtext=("[Installed] %s%s" if pkg_installed else "%s%s") - % (pkg_desc, (" (%s)" % pkg_deps) if pkg_deps else ""), - completion="%s%s" % (query.trigger, pkg_name) - ) - items.append(item) - - if pkg_installed: - item.addAction(TermAction("Remove", "sudo pacman -Rs %s" % pkg_name)) - item.addAction(TermAction("Reinstall", "sudo pacman -S %s" % pkg_name)) - else: - item.addAction(TermAction("Install", "sudo pacman -S %s" % pkg_name)) - item.addAction(UrlAction("Show on packages.archlinux.org", "https://www.archlinux.org/packages/%s/x86_64/%s/" % (pkg_repo, pkg_name))) - if pkg_purl: - item.addAction(UrlAction("Show project website", pkg_purl)) - - if items: - return items - else: - return Item( - id="%s-empty" % __name__, - icon=iconPath, - text="Search on archlinux.org", - subtext="No results found in the local database", - actions=[ - UrlAction("Search on archlinux.org", - "https://www.archlinux.org/packages/?q=%s" % query.string.strip()) - ] - ) - - elif len(query.string.strip()) > 0 and ("pacman".startswith(query.string.lower()) or "update".startswith(query.string.lower())): - return Item( - id="%s-update" % __name__, - icon=iconPath, - text="Update all packages on the system", - subtext="Synchronizes the repository databases and updates the system's packages", - actions=[ - TermAction("Update the system (no confirm)", "sudo pacman -Syu --noconfirm"), - TermAction("Update the system", "sudo pacman -Syu") - ] - ) diff --git a/pacman/__init__.py b/pacman/__init__.py new file mode 100644 index 00000000..5535d4c0 --- /dev/null +++ b/pacman/__init__.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- + +""" +This plugin is a `pacman` (Arch Linux Package Manager) wrapper. You can update, search, install and remove \ +packages. +""" + +import subprocess +from time import sleep +import pathlib + +from albert import Action, Item, QueryHandler, runTerminal + +md_iid = "0.5" +md_version = "1.6" +md_name = "PacMan" +md_description = "Search, install and remove packages" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/pacman" +md_bin_dependencies = ["pacman", "expac"] + + +class Plugin(QueryHandler): + + pkgs_url = "https://www.archlinux.org/packages/" + + def id(self): + return md_id + + def name(self): + return md_name + + def description(self): + return md_description + + def synopsis(self): + return "" + + def defaultTrigger(self): + return "pac " + + def initialize(self): + self.icons = [ + "xdg:archlinux-logo", + "xdg:system-software-install", + str(pathlib.Path(__file__).parent / "arch.svg") + ] + + def handleQuery(self, query): + stripped = query.string.strip() + + # Update item on empty queries + if not stripped: + query.add(Item( + id="%s-update" % md_id, + text="Pacman package manager", + subtext="Enter the package you are looking for or hit enter to update.", + icon=self.icons, + actions=[ + Action("up-nc", "Update packages (no confirm)", + lambda: runTerminal("sudo pacman -Syu --noconfirm")), + Action("up", "Update packages", lambda: runTerminal("sudo pacman -Syu")), + Action("up-cache", "Update pacman cache", lambda: runTerminal("sudo pacman -Sy")) + ] + )) + return + + # avoid rate limiting + for number in range(50): + sleep(0.01) + if not query.isValid: + return + + # Get data. Results are sorted so we can merge in O(n) + proc_s = subprocess.Popen(["expac", "-Ss", "%n\t%v\t%r\t%d\t%u\t%E", stripped], + stdout=subprocess.PIPE, universal_newlines=True) + proc_q = subprocess.Popen(["expac", "-Qs", "%n", stripped], stdout=subprocess.PIPE, universal_newlines=True) + proc_q.wait() + + items = [] + local_pkgs = set(proc_q.stdout.read().split('\n')) + remote_pkgs = [tuple(line.split('\t')) for line in proc_s.stdout.read().split('\n')[:-1]] # newline at end + + for pkg_name, pkg_vers, pkg_repo, pkg_desc, pkg_purl, pkg_deps in remote_pkgs: + if stripped not in pkg_name : + continue + + pkg_installed = True if pkg_name in local_pkgs else False + + actions = [] + if pkg_installed: + actions.extend([ + Action("rem", "Remove", lambda: runTerminal("sudo pacman -Rs %s" % pkg_name)), + Action("reinst", "Reinstall", lambda: runTerminal("sudo pacman -S %s" % pkg_name)) + ]) + else: + actions.append(Action("inst", "Install", lambda: runTerminal("sudo pacman -S %s" % pkg_name))) + actions.append(Action("pkg_url", "Show on packages.archlinux.org", + lambda: openUrl(f"{pkg_repo}/x86_64/{pkg_name}/"))) + if pkg_purl: + actions.append(Action("proj_url", "Show project website", lambda: openUrl(pkg_purl))) + + item = Item( + id="%s_%s_%s" % (md_id, pkg_repo, pkg_name), + icon=self.icons, + text="%s %s [%s]" % (pkg_name, pkg_vers, pkg_repo), + subtext=f"{pkg_desc} [Installed]" if pkg_installed else f"{pkg_desc}", + completion="%s%s" % (query.trigger, pkg_name), + actions=actions + ) + items.append(item) + + if items: + query.add(items) + else: + query.add(Item( + id="%s-empty" % md_id, + text="Search on archlinux.org", + subtext="No results found in the local database", + icon=self.icons, + actions=[Action("search", "Search on archlinux.org", lambda: openUrl(f"{self.pkgs_url}?q={stripped}"))] + )) diff --git a/pacman/arch.svg b/pacman/arch.svg new file mode 100644 index 00000000..61f55ed9 --- /dev/null +++ b/pacman/arch.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file From 07812fe1935a653214ef8f5f1d13b8a1b9405fe3 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Tue, 10 Jan 2023 13:39:01 -0700 Subject: [PATCH 092/355] [pint] 1.0 Rename folder refactor: method names and inheritance Update URL to albertlauncher repo Delete LICENSE Move config inline Remove traceback when error expected Update README.md Eliminate rounding config revert version change docs: Fix to docstrings Increase decimal accuracy Add precision to config but default to 12 I think 12 is a good balance for accuracy and readability. Doesn't need to be much higher since after that point there are likely floating point accuracy errors anyway. Prevent lack of internet from preventing startup --- unit_converter/README.md | 32 ++ unit_converter/__init__.py | 474 ++++++++++++++++++++++++ unit_converter/icons/currency.svg | 11 + unit_converter/icons/current.svg | 10 + unit_converter/icons/length.svg | 10 + unit_converter/icons/lengthtime.svg | 10 + unit_converter/icons/luminosity.svg | 10 + unit_converter/icons/mass.svg | 4 + unit_converter/icons/printing_unit.svg | 10 + unit_converter/icons/substance.svg | 10 + unit_converter/icons/temperature.svg | 10 + unit_converter/icons/time.svg | 4 + unit_converter/icons/unit_converter.svg | 4 + 13 files changed, 599 insertions(+) create mode 100644 unit_converter/README.md create mode 100644 unit_converter/__init__.py create mode 100644 unit_converter/icons/currency.svg create mode 100644 unit_converter/icons/current.svg create mode 100644 unit_converter/icons/length.svg create mode 100644 unit_converter/icons/lengthtime.svg create mode 100644 unit_converter/icons/luminosity.svg create mode 100644 unit_converter/icons/mass.svg create mode 100644 unit_converter/icons/printing_unit.svg create mode 100644 unit_converter/icons/substance.svg create mode 100644 unit_converter/icons/temperature.svg create mode 100644 unit_converter/icons/time.svg create mode 100644 unit_converter/icons/unit_converter.svg diff --git a/unit_converter/README.md b/unit_converter/README.md new file mode 100644 index 00000000..163cc92a --- /dev/null +++ b/unit_converter/README.md @@ -0,0 +1,32 @@ +# Unit Converter + +Extension for converting units of length, mass, speed, temperature, time, +current, luminosity, printing measurements, molecular substance, and currency. + +All units from the Pint Python library are supported. + +Currency conversion rates are provided by . + +Examples: + +`convert 180 minutes to hrs` + +`convert 100 km to miles` + +`convert 88 mph to kph` + +`convert 32 degrees F to C` + +`convert 3.14159 rad to degrees` + +`convert 100 USD to EUR` + +![demo 0.18](https://user-images.githubusercontent.com/20955511/211650412-b42412f3-c4d5-4d2a-8b77-05ff39fcb48e.gif) + +## Install Requirements + +Ensure that `Pint` and `inflect` are installed in `~/.local/share/albert/python/site-packages`. + +```bash +pip install -U inflect==6.0.2 Pint==0.20.1 -t ~/.local/share/albert/python/site-packages +``` diff --git a/unit_converter/__init__.py b/unit_converter/__init__.py new file mode 100644 index 00000000..8a6c4ac7 --- /dev/null +++ b/unit_converter/__init__.py @@ -0,0 +1,474 @@ +# -*- coding: utf-8 -*- + +from __future__ import annotations + +import json +import re +import traceback +from datetime import datetime +from pathlib import Path +from typing import Any +from urllib.error import URLError +from urllib.request import urlopen + +import albert +import inflect +import pint + +__doc__ = """ +Extension for converting units of length, mass, speed, temperature, time, +current, luminosity, printing measurements, molecular substance, and currency. + +All units from the Pint Python library are supported. + +Currency conversion rates are provided by https://www.exchangerate-api.com + +Examples: +`convert 180 minutes to hrs` +`convert 100 km to miles` +`convert 88 mph to kph` +`convert 32 degrees F to C` +`convert 3.14159 rad to degrees` +`convert 100 USD to EUR` +""" + +md_iid = "0.5" +md_version = "1.2" +md_name = "Unit Converter" +md_description = "Convert between units" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python" +md_lib_dependencies = ["pint", "inflect"] +md_maintainers = "@DenverCoder1" + + +class ConversionResult: + """A class to represent the result of a unit conversion""" + + def __init__( + self, + from_amount: float, + from_unit: str, + to_amount: float, + to_unit: str, + dimensionality: str, + source: str = "", + ): + """Initialize the ConversionResult + + Args: + from_amount (float): The amount to convert from + from_unit (str): The unit to convert from + to_amount (float): The resulting amount + to_unit (str): The unit converted to + dimensionality (str): The dimensionality of the result + source (str): The source of the conversion for attribution + """ + self.from_amount = from_amount + self.from_unit = from_unit + self.to_amount = to_amount + self.to_unit = to_unit + self.dimensionality = dimensionality + self.source = source + self.display_names: dict[str, str] = Plugin.config["display_names"] + self.inflect_engine = inflect.engine() + + def __pluralize_unit(self, unit: str) -> str: + """Pluralize the unit + + Args: + unit (str): The unit to pluralize + + Returns: + str: The pluralized unit + """ + # if all characters are uppercase, don't pluralize + if unit.isupper(): + return unit + return self.inflect_engine.plural(unit) + + def __display_unit_name(self, amount: float, unit: str) -> str: + """Display the name of the unit with plural if necessary + + Args: + amount (float): The amount to display + unit (str): The unit to display + + Returns: + str: The name of the unit + """ + unit = self.__pluralize_unit(unit) if amount != 1 else unit + return self.display_names.get(unit, unit) + + def __format_float(self, num: float) -> str: + """Format a float to remove trailing zeros and avoid scientific notation + + Args: + num (float): The number to format + + Returns: + str: The formatted number + """ + # format the float to remove trailing zeros and decimal point + precision: int = Plugin.config["precision"] + return f"{num:.{precision}f}".rstrip("0").rstrip(".") + + @property + def formatted_result(self) -> str: + """Return the formatted result amount and unit""" + units = self.__display_unit_name(self.to_amount, self.to_unit) + return f"{self.__format_float(self.to_amount)} {units}" + + @property + def formatted_from(self) -> str: + """Return the formatted from amount and unit""" + units = self.__display_unit_name(self.from_amount, self.from_unit) + result = f"{self.__format_float(self.from_amount)} {units}" + if self.source: + result += f" ({self.source})" + return result + + @property + def icon(self) -> str: + """Return the icon for the result's dimensionality""" + # strip characters from the dimensionality if not alphanumeric or underscore + dimensionality = re.sub(r"[^\w]", "", self.dimensionality) + return f"{dimensionality}.svg" + + def __repr__(self): + """Return the representation of the result""" + return f"{self.formatted_from} = {self.formatted_result}" + + +class UnitConverter: + """Base class for unit converters""" + + def __init__(self): + """Initialize the UnitConverter""" + self.aliases: dict[str, str] = Plugin.config["aliases"] + + def convert(self, amount: float, from_unit: str, to_unit: str) -> ConversionResult: + """Convert a unit to another unit + + Args: + amount (float): The amount to convert + from_unit (str): The unit to convert from + to_unit (str): The unit to convert to + + Returns: + ConversionResult: Object containing information about the conversion result + """ + raise NotImplementedError + + +class StandardUnitConverter(UnitConverter): + """Class to convert standard units of measurement""" + + def __init__(self): + """Initialize the StandardUnitConverter""" + self.units = pint.UnitRegistry() + super().__init__() + + def _get_unit(self, unit: str) -> pint.Unit: + """Check if the unit is a valid unit and return it + If any aliases are found, replace the unit with the alias + If the unit is not valid, check if making it lowercase will fix it + If not, raise the UndefinedUnitError + + Args: + unit (str): The unit to check + + Returns: + pint.Unit: The unit + + Raises: + pint.errors.UndefinedUnitError: If the unit is not valid + """ + unit = self.aliases.get(unit, unit) + if unit in self.units: + # return the unit if it is valid + return self.units.__getattr__(unit) + # check if the lowercase version is a valid unit + return self.units.__getattr__(unit.lower()) + + def convert(self, amount: float, from_unit: str, to_unit: str) -> ConversionResult: + """Convert a unit to another unit + + Args: + amount (float): The amount to convert + from_unit (str): The unit to convert from + to_unit (str): The unit to convert to + + Returns: + ConversionResult: Object containing information about the conversion result + + Raises: + pint.errors.UndefinedUnitError: If the unit is not valid + pint.errors.DimensionalityError: If the units are not compatible + """ + input_unit = self.units.Quantity(amount, self._get_unit(from_unit)) + output_unit = self._get_unit(to_unit) + result = input_unit.to(output_unit) + return ConversionResult( + from_amount=float(amount), + from_unit=str(self._get_unit(from_unit)), + to_amount=result.magnitude, + to_unit=str(result.units), + dimensionality=str(self.units._get_dimensionality(result.units)), + ) + + +class UnknownCurrencyError(Exception): + """Exception to raise when an unknown currency is passed to convert""" + + def __init__(self, currency: str): + """Initialize the UnknownCurrencyError + + Args: + currency (str): The unknown currency + """ + self.currency = currency + super().__init__(f"Unknown currency: {currency}") + + +class CurrencyConverter(UnitConverter): + """Class to convert currencies""" + + API_URL = "https://open.er-api.com/v6/latest/USD" + ATTRIBUTION = "Rates by https://www.exchangerate-api.com" + + def __init__(self): + """Initialize the CurrencyConverter""" + self.last_update = datetime.now() + self.currencies = self._get_currencies() + super().__init__() + + def _get_currencies(self) -> dict[str, float]: + """Get the currencies from the API + + Returns: + dict[str, float]: The currencies + """ + try: + with urlopen(self.API_URL) as response: + data = json.loads(response.read().decode("utf-8")) + if not data or "rates" not in data: + albert.info("No currencies found") + return {} + albert.info(f'Currencies updated: {data["rates"]}') + return data["rates"] + except URLError as error: + albert.warning(f"Error getting currencies: {error}") + return {} + + def get_currency(self, currency: str) -> str | None: + """Get the currency name normalized using aliases and capitalization + + Args: + currency (str): The currency to normalize + + Returns: + Optional[str]: The currency name or None if not found + """ + # update the currencies every 24 hours + if not self.currencies or (datetime.now() - self.last_update).days >= 1: + self.currencies = self._get_currencies() + self.last_update = datetime.now() + currency = self.aliases.get(currency, currency).upper() + return currency if currency in self.currencies else None + + def convert(self, amount: float, from_unit: str, to_unit: str) -> ConversionResult: + """Convert a currency to another currency + + Args: + amount (float): The amount to convert + from_unit (str): The currency to convert from + to_unit (str): The currency to convert to + + Returns: + ConversionResult: Object containing information about the conversion result + + Raises: + UnknownCurrencyError: If the currency is not valid + """ + # get the currency rates + from_currency = self.get_currency(from_unit) + to_currency = self.get_currency(to_unit) + # convert the currency + if from_currency is None: + raise UnknownCurrencyError(from_unit) + if to_currency is None: + raise UnknownCurrencyError(to_unit) + from_rate = self.currencies[from_currency] + to_rate = self.currencies[to_currency] + result = amount * to_rate / from_rate + return ConversionResult( + from_amount=float(amount), + from_unit=from_currency, + to_amount=result, + to_unit=to_currency, + dimensionality="currency", + source=self.ATTRIBUTION, + ) + + +class Plugin(albert.QueryHandler): + """The plugin class""" + + unit_convert_regex = re.compile( + r"(?P-?\d+\.?\d*)\s?(?P.*)\s(?:to|in)\s(?P.*)", + re.I, + ) + + config: dict[str, Any] = { + # Maximum number of decimal places for precision + "precision": 12, + # Unit aliases to replace when parsing + # Units may be added here to override the default behavior or create aliases for existing units + # The alias is the key, the string to replace it with is the value + "aliases": { + "sec": "second", + "kph": "km/hour", + "km/h": "km/hour", + "mph": "mile/hour", + "degrees F": "degF", + "degrees C": "degC", + "F": "degF", + "C": "degC", + }, + # Display names for units + # Units may be added here to override the default display names + # The string version of the unit is the key, the display name to replace with is the value + # Both the unpluralized and the pluralized version should be included + "display_names": { + "degree_Celsius": "°C", + "degree_Celsiuses": "°C", + "degree_Fahrenheit": "°F", + "degree_Fahrenheits": "°F", + "mile / hour": "mph", + "mile / hours": "mph", + "kilometer / hour": "km/h", + "kilometer / hours": "km/h", + "kilometer_per_hour": "km/h", + "kilometer_per_hours": "km/h", + }, + } + + def initialize(self): + self.unit_converter = StandardUnitConverter() + self.currency_converter = CurrencyConverter() + + def id(self) -> str: + return __name__ + + def name(self) -> str: + return md_name + + def description(self) -> str: + return md_description + + def synopsis(self) -> str: + return " to " + + def defaultTrigger(self) -> str: + return "convert " + + def handleQuery(self, query: albert.Query) -> None: + query_string = query.string.strip() + match = self.unit_convert_regex.fullmatch(query_string) + if match: + albert.info(f"Matched {query_string}") + try: + items = self._get_items( + float(match.group("from_amount")), + match.group("from_unit").strip(), + match.group("to_unit").strip(), + ) + query.add(items) + except Exception as error: + albert.warning(f"Error: {error}") + tb = "".join( + traceback.format_exception(error.__class__, error, error.__traceback__) + ) + albert.warning(tb) + albert.info("Something went wrong. Make sure you're using the correct format.") + + def _create_item(self, text: str, subtext: str, icon: str = "") -> albert.Item: + """Create an albert.Item from a text and subtext + + Args: + text (str): The text to display + subtext (str): The subtext to display + icon (Optional[str]): The icon to display. If not specified, the default icon will be used + + Returns: + albert.Item: The item to be added to the list of results + """ + icon_path = Path(__file__).parent / "icons" / icon + if not icon or not icon_path.exists(): + albert.warning(f"Icon {icon} does not exist") + icon_path = Path(__file__).parent / "icons" / "unit_converter.svg" + return albert.Item( + id=str(icon_path), + icon=[str(icon_path)], + text=text, + subtext=subtext, + actions=[ + albert.Action( + id="copy", + text="Copy result to clipboard", + callable=lambda: albert.setClipboardText(text=text), + ) + ], + ) + + def _get_converter(self, from_unit: str, to_unit: str) -> UnitConverter: + """Get the converter to use + + Args: + from_unit (str): The unit to convert from + to_unit (str): The unit to convert to + + Returns: + UnitConverter: The converter to use + """ + if ( + self.currency_converter.get_currency(from_unit) is not None + and self.currency_converter.get_currency(to_unit) is not None + ): + return self.currency_converter + return self.unit_converter + + def _get_items(self, amount: float, from_unit: str, to_unit: str) -> list[albert.Item]: + """Generate the Albert items to display for the query + + Args: + amount (float): The amount to convert from + from_unit (str): The unit to convert from + to_unit (str): The unit to convert to + + Returns: + List[albert.Item]: The list of items to display + """ + try: + converter = self._get_converter(from_unit, to_unit) + result = converter.convert(amount, from_unit, to_unit) + # return the result + return [ + self._create_item( + result.formatted_result, + f"Converted from {result.formatted_from}", + result.icon, + ) + ] + except pint.errors.DimensionalityError as e: + albert.warning(f"DimensionalityError: {e}") + return [ + self._create_item(f"Unable to convert {amount} {from_unit} to {to_unit}", str(e)) + ] + except pint.errors.UndefinedUnitError as e: + albert.warning(f"UndefinedUnitError: {e}") + return [] + except UnknownCurrencyError as e: + albert.warning(f"UnknownCurrencyError: {e}") + return [] diff --git a/unit_converter/icons/currency.svg b/unit_converter/icons/currency.svg new file mode 100644 index 00000000..51a9f40c --- /dev/null +++ b/unit_converter/icons/currency.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/unit_converter/icons/current.svg b/unit_converter/icons/current.svg new file mode 100644 index 00000000..b7cd3ad6 --- /dev/null +++ b/unit_converter/icons/current.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/unit_converter/icons/length.svg b/unit_converter/icons/length.svg new file mode 100644 index 00000000..b3af30a7 --- /dev/null +++ b/unit_converter/icons/length.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/unit_converter/icons/lengthtime.svg b/unit_converter/icons/lengthtime.svg new file mode 100644 index 00000000..edaf5548 --- /dev/null +++ b/unit_converter/icons/lengthtime.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/unit_converter/icons/luminosity.svg b/unit_converter/icons/luminosity.svg new file mode 100644 index 00000000..1f937881 --- /dev/null +++ b/unit_converter/icons/luminosity.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/unit_converter/icons/mass.svg b/unit_converter/icons/mass.svg new file mode 100644 index 00000000..981faac3 --- /dev/null +++ b/unit_converter/icons/mass.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/unit_converter/icons/printing_unit.svg b/unit_converter/icons/printing_unit.svg new file mode 100644 index 00000000..e284337b --- /dev/null +++ b/unit_converter/icons/printing_unit.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/unit_converter/icons/substance.svg b/unit_converter/icons/substance.svg new file mode 100644 index 00000000..5859d59a --- /dev/null +++ b/unit_converter/icons/substance.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/unit_converter/icons/temperature.svg b/unit_converter/icons/temperature.svg new file mode 100644 index 00000000..595e9d53 --- /dev/null +++ b/unit_converter/icons/temperature.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/unit_converter/icons/time.svg b/unit_converter/icons/time.svg new file mode 100644 index 00000000..d8c97c46 --- /dev/null +++ b/unit_converter/icons/time.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/unit_converter/icons/unit_converter.svg b/unit_converter/icons/unit_converter.svg new file mode 100644 index 00000000..e040bd91 --- /dev/null +++ b/unit_converter/icons/unit_converter.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file From 9511c21106b18152ce48b38be509108a16144aab Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 25 Jan 2023 19:57:34 +0100 Subject: [PATCH 093/355] [pint] minor adjustments --- unit_converter/README.md | 32 -------------------------------- unit_converter/__init__.py | 29 +++++++++++++---------------- 2 files changed, 13 insertions(+), 48 deletions(-) delete mode 100644 unit_converter/README.md diff --git a/unit_converter/README.md b/unit_converter/README.md deleted file mode 100644 index 163cc92a..00000000 --- a/unit_converter/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Unit Converter - -Extension for converting units of length, mass, speed, temperature, time, -current, luminosity, printing measurements, molecular substance, and currency. - -All units from the Pint Python library are supported. - -Currency conversion rates are provided by . - -Examples: - -`convert 180 minutes to hrs` - -`convert 100 km to miles` - -`convert 88 mph to kph` - -`convert 32 degrees F to C` - -`convert 3.14159 rad to degrees` - -`convert 100 USD to EUR` - -![demo 0.18](https://user-images.githubusercontent.com/20955511/211650412-b42412f3-c4d5-4d2a-8b77-05ff39fcb48e.gif) - -## Install Requirements - -Ensure that `Pint` and `inflect` are installed in `~/.local/share/albert/python/site-packages`. - -```bash -pip install -U inflect==6.0.2 Pint==0.20.1 -t ~/.local/share/albert/python/site-packages -``` diff --git a/unit_converter/__init__.py b/unit_converter/__init__.py index 8a6c4ac7..329c8532 100644 --- a/unit_converter/__init__.py +++ b/unit_converter/__init__.py @@ -1,5 +1,18 @@ # -*- coding: utf-8 -*- +""" +Unit converter based on the [Pint Python library](https://pint.readthedocs.io/en/stable/). + +Usage examples: +- `convert 180 minutes to hrs` +- `convert 100 km to miles` +- `convert 88 mph to kph` +- `convert 32 degrees F to C` +- `convert 3.14159 rad to degrees` +- `convert 100 USD to EUR` +""" + + from __future__ import annotations import json @@ -15,22 +28,6 @@ import inflect import pint -__doc__ = """ -Extension for converting units of length, mass, speed, temperature, time, -current, luminosity, printing measurements, molecular substance, and currency. - -All units from the Pint Python library are supported. - -Currency conversion rates are provided by https://www.exchangerate-api.com - -Examples: -`convert 180 minutes to hrs` -`convert 100 km to miles` -`convert 88 mph to kph` -`convert 32 degrees F to C` -`convert 3.14159 rad to degrees` -`convert 100 USD to EUR` -""" md_iid = "0.5" md_version = "1.2" From ecf9375dab1ed83c1193559e45cd4cd448ae3790 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 27 Jan 2023 15:40:38 +0100 Subject: [PATCH 094/355] [pint] dont bloat output with exchange rates --- unit_converter/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit_converter/__init__.py b/unit_converter/__init__.py index 329c8532..3a4a840d 100644 --- a/unit_converter/__init__.py +++ b/unit_converter/__init__.py @@ -252,7 +252,7 @@ def _get_currencies(self) -> dict[str, float]: if not data or "rates" not in data: albert.info("No currencies found") return {} - albert.info(f'Currencies updated: {data["rates"]}') + albert.info(f'Currencies updated') return data["rates"] except URLError as error: albert.warning(f"Error getting currencies: {error}") From af896279a55f84915e7c5296e40977420a5e0c54 Mon Sep 17 00:00:00 2001 From: Thomas Queste Date: Tue, 31 Jan 2023 10:05:22 +0100 Subject: [PATCH 095/355] [jetbrains] 1.0 (iid:0.5) --- .archive/jetbrains_projects/.gitignore | 2 - .archive/jetbrains_projects/README.md | 39 ---- .archive/jetbrains_projects/__init__.py | 144 -------------- .archive/jetbrains_projects/jetbrains.svg | 70 ------- .../LICENSE | 0 jetbrains_projects/README.md | 24 +++ jetbrains_projects/__init__.py | 188 ++++++++++++++++++ jetbrains_projects/androidstudio.svg | 1 + jetbrains_projects/clion.svg | 1 + jetbrains_projects/datagrip.svg | 1 + jetbrains_projects/dataspell.svg | 1 + jetbrains_projects/goland.svg | 1 + jetbrains_projects/idea.svg | 1 + jetbrains_projects/phpstorm.svg | 1 + jetbrains_projects/pycharm.svg | 1 + jetbrains_projects/rider.svg | 1 + jetbrains_projects/rubymine.svg | 1 + jetbrains_projects/webstorm.svg | 1 + 18 files changed, 223 insertions(+), 255 deletions(-) delete mode 100644 .archive/jetbrains_projects/.gitignore delete mode 100644 .archive/jetbrains_projects/README.md delete mode 100644 .archive/jetbrains_projects/__init__.py delete mode 100644 .archive/jetbrains_projects/jetbrains.svg rename {.archive/jetbrains_projects => jetbrains_projects}/LICENSE (100%) create mode 100644 jetbrains_projects/README.md create mode 100644 jetbrains_projects/__init__.py create mode 100644 jetbrains_projects/androidstudio.svg create mode 100644 jetbrains_projects/clion.svg create mode 100644 jetbrains_projects/datagrip.svg create mode 100644 jetbrains_projects/dataspell.svg create mode 100644 jetbrains_projects/goland.svg create mode 100644 jetbrains_projects/idea.svg create mode 100644 jetbrains_projects/phpstorm.svg create mode 100644 jetbrains_projects/pycharm.svg create mode 100644 jetbrains_projects/rider.svg create mode 100644 jetbrains_projects/rubymine.svg create mode 100644 jetbrains_projects/webstorm.svg diff --git a/.archive/jetbrains_projects/.gitignore b/.archive/jetbrains_projects/.gitignore deleted file mode 100644 index 84528e5c..00000000 --- a/.archive/jetbrains_projects/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.pyc -__pycache/* diff --git a/.archive/jetbrains_projects/README.md b/.archive/jetbrains_projects/README.md deleted file mode 100644 index 4fb746a3..00000000 --- a/.archive/jetbrains_projects/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Jetbrains-albert-plugin - -This is a plugin for the albert launcher(https://albertlauncher.github.io/) which lists and lets you start projects of Jetbrains IDEs such as IntelliJ IDEA, PyCharm, GoLand, etc. - -I made this project to maintain this plugin, which was originally part of the albert community plugins. The plugin itself(the python file(s)) is licensed under the GPLv3 license. - -DISCLAIMER: I have no affiliation with JetBrains s.r.o. The included fallback logo `jetbrains.svg` is not my property, I am using it under the terms specified [here](https://www.jetbrains.com/company/useterms.html). - -## How to install: -If you are using git, you can use the following command which will clone the repository into the right directory (respecting the XDG standard). -``` -$ git clone https://github.com/mqus/jetbrains-albert-plugin.git ${XDG_DATA_HOME:-$HOME/.local/share}/albert/org.albert.extension.python/modules/jetbrains-projects -``` - - -If you don't have git, you can simply download a zip archive, extract it and move the folder containing `__init__.py` into the `.local/share/albert/org.albert.extension.python/modules` directory in your home directory, while creating any folders that don't exist yet. - -After that, you should have the following structure: -``` -[...] -'- modules - '- - |- __init.py - '- jetbrains.svg - -``` - -Now, open your albert settings and go to Extensions and then Python. You can then activate the plugin there. You might have to restart albert if it does not show up there at first. - -## Contributors: - -Thomas Queste (@tomsquest) - -@iyzana - -@Sharsie - -@dsager - diff --git a/.archive/jetbrains_projects/__init__.py b/.archive/jetbrains_projects/__init__.py deleted file mode 100644 index 8d6d32db..00000000 --- a/.archive/jetbrains_projects/__init__.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- - -"""List and open JetBrains IDE projects.""" - -# Copyright (c) 2022 Manuel Schneider - -import os -from shutil import which -from xml.etree import ElementTree - -from albertv0 import * - -__iid__ = "PythonInterface/v0.1" -__prettyname__ = "Jetbrains IDE Projects" -__version__ = "1.3" -__trigger__ = "jb " -__author__ = "Markus Richter, Thomas Queste" -__dependencies__ = [] - -default_icon = os.path.dirname(__file__) + "/jetbrains.svg" -HOME_DIR = os.environ["HOME"] -JETBRAINS_XDG_CONFIG_DIR = os.path.join(HOME_DIR, ".config/JetBrains") - -paths = [ # , - ["AndroidStudio", "android-studio"], - ["CLion", "clion"], - ["DataGrip", "datagrip"], - ["GoLand", "goland"], - ["IntelliJIdea", - "intellij-idea-ue-bundled-jre intellij-idea-ultimate-edition idea-ce-eap idea-ue-eap idea idea-ultimate"], - ["PhpStorm", "phpstorm"], - ["PyCharm", "pycharm pycharm-eap charm"], - ["RubyMine", "rubymine jetbrains-rubymine jetbrains-rubymine-eap"], - ["WebStorm", "webstorm"], -] - - -# find the executable path and icon of a program described by space-separated lists of possible binary-names -def find_exec(namestr: str): - for name in namestr.split(" "): - executable = which(name) - if executable: - icon = iconLookup(name) or default_icon - return executable, icon - return None - - -# parse the xml at path, return all recent project paths and the time they were last open -def get_proj(path): - r = ElementTree.parse(path).getroot() # type:ElementTree.Element - add_info = None - items = dict() - for o in r[0]: # type:ElementTree.Element - if o.attrib["name"] == 'recentPaths': - for i in o[0]: - items[i.attrib["value"]] = 0 - - else: - if o.attrib["name"] == 'additionalInfo': - add_info = o[0] - - if len(items) == 0: - return [] - - if add_info is not None: - for i in add_info: - for o in i[0][0]: - if o.tag == 'option' and 'name' in o.attrib and o.attrib["name"] == 'projectOpenTimestamp': - items[i.attrib["key"]] = int(o.attrib["value"]) - return [(items[e], e.replace("$USER_HOME$", HOME_DIR)) for e in items] - - -def handleQuery(query): - if query.isTriggered: - binaries = {} - projects = [] - - for app in paths: - config_path = "options/recentProjects.xml" - - full_config_path = None - - # newer versions (since 2020.1) put their configuration here - if os.path.isdir(JETBRAINS_XDG_CONFIG_DIR): - # dirs contains possibly multiple directories for a program (eg. .GoLand2018.1 and .GoLand2017.3) - dirs = [f for f in os.listdir(JETBRAINS_XDG_CONFIG_DIR) if - os.path.isdir(os.path.join(JETBRAINS_XDG_CONFIG_DIR, f)) and f.startswith(app[0])] - # take the newest - dirs.sort(reverse=True) - if len(dirs) != 0: - full_config_path = os.path.join(JETBRAINS_XDG_CONFIG_DIR, dirs[0], config_path) - - # if no config was found in the newer path, repeat for the old ones - if full_config_path is None or not os.path.exists(full_config_path): - if app[0] != "IntelliJIdea" and app[0] != "AndroidStudio": - config_path = "options/recentProjectDirectories.xml" - # dirs contains possibly multiple directories for a program (eg. .GoLand2018.1 and .GoLand2017.3) - dirs = [f for f in os.listdir(HOME_DIR) if - os.path.isdir(os.path.join(HOME_DIR, f)) and f.startswith("." + app[0])] - # take the newest - dirs.sort(reverse=True) - if len(dirs) == 0: - continue - - full_config_path = os.path.join(HOME_DIR, dirs[0], "config", config_path) - if not os.path.exists(full_config_path): - continue - - # extract the binary name and icon - binaries[app[0]] = find_exec(app[1]) - - # add all recently opened projects - projects.extend([[e[0], e[1], app[0]] for e in get_proj(full_config_path)]) - projects.sort(key=lambda s: s[0], reverse=True) - - # List all projects or the one corresponding to the query - if query.string: - projects = [p for p in projects if p[1].lower().find(query.string.lower()) != -1] - - items = [] - for p in projects: - last_update = p[0] - project_path = p[1] - project_dir = project_path.split("/")[-1] - product_name = p[2] - binary = binaries[product_name] - if not binary: - continue - - executable = binaries[p[2]][0] - icon = binaries[p[2]][1] - - items.append(Item( - id="-" + str(last_update), - icon=icon, - text=project_dir, - subtext=project_path, - completion=__trigger__ + project_dir, - actions=[ - ProcAction("Open in %s" % product_name, [executable, project_path]) - ] - )) - - return items diff --git a/.archive/jetbrains_projects/jetbrains.svg b/.archive/jetbrains_projects/jetbrains.svg deleted file mode 100644 index 6d3eb0f3..00000000 --- a/.archive/jetbrains_projects/jetbrains.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.archive/jetbrains_projects/LICENSE b/jetbrains_projects/LICENSE similarity index 100% rename from .archive/jetbrains_projects/LICENSE rename to jetbrains_projects/LICENSE diff --git a/jetbrains_projects/README.md b/jetbrains_projects/README.md new file mode 100644 index 00000000..08f9b880 --- /dev/null +++ b/jetbrains_projects/README.md @@ -0,0 +1,24 @@ +# Jetbrains-albert-plugin + +DISCLAIMER: This plugin has no affiliation with JetBrains s.r.o.. The icons are used under the terms specified [here](https://www.jetbrains.com/company/brand/#brand-guidelines). + +The plugin itself (the python file(s)) is licensed under the GPLv3 license. + +## How to use: + +Type `jb ` in the prompt, followed by your search term. Albert should show you a list of matching projects, scraped from your "recently edited" list of your Jetbrains IDEs. It tries to match the path of your project directory (not e.g. any files or contents). + +## Creating the project launcher: + +For this plugin to find the editors, you need to create a command line launcher for them. This is done by opening the IDE (for example PyCharm) and then going to `Tools -> Create Command-line Launcher...`. This will create a launcher (for example, `charm`) that this plugin will be able to find. + +## Authors: + +- Thomas Queste (@tomsquest) +- @mqus + +## Contributors: + +- @iyzana +- @Sharsie +- @dsager diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py new file mode 100644 index 00000000..4bb96e44 --- /dev/null +++ b/jetbrains_projects/__init__.py @@ -0,0 +1,188 @@ +from dataclasses import dataclass +from pathlib import Path +from typing import Union +from shutil import which +from sys import platform +from xml.etree import ElementTree +from albert import * + +md_iid = "0.5" +md_version = "1.0" +md_name = "Jetbrains projects" +md_description = "Open projects using JetBrains IDEs" +md_license = "GPL-3" +md_url = "https://github.com/tomsquest/albert-jetbrains-projects-plugin" +md_maintainers = ["@mqus", "@tomsquest"] + + +@dataclass +class Project: + name: str + path: str + last_opened: int + + +@dataclass +class Editor: + name: str + icon: Path + config_dir_prefix: str + binary: str + + def __init__(self, name: str, icon: Path, config_dir_prefix: str, binaries: list[str]): + self.name = name + self.icon = icon + self.config_dir_prefix = config_dir_prefix + self.binary = self._find_binary(binaries) + + def _find_binary(self, binaries: list[str]) -> Union[str, None]: + for binary in binaries: + if which(binary): + return binary + return None + + def list_projects(self) -> list[Project]: + config_dir = Path.home() / ".config" + if platform == "darwin": + config_dir = Path.home() / "Library" / "Preferences" + + dirs = list(config_dir.glob(f"{self.config_dir_prefix}*/")) + print(dirs) + if not dirs: + return [] + latest = sorted(dirs)[-1] + return self._parse_recent_projects(Path(latest) / "options" / "recentProjects.xml") + + def _parse_recent_projects(self, recent_projects_file: Path) -> list[Project]: + try: + root = ElementTree.parse(recent_projects_file).getroot() + entries = root.findall(".//component[@name='RecentProjectsManager']//entry[@key]") + + projects = [] + for entry in entries: + project_path = entry.attrib["key"].replace("$USER_HOME$", str(Path.home())) + + tag_opened = entry.find(".//option[@name='projectOpenTimestamp']") + last_opened = int( + tag_opened.attrib["value"] + if tag_opened is not None and "value" in tag_opened.attrib + else None + ) + + if project_path and last_opened: + projects.append( + Project(name=Path(project_path).name, path=project_path, last_opened=last_opened) + ) + return projects + except ElementTree.ParseError: + return [] + + +class Plugin(QueryHandler): + executables = [] + + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return "jb " + + def initialize(self): + plugin_dir = Path(__file__).parent + self.editors = [ + Editor( + name="Android Studio", + icon=plugin_dir / "androidstudio.svg", + config_dir_prefix="Google/AndroidStudio", + binaries=["studio", "androidstudio", "android-studio", "android-studio-canary", "jdk-android-studio", + "android-studio-system-jdk"]), + Editor( + name="CLion", + icon=plugin_dir / "clion.svg", + config_dir_prefix="JetBrains/CLion", + binaries=["clion", "clion-eap"]), + Editor( + name="DataGrip", + icon=plugin_dir / "datagrip.svg", + config_dir_prefix="JetBrains/DataGrip", + binaries=["datagrip", "datagrip-eap"]), + Editor( + name="DataSpell", + icon=plugin_dir / "dataspell.svg", + config_dir_prefix="JetBrains/DataSpell", + binaries=["dataspell", "dataspell-eap"]), + Editor( + name="GoLand", + icon=plugin_dir / "goland.svg", + config_dir_prefix="JetBrains/GoLand", + binaries=["goland", "goland-eap"]), + Editor( + name="IntelliJ IDEA", + icon=plugin_dir / "idea.svg", + config_dir_prefix="JetBrains/IntelliJIdea", + binaries=["idea", "idea-ultimate", "idea-ce-eap", "idea-ue-eap", "intellij-idea-ce", + "intellij-idea-ce-eap", "intellij-idea-ue-bundled-jre", "intellij-idea-ultimate-edition", + "intellij-idea-community-edition-jre", "intellij-idea-community-edition-no-jre"]), + Editor( + name="PhpStorm", + icon=plugin_dir / "phpstorm.svg", + config_dir_prefix="JetBrains/PhpStorm", + binaries=["phpstorm", "phpstorm-eap"]), + Editor( + name="PyCharm", + icon=plugin_dir / "pycharm.svg", + config_dir_prefix="JetBrains/PyCharm", + binaries=["charm", "pycharm", "pycharm-eap"]), + Editor( + name="Rider", + icon=plugin_dir / "rider.svg", + config_dir_prefix="JetBrains/Rider", + binaries=["rider", "rider-eap"]), + Editor( + name="RubyMine", + icon=plugin_dir / "rubymine.svg", + config_dir_prefix="JetBrains/RubyMine", + binaries=["rubymine", "rubymine-eap", "jetbrains-rubymine", "jetbrains-rubymine-eap"]), + Editor( + name="WebStorm", + icon=plugin_dir / "webstorm.svg", + config_dir_prefix="JetBrains/WebStorm", + binaries=["webstorm", "webstorm-eap"]), + ] + + def handleQuery(self, query: Query): + editor_project_pairs = [] + for editor in self.editors: + projects = editor.list_projects() + projects = [p for p in projects if Path(p.path).exists()] + projects = [p for p in projects if query.string.lower() in p.name.lower()] + editor_project_pairs.extend([(editor, p) for p in projects]) + + # sort by last opened + editor_project_pairs.sort(key=lambda pair: pair[1].last_opened, reverse=True) + + query.add([self._make_item(editor, project, query) for editor, project in editor_project_pairs]) + + def _make_item(self, editor: Editor, project: Project, query: Query) -> Item: + return Item( + id="%s-%s-%s" % (editor.binary, project.path, project.last_opened), + text=project.name, + subtext=project.path, + completion=query.trigger + project.name, + icon=[str(editor.icon)], + actions=[ + Action( + "Open", + "Open in %s" % editor.name, + lambda selected_project=project.path: runDetachedProcess( + [editor.binary, selected_project] + ), + ) + ], + ) diff --git a/jetbrains_projects/androidstudio.svg b/jetbrains_projects/androidstudio.svg new file mode 100644 index 00000000..98fc3c6e --- /dev/null +++ b/jetbrains_projects/androidstudio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/clion.svg b/jetbrains_projects/clion.svg new file mode 100644 index 00000000..001a2da6 --- /dev/null +++ b/jetbrains_projects/clion.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/datagrip.svg b/jetbrains_projects/datagrip.svg new file mode 100644 index 00000000..5931f912 --- /dev/null +++ b/jetbrains_projects/datagrip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/dataspell.svg b/jetbrains_projects/dataspell.svg new file mode 100644 index 00000000..44cf2e17 --- /dev/null +++ b/jetbrains_projects/dataspell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/goland.svg b/jetbrains_projects/goland.svg new file mode 100644 index 00000000..3640b1d8 --- /dev/null +++ b/jetbrains_projects/goland.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/idea.svg b/jetbrains_projects/idea.svg new file mode 100644 index 00000000..04d5d615 --- /dev/null +++ b/jetbrains_projects/idea.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/phpstorm.svg b/jetbrains_projects/phpstorm.svg new file mode 100644 index 00000000..7e3600d2 --- /dev/null +++ b/jetbrains_projects/phpstorm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/pycharm.svg b/jetbrains_projects/pycharm.svg new file mode 100644 index 00000000..82469f36 --- /dev/null +++ b/jetbrains_projects/pycharm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/rider.svg b/jetbrains_projects/rider.svg new file mode 100644 index 00000000..d1ab1530 --- /dev/null +++ b/jetbrains_projects/rider.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/rubymine.svg b/jetbrains_projects/rubymine.svg new file mode 100644 index 00000000..7a68d96f --- /dev/null +++ b/jetbrains_projects/rubymine.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jetbrains_projects/webstorm.svg b/jetbrains_projects/webstorm.svg new file mode 100644 index 00000000..c55a10e4 --- /dev/null +++ b/jetbrains_projects/webstorm.svg @@ -0,0 +1 @@ + \ No newline at end of file From 21ac6e0452756c30866702385bfde53e00407553 Mon Sep 17 00:00:00 2001 From: Ste Date: Tue, 31 Jan 2023 10:12:15 +0100 Subject: [PATCH 096/355] fix api_test delay option (#158) --- api_test/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api_test/__init__.py b/api_test/__init__.py index 1d031847..5e088e50 100644 --- a/api_test/__init__.py +++ b/api_test/__init__.py @@ -26,7 +26,7 @@ class Plugin(QueryHandler): def id(self): - return "someid"; + return "test"; def name(self): return "somename"; @@ -51,10 +51,10 @@ def handleQuery(self, query): if query.string.startswith("delay"): sleep(2) - return Item(id=__title__, + return query.add(Item(id=md_id, text="Delayed test item", subtext="Query string: %s" % query.string, - icons=os.path.dirname(__file__)+"/plugin.svg") + icon=[os.path.dirname(__file__)+"/plugin.svg"])) if query.string.startswith("throw"): raise ValueError('EXPLICITLY REQUESTED TEST EXCEPTION!') From 6b236b83aa5992a9bc06c120ab073d69de0c4092 Mon Sep 17 00:00:00 2001 From: Steven Xu Date: Tue, 31 Jan 2023 20:20:26 +1100 Subject: [PATCH 097/355] [yt] v1.3 create tmp dirs lazily --- youtube/__init__.py | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/youtube/__init__.py b/youtube/__init__.py index fa7ce820..598422f8 100644 --- a/youtube/__init__.py +++ b/youtube/__init__.py @@ -1,13 +1,10 @@ -# -*- coding: utf-8 -*- - import json import re import tempfile import time -from os import path from concurrent.futures import ThreadPoolExecutor from pathlib import Path -from typing import Any, Dict, List +from typing import Any from urllib.parse import urlencode from urllib.request import Request, urlopen @@ -15,15 +12,14 @@ md_iid = '0.5' -md_version = '1.2' +md_version = '1.3' md_name = 'YouTube' md_description = 'Query and open YouTube videos and channels' md_url = 'https://github.com/albertlauncher/python/' md_maintainers = '@stevenxxiu' -ICON = path.dirname(__file__) + '/youtube.svg' +ICON_PATH = str(Path(__file__).parent / 'youtube.svg') DATA_REGEX = re.compile(r'\b(var\s|window\[")ytInitialData("\])?\s*=\s*(.*)\s*;', re.MULTILINE) -TEMP_DIR = Path(tempfile.mkdtemp(prefix='albert_yt_')) HEADERS = { 'User-Agent': ( @@ -50,23 +46,23 @@ def urlopen_with_headers(url: str) -> Any: return urlopen(req) -def text_from(val: Dict[str, Any]) -> str: +def text_from(val: dict[str, Any]) -> str: text = val['simpleText'] if 'runs' not in val else ''.join(str(v['text']) for v in val['runs']) return text.strip() -def download_item_icon(item: Item) -> None: +def download_item_icon(item: Item, temp_dir: Path) -> None: url = item.icon[0] video_id = url.split('/')[-2] - path = TEMP_DIR / f'{video_id}.png' + path = temp_dir / f'{video_id}.png' with urlopen_with_headers(url) as response, path.open('wb') as sr: sr.write(response.read()) item.icon = [str(path)] def entry_to_item(type_, data) -> Item | None: - icon = ICON + icon = ICON_PATH match type_: case 'videoRenderer': subtext = ['Video'] @@ -100,8 +96,8 @@ def entry_to_item(type_, data) -> Item | None: ) -def results_to_items(results: dict) -> List[Item]: - items: List[Item] = [] +def results_to_items(results: dict) -> list[Item]: + items: list[Item] = [] for result in results: for type_, data in result.items(): try: @@ -116,6 +112,8 @@ def results_to_items(results: dict) -> List[Item]: class Plugin(QueryHandler): + temp_dir = None + def id(self) -> str: return __name__ @@ -125,6 +123,14 @@ def name(self) -> str: def description(self) -> str: return md_description + def initialize(self) -> None: + self.temp_dir = Path(tempfile.mkdtemp(prefix='albert_yt_')) + + def finalize(self) -> None: + for child in self.temp_dir.iterdir(): + child.unlink() + self.temp_dir.rmdir() + def defaultTrigger(self) -> str: return 'yt ' @@ -162,14 +168,13 @@ def handleQuery(self, query: Query) -> None: items = results_to_items(results) # Purge previous icons - for child in TEMP_DIR.iterdir(): - if child.is_file(): - child.unlink() + for child in self.temp_dir.iterdir(): + child.unlink() # Download icons with ThreadPoolExecutor(max_workers=10) as e: for item in items: - e.submit(download_item_icon, item) + e.submit(download_item_icon, item, self.temp_dir) if not query.isValid: return @@ -180,7 +185,7 @@ def handleQuery(self, query: Query) -> None: item = Item( id=f'{md_name}/show_more', text='Show more in browser', - icon=[ICON], + icon=[ICON_PATH], actions=[ Action( f'{md_name}/show_more', From 204674a62998b08a4afae893d1dd2991dfadc95b Mon Sep 17 00:00:00 2001 From: Ste Date: Tue, 31 Jan 2023 10:23:03 +0100 Subject: [PATCH 098/355] [vpn] 1.1 (iid: 0.5) --- .gitmodules | 6 ----- vpn/__init__.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 vpn/__init__.py diff --git a/.gitmodules b/.gitmodules index 3d4a210c..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +0,0 @@ -[submodule "xkcd"] - path = xkcd - url = https://github.com/bergercookie/xkcd-albert-plugin -[submodule "jetbrains_projects"] - path = jetbrains_projects - url = https://github.com/mqus/jetbrains-albert-plugin.git diff --git a/vpn/__init__.py b/vpn/__init__.py new file mode 100644 index 00000000..9c8c571e --- /dev/null +++ b/vpn/__init__.py @@ -0,0 +1,67 @@ +"""connect or disconnect from a NetworkManager VPN profiles (via nmcli)""" + +from albert import * +from collections import namedtuple +import subprocess + +md_iid = "0.5" +md_version = "1.1" +md_id = "vpn" +md_name = "VPN" +md_description = "Manage VPN connection" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python" +md_maintainers = ["@Bierchermuesli"] +md_credits = ["@janeklb"] +md_bin_dependencies = ["nmcli"] + + + +class Plugin(QueryHandler): + + iconPath = ['xdg:network-wired'] + + VPNConnection = namedtuple('VPNConnection', ['name', 'connected']) + + def id(self): + return md_id + + def name(self): + return md_name + + def description(self): + return md_description + + def getVPNConnections(self): + consStr = subprocess.check_output( + 'nmcli -t connection show', + shell=True, + encoding='UTF-8' + ) + for conStr in consStr.splitlines(): + con = conStr.split(':') + if con[2] == 'vpn': + yield self.VPNConnection(name=con[0], connected=con[3] != '') + + + def buildItem(self,con): + name = con.name + command = 'down' if con.connected else 'up' + text = f'Connect to {name}' if command == 'up' else f'Disconnect from {name}' + commandline = ['nmcli', 'connection', command, 'id', name] + return Item( + id=f'vpn-{command}-{name}', + text=name, + subtext=text, + icon=self.iconPath, + completion=name, + actions=[ Action("run",text=text, callable=lambda: runDetachedProcess(commandline)) ] + ) + + + def handleQuery(self,query): + if query.isValid: + connections = self.getVPNConnections() + if query.string: + connections = [ con for con in connections if query.string.lower() in con.name.lower() ] + query.add([ self.buildItem(con) for con in connections ]) From 6f734c7586c3889796846618fc9d8edb1a1ea386 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Tue, 31 Jan 2023 02:27:12 -0700 Subject: [PATCH 099/355] [tex_to_unicode] py interface 0.5 --- .archive/tex_to_unicode/__init__.py | 64 -------------------- tex_to_unicode/__init__.py | 87 ++++++++++++++++++++++++++++ tex_to_unicode/tex.png | Bin 0 -> 9268 bytes 3 files changed, 87 insertions(+), 64 deletions(-) delete mode 100644 .archive/tex_to_unicode/__init__.py create mode 100644 tex_to_unicode/__init__.py create mode 100644 tex_to_unicode/tex.png diff --git a/.archive/tex_to_unicode/__init__.py b/.archive/tex_to_unicode/__init__.py deleted file mode 100644 index 87daf423..00000000 --- a/.archive/tex_to_unicode/__init__.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- - -'''Convert TeX mathmode commands to unicode characters. - -Synopsis: ''' - -# Copyright (c) 2022 Manuel Schneider - -import re -import unicodedata - -from pylatexenc.latex2text import LatexNodes2Text - -from albert import * - -__title__ = 'TeX to unicode' -__version__ = '0.4.0' -__triggers__ = 'tex ' -__authors__ = 'Asger Hautop Drewsen' -__py_deps__ = ['pylatexenc'] - -COMBINING_LONG_SOLIDUS_OVERLAY = '\u0338' - - -def handleQuery(query): - if not query.isTriggered: - return - - item = Item() - stripped = query.string.strip() - - success = False - if stripped: - if not stripped.startswith('\\'): - stripped = '\\' + stripped - - # Remove double backslashes (newlines) - stripped = stripped.replace('\\\\', ' ') - - # pylatexenc doesn't support \not - stripped = stripped.replace('\\not', '@NOT@') - - # pylatexenc doesn't like backslashes at end of string - if not stripped.endswith('\\'): - n = LatexNodes2Text() - result = n.latex_to_text(stripped) - if result: - result = unicodedata.normalize('NFC', result) - result = re.sub(r'@NOT@\s*(\S)', '\\1' + COMBINING_LONG_SOLIDUS_OVERLAY, result) - result = result.replace('@NOT@', '') - result = unicodedata.normalize('NFC', result) - item.text = result - item.subtext = 'Result' - success = True - - if not success: - item.text = stripped - item.subtext = 'Type some TeX math' - success = False - - if success: - item.addAction(ClipAction('Copy result to clipboard', result)) - - return item diff --git a/tex_to_unicode/__init__.py b/tex_to_unicode/__init__.py new file mode 100644 index 00000000..e0e38eb5 --- /dev/null +++ b/tex_to_unicode/__init__.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2022 Manuel Schneider + +import os +import re +import unicodedata + +from albert import * +from pylatexenc.latex2text import LatexNodes2Text + +md_iid = "0.5" +md_version = "1.0" +md_name = "TeX to Unicode" +md_description = "Convert TeX mathmode commands to unicode characters" +md_license = "GPL-3.0" +md_url = "https://github.com/albertlauncher/python/" +md_lib_dependencies = "pylatexenc" +md_maintainers = "@DenverCoder1" + + +class Plugin(QueryHandler): + def id(self) -> str: + return md_id + + def name(self) -> str: + return md_name + + def description(self) -> str: + return md_description + + def defaultTrigger(self) -> str: + return "tex " + + def synopsis(self) -> str: + return "" + + def initialize(self) -> None: + self.COMBINING_LONG_SOLIDUS_OVERLAY = "\u0338" + self.icon = [os.path.dirname(__file__) + "/tex.png"] + + def _create_item(self, text: str, subtext: str, can_copy: bool) -> Item: + actions = [] + if can_copy: + actions.append( + Action( + "copy", + "Copy result to clipboard", + lambda t=text: setClipboardText(t), + ) + ) + return Item( + id=md_id, + icon=self.icon, + text=text, + subtext=subtext, + actions=actions, + ) + + def handleQuery(self, query: Query) -> None: + stripped = query.string.strip() + + if not stripped: + return + + if not stripped.startswith("\\"): + stripped = "\\" + stripped + + # Remove double backslashes (newlines) + stripped = stripped.replace("\\\\", " ") + + # pylatexenc doesn't support \not + stripped = stripped.replace("\\not", "@NOT@") + + n = LatexNodes2Text() + result = n.latex_to_text(stripped) + + if not result: + query.add(self._create_item(stripped, "Type some TeX math", False)) + return + + # success + result = unicodedata.normalize("NFC", result) + result = re.sub(r"@NOT@\s*(\S)", "\\1" + self.COMBINING_LONG_SOLIDUS_OVERLAY, result) + result = result.replace("@NOT@", "") + result = unicodedata.normalize("NFC", result) + query.add(self._create_item(result, "Result", True)) diff --git a/tex_to_unicode/tex.png b/tex_to_unicode/tex.png new file mode 100644 index 0000000000000000000000000000000000000000..49379b81f05387b988f68864e06b4dfe3d55f841 GIT binary patch literal 9268 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 W3tuFJQegG~0000 Date: Wed, 1 Feb 2023 14:59:00 +0100 Subject: [PATCH 100/355] [jetbrains:1.1] Polish. Fix Macos. --- jetbrains_projects/__init__.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 4bb96e44..21a019db 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -1,3 +1,12 @@ +""" +Supported IDEs: + +Android Studio, CLion, DataGrip, DataSpell, GoLand, IntelliJ IDEA, PhpStorm, PyCharm, Rider, RubyMine, WebStorm. + +Note: To open projects the command-line launcher is required. If your IDE has no \ +command-line launcher in $PATH, use `Tools` > `Create Command-line Launcher`. +""" + from dataclasses import dataclass from pathlib import Path from typing import Union @@ -7,9 +16,9 @@ from albert import * md_iid = "0.5" -md_version = "1.0" +md_version = "1.1" md_name = "Jetbrains projects" -md_description = "Open projects using JetBrains IDEs" +md_description = "Open your JetBrains projects" md_license = "GPL-3" md_url = "https://github.com/tomsquest/albert-jetbrains-projects-plugin" md_maintainers = ["@mqus", "@tomsquest"] @@ -44,10 +53,9 @@ def _find_binary(self, binaries: list[str]) -> Union[str, None]: def list_projects(self) -> list[Project]: config_dir = Path.home() / ".config" if platform == "darwin": - config_dir = Path.home() / "Library" / "Preferences" + config_dir = Path.home() / "Library" / "Application Support" dirs = list(config_dir.glob(f"{self.config_dir_prefix}*/")) - print(dirs) if not dirs: return [] latest = sorted(dirs)[-1] @@ -95,7 +103,7 @@ def defaultTrigger(self): def initialize(self): plugin_dir = Path(__file__).parent - self.editors = [ + editors = [ Editor( name="Android Studio", icon=plugin_dir / "androidstudio.svg", @@ -155,6 +163,7 @@ def initialize(self): config_dir_prefix="JetBrains/WebStorm", binaries=["webstorm", "webstorm-eap"]), ] + self.editors = [e for e in editors if e.binary is not None] def handleQuery(self, query: Query): editor_project_pairs = [] From 717abfb744ee6bb66236fda50815891b0100c27e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 1 Feb 2023 15:04:31 +0100 Subject: [PATCH 101/355] [vpn] Drop obsolete plugin. --- .archive/vpn/__init__.py | 56 ---------------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 .archive/vpn/__init__.py diff --git a/.archive/vpn/__init__.py b/.archive/vpn/__init__.py deleted file mode 100644 index c6039c31..00000000 --- a/.archive/vpn/__init__.py +++ /dev/null @@ -1,56 +0,0 @@ -"""VPN Extension - -Connect or disconnect from a network manager VPN profile""" - - -# Copyright (c) 2022 Manuel Schneider - -import subprocess -from collections import namedtuple -from albert import * - -__title__ = "VPN" -__version__ = "0.4.0" -__triggers__ = "vpn " -__authors__ = "janeklb" -__exec_deps__ = ['nmcli'] - -iconPath = iconLookup('network-wireless') or ":python_module" - -VPNConnection = namedtuple('VPNConnection', ['name', 'connected']) - - -def getVPNConnections(): - consStr = subprocess.check_output( - 'nmcli -t connection show', - shell=True, - encoding='UTF-8' - ) - for conStr in consStr.splitlines(): - con = conStr.split(':') - if con[2] == 'vpn': - yield VPNConnection(name=con[0], connected=con[3] != '') - - -def buildItem(con): - name = con.name - command = 'down' if con.connected else 'up' - text = f'Connect to {name}' if command == 'up' else f'Disconnect from {name}' - commandline = ['nmcli', 'connection', command, 'id', name] - return Item( - id=f'vpn-{command}-{name}', - text=name, - subtext=text, - icon=iconPath, - completion=name, - actions=[ ProcAction(text=text, commandline=commandline) ] - ) - - -def handleQuery(query): - if query.isValid and query.isTriggered: - connections = getVPNConnections() - if query.string: - connections = [ con for con in connections if query.string.lower() in con.name.lower() ] - return [ buildItem(con) for con in connections ] - return [] From 4dea5d4fac1aac0af1cb3ed36bf257f886fa6cb5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 14 Feb 2023 10:01:19 +0100 Subject: [PATCH 102/355] [pacman] Fix out of scope lambda vars --- pacman/__init__.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pacman/__init__.py b/pacman/__init__.py index 5535d4c0..a15efefe 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -9,12 +9,12 @@ from time import sleep import pathlib -from albert import Action, Item, QueryHandler, runTerminal +from albert import Action, Item, QueryHandler, runTerminal, openUrl md_iid = "0.5" md_version = "1.6" md_name = "PacMan" -md_description = "Search, install and remove packages" +md_description = "Search, install and remove packages" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/pacman" md_bin_dependencies = ["pacman", "expac"] @@ -71,7 +71,7 @@ def handleQuery(self, query): if not query.isValid: return - # Get data. Results are sorted so we can merge in O(n) + # Get data. Results are sorted, so we can merge in O(n) proc_s = subprocess.Popen(["expac", "-Ss", "%n\t%v\t%r\t%d\t%u\t%E", stripped], stdout=subprocess.PIPE, universal_newlines=True) proc_q = subprocess.Popen(["expac", "-Qs", "%n", stripped], stdout=subprocess.PIPE, universal_newlines=True) @@ -90,15 +90,15 @@ def handleQuery(self, query): actions = [] if pkg_installed: actions.extend([ - Action("rem", "Remove", lambda: runTerminal("sudo pacman -Rs %s" % pkg_name)), - Action("reinst", "Reinstall", lambda: runTerminal("sudo pacman -S %s" % pkg_name)) + Action("rem", "Remove", lambda n=pkg_name: runTerminal("sudo pacman -Rs %s" % n)), + Action("reinst", "Reinstall", lambda n=pkg_name: runTerminal("sudo pacman -S %s" % n)) ]) else: - actions.append(Action("inst", "Install", lambda: runTerminal("sudo pacman -S %s" % pkg_name))) + actions.append(Action("inst", "Install", lambda n=pkg_name: runTerminal("sudo pacman -S %s" % n))) actions.append(Action("pkg_url", "Show on packages.archlinux.org", - lambda: openUrl(f"{pkg_repo}/x86_64/{pkg_name}/"))) + lambda r=pkg_repo, n=pkg_name: openUrl(f"{r}/x86_64/{n}/"))) if pkg_purl: - actions.append(Action("proj_url", "Show project website", lambda: openUrl(pkg_purl))) + actions.append(Action("proj_url", "Show project website", lambda u=pkg_purl: openUrl(u))) item = Item( id="%s_%s_%s" % (md_id, pkg_repo, pkg_name), From 7dc1514bc8d0ca9bb6e934c0aeb926cdab222554 Mon Sep 17 00:00:00 2001 From: er-azh <80633916+er-azh@users.noreply.github.com> Date: Mon, 13 Mar 2023 14:29:26 +0000 Subject: [PATCH 103/355] [vpn] Add wireguard to connection types --- vpn/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpn/__init__.py b/vpn/__init__.py index 9c8c571e..aae011cd 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -40,7 +40,7 @@ def getVPNConnections(self): ) for conStr in consStr.splitlines(): con = conStr.split(':') - if con[2] == 'vpn': + if con[2] in ['vpn', 'wireguard']: yield self.VPNConnection(name=con[0], connected=con[3] != '') From 206db4ef97d966e6586618f1d302f12dd73aa915 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 13 Mar 2023 15:33:18 +0100 Subject: [PATCH 104/355] [vpn] polish --- vpn/__init__.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/vpn/__init__.py b/vpn/__init__.py index aae011cd..44af6857 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -1,14 +1,12 @@ -"""connect or disconnect from a NetworkManager VPN profiles (via nmcli)""" - from albert import * from collections import namedtuple import subprocess md_iid = "0.5" -md_version = "1.1" +md_version = "1.2" md_id = "vpn" md_name = "VPN" -md_description = "Manage VPN connection" +md_description = "Manage NetworkManager VPN connections" md_license = "MIT" md_url = "https://github.com/albertlauncher/python" md_maintainers = ["@Bierchermuesli"] @@ -16,7 +14,6 @@ md_bin_dependencies = ["nmcli"] - class Plugin(QueryHandler): iconPath = ['xdg:network-wired'] From c813c55df62e0274fc6e337509ae3e4dc20636e3 Mon Sep 17 00:00:00 2001 From: Vitor Carvalho Date: Fri, 24 Mar 2023 13:25:18 -0300 Subject: [PATCH 105/355] [bitwarden] 1.1 (iid: 0.5) --- bitwarden/__init__.py | 145 ++++++++++++++++++++++++++++++++++++++++++ bitwarden/bw.svg | 3 + 2 files changed, 148 insertions(+) create mode 100644 bitwarden/__init__.py create mode 100644 bitwarden/bw.svg diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py new file mode 100644 index 00000000..9d2d6caf --- /dev/null +++ b/bitwarden/__init__.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2022 Manuel Schneider + +import fnmatch +import os +from subprocess import run, CalledProcessError + +from albert import * + +md_iid = "0.5" +md_version = "0.5" +md_name = "Bitwarden" +md_description = "'rbw' wrapper extensions" +md_trigger = "bw " +md_license = "copyleft" +md_url = "" +md_maintainers = "Vitor Carvalho" +md_credits = "Asger Hautop Drewsen" +md_bin_dependencies = ["rbw"] + +class Plugin(QueryHandler): + def id(self): + return md_id + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return md_trigger + + def initialize(self): + self.icon = [os.path.dirname(__file__) + "/bw.svg"] + + def _get_passwords(self): + field_names = ["id", "name", "user", "folder"] + p = run( + ["rbw", "list", "--fields", ",".join(field_names)], + capture_output=True, + encoding="utf-8", + check=True, + ) + passwords = [] + for l in p.stdout.splitlines(): + fields = l.split("\t") + d = dict(zip(field_names, fields)) + if d["folder"]: + d["path"] = d["folder"] + "/" + d["name"] + else: + d["path"] = d["name"] + passwords.append(d) + + return passwords + + def handleQuery(self, query): + if query.string.strip().lower() == "unlock": + query.add( + Item( + id="unlock", + text="Unlock Bitwarden Vault", + icon=self.icon, + actions=[ + Action( + id="unlock", + text="Unlocking Bitwarden Vault", + callable=lambda: runTerminal( + script="rbw stop-agent && rbw unlock", + close_on_exit=True + ) + ) + ] + ) + ) + passwords = self._get_passwords() + filtered_passwords = [] + search_fields = ["path", "user"] + words = query.string.strip().lower().split() + + for p in passwords: + all_matches = True + for w in words: + for k in search_fields: + if w in p[k].lower(): + break + else: + all_matches = False + break + + if all_matches: + filtered_passwords.append(p) + + results = [] + for p in filtered_passwords: + pw = run( + ["rbw", "get", p["id"]], + capture_output=True, + encoding="utf-8", + check=True + ) + try: + code = run( + ["rbw", "code", p["id"]], + capture_output=True, + encoding="utf-8", + check=True + ) + except CalledProcessError as err: + code = run (["echo"], capture_output=True,encoding="utf-8", check=True) + results.append( + query.add( + Item( + id=p["id"], + text=p["path"], + subtext=p["user"], + icon=self.icon, + actions=[ + Action( + id="copy", + text="Copy password to clipboard", + callable=lambda password=pw.stdout.strip(): setClipboardText( + text=password) + ), + Action( + id="copy-auth", + text="Copy auth code to clipboard", + callable=lambda code=code.stdout.strip(): setClipboardText( + text=code) + ), + Action( + id="edit", + text="Edit entry in terminal", + callable=lambda pid=p['id']: runTerminal( + script=f"rbw edit {pid}", + workdir="~", + close_on_exit=False + ) + ) + ] + ) + ) + ) + return results diff --git a/bitwarden/bw.svg b/bitwarden/bw.svg new file mode 100644 index 00000000..319329ac --- /dev/null +++ b/bitwarden/bw.svg @@ -0,0 +1,3 @@ + + + From bfdf1ac60309404f770a0cd38fbc368857090af7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 24 Mar 2023 17:48:12 +0100 Subject: [PATCH 106/355] [bw] Some polishing --- .archive/bitwarden/__init__.py | 95 ---------------------------------- bitwarden/__init__.py | 80 +++++++++++++--------------- bitwarden/bw.svg | 5 +- 3 files changed, 39 insertions(+), 141 deletions(-) delete mode 100644 .archive/bitwarden/__init__.py diff --git a/.archive/bitwarden/__init__.py b/.archive/bitwarden/__init__.py deleted file mode 100644 index 8b87a400..00000000 --- a/.archive/bitwarden/__init__.py +++ /dev/null @@ -1,95 +0,0 @@ -# -*- coding: utf-8 -*- - -"""'rbw' wrapper extension.""" - -# Copyright (c) 2022 Manuel Schneider - -import fnmatch -import os -from subprocess import run - -from albert import * - -__title__ = "Bitwarden" -__version__ = "0.4.0" -__triggers__ = "bw " -__authors__ = "Asger Hautop Drewsen" -__exec_deps__ = ["rbw", "xclip"] - -ICON_PATH = iconLookup("dialog-password") - - -def handleQuery(query): - if not query.isTriggered: - return - - passwords = get_passwords() - filtered_passwords = [] - search_fields = ["path", "user"] - words = query.string.strip().lower().split() - for p in passwords: - all_matches = True - for w in words: - for k in search_fields: - if w in p[k].lower(): - break - else: - all_matches = False - break - - if all_matches: - filtered_passwords.append(p) - - results = [] - for p in filtered_passwords: - results.append( - Item( - id=p["id"], - icon=ICON_PATH, - text=p["path"], - subtext=p["user"], - completion=f"rbw {p['path']}", - actions=[ - ProcAction( - "Copy", - [ - "sh", - "-c", - f"rbw get {p['id']} | tr -d '\\n' | xclip -selection clipboard -in", - ], - ), - ProcAction( - "Copy auth code", - [ - "sh", - "-c", - f"rbw code {p['id']} | tr -d '\\n' | xclip -selection clipboard -in", - ], - ), - TermAction("Edit", ["rbw", "edit", p["id"]]), - ], - ), - ) - - return results - - -def get_passwords(): - field_names = ["id", "name", "user", "folder"] - p = run( - ["rbw", "list", "--fields", *field_names], - capture_output=True, - encoding="utf-8", - check=True, - ) - passwords = [] - for l in p.stdout.splitlines(): - fields = l.split("\t") - d = dict(zip(field_names, fields)) - if d["folder"]: - d["path"] = d["folder"] + "/" + d["name"] - else: - d["path"] = d["name"] - passwords.append(d) - - return passwords diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 9d2d6caf..3f482cfa 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -1,22 +1,18 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2022 Manuel Schneider - -import fnmatch import os from subprocess import run, CalledProcessError from albert import * md_iid = "0.5" -md_version = "0.5" +md_version = "1.1" md_name = "Bitwarden" -md_description = "'rbw' wrapper extensions" -md_trigger = "bw " -md_license = "copyleft" -md_url = "" -md_maintainers = "Vitor Carvalho" -md_credits = "Asger Hautop Drewsen" +md_description = "'rbw' wrapper extension" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python" +md_maintainers = "@ovitor" +md_credits = "Original author: @tylio" md_bin_dependencies = ["rbw"] class Plugin(QueryHandler): @@ -30,7 +26,7 @@ def description(self): return md_description def defaultTrigger(self): - return md_trigger + return "bw " def initialize(self): self.icon = [os.path.dirname(__file__) + "/bw.svg"] @@ -92,7 +88,6 @@ def handleQuery(self, query): if all_matches: filtered_passwords.append(p) - results = [] for p in filtered_passwords: pw = run( ["rbw", "get", p["id"]], @@ -109,37 +104,34 @@ def handleQuery(self, query): ) except CalledProcessError as err: code = run (["echo"], capture_output=True,encoding="utf-8", check=True) - results.append( - query.add( - Item( - id=p["id"], - text=p["path"], - subtext=p["user"], - icon=self.icon, - actions=[ - Action( - id="copy", - text="Copy password to clipboard", - callable=lambda password=pw.stdout.strip(): setClipboardText( - text=password) - ), - Action( - id="copy-auth", - text="Copy auth code to clipboard", - callable=lambda code=code.stdout.strip(): setClipboardText( - text=code) - ), - Action( - id="edit", - text="Edit entry in terminal", - callable=lambda pid=p['id']: runTerminal( - script=f"rbw edit {pid}", - workdir="~", - close_on_exit=False - ) + query.add( + Item( + id=p["id"], + text=p["path"], + subtext=p["user"], + icon=self.icon, + actions=[ + Action( + id="copy", + text="Copy password to clipboard", + callable=lambda password=pw.stdout.strip(): setClipboardText( + text=password) + ), + Action( + id="copy-auth", + text="Copy auth code to clipboard", + callable=lambda code=code.stdout.strip(): setClipboardText( + text=code) + ), + Action( + id="edit", + text="Edit entry in terminal", + callable=lambda pid=p['id']: runTerminal( + script=f"rbw edit {pid}", + workdir="~", + close_on_exit=False ) - ] - ) + ) + ] ) - ) - return results + ) \ No newline at end of file diff --git a/bitwarden/bw.svg b/bitwarden/bw.svg index 319329ac..b487d569 100644 --- a/bitwarden/bw.svg +++ b/bitwarden/bw.svg @@ -1,3 +1,4 @@ - - + + + From e5479ab6dde1c7520459a2c178d220db5b6e5be0 Mon Sep 17 00:00:00 2001 From: Asger Hautop Drewsen Date: Thu, 30 Mar 2023 09:52:49 +0200 Subject: [PATCH 107/355] [emoji] iid:0.5 v1.0 --- emoji/__init__.py | 149 ++ emoji/aliases.json | 1 + emoji/emoji-test.txt | 5024 ++++++++++++++++++++++++++++++++++++++++++ emoji/scrape_aliases | 68 + 4 files changed, 5242 insertions(+) create mode 100644 emoji/__init__.py create mode 100644 emoji/aliases.json create mode 100644 emoji/emoji-test.txt create mode 100755 emoji/scrape_aliases diff --git a/emoji/__init__.py b/emoji/__init__.py new file mode 100644 index 00000000..e8df5a88 --- /dev/null +++ b/emoji/__init__.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- + +"""Find emojis by name. + +Synopsis: """ + +import json +import re +import subprocess +from concurrent.futures import ThreadPoolExecutor +from itertools import islice +from pathlib import Path + +from albert import Action, Item, QueryHandler, cacheLocation, setClipboardText + +md_iid = "0.5" +md_version = "1.0" +md_name = "Emoji Picker" +md_description = "Find emojis by name" +md_license = "GPL-3.0" +md_url = "https://github.com/albertlauncher/python/tree/master/emoji" +md_maintainers = "@tyilo" +md_bin_dependencies = ["convert"] + + +EXTENSION_DIR = Path(__file__).parent +ALIASES_PATH = EXTENSION_DIR / "aliases.json" +EMOJI_PATH = EXTENSION_DIR / "emoji-test.txt" +ICON_DIR = Path(cacheLocation()) / "emojis" + + +ICON_DIR.mkdir(exist_ok=True, parents=True) + + +def icon_path(emoji): + return ICON_DIR / f"{emoji}.png" + + +def convert_to_png(emoji, output_path): + subprocess.run( + [ + "convert", + "-pointsize", + "64", + "-background", + "transparent", + f"pango:{emoji}", + output_path, + ] + ) + + +def schedule_create_missing_icons(emojis): + executor = ThreadPoolExecutor() + for emoji in emojis: + path = icon_path(emoji["emoji"]) + if not path.exists(): + executor.submit(convert_to_png, emoji["emoji"], path) + + return executor + + +class Plugin(QueryHandler): + def id(self): + return __name__ + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return ": " + + def synopsis(self): + return "" + + def initialize(self): + line_re = re.compile( + r""" + ^ + (?P .*\S) + \s*;\s* + (?P \S+) + \s*\#\s* + (?P \S+) + \s* + (?P E\d+.\d+) + \s* + (?P [^:]+) + (?: : \s* (?P .+))? + \n + $ + """, + re.VERBOSE, + ) + + with ALIASES_PATH.open("r") as f: + aliases = json.load(f) + + self.emojis = [] + with EMOJI_PATH.open("r") as f: + for line in f: + if m := line_re.match(line): + e = m.groupdict() + if e["status"] == "fully-qualified": + search_tokens = [e["name"]] + if e["modifiers"]: + search_tokens.append(e["modifiers"]) + e["aliases"] = [a.lower() for a in aliases.get(e["name"], [])] + search_tokens += e["aliases"] + e["search_tokens"] = search_tokens + self.emojis.append(e) + + self.icon_executor = schedule_create_missing_icons(self.emojis) + + def finalize(self): + self.icon_executor.shutdown(wait=True, cancel_futures=True) + + def matched_emojis(self, query_tokens): + for emoji in self.emojis: + for w in query_tokens: + if w not in " ".join(emoji["search_tokens"]): + break + + yield emoji + + def handleQuery(self, query): + query_tokens = query.string.strip().lower().split() + if not query_tokens: + return + + for emoji in islice(self.matched_emojis(query_tokens), 100): + query.add( + Item( + id=f"emoji_{emoji['emoji']}", + text=f"{emoji['emoji']} {emoji['name']}", + subtext=emoji["modifiers"] or "", + icon=[str(icon_path(emoji["emoji"]))], + actions=[ + Action( + "copy", + "Copy to clipboard", + lambda r=emoji["emoji"]: setClipboardText(r), + ), + ], + ) + ) diff --git a/emoji/aliases.json b/emoji/aliases.json new file mode 100644 index 00000000..55b0874d --- /dev/null +++ b/emoji/aliases.json @@ -0,0 +1 @@ +{"person walking": ["Walker", "Walking"], "grinning face with sweat": ["Exercise", "Happy Sweat"], "slightly smiling face": ["Slightly Happy", "This Is Fine"], "face with tears of joy": ["Laughing", "Laughing Crying", "Laughing Tears", "LOL"], "upside-down face": ["Sarcasm", "Silly"], "grinning squinting face": ["><", "Big Grin", "Closed-Eyes Smile", "Laughing", "XD"], "smiling face with hearts": ["In Love Face"], "winking face": ["Wink", "Wink Face", "Winky Face"], "rolling on the floor laughing": ["ROFL"], "smiling face with heart-eyes": ["Heart Eyes", "Heart Face"], "face blowing a kiss": ["Blow A Kiss", "Blowing Kiss", "Kissing"], "kissing face": [":-*", "Duck Face", "Kissy Face", "Whistling"], "star-struck": ["Excited", "Star Eyes", "Starry Eyed", "Wow Face"], "smiling face with halo": ["Angel", "Halo"], "kissing face with closed eyes": ["Kiss Face", "Kissy Face"], "smiling face with smiling eyes": ["^^", "Happy Face", "Smile", "Smiley Face"], "face with tongue": ["Cheeky", "Tongue Face", "Tongue-Out"], "face savoring food": ["Goofy", "Hungry"], "smiling face": ["Happy Face", "Smiley Face", "Smiling"], "winking face with tongue": ["Crazy", "Crazy Face"], "kissing face with smiling eyes": ["Kiss Face", "Kissy", "Whistle", "Whistling"], "shushing face": ["Hush", "Quiet", "Shh"], "zany face": ["Crazy Eyes", "Excited", "Wild"], "squinting face with tongue": ["Tongue Out"], "thinking face": ["Chin Thumb", "Thinker", "Throwing Shade"], "zipper-mouth face": ["Lips Sealed", "Sealed Lips", "Zip It"], "face with raised eyebrow": ["Colbert", "The Rock"], "expressionless face": ["Face With Straight Mouth", "Straight Face"], "neutral face": ["Face With Straight Mouth", "Straight Faced"], "smirking face": ["Flirting", "Sexual Face", "Smug Face", "Suggestive Smile"], "face with rolling eyes": ["Eye Roll"], "grimacing face": ["Awkward", "Eek", "Foot In Mouth", "Nervous", "Snapchat Mutual #1 Best Friend"], "face in clouds": ["Brain Fog", "Forgetful", "Haze"], "face without mouth": ["Blank Face", "Mouthless", "Silence", "Silent"], "pensive face": ["Pensive", "Sad", "Sadface", "Sorrowful"], "money-mouth face": ["Dollar Sign Eyes", "Money Face", "Rich"], "face exhaling": ["Sigh"], "lying face": ["Liar", "Long Nose", "Pinocchio"], "sleepy face": ["Side-Tear", "Snot Bubble"], "sleeping face": ["Sleep Face", "Snoring", "Zzz Face"], "face with medical mask": ["Coronavirus", "COVID-19", "Mask Face", "Surgical Mask"], "face with thermometer": ["Ill", "Sick"], "relieved face": ["Content", "Pleased"], "drooling face": ["Drool"], "face with head-bandage": ["Bandaged Head", "Clumsy", "Injured"], "nauseated face": ["Disgust", "Green Face", "Vomit"], "sneezing face": ["Gesundheit"], "woozy face": ["Drunk Face"], "unamused face": ["Dissatisfied", "Meh", "Side-Eye", "Unimpressed"], "exploding head": ["Mind Blown"], "cowboy hat face": ["Cowboy"], "smiling face with sunglasses": ["Cool", "Mutual Best Friends (Snapchat)", "Sunglasses"], "nerd face": ["Nerdy"], "face with spiral eyes": ["Dizzy Face"], "confused face": ["Nonplussed", "Puzzled", ":S"], "face vomiting": ["Spew", "Throwing Up", "Vomit"], "frowning face": ["Megafrown"], "slightly frowning face": ["Slightly Sad"], "face with open mouth": ["Open Mouth", "Surprised"], "astonished face": ["Drunk Face", "Gasping Face", "Shocked Face"], "pleading face": ["Begging", "Glossy Eyes", "Simp"], "hushed face": ["Surprise", "Surprised Face"], "frowning face with open mouth": ["Yawning"], "worried face": ["Sad", "Sadface"], "sad but relieved face": ["Eyebrow Sweat"], "loudly crying face": ["Bawling", "Crying", "Sad Tears", "Sobbing"], "crying face": ["Crying", "Tear"], "flushed face": [":$", "Blushing Face", "Embarrassed", "Shame"], "person running": ["Jogging", "Run"], "fearful face": ["Scared", "Surprised"], "anguished face": ["Pained Face"], "anxious face with sweat": ["Blue Face", "Concerned Face", "Nervous Face"], "face screaming in fear": ["Home Alone", "Scream", "Screaming Face"], "man juggling": ["Male Juggler"], "synagogue": ["Jewish", "Synagog", "Temple"], "card index": ["Index Card", "Rolodex", "System Card"], "shinto shrine": ["Kami-no-michi"], "confounded face": ["Quivering Mouth", "Scrunched Face"], "raising hands": ["Arms In The Air", "Banzai", "Festivus Miracle", "Hallelujah", "Praise Hands", "Two Hands"], "chart decreasing": ["Down Pointing Graph", "Negative Chart"], "chart increasing": ["Positive Chart", "Up Pointing Graph"], "fountain": ["Park", "Water Feature", "Water Fountain"], "woman juggling": ["Female Juggler"], "bar chart": ["Bar Graph"], "kaaba": ["Mecca"], "man cook": ["Male Chef"], "tent": ["Camping Tent"], "round pushpin": ["Dropped Pin", "Map Pin", "Pin", "Red Pin"], "foggy": ["Fog", "Foggy City", "Fog Bridge"], "pushpin": ["Thumb Tack"], "night with stars": ["City At Night", "Starry Night"], "sunrise over mountains": ["Morning", "Sunrise"], "woman cook": ["Female Chef"], "paperclip": ["Clippy"], "cityscape at dusk": ["Dusk City", "Orange Sky City"], "sunrise": ["Sunset"], "person in lotus position": ["Meditation", "Yoga"], "triangular ruler": ["Triangle Ruler"], "sunset": ["City Sunset"], "scissors": ["Cutting"], "hot springs": ["Onsen", "Steam"], "carousel horse": ["Carnival", "Fairground", "Merry Go Round"], "file cabinet": ["Filing Cabinet"], "open hands": ["Hug", "Jazz Hands"], "locked": ["Closed Lock", "Padlock"], "bridge at night": ["Bridge", "Golden Gate Bridge"], "roller coaster": ["Rollercoaster", "Theme Park"], "unlocked": ["Open Padlock", "Unlock"], "locked with key": ["Lock And Key"], "palms up together": ["Dua"], "wastebasket": ["Garbage Can", "Rubbish Bin", "Trash Can", "Wastepaper Basket"], "ferris wheel": ["Big Wheel", "Fairground", "Observation Wheel"], "barber pole": ["Barber Shop", "Barber's Stripes", "Hairdresser"], "circus tent": ["Big Top", "Circus"], "locked with pen": ["Lock And Pen", "Lock With Fountain Pen"], "pick": ["Pickaxe"], "key": ["Gold Key"], "train": ["Diesel Train", "Electric Train", "Passenger Train", "Regular Train"], "locomotive": ["Railway Locomotive", "Steam Train"], "hammer": ["Claw Hammer", "Handyman", "Tool"], "railway car": ["Railcar", "Railroad Car", "Railway Carriage", "Railway Wagon"], "handshake": ["Shaking Hands"], "metro": ["Subway", "Tube", "Underground"], "dagger": ["Knife Weapon"], "station": ["Train Platform", "Train Station"], "bullet train": ["Bullet Train", "Shinkansen"], "mountain railway": ["Funicular", "Train And Mountain"], "person taking bath": ["Bathing", "Hot Bath"], "bow and arrow": ["Archery"], "oncoming bus": ["Front Of Bus"], "bus": ["School Bus"], "wrench": ["Spanner"], "nut and bolt": ["Bolt", "Screw"], "trolleybus": ["Electric Bus", "Trolley Bus"], "minibus": ["Minivan", "People-Mover"], "fire engine": ["Fire Department", "Fire Truck"], "taxi": ["New York Taxi", "Side Of Taxi", "Taxicab"], "balance scale": ["Scales of Justice"], "police car": ["Cop Car", "Side Of Police Car"], "oncoming police car": ["\ud83d\ude93 Front Of Police Car", "\ud83d\ude93 Cop Car"], "link": ["Chain", "Hyperlink", "Linked Chain"], "clamp": ["Clamp", "Table Vice", "WinZip"], "people holding hands": ["Gender Inclusive Couple", "Gender Neutral Couple", "Gender Nonconforming Couple"], "oncoming taxi": ["Front Of Taxi", "Taxicab"], "automobile": ["Car", "Red Car", "Side Of Car"], "oncoming automobile": ["Front Of Car"], "sport utility vehicle": ["Campervan", "Motorhome", "RV"], "articulated lorry": ["Green Truck", "Truck"], "tractor": ["Farm", "Farming"], "racing car": ["F1", "Formula One"], "microscope": ["Magnify", "Science"], "motorcycle": ["Motorbike", "Motorcycle"], "telescope": ["Stargazing"], "syringe": ["Vaccination"], "auto rickshaw": ["Tuk Tuk"], "pill": ["Capsule", "Drugs", "Tablet"], "motor scooter": ["Motor Bike", "Motor Cycle", "Vespa"], "drop of blood": ["Blood Donation", "Menstruation", "Period"], "bicycle": ["Bike", "Push Bike"], "man office worker": ["Businessman", "CEO"], "roller skate": ["Inline Skate", "Roller Derby"], "adhesive bandage": ["Band Aid", "Plaster"], "door": ["Doorway", "Front Door"], "fuel pump": ["Gas Pump", "Petrol Pump"], "bed": ["Bedroom"], "police car light": ["Emergency Light", "Flashing Light", "Police Siren", "Siren"], "motorway": ["Highway", "Interstate", "Road"], "couch and lamp": ["Lounge", "Settee", "Sofa"], "horizontal traffic light": ["Traffic Light"], "folded hands": ["Namaste", "Please", "Prayer", "Thank You"], "toilet": ["Bathroom", "Loo", "Restroom"], "stop sign": ["Stop Sign"], "woman office worker": ["Businesswoman", "CEO"], "vertical traffic light": ["Traffic Light"], "bathtub": ["Bubble Bath"], "ring buoy": ["Life Preserver", "Life Ring"], "sailboat": ["Dinghy", "Yacht"], "anchor": ["Admiralty Pattern Anchor", "Fisherman"], "construction": ["Black And Yellow Striped Sign", "Roadwork", "Roadwork Sign"], "shower": ["Shower Head"], "speedboat": ["Motorboat", "Powerboat"], "broom": ["Brush", "Sweep"], "nail polish": ["Fingers", "Manicure", "Nonchalant"], "ship": ["Cruise", "Cruise Ship"], "airplane": ["Aeroplane", "Plane"], "roll of paper": ["Toilet Paper"], "airplane arrival": ["Aeroplane Landing", "Plane Landing"], "selfie": ["Phone Camera", "Selfie Hand"], "small airplane": ["Small Aeroplane", "Small Plane"], "seat": ["Aeroplane Seat", "Airplane Seat", "Bus Seat", "Train Seat"], "cigarette": ["Cigarette", "Smoke"], "women holding hands": ["Lesbian Couple"], "airplane departure": ["Aeroplane Taking Off", "Plane Taking Off"], "shopping cart": ["Shopping Cart"], "coffin": ["Casket", "Funeral"], "aerial tramway": ["Cable Car", "Gondola", "Ropeway"], "funeral urn": ["Vase"], "nazar amulet": ["Evil Eye Talisman", "Nazar Boncu\u011fu"], "flexed biceps": ["Feats of Strength", "Flexing Arm Muscles", "Muscle", "Strong"], "rocket": ["Rocket Ship", "Space Shuttle"], "placard": ["Lawn Sign", "Protest Sign", "Sign", "Sign on Post"], "flying saucer": ["UFO"], "man technologist": ["Male Blogger"], "moai": ["Easter Island", "Human Rock Carving", "Moai", "Moyai Statue"], "luggage": ["Suitcase"], "alarm clock": ["Alarm", "Clock"], "woman technologist": ["Female Blogger"], "litter in bin sign": ["Person With Trash", "Put Litter In Trash"], "potable water": ["Thirst", "Thirsty", "Water Tap"], "watch": ["Apple Watch", "Timepiece", "Wrist Watch"], "restroom": ["Bathroom Sign", "Toilet Sign"], "wheelchair symbol": ["Accessible Bathroom"], "baby symbol": ["Baby Change Station", "Baby Change Symbol", "Nursery"], "water closet": ["Toilet WC", "WC"], "passport control": ["Border Control"], "warning": ["Alert Symbol"], "children crossing": ["Kids Crossing", "School Crossing"], "man singer": ["Aladdin Sane", "Bowie"], "ear": ["Ears", "Hearing", "Listening"], "prohibited": ["Banned", "Circle Backslash", "No", "Red Circle Crossed", "Restricted"], "left luggage": ["Bag With Key", "Locked Suitcase"], "non-potable water": ["No Drinking Water", "No Water"], "no mobile phones": ["No Cell Phones", "No Phones", "No Smartphones"], "no bicycles": ["No Bikes Sign"], "radioactive": ["International Radiation Symbol", "Nuclear"], "no one under eighteen": ["NSFW"], "no pedestrians": ["No People", "No Walking"], "nose": ["Smelling", "Sniffing", "Stinky"], "up arrow": ["Arrow Pointing Up", "Up Arrow"], "left arrow": ["Arrow Pointing Left", "Left Arrow"], "down arrow": ["Arrow Pointing Down", "Down Arrow"], "up-right arrow": ["Diagonal Up-Right Arrow"], "right arrow": ["Arrow Pointing Right", "Right Arrow"], "up-left arrow": ["Diagonal Up-Left Arrow"], "down-right arrow": ["Diagonal Down-Right Arrow"], "down-left arrow": ["Diagonal Down-Left Arrow"], "left-right arrow": ["Horizontal Arrows", "Sideways Arrows"], "right arrow curving left": ["Email Reply", "Left Curved Arrow"], "up-down arrow": ["Vertical Arrows"], "right arrow curving down": ["Curved Down Arrow"], "woman and man holding hands": ["Heterosexual Couple", "Straight Couple"], "eyes": ["Eyeballs", "Shifty Eyes", "Wide Eyes"], "new moon": ["Dark Moon", "Shadow Moon", "Solar Eclipse"], "tongue": ["Tongue Out"], "eye": ["Single Eye"], "left arrow curving right": ["Email Forward", "Right Curved Arrow"], "baby": ["Child", "Toddler"], "mouth": ["Kissing Lips", "Lips"], "counterclockwise arrows button": ["Refresh", "Rotate", "Switch"], "place of worship": ["Religious Building"], "new moon face": ["Creepy Moon", "Dark Moon Face", "Molester Moon"], "bread": ["Loaf Of Bread"], "pancakes": ["Cr\u00eapes", "Hotcakes"], "baguette bread": ["French Bread"], "cut of meat": ["Meat", "Steak"], "cheese wedge": ["Cheese"], "poultry leg": ["Drumstick", "Turkey Leg"], "chestnut": ["Acorn", "Nut"], "hamburger": ["Burger", "Cheeseburger"], "pizza": ["Pepperoni Pizza", "Pizza"], "meat on bone": ["Barbecue", "BBQ", "Manga Meat"], "flatbread": ["Arepa"], "bacon": ["Rashers"], "tamale": ["Tamal"], "french fries": ["Chips", "Fries", "McDonald's Fries"], "burrito": ["Wrap"], "stuffed flatbread": ["Doner Kebab", "Gyro", "Shawarma"], "shallow pan of food": ["Paella"], "bowl with spoon": ["Cereal Bowl"], "cooking": ["Breakfast", "Fried Egg", "Frying Pan"], "popcorn": ["Popping Corn"], "pot of food": ["Bowl Of Food", "Soup", "Stew"], "canned food": ["Can of Food", "Tin Can", "Tinned Food"], "rice cracker": ["Cracker"], "rice ball": ["Onigiri"], "steaming bowl": ["Noodles", "Noodles With Chopsticks", "Ramen"], "hot dog": ["Hotdog", "Sausage"], "bento box": ["Lunch Box"], "curry rice": ["Curry", "Indian Food"], "sushi": ["Sashimi", "Seafood"], "fried shrimp": ["Fried Prawn", "Shrimp Tempura"], "oden": ["Kebab", "Skewer"], "fish cake with swirl": ["Fishcake", "Pink Swirl"], "cooked rice": ["Boiled Rice", "Bowl Of Rice", "Rice", "Steamed Rice"], "dumpling": ["Empanada", "Pierogi"], "takeout box": ["Chinese Food Box", "Oyster Pail"], "roasted sweet potato": ["Goguma", "Sweet Potato", "Yam"], "dango": ["Dessert Stick", "Pink White Green Balls"], "shrimp": ["Prawn"], "soft ice cream": ["Mr. Whippy", "Soft Serve"], "green salad": ["Salad"], "shaved ice": ["Snow Cone"], "ice cream": ["Bowl Of Ice Cream", "Dessert"], "doughnut": ["Donut"], "birthday cake": ["Birthday", "Cake", "Cake With Candles"], "shortcake": ["Cake", "Piece Of Cake", "Strawberry Shortcake"], "spaghetti": ["Pasta"], "cupcake": ["Fairy Cake"], "candy": ["Lolly", "Sweet"], "lollipop": ["Lollypop", "Sucker"], "custard": ["Creme Caramel", "Dessert", "Flan", "Pudding"], "teacup without handle": ["Green Tea", "Matcha", "Matcha Green Tea"], "chocolate bar": ["Candy Bar", "Chocolate"], "wine glass": ["Alcohol", "Red Wine", "Wine"], "cookie": ["Biscuit", "Chocolate Chip Cookie"], "honey pot": ["Honey", "Pot"], "sake": ["Bottle", "Rice Wine"], "glass of milk": ["Milk"], "bottle with popping cork": ["Celebration", "Champagne", "Sparkling Wine"], "hot beverage": ["Coffee", "Espresso", "Hot Chocolate", "Tea"], "tropical drink": ["Fruit Punch", "Tiki Drink"], "beer mug": ["Beer", "Beer Stein"], "cocktail glass": ["Cocktail", "Martini"], "bubble tea": ["Boba"], "tumbler glass": ["Bourbon", "Liquor", "Rum", "Whiskey", "Whisky"], "clinking glasses": ["Celebration", "Champagne Glasses", "Cheers"], "cup with straw": ["Milkshake", "Smoothie", "Soda Pop", "Soft Drink"], "clinking beer mugs": ["Beers", "Cheers"], "beverage box": ["Juice Box"], "mate": ["Chimarr\u00e3o", "Cimarr\u00f3n", "Yerba Mate"], "fork and knife with plate": ["Dinner"], "baby bottle": ["Bottle Feeding"], "kitchen knife": ["Butchers Knife", "Kitchen Knife", "Knife"], "amphora": ["Jar", "Vase"], "family": ["Parents With Child"], "globe with meridians": ["Internet", "World Wide Web", "WWW"], "fork and knife": ["Cutlery", "Knife And Fork", "Silverware"], "mount fuji": ["Fuji-san", "Snow-capped Mountain"], "stadium": ["Grandstand", "Sport Stadium"], "camping": ["Campsite"], "building construction": ["Crane"], "derelict house": ["Abandoned House", "Haunted House", "Old House"], "house": ["Home"], "office building": ["City Building", "High-Rise Building"], "house with garden": ["House And Tree"], "hospital": ["Emergency Room", "Medical", "Red Cross"], "hotel": ["Accommodation", "H Building"], "bank": ["Bakkureru", "Bank Branch", "BK"], "department store": ["Shopping Center", "Shops"], "factory": ["Industrial", "Industry", "Pollution", "Smog"], "convenience store": ["24-Hour Store", "7-Eleven\u00ae", "Corner Shop", "Kwik-E-Mart"], "love hotel": ["Heart Hospital", "Love Heart Hotel"], "school": ["Clock Tower", "Elementary School", "High School", "Middle School"], "post office": ["Post Office"], "church": ["Church Building", "Cross"], "wedding": ["Church Heart", "Church Wedding", "Marriage"], "mosque": ["Domed Roof", "Minaret"], "clutch bag": ["Clutch", "Small Bag"], "castle": ["Castle", "Turrets"], "pinched fingers": ["Finger Purse", "Ma Che Vuoi"], "thong sandal": ["Flip Flops", "Jandals", "Thongs"], "running shoe": ["Runner", "Sneaker", "Trainer"], "backpack": ["Backpack", "Bag", "School Bag"], "grinning face with big eyes": ["Grinning Face", "Happy", "Happy Face", "Smiley Face"], "grinning face with smiling eyes": ["Grinning Face", "Happy Face", "Smiley Face"], "ballet shoes": ["Pointe Shoe"], "victory hand": ["Air Quotes", "Peace", "Peace Sign", "V Sign"], "high-heeled shoe": ["High Heels", "Stiletto"], "crown": ["King", "Queen", "Royal"], "top hat": ["Formal Wear", "Groom"], "person facepalming": ["Facepalm", "Hitting Head", "Picard", "SMH"], "graduation cap": ["College", "Graduate", "Mortar Board", "Square Academic Cap", "University"], "crossed fingers": ["Fingers Crossed", "Good Luck"], "billed cap": ["Baseball Cap"], "lipstick": ["Lip Gloss", "Makeup"], "prayer beads": ["Dhikr Beads", "Rosary Beads"], "gem stone": ["Diamond", "Gem", "Jewel"], "person lifting weights": ["Bodybuilder"], "mage": ["Sorcerer", "Sorceress", "Witch", "Wizard"], "speaker low volume": ["Volume"], "ring": ["Diamond Ring", "Engagement Ring"], "speaker medium volume": ["Reduce Volume"], "muted speaker": ["Mute Volume"], "speaker high volume": ["Increase Volume"], "megaphone": ["Megaphone"], "person shrugging": ["\u00af\\_(\u30c4)_/\u00af", "Shrug", "Shruggie"], "loudspeaker": ["Announcement", "PA System"], "man mage": ["Wizard"], "bell": ["Liberty Bell", "Ringer", "Wedding Bell"], "postal horn": ["Bugle", "French Horn"], "bell with slash": ["Notifications", "Ringer Disabled"], "musical score": ["Sheet Music", "Treble Clef"], "musical note": ["Beamed Pair Of Eighth Notes", "Beamed Pair Of Quavers", "Music Note"], "musical notes": ["Music", "Music Notes", "Singing"], "microphone": ["Karaoke", "Singing"], "sign of the horns": ["Devil Fingers", "Heavy Metal", "Rock On"], "headphone": ["Earphone", "Headphones", "iPod"], "woman mage": ["Witch"], "person biking": ["Bicycle", "Bike", "Cyclist", "Person On Bike"], "radio": ["Digital Radio", "Wireless"], "saxophone": ["Jazz", "Sax"], "guitar": ["Acoustic Guitar", "Bass Guitar", "Electric Guitar"], "call me hand": ["Phone Hand", "Shaka"], "trumpet": ["Horn", "Jazz"], "musical keyboard": ["Piano"], "violin": ["String Quartet", "World\u2019s Smallest Violin"], "man biking": ["Male Cyclist"], "backhand index pointing left": ["Pointing Left"], "woman biking": ["Female Cyclist"], "mobile phone with arrow": ["Phone Call", "Phone With Arrow", "Pointing To Phone"], "mobile phone": ["Cell Phone", "iPhone", "Smartphone"], "telephone": ["Rotary Phone", "Telephone"], "man health worker": ["Male Doctor", "Male Nurse"], "pager": ["Beeper", "Bleeper"], "fax machine": ["Facsimile", "Fax"], "telephone receiver": ["Handset", "Phone"], "person mountain biking": ["Mountain Bike", "Person On Bike"], "backhand index pointing right": ["Pointing Right"], "vampire": ["Dracula"], "low battery": ["No Battery", "Red Battery"], "woman health worker": ["Female Doctor", "Female Nurse"], "laptop": ["Laptop", "Notebook"], "electric plug": ["AC Adaptor", "Power Cable", "Power Plug"], "desktop computer": ["iMac"], "battery": ["AA Battery", "Phone Battery"], "floppy disk": ["3.5\u2033 Disk", "Disk"], "man vampire": ["Dracula"], "optical disk": ["CD", "CD-ROM", "Compact Disc"], "backhand index pointing up": ["Middle Finger", "Pointing Up"], "movie camera": ["Film Camera", "Hollywood", "Movie"], "middle finger": ["Dito Medio", "Flipping The Bird", "Middle Finger", "Rude Finger"], "dvd": ["DVD-ROM", "DVD Video"], "clapper board": ["Clapboard", "Director", "Film Slate"], "camera": ["Digital Camera"], "person cartwheeling": ["Gymnast", "Gymnastics"], "merperson": ["Merboy", "Mergirl", "Mermaid", "Merman"], "television": ["TV"], "videocassette": ["VCR", "VHS", "Video Tape"], "backhand index pointing down": ["Pointing Down"], "video camera": ["Camcorder"], "magnifying glass tilted left": ["Magnifier", "Magnifying Glass", "Search Icon"], "light bulb": ["Idea", "Light Bulb"], "magnifying glass tilted right": ["Magnifier", "Magnifying Glass", "Search Icon"], "flashlight": ["Flashlight", "Torch"], "diya lamp": ["Oil Lamp"], "index pointing up": ["Pointing Up", "Secret"], "open book": ["Book", "Novel"], "red paper lantern": ["Asian Lantern", "Japanese Lantern", "Red Lantern"], "closed book": ["Red Book"], "elf": ["Legolas"], "books": ["Pile Of Books", "Stack Of Books"], "ledger": ["Binder", "Spiral Bound Book", "Yellow Book"], "people wrestling": ["Wrestling"], "notebook": ["Black And White Book"], "page with curl": ["Curled Page", "Curly Page"], "scroll": ["Degree", "Parchment"], "page facing up": ["Printed Page"], "thumbs up": ["Like", "Thumbs Up", "Yes"], "rolled-up newspaper": ["Newspaper Delivery"], "bookmark": ["Price Tag", "Tag"], "yen banknote": ["\u00a51000 Note", "Yen Note"], "dollar banknote": ["$1 Note", "American Dollar", "Dollar Bill"], "thumbs down": ["Bad", "Dislike", "No"], "money bag": ["Moneybags", "Rich"], "pound banknote": ["\u00a320 Note", "Pound Note", "Twenty Quid Note"], "euro banknote": ["\u20ac100 Note", "Euro"], "genie": ["Djinni", "Jinni"], "money with wings": ["Flying Money", "Losing Money"], "credit card": ["AMEX", "Diners Club", "Mastercard", "VISA Card"], "raised fist": ["Fist Pump"], "envelope": ["\u2709 Letter"], "envelope with arrow": ["Down Arrow Envelope", "Insert In Envelope"], "incoming envelope": ["Envelope With Lines", "Fast Envelope"], "e-mail": ["Email"], "chart increasing with yen": ["Yen Exchange Rate", "Yen Graph"], "outbox tray": ["Outbox"], "person getting massage": ["Head Massage", "Massaging"], "package": ["Box", "Parcel"], "inbox tray": ["Inbox"], "oncoming fist": ["Bro Fist / Brofist", "Fist Bump", "Punch"], "open mailbox with raised flag": ["Open Mailbox"], "ballot box with ballot": ["Vote Box", "Voting"], "left-facing fist": ["Left Fist Bump"], "pencil": ["\u270f Lead Pencil"], "black nib": ["\u2712 Pen Nib", "\u2712 Fountain Pen"], "paintbrush": ["Brush"], "right-facing fist": ["Right Fist Bump"], "memo": ["Memorandum", "Note", "Pencil And Paper"], "briefcase": ["Suitcase"], "person juggling": ["Juggler"], "clapping hands": ["Applause", "Clap", "Clapping", "Golf Clap", "Round Of Applause"], "calendar": ["July 17", "World Emoji Day"], "grinning face": ["Happy Face", "Smiley Face"], "file folder": ["Folder", "Manilla Folder"], "person getting haircut": ["Cutting Hair", "Hairdresser"], "tear-off calendar": ["Day Calendar", "Desk Calendar"], "open file folder": ["Open Folder"], "disappointed face": [":(", "Sad", "Sadface"], "persevering face": ["Helpless Face", "Scrunched Eyes"], "downcast face with sweat": ["Hard Work", "Sad Sweat Face"], "tired face": ["Exhausted", "Fed Up"], "face with steam from nose": ["Airing of Grievances", "Frustrated", "Mad Face", "Steaming"], "smiling face with horns": ["Devil", "Devil Horns", "Happy Devil", "Purple Devil", "Red Devil"], "face with symbols on mouth": ["Cursing", "Cussing", "Grawlix", "Swearing"], "old woman": ["Elderly Woman", "Grandma", "Nanna", "Old Lady"], "angry face with horns": ["Devil", "Devil Horns", "Purple Devil", "Purple Goblin", "Sad Devil"], "weary face": ["Distraught Face", "Wailing"], "old man": ["Elderly Man", "Grandpa", "Old Man"], "skull": ["Death", "Grey Skull", "Skeleton"], "angry face": ["Angry", "Grumpy Face"], "ghost": ["Disappear", "Ghoul", "Halloween"], "ogre": ["Mask Face", "Oni", "Red Monster"], "goblin": ["Long Nose Face", "Red Mask", "Tengu"], "grinning cat": ["Happy Cat", "Smiling Cat"], "grinning cat with smiling eyes": ["Grinning Cat", "Happy Cat"], "robot": ["Robot"], "smiling cat with heart-eyes": ["Heart Eyes Cat", "Loving Cat"], "cat with wry smile": ["Smirking Cat"], "pile of poo": ["Dog Dirt", "Smiling Poop"], "kissing cat": ["Kissing Cat"], "alien": ["Alien", "ET"], "love letter": ["Heart Envelope", "Love Note"], "person frowning": ["Sad Person", "Woman Frowning"], "heart with arrow": ["Cupid Arrow", "Lovestruck"], "alien monster": ["Space Invader", "Video Game Monster"], "cat with tears of joy": ["Happy Tears Cat", "Laughing Cat"], "person pouting": ["Blank Look", "Fed Up"], "heart with ribbon": ["Chocolate Box", "Gift Box", "Gift Heart"], "sparkling heart": ["Sparkle Heart", "Sparkly Heart", "Stars Heart"], "hear-no-evil monkey": ["Kikazaru", "Monkey Covering Ears"], "growing heart": ["Multiple Heart", "Triple Heart"], "revolving hearts": ["Two Hearts"], "heart exclamation": ["Heart Above Dot"], "two hearts": ["Small Hearts", "Two Pink Hearts"], "mending heart": ["Bandaged Heart", "Healing Heart", "Unbroken Heart"], "red heart": ["Heart", "Love Heart", "Red Heart"], "beating heart": ["Heart Alarm", "Heartbeat", "Wifi Heart"], "weary cat": ["Scared Cat", "Screaming Cat"], "green heart": ["NCT Heart"], "crying cat": ["Crying Cat", "Sad Cat"], "see-no-evil monkey": ["Mizaru", "Monkey Covering Eyes"], "pouting cat": ["Grumpy Cat"], "purple heart": ["BTS Emoji"], "speak-no-evil monkey": ["Iwazaru", "Monkey Covering Mouth", "No Speaking"], "black heart": ["Dark Heart"], "yellow heart": ["#1 BF Snapchat", "Gold Heart"], "hundred points": ["100", "Keep It 100", "Perfect Score"], "blue heart": ["Brand Heart", "Neutral Heart"], "broken heart": ["Breaking Heart", "Brokenhearted", "Heart Broken"], "dizzy": ["Circle And Star", "Dizzy"], "anger symbol": ["Anger Sign", "Vein Pop"], "collision": ["Bang", "Explode", "Impact", "Red Spark"], "speech balloon": ["Chat Bubble", "Speech Bubble"], "dashing away": ["Fast", "Steam", "Vaping", "Wind"], "eye in speech bubble": ["I Am A Witness"], "thought balloon": ["Thinking Bubble", "Thought Bubble"], "kiss mark": ["Kissing Lips"], "waving hand": ["Goodbye", "Hand Wave", "Hello", "Waving"], "right anger bubble": ["Zig Zag Bubble"], "sweat droplets": ["Plewds", "Splashing Water", "Water Drops"], "hand with fingers splayed": ["Five Hand", "Splayed Hand"], "person tipping hand": ["Bellhop", "Concierge", "Hair Flick", "Sassy Girl"], "raised hand": ["High Five", "Stop"], "person raising hand": ["Answering Question", "Hand Up"], "raised back of hand": ["Backhand"], "vulcan salute": ["Spock", "Star Trek", "Vulcan Salute"], "person bowing": ["Bowing Man", "Cute Boy", "Dogeza", "Massage"], "llama": ["Alpaca"], "rhinoceros": ["Rhino"], "hippopotamus": ["Hippo"], "mouse face": ["Mouse"], "mouse": ["Dormouse", "Mice", "Rodent"], "rabbit face": ["Easter Bunny"], "chipmunk": ["Squirrel"], "rat": ["Rodent"], "rabbit": ["Bunny", "Bunny Rabbit"], "bear": ["Teddy Bear"], "koala": ["Koala Bear"], "person with skullcap": ["Asian Man"], "kangaroo": ["Roo"], "person wearing turban": ["Arab", "Muslim", "Sikh", "Turban"], "bat": ["Batman"], "chicken": ["Hen"], "rooster": ["Cock", "Cockerel"], "baby chick": ["Yellow Bird"], "hamster": ["Hamster"], "eagle": ["Bald Eagle"], "person in tuxedo": ["Groom", "Man In Suit"], "paw prints": ["Cat Paw Prints", "Dog Paw Prints", "Kitten Paw Prints", "Puppy Paw Prints"], "turkey": ["Thanksgiving Turkey", "Wild Turkey"], "front-facing baby chick": ["Baby Chick"], "hatching chick": ["Baby Chicken", "Chick Hatching"], "crocodile": ["Alligator", "Croc"], "turtle": ["Tortoise"], "snake": ["Serpent"], "frog": ["Frog", "Toad"], "dragon face": ["Dragon Head"], "lizard": ["Gecko"], "tropical fish": ["Fish", "Yellow-Blue Fish"], "sauropod": ["Brachiosaurus", "Brontosaurus", "Dinosaur"], "fish": ["Freshwater Fish"], "spouting whale": ["Cute Whale"], "snail": ["Garden Snail", "Slug"], "blowfish": ["Fugu", "Pufferfish"], "ant": ["Bug", "Insect"], "honeybee": ["Bee", "Bumblebee"], "bug": ["Caterpillar", "Insect"], "shark": ["Great White Shark"], "lady beetle": ["Ladybird", "Ladybug", "Lady Bug"], "pregnant woman": ["Pregnancy", "Pregnant Lady"], "spiral shell": ["Beach", "Seashell", "Shell"], "cricket": ["Grasshopper"], "spider web": ["Cobweb", "Web"], "microbe": ["Cell", "Coronavirus", "COVID-19", "Germ", "Microorganism", "Virus"], "rose": ["Red Flower", "Red Rose"], "breast-feeding": ["Breastfeeding"], "bouquet": ["Bouquet Of Flowers"], "cherry blossom": ["Pink Flower", "Sakura"], "white flower": ["Cherry Blossom", "Paper Doily", "Well Done Stamp"], "wilted flower": ["Dead Flower", "Drooping Flower"], "blossom": ["Blossoming Flower", "Daisy", "Yellow Flower"], "potted plant": ["Houseplant"], "sunflower": ["Yellow Flower"], "deciduous tree": ["Rounded Tree"], "seedling": ["Spring", "Sprout", "Sprouting"], "sheaf of rice": ["Crop", "Farming", "Wheat"], "herb": ["Crop", "Plant"], "shamrock": ["Clover", "Trefoil"], "evergreen tree": ["Fir Tree", "Pine Tree", "Tree"], "fallen leaf": ["Autumn Leaves", "Brown Leaves", "Fall Leaves"], "cactus": ["Desert"], "baby angel": ["Angel", "Cherub", "Cupid", "Putto"], "mushroom": ["Shroom", "Toadstool"], "maple leaf": ["Canada", "Canadian", "Maple"], "palm tree": ["Coconut Tree"], "tangerine": ["Mandarin", "Orange"], "four leaf clover": ["Clover", "Ireland", "Lucky"], "banana": ["Plantain"], "leaf fluttering in wind": ["Green Leaves", "Spring"], "red apple": ["Red Delicious Apple"], "grapes": ["Grape"], "cherries": ["Cherry", "Wild Cherry"], "lemon": ["Lemonade"], "coconut": ["Cocoanut"], "green apple": ["Golden Delicious Apple", "Granny Smith Apple"], "peach": ["Bottom", "Butt"], "eggplant": ["Eggplant", "Phallic", "Purple Vegetable"], "potato": ["Baked Potato", "Idaho Potato"], "ear of corn": ["Corn", "Corn On The Cob", "Maize"], "melon": ["Cantaloupe", "Honeydew", "Muskmelon"], "kiwi fruit": ["Chinese Gooseberry", "Kiwi"], "hot pepper": ["Chili Pepper", "Spicy"], "cucumber": ["Gherkin", "Pickle"], "child": ["Gender Inclusive Child", "Gender Neutral Child"], "leafy green": ["Bok Choy", "Chinese Cabbage", "Cos Lettuce", "Romaine Lettuce"], "peanuts": ["Nuts"], "thermometer": ["Hot Weather", "Temperature"], "om": ["Aumkara", "Omkara", "Pranava"], "sun": ["Sun", "Sunshine"], "full moon face": ["Moonface", "Smiley Moon", "Smiling Moon"], "woman running": ["Boy Runner"], "sun with face": ["Smiley Sun", "Smiling Sun", "Sunface"], "ringed planet": ["Saturn"], "wheel of dharma": ["Helm"], "woman dancing": ["Red Dress Woman", "Salsa Dancer"], "peace symbol": ["Peace Sign"], "latin cross": ["Christian Cross"], "red square": ["Red Card"], "shooting star": ["Meteoroid", "When You Wish Upon A Star"], "star": ["Gold Star"], "yellow square": ["Yellow Card"], "menorah": ["Candelabrum", "Candles", "Chanukiah", "Menorah"], "glowing star": ["Shining Star"], "milky way": ["Galaxy", "Night Sky", "Space", "Stars", "Universe"], "cloud": ["Cloudy", "Overcast"], "man dancing": ["Disco Dancer", "Male Dancer"], "person": ["Gender Inclusive Adult", "Gender Neutral Adult", "Person"], "person in suit levitating": ["Hovering Man", "Rude Boy", "Walt Jabsco"], "man astronaut": ["Man Cosmonaut"], "rainbow": ["Gay Pride", "Primary Rainbow"], "wind face": ["Blowing Wind", "Mother Nature"], "cyclone": ["Hurricane", "Spiral", "Swirl", "Tornado"], "closed umbrella": ["Collapsed Umbrella", "Pink Umbrella"], "repeat button": ["Loop Symbol", "Retweet"], "diamond with a dot": ["Cuteness", "Diamond Flower", "Kawaii"], "woman astronaut": ["Woman Cosmonaut"], "play button": ["Play Button", "Right Triangle"], "umbrella": ["Umbrella"], "high voltage": ["Lightning Bolt", "Thunderbolt"], "repeat single button": ["Circle Arrows With Number 1", "Loop Once Symbol"], "next track button": ["Next Track"], "man": ["Male", "Moustache Man"], "people with bunny ears": ["Ballet", "Dancing Girls", "Let's Party", "Showgirls"], "snowman": ["Snowing Snowman"], "snowflake": ["Snow", "Snowing"], "umbrella with rain drops": ["Raining", "Rainy"], "snowman without snow": ["Frosty The Snowman", "Olaf", "Snowman"], "chequered flag": ["Checkered Flag", "Grid Girl", "Racing Flag"], "person in steamy room": ["Sauna"], "play or pause button": ["Play-Pause"], "fast-forward button": ["Fast Forward"], "fast reverse button": ["Rewind"], "reverse button": ["Left Triangle"], "triangular flag": ["Flag on Pole", "Red Flag"], "crossed flags": ["Two Flags"], "rainbow flag": ["Pride Flag"], "water wave": ["Beach", "Ocean Wave", "Sea", "Waves"], "last track button": ["Previous Track"], "pirate flag": ["Jolly Roger"], "fire": ["Flame", "Hot", "Lit", "Snapstreak"], "droplet": ["Water", "Water Drop"], "jack-o-lantern": ["Gourd", "Halloween", "Pumpkin"], "fireworks": ["Explosion"], "upwards button": ["Up Triangle"], "transgender flag": ["Blue, Pink, and White Flag", "Trans Flag"], "sparkler": ["Senko Hanabi"], "downwards button": ["Down Triangle"], "stop button": ["Stop"], "sparkles": ["Glitter", "Shiny"], "cinema": ["Cinema Screen", "Movies"], "pause button": ["Pause"], "party popper": ["Celebration", "Party Hat"], "dim button": ["Decrease Brightness"], "tanabata tree": ["Tanabata", "Wish Tree"], "firecracker": ["Dynamite"], "record button": ["Record"], "antenna bars": ["Reception Bars", "Signal Strength", "Stairs"], "vibration mode": ["Phone Heart", "Silent Mode"], "balloon": ["Party", "Red Balloon"], "carp streamer": ["Fish Flag", "Koinobori", "Wind Socks"], "bright button": ["Increase Brightness"], "wind chime": ["Furin", "Jellyfish", "Wind Bell"], "confetti ball": ["Confetti"], "police officer": ["Cop", "Police", "Policeman", "Policewoman"], "moon viewing ceremony": ["Grass, Dumplings and Moon", "Harvest Moon", "Mid-Autumn Festival", "Tsukimi"], "pine decoration": ["Bamboo", "Kadomatsu", "New Year Decoration"], "ribbon": ["Bow", "Pink Bow"], "person climbing": ["Climber", "Rock Climbing"], "male sign": ["Man Symbol", "Mars Symbol"], "transgender symbol": ["Transgender Sign"], "female sign": ["Venus Symbol", "Woman Symbol"], "wrapped gift": ["Birthday Present", "Christmas Present", "Gift", "Gift Box"], "red envelope": ["Ang Pao", "H\u00f3ngb\u0101o", "Lai See", "Red Packet"], "ticket": ["Ticket Stub", "World Tour TIcket"], "military medal": ["Medal", "Medallion", "Military Decoration"], "man climbing": ["Male Rock Climber", "Man Climber"], "trophy": ["Championship Trophy", "Winners Trophy"], "woman climbing": ["Female Rock Climber", "Woman Climber"], "2nd place medal": ["Silver Medal"], "infinity": ["Infinity"], "3rd place medal": ["Bronze Medal"], "soccer ball": ["Football", "Soccer"], "baseball": ["Softball"], "wavy dash": ["\u3030 Wave"], "basketball": ["Basketball", "Orange Ball"], "heavy dollar sign": ["Dollar", "Dollar Sign"], "horse racing": ["Horse Race", "Jockey"], "medical symbol": ["Aesculapius", "Asklepios", "Rod of Asclepius"], "recycling symbol": ["Recycle Logo"], "1st place medal": ["Gold Medal"], "detective": ["Detective", "Private Eye", "Sleuth", "Spy"], "rugby football": ["Football", "League", "Rugby", "Union"], "fleur-de-lis": ["New Orleans Saints", "Scouts"], "trident emblem": ["Pitchfork", "Trident"], "name badge": ["Fire Tag", "Name Tag", "Tofu On Fire"], "bowling": ["Bowling Ball", "Pins", "Skittles", "Ten Pin Bowling"], "cricket game": ["Cricket"], "hollow red circle": ["Circle", "Correct", "Red Circle"], "american football": ["Football", "Gridiron", "Superbowl"], "snowboarder": ["Snowboard", "Snowboarding"], "field hockey": ["Field Hockey", "Hockey"], "check box with check": ["Checkbox", "Check Mark In Box"], "tennis": ["Tennis", "Tennis Ball", "Tennis Racket", "Tennis Racquet"], "woman": ["Female", "Lady", "Yellow Woman"], "cross mark": ["Cross", "X"], "cross mark button": ["Cross", "X"], "check mark button": ["Green Check Mark", "Green Tick"], "ice hockey": ["Ice Hockey"], "check mark": ["Check", "Tick"], "ping pong": ["Ping Pong", "Table Tennis"], "martial arts uniform": ["Judo"], "curly loop": ["Curling Loop", "Loop"], "double curly loop": ["Double Curling Loop", "Voicemail"], "part alternation mark": ["M", "McDonald\u2019s"], "person golfing": ["Golf", "Golf Club"], "fishing pole": ["Fishing", "Fishing Rod"], "ice skate": ["Ice Skating"], "flag in hole": ["Golf", "Golf Flag"], "guard": ["British Guardsman", "Foot Guard"], "running shirt": ["Running Shirt", "Singlet"], "eight-pointed star": ["Orange Star"], "skis": ["Skiing", "Skis"], "trade mark": ["\u2122 TM", "\u2122 Trademark"], "yo-yo": ["Yoyo"], "crystal ball": ["Clairvoyant", "Fortune Teller", "Psychic", "Purple Crystal"], "pool 8 ball": ["8 Ball", "Cue Ball", "Magic 8 Ball", "Pool", "Snooker"], "video game": ["Gamepad", "Playstation", "Wii U", "Xbox"], "person surfing": ["Surf", "Surfing"], "game die": ["Dice"], "slot machine": ["Casino", "Fruit Machine", "Gambling", "Poker Machine"], "speaking head": ["Mansplaining", "Shout", "Shouting"], "busts in silhouette": ["Shadows", "Silhouettes", "Users"], "teddy bear": ["Toy"], "bust in silhouette": ["Shadow", "Silhouette", "User"], "input numbers": ["1234", "Numbers", "Numeric Input"], "input symbols": ["Symbols", "Symbol Input"], "input latin uppercase": ["ABCD", "Uppercase"], "monkey face": ["Monkey Head"], "nesting dolls": ["Matryoshka", "Russian Dolls"], "input latin lowercase": ["ABCD", "Lowercase"], "monkey": ["Cheeky Monkey"], "spade suit": ["Spades"], "heart suit": ["Card With Heart", "Hearts"], "mirror ball": ["Disco Ball"], "input latin letters": ["ABC", "Alphabet", "Letters"], "footprints": ["Feet", "Footsteps"], "dog face": ["Dog", "Puppy"], "club suit": ["Clubs"], "dog": ["Doggo"], "diamond suit": ["Diamonds"], "guide dog": ["Seeing Eye Dog"], "information": ["Info", "Lowercase I", "Tourist Information"], "joker": ["Joker", "Joker Card"], "poodle": ["Miniature Poodle", "Standard Poodle", "Toy Poodle"], "flower playing cards": ["Deck Of Cards", "Hanafuda", "Hwatu", "Playing Cards"], "construction worker": ["Builder", "Face With Hat", "Hard-Hat", "Safety Helmet"], "mahjong red dragon": ["Mahjong", "Mahjong Tile", "\u4e2d"], "performing arts": ["Drama Masks", "Greek Theatre Masks", "Theatre Logo", "Tragedy and Comedy Masks"], "fox": ["Fox"], "framed picture": ["Painting", "Picture Frame"], "artist palette": ["Art", "Painting"], "cat face": [":3", "Kitten", "Kitty"], "cat": ["Domestic Cat", "Feline", "Housecat"], "person rowing boat": ["Boat With Paddles", "Rowing"], "glasses": ["Glasses"], "tiger face": ["Cute Tiger"], "tiger": ["Bengal Tiger"], "leopard": ["African Leopard", "Jaguar"], "horse face": ["Horse Head"], "necktie": ["Business Shirt", "Shirt And Tie", "Tie"], "horse": ["Galloping Horse", "Racehorse"], "unicorn": ["Unicorn"], "jeans": ["Denim", "Pants", "Trousers"], "t-shirt": ["Polo Shirt", "Tee Shirt"], "deer": ["Buck", "Reindeer", "Stag"], "cow face": ["Cow", "Happy Cow"], "bison": ["buffalo"], "ox": ["Bull", "Bullock", "Oxen", "Steer"], "water buffalo": ["Buffalo", "Domestic Water Buffalo"], "person swimming": ["Swimming"], "pig face": ["Pig Head"], "dress": ["Gown", "Skirt"], "pig": ["Hog", "Sow"], "kimono": ["Dressing Gown", "Japanese Dress"], "sari": ["Saree", "Shari"], "cow": ["Dairy Cow"], "bikini": ["Bathers", "Swimsuit"], "pig nose": ["Pig Snout"], "ram": ["Sheep"], "ewe": ["Ewe", "Lamb"], "princess": ["Blonde Girl", "Girl With Crown", "Girl With Tiara"], "camel": ["Arabian Camel", "Dromedary Camel", "One-Bump Camel"], "purse": ["Wallet"], "two-hump camel": ["Asian Camel", "Bactrian Camel", "Two-Bump Camel"], "older person": ["Gender Neutral Older Adult"], "handbag": ["Women\u2019s Bag"], "boar": ["Warthog", "Wild Boar", "Wild Pig"], "men holding hands": ["Gay Couple"], "kiss": ["Couple Kissing", "Gender Neutral Couple Kissing"], "couple with heart": ["Couple In Love", "Gender Neutral Couple", "Loving Couple"]} \ No newline at end of file diff --git a/emoji/emoji-test.txt b/emoji/emoji-test.txt new file mode 100644 index 00000000..87d093d6 --- /dev/null +++ b/emoji/emoji-test.txt @@ -0,0 +1,5024 @@ +# emoji-test.txt +# Date: 2022-08-12, 20:24:39 GMT +# © 2022 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see https://www.unicode.org/terms_of_use.html +# +# Emoji Keyboard/Display Test Data for UTS #51 +# Version: 15.0 +# +# For documentation and usage, see https://www.unicode.org/reports/tr51 +# +# This file provides data for testing which emoji forms should be in keyboards and which should also be displayed/processed. +# Format: code points; status # emoji name +# Code points — list of one or more hex code points, separated by spaces +# Status +# component — an Emoji_Component, +# excluding Regional_Indicators, ASCII, and non-Emoji. +# fully-qualified — a fully-qualified emoji (see ED-18 in UTS #51), +# excluding Emoji_Component +# minimally-qualified — a minimally-qualified emoji (see ED-18a in UTS #51) +# unqualified — a unqualified emoji (See ED-19 in UTS #51) +# Notes: +# • This includes the emoji components that need emoji presentation (skin tone and hair) +# when isolated, but omits the components that need not have an emoji +# presentation when isolated. +# • The RGI set is covered by the listed fully-qualified emoji. +# • The listed minimally-qualified and unqualified cover all cases where an +# element of the RGI set is missing one or more emoji presentation selectors. +# • The file is in CLDR order, not codepoint order. This is recommended (but not required!) for keyboard palettes. +# • The groups and subgroups are illustrative. See the Emoji Order chart for more information. + + +# group: Smileys & Emotion + +# subgroup: face-smiling +1F600 ; fully-qualified # 😀 E1.0 grinning face +1F603 ; fully-qualified # 😃 E0.6 grinning face with big eyes +1F604 ; fully-qualified # 😄 E0.6 grinning face with smiling eyes +1F601 ; fully-qualified # 😁 E0.6 beaming face with smiling eyes +1F606 ; fully-qualified # 😆 E0.6 grinning squinting face +1F605 ; fully-qualified # 😅 E0.6 grinning face with sweat +1F923 ; fully-qualified # 🤣 E3.0 rolling on the floor laughing +1F602 ; fully-qualified # 😂 E0.6 face with tears of joy +1F642 ; fully-qualified # 🙂 E1.0 slightly smiling face +1F643 ; fully-qualified # 🙃 E1.0 upside-down face +1FAE0 ; fully-qualified # 🫠 E14.0 melting face +1F609 ; fully-qualified # 😉 E0.6 winking face +1F60A ; fully-qualified # 😊 E0.6 smiling face with smiling eyes +1F607 ; fully-qualified # 😇 E1.0 smiling face with halo + +# subgroup: face-affection +1F970 ; fully-qualified # 🥰 E11.0 smiling face with hearts +1F60D ; fully-qualified # 😍 E0.6 smiling face with heart-eyes +1F929 ; fully-qualified # 🤩 E5.0 star-struck +1F618 ; fully-qualified # 😘 E0.6 face blowing a kiss +1F617 ; fully-qualified # 😗 E1.0 kissing face +263A FE0F ; fully-qualified # ☺️ E0.6 smiling face +263A ; unqualified # ☺ E0.6 smiling face +1F61A ; fully-qualified # 😚 E0.6 kissing face with closed eyes +1F619 ; fully-qualified # 😙 E1.0 kissing face with smiling eyes +1F972 ; fully-qualified # 🥲 E13.0 smiling face with tear + +# subgroup: face-tongue +1F60B ; fully-qualified # 😋 E0.6 face savoring food +1F61B ; fully-qualified # 😛 E1.0 face with tongue +1F61C ; fully-qualified # 😜 E0.6 winking face with tongue +1F92A ; fully-qualified # 🤪 E5.0 zany face +1F61D ; fully-qualified # 😝 E0.6 squinting face with tongue +1F911 ; fully-qualified # 🤑 E1.0 money-mouth face + +# subgroup: face-hand +1F917 ; fully-qualified # 🤗 E1.0 smiling face with open hands +1F92D ; fully-qualified # 🤭 E5.0 face with hand over mouth +1FAE2 ; fully-qualified # 🫢 E14.0 face with open eyes and hand over mouth +1FAE3 ; fully-qualified # 🫣 E14.0 face with peeking eye +1F92B ; fully-qualified # 🤫 E5.0 shushing face +1F914 ; fully-qualified # 🤔 E1.0 thinking face +1FAE1 ; fully-qualified # 🫡 E14.0 saluting face + +# subgroup: face-neutral-skeptical +1F910 ; fully-qualified # 🤐 E1.0 zipper-mouth face +1F928 ; fully-qualified # 🤨 E5.0 face with raised eyebrow +1F610 ; fully-qualified # 😐 E0.7 neutral face +1F611 ; fully-qualified # 😑 E1.0 expressionless face +1F636 ; fully-qualified # 😶 E1.0 face without mouth +1FAE5 ; fully-qualified # 🫥 E14.0 dotted line face +1F636 200D 1F32B FE0F ; fully-qualified # 😶‍🌫️ E13.1 face in clouds +1F636 200D 1F32B ; minimally-qualified # 😶‍🌫 E13.1 face in clouds +1F60F ; fully-qualified # 😏 E0.6 smirking face +1F612 ; fully-qualified # 😒 E0.6 unamused face +1F644 ; fully-qualified # 🙄 E1.0 face with rolling eyes +1F62C ; fully-qualified # 😬 E1.0 grimacing face +1F62E 200D 1F4A8 ; fully-qualified # 😮‍💨 E13.1 face exhaling +1F925 ; fully-qualified # 🤥 E3.0 lying face +1FAE8 ; fully-qualified # 🫨 E15.0 shaking face + +# subgroup: face-sleepy +1F60C ; fully-qualified # 😌 E0.6 relieved face +1F614 ; fully-qualified # 😔 E0.6 pensive face +1F62A ; fully-qualified # 😪 E0.6 sleepy face +1F924 ; fully-qualified # 🤤 E3.0 drooling face +1F634 ; fully-qualified # 😴 E1.0 sleeping face + +# subgroup: face-unwell +1F637 ; fully-qualified # 😷 E0.6 face with medical mask +1F912 ; fully-qualified # 🤒 E1.0 face with thermometer +1F915 ; fully-qualified # 🤕 E1.0 face with head-bandage +1F922 ; fully-qualified # 🤢 E3.0 nauseated face +1F92E ; fully-qualified # 🤮 E5.0 face vomiting +1F927 ; fully-qualified # 🤧 E3.0 sneezing face +1F975 ; fully-qualified # 🥵 E11.0 hot face +1F976 ; fully-qualified # 🥶 E11.0 cold face +1F974 ; fully-qualified # 🥴 E11.0 woozy face +1F635 ; fully-qualified # 😵 E0.6 face with crossed-out eyes +1F635 200D 1F4AB ; fully-qualified # 😵‍💫 E13.1 face with spiral eyes +1F92F ; fully-qualified # 🤯 E5.0 exploding head + +# subgroup: face-hat +1F920 ; fully-qualified # 🤠 E3.0 cowboy hat face +1F973 ; fully-qualified # 🥳 E11.0 partying face +1F978 ; fully-qualified # 🥸 E13.0 disguised face + +# subgroup: face-glasses +1F60E ; fully-qualified # 😎 E1.0 smiling face with sunglasses +1F913 ; fully-qualified # 🤓 E1.0 nerd face +1F9D0 ; fully-qualified # 🧐 E5.0 face with monocle + +# subgroup: face-concerned +1F615 ; fully-qualified # 😕 E1.0 confused face +1FAE4 ; fully-qualified # 🫤 E14.0 face with diagonal mouth +1F61F ; fully-qualified # 😟 E1.0 worried face +1F641 ; fully-qualified # 🙁 E1.0 slightly frowning face +2639 FE0F ; fully-qualified # ☹️ E0.7 frowning face +2639 ; unqualified # ☹ E0.7 frowning face +1F62E ; fully-qualified # 😮 E1.0 face with open mouth +1F62F ; fully-qualified # 😯 E1.0 hushed face +1F632 ; fully-qualified # 😲 E0.6 astonished face +1F633 ; fully-qualified # 😳 E0.6 flushed face +1F97A ; fully-qualified # 🥺 E11.0 pleading face +1F979 ; fully-qualified # 🥹 E14.0 face holding back tears +1F626 ; fully-qualified # 😦 E1.0 frowning face with open mouth +1F627 ; fully-qualified # 😧 E1.0 anguished face +1F628 ; fully-qualified # 😨 E0.6 fearful face +1F630 ; fully-qualified # 😰 E0.6 anxious face with sweat +1F625 ; fully-qualified # 😥 E0.6 sad but relieved face +1F622 ; fully-qualified # 😢 E0.6 crying face +1F62D ; fully-qualified # 😭 E0.6 loudly crying face +1F631 ; fully-qualified # 😱 E0.6 face screaming in fear +1F616 ; fully-qualified # 😖 E0.6 confounded face +1F623 ; fully-qualified # 😣 E0.6 persevering face +1F61E ; fully-qualified # 😞 E0.6 disappointed face +1F613 ; fully-qualified # 😓 E0.6 downcast face with sweat +1F629 ; fully-qualified # 😩 E0.6 weary face +1F62B ; fully-qualified # 😫 E0.6 tired face +1F971 ; fully-qualified # 🥱 E12.0 yawning face + +# subgroup: face-negative +1F624 ; fully-qualified # 😤 E0.6 face with steam from nose +1F621 ; fully-qualified # 😡 E0.6 enraged face +1F620 ; fully-qualified # 😠 E0.6 angry face +1F92C ; fully-qualified # 🤬 E5.0 face with symbols on mouth +1F608 ; fully-qualified # 😈 E1.0 smiling face with horns +1F47F ; fully-qualified # 👿 E0.6 angry face with horns +1F480 ; fully-qualified # 💀 E0.6 skull +2620 FE0F ; fully-qualified # ☠️ E1.0 skull and crossbones +2620 ; unqualified # ☠ E1.0 skull and crossbones + +# subgroup: face-costume +1F4A9 ; fully-qualified # 💩 E0.6 pile of poo +1F921 ; fully-qualified # 🤡 E3.0 clown face +1F479 ; fully-qualified # 👹 E0.6 ogre +1F47A ; fully-qualified # 👺 E0.6 goblin +1F47B ; fully-qualified # 👻 E0.6 ghost +1F47D ; fully-qualified # 👽 E0.6 alien +1F47E ; fully-qualified # 👾 E0.6 alien monster +1F916 ; fully-qualified # 🤖 E1.0 robot + +# subgroup: cat-face +1F63A ; fully-qualified # 😺 E0.6 grinning cat +1F638 ; fully-qualified # 😸 E0.6 grinning cat with smiling eyes +1F639 ; fully-qualified # 😹 E0.6 cat with tears of joy +1F63B ; fully-qualified # 😻 E0.6 smiling cat with heart-eyes +1F63C ; fully-qualified # 😼 E0.6 cat with wry smile +1F63D ; fully-qualified # 😽 E0.6 kissing cat +1F640 ; fully-qualified # 🙀 E0.6 weary cat +1F63F ; fully-qualified # 😿 E0.6 crying cat +1F63E ; fully-qualified # 😾 E0.6 pouting cat + +# subgroup: monkey-face +1F648 ; fully-qualified # 🙈 E0.6 see-no-evil monkey +1F649 ; fully-qualified # 🙉 E0.6 hear-no-evil monkey +1F64A ; fully-qualified # 🙊 E0.6 speak-no-evil monkey + +# subgroup: heart +1F48C ; fully-qualified # 💌 E0.6 love letter +1F498 ; fully-qualified # 💘 E0.6 heart with arrow +1F49D ; fully-qualified # 💝 E0.6 heart with ribbon +1F496 ; fully-qualified # 💖 E0.6 sparkling heart +1F497 ; fully-qualified # 💗 E0.6 growing heart +1F493 ; fully-qualified # 💓 E0.6 beating heart +1F49E ; fully-qualified # 💞 E0.6 revolving hearts +1F495 ; fully-qualified # 💕 E0.6 two hearts +1F49F ; fully-qualified # 💟 E0.6 heart decoration +2763 FE0F ; fully-qualified # ❣️ E1.0 heart exclamation +2763 ; unqualified # ❣ E1.0 heart exclamation +1F494 ; fully-qualified # 💔 E0.6 broken heart +2764 FE0F 200D 1F525 ; fully-qualified # ❤️‍🔥 E13.1 heart on fire +2764 200D 1F525 ; unqualified # ❤‍🔥 E13.1 heart on fire +2764 FE0F 200D 1FA79 ; fully-qualified # ❤️‍🩹 E13.1 mending heart +2764 200D 1FA79 ; unqualified # ❤‍🩹 E13.1 mending heart +2764 FE0F ; fully-qualified # ❤️ E0.6 red heart +2764 ; unqualified # ❤ E0.6 red heart +1FA77 ; fully-qualified # 🩷 E15.0 pink heart +1F9E1 ; fully-qualified # 🧡 E5.0 orange heart +1F49B ; fully-qualified # 💛 E0.6 yellow heart +1F49A ; fully-qualified # 💚 E0.6 green heart +1F499 ; fully-qualified # 💙 E0.6 blue heart +1FA75 ; fully-qualified # 🩵 E15.0 light blue heart +1F49C ; fully-qualified # 💜 E0.6 purple heart +1F90E ; fully-qualified # 🤎 E12.0 brown heart +1F5A4 ; fully-qualified # 🖤 E3.0 black heart +1FA76 ; fully-qualified # 🩶 E15.0 grey heart +1F90D ; fully-qualified # 🤍 E12.0 white heart + +# subgroup: emotion +1F48B ; fully-qualified # 💋 E0.6 kiss mark +1F4AF ; fully-qualified # 💯 E0.6 hundred points +1F4A2 ; fully-qualified # 💢 E0.6 anger symbol +1F4A5 ; fully-qualified # 💥 E0.6 collision +1F4AB ; fully-qualified # 💫 E0.6 dizzy +1F4A6 ; fully-qualified # 💦 E0.6 sweat droplets +1F4A8 ; fully-qualified # 💨 E0.6 dashing away +1F573 FE0F ; fully-qualified # 🕳️ E0.7 hole +1F573 ; unqualified # 🕳 E0.7 hole +1F4AC ; fully-qualified # 💬 E0.6 speech balloon +1F441 FE0F 200D 1F5E8 FE0F ; fully-qualified # 👁️‍🗨️ E2.0 eye in speech bubble +1F441 200D 1F5E8 FE0F ; unqualified # 👁‍🗨️ E2.0 eye in speech bubble +1F441 FE0F 200D 1F5E8 ; minimally-qualified # 👁️‍🗨 E2.0 eye in speech bubble +1F441 200D 1F5E8 ; unqualified # 👁‍🗨 E2.0 eye in speech bubble +1F5E8 FE0F ; fully-qualified # 🗨️ E2.0 left speech bubble +1F5E8 ; unqualified # 🗨 E2.0 left speech bubble +1F5EF FE0F ; fully-qualified # 🗯️ E0.7 right anger bubble +1F5EF ; unqualified # 🗯 E0.7 right anger bubble +1F4AD ; fully-qualified # 💭 E1.0 thought balloon +1F4A4 ; fully-qualified # 💤 E0.6 ZZZ + +# Smileys & Emotion subtotal: 180 +# Smileys & Emotion subtotal: 180 w/o modifiers + +# group: People & Body + +# subgroup: hand-fingers-open +1F44B ; fully-qualified # 👋 E0.6 waving hand +1F44B 1F3FB ; fully-qualified # 👋🏻 E1.0 waving hand: light skin tone +1F44B 1F3FC ; fully-qualified # 👋🏼 E1.0 waving hand: medium-light skin tone +1F44B 1F3FD ; fully-qualified # 👋🏽 E1.0 waving hand: medium skin tone +1F44B 1F3FE ; fully-qualified # 👋🏾 E1.0 waving hand: medium-dark skin tone +1F44B 1F3FF ; fully-qualified # 👋🏿 E1.0 waving hand: dark skin tone +1F91A ; fully-qualified # 🤚 E3.0 raised back of hand +1F91A 1F3FB ; fully-qualified # 🤚🏻 E3.0 raised back of hand: light skin tone +1F91A 1F3FC ; fully-qualified # 🤚🏼 E3.0 raised back of hand: medium-light skin tone +1F91A 1F3FD ; fully-qualified # 🤚🏽 E3.0 raised back of hand: medium skin tone +1F91A 1F3FE ; fully-qualified # 🤚🏾 E3.0 raised back of hand: medium-dark skin tone +1F91A 1F3FF ; fully-qualified # 🤚🏿 E3.0 raised back of hand: dark skin tone +1F590 FE0F ; fully-qualified # 🖐️ E0.7 hand with fingers splayed +1F590 ; unqualified # 🖐 E0.7 hand with fingers splayed +1F590 1F3FB ; fully-qualified # 🖐🏻 E1.0 hand with fingers splayed: light skin tone +1F590 1F3FC ; fully-qualified # 🖐🏼 E1.0 hand with fingers splayed: medium-light skin tone +1F590 1F3FD ; fully-qualified # 🖐🏽 E1.0 hand with fingers splayed: medium skin tone +1F590 1F3FE ; fully-qualified # 🖐🏾 E1.0 hand with fingers splayed: medium-dark skin tone +1F590 1F3FF ; fully-qualified # 🖐🏿 E1.0 hand with fingers splayed: dark skin tone +270B ; fully-qualified # ✋ E0.6 raised hand +270B 1F3FB ; fully-qualified # ✋🏻 E1.0 raised hand: light skin tone +270B 1F3FC ; fully-qualified # ✋🏼 E1.0 raised hand: medium-light skin tone +270B 1F3FD ; fully-qualified # ✋🏽 E1.0 raised hand: medium skin tone +270B 1F3FE ; fully-qualified # ✋🏾 E1.0 raised hand: medium-dark skin tone +270B 1F3FF ; fully-qualified # ✋🏿 E1.0 raised hand: dark skin tone +1F596 ; fully-qualified # 🖖 E1.0 vulcan salute +1F596 1F3FB ; fully-qualified # 🖖🏻 E1.0 vulcan salute: light skin tone +1F596 1F3FC ; fully-qualified # 🖖🏼 E1.0 vulcan salute: medium-light skin tone +1F596 1F3FD ; fully-qualified # 🖖🏽 E1.0 vulcan salute: medium skin tone +1F596 1F3FE ; fully-qualified # 🖖🏾 E1.0 vulcan salute: medium-dark skin tone +1F596 1F3FF ; fully-qualified # 🖖🏿 E1.0 vulcan salute: dark skin tone +1FAF1 ; fully-qualified # 🫱 E14.0 rightwards hand +1FAF1 1F3FB ; fully-qualified # 🫱🏻 E14.0 rightwards hand: light skin tone +1FAF1 1F3FC ; fully-qualified # 🫱🏼 E14.0 rightwards hand: medium-light skin tone +1FAF1 1F3FD ; fully-qualified # 🫱🏽 E14.0 rightwards hand: medium skin tone +1FAF1 1F3FE ; fully-qualified # 🫱🏾 E14.0 rightwards hand: medium-dark skin tone +1FAF1 1F3FF ; fully-qualified # 🫱🏿 E14.0 rightwards hand: dark skin tone +1FAF2 ; fully-qualified # 🫲 E14.0 leftwards hand +1FAF2 1F3FB ; fully-qualified # 🫲🏻 E14.0 leftwards hand: light skin tone +1FAF2 1F3FC ; fully-qualified # 🫲🏼 E14.0 leftwards hand: medium-light skin tone +1FAF2 1F3FD ; fully-qualified # 🫲🏽 E14.0 leftwards hand: medium skin tone +1FAF2 1F3FE ; fully-qualified # 🫲🏾 E14.0 leftwards hand: medium-dark skin tone +1FAF2 1F3FF ; fully-qualified # 🫲🏿 E14.0 leftwards hand: dark skin tone +1FAF3 ; fully-qualified # 🫳 E14.0 palm down hand +1FAF3 1F3FB ; fully-qualified # 🫳🏻 E14.0 palm down hand: light skin tone +1FAF3 1F3FC ; fully-qualified # 🫳🏼 E14.0 palm down hand: medium-light skin tone +1FAF3 1F3FD ; fully-qualified # 🫳🏽 E14.0 palm down hand: medium skin tone +1FAF3 1F3FE ; fully-qualified # 🫳🏾 E14.0 palm down hand: medium-dark skin tone +1FAF3 1F3FF ; fully-qualified # 🫳🏿 E14.0 palm down hand: dark skin tone +1FAF4 ; fully-qualified # 🫴 E14.0 palm up hand +1FAF4 1F3FB ; fully-qualified # 🫴🏻 E14.0 palm up hand: light skin tone +1FAF4 1F3FC ; fully-qualified # 🫴🏼 E14.0 palm up hand: medium-light skin tone +1FAF4 1F3FD ; fully-qualified # 🫴🏽 E14.0 palm up hand: medium skin tone +1FAF4 1F3FE ; fully-qualified # 🫴🏾 E14.0 palm up hand: medium-dark skin tone +1FAF4 1F3FF ; fully-qualified # 🫴🏿 E14.0 palm up hand: dark skin tone +1FAF7 ; fully-qualified # 🫷 E15.0 leftwards pushing hand +1FAF7 1F3FB ; fully-qualified # 🫷🏻 E15.0 leftwards pushing hand: light skin tone +1FAF7 1F3FC ; fully-qualified # 🫷🏼 E15.0 leftwards pushing hand: medium-light skin tone +1FAF7 1F3FD ; fully-qualified # 🫷🏽 E15.0 leftwards pushing hand: medium skin tone +1FAF7 1F3FE ; fully-qualified # 🫷🏾 E15.0 leftwards pushing hand: medium-dark skin tone +1FAF7 1F3FF ; fully-qualified # 🫷🏿 E15.0 leftwards pushing hand: dark skin tone +1FAF8 ; fully-qualified # 🫸 E15.0 rightwards pushing hand +1FAF8 1F3FB ; fully-qualified # 🫸🏻 E15.0 rightwards pushing hand: light skin tone +1FAF8 1F3FC ; fully-qualified # 🫸🏼 E15.0 rightwards pushing hand: medium-light skin tone +1FAF8 1F3FD ; fully-qualified # 🫸🏽 E15.0 rightwards pushing hand: medium skin tone +1FAF8 1F3FE ; fully-qualified # 🫸🏾 E15.0 rightwards pushing hand: medium-dark skin tone +1FAF8 1F3FF ; fully-qualified # 🫸🏿 E15.0 rightwards pushing hand: dark skin tone + +# subgroup: hand-fingers-partial +1F44C ; fully-qualified # 👌 E0.6 OK hand +1F44C 1F3FB ; fully-qualified # 👌🏻 E1.0 OK hand: light skin tone +1F44C 1F3FC ; fully-qualified # 👌🏼 E1.0 OK hand: medium-light skin tone +1F44C 1F3FD ; fully-qualified # 👌🏽 E1.0 OK hand: medium skin tone +1F44C 1F3FE ; fully-qualified # 👌🏾 E1.0 OK hand: medium-dark skin tone +1F44C 1F3FF ; fully-qualified # 👌🏿 E1.0 OK hand: dark skin tone +1F90C ; fully-qualified # 🤌 E13.0 pinched fingers +1F90C 1F3FB ; fully-qualified # 🤌🏻 E13.0 pinched fingers: light skin tone +1F90C 1F3FC ; fully-qualified # 🤌🏼 E13.0 pinched fingers: medium-light skin tone +1F90C 1F3FD ; fully-qualified # 🤌🏽 E13.0 pinched fingers: medium skin tone +1F90C 1F3FE ; fully-qualified # 🤌🏾 E13.0 pinched fingers: medium-dark skin tone +1F90C 1F3FF ; fully-qualified # 🤌🏿 E13.0 pinched fingers: dark skin tone +1F90F ; fully-qualified # 🤏 E12.0 pinching hand +1F90F 1F3FB ; fully-qualified # 🤏🏻 E12.0 pinching hand: light skin tone +1F90F 1F3FC ; fully-qualified # 🤏🏼 E12.0 pinching hand: medium-light skin tone +1F90F 1F3FD ; fully-qualified # 🤏🏽 E12.0 pinching hand: medium skin tone +1F90F 1F3FE ; fully-qualified # 🤏🏾 E12.0 pinching hand: medium-dark skin tone +1F90F 1F3FF ; fully-qualified # 🤏🏿 E12.0 pinching hand: dark skin tone +270C FE0F ; fully-qualified # ✌️ E0.6 victory hand +270C ; unqualified # ✌ E0.6 victory hand +270C 1F3FB ; fully-qualified # ✌🏻 E1.0 victory hand: light skin tone +270C 1F3FC ; fully-qualified # ✌🏼 E1.0 victory hand: medium-light skin tone +270C 1F3FD ; fully-qualified # ✌🏽 E1.0 victory hand: medium skin tone +270C 1F3FE ; fully-qualified # ✌🏾 E1.0 victory hand: medium-dark skin tone +270C 1F3FF ; fully-qualified # ✌🏿 E1.0 victory hand: dark skin tone +1F91E ; fully-qualified # 🤞 E3.0 crossed fingers +1F91E 1F3FB ; fully-qualified # 🤞🏻 E3.0 crossed fingers: light skin tone +1F91E 1F3FC ; fully-qualified # 🤞🏼 E3.0 crossed fingers: medium-light skin tone +1F91E 1F3FD ; fully-qualified # 🤞🏽 E3.0 crossed fingers: medium skin tone +1F91E 1F3FE ; fully-qualified # 🤞🏾 E3.0 crossed fingers: medium-dark skin tone +1F91E 1F3FF ; fully-qualified # 🤞🏿 E3.0 crossed fingers: dark skin tone +1FAF0 ; fully-qualified # 🫰 E14.0 hand with index finger and thumb crossed +1FAF0 1F3FB ; fully-qualified # 🫰🏻 E14.0 hand with index finger and thumb crossed: light skin tone +1FAF0 1F3FC ; fully-qualified # 🫰🏼 E14.0 hand with index finger and thumb crossed: medium-light skin tone +1FAF0 1F3FD ; fully-qualified # 🫰🏽 E14.0 hand with index finger and thumb crossed: medium skin tone +1FAF0 1F3FE ; fully-qualified # 🫰🏾 E14.0 hand with index finger and thumb crossed: medium-dark skin tone +1FAF0 1F3FF ; fully-qualified # 🫰🏿 E14.0 hand with index finger and thumb crossed: dark skin tone +1F91F ; fully-qualified # 🤟 E5.0 love-you gesture +1F91F 1F3FB ; fully-qualified # 🤟🏻 E5.0 love-you gesture: light skin tone +1F91F 1F3FC ; fully-qualified # 🤟🏼 E5.0 love-you gesture: medium-light skin tone +1F91F 1F3FD ; fully-qualified # 🤟🏽 E5.0 love-you gesture: medium skin tone +1F91F 1F3FE ; fully-qualified # 🤟🏾 E5.0 love-you gesture: medium-dark skin tone +1F91F 1F3FF ; fully-qualified # 🤟🏿 E5.0 love-you gesture: dark skin tone +1F918 ; fully-qualified # 🤘 E1.0 sign of the horns +1F918 1F3FB ; fully-qualified # 🤘🏻 E1.0 sign of the horns: light skin tone +1F918 1F3FC ; fully-qualified # 🤘🏼 E1.0 sign of the horns: medium-light skin tone +1F918 1F3FD ; fully-qualified # 🤘🏽 E1.0 sign of the horns: medium skin tone +1F918 1F3FE ; fully-qualified # 🤘🏾 E1.0 sign of the horns: medium-dark skin tone +1F918 1F3FF ; fully-qualified # 🤘🏿 E1.0 sign of the horns: dark skin tone +1F919 ; fully-qualified # 🤙 E3.0 call me hand +1F919 1F3FB ; fully-qualified # 🤙🏻 E3.0 call me hand: light skin tone +1F919 1F3FC ; fully-qualified # 🤙🏼 E3.0 call me hand: medium-light skin tone +1F919 1F3FD ; fully-qualified # 🤙🏽 E3.0 call me hand: medium skin tone +1F919 1F3FE ; fully-qualified # 🤙🏾 E3.0 call me hand: medium-dark skin tone +1F919 1F3FF ; fully-qualified # 🤙🏿 E3.0 call me hand: dark skin tone + +# subgroup: hand-single-finger +1F448 ; fully-qualified # 👈 E0.6 backhand index pointing left +1F448 1F3FB ; fully-qualified # 👈🏻 E1.0 backhand index pointing left: light skin tone +1F448 1F3FC ; fully-qualified # 👈🏼 E1.0 backhand index pointing left: medium-light skin tone +1F448 1F3FD ; fully-qualified # 👈🏽 E1.0 backhand index pointing left: medium skin tone +1F448 1F3FE ; fully-qualified # 👈🏾 E1.0 backhand index pointing left: medium-dark skin tone +1F448 1F3FF ; fully-qualified # 👈🏿 E1.0 backhand index pointing left: dark skin tone +1F449 ; fully-qualified # 👉 E0.6 backhand index pointing right +1F449 1F3FB ; fully-qualified # 👉🏻 E1.0 backhand index pointing right: light skin tone +1F449 1F3FC ; fully-qualified # 👉🏼 E1.0 backhand index pointing right: medium-light skin tone +1F449 1F3FD ; fully-qualified # 👉🏽 E1.0 backhand index pointing right: medium skin tone +1F449 1F3FE ; fully-qualified # 👉🏾 E1.0 backhand index pointing right: medium-dark skin tone +1F449 1F3FF ; fully-qualified # 👉🏿 E1.0 backhand index pointing right: dark skin tone +1F446 ; fully-qualified # 👆 E0.6 backhand index pointing up +1F446 1F3FB ; fully-qualified # 👆🏻 E1.0 backhand index pointing up: light skin tone +1F446 1F3FC ; fully-qualified # 👆🏼 E1.0 backhand index pointing up: medium-light skin tone +1F446 1F3FD ; fully-qualified # 👆🏽 E1.0 backhand index pointing up: medium skin tone +1F446 1F3FE ; fully-qualified # 👆🏾 E1.0 backhand index pointing up: medium-dark skin tone +1F446 1F3FF ; fully-qualified # 👆🏿 E1.0 backhand index pointing up: dark skin tone +1F595 ; fully-qualified # 🖕 E1.0 middle finger +1F595 1F3FB ; fully-qualified # 🖕🏻 E1.0 middle finger: light skin tone +1F595 1F3FC ; fully-qualified # 🖕🏼 E1.0 middle finger: medium-light skin tone +1F595 1F3FD ; fully-qualified # 🖕🏽 E1.0 middle finger: medium skin tone +1F595 1F3FE ; fully-qualified # 🖕🏾 E1.0 middle finger: medium-dark skin tone +1F595 1F3FF ; fully-qualified # 🖕🏿 E1.0 middle finger: dark skin tone +1F447 ; fully-qualified # 👇 E0.6 backhand index pointing down +1F447 1F3FB ; fully-qualified # 👇🏻 E1.0 backhand index pointing down: light skin tone +1F447 1F3FC ; fully-qualified # 👇🏼 E1.0 backhand index pointing down: medium-light skin tone +1F447 1F3FD ; fully-qualified # 👇🏽 E1.0 backhand index pointing down: medium skin tone +1F447 1F3FE ; fully-qualified # 👇🏾 E1.0 backhand index pointing down: medium-dark skin tone +1F447 1F3FF ; fully-qualified # 👇🏿 E1.0 backhand index pointing down: dark skin tone +261D FE0F ; fully-qualified # ☝️ E0.6 index pointing up +261D ; unqualified # ☝ E0.6 index pointing up +261D 1F3FB ; fully-qualified # ☝🏻 E1.0 index pointing up: light skin tone +261D 1F3FC ; fully-qualified # ☝🏼 E1.0 index pointing up: medium-light skin tone +261D 1F3FD ; fully-qualified # ☝🏽 E1.0 index pointing up: medium skin tone +261D 1F3FE ; fully-qualified # ☝🏾 E1.0 index pointing up: medium-dark skin tone +261D 1F3FF ; fully-qualified # ☝🏿 E1.0 index pointing up: dark skin tone +1FAF5 ; fully-qualified # 🫵 E14.0 index pointing at the viewer +1FAF5 1F3FB ; fully-qualified # 🫵🏻 E14.0 index pointing at the viewer: light skin tone +1FAF5 1F3FC ; fully-qualified # 🫵🏼 E14.0 index pointing at the viewer: medium-light skin tone +1FAF5 1F3FD ; fully-qualified # 🫵🏽 E14.0 index pointing at the viewer: medium skin tone +1FAF5 1F3FE ; fully-qualified # 🫵🏾 E14.0 index pointing at the viewer: medium-dark skin tone +1FAF5 1F3FF ; fully-qualified # 🫵🏿 E14.0 index pointing at the viewer: dark skin tone + +# subgroup: hand-fingers-closed +1F44D ; fully-qualified # 👍 E0.6 thumbs up +1F44D 1F3FB ; fully-qualified # 👍🏻 E1.0 thumbs up: light skin tone +1F44D 1F3FC ; fully-qualified # 👍🏼 E1.0 thumbs up: medium-light skin tone +1F44D 1F3FD ; fully-qualified # 👍🏽 E1.0 thumbs up: medium skin tone +1F44D 1F3FE ; fully-qualified # 👍🏾 E1.0 thumbs up: medium-dark skin tone +1F44D 1F3FF ; fully-qualified # 👍🏿 E1.0 thumbs up: dark skin tone +1F44E ; fully-qualified # 👎 E0.6 thumbs down +1F44E 1F3FB ; fully-qualified # 👎🏻 E1.0 thumbs down: light skin tone +1F44E 1F3FC ; fully-qualified # 👎🏼 E1.0 thumbs down: medium-light skin tone +1F44E 1F3FD ; fully-qualified # 👎🏽 E1.0 thumbs down: medium skin tone +1F44E 1F3FE ; fully-qualified # 👎🏾 E1.0 thumbs down: medium-dark skin tone +1F44E 1F3FF ; fully-qualified # 👎🏿 E1.0 thumbs down: dark skin tone +270A ; fully-qualified # ✊ E0.6 raised fist +270A 1F3FB ; fully-qualified # ✊🏻 E1.0 raised fist: light skin tone +270A 1F3FC ; fully-qualified # ✊🏼 E1.0 raised fist: medium-light skin tone +270A 1F3FD ; fully-qualified # ✊🏽 E1.0 raised fist: medium skin tone +270A 1F3FE ; fully-qualified # ✊🏾 E1.0 raised fist: medium-dark skin tone +270A 1F3FF ; fully-qualified # ✊🏿 E1.0 raised fist: dark skin tone +1F44A ; fully-qualified # 👊 E0.6 oncoming fist +1F44A 1F3FB ; fully-qualified # 👊🏻 E1.0 oncoming fist: light skin tone +1F44A 1F3FC ; fully-qualified # 👊🏼 E1.0 oncoming fist: medium-light skin tone +1F44A 1F3FD ; fully-qualified # 👊🏽 E1.0 oncoming fist: medium skin tone +1F44A 1F3FE ; fully-qualified # 👊🏾 E1.0 oncoming fist: medium-dark skin tone +1F44A 1F3FF ; fully-qualified # 👊🏿 E1.0 oncoming fist: dark skin tone +1F91B ; fully-qualified # 🤛 E3.0 left-facing fist +1F91B 1F3FB ; fully-qualified # 🤛🏻 E3.0 left-facing fist: light skin tone +1F91B 1F3FC ; fully-qualified # 🤛🏼 E3.0 left-facing fist: medium-light skin tone +1F91B 1F3FD ; fully-qualified # 🤛🏽 E3.0 left-facing fist: medium skin tone +1F91B 1F3FE ; fully-qualified # 🤛🏾 E3.0 left-facing fist: medium-dark skin tone +1F91B 1F3FF ; fully-qualified # 🤛🏿 E3.0 left-facing fist: dark skin tone +1F91C ; fully-qualified # 🤜 E3.0 right-facing fist +1F91C 1F3FB ; fully-qualified # 🤜🏻 E3.0 right-facing fist: light skin tone +1F91C 1F3FC ; fully-qualified # 🤜🏼 E3.0 right-facing fist: medium-light skin tone +1F91C 1F3FD ; fully-qualified # 🤜🏽 E3.0 right-facing fist: medium skin tone +1F91C 1F3FE ; fully-qualified # 🤜🏾 E3.0 right-facing fist: medium-dark skin tone +1F91C 1F3FF ; fully-qualified # 🤜🏿 E3.0 right-facing fist: dark skin tone + +# subgroup: hands +1F44F ; fully-qualified # 👏 E0.6 clapping hands +1F44F 1F3FB ; fully-qualified # 👏🏻 E1.0 clapping hands: light skin tone +1F44F 1F3FC ; fully-qualified # 👏🏼 E1.0 clapping hands: medium-light skin tone +1F44F 1F3FD ; fully-qualified # 👏🏽 E1.0 clapping hands: medium skin tone +1F44F 1F3FE ; fully-qualified # 👏🏾 E1.0 clapping hands: medium-dark skin tone +1F44F 1F3FF ; fully-qualified # 👏🏿 E1.0 clapping hands: dark skin tone +1F64C ; fully-qualified # 🙌 E0.6 raising hands +1F64C 1F3FB ; fully-qualified # 🙌🏻 E1.0 raising hands: light skin tone +1F64C 1F3FC ; fully-qualified # 🙌🏼 E1.0 raising hands: medium-light skin tone +1F64C 1F3FD ; fully-qualified # 🙌🏽 E1.0 raising hands: medium skin tone +1F64C 1F3FE ; fully-qualified # 🙌🏾 E1.0 raising hands: medium-dark skin tone +1F64C 1F3FF ; fully-qualified # 🙌🏿 E1.0 raising hands: dark skin tone +1FAF6 ; fully-qualified # 🫶 E14.0 heart hands +1FAF6 1F3FB ; fully-qualified # 🫶🏻 E14.0 heart hands: light skin tone +1FAF6 1F3FC ; fully-qualified # 🫶🏼 E14.0 heart hands: medium-light skin tone +1FAF6 1F3FD ; fully-qualified # 🫶🏽 E14.0 heart hands: medium skin tone +1FAF6 1F3FE ; fully-qualified # 🫶🏾 E14.0 heart hands: medium-dark skin tone +1FAF6 1F3FF ; fully-qualified # 🫶🏿 E14.0 heart hands: dark skin tone +1F450 ; fully-qualified # 👐 E0.6 open hands +1F450 1F3FB ; fully-qualified # 👐🏻 E1.0 open hands: light skin tone +1F450 1F3FC ; fully-qualified # 👐🏼 E1.0 open hands: medium-light skin tone +1F450 1F3FD ; fully-qualified # 👐🏽 E1.0 open hands: medium skin tone +1F450 1F3FE ; fully-qualified # 👐🏾 E1.0 open hands: medium-dark skin tone +1F450 1F3FF ; fully-qualified # 👐🏿 E1.0 open hands: dark skin tone +1F932 ; fully-qualified # 🤲 E5.0 palms up together +1F932 1F3FB ; fully-qualified # 🤲🏻 E5.0 palms up together: light skin tone +1F932 1F3FC ; fully-qualified # 🤲🏼 E5.0 palms up together: medium-light skin tone +1F932 1F3FD ; fully-qualified # 🤲🏽 E5.0 palms up together: medium skin tone +1F932 1F3FE ; fully-qualified # 🤲🏾 E5.0 palms up together: medium-dark skin tone +1F932 1F3FF ; fully-qualified # 🤲🏿 E5.0 palms up together: dark skin tone +1F91D ; fully-qualified # 🤝 E3.0 handshake +1F91D 1F3FB ; fully-qualified # 🤝🏻 E14.0 handshake: light skin tone +1F91D 1F3FC ; fully-qualified # 🤝🏼 E14.0 handshake: medium-light skin tone +1F91D 1F3FD ; fully-qualified # 🤝🏽 E14.0 handshake: medium skin tone +1F91D 1F3FE ; fully-qualified # 🤝🏾 E14.0 handshake: medium-dark skin tone +1F91D 1F3FF ; fully-qualified # 🤝🏿 E14.0 handshake: dark skin tone +1FAF1 1F3FB 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏻‍🫲🏼 E14.0 handshake: light skin tone, medium-light skin tone +1FAF1 1F3FB 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏻‍🫲🏽 E14.0 handshake: light skin tone, medium skin tone +1FAF1 1F3FB 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏻‍🫲🏾 E14.0 handshake: light skin tone, medium-dark skin tone +1FAF1 1F3FB 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏻‍🫲🏿 E14.0 handshake: light skin tone, dark skin tone +1FAF1 1F3FC 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏼‍🫲🏻 E14.0 handshake: medium-light skin tone, light skin tone +1FAF1 1F3FC 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏼‍🫲🏽 E14.0 handshake: medium-light skin tone, medium skin tone +1FAF1 1F3FC 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏼‍🫲🏾 E14.0 handshake: medium-light skin tone, medium-dark skin tone +1FAF1 1F3FC 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏼‍🫲🏿 E14.0 handshake: medium-light skin tone, dark skin tone +1FAF1 1F3FD 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏽‍🫲🏻 E14.0 handshake: medium skin tone, light skin tone +1FAF1 1F3FD 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏽‍🫲🏼 E14.0 handshake: medium skin tone, medium-light skin tone +1FAF1 1F3FD 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏽‍🫲🏾 E14.0 handshake: medium skin tone, medium-dark skin tone +1FAF1 1F3FD 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏽‍🫲🏿 E14.0 handshake: medium skin tone, dark skin tone +1FAF1 1F3FE 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏾‍🫲🏻 E14.0 handshake: medium-dark skin tone, light skin tone +1FAF1 1F3FE 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏾‍🫲🏼 E14.0 handshake: medium-dark skin tone, medium-light skin tone +1FAF1 1F3FE 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏾‍🫲🏽 E14.0 handshake: medium-dark skin tone, medium skin tone +1FAF1 1F3FE 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏾‍🫲🏿 E14.0 handshake: medium-dark skin tone, dark skin tone +1FAF1 1F3FF 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏿‍🫲🏻 E14.0 handshake: dark skin tone, light skin tone +1FAF1 1F3FF 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏿‍🫲🏼 E14.0 handshake: dark skin tone, medium-light skin tone +1FAF1 1F3FF 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏿‍🫲🏽 E14.0 handshake: dark skin tone, medium skin tone +1FAF1 1F3FF 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏿‍🫲🏾 E14.0 handshake: dark skin tone, medium-dark skin tone +1F64F ; fully-qualified # 🙏 E0.6 folded hands +1F64F 1F3FB ; fully-qualified # 🙏🏻 E1.0 folded hands: light skin tone +1F64F 1F3FC ; fully-qualified # 🙏🏼 E1.0 folded hands: medium-light skin tone +1F64F 1F3FD ; fully-qualified # 🙏🏽 E1.0 folded hands: medium skin tone +1F64F 1F3FE ; fully-qualified # 🙏🏾 E1.0 folded hands: medium-dark skin tone +1F64F 1F3FF ; fully-qualified # 🙏🏿 E1.0 folded hands: dark skin tone + +# subgroup: hand-prop +270D FE0F ; fully-qualified # ✍️ E0.7 writing hand +270D ; unqualified # ✍ E0.7 writing hand +270D 1F3FB ; fully-qualified # ✍🏻 E1.0 writing hand: light skin tone +270D 1F3FC ; fully-qualified # ✍🏼 E1.0 writing hand: medium-light skin tone +270D 1F3FD ; fully-qualified # ✍🏽 E1.0 writing hand: medium skin tone +270D 1F3FE ; fully-qualified # ✍🏾 E1.0 writing hand: medium-dark skin tone +270D 1F3FF ; fully-qualified # ✍🏿 E1.0 writing hand: dark skin tone +1F485 ; fully-qualified # 💅 E0.6 nail polish +1F485 1F3FB ; fully-qualified # 💅🏻 E1.0 nail polish: light skin tone +1F485 1F3FC ; fully-qualified # 💅🏼 E1.0 nail polish: medium-light skin tone +1F485 1F3FD ; fully-qualified # 💅🏽 E1.0 nail polish: medium skin tone +1F485 1F3FE ; fully-qualified # 💅🏾 E1.0 nail polish: medium-dark skin tone +1F485 1F3FF ; fully-qualified # 💅🏿 E1.0 nail polish: dark skin tone +1F933 ; fully-qualified # 🤳 E3.0 selfie +1F933 1F3FB ; fully-qualified # 🤳🏻 E3.0 selfie: light skin tone +1F933 1F3FC ; fully-qualified # 🤳🏼 E3.0 selfie: medium-light skin tone +1F933 1F3FD ; fully-qualified # 🤳🏽 E3.0 selfie: medium skin tone +1F933 1F3FE ; fully-qualified # 🤳🏾 E3.0 selfie: medium-dark skin tone +1F933 1F3FF ; fully-qualified # 🤳🏿 E3.0 selfie: dark skin tone + +# subgroup: body-parts +1F4AA ; fully-qualified # 💪 E0.6 flexed biceps +1F4AA 1F3FB ; fully-qualified # 💪🏻 E1.0 flexed biceps: light skin tone +1F4AA 1F3FC ; fully-qualified # 💪🏼 E1.0 flexed biceps: medium-light skin tone +1F4AA 1F3FD ; fully-qualified # 💪🏽 E1.0 flexed biceps: medium skin tone +1F4AA 1F3FE ; fully-qualified # 💪🏾 E1.0 flexed biceps: medium-dark skin tone +1F4AA 1F3FF ; fully-qualified # 💪🏿 E1.0 flexed biceps: dark skin tone +1F9BE ; fully-qualified # 🦾 E12.0 mechanical arm +1F9BF ; fully-qualified # 🦿 E12.0 mechanical leg +1F9B5 ; fully-qualified # 🦵 E11.0 leg +1F9B5 1F3FB ; fully-qualified # 🦵🏻 E11.0 leg: light skin tone +1F9B5 1F3FC ; fully-qualified # 🦵🏼 E11.0 leg: medium-light skin tone +1F9B5 1F3FD ; fully-qualified # 🦵🏽 E11.0 leg: medium skin tone +1F9B5 1F3FE ; fully-qualified # 🦵🏾 E11.0 leg: medium-dark skin tone +1F9B5 1F3FF ; fully-qualified # 🦵🏿 E11.0 leg: dark skin tone +1F9B6 ; fully-qualified # 🦶 E11.0 foot +1F9B6 1F3FB ; fully-qualified # 🦶🏻 E11.0 foot: light skin tone +1F9B6 1F3FC ; fully-qualified # 🦶🏼 E11.0 foot: medium-light skin tone +1F9B6 1F3FD ; fully-qualified # 🦶🏽 E11.0 foot: medium skin tone +1F9B6 1F3FE ; fully-qualified # 🦶🏾 E11.0 foot: medium-dark skin tone +1F9B6 1F3FF ; fully-qualified # 🦶🏿 E11.0 foot: dark skin tone +1F442 ; fully-qualified # 👂 E0.6 ear +1F442 1F3FB ; fully-qualified # 👂🏻 E1.0 ear: light skin tone +1F442 1F3FC ; fully-qualified # 👂🏼 E1.0 ear: medium-light skin tone +1F442 1F3FD ; fully-qualified # 👂🏽 E1.0 ear: medium skin tone +1F442 1F3FE ; fully-qualified # 👂🏾 E1.0 ear: medium-dark skin tone +1F442 1F3FF ; fully-qualified # 👂🏿 E1.0 ear: dark skin tone +1F9BB ; fully-qualified # 🦻 E12.0 ear with hearing aid +1F9BB 1F3FB ; fully-qualified # 🦻🏻 E12.0 ear with hearing aid: light skin tone +1F9BB 1F3FC ; fully-qualified # 🦻🏼 E12.0 ear with hearing aid: medium-light skin tone +1F9BB 1F3FD ; fully-qualified # 🦻🏽 E12.0 ear with hearing aid: medium skin tone +1F9BB 1F3FE ; fully-qualified # 🦻🏾 E12.0 ear with hearing aid: medium-dark skin tone +1F9BB 1F3FF ; fully-qualified # 🦻🏿 E12.0 ear with hearing aid: dark skin tone +1F443 ; fully-qualified # 👃 E0.6 nose +1F443 1F3FB ; fully-qualified # 👃🏻 E1.0 nose: light skin tone +1F443 1F3FC ; fully-qualified # 👃🏼 E1.0 nose: medium-light skin tone +1F443 1F3FD ; fully-qualified # 👃🏽 E1.0 nose: medium skin tone +1F443 1F3FE ; fully-qualified # 👃🏾 E1.0 nose: medium-dark skin tone +1F443 1F3FF ; fully-qualified # 👃🏿 E1.0 nose: dark skin tone +1F9E0 ; fully-qualified # 🧠 E5.0 brain +1FAC0 ; fully-qualified # 🫀 E13.0 anatomical heart +1FAC1 ; fully-qualified # 🫁 E13.0 lungs +1F9B7 ; fully-qualified # 🦷 E11.0 tooth +1F9B4 ; fully-qualified # 🦴 E11.0 bone +1F440 ; fully-qualified # 👀 E0.6 eyes +1F441 FE0F ; fully-qualified # 👁️ E0.7 eye +1F441 ; unqualified # 👁 E0.7 eye +1F445 ; fully-qualified # 👅 E0.6 tongue +1F444 ; fully-qualified # 👄 E0.6 mouth +1FAE6 ; fully-qualified # 🫦 E14.0 biting lip + +# subgroup: person +1F476 ; fully-qualified # 👶 E0.6 baby +1F476 1F3FB ; fully-qualified # 👶🏻 E1.0 baby: light skin tone +1F476 1F3FC ; fully-qualified # 👶🏼 E1.0 baby: medium-light skin tone +1F476 1F3FD ; fully-qualified # 👶🏽 E1.0 baby: medium skin tone +1F476 1F3FE ; fully-qualified # 👶🏾 E1.0 baby: medium-dark skin tone +1F476 1F3FF ; fully-qualified # 👶🏿 E1.0 baby: dark skin tone +1F9D2 ; fully-qualified # 🧒 E5.0 child +1F9D2 1F3FB ; fully-qualified # 🧒🏻 E5.0 child: light skin tone +1F9D2 1F3FC ; fully-qualified # 🧒🏼 E5.0 child: medium-light skin tone +1F9D2 1F3FD ; fully-qualified # 🧒🏽 E5.0 child: medium skin tone +1F9D2 1F3FE ; fully-qualified # 🧒🏾 E5.0 child: medium-dark skin tone +1F9D2 1F3FF ; fully-qualified # 🧒🏿 E5.0 child: dark skin tone +1F466 ; fully-qualified # 👦 E0.6 boy +1F466 1F3FB ; fully-qualified # 👦🏻 E1.0 boy: light skin tone +1F466 1F3FC ; fully-qualified # 👦🏼 E1.0 boy: medium-light skin tone +1F466 1F3FD ; fully-qualified # 👦🏽 E1.0 boy: medium skin tone +1F466 1F3FE ; fully-qualified # 👦🏾 E1.0 boy: medium-dark skin tone +1F466 1F3FF ; fully-qualified # 👦🏿 E1.0 boy: dark skin tone +1F467 ; fully-qualified # 👧 E0.6 girl +1F467 1F3FB ; fully-qualified # 👧🏻 E1.0 girl: light skin tone +1F467 1F3FC ; fully-qualified # 👧🏼 E1.0 girl: medium-light skin tone +1F467 1F3FD ; fully-qualified # 👧🏽 E1.0 girl: medium skin tone +1F467 1F3FE ; fully-qualified # 👧🏾 E1.0 girl: medium-dark skin tone +1F467 1F3FF ; fully-qualified # 👧🏿 E1.0 girl: dark skin tone +1F9D1 ; fully-qualified # 🧑 E5.0 person +1F9D1 1F3FB ; fully-qualified # 🧑🏻 E5.0 person: light skin tone +1F9D1 1F3FC ; fully-qualified # 🧑🏼 E5.0 person: medium-light skin tone +1F9D1 1F3FD ; fully-qualified # 🧑🏽 E5.0 person: medium skin tone +1F9D1 1F3FE ; fully-qualified # 🧑🏾 E5.0 person: medium-dark skin tone +1F9D1 1F3FF ; fully-qualified # 🧑🏿 E5.0 person: dark skin tone +1F471 ; fully-qualified # 👱 E0.6 person: blond hair +1F471 1F3FB ; fully-qualified # 👱🏻 E1.0 person: light skin tone, blond hair +1F471 1F3FC ; fully-qualified # 👱🏼 E1.0 person: medium-light skin tone, blond hair +1F471 1F3FD ; fully-qualified # 👱🏽 E1.0 person: medium skin tone, blond hair +1F471 1F3FE ; fully-qualified # 👱🏾 E1.0 person: medium-dark skin tone, blond hair +1F471 1F3FF ; fully-qualified # 👱🏿 E1.0 person: dark skin tone, blond hair +1F468 ; fully-qualified # 👨 E0.6 man +1F468 1F3FB ; fully-qualified # 👨🏻 E1.0 man: light skin tone +1F468 1F3FC ; fully-qualified # 👨🏼 E1.0 man: medium-light skin tone +1F468 1F3FD ; fully-qualified # 👨🏽 E1.0 man: medium skin tone +1F468 1F3FE ; fully-qualified # 👨🏾 E1.0 man: medium-dark skin tone +1F468 1F3FF ; fully-qualified # 👨🏿 E1.0 man: dark skin tone +1F9D4 ; fully-qualified # 🧔 E5.0 person: beard +1F9D4 1F3FB ; fully-qualified # 🧔🏻 E5.0 person: light skin tone, beard +1F9D4 1F3FC ; fully-qualified # 🧔🏼 E5.0 person: medium-light skin tone, beard +1F9D4 1F3FD ; fully-qualified # 🧔🏽 E5.0 person: medium skin tone, beard +1F9D4 1F3FE ; fully-qualified # 🧔🏾 E5.0 person: medium-dark skin tone, beard +1F9D4 1F3FF ; fully-qualified # 🧔🏿 E5.0 person: dark skin tone, beard +1F9D4 200D 2642 FE0F ; fully-qualified # 🧔‍♂️ E13.1 man: beard +1F9D4 200D 2642 ; minimally-qualified # 🧔‍♂ E13.1 man: beard +1F9D4 1F3FB 200D 2642 FE0F ; fully-qualified # 🧔🏻‍♂️ E13.1 man: light skin tone, beard +1F9D4 1F3FB 200D 2642 ; minimally-qualified # 🧔🏻‍♂ E13.1 man: light skin tone, beard +1F9D4 1F3FC 200D 2642 FE0F ; fully-qualified # 🧔🏼‍♂️ E13.1 man: medium-light skin tone, beard +1F9D4 1F3FC 200D 2642 ; minimally-qualified # 🧔🏼‍♂ E13.1 man: medium-light skin tone, beard +1F9D4 1F3FD 200D 2642 FE0F ; fully-qualified # 🧔🏽‍♂️ E13.1 man: medium skin tone, beard +1F9D4 1F3FD 200D 2642 ; minimally-qualified # 🧔🏽‍♂ E13.1 man: medium skin tone, beard +1F9D4 1F3FE 200D 2642 FE0F ; fully-qualified # 🧔🏾‍♂️ E13.1 man: medium-dark skin tone, beard +1F9D4 1F3FE 200D 2642 ; minimally-qualified # 🧔🏾‍♂ E13.1 man: medium-dark skin tone, beard +1F9D4 1F3FF 200D 2642 FE0F ; fully-qualified # 🧔🏿‍♂️ E13.1 man: dark skin tone, beard +1F9D4 1F3FF 200D 2642 ; minimally-qualified # 🧔🏿‍♂ E13.1 man: dark skin tone, beard +1F9D4 200D 2640 FE0F ; fully-qualified # 🧔‍♀️ E13.1 woman: beard +1F9D4 200D 2640 ; minimally-qualified # 🧔‍♀ E13.1 woman: beard +1F9D4 1F3FB 200D 2640 FE0F ; fully-qualified # 🧔🏻‍♀️ E13.1 woman: light skin tone, beard +1F9D4 1F3FB 200D 2640 ; minimally-qualified # 🧔🏻‍♀ E13.1 woman: light skin tone, beard +1F9D4 1F3FC 200D 2640 FE0F ; fully-qualified # 🧔🏼‍♀️ E13.1 woman: medium-light skin tone, beard +1F9D4 1F3FC 200D 2640 ; minimally-qualified # 🧔🏼‍♀ E13.1 woman: medium-light skin tone, beard +1F9D4 1F3FD 200D 2640 FE0F ; fully-qualified # 🧔🏽‍♀️ E13.1 woman: medium skin tone, beard +1F9D4 1F3FD 200D 2640 ; minimally-qualified # 🧔🏽‍♀ E13.1 woman: medium skin tone, beard +1F9D4 1F3FE 200D 2640 FE0F ; fully-qualified # 🧔🏾‍♀️ E13.1 woman: medium-dark skin tone, beard +1F9D4 1F3FE 200D 2640 ; minimally-qualified # 🧔🏾‍♀ E13.1 woman: medium-dark skin tone, beard +1F9D4 1F3FF 200D 2640 FE0F ; fully-qualified # 🧔🏿‍♀️ E13.1 woman: dark skin tone, beard +1F9D4 1F3FF 200D 2640 ; minimally-qualified # 🧔🏿‍♀ E13.1 woman: dark skin tone, beard +1F468 200D 1F9B0 ; fully-qualified # 👨‍🦰 E11.0 man: red hair +1F468 1F3FB 200D 1F9B0 ; fully-qualified # 👨🏻‍🦰 E11.0 man: light skin tone, red hair +1F468 1F3FC 200D 1F9B0 ; fully-qualified # 👨🏼‍🦰 E11.0 man: medium-light skin tone, red hair +1F468 1F3FD 200D 1F9B0 ; fully-qualified # 👨🏽‍🦰 E11.0 man: medium skin tone, red hair +1F468 1F3FE 200D 1F9B0 ; fully-qualified # 👨🏾‍🦰 E11.0 man: medium-dark skin tone, red hair +1F468 1F3FF 200D 1F9B0 ; fully-qualified # 👨🏿‍🦰 E11.0 man: dark skin tone, red hair +1F468 200D 1F9B1 ; fully-qualified # 👨‍🦱 E11.0 man: curly hair +1F468 1F3FB 200D 1F9B1 ; fully-qualified # 👨🏻‍🦱 E11.0 man: light skin tone, curly hair +1F468 1F3FC 200D 1F9B1 ; fully-qualified # 👨🏼‍🦱 E11.0 man: medium-light skin tone, curly hair +1F468 1F3FD 200D 1F9B1 ; fully-qualified # 👨🏽‍🦱 E11.0 man: medium skin tone, curly hair +1F468 1F3FE 200D 1F9B1 ; fully-qualified # 👨🏾‍🦱 E11.0 man: medium-dark skin tone, curly hair +1F468 1F3FF 200D 1F9B1 ; fully-qualified # 👨🏿‍🦱 E11.0 man: dark skin tone, curly hair +1F468 200D 1F9B3 ; fully-qualified # 👨‍🦳 E11.0 man: white hair +1F468 1F3FB 200D 1F9B3 ; fully-qualified # 👨🏻‍🦳 E11.0 man: light skin tone, white hair +1F468 1F3FC 200D 1F9B3 ; fully-qualified # 👨🏼‍🦳 E11.0 man: medium-light skin tone, white hair +1F468 1F3FD 200D 1F9B3 ; fully-qualified # 👨🏽‍🦳 E11.0 man: medium skin tone, white hair +1F468 1F3FE 200D 1F9B3 ; fully-qualified # 👨🏾‍🦳 E11.0 man: medium-dark skin tone, white hair +1F468 1F3FF 200D 1F9B3 ; fully-qualified # 👨🏿‍🦳 E11.0 man: dark skin tone, white hair +1F468 200D 1F9B2 ; fully-qualified # 👨‍🦲 E11.0 man: bald +1F468 1F3FB 200D 1F9B2 ; fully-qualified # 👨🏻‍🦲 E11.0 man: light skin tone, bald +1F468 1F3FC 200D 1F9B2 ; fully-qualified # 👨🏼‍🦲 E11.0 man: medium-light skin tone, bald +1F468 1F3FD 200D 1F9B2 ; fully-qualified # 👨🏽‍🦲 E11.0 man: medium skin tone, bald +1F468 1F3FE 200D 1F9B2 ; fully-qualified # 👨🏾‍🦲 E11.0 man: medium-dark skin tone, bald +1F468 1F3FF 200D 1F9B2 ; fully-qualified # 👨🏿‍🦲 E11.0 man: dark skin tone, bald +1F469 ; fully-qualified # 👩 E0.6 woman +1F469 1F3FB ; fully-qualified # 👩🏻 E1.0 woman: light skin tone +1F469 1F3FC ; fully-qualified # 👩🏼 E1.0 woman: medium-light skin tone +1F469 1F3FD ; fully-qualified # 👩🏽 E1.0 woman: medium skin tone +1F469 1F3FE ; fully-qualified # 👩🏾 E1.0 woman: medium-dark skin tone +1F469 1F3FF ; fully-qualified # 👩🏿 E1.0 woman: dark skin tone +1F469 200D 1F9B0 ; fully-qualified # 👩‍🦰 E11.0 woman: red hair +1F469 1F3FB 200D 1F9B0 ; fully-qualified # 👩🏻‍🦰 E11.0 woman: light skin tone, red hair +1F469 1F3FC 200D 1F9B0 ; fully-qualified # 👩🏼‍🦰 E11.0 woman: medium-light skin tone, red hair +1F469 1F3FD 200D 1F9B0 ; fully-qualified # 👩🏽‍🦰 E11.0 woman: medium skin tone, red hair +1F469 1F3FE 200D 1F9B0 ; fully-qualified # 👩🏾‍🦰 E11.0 woman: medium-dark skin tone, red hair +1F469 1F3FF 200D 1F9B0 ; fully-qualified # 👩🏿‍🦰 E11.0 woman: dark skin tone, red hair +1F9D1 200D 1F9B0 ; fully-qualified # 🧑‍🦰 E12.1 person: red hair +1F9D1 1F3FB 200D 1F9B0 ; fully-qualified # 🧑🏻‍🦰 E12.1 person: light skin tone, red hair +1F9D1 1F3FC 200D 1F9B0 ; fully-qualified # 🧑🏼‍🦰 E12.1 person: medium-light skin tone, red hair +1F9D1 1F3FD 200D 1F9B0 ; fully-qualified # 🧑🏽‍🦰 E12.1 person: medium skin tone, red hair +1F9D1 1F3FE 200D 1F9B0 ; fully-qualified # 🧑🏾‍🦰 E12.1 person: medium-dark skin tone, red hair +1F9D1 1F3FF 200D 1F9B0 ; fully-qualified # 🧑🏿‍🦰 E12.1 person: dark skin tone, red hair +1F469 200D 1F9B1 ; fully-qualified # 👩‍🦱 E11.0 woman: curly hair +1F469 1F3FB 200D 1F9B1 ; fully-qualified # 👩🏻‍🦱 E11.0 woman: light skin tone, curly hair +1F469 1F3FC 200D 1F9B1 ; fully-qualified # 👩🏼‍🦱 E11.0 woman: medium-light skin tone, curly hair +1F469 1F3FD 200D 1F9B1 ; fully-qualified # 👩🏽‍🦱 E11.0 woman: medium skin tone, curly hair +1F469 1F3FE 200D 1F9B1 ; fully-qualified # 👩🏾‍🦱 E11.0 woman: medium-dark skin tone, curly hair +1F469 1F3FF 200D 1F9B1 ; fully-qualified # 👩🏿‍🦱 E11.0 woman: dark skin tone, curly hair +1F9D1 200D 1F9B1 ; fully-qualified # 🧑‍🦱 E12.1 person: curly hair +1F9D1 1F3FB 200D 1F9B1 ; fully-qualified # 🧑🏻‍🦱 E12.1 person: light skin tone, curly hair +1F9D1 1F3FC 200D 1F9B1 ; fully-qualified # 🧑🏼‍🦱 E12.1 person: medium-light skin tone, curly hair +1F9D1 1F3FD 200D 1F9B1 ; fully-qualified # 🧑🏽‍🦱 E12.1 person: medium skin tone, curly hair +1F9D1 1F3FE 200D 1F9B1 ; fully-qualified # 🧑🏾‍🦱 E12.1 person: medium-dark skin tone, curly hair +1F9D1 1F3FF 200D 1F9B1 ; fully-qualified # 🧑🏿‍🦱 E12.1 person: dark skin tone, curly hair +1F469 200D 1F9B3 ; fully-qualified # 👩‍🦳 E11.0 woman: white hair +1F469 1F3FB 200D 1F9B3 ; fully-qualified # 👩🏻‍🦳 E11.0 woman: light skin tone, white hair +1F469 1F3FC 200D 1F9B3 ; fully-qualified # 👩🏼‍🦳 E11.0 woman: medium-light skin tone, white hair +1F469 1F3FD 200D 1F9B3 ; fully-qualified # 👩🏽‍🦳 E11.0 woman: medium skin tone, white hair +1F469 1F3FE 200D 1F9B3 ; fully-qualified # 👩🏾‍🦳 E11.0 woman: medium-dark skin tone, white hair +1F469 1F3FF 200D 1F9B3 ; fully-qualified # 👩🏿‍🦳 E11.0 woman: dark skin tone, white hair +1F9D1 200D 1F9B3 ; fully-qualified # 🧑‍🦳 E12.1 person: white hair +1F9D1 1F3FB 200D 1F9B3 ; fully-qualified # 🧑🏻‍🦳 E12.1 person: light skin tone, white hair +1F9D1 1F3FC 200D 1F9B3 ; fully-qualified # 🧑🏼‍🦳 E12.1 person: medium-light skin tone, white hair +1F9D1 1F3FD 200D 1F9B3 ; fully-qualified # 🧑🏽‍🦳 E12.1 person: medium skin tone, white hair +1F9D1 1F3FE 200D 1F9B3 ; fully-qualified # 🧑🏾‍🦳 E12.1 person: medium-dark skin tone, white hair +1F9D1 1F3FF 200D 1F9B3 ; fully-qualified # 🧑🏿‍🦳 E12.1 person: dark skin tone, white hair +1F469 200D 1F9B2 ; fully-qualified # 👩‍🦲 E11.0 woman: bald +1F469 1F3FB 200D 1F9B2 ; fully-qualified # 👩🏻‍🦲 E11.0 woman: light skin tone, bald +1F469 1F3FC 200D 1F9B2 ; fully-qualified # 👩🏼‍🦲 E11.0 woman: medium-light skin tone, bald +1F469 1F3FD 200D 1F9B2 ; fully-qualified # 👩🏽‍🦲 E11.0 woman: medium skin tone, bald +1F469 1F3FE 200D 1F9B2 ; fully-qualified # 👩🏾‍🦲 E11.0 woman: medium-dark skin tone, bald +1F469 1F3FF 200D 1F9B2 ; fully-qualified # 👩🏿‍🦲 E11.0 woman: dark skin tone, bald +1F9D1 200D 1F9B2 ; fully-qualified # 🧑‍🦲 E12.1 person: bald +1F9D1 1F3FB 200D 1F9B2 ; fully-qualified # 🧑🏻‍🦲 E12.1 person: light skin tone, bald +1F9D1 1F3FC 200D 1F9B2 ; fully-qualified # 🧑🏼‍🦲 E12.1 person: medium-light skin tone, bald +1F9D1 1F3FD 200D 1F9B2 ; fully-qualified # 🧑🏽‍🦲 E12.1 person: medium skin tone, bald +1F9D1 1F3FE 200D 1F9B2 ; fully-qualified # 🧑🏾‍🦲 E12.1 person: medium-dark skin tone, bald +1F9D1 1F3FF 200D 1F9B2 ; fully-qualified # 🧑🏿‍🦲 E12.1 person: dark skin tone, bald +1F471 200D 2640 FE0F ; fully-qualified # 👱‍♀️ E4.0 woman: blond hair +1F471 200D 2640 ; minimally-qualified # 👱‍♀ E4.0 woman: blond hair +1F471 1F3FB 200D 2640 FE0F ; fully-qualified # 👱🏻‍♀️ E4.0 woman: light skin tone, blond hair +1F471 1F3FB 200D 2640 ; minimally-qualified # 👱🏻‍♀ E4.0 woman: light skin tone, blond hair +1F471 1F3FC 200D 2640 FE0F ; fully-qualified # 👱🏼‍♀️ E4.0 woman: medium-light skin tone, blond hair +1F471 1F3FC 200D 2640 ; minimally-qualified # 👱🏼‍♀ E4.0 woman: medium-light skin tone, blond hair +1F471 1F3FD 200D 2640 FE0F ; fully-qualified # 👱🏽‍♀️ E4.0 woman: medium skin tone, blond hair +1F471 1F3FD 200D 2640 ; minimally-qualified # 👱🏽‍♀ E4.0 woman: medium skin tone, blond hair +1F471 1F3FE 200D 2640 FE0F ; fully-qualified # 👱🏾‍♀️ E4.0 woman: medium-dark skin tone, blond hair +1F471 1F3FE 200D 2640 ; minimally-qualified # 👱🏾‍♀ E4.0 woman: medium-dark skin tone, blond hair +1F471 1F3FF 200D 2640 FE0F ; fully-qualified # 👱🏿‍♀️ E4.0 woman: dark skin tone, blond hair +1F471 1F3FF 200D 2640 ; minimally-qualified # 👱🏿‍♀ E4.0 woman: dark skin tone, blond hair +1F471 200D 2642 FE0F ; fully-qualified # 👱‍♂️ E4.0 man: blond hair +1F471 200D 2642 ; minimally-qualified # 👱‍♂ E4.0 man: blond hair +1F471 1F3FB 200D 2642 FE0F ; fully-qualified # 👱🏻‍♂️ E4.0 man: light skin tone, blond hair +1F471 1F3FB 200D 2642 ; minimally-qualified # 👱🏻‍♂ E4.0 man: light skin tone, blond hair +1F471 1F3FC 200D 2642 FE0F ; fully-qualified # 👱🏼‍♂️ E4.0 man: medium-light skin tone, blond hair +1F471 1F3FC 200D 2642 ; minimally-qualified # 👱🏼‍♂ E4.0 man: medium-light skin tone, blond hair +1F471 1F3FD 200D 2642 FE0F ; fully-qualified # 👱🏽‍♂️ E4.0 man: medium skin tone, blond hair +1F471 1F3FD 200D 2642 ; minimally-qualified # 👱🏽‍♂ E4.0 man: medium skin tone, blond hair +1F471 1F3FE 200D 2642 FE0F ; fully-qualified # 👱🏾‍♂️ E4.0 man: medium-dark skin tone, blond hair +1F471 1F3FE 200D 2642 ; minimally-qualified # 👱🏾‍♂ E4.0 man: medium-dark skin tone, blond hair +1F471 1F3FF 200D 2642 FE0F ; fully-qualified # 👱🏿‍♂️ E4.0 man: dark skin tone, blond hair +1F471 1F3FF 200D 2642 ; minimally-qualified # 👱🏿‍♂ E4.0 man: dark skin tone, blond hair +1F9D3 ; fully-qualified # 🧓 E5.0 older person +1F9D3 1F3FB ; fully-qualified # 🧓🏻 E5.0 older person: light skin tone +1F9D3 1F3FC ; fully-qualified # 🧓🏼 E5.0 older person: medium-light skin tone +1F9D3 1F3FD ; fully-qualified # 🧓🏽 E5.0 older person: medium skin tone +1F9D3 1F3FE ; fully-qualified # 🧓🏾 E5.0 older person: medium-dark skin tone +1F9D3 1F3FF ; fully-qualified # 🧓🏿 E5.0 older person: dark skin tone +1F474 ; fully-qualified # 👴 E0.6 old man +1F474 1F3FB ; fully-qualified # 👴🏻 E1.0 old man: light skin tone +1F474 1F3FC ; fully-qualified # 👴🏼 E1.0 old man: medium-light skin tone +1F474 1F3FD ; fully-qualified # 👴🏽 E1.0 old man: medium skin tone +1F474 1F3FE ; fully-qualified # 👴🏾 E1.0 old man: medium-dark skin tone +1F474 1F3FF ; fully-qualified # 👴🏿 E1.0 old man: dark skin tone +1F475 ; fully-qualified # 👵 E0.6 old woman +1F475 1F3FB ; fully-qualified # 👵🏻 E1.0 old woman: light skin tone +1F475 1F3FC ; fully-qualified # 👵🏼 E1.0 old woman: medium-light skin tone +1F475 1F3FD ; fully-qualified # 👵🏽 E1.0 old woman: medium skin tone +1F475 1F3FE ; fully-qualified # 👵🏾 E1.0 old woman: medium-dark skin tone +1F475 1F3FF ; fully-qualified # 👵🏿 E1.0 old woman: dark skin tone + +# subgroup: person-gesture +1F64D ; fully-qualified # 🙍 E0.6 person frowning +1F64D 1F3FB ; fully-qualified # 🙍🏻 E1.0 person frowning: light skin tone +1F64D 1F3FC ; fully-qualified # 🙍🏼 E1.0 person frowning: medium-light skin tone +1F64D 1F3FD ; fully-qualified # 🙍🏽 E1.0 person frowning: medium skin tone +1F64D 1F3FE ; fully-qualified # 🙍🏾 E1.0 person frowning: medium-dark skin tone +1F64D 1F3FF ; fully-qualified # 🙍🏿 E1.0 person frowning: dark skin tone +1F64D 200D 2642 FE0F ; fully-qualified # 🙍‍♂️ E4.0 man frowning +1F64D 200D 2642 ; minimally-qualified # 🙍‍♂ E4.0 man frowning +1F64D 1F3FB 200D 2642 FE0F ; fully-qualified # 🙍🏻‍♂️ E4.0 man frowning: light skin tone +1F64D 1F3FB 200D 2642 ; minimally-qualified # 🙍🏻‍♂ E4.0 man frowning: light skin tone +1F64D 1F3FC 200D 2642 FE0F ; fully-qualified # 🙍🏼‍♂️ E4.0 man frowning: medium-light skin tone +1F64D 1F3FC 200D 2642 ; minimally-qualified # 🙍🏼‍♂ E4.0 man frowning: medium-light skin tone +1F64D 1F3FD 200D 2642 FE0F ; fully-qualified # 🙍🏽‍♂️ E4.0 man frowning: medium skin tone +1F64D 1F3FD 200D 2642 ; minimally-qualified # 🙍🏽‍♂ E4.0 man frowning: medium skin tone +1F64D 1F3FE 200D 2642 FE0F ; fully-qualified # 🙍🏾‍♂️ E4.0 man frowning: medium-dark skin tone +1F64D 1F3FE 200D 2642 ; minimally-qualified # 🙍🏾‍♂ E4.0 man frowning: medium-dark skin tone +1F64D 1F3FF 200D 2642 FE0F ; fully-qualified # 🙍🏿‍♂️ E4.0 man frowning: dark skin tone +1F64D 1F3FF 200D 2642 ; minimally-qualified # 🙍🏿‍♂ E4.0 man frowning: dark skin tone +1F64D 200D 2640 FE0F ; fully-qualified # 🙍‍♀️ E4.0 woman frowning +1F64D 200D 2640 ; minimally-qualified # 🙍‍♀ E4.0 woman frowning +1F64D 1F3FB 200D 2640 FE0F ; fully-qualified # 🙍🏻‍♀️ E4.0 woman frowning: light skin tone +1F64D 1F3FB 200D 2640 ; minimally-qualified # 🙍🏻‍♀ E4.0 woman frowning: light skin tone +1F64D 1F3FC 200D 2640 FE0F ; fully-qualified # 🙍🏼‍♀️ E4.0 woman frowning: medium-light skin tone +1F64D 1F3FC 200D 2640 ; minimally-qualified # 🙍🏼‍♀ E4.0 woman frowning: medium-light skin tone +1F64D 1F3FD 200D 2640 FE0F ; fully-qualified # 🙍🏽‍♀️ E4.0 woman frowning: medium skin tone +1F64D 1F3FD 200D 2640 ; minimally-qualified # 🙍🏽‍♀ E4.0 woman frowning: medium skin tone +1F64D 1F3FE 200D 2640 FE0F ; fully-qualified # 🙍🏾‍♀️ E4.0 woman frowning: medium-dark skin tone +1F64D 1F3FE 200D 2640 ; minimally-qualified # 🙍🏾‍♀ E4.0 woman frowning: medium-dark skin tone +1F64D 1F3FF 200D 2640 FE0F ; fully-qualified # 🙍🏿‍♀️ E4.0 woman frowning: dark skin tone +1F64D 1F3FF 200D 2640 ; minimally-qualified # 🙍🏿‍♀ E4.0 woman frowning: dark skin tone +1F64E ; fully-qualified # 🙎 E0.6 person pouting +1F64E 1F3FB ; fully-qualified # 🙎🏻 E1.0 person pouting: light skin tone +1F64E 1F3FC ; fully-qualified # 🙎🏼 E1.0 person pouting: medium-light skin tone +1F64E 1F3FD ; fully-qualified # 🙎🏽 E1.0 person pouting: medium skin tone +1F64E 1F3FE ; fully-qualified # 🙎🏾 E1.0 person pouting: medium-dark skin tone +1F64E 1F3FF ; fully-qualified # 🙎🏿 E1.0 person pouting: dark skin tone +1F64E 200D 2642 FE0F ; fully-qualified # 🙎‍♂️ E4.0 man pouting +1F64E 200D 2642 ; minimally-qualified # 🙎‍♂ E4.0 man pouting +1F64E 1F3FB 200D 2642 FE0F ; fully-qualified # 🙎🏻‍♂️ E4.0 man pouting: light skin tone +1F64E 1F3FB 200D 2642 ; minimally-qualified # 🙎🏻‍♂ E4.0 man pouting: light skin tone +1F64E 1F3FC 200D 2642 FE0F ; fully-qualified # 🙎🏼‍♂️ E4.0 man pouting: medium-light skin tone +1F64E 1F3FC 200D 2642 ; minimally-qualified # 🙎🏼‍♂ E4.0 man pouting: medium-light skin tone +1F64E 1F3FD 200D 2642 FE0F ; fully-qualified # 🙎🏽‍♂️ E4.0 man pouting: medium skin tone +1F64E 1F3FD 200D 2642 ; minimally-qualified # 🙎🏽‍♂ E4.0 man pouting: medium skin tone +1F64E 1F3FE 200D 2642 FE0F ; fully-qualified # 🙎🏾‍♂️ E4.0 man pouting: medium-dark skin tone +1F64E 1F3FE 200D 2642 ; minimally-qualified # 🙎🏾‍♂ E4.0 man pouting: medium-dark skin tone +1F64E 1F3FF 200D 2642 FE0F ; fully-qualified # 🙎🏿‍♂️ E4.0 man pouting: dark skin tone +1F64E 1F3FF 200D 2642 ; minimally-qualified # 🙎🏿‍♂ E4.0 man pouting: dark skin tone +1F64E 200D 2640 FE0F ; fully-qualified # 🙎‍♀️ E4.0 woman pouting +1F64E 200D 2640 ; minimally-qualified # 🙎‍♀ E4.0 woman pouting +1F64E 1F3FB 200D 2640 FE0F ; fully-qualified # 🙎🏻‍♀️ E4.0 woman pouting: light skin tone +1F64E 1F3FB 200D 2640 ; minimally-qualified # 🙎🏻‍♀ E4.0 woman pouting: light skin tone +1F64E 1F3FC 200D 2640 FE0F ; fully-qualified # 🙎🏼‍♀️ E4.0 woman pouting: medium-light skin tone +1F64E 1F3FC 200D 2640 ; minimally-qualified # 🙎🏼‍♀ E4.0 woman pouting: medium-light skin tone +1F64E 1F3FD 200D 2640 FE0F ; fully-qualified # 🙎🏽‍♀️ E4.0 woman pouting: medium skin tone +1F64E 1F3FD 200D 2640 ; minimally-qualified # 🙎🏽‍♀ E4.0 woman pouting: medium skin tone +1F64E 1F3FE 200D 2640 FE0F ; fully-qualified # 🙎🏾‍♀️ E4.0 woman pouting: medium-dark skin tone +1F64E 1F3FE 200D 2640 ; minimally-qualified # 🙎🏾‍♀ E4.0 woman pouting: medium-dark skin tone +1F64E 1F3FF 200D 2640 FE0F ; fully-qualified # 🙎🏿‍♀️ E4.0 woman pouting: dark skin tone +1F64E 1F3FF 200D 2640 ; minimally-qualified # 🙎🏿‍♀ E4.0 woman pouting: dark skin tone +1F645 ; fully-qualified # 🙅 E0.6 person gesturing NO +1F645 1F3FB ; fully-qualified # 🙅🏻 E1.0 person gesturing NO: light skin tone +1F645 1F3FC ; fully-qualified # 🙅🏼 E1.0 person gesturing NO: medium-light skin tone +1F645 1F3FD ; fully-qualified # 🙅🏽 E1.0 person gesturing NO: medium skin tone +1F645 1F3FE ; fully-qualified # 🙅🏾 E1.0 person gesturing NO: medium-dark skin tone +1F645 1F3FF ; fully-qualified # 🙅🏿 E1.0 person gesturing NO: dark skin tone +1F645 200D 2642 FE0F ; fully-qualified # 🙅‍♂️ E4.0 man gesturing NO +1F645 200D 2642 ; minimally-qualified # 🙅‍♂ E4.0 man gesturing NO +1F645 1F3FB 200D 2642 FE0F ; fully-qualified # 🙅🏻‍♂️ E4.0 man gesturing NO: light skin tone +1F645 1F3FB 200D 2642 ; minimally-qualified # 🙅🏻‍♂ E4.0 man gesturing NO: light skin tone +1F645 1F3FC 200D 2642 FE0F ; fully-qualified # 🙅🏼‍♂️ E4.0 man gesturing NO: medium-light skin tone +1F645 1F3FC 200D 2642 ; minimally-qualified # 🙅🏼‍♂ E4.0 man gesturing NO: medium-light skin tone +1F645 1F3FD 200D 2642 FE0F ; fully-qualified # 🙅🏽‍♂️ E4.0 man gesturing NO: medium skin tone +1F645 1F3FD 200D 2642 ; minimally-qualified # 🙅🏽‍♂ E4.0 man gesturing NO: medium skin tone +1F645 1F3FE 200D 2642 FE0F ; fully-qualified # 🙅🏾‍♂️ E4.0 man gesturing NO: medium-dark skin tone +1F645 1F3FE 200D 2642 ; minimally-qualified # 🙅🏾‍♂ E4.0 man gesturing NO: medium-dark skin tone +1F645 1F3FF 200D 2642 FE0F ; fully-qualified # 🙅🏿‍♂️ E4.0 man gesturing NO: dark skin tone +1F645 1F3FF 200D 2642 ; minimally-qualified # 🙅🏿‍♂ E4.0 man gesturing NO: dark skin tone +1F645 200D 2640 FE0F ; fully-qualified # 🙅‍♀️ E4.0 woman gesturing NO +1F645 200D 2640 ; minimally-qualified # 🙅‍♀ E4.0 woman gesturing NO +1F645 1F3FB 200D 2640 FE0F ; fully-qualified # 🙅🏻‍♀️ E4.0 woman gesturing NO: light skin tone +1F645 1F3FB 200D 2640 ; minimally-qualified # 🙅🏻‍♀ E4.0 woman gesturing NO: light skin tone +1F645 1F3FC 200D 2640 FE0F ; fully-qualified # 🙅🏼‍♀️ E4.0 woman gesturing NO: medium-light skin tone +1F645 1F3FC 200D 2640 ; minimally-qualified # 🙅🏼‍♀ E4.0 woman gesturing NO: medium-light skin tone +1F645 1F3FD 200D 2640 FE0F ; fully-qualified # 🙅🏽‍♀️ E4.0 woman gesturing NO: medium skin tone +1F645 1F3FD 200D 2640 ; minimally-qualified # 🙅🏽‍♀ E4.0 woman gesturing NO: medium skin tone +1F645 1F3FE 200D 2640 FE0F ; fully-qualified # 🙅🏾‍♀️ E4.0 woman gesturing NO: medium-dark skin tone +1F645 1F3FE 200D 2640 ; minimally-qualified # 🙅🏾‍♀ E4.0 woman gesturing NO: medium-dark skin tone +1F645 1F3FF 200D 2640 FE0F ; fully-qualified # 🙅🏿‍♀️ E4.0 woman gesturing NO: dark skin tone +1F645 1F3FF 200D 2640 ; minimally-qualified # 🙅🏿‍♀ E4.0 woman gesturing NO: dark skin tone +1F646 ; fully-qualified # 🙆 E0.6 person gesturing OK +1F646 1F3FB ; fully-qualified # 🙆🏻 E1.0 person gesturing OK: light skin tone +1F646 1F3FC ; fully-qualified # 🙆🏼 E1.0 person gesturing OK: medium-light skin tone +1F646 1F3FD ; fully-qualified # 🙆🏽 E1.0 person gesturing OK: medium skin tone +1F646 1F3FE ; fully-qualified # 🙆🏾 E1.0 person gesturing OK: medium-dark skin tone +1F646 1F3FF ; fully-qualified # 🙆🏿 E1.0 person gesturing OK: dark skin tone +1F646 200D 2642 FE0F ; fully-qualified # 🙆‍♂️ E4.0 man gesturing OK +1F646 200D 2642 ; minimally-qualified # 🙆‍♂ E4.0 man gesturing OK +1F646 1F3FB 200D 2642 FE0F ; fully-qualified # 🙆🏻‍♂️ E4.0 man gesturing OK: light skin tone +1F646 1F3FB 200D 2642 ; minimally-qualified # 🙆🏻‍♂ E4.0 man gesturing OK: light skin tone +1F646 1F3FC 200D 2642 FE0F ; fully-qualified # 🙆🏼‍♂️ E4.0 man gesturing OK: medium-light skin tone +1F646 1F3FC 200D 2642 ; minimally-qualified # 🙆🏼‍♂ E4.0 man gesturing OK: medium-light skin tone +1F646 1F3FD 200D 2642 FE0F ; fully-qualified # 🙆🏽‍♂️ E4.0 man gesturing OK: medium skin tone +1F646 1F3FD 200D 2642 ; minimally-qualified # 🙆🏽‍♂ E4.0 man gesturing OK: medium skin tone +1F646 1F3FE 200D 2642 FE0F ; fully-qualified # 🙆🏾‍♂️ E4.0 man gesturing OK: medium-dark skin tone +1F646 1F3FE 200D 2642 ; minimally-qualified # 🙆🏾‍♂ E4.0 man gesturing OK: medium-dark skin tone +1F646 1F3FF 200D 2642 FE0F ; fully-qualified # 🙆🏿‍♂️ E4.0 man gesturing OK: dark skin tone +1F646 1F3FF 200D 2642 ; minimally-qualified # 🙆🏿‍♂ E4.0 man gesturing OK: dark skin tone +1F646 200D 2640 FE0F ; fully-qualified # 🙆‍♀️ E4.0 woman gesturing OK +1F646 200D 2640 ; minimally-qualified # 🙆‍♀ E4.0 woman gesturing OK +1F646 1F3FB 200D 2640 FE0F ; fully-qualified # 🙆🏻‍♀️ E4.0 woman gesturing OK: light skin tone +1F646 1F3FB 200D 2640 ; minimally-qualified # 🙆🏻‍♀ E4.0 woman gesturing OK: light skin tone +1F646 1F3FC 200D 2640 FE0F ; fully-qualified # 🙆🏼‍♀️ E4.0 woman gesturing OK: medium-light skin tone +1F646 1F3FC 200D 2640 ; minimally-qualified # 🙆🏼‍♀ E4.0 woman gesturing OK: medium-light skin tone +1F646 1F3FD 200D 2640 FE0F ; fully-qualified # 🙆🏽‍♀️ E4.0 woman gesturing OK: medium skin tone +1F646 1F3FD 200D 2640 ; minimally-qualified # 🙆🏽‍♀ E4.0 woman gesturing OK: medium skin tone +1F646 1F3FE 200D 2640 FE0F ; fully-qualified # 🙆🏾‍♀️ E4.0 woman gesturing OK: medium-dark skin tone +1F646 1F3FE 200D 2640 ; minimally-qualified # 🙆🏾‍♀ E4.0 woman gesturing OK: medium-dark skin tone +1F646 1F3FF 200D 2640 FE0F ; fully-qualified # 🙆🏿‍♀️ E4.0 woman gesturing OK: dark skin tone +1F646 1F3FF 200D 2640 ; minimally-qualified # 🙆🏿‍♀ E4.0 woman gesturing OK: dark skin tone +1F481 ; fully-qualified # 💁 E0.6 person tipping hand +1F481 1F3FB ; fully-qualified # 💁🏻 E1.0 person tipping hand: light skin tone +1F481 1F3FC ; fully-qualified # 💁🏼 E1.0 person tipping hand: medium-light skin tone +1F481 1F3FD ; fully-qualified # 💁🏽 E1.0 person tipping hand: medium skin tone +1F481 1F3FE ; fully-qualified # 💁🏾 E1.0 person tipping hand: medium-dark skin tone +1F481 1F3FF ; fully-qualified # 💁🏿 E1.0 person tipping hand: dark skin tone +1F481 200D 2642 FE0F ; fully-qualified # 💁‍♂️ E4.0 man tipping hand +1F481 200D 2642 ; minimally-qualified # 💁‍♂ E4.0 man tipping hand +1F481 1F3FB 200D 2642 FE0F ; fully-qualified # 💁🏻‍♂️ E4.0 man tipping hand: light skin tone +1F481 1F3FB 200D 2642 ; minimally-qualified # 💁🏻‍♂ E4.0 man tipping hand: light skin tone +1F481 1F3FC 200D 2642 FE0F ; fully-qualified # 💁🏼‍♂️ E4.0 man tipping hand: medium-light skin tone +1F481 1F3FC 200D 2642 ; minimally-qualified # 💁🏼‍♂ E4.0 man tipping hand: medium-light skin tone +1F481 1F3FD 200D 2642 FE0F ; fully-qualified # 💁🏽‍♂️ E4.0 man tipping hand: medium skin tone +1F481 1F3FD 200D 2642 ; minimally-qualified # 💁🏽‍♂ E4.0 man tipping hand: medium skin tone +1F481 1F3FE 200D 2642 FE0F ; fully-qualified # 💁🏾‍♂️ E4.0 man tipping hand: medium-dark skin tone +1F481 1F3FE 200D 2642 ; minimally-qualified # 💁🏾‍♂ E4.0 man tipping hand: medium-dark skin tone +1F481 1F3FF 200D 2642 FE0F ; fully-qualified # 💁🏿‍♂️ E4.0 man tipping hand: dark skin tone +1F481 1F3FF 200D 2642 ; minimally-qualified # 💁🏿‍♂ E4.0 man tipping hand: dark skin tone +1F481 200D 2640 FE0F ; fully-qualified # 💁‍♀️ E4.0 woman tipping hand +1F481 200D 2640 ; minimally-qualified # 💁‍♀ E4.0 woman tipping hand +1F481 1F3FB 200D 2640 FE0F ; fully-qualified # 💁🏻‍♀️ E4.0 woman tipping hand: light skin tone +1F481 1F3FB 200D 2640 ; minimally-qualified # 💁🏻‍♀ E4.0 woman tipping hand: light skin tone +1F481 1F3FC 200D 2640 FE0F ; fully-qualified # 💁🏼‍♀️ E4.0 woman tipping hand: medium-light skin tone +1F481 1F3FC 200D 2640 ; minimally-qualified # 💁🏼‍♀ E4.0 woman tipping hand: medium-light skin tone +1F481 1F3FD 200D 2640 FE0F ; fully-qualified # 💁🏽‍♀️ E4.0 woman tipping hand: medium skin tone +1F481 1F3FD 200D 2640 ; minimally-qualified # 💁🏽‍♀ E4.0 woman tipping hand: medium skin tone +1F481 1F3FE 200D 2640 FE0F ; fully-qualified # 💁🏾‍♀️ E4.0 woman tipping hand: medium-dark skin tone +1F481 1F3FE 200D 2640 ; minimally-qualified # 💁🏾‍♀ E4.0 woman tipping hand: medium-dark skin tone +1F481 1F3FF 200D 2640 FE0F ; fully-qualified # 💁🏿‍♀️ E4.0 woman tipping hand: dark skin tone +1F481 1F3FF 200D 2640 ; minimally-qualified # 💁🏿‍♀ E4.0 woman tipping hand: dark skin tone +1F64B ; fully-qualified # 🙋 E0.6 person raising hand +1F64B 1F3FB ; fully-qualified # 🙋🏻 E1.0 person raising hand: light skin tone +1F64B 1F3FC ; fully-qualified # 🙋🏼 E1.0 person raising hand: medium-light skin tone +1F64B 1F3FD ; fully-qualified # 🙋🏽 E1.0 person raising hand: medium skin tone +1F64B 1F3FE ; fully-qualified # 🙋🏾 E1.0 person raising hand: medium-dark skin tone +1F64B 1F3FF ; fully-qualified # 🙋🏿 E1.0 person raising hand: dark skin tone +1F64B 200D 2642 FE0F ; fully-qualified # 🙋‍♂️ E4.0 man raising hand +1F64B 200D 2642 ; minimally-qualified # 🙋‍♂ E4.0 man raising hand +1F64B 1F3FB 200D 2642 FE0F ; fully-qualified # 🙋🏻‍♂️ E4.0 man raising hand: light skin tone +1F64B 1F3FB 200D 2642 ; minimally-qualified # 🙋🏻‍♂ E4.0 man raising hand: light skin tone +1F64B 1F3FC 200D 2642 FE0F ; fully-qualified # 🙋🏼‍♂️ E4.0 man raising hand: medium-light skin tone +1F64B 1F3FC 200D 2642 ; minimally-qualified # 🙋🏼‍♂ E4.0 man raising hand: medium-light skin tone +1F64B 1F3FD 200D 2642 FE0F ; fully-qualified # 🙋🏽‍♂️ E4.0 man raising hand: medium skin tone +1F64B 1F3FD 200D 2642 ; minimally-qualified # 🙋🏽‍♂ E4.0 man raising hand: medium skin tone +1F64B 1F3FE 200D 2642 FE0F ; fully-qualified # 🙋🏾‍♂️ E4.0 man raising hand: medium-dark skin tone +1F64B 1F3FE 200D 2642 ; minimally-qualified # 🙋🏾‍♂ E4.0 man raising hand: medium-dark skin tone +1F64B 1F3FF 200D 2642 FE0F ; fully-qualified # 🙋🏿‍♂️ E4.0 man raising hand: dark skin tone +1F64B 1F3FF 200D 2642 ; minimally-qualified # 🙋🏿‍♂ E4.0 man raising hand: dark skin tone +1F64B 200D 2640 FE0F ; fully-qualified # 🙋‍♀️ E4.0 woman raising hand +1F64B 200D 2640 ; minimally-qualified # 🙋‍♀ E4.0 woman raising hand +1F64B 1F3FB 200D 2640 FE0F ; fully-qualified # 🙋🏻‍♀️ E4.0 woman raising hand: light skin tone +1F64B 1F3FB 200D 2640 ; minimally-qualified # 🙋🏻‍♀ E4.0 woman raising hand: light skin tone +1F64B 1F3FC 200D 2640 FE0F ; fully-qualified # 🙋🏼‍♀️ E4.0 woman raising hand: medium-light skin tone +1F64B 1F3FC 200D 2640 ; minimally-qualified # 🙋🏼‍♀ E4.0 woman raising hand: medium-light skin tone +1F64B 1F3FD 200D 2640 FE0F ; fully-qualified # 🙋🏽‍♀️ E4.0 woman raising hand: medium skin tone +1F64B 1F3FD 200D 2640 ; minimally-qualified # 🙋🏽‍♀ E4.0 woman raising hand: medium skin tone +1F64B 1F3FE 200D 2640 FE0F ; fully-qualified # 🙋🏾‍♀️ E4.0 woman raising hand: medium-dark skin tone +1F64B 1F3FE 200D 2640 ; minimally-qualified # 🙋🏾‍♀ E4.0 woman raising hand: medium-dark skin tone +1F64B 1F3FF 200D 2640 FE0F ; fully-qualified # 🙋🏿‍♀️ E4.0 woman raising hand: dark skin tone +1F64B 1F3FF 200D 2640 ; minimally-qualified # 🙋🏿‍♀ E4.0 woman raising hand: dark skin tone +1F9CF ; fully-qualified # 🧏 E12.0 deaf person +1F9CF 1F3FB ; fully-qualified # 🧏🏻 E12.0 deaf person: light skin tone +1F9CF 1F3FC ; fully-qualified # 🧏🏼 E12.0 deaf person: medium-light skin tone +1F9CF 1F3FD ; fully-qualified # 🧏🏽 E12.0 deaf person: medium skin tone +1F9CF 1F3FE ; fully-qualified # 🧏🏾 E12.0 deaf person: medium-dark skin tone +1F9CF 1F3FF ; fully-qualified # 🧏🏿 E12.0 deaf person: dark skin tone +1F9CF 200D 2642 FE0F ; fully-qualified # 🧏‍♂️ E12.0 deaf man +1F9CF 200D 2642 ; minimally-qualified # 🧏‍♂ E12.0 deaf man +1F9CF 1F3FB 200D 2642 FE0F ; fully-qualified # 🧏🏻‍♂️ E12.0 deaf man: light skin tone +1F9CF 1F3FB 200D 2642 ; minimally-qualified # 🧏🏻‍♂ E12.0 deaf man: light skin tone +1F9CF 1F3FC 200D 2642 FE0F ; fully-qualified # 🧏🏼‍♂️ E12.0 deaf man: medium-light skin tone +1F9CF 1F3FC 200D 2642 ; minimally-qualified # 🧏🏼‍♂ E12.0 deaf man: medium-light skin tone +1F9CF 1F3FD 200D 2642 FE0F ; fully-qualified # 🧏🏽‍♂️ E12.0 deaf man: medium skin tone +1F9CF 1F3FD 200D 2642 ; minimally-qualified # 🧏🏽‍♂ E12.0 deaf man: medium skin tone +1F9CF 1F3FE 200D 2642 FE0F ; fully-qualified # 🧏🏾‍♂️ E12.0 deaf man: medium-dark skin tone +1F9CF 1F3FE 200D 2642 ; minimally-qualified # 🧏🏾‍♂ E12.0 deaf man: medium-dark skin tone +1F9CF 1F3FF 200D 2642 FE0F ; fully-qualified # 🧏🏿‍♂️ E12.0 deaf man: dark skin tone +1F9CF 1F3FF 200D 2642 ; minimally-qualified # 🧏🏿‍♂ E12.0 deaf man: dark skin tone +1F9CF 200D 2640 FE0F ; fully-qualified # 🧏‍♀️ E12.0 deaf woman +1F9CF 200D 2640 ; minimally-qualified # 🧏‍♀ E12.0 deaf woman +1F9CF 1F3FB 200D 2640 FE0F ; fully-qualified # 🧏🏻‍♀️ E12.0 deaf woman: light skin tone +1F9CF 1F3FB 200D 2640 ; minimally-qualified # 🧏🏻‍♀ E12.0 deaf woman: light skin tone +1F9CF 1F3FC 200D 2640 FE0F ; fully-qualified # 🧏🏼‍♀️ E12.0 deaf woman: medium-light skin tone +1F9CF 1F3FC 200D 2640 ; minimally-qualified # 🧏🏼‍♀ E12.0 deaf woman: medium-light skin tone +1F9CF 1F3FD 200D 2640 FE0F ; fully-qualified # 🧏🏽‍♀️ E12.0 deaf woman: medium skin tone +1F9CF 1F3FD 200D 2640 ; minimally-qualified # 🧏🏽‍♀ E12.0 deaf woman: medium skin tone +1F9CF 1F3FE 200D 2640 FE0F ; fully-qualified # 🧏🏾‍♀️ E12.0 deaf woman: medium-dark skin tone +1F9CF 1F3FE 200D 2640 ; minimally-qualified # 🧏🏾‍♀ E12.0 deaf woman: medium-dark skin tone +1F9CF 1F3FF 200D 2640 FE0F ; fully-qualified # 🧏🏿‍♀️ E12.0 deaf woman: dark skin tone +1F9CF 1F3FF 200D 2640 ; minimally-qualified # 🧏🏿‍♀ E12.0 deaf woman: dark skin tone +1F647 ; fully-qualified # 🙇 E0.6 person bowing +1F647 1F3FB ; fully-qualified # 🙇🏻 E1.0 person bowing: light skin tone +1F647 1F3FC ; fully-qualified # 🙇🏼 E1.0 person bowing: medium-light skin tone +1F647 1F3FD ; fully-qualified # 🙇🏽 E1.0 person bowing: medium skin tone +1F647 1F3FE ; fully-qualified # 🙇🏾 E1.0 person bowing: medium-dark skin tone +1F647 1F3FF ; fully-qualified # 🙇🏿 E1.0 person bowing: dark skin tone +1F647 200D 2642 FE0F ; fully-qualified # 🙇‍♂️ E4.0 man bowing +1F647 200D 2642 ; minimally-qualified # 🙇‍♂ E4.0 man bowing +1F647 1F3FB 200D 2642 FE0F ; fully-qualified # 🙇🏻‍♂️ E4.0 man bowing: light skin tone +1F647 1F3FB 200D 2642 ; minimally-qualified # 🙇🏻‍♂ E4.0 man bowing: light skin tone +1F647 1F3FC 200D 2642 FE0F ; fully-qualified # 🙇🏼‍♂️ E4.0 man bowing: medium-light skin tone +1F647 1F3FC 200D 2642 ; minimally-qualified # 🙇🏼‍♂ E4.0 man bowing: medium-light skin tone +1F647 1F3FD 200D 2642 FE0F ; fully-qualified # 🙇🏽‍♂️ E4.0 man bowing: medium skin tone +1F647 1F3FD 200D 2642 ; minimally-qualified # 🙇🏽‍♂ E4.0 man bowing: medium skin tone +1F647 1F3FE 200D 2642 FE0F ; fully-qualified # 🙇🏾‍♂️ E4.0 man bowing: medium-dark skin tone +1F647 1F3FE 200D 2642 ; minimally-qualified # 🙇🏾‍♂ E4.0 man bowing: medium-dark skin tone +1F647 1F3FF 200D 2642 FE0F ; fully-qualified # 🙇🏿‍♂️ E4.0 man bowing: dark skin tone +1F647 1F3FF 200D 2642 ; minimally-qualified # 🙇🏿‍♂ E4.0 man bowing: dark skin tone +1F647 200D 2640 FE0F ; fully-qualified # 🙇‍♀️ E4.0 woman bowing +1F647 200D 2640 ; minimally-qualified # 🙇‍♀ E4.0 woman bowing +1F647 1F3FB 200D 2640 FE0F ; fully-qualified # 🙇🏻‍♀️ E4.0 woman bowing: light skin tone +1F647 1F3FB 200D 2640 ; minimally-qualified # 🙇🏻‍♀ E4.0 woman bowing: light skin tone +1F647 1F3FC 200D 2640 FE0F ; fully-qualified # 🙇🏼‍♀️ E4.0 woman bowing: medium-light skin tone +1F647 1F3FC 200D 2640 ; minimally-qualified # 🙇🏼‍♀ E4.0 woman bowing: medium-light skin tone +1F647 1F3FD 200D 2640 FE0F ; fully-qualified # 🙇🏽‍♀️ E4.0 woman bowing: medium skin tone +1F647 1F3FD 200D 2640 ; minimally-qualified # 🙇🏽‍♀ E4.0 woman bowing: medium skin tone +1F647 1F3FE 200D 2640 FE0F ; fully-qualified # 🙇🏾‍♀️ E4.0 woman bowing: medium-dark skin tone +1F647 1F3FE 200D 2640 ; minimally-qualified # 🙇🏾‍♀ E4.0 woman bowing: medium-dark skin tone +1F647 1F3FF 200D 2640 FE0F ; fully-qualified # 🙇🏿‍♀️ E4.0 woman bowing: dark skin tone +1F647 1F3FF 200D 2640 ; minimally-qualified # 🙇🏿‍♀ E4.0 woman bowing: dark skin tone +1F926 ; fully-qualified # 🤦 E3.0 person facepalming +1F926 1F3FB ; fully-qualified # 🤦🏻 E3.0 person facepalming: light skin tone +1F926 1F3FC ; fully-qualified # 🤦🏼 E3.0 person facepalming: medium-light skin tone +1F926 1F3FD ; fully-qualified # 🤦🏽 E3.0 person facepalming: medium skin tone +1F926 1F3FE ; fully-qualified # 🤦🏾 E3.0 person facepalming: medium-dark skin tone +1F926 1F3FF ; fully-qualified # 🤦🏿 E3.0 person facepalming: dark skin tone +1F926 200D 2642 FE0F ; fully-qualified # 🤦‍♂️ E4.0 man facepalming +1F926 200D 2642 ; minimally-qualified # 🤦‍♂ E4.0 man facepalming +1F926 1F3FB 200D 2642 FE0F ; fully-qualified # 🤦🏻‍♂️ E4.0 man facepalming: light skin tone +1F926 1F3FB 200D 2642 ; minimally-qualified # 🤦🏻‍♂ E4.0 man facepalming: light skin tone +1F926 1F3FC 200D 2642 FE0F ; fully-qualified # 🤦🏼‍♂️ E4.0 man facepalming: medium-light skin tone +1F926 1F3FC 200D 2642 ; minimally-qualified # 🤦🏼‍♂ E4.0 man facepalming: medium-light skin tone +1F926 1F3FD 200D 2642 FE0F ; fully-qualified # 🤦🏽‍♂️ E4.0 man facepalming: medium skin tone +1F926 1F3FD 200D 2642 ; minimally-qualified # 🤦🏽‍♂ E4.0 man facepalming: medium skin tone +1F926 1F3FE 200D 2642 FE0F ; fully-qualified # 🤦🏾‍♂️ E4.0 man facepalming: medium-dark skin tone +1F926 1F3FE 200D 2642 ; minimally-qualified # 🤦🏾‍♂ E4.0 man facepalming: medium-dark skin tone +1F926 1F3FF 200D 2642 FE0F ; fully-qualified # 🤦🏿‍♂️ E4.0 man facepalming: dark skin tone +1F926 1F3FF 200D 2642 ; minimally-qualified # 🤦🏿‍♂ E4.0 man facepalming: dark skin tone +1F926 200D 2640 FE0F ; fully-qualified # 🤦‍♀️ E4.0 woman facepalming +1F926 200D 2640 ; minimally-qualified # 🤦‍♀ E4.0 woman facepalming +1F926 1F3FB 200D 2640 FE0F ; fully-qualified # 🤦🏻‍♀️ E4.0 woman facepalming: light skin tone +1F926 1F3FB 200D 2640 ; minimally-qualified # 🤦🏻‍♀ E4.0 woman facepalming: light skin tone +1F926 1F3FC 200D 2640 FE0F ; fully-qualified # 🤦🏼‍♀️ E4.0 woman facepalming: medium-light skin tone +1F926 1F3FC 200D 2640 ; minimally-qualified # 🤦🏼‍♀ E4.0 woman facepalming: medium-light skin tone +1F926 1F3FD 200D 2640 FE0F ; fully-qualified # 🤦🏽‍♀️ E4.0 woman facepalming: medium skin tone +1F926 1F3FD 200D 2640 ; minimally-qualified # 🤦🏽‍♀ E4.0 woman facepalming: medium skin tone +1F926 1F3FE 200D 2640 FE0F ; fully-qualified # 🤦🏾‍♀️ E4.0 woman facepalming: medium-dark skin tone +1F926 1F3FE 200D 2640 ; minimally-qualified # 🤦🏾‍♀ E4.0 woman facepalming: medium-dark skin tone +1F926 1F3FF 200D 2640 FE0F ; fully-qualified # 🤦🏿‍♀️ E4.0 woman facepalming: dark skin tone +1F926 1F3FF 200D 2640 ; minimally-qualified # 🤦🏿‍♀ E4.0 woman facepalming: dark skin tone +1F937 ; fully-qualified # 🤷 E3.0 person shrugging +1F937 1F3FB ; fully-qualified # 🤷🏻 E3.0 person shrugging: light skin tone +1F937 1F3FC ; fully-qualified # 🤷🏼 E3.0 person shrugging: medium-light skin tone +1F937 1F3FD ; fully-qualified # 🤷🏽 E3.0 person shrugging: medium skin tone +1F937 1F3FE ; fully-qualified # 🤷🏾 E3.0 person shrugging: medium-dark skin tone +1F937 1F3FF ; fully-qualified # 🤷🏿 E3.0 person shrugging: dark skin tone +1F937 200D 2642 FE0F ; fully-qualified # 🤷‍♂️ E4.0 man shrugging +1F937 200D 2642 ; minimally-qualified # 🤷‍♂ E4.0 man shrugging +1F937 1F3FB 200D 2642 FE0F ; fully-qualified # 🤷🏻‍♂️ E4.0 man shrugging: light skin tone +1F937 1F3FB 200D 2642 ; minimally-qualified # 🤷🏻‍♂ E4.0 man shrugging: light skin tone +1F937 1F3FC 200D 2642 FE0F ; fully-qualified # 🤷🏼‍♂️ E4.0 man shrugging: medium-light skin tone +1F937 1F3FC 200D 2642 ; minimally-qualified # 🤷🏼‍♂ E4.0 man shrugging: medium-light skin tone +1F937 1F3FD 200D 2642 FE0F ; fully-qualified # 🤷🏽‍♂️ E4.0 man shrugging: medium skin tone +1F937 1F3FD 200D 2642 ; minimally-qualified # 🤷🏽‍♂ E4.0 man shrugging: medium skin tone +1F937 1F3FE 200D 2642 FE0F ; fully-qualified # 🤷🏾‍♂️ E4.0 man shrugging: medium-dark skin tone +1F937 1F3FE 200D 2642 ; minimally-qualified # 🤷🏾‍♂ E4.0 man shrugging: medium-dark skin tone +1F937 1F3FF 200D 2642 FE0F ; fully-qualified # 🤷🏿‍♂️ E4.0 man shrugging: dark skin tone +1F937 1F3FF 200D 2642 ; minimally-qualified # 🤷🏿‍♂ E4.0 man shrugging: dark skin tone +1F937 200D 2640 FE0F ; fully-qualified # 🤷‍♀️ E4.0 woman shrugging +1F937 200D 2640 ; minimally-qualified # 🤷‍♀ E4.0 woman shrugging +1F937 1F3FB 200D 2640 FE0F ; fully-qualified # 🤷🏻‍♀️ E4.0 woman shrugging: light skin tone +1F937 1F3FB 200D 2640 ; minimally-qualified # 🤷🏻‍♀ E4.0 woman shrugging: light skin tone +1F937 1F3FC 200D 2640 FE0F ; fully-qualified # 🤷🏼‍♀️ E4.0 woman shrugging: medium-light skin tone +1F937 1F3FC 200D 2640 ; minimally-qualified # 🤷🏼‍♀ E4.0 woman shrugging: medium-light skin tone +1F937 1F3FD 200D 2640 FE0F ; fully-qualified # 🤷🏽‍♀️ E4.0 woman shrugging: medium skin tone +1F937 1F3FD 200D 2640 ; minimally-qualified # 🤷🏽‍♀ E4.0 woman shrugging: medium skin tone +1F937 1F3FE 200D 2640 FE0F ; fully-qualified # 🤷🏾‍♀️ E4.0 woman shrugging: medium-dark skin tone +1F937 1F3FE 200D 2640 ; minimally-qualified # 🤷🏾‍♀ E4.0 woman shrugging: medium-dark skin tone +1F937 1F3FF 200D 2640 FE0F ; fully-qualified # 🤷🏿‍♀️ E4.0 woman shrugging: dark skin tone +1F937 1F3FF 200D 2640 ; minimally-qualified # 🤷🏿‍♀ E4.0 woman shrugging: dark skin tone + +# subgroup: person-role +1F9D1 200D 2695 FE0F ; fully-qualified # 🧑‍⚕️ E12.1 health worker +1F9D1 200D 2695 ; minimally-qualified # 🧑‍⚕ E12.1 health worker +1F9D1 1F3FB 200D 2695 FE0F ; fully-qualified # 🧑🏻‍⚕️ E12.1 health worker: light skin tone +1F9D1 1F3FB 200D 2695 ; minimally-qualified # 🧑🏻‍⚕ E12.1 health worker: light skin tone +1F9D1 1F3FC 200D 2695 FE0F ; fully-qualified # 🧑🏼‍⚕️ E12.1 health worker: medium-light skin tone +1F9D1 1F3FC 200D 2695 ; minimally-qualified # 🧑🏼‍⚕ E12.1 health worker: medium-light skin tone +1F9D1 1F3FD 200D 2695 FE0F ; fully-qualified # 🧑🏽‍⚕️ E12.1 health worker: medium skin tone +1F9D1 1F3FD 200D 2695 ; minimally-qualified # 🧑🏽‍⚕ E12.1 health worker: medium skin tone +1F9D1 1F3FE 200D 2695 FE0F ; fully-qualified # 🧑🏾‍⚕️ E12.1 health worker: medium-dark skin tone +1F9D1 1F3FE 200D 2695 ; minimally-qualified # 🧑🏾‍⚕ E12.1 health worker: medium-dark skin tone +1F9D1 1F3FF 200D 2695 FE0F ; fully-qualified # 🧑🏿‍⚕️ E12.1 health worker: dark skin tone +1F9D1 1F3FF 200D 2695 ; minimally-qualified # 🧑🏿‍⚕ E12.1 health worker: dark skin tone +1F468 200D 2695 FE0F ; fully-qualified # 👨‍⚕️ E4.0 man health worker +1F468 200D 2695 ; minimally-qualified # 👨‍⚕ E4.0 man health worker +1F468 1F3FB 200D 2695 FE0F ; fully-qualified # 👨🏻‍⚕️ E4.0 man health worker: light skin tone +1F468 1F3FB 200D 2695 ; minimally-qualified # 👨🏻‍⚕ E4.0 man health worker: light skin tone +1F468 1F3FC 200D 2695 FE0F ; fully-qualified # 👨🏼‍⚕️ E4.0 man health worker: medium-light skin tone +1F468 1F3FC 200D 2695 ; minimally-qualified # 👨🏼‍⚕ E4.0 man health worker: medium-light skin tone +1F468 1F3FD 200D 2695 FE0F ; fully-qualified # 👨🏽‍⚕️ E4.0 man health worker: medium skin tone +1F468 1F3FD 200D 2695 ; minimally-qualified # 👨🏽‍⚕ E4.0 man health worker: medium skin tone +1F468 1F3FE 200D 2695 FE0F ; fully-qualified # 👨🏾‍⚕️ E4.0 man health worker: medium-dark skin tone +1F468 1F3FE 200D 2695 ; minimally-qualified # 👨🏾‍⚕ E4.0 man health worker: medium-dark skin tone +1F468 1F3FF 200D 2695 FE0F ; fully-qualified # 👨🏿‍⚕️ E4.0 man health worker: dark skin tone +1F468 1F3FF 200D 2695 ; minimally-qualified # 👨🏿‍⚕ E4.0 man health worker: dark skin tone +1F469 200D 2695 FE0F ; fully-qualified # 👩‍⚕️ E4.0 woman health worker +1F469 200D 2695 ; minimally-qualified # 👩‍⚕ E4.0 woman health worker +1F469 1F3FB 200D 2695 FE0F ; fully-qualified # 👩🏻‍⚕️ E4.0 woman health worker: light skin tone +1F469 1F3FB 200D 2695 ; minimally-qualified # 👩🏻‍⚕ E4.0 woman health worker: light skin tone +1F469 1F3FC 200D 2695 FE0F ; fully-qualified # 👩🏼‍⚕️ E4.0 woman health worker: medium-light skin tone +1F469 1F3FC 200D 2695 ; minimally-qualified # 👩🏼‍⚕ E4.0 woman health worker: medium-light skin tone +1F469 1F3FD 200D 2695 FE0F ; fully-qualified # 👩🏽‍⚕️ E4.0 woman health worker: medium skin tone +1F469 1F3FD 200D 2695 ; minimally-qualified # 👩🏽‍⚕ E4.0 woman health worker: medium skin tone +1F469 1F3FE 200D 2695 FE0F ; fully-qualified # 👩🏾‍⚕️ E4.0 woman health worker: medium-dark skin tone +1F469 1F3FE 200D 2695 ; minimally-qualified # 👩🏾‍⚕ E4.0 woman health worker: medium-dark skin tone +1F469 1F3FF 200D 2695 FE0F ; fully-qualified # 👩🏿‍⚕️ E4.0 woman health worker: dark skin tone +1F469 1F3FF 200D 2695 ; minimally-qualified # 👩🏿‍⚕ E4.0 woman health worker: dark skin tone +1F9D1 200D 1F393 ; fully-qualified # 🧑‍🎓 E12.1 student +1F9D1 1F3FB 200D 1F393 ; fully-qualified # 🧑🏻‍🎓 E12.1 student: light skin tone +1F9D1 1F3FC 200D 1F393 ; fully-qualified # 🧑🏼‍🎓 E12.1 student: medium-light skin tone +1F9D1 1F3FD 200D 1F393 ; fully-qualified # 🧑🏽‍🎓 E12.1 student: medium skin tone +1F9D1 1F3FE 200D 1F393 ; fully-qualified # 🧑🏾‍🎓 E12.1 student: medium-dark skin tone +1F9D1 1F3FF 200D 1F393 ; fully-qualified # 🧑🏿‍🎓 E12.1 student: dark skin tone +1F468 200D 1F393 ; fully-qualified # 👨‍🎓 E4.0 man student +1F468 1F3FB 200D 1F393 ; fully-qualified # 👨🏻‍🎓 E4.0 man student: light skin tone +1F468 1F3FC 200D 1F393 ; fully-qualified # 👨🏼‍🎓 E4.0 man student: medium-light skin tone +1F468 1F3FD 200D 1F393 ; fully-qualified # 👨🏽‍🎓 E4.0 man student: medium skin tone +1F468 1F3FE 200D 1F393 ; fully-qualified # 👨🏾‍🎓 E4.0 man student: medium-dark skin tone +1F468 1F3FF 200D 1F393 ; fully-qualified # 👨🏿‍🎓 E4.0 man student: dark skin tone +1F469 200D 1F393 ; fully-qualified # 👩‍🎓 E4.0 woman student +1F469 1F3FB 200D 1F393 ; fully-qualified # 👩🏻‍🎓 E4.0 woman student: light skin tone +1F469 1F3FC 200D 1F393 ; fully-qualified # 👩🏼‍🎓 E4.0 woman student: medium-light skin tone +1F469 1F3FD 200D 1F393 ; fully-qualified # 👩🏽‍🎓 E4.0 woman student: medium skin tone +1F469 1F3FE 200D 1F393 ; fully-qualified # 👩🏾‍🎓 E4.0 woman student: medium-dark skin tone +1F469 1F3FF 200D 1F393 ; fully-qualified # 👩🏿‍🎓 E4.0 woman student: dark skin tone +1F9D1 200D 1F3EB ; fully-qualified # 🧑‍🏫 E12.1 teacher +1F9D1 1F3FB 200D 1F3EB ; fully-qualified # 🧑🏻‍🏫 E12.1 teacher: light skin tone +1F9D1 1F3FC 200D 1F3EB ; fully-qualified # 🧑🏼‍🏫 E12.1 teacher: medium-light skin tone +1F9D1 1F3FD 200D 1F3EB ; fully-qualified # 🧑🏽‍🏫 E12.1 teacher: medium skin tone +1F9D1 1F3FE 200D 1F3EB ; fully-qualified # 🧑🏾‍🏫 E12.1 teacher: medium-dark skin tone +1F9D1 1F3FF 200D 1F3EB ; fully-qualified # 🧑🏿‍🏫 E12.1 teacher: dark skin tone +1F468 200D 1F3EB ; fully-qualified # 👨‍🏫 E4.0 man teacher +1F468 1F3FB 200D 1F3EB ; fully-qualified # 👨🏻‍🏫 E4.0 man teacher: light skin tone +1F468 1F3FC 200D 1F3EB ; fully-qualified # 👨🏼‍🏫 E4.0 man teacher: medium-light skin tone +1F468 1F3FD 200D 1F3EB ; fully-qualified # 👨🏽‍🏫 E4.0 man teacher: medium skin tone +1F468 1F3FE 200D 1F3EB ; fully-qualified # 👨🏾‍🏫 E4.0 man teacher: medium-dark skin tone +1F468 1F3FF 200D 1F3EB ; fully-qualified # 👨🏿‍🏫 E4.0 man teacher: dark skin tone +1F469 200D 1F3EB ; fully-qualified # 👩‍🏫 E4.0 woman teacher +1F469 1F3FB 200D 1F3EB ; fully-qualified # 👩🏻‍🏫 E4.0 woman teacher: light skin tone +1F469 1F3FC 200D 1F3EB ; fully-qualified # 👩🏼‍🏫 E4.0 woman teacher: medium-light skin tone +1F469 1F3FD 200D 1F3EB ; fully-qualified # 👩🏽‍🏫 E4.0 woman teacher: medium skin tone +1F469 1F3FE 200D 1F3EB ; fully-qualified # 👩🏾‍🏫 E4.0 woman teacher: medium-dark skin tone +1F469 1F3FF 200D 1F3EB ; fully-qualified # 👩🏿‍🏫 E4.0 woman teacher: dark skin tone +1F9D1 200D 2696 FE0F ; fully-qualified # 🧑‍⚖️ E12.1 judge +1F9D1 200D 2696 ; minimally-qualified # 🧑‍⚖ E12.1 judge +1F9D1 1F3FB 200D 2696 FE0F ; fully-qualified # 🧑🏻‍⚖️ E12.1 judge: light skin tone +1F9D1 1F3FB 200D 2696 ; minimally-qualified # 🧑🏻‍⚖ E12.1 judge: light skin tone +1F9D1 1F3FC 200D 2696 FE0F ; fully-qualified # 🧑🏼‍⚖️ E12.1 judge: medium-light skin tone +1F9D1 1F3FC 200D 2696 ; minimally-qualified # 🧑🏼‍⚖ E12.1 judge: medium-light skin tone +1F9D1 1F3FD 200D 2696 FE0F ; fully-qualified # 🧑🏽‍⚖️ E12.1 judge: medium skin tone +1F9D1 1F3FD 200D 2696 ; minimally-qualified # 🧑🏽‍⚖ E12.1 judge: medium skin tone +1F9D1 1F3FE 200D 2696 FE0F ; fully-qualified # 🧑🏾‍⚖️ E12.1 judge: medium-dark skin tone +1F9D1 1F3FE 200D 2696 ; minimally-qualified # 🧑🏾‍⚖ E12.1 judge: medium-dark skin tone +1F9D1 1F3FF 200D 2696 FE0F ; fully-qualified # 🧑🏿‍⚖️ E12.1 judge: dark skin tone +1F9D1 1F3FF 200D 2696 ; minimally-qualified # 🧑🏿‍⚖ E12.1 judge: dark skin tone +1F468 200D 2696 FE0F ; fully-qualified # 👨‍⚖️ E4.0 man judge +1F468 200D 2696 ; minimally-qualified # 👨‍⚖ E4.0 man judge +1F468 1F3FB 200D 2696 FE0F ; fully-qualified # 👨🏻‍⚖️ E4.0 man judge: light skin tone +1F468 1F3FB 200D 2696 ; minimally-qualified # 👨🏻‍⚖ E4.0 man judge: light skin tone +1F468 1F3FC 200D 2696 FE0F ; fully-qualified # 👨🏼‍⚖️ E4.0 man judge: medium-light skin tone +1F468 1F3FC 200D 2696 ; minimally-qualified # 👨🏼‍⚖ E4.0 man judge: medium-light skin tone +1F468 1F3FD 200D 2696 FE0F ; fully-qualified # 👨🏽‍⚖️ E4.0 man judge: medium skin tone +1F468 1F3FD 200D 2696 ; minimally-qualified # 👨🏽‍⚖ E4.0 man judge: medium skin tone +1F468 1F3FE 200D 2696 FE0F ; fully-qualified # 👨🏾‍⚖️ E4.0 man judge: medium-dark skin tone +1F468 1F3FE 200D 2696 ; minimally-qualified # 👨🏾‍⚖ E4.0 man judge: medium-dark skin tone +1F468 1F3FF 200D 2696 FE0F ; fully-qualified # 👨🏿‍⚖️ E4.0 man judge: dark skin tone +1F468 1F3FF 200D 2696 ; minimally-qualified # 👨🏿‍⚖ E4.0 man judge: dark skin tone +1F469 200D 2696 FE0F ; fully-qualified # 👩‍⚖️ E4.0 woman judge +1F469 200D 2696 ; minimally-qualified # 👩‍⚖ E4.0 woman judge +1F469 1F3FB 200D 2696 FE0F ; fully-qualified # 👩🏻‍⚖️ E4.0 woman judge: light skin tone +1F469 1F3FB 200D 2696 ; minimally-qualified # 👩🏻‍⚖ E4.0 woman judge: light skin tone +1F469 1F3FC 200D 2696 FE0F ; fully-qualified # 👩🏼‍⚖️ E4.0 woman judge: medium-light skin tone +1F469 1F3FC 200D 2696 ; minimally-qualified # 👩🏼‍⚖ E4.0 woman judge: medium-light skin tone +1F469 1F3FD 200D 2696 FE0F ; fully-qualified # 👩🏽‍⚖️ E4.0 woman judge: medium skin tone +1F469 1F3FD 200D 2696 ; minimally-qualified # 👩🏽‍⚖ E4.0 woman judge: medium skin tone +1F469 1F3FE 200D 2696 FE0F ; fully-qualified # 👩🏾‍⚖️ E4.0 woman judge: medium-dark skin tone +1F469 1F3FE 200D 2696 ; minimally-qualified # 👩🏾‍⚖ E4.0 woman judge: medium-dark skin tone +1F469 1F3FF 200D 2696 FE0F ; fully-qualified # 👩🏿‍⚖️ E4.0 woman judge: dark skin tone +1F469 1F3FF 200D 2696 ; minimally-qualified # 👩🏿‍⚖ E4.0 woman judge: dark skin tone +1F9D1 200D 1F33E ; fully-qualified # 🧑‍🌾 E12.1 farmer +1F9D1 1F3FB 200D 1F33E ; fully-qualified # 🧑🏻‍🌾 E12.1 farmer: light skin tone +1F9D1 1F3FC 200D 1F33E ; fully-qualified # 🧑🏼‍🌾 E12.1 farmer: medium-light skin tone +1F9D1 1F3FD 200D 1F33E ; fully-qualified # 🧑🏽‍🌾 E12.1 farmer: medium skin tone +1F9D1 1F3FE 200D 1F33E ; fully-qualified # 🧑🏾‍🌾 E12.1 farmer: medium-dark skin tone +1F9D1 1F3FF 200D 1F33E ; fully-qualified # 🧑🏿‍🌾 E12.1 farmer: dark skin tone +1F468 200D 1F33E ; fully-qualified # 👨‍🌾 E4.0 man farmer +1F468 1F3FB 200D 1F33E ; fully-qualified # 👨🏻‍🌾 E4.0 man farmer: light skin tone +1F468 1F3FC 200D 1F33E ; fully-qualified # 👨🏼‍🌾 E4.0 man farmer: medium-light skin tone +1F468 1F3FD 200D 1F33E ; fully-qualified # 👨🏽‍🌾 E4.0 man farmer: medium skin tone +1F468 1F3FE 200D 1F33E ; fully-qualified # 👨🏾‍🌾 E4.0 man farmer: medium-dark skin tone +1F468 1F3FF 200D 1F33E ; fully-qualified # 👨🏿‍🌾 E4.0 man farmer: dark skin tone +1F469 200D 1F33E ; fully-qualified # 👩‍🌾 E4.0 woman farmer +1F469 1F3FB 200D 1F33E ; fully-qualified # 👩🏻‍🌾 E4.0 woman farmer: light skin tone +1F469 1F3FC 200D 1F33E ; fully-qualified # 👩🏼‍🌾 E4.0 woman farmer: medium-light skin tone +1F469 1F3FD 200D 1F33E ; fully-qualified # 👩🏽‍🌾 E4.0 woman farmer: medium skin tone +1F469 1F3FE 200D 1F33E ; fully-qualified # 👩🏾‍🌾 E4.0 woman farmer: medium-dark skin tone +1F469 1F3FF 200D 1F33E ; fully-qualified # 👩🏿‍🌾 E4.0 woman farmer: dark skin tone +1F9D1 200D 1F373 ; fully-qualified # 🧑‍🍳 E12.1 cook +1F9D1 1F3FB 200D 1F373 ; fully-qualified # 🧑🏻‍🍳 E12.1 cook: light skin tone +1F9D1 1F3FC 200D 1F373 ; fully-qualified # 🧑🏼‍🍳 E12.1 cook: medium-light skin tone +1F9D1 1F3FD 200D 1F373 ; fully-qualified # 🧑🏽‍🍳 E12.1 cook: medium skin tone +1F9D1 1F3FE 200D 1F373 ; fully-qualified # 🧑🏾‍🍳 E12.1 cook: medium-dark skin tone +1F9D1 1F3FF 200D 1F373 ; fully-qualified # 🧑🏿‍🍳 E12.1 cook: dark skin tone +1F468 200D 1F373 ; fully-qualified # 👨‍🍳 E4.0 man cook +1F468 1F3FB 200D 1F373 ; fully-qualified # 👨🏻‍🍳 E4.0 man cook: light skin tone +1F468 1F3FC 200D 1F373 ; fully-qualified # 👨🏼‍🍳 E4.0 man cook: medium-light skin tone +1F468 1F3FD 200D 1F373 ; fully-qualified # 👨🏽‍🍳 E4.0 man cook: medium skin tone +1F468 1F3FE 200D 1F373 ; fully-qualified # 👨🏾‍🍳 E4.0 man cook: medium-dark skin tone +1F468 1F3FF 200D 1F373 ; fully-qualified # 👨🏿‍🍳 E4.0 man cook: dark skin tone +1F469 200D 1F373 ; fully-qualified # 👩‍🍳 E4.0 woman cook +1F469 1F3FB 200D 1F373 ; fully-qualified # 👩🏻‍🍳 E4.0 woman cook: light skin tone +1F469 1F3FC 200D 1F373 ; fully-qualified # 👩🏼‍🍳 E4.0 woman cook: medium-light skin tone +1F469 1F3FD 200D 1F373 ; fully-qualified # 👩🏽‍🍳 E4.0 woman cook: medium skin tone +1F469 1F3FE 200D 1F373 ; fully-qualified # 👩🏾‍🍳 E4.0 woman cook: medium-dark skin tone +1F469 1F3FF 200D 1F373 ; fully-qualified # 👩🏿‍🍳 E4.0 woman cook: dark skin tone +1F9D1 200D 1F527 ; fully-qualified # 🧑‍🔧 E12.1 mechanic +1F9D1 1F3FB 200D 1F527 ; fully-qualified # 🧑🏻‍🔧 E12.1 mechanic: light skin tone +1F9D1 1F3FC 200D 1F527 ; fully-qualified # 🧑🏼‍🔧 E12.1 mechanic: medium-light skin tone +1F9D1 1F3FD 200D 1F527 ; fully-qualified # 🧑🏽‍🔧 E12.1 mechanic: medium skin tone +1F9D1 1F3FE 200D 1F527 ; fully-qualified # 🧑🏾‍🔧 E12.1 mechanic: medium-dark skin tone +1F9D1 1F3FF 200D 1F527 ; fully-qualified # 🧑🏿‍🔧 E12.1 mechanic: dark skin tone +1F468 200D 1F527 ; fully-qualified # 👨‍🔧 E4.0 man mechanic +1F468 1F3FB 200D 1F527 ; fully-qualified # 👨🏻‍🔧 E4.0 man mechanic: light skin tone +1F468 1F3FC 200D 1F527 ; fully-qualified # 👨🏼‍🔧 E4.0 man mechanic: medium-light skin tone +1F468 1F3FD 200D 1F527 ; fully-qualified # 👨🏽‍🔧 E4.0 man mechanic: medium skin tone +1F468 1F3FE 200D 1F527 ; fully-qualified # 👨🏾‍🔧 E4.0 man mechanic: medium-dark skin tone +1F468 1F3FF 200D 1F527 ; fully-qualified # 👨🏿‍🔧 E4.0 man mechanic: dark skin tone +1F469 200D 1F527 ; fully-qualified # 👩‍🔧 E4.0 woman mechanic +1F469 1F3FB 200D 1F527 ; fully-qualified # 👩🏻‍🔧 E4.0 woman mechanic: light skin tone +1F469 1F3FC 200D 1F527 ; fully-qualified # 👩🏼‍🔧 E4.0 woman mechanic: medium-light skin tone +1F469 1F3FD 200D 1F527 ; fully-qualified # 👩🏽‍🔧 E4.0 woman mechanic: medium skin tone +1F469 1F3FE 200D 1F527 ; fully-qualified # 👩🏾‍🔧 E4.0 woman mechanic: medium-dark skin tone +1F469 1F3FF 200D 1F527 ; fully-qualified # 👩🏿‍🔧 E4.0 woman mechanic: dark skin tone +1F9D1 200D 1F3ED ; fully-qualified # 🧑‍🏭 E12.1 factory worker +1F9D1 1F3FB 200D 1F3ED ; fully-qualified # 🧑🏻‍🏭 E12.1 factory worker: light skin tone +1F9D1 1F3FC 200D 1F3ED ; fully-qualified # 🧑🏼‍🏭 E12.1 factory worker: medium-light skin tone +1F9D1 1F3FD 200D 1F3ED ; fully-qualified # 🧑🏽‍🏭 E12.1 factory worker: medium skin tone +1F9D1 1F3FE 200D 1F3ED ; fully-qualified # 🧑🏾‍🏭 E12.1 factory worker: medium-dark skin tone +1F9D1 1F3FF 200D 1F3ED ; fully-qualified # 🧑🏿‍🏭 E12.1 factory worker: dark skin tone +1F468 200D 1F3ED ; fully-qualified # 👨‍🏭 E4.0 man factory worker +1F468 1F3FB 200D 1F3ED ; fully-qualified # 👨🏻‍🏭 E4.0 man factory worker: light skin tone +1F468 1F3FC 200D 1F3ED ; fully-qualified # 👨🏼‍🏭 E4.0 man factory worker: medium-light skin tone +1F468 1F3FD 200D 1F3ED ; fully-qualified # 👨🏽‍🏭 E4.0 man factory worker: medium skin tone +1F468 1F3FE 200D 1F3ED ; fully-qualified # 👨🏾‍🏭 E4.0 man factory worker: medium-dark skin tone +1F468 1F3FF 200D 1F3ED ; fully-qualified # 👨🏿‍🏭 E4.0 man factory worker: dark skin tone +1F469 200D 1F3ED ; fully-qualified # 👩‍🏭 E4.0 woman factory worker +1F469 1F3FB 200D 1F3ED ; fully-qualified # 👩🏻‍🏭 E4.0 woman factory worker: light skin tone +1F469 1F3FC 200D 1F3ED ; fully-qualified # 👩🏼‍🏭 E4.0 woman factory worker: medium-light skin tone +1F469 1F3FD 200D 1F3ED ; fully-qualified # 👩🏽‍🏭 E4.0 woman factory worker: medium skin tone +1F469 1F3FE 200D 1F3ED ; fully-qualified # 👩🏾‍🏭 E4.0 woman factory worker: medium-dark skin tone +1F469 1F3FF 200D 1F3ED ; fully-qualified # 👩🏿‍🏭 E4.0 woman factory worker: dark skin tone +1F9D1 200D 1F4BC ; fully-qualified # 🧑‍💼 E12.1 office worker +1F9D1 1F3FB 200D 1F4BC ; fully-qualified # 🧑🏻‍💼 E12.1 office worker: light skin tone +1F9D1 1F3FC 200D 1F4BC ; fully-qualified # 🧑🏼‍💼 E12.1 office worker: medium-light skin tone +1F9D1 1F3FD 200D 1F4BC ; fully-qualified # 🧑🏽‍💼 E12.1 office worker: medium skin tone +1F9D1 1F3FE 200D 1F4BC ; fully-qualified # 🧑🏾‍💼 E12.1 office worker: medium-dark skin tone +1F9D1 1F3FF 200D 1F4BC ; fully-qualified # 🧑🏿‍💼 E12.1 office worker: dark skin tone +1F468 200D 1F4BC ; fully-qualified # 👨‍💼 E4.0 man office worker +1F468 1F3FB 200D 1F4BC ; fully-qualified # 👨🏻‍💼 E4.0 man office worker: light skin tone +1F468 1F3FC 200D 1F4BC ; fully-qualified # 👨🏼‍💼 E4.0 man office worker: medium-light skin tone +1F468 1F3FD 200D 1F4BC ; fully-qualified # 👨🏽‍💼 E4.0 man office worker: medium skin tone +1F468 1F3FE 200D 1F4BC ; fully-qualified # 👨🏾‍💼 E4.0 man office worker: medium-dark skin tone +1F468 1F3FF 200D 1F4BC ; fully-qualified # 👨🏿‍💼 E4.0 man office worker: dark skin tone +1F469 200D 1F4BC ; fully-qualified # 👩‍💼 E4.0 woman office worker +1F469 1F3FB 200D 1F4BC ; fully-qualified # 👩🏻‍💼 E4.0 woman office worker: light skin tone +1F469 1F3FC 200D 1F4BC ; fully-qualified # 👩🏼‍💼 E4.0 woman office worker: medium-light skin tone +1F469 1F3FD 200D 1F4BC ; fully-qualified # 👩🏽‍💼 E4.0 woman office worker: medium skin tone +1F469 1F3FE 200D 1F4BC ; fully-qualified # 👩🏾‍💼 E4.0 woman office worker: medium-dark skin tone +1F469 1F3FF 200D 1F4BC ; fully-qualified # 👩🏿‍💼 E4.0 woman office worker: dark skin tone +1F9D1 200D 1F52C ; fully-qualified # 🧑‍🔬 E12.1 scientist +1F9D1 1F3FB 200D 1F52C ; fully-qualified # 🧑🏻‍🔬 E12.1 scientist: light skin tone +1F9D1 1F3FC 200D 1F52C ; fully-qualified # 🧑🏼‍🔬 E12.1 scientist: medium-light skin tone +1F9D1 1F3FD 200D 1F52C ; fully-qualified # 🧑🏽‍🔬 E12.1 scientist: medium skin tone +1F9D1 1F3FE 200D 1F52C ; fully-qualified # 🧑🏾‍🔬 E12.1 scientist: medium-dark skin tone +1F9D1 1F3FF 200D 1F52C ; fully-qualified # 🧑🏿‍🔬 E12.1 scientist: dark skin tone +1F468 200D 1F52C ; fully-qualified # 👨‍🔬 E4.0 man scientist +1F468 1F3FB 200D 1F52C ; fully-qualified # 👨🏻‍🔬 E4.0 man scientist: light skin tone +1F468 1F3FC 200D 1F52C ; fully-qualified # 👨🏼‍🔬 E4.0 man scientist: medium-light skin tone +1F468 1F3FD 200D 1F52C ; fully-qualified # 👨🏽‍🔬 E4.0 man scientist: medium skin tone +1F468 1F3FE 200D 1F52C ; fully-qualified # 👨🏾‍🔬 E4.0 man scientist: medium-dark skin tone +1F468 1F3FF 200D 1F52C ; fully-qualified # 👨🏿‍🔬 E4.0 man scientist: dark skin tone +1F469 200D 1F52C ; fully-qualified # 👩‍🔬 E4.0 woman scientist +1F469 1F3FB 200D 1F52C ; fully-qualified # 👩🏻‍🔬 E4.0 woman scientist: light skin tone +1F469 1F3FC 200D 1F52C ; fully-qualified # 👩🏼‍🔬 E4.0 woman scientist: medium-light skin tone +1F469 1F3FD 200D 1F52C ; fully-qualified # 👩🏽‍🔬 E4.0 woman scientist: medium skin tone +1F469 1F3FE 200D 1F52C ; fully-qualified # 👩🏾‍🔬 E4.0 woman scientist: medium-dark skin tone +1F469 1F3FF 200D 1F52C ; fully-qualified # 👩🏿‍🔬 E4.0 woman scientist: dark skin tone +1F9D1 200D 1F4BB ; fully-qualified # 🧑‍💻 E12.1 technologist +1F9D1 1F3FB 200D 1F4BB ; fully-qualified # 🧑🏻‍💻 E12.1 technologist: light skin tone +1F9D1 1F3FC 200D 1F4BB ; fully-qualified # 🧑🏼‍💻 E12.1 technologist: medium-light skin tone +1F9D1 1F3FD 200D 1F4BB ; fully-qualified # 🧑🏽‍💻 E12.1 technologist: medium skin tone +1F9D1 1F3FE 200D 1F4BB ; fully-qualified # 🧑🏾‍💻 E12.1 technologist: medium-dark skin tone +1F9D1 1F3FF 200D 1F4BB ; fully-qualified # 🧑🏿‍💻 E12.1 technologist: dark skin tone +1F468 200D 1F4BB ; fully-qualified # 👨‍💻 E4.0 man technologist +1F468 1F3FB 200D 1F4BB ; fully-qualified # 👨🏻‍💻 E4.0 man technologist: light skin tone +1F468 1F3FC 200D 1F4BB ; fully-qualified # 👨🏼‍💻 E4.0 man technologist: medium-light skin tone +1F468 1F3FD 200D 1F4BB ; fully-qualified # 👨🏽‍💻 E4.0 man technologist: medium skin tone +1F468 1F3FE 200D 1F4BB ; fully-qualified # 👨🏾‍💻 E4.0 man technologist: medium-dark skin tone +1F468 1F3FF 200D 1F4BB ; fully-qualified # 👨🏿‍💻 E4.0 man technologist: dark skin tone +1F469 200D 1F4BB ; fully-qualified # 👩‍💻 E4.0 woman technologist +1F469 1F3FB 200D 1F4BB ; fully-qualified # 👩🏻‍💻 E4.0 woman technologist: light skin tone +1F469 1F3FC 200D 1F4BB ; fully-qualified # 👩🏼‍💻 E4.0 woman technologist: medium-light skin tone +1F469 1F3FD 200D 1F4BB ; fully-qualified # 👩🏽‍💻 E4.0 woman technologist: medium skin tone +1F469 1F3FE 200D 1F4BB ; fully-qualified # 👩🏾‍💻 E4.0 woman technologist: medium-dark skin tone +1F469 1F3FF 200D 1F4BB ; fully-qualified # 👩🏿‍💻 E4.0 woman technologist: dark skin tone +1F9D1 200D 1F3A4 ; fully-qualified # 🧑‍🎤 E12.1 singer +1F9D1 1F3FB 200D 1F3A4 ; fully-qualified # 🧑🏻‍🎤 E12.1 singer: light skin tone +1F9D1 1F3FC 200D 1F3A4 ; fully-qualified # 🧑🏼‍🎤 E12.1 singer: medium-light skin tone +1F9D1 1F3FD 200D 1F3A4 ; fully-qualified # 🧑🏽‍🎤 E12.1 singer: medium skin tone +1F9D1 1F3FE 200D 1F3A4 ; fully-qualified # 🧑🏾‍🎤 E12.1 singer: medium-dark skin tone +1F9D1 1F3FF 200D 1F3A4 ; fully-qualified # 🧑🏿‍🎤 E12.1 singer: dark skin tone +1F468 200D 1F3A4 ; fully-qualified # 👨‍🎤 E4.0 man singer +1F468 1F3FB 200D 1F3A4 ; fully-qualified # 👨🏻‍🎤 E4.0 man singer: light skin tone +1F468 1F3FC 200D 1F3A4 ; fully-qualified # 👨🏼‍🎤 E4.0 man singer: medium-light skin tone +1F468 1F3FD 200D 1F3A4 ; fully-qualified # 👨🏽‍🎤 E4.0 man singer: medium skin tone +1F468 1F3FE 200D 1F3A4 ; fully-qualified # 👨🏾‍🎤 E4.0 man singer: medium-dark skin tone +1F468 1F3FF 200D 1F3A4 ; fully-qualified # 👨🏿‍🎤 E4.0 man singer: dark skin tone +1F469 200D 1F3A4 ; fully-qualified # 👩‍🎤 E4.0 woman singer +1F469 1F3FB 200D 1F3A4 ; fully-qualified # 👩🏻‍🎤 E4.0 woman singer: light skin tone +1F469 1F3FC 200D 1F3A4 ; fully-qualified # 👩🏼‍🎤 E4.0 woman singer: medium-light skin tone +1F469 1F3FD 200D 1F3A4 ; fully-qualified # 👩🏽‍🎤 E4.0 woman singer: medium skin tone +1F469 1F3FE 200D 1F3A4 ; fully-qualified # 👩🏾‍🎤 E4.0 woman singer: medium-dark skin tone +1F469 1F3FF 200D 1F3A4 ; fully-qualified # 👩🏿‍🎤 E4.0 woman singer: dark skin tone +1F9D1 200D 1F3A8 ; fully-qualified # 🧑‍🎨 E12.1 artist +1F9D1 1F3FB 200D 1F3A8 ; fully-qualified # 🧑🏻‍🎨 E12.1 artist: light skin tone +1F9D1 1F3FC 200D 1F3A8 ; fully-qualified # 🧑🏼‍🎨 E12.1 artist: medium-light skin tone +1F9D1 1F3FD 200D 1F3A8 ; fully-qualified # 🧑🏽‍🎨 E12.1 artist: medium skin tone +1F9D1 1F3FE 200D 1F3A8 ; fully-qualified # 🧑🏾‍🎨 E12.1 artist: medium-dark skin tone +1F9D1 1F3FF 200D 1F3A8 ; fully-qualified # 🧑🏿‍🎨 E12.1 artist: dark skin tone +1F468 200D 1F3A8 ; fully-qualified # 👨‍🎨 E4.0 man artist +1F468 1F3FB 200D 1F3A8 ; fully-qualified # 👨🏻‍🎨 E4.0 man artist: light skin tone +1F468 1F3FC 200D 1F3A8 ; fully-qualified # 👨🏼‍🎨 E4.0 man artist: medium-light skin tone +1F468 1F3FD 200D 1F3A8 ; fully-qualified # 👨🏽‍🎨 E4.0 man artist: medium skin tone +1F468 1F3FE 200D 1F3A8 ; fully-qualified # 👨🏾‍🎨 E4.0 man artist: medium-dark skin tone +1F468 1F3FF 200D 1F3A8 ; fully-qualified # 👨🏿‍🎨 E4.0 man artist: dark skin tone +1F469 200D 1F3A8 ; fully-qualified # 👩‍🎨 E4.0 woman artist +1F469 1F3FB 200D 1F3A8 ; fully-qualified # 👩🏻‍🎨 E4.0 woman artist: light skin tone +1F469 1F3FC 200D 1F3A8 ; fully-qualified # 👩🏼‍🎨 E4.0 woman artist: medium-light skin tone +1F469 1F3FD 200D 1F3A8 ; fully-qualified # 👩🏽‍🎨 E4.0 woman artist: medium skin tone +1F469 1F3FE 200D 1F3A8 ; fully-qualified # 👩🏾‍🎨 E4.0 woman artist: medium-dark skin tone +1F469 1F3FF 200D 1F3A8 ; fully-qualified # 👩🏿‍🎨 E4.0 woman artist: dark skin tone +1F9D1 200D 2708 FE0F ; fully-qualified # 🧑‍✈️ E12.1 pilot +1F9D1 200D 2708 ; minimally-qualified # 🧑‍✈ E12.1 pilot +1F9D1 1F3FB 200D 2708 FE0F ; fully-qualified # 🧑🏻‍✈️ E12.1 pilot: light skin tone +1F9D1 1F3FB 200D 2708 ; minimally-qualified # 🧑🏻‍✈ E12.1 pilot: light skin tone +1F9D1 1F3FC 200D 2708 FE0F ; fully-qualified # 🧑🏼‍✈️ E12.1 pilot: medium-light skin tone +1F9D1 1F3FC 200D 2708 ; minimally-qualified # 🧑🏼‍✈ E12.1 pilot: medium-light skin tone +1F9D1 1F3FD 200D 2708 FE0F ; fully-qualified # 🧑🏽‍✈️ E12.1 pilot: medium skin tone +1F9D1 1F3FD 200D 2708 ; minimally-qualified # 🧑🏽‍✈ E12.1 pilot: medium skin tone +1F9D1 1F3FE 200D 2708 FE0F ; fully-qualified # 🧑🏾‍✈️ E12.1 pilot: medium-dark skin tone +1F9D1 1F3FE 200D 2708 ; minimally-qualified # 🧑🏾‍✈ E12.1 pilot: medium-dark skin tone +1F9D1 1F3FF 200D 2708 FE0F ; fully-qualified # 🧑🏿‍✈️ E12.1 pilot: dark skin tone +1F9D1 1F3FF 200D 2708 ; minimally-qualified # 🧑🏿‍✈ E12.1 pilot: dark skin tone +1F468 200D 2708 FE0F ; fully-qualified # 👨‍✈️ E4.0 man pilot +1F468 200D 2708 ; minimally-qualified # 👨‍✈ E4.0 man pilot +1F468 1F3FB 200D 2708 FE0F ; fully-qualified # 👨🏻‍✈️ E4.0 man pilot: light skin tone +1F468 1F3FB 200D 2708 ; minimally-qualified # 👨🏻‍✈ E4.0 man pilot: light skin tone +1F468 1F3FC 200D 2708 FE0F ; fully-qualified # 👨🏼‍✈️ E4.0 man pilot: medium-light skin tone +1F468 1F3FC 200D 2708 ; minimally-qualified # 👨🏼‍✈ E4.0 man pilot: medium-light skin tone +1F468 1F3FD 200D 2708 FE0F ; fully-qualified # 👨🏽‍✈️ E4.0 man pilot: medium skin tone +1F468 1F3FD 200D 2708 ; minimally-qualified # 👨🏽‍✈ E4.0 man pilot: medium skin tone +1F468 1F3FE 200D 2708 FE0F ; fully-qualified # 👨🏾‍✈️ E4.0 man pilot: medium-dark skin tone +1F468 1F3FE 200D 2708 ; minimally-qualified # 👨🏾‍✈ E4.0 man pilot: medium-dark skin tone +1F468 1F3FF 200D 2708 FE0F ; fully-qualified # 👨🏿‍✈️ E4.0 man pilot: dark skin tone +1F468 1F3FF 200D 2708 ; minimally-qualified # 👨🏿‍✈ E4.0 man pilot: dark skin tone +1F469 200D 2708 FE0F ; fully-qualified # 👩‍✈️ E4.0 woman pilot +1F469 200D 2708 ; minimally-qualified # 👩‍✈ E4.0 woman pilot +1F469 1F3FB 200D 2708 FE0F ; fully-qualified # 👩🏻‍✈️ E4.0 woman pilot: light skin tone +1F469 1F3FB 200D 2708 ; minimally-qualified # 👩🏻‍✈ E4.0 woman pilot: light skin tone +1F469 1F3FC 200D 2708 FE0F ; fully-qualified # 👩🏼‍✈️ E4.0 woman pilot: medium-light skin tone +1F469 1F3FC 200D 2708 ; minimally-qualified # 👩🏼‍✈ E4.0 woman pilot: medium-light skin tone +1F469 1F3FD 200D 2708 FE0F ; fully-qualified # 👩🏽‍✈️ E4.0 woman pilot: medium skin tone +1F469 1F3FD 200D 2708 ; minimally-qualified # 👩🏽‍✈ E4.0 woman pilot: medium skin tone +1F469 1F3FE 200D 2708 FE0F ; fully-qualified # 👩🏾‍✈️ E4.0 woman pilot: medium-dark skin tone +1F469 1F3FE 200D 2708 ; minimally-qualified # 👩🏾‍✈ E4.0 woman pilot: medium-dark skin tone +1F469 1F3FF 200D 2708 FE0F ; fully-qualified # 👩🏿‍✈️ E4.0 woman pilot: dark skin tone +1F469 1F3FF 200D 2708 ; minimally-qualified # 👩🏿‍✈ E4.0 woman pilot: dark skin tone +1F9D1 200D 1F680 ; fully-qualified # 🧑‍🚀 E12.1 astronaut +1F9D1 1F3FB 200D 1F680 ; fully-qualified # 🧑🏻‍🚀 E12.1 astronaut: light skin tone +1F9D1 1F3FC 200D 1F680 ; fully-qualified # 🧑🏼‍🚀 E12.1 astronaut: medium-light skin tone +1F9D1 1F3FD 200D 1F680 ; fully-qualified # 🧑🏽‍🚀 E12.1 astronaut: medium skin tone +1F9D1 1F3FE 200D 1F680 ; fully-qualified # 🧑🏾‍🚀 E12.1 astronaut: medium-dark skin tone +1F9D1 1F3FF 200D 1F680 ; fully-qualified # 🧑🏿‍🚀 E12.1 astronaut: dark skin tone +1F468 200D 1F680 ; fully-qualified # 👨‍🚀 E4.0 man astronaut +1F468 1F3FB 200D 1F680 ; fully-qualified # 👨🏻‍🚀 E4.0 man astronaut: light skin tone +1F468 1F3FC 200D 1F680 ; fully-qualified # 👨🏼‍🚀 E4.0 man astronaut: medium-light skin tone +1F468 1F3FD 200D 1F680 ; fully-qualified # 👨🏽‍🚀 E4.0 man astronaut: medium skin tone +1F468 1F3FE 200D 1F680 ; fully-qualified # 👨🏾‍🚀 E4.0 man astronaut: medium-dark skin tone +1F468 1F3FF 200D 1F680 ; fully-qualified # 👨🏿‍🚀 E4.0 man astronaut: dark skin tone +1F469 200D 1F680 ; fully-qualified # 👩‍🚀 E4.0 woman astronaut +1F469 1F3FB 200D 1F680 ; fully-qualified # 👩🏻‍🚀 E4.0 woman astronaut: light skin tone +1F469 1F3FC 200D 1F680 ; fully-qualified # 👩🏼‍🚀 E4.0 woman astronaut: medium-light skin tone +1F469 1F3FD 200D 1F680 ; fully-qualified # 👩🏽‍🚀 E4.0 woman astronaut: medium skin tone +1F469 1F3FE 200D 1F680 ; fully-qualified # 👩🏾‍🚀 E4.0 woman astronaut: medium-dark skin tone +1F469 1F3FF 200D 1F680 ; fully-qualified # 👩🏿‍🚀 E4.0 woman astronaut: dark skin tone +1F9D1 200D 1F692 ; fully-qualified # 🧑‍🚒 E12.1 firefighter +1F9D1 1F3FB 200D 1F692 ; fully-qualified # 🧑🏻‍🚒 E12.1 firefighter: light skin tone +1F9D1 1F3FC 200D 1F692 ; fully-qualified # 🧑🏼‍🚒 E12.1 firefighter: medium-light skin tone +1F9D1 1F3FD 200D 1F692 ; fully-qualified # 🧑🏽‍🚒 E12.1 firefighter: medium skin tone +1F9D1 1F3FE 200D 1F692 ; fully-qualified # 🧑🏾‍🚒 E12.1 firefighter: medium-dark skin tone +1F9D1 1F3FF 200D 1F692 ; fully-qualified # 🧑🏿‍🚒 E12.1 firefighter: dark skin tone +1F468 200D 1F692 ; fully-qualified # 👨‍🚒 E4.0 man firefighter +1F468 1F3FB 200D 1F692 ; fully-qualified # 👨🏻‍🚒 E4.0 man firefighter: light skin tone +1F468 1F3FC 200D 1F692 ; fully-qualified # 👨🏼‍🚒 E4.0 man firefighter: medium-light skin tone +1F468 1F3FD 200D 1F692 ; fully-qualified # 👨🏽‍🚒 E4.0 man firefighter: medium skin tone +1F468 1F3FE 200D 1F692 ; fully-qualified # 👨🏾‍🚒 E4.0 man firefighter: medium-dark skin tone +1F468 1F3FF 200D 1F692 ; fully-qualified # 👨🏿‍🚒 E4.0 man firefighter: dark skin tone +1F469 200D 1F692 ; fully-qualified # 👩‍🚒 E4.0 woman firefighter +1F469 1F3FB 200D 1F692 ; fully-qualified # 👩🏻‍🚒 E4.0 woman firefighter: light skin tone +1F469 1F3FC 200D 1F692 ; fully-qualified # 👩🏼‍🚒 E4.0 woman firefighter: medium-light skin tone +1F469 1F3FD 200D 1F692 ; fully-qualified # 👩🏽‍🚒 E4.0 woman firefighter: medium skin tone +1F469 1F3FE 200D 1F692 ; fully-qualified # 👩🏾‍🚒 E4.0 woman firefighter: medium-dark skin tone +1F469 1F3FF 200D 1F692 ; fully-qualified # 👩🏿‍🚒 E4.0 woman firefighter: dark skin tone +1F46E ; fully-qualified # 👮 E0.6 police officer +1F46E 1F3FB ; fully-qualified # 👮🏻 E1.0 police officer: light skin tone +1F46E 1F3FC ; fully-qualified # 👮🏼 E1.0 police officer: medium-light skin tone +1F46E 1F3FD ; fully-qualified # 👮🏽 E1.0 police officer: medium skin tone +1F46E 1F3FE ; fully-qualified # 👮🏾 E1.0 police officer: medium-dark skin tone +1F46E 1F3FF ; fully-qualified # 👮🏿 E1.0 police officer: dark skin tone +1F46E 200D 2642 FE0F ; fully-qualified # 👮‍♂️ E4.0 man police officer +1F46E 200D 2642 ; minimally-qualified # 👮‍♂ E4.0 man police officer +1F46E 1F3FB 200D 2642 FE0F ; fully-qualified # 👮🏻‍♂️ E4.0 man police officer: light skin tone +1F46E 1F3FB 200D 2642 ; minimally-qualified # 👮🏻‍♂ E4.0 man police officer: light skin tone +1F46E 1F3FC 200D 2642 FE0F ; fully-qualified # 👮🏼‍♂️ E4.0 man police officer: medium-light skin tone +1F46E 1F3FC 200D 2642 ; minimally-qualified # 👮🏼‍♂ E4.0 man police officer: medium-light skin tone +1F46E 1F3FD 200D 2642 FE0F ; fully-qualified # 👮🏽‍♂️ E4.0 man police officer: medium skin tone +1F46E 1F3FD 200D 2642 ; minimally-qualified # 👮🏽‍♂ E4.0 man police officer: medium skin tone +1F46E 1F3FE 200D 2642 FE0F ; fully-qualified # 👮🏾‍♂️ E4.0 man police officer: medium-dark skin tone +1F46E 1F3FE 200D 2642 ; minimally-qualified # 👮🏾‍♂ E4.0 man police officer: medium-dark skin tone +1F46E 1F3FF 200D 2642 FE0F ; fully-qualified # 👮🏿‍♂️ E4.0 man police officer: dark skin tone +1F46E 1F3FF 200D 2642 ; minimally-qualified # 👮🏿‍♂ E4.0 man police officer: dark skin tone +1F46E 200D 2640 FE0F ; fully-qualified # 👮‍♀️ E4.0 woman police officer +1F46E 200D 2640 ; minimally-qualified # 👮‍♀ E4.0 woman police officer +1F46E 1F3FB 200D 2640 FE0F ; fully-qualified # 👮🏻‍♀️ E4.0 woman police officer: light skin tone +1F46E 1F3FB 200D 2640 ; minimally-qualified # 👮🏻‍♀ E4.0 woman police officer: light skin tone +1F46E 1F3FC 200D 2640 FE0F ; fully-qualified # 👮🏼‍♀️ E4.0 woman police officer: medium-light skin tone +1F46E 1F3FC 200D 2640 ; minimally-qualified # 👮🏼‍♀ E4.0 woman police officer: medium-light skin tone +1F46E 1F3FD 200D 2640 FE0F ; fully-qualified # 👮🏽‍♀️ E4.0 woman police officer: medium skin tone +1F46E 1F3FD 200D 2640 ; minimally-qualified # 👮🏽‍♀ E4.0 woman police officer: medium skin tone +1F46E 1F3FE 200D 2640 FE0F ; fully-qualified # 👮🏾‍♀️ E4.0 woman police officer: medium-dark skin tone +1F46E 1F3FE 200D 2640 ; minimally-qualified # 👮🏾‍♀ E4.0 woman police officer: medium-dark skin tone +1F46E 1F3FF 200D 2640 FE0F ; fully-qualified # 👮🏿‍♀️ E4.0 woman police officer: dark skin tone +1F46E 1F3FF 200D 2640 ; minimally-qualified # 👮🏿‍♀ E4.0 woman police officer: dark skin tone +1F575 FE0F ; fully-qualified # 🕵️ E0.7 detective +1F575 ; unqualified # 🕵 E0.7 detective +1F575 1F3FB ; fully-qualified # 🕵🏻 E2.0 detective: light skin tone +1F575 1F3FC ; fully-qualified # 🕵🏼 E2.0 detective: medium-light skin tone +1F575 1F3FD ; fully-qualified # 🕵🏽 E2.0 detective: medium skin tone +1F575 1F3FE ; fully-qualified # 🕵🏾 E2.0 detective: medium-dark skin tone +1F575 1F3FF ; fully-qualified # 🕵🏿 E2.0 detective: dark skin tone +1F575 FE0F 200D 2642 FE0F ; fully-qualified # 🕵️‍♂️ E4.0 man detective +1F575 200D 2642 FE0F ; unqualified # 🕵‍♂️ E4.0 man detective +1F575 FE0F 200D 2642 ; minimally-qualified # 🕵️‍♂ E4.0 man detective +1F575 200D 2642 ; unqualified # 🕵‍♂ E4.0 man detective +1F575 1F3FB 200D 2642 FE0F ; fully-qualified # 🕵🏻‍♂️ E4.0 man detective: light skin tone +1F575 1F3FB 200D 2642 ; minimally-qualified # 🕵🏻‍♂ E4.0 man detective: light skin tone +1F575 1F3FC 200D 2642 FE0F ; fully-qualified # 🕵🏼‍♂️ E4.0 man detective: medium-light skin tone +1F575 1F3FC 200D 2642 ; minimally-qualified # 🕵🏼‍♂ E4.0 man detective: medium-light skin tone +1F575 1F3FD 200D 2642 FE0F ; fully-qualified # 🕵🏽‍♂️ E4.0 man detective: medium skin tone +1F575 1F3FD 200D 2642 ; minimally-qualified # 🕵🏽‍♂ E4.0 man detective: medium skin tone +1F575 1F3FE 200D 2642 FE0F ; fully-qualified # 🕵🏾‍♂️ E4.0 man detective: medium-dark skin tone +1F575 1F3FE 200D 2642 ; minimally-qualified # 🕵🏾‍♂ E4.0 man detective: medium-dark skin tone +1F575 1F3FF 200D 2642 FE0F ; fully-qualified # 🕵🏿‍♂️ E4.0 man detective: dark skin tone +1F575 1F3FF 200D 2642 ; minimally-qualified # 🕵🏿‍♂ E4.0 man detective: dark skin tone +1F575 FE0F 200D 2640 FE0F ; fully-qualified # 🕵️‍♀️ E4.0 woman detective +1F575 200D 2640 FE0F ; unqualified # 🕵‍♀️ E4.0 woman detective +1F575 FE0F 200D 2640 ; minimally-qualified # 🕵️‍♀ E4.0 woman detective +1F575 200D 2640 ; unqualified # 🕵‍♀ E4.0 woman detective +1F575 1F3FB 200D 2640 FE0F ; fully-qualified # 🕵🏻‍♀️ E4.0 woman detective: light skin tone +1F575 1F3FB 200D 2640 ; minimally-qualified # 🕵🏻‍♀ E4.0 woman detective: light skin tone +1F575 1F3FC 200D 2640 FE0F ; fully-qualified # 🕵🏼‍♀️ E4.0 woman detective: medium-light skin tone +1F575 1F3FC 200D 2640 ; minimally-qualified # 🕵🏼‍♀ E4.0 woman detective: medium-light skin tone +1F575 1F3FD 200D 2640 FE0F ; fully-qualified # 🕵🏽‍♀️ E4.0 woman detective: medium skin tone +1F575 1F3FD 200D 2640 ; minimally-qualified # 🕵🏽‍♀ E4.0 woman detective: medium skin tone +1F575 1F3FE 200D 2640 FE0F ; fully-qualified # 🕵🏾‍♀️ E4.0 woman detective: medium-dark skin tone +1F575 1F3FE 200D 2640 ; minimally-qualified # 🕵🏾‍♀ E4.0 woman detective: medium-dark skin tone +1F575 1F3FF 200D 2640 FE0F ; fully-qualified # 🕵🏿‍♀️ E4.0 woman detective: dark skin tone +1F575 1F3FF 200D 2640 ; minimally-qualified # 🕵🏿‍♀ E4.0 woman detective: dark skin tone +1F482 ; fully-qualified # 💂 E0.6 guard +1F482 1F3FB ; fully-qualified # 💂🏻 E1.0 guard: light skin tone +1F482 1F3FC ; fully-qualified # 💂🏼 E1.0 guard: medium-light skin tone +1F482 1F3FD ; fully-qualified # 💂🏽 E1.0 guard: medium skin tone +1F482 1F3FE ; fully-qualified # 💂🏾 E1.0 guard: medium-dark skin tone +1F482 1F3FF ; fully-qualified # 💂🏿 E1.0 guard: dark skin tone +1F482 200D 2642 FE0F ; fully-qualified # 💂‍♂️ E4.0 man guard +1F482 200D 2642 ; minimally-qualified # 💂‍♂ E4.0 man guard +1F482 1F3FB 200D 2642 FE0F ; fully-qualified # 💂🏻‍♂️ E4.0 man guard: light skin tone +1F482 1F3FB 200D 2642 ; minimally-qualified # 💂🏻‍♂ E4.0 man guard: light skin tone +1F482 1F3FC 200D 2642 FE0F ; fully-qualified # 💂🏼‍♂️ E4.0 man guard: medium-light skin tone +1F482 1F3FC 200D 2642 ; minimally-qualified # 💂🏼‍♂ E4.0 man guard: medium-light skin tone +1F482 1F3FD 200D 2642 FE0F ; fully-qualified # 💂🏽‍♂️ E4.0 man guard: medium skin tone +1F482 1F3FD 200D 2642 ; minimally-qualified # 💂🏽‍♂ E4.0 man guard: medium skin tone +1F482 1F3FE 200D 2642 FE0F ; fully-qualified # 💂🏾‍♂️ E4.0 man guard: medium-dark skin tone +1F482 1F3FE 200D 2642 ; minimally-qualified # 💂🏾‍♂ E4.0 man guard: medium-dark skin tone +1F482 1F3FF 200D 2642 FE0F ; fully-qualified # 💂🏿‍♂️ E4.0 man guard: dark skin tone +1F482 1F3FF 200D 2642 ; minimally-qualified # 💂🏿‍♂ E4.0 man guard: dark skin tone +1F482 200D 2640 FE0F ; fully-qualified # 💂‍♀️ E4.0 woman guard +1F482 200D 2640 ; minimally-qualified # 💂‍♀ E4.0 woman guard +1F482 1F3FB 200D 2640 FE0F ; fully-qualified # 💂🏻‍♀️ E4.0 woman guard: light skin tone +1F482 1F3FB 200D 2640 ; minimally-qualified # 💂🏻‍♀ E4.0 woman guard: light skin tone +1F482 1F3FC 200D 2640 FE0F ; fully-qualified # 💂🏼‍♀️ E4.0 woman guard: medium-light skin tone +1F482 1F3FC 200D 2640 ; minimally-qualified # 💂🏼‍♀ E4.0 woman guard: medium-light skin tone +1F482 1F3FD 200D 2640 FE0F ; fully-qualified # 💂🏽‍♀️ E4.0 woman guard: medium skin tone +1F482 1F3FD 200D 2640 ; minimally-qualified # 💂🏽‍♀ E4.0 woman guard: medium skin tone +1F482 1F3FE 200D 2640 FE0F ; fully-qualified # 💂🏾‍♀️ E4.0 woman guard: medium-dark skin tone +1F482 1F3FE 200D 2640 ; minimally-qualified # 💂🏾‍♀ E4.0 woman guard: medium-dark skin tone +1F482 1F3FF 200D 2640 FE0F ; fully-qualified # 💂🏿‍♀️ E4.0 woman guard: dark skin tone +1F482 1F3FF 200D 2640 ; minimally-qualified # 💂🏿‍♀ E4.0 woman guard: dark skin tone +1F977 ; fully-qualified # 🥷 E13.0 ninja +1F977 1F3FB ; fully-qualified # 🥷🏻 E13.0 ninja: light skin tone +1F977 1F3FC ; fully-qualified # 🥷🏼 E13.0 ninja: medium-light skin tone +1F977 1F3FD ; fully-qualified # 🥷🏽 E13.0 ninja: medium skin tone +1F977 1F3FE ; fully-qualified # 🥷🏾 E13.0 ninja: medium-dark skin tone +1F977 1F3FF ; fully-qualified # 🥷🏿 E13.0 ninja: dark skin tone +1F477 ; fully-qualified # 👷 E0.6 construction worker +1F477 1F3FB ; fully-qualified # 👷🏻 E1.0 construction worker: light skin tone +1F477 1F3FC ; fully-qualified # 👷🏼 E1.0 construction worker: medium-light skin tone +1F477 1F3FD ; fully-qualified # 👷🏽 E1.0 construction worker: medium skin tone +1F477 1F3FE ; fully-qualified # 👷🏾 E1.0 construction worker: medium-dark skin tone +1F477 1F3FF ; fully-qualified # 👷🏿 E1.0 construction worker: dark skin tone +1F477 200D 2642 FE0F ; fully-qualified # 👷‍♂️ E4.0 man construction worker +1F477 200D 2642 ; minimally-qualified # 👷‍♂ E4.0 man construction worker +1F477 1F3FB 200D 2642 FE0F ; fully-qualified # 👷🏻‍♂️ E4.0 man construction worker: light skin tone +1F477 1F3FB 200D 2642 ; minimally-qualified # 👷🏻‍♂ E4.0 man construction worker: light skin tone +1F477 1F3FC 200D 2642 FE0F ; fully-qualified # 👷🏼‍♂️ E4.0 man construction worker: medium-light skin tone +1F477 1F3FC 200D 2642 ; minimally-qualified # 👷🏼‍♂ E4.0 man construction worker: medium-light skin tone +1F477 1F3FD 200D 2642 FE0F ; fully-qualified # 👷🏽‍♂️ E4.0 man construction worker: medium skin tone +1F477 1F3FD 200D 2642 ; minimally-qualified # 👷🏽‍♂ E4.0 man construction worker: medium skin tone +1F477 1F3FE 200D 2642 FE0F ; fully-qualified # 👷🏾‍♂️ E4.0 man construction worker: medium-dark skin tone +1F477 1F3FE 200D 2642 ; minimally-qualified # 👷🏾‍♂ E4.0 man construction worker: medium-dark skin tone +1F477 1F3FF 200D 2642 FE0F ; fully-qualified # 👷🏿‍♂️ E4.0 man construction worker: dark skin tone +1F477 1F3FF 200D 2642 ; minimally-qualified # 👷🏿‍♂ E4.0 man construction worker: dark skin tone +1F477 200D 2640 FE0F ; fully-qualified # 👷‍♀️ E4.0 woman construction worker +1F477 200D 2640 ; minimally-qualified # 👷‍♀ E4.0 woman construction worker +1F477 1F3FB 200D 2640 FE0F ; fully-qualified # 👷🏻‍♀️ E4.0 woman construction worker: light skin tone +1F477 1F3FB 200D 2640 ; minimally-qualified # 👷🏻‍♀ E4.0 woman construction worker: light skin tone +1F477 1F3FC 200D 2640 FE0F ; fully-qualified # 👷🏼‍♀️ E4.0 woman construction worker: medium-light skin tone +1F477 1F3FC 200D 2640 ; minimally-qualified # 👷🏼‍♀ E4.0 woman construction worker: medium-light skin tone +1F477 1F3FD 200D 2640 FE0F ; fully-qualified # 👷🏽‍♀️ E4.0 woman construction worker: medium skin tone +1F477 1F3FD 200D 2640 ; minimally-qualified # 👷🏽‍♀ E4.0 woman construction worker: medium skin tone +1F477 1F3FE 200D 2640 FE0F ; fully-qualified # 👷🏾‍♀️ E4.0 woman construction worker: medium-dark skin tone +1F477 1F3FE 200D 2640 ; minimally-qualified # 👷🏾‍♀ E4.0 woman construction worker: medium-dark skin tone +1F477 1F3FF 200D 2640 FE0F ; fully-qualified # 👷🏿‍♀️ E4.0 woman construction worker: dark skin tone +1F477 1F3FF 200D 2640 ; minimally-qualified # 👷🏿‍♀ E4.0 woman construction worker: dark skin tone +1FAC5 ; fully-qualified # 🫅 E14.0 person with crown +1FAC5 1F3FB ; fully-qualified # 🫅🏻 E14.0 person with crown: light skin tone +1FAC5 1F3FC ; fully-qualified # 🫅🏼 E14.0 person with crown: medium-light skin tone +1FAC5 1F3FD ; fully-qualified # 🫅🏽 E14.0 person with crown: medium skin tone +1FAC5 1F3FE ; fully-qualified # 🫅🏾 E14.0 person with crown: medium-dark skin tone +1FAC5 1F3FF ; fully-qualified # 🫅🏿 E14.0 person with crown: dark skin tone +1F934 ; fully-qualified # 🤴 E3.0 prince +1F934 1F3FB ; fully-qualified # 🤴🏻 E3.0 prince: light skin tone +1F934 1F3FC ; fully-qualified # 🤴🏼 E3.0 prince: medium-light skin tone +1F934 1F3FD ; fully-qualified # 🤴🏽 E3.0 prince: medium skin tone +1F934 1F3FE ; fully-qualified # 🤴🏾 E3.0 prince: medium-dark skin tone +1F934 1F3FF ; fully-qualified # 🤴🏿 E3.0 prince: dark skin tone +1F478 ; fully-qualified # 👸 E0.6 princess +1F478 1F3FB ; fully-qualified # 👸🏻 E1.0 princess: light skin tone +1F478 1F3FC ; fully-qualified # 👸🏼 E1.0 princess: medium-light skin tone +1F478 1F3FD ; fully-qualified # 👸🏽 E1.0 princess: medium skin tone +1F478 1F3FE ; fully-qualified # 👸🏾 E1.0 princess: medium-dark skin tone +1F478 1F3FF ; fully-qualified # 👸🏿 E1.0 princess: dark skin tone +1F473 ; fully-qualified # 👳 E0.6 person wearing turban +1F473 1F3FB ; fully-qualified # 👳🏻 E1.0 person wearing turban: light skin tone +1F473 1F3FC ; fully-qualified # 👳🏼 E1.0 person wearing turban: medium-light skin tone +1F473 1F3FD ; fully-qualified # 👳🏽 E1.0 person wearing turban: medium skin tone +1F473 1F3FE ; fully-qualified # 👳🏾 E1.0 person wearing turban: medium-dark skin tone +1F473 1F3FF ; fully-qualified # 👳🏿 E1.0 person wearing turban: dark skin tone +1F473 200D 2642 FE0F ; fully-qualified # 👳‍♂️ E4.0 man wearing turban +1F473 200D 2642 ; minimally-qualified # 👳‍♂ E4.0 man wearing turban +1F473 1F3FB 200D 2642 FE0F ; fully-qualified # 👳🏻‍♂️ E4.0 man wearing turban: light skin tone +1F473 1F3FB 200D 2642 ; minimally-qualified # 👳🏻‍♂ E4.0 man wearing turban: light skin tone +1F473 1F3FC 200D 2642 FE0F ; fully-qualified # 👳🏼‍♂️ E4.0 man wearing turban: medium-light skin tone +1F473 1F3FC 200D 2642 ; minimally-qualified # 👳🏼‍♂ E4.0 man wearing turban: medium-light skin tone +1F473 1F3FD 200D 2642 FE0F ; fully-qualified # 👳🏽‍♂️ E4.0 man wearing turban: medium skin tone +1F473 1F3FD 200D 2642 ; minimally-qualified # 👳🏽‍♂ E4.0 man wearing turban: medium skin tone +1F473 1F3FE 200D 2642 FE0F ; fully-qualified # 👳🏾‍♂️ E4.0 man wearing turban: medium-dark skin tone +1F473 1F3FE 200D 2642 ; minimally-qualified # 👳🏾‍♂ E4.0 man wearing turban: medium-dark skin tone +1F473 1F3FF 200D 2642 FE0F ; fully-qualified # 👳🏿‍♂️ E4.0 man wearing turban: dark skin tone +1F473 1F3FF 200D 2642 ; minimally-qualified # 👳🏿‍♂ E4.0 man wearing turban: dark skin tone +1F473 200D 2640 FE0F ; fully-qualified # 👳‍♀️ E4.0 woman wearing turban +1F473 200D 2640 ; minimally-qualified # 👳‍♀ E4.0 woman wearing turban +1F473 1F3FB 200D 2640 FE0F ; fully-qualified # 👳🏻‍♀️ E4.0 woman wearing turban: light skin tone +1F473 1F3FB 200D 2640 ; minimally-qualified # 👳🏻‍♀ E4.0 woman wearing turban: light skin tone +1F473 1F3FC 200D 2640 FE0F ; fully-qualified # 👳🏼‍♀️ E4.0 woman wearing turban: medium-light skin tone +1F473 1F3FC 200D 2640 ; minimally-qualified # 👳🏼‍♀ E4.0 woman wearing turban: medium-light skin tone +1F473 1F3FD 200D 2640 FE0F ; fully-qualified # 👳🏽‍♀️ E4.0 woman wearing turban: medium skin tone +1F473 1F3FD 200D 2640 ; minimally-qualified # 👳🏽‍♀ E4.0 woman wearing turban: medium skin tone +1F473 1F3FE 200D 2640 FE0F ; fully-qualified # 👳🏾‍♀️ E4.0 woman wearing turban: medium-dark skin tone +1F473 1F3FE 200D 2640 ; minimally-qualified # 👳🏾‍♀ E4.0 woman wearing turban: medium-dark skin tone +1F473 1F3FF 200D 2640 FE0F ; fully-qualified # 👳🏿‍♀️ E4.0 woman wearing turban: dark skin tone +1F473 1F3FF 200D 2640 ; minimally-qualified # 👳🏿‍♀ E4.0 woman wearing turban: dark skin tone +1F472 ; fully-qualified # 👲 E0.6 person with skullcap +1F472 1F3FB ; fully-qualified # 👲🏻 E1.0 person with skullcap: light skin tone +1F472 1F3FC ; fully-qualified # 👲🏼 E1.0 person with skullcap: medium-light skin tone +1F472 1F3FD ; fully-qualified # 👲🏽 E1.0 person with skullcap: medium skin tone +1F472 1F3FE ; fully-qualified # 👲🏾 E1.0 person with skullcap: medium-dark skin tone +1F472 1F3FF ; fully-qualified # 👲🏿 E1.0 person with skullcap: dark skin tone +1F9D5 ; fully-qualified # 🧕 E5.0 woman with headscarf +1F9D5 1F3FB ; fully-qualified # 🧕🏻 E5.0 woman with headscarf: light skin tone +1F9D5 1F3FC ; fully-qualified # 🧕🏼 E5.0 woman with headscarf: medium-light skin tone +1F9D5 1F3FD ; fully-qualified # 🧕🏽 E5.0 woman with headscarf: medium skin tone +1F9D5 1F3FE ; fully-qualified # 🧕🏾 E5.0 woman with headscarf: medium-dark skin tone +1F9D5 1F3FF ; fully-qualified # 🧕🏿 E5.0 woman with headscarf: dark skin tone +1F935 ; fully-qualified # 🤵 E3.0 person in tuxedo +1F935 1F3FB ; fully-qualified # 🤵🏻 E3.0 person in tuxedo: light skin tone +1F935 1F3FC ; fully-qualified # 🤵🏼 E3.0 person in tuxedo: medium-light skin tone +1F935 1F3FD ; fully-qualified # 🤵🏽 E3.0 person in tuxedo: medium skin tone +1F935 1F3FE ; fully-qualified # 🤵🏾 E3.0 person in tuxedo: medium-dark skin tone +1F935 1F3FF ; fully-qualified # 🤵🏿 E3.0 person in tuxedo: dark skin tone +1F935 200D 2642 FE0F ; fully-qualified # 🤵‍♂️ E13.0 man in tuxedo +1F935 200D 2642 ; minimally-qualified # 🤵‍♂ E13.0 man in tuxedo +1F935 1F3FB 200D 2642 FE0F ; fully-qualified # 🤵🏻‍♂️ E13.0 man in tuxedo: light skin tone +1F935 1F3FB 200D 2642 ; minimally-qualified # 🤵🏻‍♂ E13.0 man in tuxedo: light skin tone +1F935 1F3FC 200D 2642 FE0F ; fully-qualified # 🤵🏼‍♂️ E13.0 man in tuxedo: medium-light skin tone +1F935 1F3FC 200D 2642 ; minimally-qualified # 🤵🏼‍♂ E13.0 man in tuxedo: medium-light skin tone +1F935 1F3FD 200D 2642 FE0F ; fully-qualified # 🤵🏽‍♂️ E13.0 man in tuxedo: medium skin tone +1F935 1F3FD 200D 2642 ; minimally-qualified # 🤵🏽‍♂ E13.0 man in tuxedo: medium skin tone +1F935 1F3FE 200D 2642 FE0F ; fully-qualified # 🤵🏾‍♂️ E13.0 man in tuxedo: medium-dark skin tone +1F935 1F3FE 200D 2642 ; minimally-qualified # 🤵🏾‍♂ E13.0 man in tuxedo: medium-dark skin tone +1F935 1F3FF 200D 2642 FE0F ; fully-qualified # 🤵🏿‍♂️ E13.0 man in tuxedo: dark skin tone +1F935 1F3FF 200D 2642 ; minimally-qualified # 🤵🏿‍♂ E13.0 man in tuxedo: dark skin tone +1F935 200D 2640 FE0F ; fully-qualified # 🤵‍♀️ E13.0 woman in tuxedo +1F935 200D 2640 ; minimally-qualified # 🤵‍♀ E13.0 woman in tuxedo +1F935 1F3FB 200D 2640 FE0F ; fully-qualified # 🤵🏻‍♀️ E13.0 woman in tuxedo: light skin tone +1F935 1F3FB 200D 2640 ; minimally-qualified # 🤵🏻‍♀ E13.0 woman in tuxedo: light skin tone +1F935 1F3FC 200D 2640 FE0F ; fully-qualified # 🤵🏼‍♀️ E13.0 woman in tuxedo: medium-light skin tone +1F935 1F3FC 200D 2640 ; minimally-qualified # 🤵🏼‍♀ E13.0 woman in tuxedo: medium-light skin tone +1F935 1F3FD 200D 2640 FE0F ; fully-qualified # 🤵🏽‍♀️ E13.0 woman in tuxedo: medium skin tone +1F935 1F3FD 200D 2640 ; minimally-qualified # 🤵🏽‍♀ E13.0 woman in tuxedo: medium skin tone +1F935 1F3FE 200D 2640 FE0F ; fully-qualified # 🤵🏾‍♀️ E13.0 woman in tuxedo: medium-dark skin tone +1F935 1F3FE 200D 2640 ; minimally-qualified # 🤵🏾‍♀ E13.0 woman in tuxedo: medium-dark skin tone +1F935 1F3FF 200D 2640 FE0F ; fully-qualified # 🤵🏿‍♀️ E13.0 woman in tuxedo: dark skin tone +1F935 1F3FF 200D 2640 ; minimally-qualified # 🤵🏿‍♀ E13.0 woman in tuxedo: dark skin tone +1F470 ; fully-qualified # 👰 E0.6 person with veil +1F470 1F3FB ; fully-qualified # 👰🏻 E1.0 person with veil: light skin tone +1F470 1F3FC ; fully-qualified # 👰🏼 E1.0 person with veil: medium-light skin tone +1F470 1F3FD ; fully-qualified # 👰🏽 E1.0 person with veil: medium skin tone +1F470 1F3FE ; fully-qualified # 👰🏾 E1.0 person with veil: medium-dark skin tone +1F470 1F3FF ; fully-qualified # 👰🏿 E1.0 person with veil: dark skin tone +1F470 200D 2642 FE0F ; fully-qualified # 👰‍♂️ E13.0 man with veil +1F470 200D 2642 ; minimally-qualified # 👰‍♂ E13.0 man with veil +1F470 1F3FB 200D 2642 FE0F ; fully-qualified # 👰🏻‍♂️ E13.0 man with veil: light skin tone +1F470 1F3FB 200D 2642 ; minimally-qualified # 👰🏻‍♂ E13.0 man with veil: light skin tone +1F470 1F3FC 200D 2642 FE0F ; fully-qualified # 👰🏼‍♂️ E13.0 man with veil: medium-light skin tone +1F470 1F3FC 200D 2642 ; minimally-qualified # 👰🏼‍♂ E13.0 man with veil: medium-light skin tone +1F470 1F3FD 200D 2642 FE0F ; fully-qualified # 👰🏽‍♂️ E13.0 man with veil: medium skin tone +1F470 1F3FD 200D 2642 ; minimally-qualified # 👰🏽‍♂ E13.0 man with veil: medium skin tone +1F470 1F3FE 200D 2642 FE0F ; fully-qualified # 👰🏾‍♂️ E13.0 man with veil: medium-dark skin tone +1F470 1F3FE 200D 2642 ; minimally-qualified # 👰🏾‍♂ E13.0 man with veil: medium-dark skin tone +1F470 1F3FF 200D 2642 FE0F ; fully-qualified # 👰🏿‍♂️ E13.0 man with veil: dark skin tone +1F470 1F3FF 200D 2642 ; minimally-qualified # 👰🏿‍♂ E13.0 man with veil: dark skin tone +1F470 200D 2640 FE0F ; fully-qualified # 👰‍♀️ E13.0 woman with veil +1F470 200D 2640 ; minimally-qualified # 👰‍♀ E13.0 woman with veil +1F470 1F3FB 200D 2640 FE0F ; fully-qualified # 👰🏻‍♀️ E13.0 woman with veil: light skin tone +1F470 1F3FB 200D 2640 ; minimally-qualified # 👰🏻‍♀ E13.0 woman with veil: light skin tone +1F470 1F3FC 200D 2640 FE0F ; fully-qualified # 👰🏼‍♀️ E13.0 woman with veil: medium-light skin tone +1F470 1F3FC 200D 2640 ; minimally-qualified # 👰🏼‍♀ E13.0 woman with veil: medium-light skin tone +1F470 1F3FD 200D 2640 FE0F ; fully-qualified # 👰🏽‍♀️ E13.0 woman with veil: medium skin tone +1F470 1F3FD 200D 2640 ; minimally-qualified # 👰🏽‍♀ E13.0 woman with veil: medium skin tone +1F470 1F3FE 200D 2640 FE0F ; fully-qualified # 👰🏾‍♀️ E13.0 woman with veil: medium-dark skin tone +1F470 1F3FE 200D 2640 ; minimally-qualified # 👰🏾‍♀ E13.0 woman with veil: medium-dark skin tone +1F470 1F3FF 200D 2640 FE0F ; fully-qualified # 👰🏿‍♀️ E13.0 woman with veil: dark skin tone +1F470 1F3FF 200D 2640 ; minimally-qualified # 👰🏿‍♀ E13.0 woman with veil: dark skin tone +1F930 ; fully-qualified # 🤰 E3.0 pregnant woman +1F930 1F3FB ; fully-qualified # 🤰🏻 E3.0 pregnant woman: light skin tone +1F930 1F3FC ; fully-qualified # 🤰🏼 E3.0 pregnant woman: medium-light skin tone +1F930 1F3FD ; fully-qualified # 🤰🏽 E3.0 pregnant woman: medium skin tone +1F930 1F3FE ; fully-qualified # 🤰🏾 E3.0 pregnant woman: medium-dark skin tone +1F930 1F3FF ; fully-qualified # 🤰🏿 E3.0 pregnant woman: dark skin tone +1FAC3 ; fully-qualified # 🫃 E14.0 pregnant man +1FAC3 1F3FB ; fully-qualified # 🫃🏻 E14.0 pregnant man: light skin tone +1FAC3 1F3FC ; fully-qualified # 🫃🏼 E14.0 pregnant man: medium-light skin tone +1FAC3 1F3FD ; fully-qualified # 🫃🏽 E14.0 pregnant man: medium skin tone +1FAC3 1F3FE ; fully-qualified # 🫃🏾 E14.0 pregnant man: medium-dark skin tone +1FAC3 1F3FF ; fully-qualified # 🫃🏿 E14.0 pregnant man: dark skin tone +1FAC4 ; fully-qualified # 🫄 E14.0 pregnant person +1FAC4 1F3FB ; fully-qualified # 🫄🏻 E14.0 pregnant person: light skin tone +1FAC4 1F3FC ; fully-qualified # 🫄🏼 E14.0 pregnant person: medium-light skin tone +1FAC4 1F3FD ; fully-qualified # 🫄🏽 E14.0 pregnant person: medium skin tone +1FAC4 1F3FE ; fully-qualified # 🫄🏾 E14.0 pregnant person: medium-dark skin tone +1FAC4 1F3FF ; fully-qualified # 🫄🏿 E14.0 pregnant person: dark skin tone +1F931 ; fully-qualified # 🤱 E5.0 breast-feeding +1F931 1F3FB ; fully-qualified # 🤱🏻 E5.0 breast-feeding: light skin tone +1F931 1F3FC ; fully-qualified # 🤱🏼 E5.0 breast-feeding: medium-light skin tone +1F931 1F3FD ; fully-qualified # 🤱🏽 E5.0 breast-feeding: medium skin tone +1F931 1F3FE ; fully-qualified # 🤱🏾 E5.0 breast-feeding: medium-dark skin tone +1F931 1F3FF ; fully-qualified # 🤱🏿 E5.0 breast-feeding: dark skin tone +1F469 200D 1F37C ; fully-qualified # 👩‍🍼 E13.0 woman feeding baby +1F469 1F3FB 200D 1F37C ; fully-qualified # 👩🏻‍🍼 E13.0 woman feeding baby: light skin tone +1F469 1F3FC 200D 1F37C ; fully-qualified # 👩🏼‍🍼 E13.0 woman feeding baby: medium-light skin tone +1F469 1F3FD 200D 1F37C ; fully-qualified # 👩🏽‍🍼 E13.0 woman feeding baby: medium skin tone +1F469 1F3FE 200D 1F37C ; fully-qualified # 👩🏾‍🍼 E13.0 woman feeding baby: medium-dark skin tone +1F469 1F3FF 200D 1F37C ; fully-qualified # 👩🏿‍🍼 E13.0 woman feeding baby: dark skin tone +1F468 200D 1F37C ; fully-qualified # 👨‍🍼 E13.0 man feeding baby +1F468 1F3FB 200D 1F37C ; fully-qualified # 👨🏻‍🍼 E13.0 man feeding baby: light skin tone +1F468 1F3FC 200D 1F37C ; fully-qualified # 👨🏼‍🍼 E13.0 man feeding baby: medium-light skin tone +1F468 1F3FD 200D 1F37C ; fully-qualified # 👨🏽‍🍼 E13.0 man feeding baby: medium skin tone +1F468 1F3FE 200D 1F37C ; fully-qualified # 👨🏾‍🍼 E13.0 man feeding baby: medium-dark skin tone +1F468 1F3FF 200D 1F37C ; fully-qualified # 👨🏿‍🍼 E13.0 man feeding baby: dark skin tone +1F9D1 200D 1F37C ; fully-qualified # 🧑‍🍼 E13.0 person feeding baby +1F9D1 1F3FB 200D 1F37C ; fully-qualified # 🧑🏻‍🍼 E13.0 person feeding baby: light skin tone +1F9D1 1F3FC 200D 1F37C ; fully-qualified # 🧑🏼‍🍼 E13.0 person feeding baby: medium-light skin tone +1F9D1 1F3FD 200D 1F37C ; fully-qualified # 🧑🏽‍🍼 E13.0 person feeding baby: medium skin tone +1F9D1 1F3FE 200D 1F37C ; fully-qualified # 🧑🏾‍🍼 E13.0 person feeding baby: medium-dark skin tone +1F9D1 1F3FF 200D 1F37C ; fully-qualified # 🧑🏿‍🍼 E13.0 person feeding baby: dark skin tone + +# subgroup: person-fantasy +1F47C ; fully-qualified # 👼 E0.6 baby angel +1F47C 1F3FB ; fully-qualified # 👼🏻 E1.0 baby angel: light skin tone +1F47C 1F3FC ; fully-qualified # 👼🏼 E1.0 baby angel: medium-light skin tone +1F47C 1F3FD ; fully-qualified # 👼🏽 E1.0 baby angel: medium skin tone +1F47C 1F3FE ; fully-qualified # 👼🏾 E1.0 baby angel: medium-dark skin tone +1F47C 1F3FF ; fully-qualified # 👼🏿 E1.0 baby angel: dark skin tone +1F385 ; fully-qualified # 🎅 E0.6 Santa Claus +1F385 1F3FB ; fully-qualified # 🎅🏻 E1.0 Santa Claus: light skin tone +1F385 1F3FC ; fully-qualified # 🎅🏼 E1.0 Santa Claus: medium-light skin tone +1F385 1F3FD ; fully-qualified # 🎅🏽 E1.0 Santa Claus: medium skin tone +1F385 1F3FE ; fully-qualified # 🎅🏾 E1.0 Santa Claus: medium-dark skin tone +1F385 1F3FF ; fully-qualified # 🎅🏿 E1.0 Santa Claus: dark skin tone +1F936 ; fully-qualified # 🤶 E3.0 Mrs. Claus +1F936 1F3FB ; fully-qualified # 🤶🏻 E3.0 Mrs. Claus: light skin tone +1F936 1F3FC ; fully-qualified # 🤶🏼 E3.0 Mrs. Claus: medium-light skin tone +1F936 1F3FD ; fully-qualified # 🤶🏽 E3.0 Mrs. Claus: medium skin tone +1F936 1F3FE ; fully-qualified # 🤶🏾 E3.0 Mrs. Claus: medium-dark skin tone +1F936 1F3FF ; fully-qualified # 🤶🏿 E3.0 Mrs. Claus: dark skin tone +1F9D1 200D 1F384 ; fully-qualified # 🧑‍🎄 E13.0 mx claus +1F9D1 1F3FB 200D 1F384 ; fully-qualified # 🧑🏻‍🎄 E13.0 mx claus: light skin tone +1F9D1 1F3FC 200D 1F384 ; fully-qualified # 🧑🏼‍🎄 E13.0 mx claus: medium-light skin tone +1F9D1 1F3FD 200D 1F384 ; fully-qualified # 🧑🏽‍🎄 E13.0 mx claus: medium skin tone +1F9D1 1F3FE 200D 1F384 ; fully-qualified # 🧑🏾‍🎄 E13.0 mx claus: medium-dark skin tone +1F9D1 1F3FF 200D 1F384 ; fully-qualified # 🧑🏿‍🎄 E13.0 mx claus: dark skin tone +1F9B8 ; fully-qualified # 🦸 E11.0 superhero +1F9B8 1F3FB ; fully-qualified # 🦸🏻 E11.0 superhero: light skin tone +1F9B8 1F3FC ; fully-qualified # 🦸🏼 E11.0 superhero: medium-light skin tone +1F9B8 1F3FD ; fully-qualified # 🦸🏽 E11.0 superhero: medium skin tone +1F9B8 1F3FE ; fully-qualified # 🦸🏾 E11.0 superhero: medium-dark skin tone +1F9B8 1F3FF ; fully-qualified # 🦸🏿 E11.0 superhero: dark skin tone +1F9B8 200D 2642 FE0F ; fully-qualified # 🦸‍♂️ E11.0 man superhero +1F9B8 200D 2642 ; minimally-qualified # 🦸‍♂ E11.0 man superhero +1F9B8 1F3FB 200D 2642 FE0F ; fully-qualified # 🦸🏻‍♂️ E11.0 man superhero: light skin tone +1F9B8 1F3FB 200D 2642 ; minimally-qualified # 🦸🏻‍♂ E11.0 man superhero: light skin tone +1F9B8 1F3FC 200D 2642 FE0F ; fully-qualified # 🦸🏼‍♂️ E11.0 man superhero: medium-light skin tone +1F9B8 1F3FC 200D 2642 ; minimally-qualified # 🦸🏼‍♂ E11.0 man superhero: medium-light skin tone +1F9B8 1F3FD 200D 2642 FE0F ; fully-qualified # 🦸🏽‍♂️ E11.0 man superhero: medium skin tone +1F9B8 1F3FD 200D 2642 ; minimally-qualified # 🦸🏽‍♂ E11.0 man superhero: medium skin tone +1F9B8 1F3FE 200D 2642 FE0F ; fully-qualified # 🦸🏾‍♂️ E11.0 man superhero: medium-dark skin tone +1F9B8 1F3FE 200D 2642 ; minimally-qualified # 🦸🏾‍♂ E11.0 man superhero: medium-dark skin tone +1F9B8 1F3FF 200D 2642 FE0F ; fully-qualified # 🦸🏿‍♂️ E11.0 man superhero: dark skin tone +1F9B8 1F3FF 200D 2642 ; minimally-qualified # 🦸🏿‍♂ E11.0 man superhero: dark skin tone +1F9B8 200D 2640 FE0F ; fully-qualified # 🦸‍♀️ E11.0 woman superhero +1F9B8 200D 2640 ; minimally-qualified # 🦸‍♀ E11.0 woman superhero +1F9B8 1F3FB 200D 2640 FE0F ; fully-qualified # 🦸🏻‍♀️ E11.0 woman superhero: light skin tone +1F9B8 1F3FB 200D 2640 ; minimally-qualified # 🦸🏻‍♀ E11.0 woman superhero: light skin tone +1F9B8 1F3FC 200D 2640 FE0F ; fully-qualified # 🦸🏼‍♀️ E11.0 woman superhero: medium-light skin tone +1F9B8 1F3FC 200D 2640 ; minimally-qualified # 🦸🏼‍♀ E11.0 woman superhero: medium-light skin tone +1F9B8 1F3FD 200D 2640 FE0F ; fully-qualified # 🦸🏽‍♀️ E11.0 woman superhero: medium skin tone +1F9B8 1F3FD 200D 2640 ; minimally-qualified # 🦸🏽‍♀ E11.0 woman superhero: medium skin tone +1F9B8 1F3FE 200D 2640 FE0F ; fully-qualified # 🦸🏾‍♀️ E11.0 woman superhero: medium-dark skin tone +1F9B8 1F3FE 200D 2640 ; minimally-qualified # 🦸🏾‍♀ E11.0 woman superhero: medium-dark skin tone +1F9B8 1F3FF 200D 2640 FE0F ; fully-qualified # 🦸🏿‍♀️ E11.0 woman superhero: dark skin tone +1F9B8 1F3FF 200D 2640 ; minimally-qualified # 🦸🏿‍♀ E11.0 woman superhero: dark skin tone +1F9B9 ; fully-qualified # 🦹 E11.0 supervillain +1F9B9 1F3FB ; fully-qualified # 🦹🏻 E11.0 supervillain: light skin tone +1F9B9 1F3FC ; fully-qualified # 🦹🏼 E11.0 supervillain: medium-light skin tone +1F9B9 1F3FD ; fully-qualified # 🦹🏽 E11.0 supervillain: medium skin tone +1F9B9 1F3FE ; fully-qualified # 🦹🏾 E11.0 supervillain: medium-dark skin tone +1F9B9 1F3FF ; fully-qualified # 🦹🏿 E11.0 supervillain: dark skin tone +1F9B9 200D 2642 FE0F ; fully-qualified # 🦹‍♂️ E11.0 man supervillain +1F9B9 200D 2642 ; minimally-qualified # 🦹‍♂ E11.0 man supervillain +1F9B9 1F3FB 200D 2642 FE0F ; fully-qualified # 🦹🏻‍♂️ E11.0 man supervillain: light skin tone +1F9B9 1F3FB 200D 2642 ; minimally-qualified # 🦹🏻‍♂ E11.0 man supervillain: light skin tone +1F9B9 1F3FC 200D 2642 FE0F ; fully-qualified # 🦹🏼‍♂️ E11.0 man supervillain: medium-light skin tone +1F9B9 1F3FC 200D 2642 ; minimally-qualified # 🦹🏼‍♂ E11.0 man supervillain: medium-light skin tone +1F9B9 1F3FD 200D 2642 FE0F ; fully-qualified # 🦹🏽‍♂️ E11.0 man supervillain: medium skin tone +1F9B9 1F3FD 200D 2642 ; minimally-qualified # 🦹🏽‍♂ E11.0 man supervillain: medium skin tone +1F9B9 1F3FE 200D 2642 FE0F ; fully-qualified # 🦹🏾‍♂️ E11.0 man supervillain: medium-dark skin tone +1F9B9 1F3FE 200D 2642 ; minimally-qualified # 🦹🏾‍♂ E11.0 man supervillain: medium-dark skin tone +1F9B9 1F3FF 200D 2642 FE0F ; fully-qualified # 🦹🏿‍♂️ E11.0 man supervillain: dark skin tone +1F9B9 1F3FF 200D 2642 ; minimally-qualified # 🦹🏿‍♂ E11.0 man supervillain: dark skin tone +1F9B9 200D 2640 FE0F ; fully-qualified # 🦹‍♀️ E11.0 woman supervillain +1F9B9 200D 2640 ; minimally-qualified # 🦹‍♀ E11.0 woman supervillain +1F9B9 1F3FB 200D 2640 FE0F ; fully-qualified # 🦹🏻‍♀️ E11.0 woman supervillain: light skin tone +1F9B9 1F3FB 200D 2640 ; minimally-qualified # 🦹🏻‍♀ E11.0 woman supervillain: light skin tone +1F9B9 1F3FC 200D 2640 FE0F ; fully-qualified # 🦹🏼‍♀️ E11.0 woman supervillain: medium-light skin tone +1F9B9 1F3FC 200D 2640 ; minimally-qualified # 🦹🏼‍♀ E11.0 woman supervillain: medium-light skin tone +1F9B9 1F3FD 200D 2640 FE0F ; fully-qualified # 🦹🏽‍♀️ E11.0 woman supervillain: medium skin tone +1F9B9 1F3FD 200D 2640 ; minimally-qualified # 🦹🏽‍♀ E11.0 woman supervillain: medium skin tone +1F9B9 1F3FE 200D 2640 FE0F ; fully-qualified # 🦹🏾‍♀️ E11.0 woman supervillain: medium-dark skin tone +1F9B9 1F3FE 200D 2640 ; minimally-qualified # 🦹🏾‍♀ E11.0 woman supervillain: medium-dark skin tone +1F9B9 1F3FF 200D 2640 FE0F ; fully-qualified # 🦹🏿‍♀️ E11.0 woman supervillain: dark skin tone +1F9B9 1F3FF 200D 2640 ; minimally-qualified # 🦹🏿‍♀ E11.0 woman supervillain: dark skin tone +1F9D9 ; fully-qualified # 🧙 E5.0 mage +1F9D9 1F3FB ; fully-qualified # 🧙🏻 E5.0 mage: light skin tone +1F9D9 1F3FC ; fully-qualified # 🧙🏼 E5.0 mage: medium-light skin tone +1F9D9 1F3FD ; fully-qualified # 🧙🏽 E5.0 mage: medium skin tone +1F9D9 1F3FE ; fully-qualified # 🧙🏾 E5.0 mage: medium-dark skin tone +1F9D9 1F3FF ; fully-qualified # 🧙🏿 E5.0 mage: dark skin tone +1F9D9 200D 2642 FE0F ; fully-qualified # 🧙‍♂️ E5.0 man mage +1F9D9 200D 2642 ; minimally-qualified # 🧙‍♂ E5.0 man mage +1F9D9 1F3FB 200D 2642 FE0F ; fully-qualified # 🧙🏻‍♂️ E5.0 man mage: light skin tone +1F9D9 1F3FB 200D 2642 ; minimally-qualified # 🧙🏻‍♂ E5.0 man mage: light skin tone +1F9D9 1F3FC 200D 2642 FE0F ; fully-qualified # 🧙🏼‍♂️ E5.0 man mage: medium-light skin tone +1F9D9 1F3FC 200D 2642 ; minimally-qualified # 🧙🏼‍♂ E5.0 man mage: medium-light skin tone +1F9D9 1F3FD 200D 2642 FE0F ; fully-qualified # 🧙🏽‍♂️ E5.0 man mage: medium skin tone +1F9D9 1F3FD 200D 2642 ; minimally-qualified # 🧙🏽‍♂ E5.0 man mage: medium skin tone +1F9D9 1F3FE 200D 2642 FE0F ; fully-qualified # 🧙🏾‍♂️ E5.0 man mage: medium-dark skin tone +1F9D9 1F3FE 200D 2642 ; minimally-qualified # 🧙🏾‍♂ E5.0 man mage: medium-dark skin tone +1F9D9 1F3FF 200D 2642 FE0F ; fully-qualified # 🧙🏿‍♂️ E5.0 man mage: dark skin tone +1F9D9 1F3FF 200D 2642 ; minimally-qualified # 🧙🏿‍♂ E5.0 man mage: dark skin tone +1F9D9 200D 2640 FE0F ; fully-qualified # 🧙‍♀️ E5.0 woman mage +1F9D9 200D 2640 ; minimally-qualified # 🧙‍♀ E5.0 woman mage +1F9D9 1F3FB 200D 2640 FE0F ; fully-qualified # 🧙🏻‍♀️ E5.0 woman mage: light skin tone +1F9D9 1F3FB 200D 2640 ; minimally-qualified # 🧙🏻‍♀ E5.0 woman mage: light skin tone +1F9D9 1F3FC 200D 2640 FE0F ; fully-qualified # 🧙🏼‍♀️ E5.0 woman mage: medium-light skin tone +1F9D9 1F3FC 200D 2640 ; minimally-qualified # 🧙🏼‍♀ E5.0 woman mage: medium-light skin tone +1F9D9 1F3FD 200D 2640 FE0F ; fully-qualified # 🧙🏽‍♀️ E5.0 woman mage: medium skin tone +1F9D9 1F3FD 200D 2640 ; minimally-qualified # 🧙🏽‍♀ E5.0 woman mage: medium skin tone +1F9D9 1F3FE 200D 2640 FE0F ; fully-qualified # 🧙🏾‍♀️ E5.0 woman mage: medium-dark skin tone +1F9D9 1F3FE 200D 2640 ; minimally-qualified # 🧙🏾‍♀ E5.0 woman mage: medium-dark skin tone +1F9D9 1F3FF 200D 2640 FE0F ; fully-qualified # 🧙🏿‍♀️ E5.0 woman mage: dark skin tone +1F9D9 1F3FF 200D 2640 ; minimally-qualified # 🧙🏿‍♀ E5.0 woman mage: dark skin tone +1F9DA ; fully-qualified # 🧚 E5.0 fairy +1F9DA 1F3FB ; fully-qualified # 🧚🏻 E5.0 fairy: light skin tone +1F9DA 1F3FC ; fully-qualified # 🧚🏼 E5.0 fairy: medium-light skin tone +1F9DA 1F3FD ; fully-qualified # 🧚🏽 E5.0 fairy: medium skin tone +1F9DA 1F3FE ; fully-qualified # 🧚🏾 E5.0 fairy: medium-dark skin tone +1F9DA 1F3FF ; fully-qualified # 🧚🏿 E5.0 fairy: dark skin tone +1F9DA 200D 2642 FE0F ; fully-qualified # 🧚‍♂️ E5.0 man fairy +1F9DA 200D 2642 ; minimally-qualified # 🧚‍♂ E5.0 man fairy +1F9DA 1F3FB 200D 2642 FE0F ; fully-qualified # 🧚🏻‍♂️ E5.0 man fairy: light skin tone +1F9DA 1F3FB 200D 2642 ; minimally-qualified # 🧚🏻‍♂ E5.0 man fairy: light skin tone +1F9DA 1F3FC 200D 2642 FE0F ; fully-qualified # 🧚🏼‍♂️ E5.0 man fairy: medium-light skin tone +1F9DA 1F3FC 200D 2642 ; minimally-qualified # 🧚🏼‍♂ E5.0 man fairy: medium-light skin tone +1F9DA 1F3FD 200D 2642 FE0F ; fully-qualified # 🧚🏽‍♂️ E5.0 man fairy: medium skin tone +1F9DA 1F3FD 200D 2642 ; minimally-qualified # 🧚🏽‍♂ E5.0 man fairy: medium skin tone +1F9DA 1F3FE 200D 2642 FE0F ; fully-qualified # 🧚🏾‍♂️ E5.0 man fairy: medium-dark skin tone +1F9DA 1F3FE 200D 2642 ; minimally-qualified # 🧚🏾‍♂ E5.0 man fairy: medium-dark skin tone +1F9DA 1F3FF 200D 2642 FE0F ; fully-qualified # 🧚🏿‍♂️ E5.0 man fairy: dark skin tone +1F9DA 1F3FF 200D 2642 ; minimally-qualified # 🧚🏿‍♂ E5.0 man fairy: dark skin tone +1F9DA 200D 2640 FE0F ; fully-qualified # 🧚‍♀️ E5.0 woman fairy +1F9DA 200D 2640 ; minimally-qualified # 🧚‍♀ E5.0 woman fairy +1F9DA 1F3FB 200D 2640 FE0F ; fully-qualified # 🧚🏻‍♀️ E5.0 woman fairy: light skin tone +1F9DA 1F3FB 200D 2640 ; minimally-qualified # 🧚🏻‍♀ E5.0 woman fairy: light skin tone +1F9DA 1F3FC 200D 2640 FE0F ; fully-qualified # 🧚🏼‍♀️ E5.0 woman fairy: medium-light skin tone +1F9DA 1F3FC 200D 2640 ; minimally-qualified # 🧚🏼‍♀ E5.0 woman fairy: medium-light skin tone +1F9DA 1F3FD 200D 2640 FE0F ; fully-qualified # 🧚🏽‍♀️ E5.0 woman fairy: medium skin tone +1F9DA 1F3FD 200D 2640 ; minimally-qualified # 🧚🏽‍♀ E5.0 woman fairy: medium skin tone +1F9DA 1F3FE 200D 2640 FE0F ; fully-qualified # 🧚🏾‍♀️ E5.0 woman fairy: medium-dark skin tone +1F9DA 1F3FE 200D 2640 ; minimally-qualified # 🧚🏾‍♀ E5.0 woman fairy: medium-dark skin tone +1F9DA 1F3FF 200D 2640 FE0F ; fully-qualified # 🧚🏿‍♀️ E5.0 woman fairy: dark skin tone +1F9DA 1F3FF 200D 2640 ; minimally-qualified # 🧚🏿‍♀ E5.0 woman fairy: dark skin tone +1F9DB ; fully-qualified # 🧛 E5.0 vampire +1F9DB 1F3FB ; fully-qualified # 🧛🏻 E5.0 vampire: light skin tone +1F9DB 1F3FC ; fully-qualified # 🧛🏼 E5.0 vampire: medium-light skin tone +1F9DB 1F3FD ; fully-qualified # 🧛🏽 E5.0 vampire: medium skin tone +1F9DB 1F3FE ; fully-qualified # 🧛🏾 E5.0 vampire: medium-dark skin tone +1F9DB 1F3FF ; fully-qualified # 🧛🏿 E5.0 vampire: dark skin tone +1F9DB 200D 2642 FE0F ; fully-qualified # 🧛‍♂️ E5.0 man vampire +1F9DB 200D 2642 ; minimally-qualified # 🧛‍♂ E5.0 man vampire +1F9DB 1F3FB 200D 2642 FE0F ; fully-qualified # 🧛🏻‍♂️ E5.0 man vampire: light skin tone +1F9DB 1F3FB 200D 2642 ; minimally-qualified # 🧛🏻‍♂ E5.0 man vampire: light skin tone +1F9DB 1F3FC 200D 2642 FE0F ; fully-qualified # 🧛🏼‍♂️ E5.0 man vampire: medium-light skin tone +1F9DB 1F3FC 200D 2642 ; minimally-qualified # 🧛🏼‍♂ E5.0 man vampire: medium-light skin tone +1F9DB 1F3FD 200D 2642 FE0F ; fully-qualified # 🧛🏽‍♂️ E5.0 man vampire: medium skin tone +1F9DB 1F3FD 200D 2642 ; minimally-qualified # 🧛🏽‍♂ E5.0 man vampire: medium skin tone +1F9DB 1F3FE 200D 2642 FE0F ; fully-qualified # 🧛🏾‍♂️ E5.0 man vampire: medium-dark skin tone +1F9DB 1F3FE 200D 2642 ; minimally-qualified # 🧛🏾‍♂ E5.0 man vampire: medium-dark skin tone +1F9DB 1F3FF 200D 2642 FE0F ; fully-qualified # 🧛🏿‍♂️ E5.0 man vampire: dark skin tone +1F9DB 1F3FF 200D 2642 ; minimally-qualified # 🧛🏿‍♂ E5.0 man vampire: dark skin tone +1F9DB 200D 2640 FE0F ; fully-qualified # 🧛‍♀️ E5.0 woman vampire +1F9DB 200D 2640 ; minimally-qualified # 🧛‍♀ E5.0 woman vampire +1F9DB 1F3FB 200D 2640 FE0F ; fully-qualified # 🧛🏻‍♀️ E5.0 woman vampire: light skin tone +1F9DB 1F3FB 200D 2640 ; minimally-qualified # 🧛🏻‍♀ E5.0 woman vampire: light skin tone +1F9DB 1F3FC 200D 2640 FE0F ; fully-qualified # 🧛🏼‍♀️ E5.0 woman vampire: medium-light skin tone +1F9DB 1F3FC 200D 2640 ; minimally-qualified # 🧛🏼‍♀ E5.0 woman vampire: medium-light skin tone +1F9DB 1F3FD 200D 2640 FE0F ; fully-qualified # 🧛🏽‍♀️ E5.0 woman vampire: medium skin tone +1F9DB 1F3FD 200D 2640 ; minimally-qualified # 🧛🏽‍♀ E5.0 woman vampire: medium skin tone +1F9DB 1F3FE 200D 2640 FE0F ; fully-qualified # 🧛🏾‍♀️ E5.0 woman vampire: medium-dark skin tone +1F9DB 1F3FE 200D 2640 ; minimally-qualified # 🧛🏾‍♀ E5.0 woman vampire: medium-dark skin tone +1F9DB 1F3FF 200D 2640 FE0F ; fully-qualified # 🧛🏿‍♀️ E5.0 woman vampire: dark skin tone +1F9DB 1F3FF 200D 2640 ; minimally-qualified # 🧛🏿‍♀ E5.0 woman vampire: dark skin tone +1F9DC ; fully-qualified # 🧜 E5.0 merperson +1F9DC 1F3FB ; fully-qualified # 🧜🏻 E5.0 merperson: light skin tone +1F9DC 1F3FC ; fully-qualified # 🧜🏼 E5.0 merperson: medium-light skin tone +1F9DC 1F3FD ; fully-qualified # 🧜🏽 E5.0 merperson: medium skin tone +1F9DC 1F3FE ; fully-qualified # 🧜🏾 E5.0 merperson: medium-dark skin tone +1F9DC 1F3FF ; fully-qualified # 🧜🏿 E5.0 merperson: dark skin tone +1F9DC 200D 2642 FE0F ; fully-qualified # 🧜‍♂️ E5.0 merman +1F9DC 200D 2642 ; minimally-qualified # 🧜‍♂ E5.0 merman +1F9DC 1F3FB 200D 2642 FE0F ; fully-qualified # 🧜🏻‍♂️ E5.0 merman: light skin tone +1F9DC 1F3FB 200D 2642 ; minimally-qualified # 🧜🏻‍♂ E5.0 merman: light skin tone +1F9DC 1F3FC 200D 2642 FE0F ; fully-qualified # 🧜🏼‍♂️ E5.0 merman: medium-light skin tone +1F9DC 1F3FC 200D 2642 ; minimally-qualified # 🧜🏼‍♂ E5.0 merman: medium-light skin tone +1F9DC 1F3FD 200D 2642 FE0F ; fully-qualified # 🧜🏽‍♂️ E5.0 merman: medium skin tone +1F9DC 1F3FD 200D 2642 ; minimally-qualified # 🧜🏽‍♂ E5.0 merman: medium skin tone +1F9DC 1F3FE 200D 2642 FE0F ; fully-qualified # 🧜🏾‍♂️ E5.0 merman: medium-dark skin tone +1F9DC 1F3FE 200D 2642 ; minimally-qualified # 🧜🏾‍♂ E5.0 merman: medium-dark skin tone +1F9DC 1F3FF 200D 2642 FE0F ; fully-qualified # 🧜🏿‍♂️ E5.0 merman: dark skin tone +1F9DC 1F3FF 200D 2642 ; minimally-qualified # 🧜🏿‍♂ E5.0 merman: dark skin tone +1F9DC 200D 2640 FE0F ; fully-qualified # 🧜‍♀️ E5.0 mermaid +1F9DC 200D 2640 ; minimally-qualified # 🧜‍♀ E5.0 mermaid +1F9DC 1F3FB 200D 2640 FE0F ; fully-qualified # 🧜🏻‍♀️ E5.0 mermaid: light skin tone +1F9DC 1F3FB 200D 2640 ; minimally-qualified # 🧜🏻‍♀ E5.0 mermaid: light skin tone +1F9DC 1F3FC 200D 2640 FE0F ; fully-qualified # 🧜🏼‍♀️ E5.0 mermaid: medium-light skin tone +1F9DC 1F3FC 200D 2640 ; minimally-qualified # 🧜🏼‍♀ E5.0 mermaid: medium-light skin tone +1F9DC 1F3FD 200D 2640 FE0F ; fully-qualified # 🧜🏽‍♀️ E5.0 mermaid: medium skin tone +1F9DC 1F3FD 200D 2640 ; minimally-qualified # 🧜🏽‍♀ E5.0 mermaid: medium skin tone +1F9DC 1F3FE 200D 2640 FE0F ; fully-qualified # 🧜🏾‍♀️ E5.0 mermaid: medium-dark skin tone +1F9DC 1F3FE 200D 2640 ; minimally-qualified # 🧜🏾‍♀ E5.0 mermaid: medium-dark skin tone +1F9DC 1F3FF 200D 2640 FE0F ; fully-qualified # 🧜🏿‍♀️ E5.0 mermaid: dark skin tone +1F9DC 1F3FF 200D 2640 ; minimally-qualified # 🧜🏿‍♀ E5.0 mermaid: dark skin tone +1F9DD ; fully-qualified # 🧝 E5.0 elf +1F9DD 1F3FB ; fully-qualified # 🧝🏻 E5.0 elf: light skin tone +1F9DD 1F3FC ; fully-qualified # 🧝🏼 E5.0 elf: medium-light skin tone +1F9DD 1F3FD ; fully-qualified # 🧝🏽 E5.0 elf: medium skin tone +1F9DD 1F3FE ; fully-qualified # 🧝🏾 E5.0 elf: medium-dark skin tone +1F9DD 1F3FF ; fully-qualified # 🧝🏿 E5.0 elf: dark skin tone +1F9DD 200D 2642 FE0F ; fully-qualified # 🧝‍♂️ E5.0 man elf +1F9DD 200D 2642 ; minimally-qualified # 🧝‍♂ E5.0 man elf +1F9DD 1F3FB 200D 2642 FE0F ; fully-qualified # 🧝🏻‍♂️ E5.0 man elf: light skin tone +1F9DD 1F3FB 200D 2642 ; minimally-qualified # 🧝🏻‍♂ E5.0 man elf: light skin tone +1F9DD 1F3FC 200D 2642 FE0F ; fully-qualified # 🧝🏼‍♂️ E5.0 man elf: medium-light skin tone +1F9DD 1F3FC 200D 2642 ; minimally-qualified # 🧝🏼‍♂ E5.0 man elf: medium-light skin tone +1F9DD 1F3FD 200D 2642 FE0F ; fully-qualified # 🧝🏽‍♂️ E5.0 man elf: medium skin tone +1F9DD 1F3FD 200D 2642 ; minimally-qualified # 🧝🏽‍♂ E5.0 man elf: medium skin tone +1F9DD 1F3FE 200D 2642 FE0F ; fully-qualified # 🧝🏾‍♂️ E5.0 man elf: medium-dark skin tone +1F9DD 1F3FE 200D 2642 ; minimally-qualified # 🧝🏾‍♂ E5.0 man elf: medium-dark skin tone +1F9DD 1F3FF 200D 2642 FE0F ; fully-qualified # 🧝🏿‍♂️ E5.0 man elf: dark skin tone +1F9DD 1F3FF 200D 2642 ; minimally-qualified # 🧝🏿‍♂ E5.0 man elf: dark skin tone +1F9DD 200D 2640 FE0F ; fully-qualified # 🧝‍♀️ E5.0 woman elf +1F9DD 200D 2640 ; minimally-qualified # 🧝‍♀ E5.0 woman elf +1F9DD 1F3FB 200D 2640 FE0F ; fully-qualified # 🧝🏻‍♀️ E5.0 woman elf: light skin tone +1F9DD 1F3FB 200D 2640 ; minimally-qualified # 🧝🏻‍♀ E5.0 woman elf: light skin tone +1F9DD 1F3FC 200D 2640 FE0F ; fully-qualified # 🧝🏼‍♀️ E5.0 woman elf: medium-light skin tone +1F9DD 1F3FC 200D 2640 ; minimally-qualified # 🧝🏼‍♀ E5.0 woman elf: medium-light skin tone +1F9DD 1F3FD 200D 2640 FE0F ; fully-qualified # 🧝🏽‍♀️ E5.0 woman elf: medium skin tone +1F9DD 1F3FD 200D 2640 ; minimally-qualified # 🧝🏽‍♀ E5.0 woman elf: medium skin tone +1F9DD 1F3FE 200D 2640 FE0F ; fully-qualified # 🧝🏾‍♀️ E5.0 woman elf: medium-dark skin tone +1F9DD 1F3FE 200D 2640 ; minimally-qualified # 🧝🏾‍♀ E5.0 woman elf: medium-dark skin tone +1F9DD 1F3FF 200D 2640 FE0F ; fully-qualified # 🧝🏿‍♀️ E5.0 woman elf: dark skin tone +1F9DD 1F3FF 200D 2640 ; minimally-qualified # 🧝🏿‍♀ E5.0 woman elf: dark skin tone +1F9DE ; fully-qualified # 🧞 E5.0 genie +1F9DE 200D 2642 FE0F ; fully-qualified # 🧞‍♂️ E5.0 man genie +1F9DE 200D 2642 ; minimally-qualified # 🧞‍♂ E5.0 man genie +1F9DE 200D 2640 FE0F ; fully-qualified # 🧞‍♀️ E5.0 woman genie +1F9DE 200D 2640 ; minimally-qualified # 🧞‍♀ E5.0 woman genie +1F9DF ; fully-qualified # 🧟 E5.0 zombie +1F9DF 200D 2642 FE0F ; fully-qualified # 🧟‍♂️ E5.0 man zombie +1F9DF 200D 2642 ; minimally-qualified # 🧟‍♂ E5.0 man zombie +1F9DF 200D 2640 FE0F ; fully-qualified # 🧟‍♀️ E5.0 woman zombie +1F9DF 200D 2640 ; minimally-qualified # 🧟‍♀ E5.0 woman zombie +1F9CC ; fully-qualified # 🧌 E14.0 troll + +# subgroup: person-activity +1F486 ; fully-qualified # 💆 E0.6 person getting massage +1F486 1F3FB ; fully-qualified # 💆🏻 E1.0 person getting massage: light skin tone +1F486 1F3FC ; fully-qualified # 💆🏼 E1.0 person getting massage: medium-light skin tone +1F486 1F3FD ; fully-qualified # 💆🏽 E1.0 person getting massage: medium skin tone +1F486 1F3FE ; fully-qualified # 💆🏾 E1.0 person getting massage: medium-dark skin tone +1F486 1F3FF ; fully-qualified # 💆🏿 E1.0 person getting massage: dark skin tone +1F486 200D 2642 FE0F ; fully-qualified # 💆‍♂️ E4.0 man getting massage +1F486 200D 2642 ; minimally-qualified # 💆‍♂ E4.0 man getting massage +1F486 1F3FB 200D 2642 FE0F ; fully-qualified # 💆🏻‍♂️ E4.0 man getting massage: light skin tone +1F486 1F3FB 200D 2642 ; minimally-qualified # 💆🏻‍♂ E4.0 man getting massage: light skin tone +1F486 1F3FC 200D 2642 FE0F ; fully-qualified # 💆🏼‍♂️ E4.0 man getting massage: medium-light skin tone +1F486 1F3FC 200D 2642 ; minimally-qualified # 💆🏼‍♂ E4.0 man getting massage: medium-light skin tone +1F486 1F3FD 200D 2642 FE0F ; fully-qualified # 💆🏽‍♂️ E4.0 man getting massage: medium skin tone +1F486 1F3FD 200D 2642 ; minimally-qualified # 💆🏽‍♂ E4.0 man getting massage: medium skin tone +1F486 1F3FE 200D 2642 FE0F ; fully-qualified # 💆🏾‍♂️ E4.0 man getting massage: medium-dark skin tone +1F486 1F3FE 200D 2642 ; minimally-qualified # 💆🏾‍♂ E4.0 man getting massage: medium-dark skin tone +1F486 1F3FF 200D 2642 FE0F ; fully-qualified # 💆🏿‍♂️ E4.0 man getting massage: dark skin tone +1F486 1F3FF 200D 2642 ; minimally-qualified # 💆🏿‍♂ E4.0 man getting massage: dark skin tone +1F486 200D 2640 FE0F ; fully-qualified # 💆‍♀️ E4.0 woman getting massage +1F486 200D 2640 ; minimally-qualified # 💆‍♀ E4.0 woman getting massage +1F486 1F3FB 200D 2640 FE0F ; fully-qualified # 💆🏻‍♀️ E4.0 woman getting massage: light skin tone +1F486 1F3FB 200D 2640 ; minimally-qualified # 💆🏻‍♀ E4.0 woman getting massage: light skin tone +1F486 1F3FC 200D 2640 FE0F ; fully-qualified # 💆🏼‍♀️ E4.0 woman getting massage: medium-light skin tone +1F486 1F3FC 200D 2640 ; minimally-qualified # 💆🏼‍♀ E4.0 woman getting massage: medium-light skin tone +1F486 1F3FD 200D 2640 FE0F ; fully-qualified # 💆🏽‍♀️ E4.0 woman getting massage: medium skin tone +1F486 1F3FD 200D 2640 ; minimally-qualified # 💆🏽‍♀ E4.0 woman getting massage: medium skin tone +1F486 1F3FE 200D 2640 FE0F ; fully-qualified # 💆🏾‍♀️ E4.0 woman getting massage: medium-dark skin tone +1F486 1F3FE 200D 2640 ; minimally-qualified # 💆🏾‍♀ E4.0 woman getting massage: medium-dark skin tone +1F486 1F3FF 200D 2640 FE0F ; fully-qualified # 💆🏿‍♀️ E4.0 woman getting massage: dark skin tone +1F486 1F3FF 200D 2640 ; minimally-qualified # 💆🏿‍♀ E4.0 woman getting massage: dark skin tone +1F487 ; fully-qualified # 💇 E0.6 person getting haircut +1F487 1F3FB ; fully-qualified # 💇🏻 E1.0 person getting haircut: light skin tone +1F487 1F3FC ; fully-qualified # 💇🏼 E1.0 person getting haircut: medium-light skin tone +1F487 1F3FD ; fully-qualified # 💇🏽 E1.0 person getting haircut: medium skin tone +1F487 1F3FE ; fully-qualified # 💇🏾 E1.0 person getting haircut: medium-dark skin tone +1F487 1F3FF ; fully-qualified # 💇🏿 E1.0 person getting haircut: dark skin tone +1F487 200D 2642 FE0F ; fully-qualified # 💇‍♂️ E4.0 man getting haircut +1F487 200D 2642 ; minimally-qualified # 💇‍♂ E4.0 man getting haircut +1F487 1F3FB 200D 2642 FE0F ; fully-qualified # 💇🏻‍♂️ E4.0 man getting haircut: light skin tone +1F487 1F3FB 200D 2642 ; minimally-qualified # 💇🏻‍♂ E4.0 man getting haircut: light skin tone +1F487 1F3FC 200D 2642 FE0F ; fully-qualified # 💇🏼‍♂️ E4.0 man getting haircut: medium-light skin tone +1F487 1F3FC 200D 2642 ; minimally-qualified # 💇🏼‍♂ E4.0 man getting haircut: medium-light skin tone +1F487 1F3FD 200D 2642 FE0F ; fully-qualified # 💇🏽‍♂️ E4.0 man getting haircut: medium skin tone +1F487 1F3FD 200D 2642 ; minimally-qualified # 💇🏽‍♂ E4.0 man getting haircut: medium skin tone +1F487 1F3FE 200D 2642 FE0F ; fully-qualified # 💇🏾‍♂️ E4.0 man getting haircut: medium-dark skin tone +1F487 1F3FE 200D 2642 ; minimally-qualified # 💇🏾‍♂ E4.0 man getting haircut: medium-dark skin tone +1F487 1F3FF 200D 2642 FE0F ; fully-qualified # 💇🏿‍♂️ E4.0 man getting haircut: dark skin tone +1F487 1F3FF 200D 2642 ; minimally-qualified # 💇🏿‍♂ E4.0 man getting haircut: dark skin tone +1F487 200D 2640 FE0F ; fully-qualified # 💇‍♀️ E4.0 woman getting haircut +1F487 200D 2640 ; minimally-qualified # 💇‍♀ E4.0 woman getting haircut +1F487 1F3FB 200D 2640 FE0F ; fully-qualified # 💇🏻‍♀️ E4.0 woman getting haircut: light skin tone +1F487 1F3FB 200D 2640 ; minimally-qualified # 💇🏻‍♀ E4.0 woman getting haircut: light skin tone +1F487 1F3FC 200D 2640 FE0F ; fully-qualified # 💇🏼‍♀️ E4.0 woman getting haircut: medium-light skin tone +1F487 1F3FC 200D 2640 ; minimally-qualified # 💇🏼‍♀ E4.0 woman getting haircut: medium-light skin tone +1F487 1F3FD 200D 2640 FE0F ; fully-qualified # 💇🏽‍♀️ E4.0 woman getting haircut: medium skin tone +1F487 1F3FD 200D 2640 ; minimally-qualified # 💇🏽‍♀ E4.0 woman getting haircut: medium skin tone +1F487 1F3FE 200D 2640 FE0F ; fully-qualified # 💇🏾‍♀️ E4.0 woman getting haircut: medium-dark skin tone +1F487 1F3FE 200D 2640 ; minimally-qualified # 💇🏾‍♀ E4.0 woman getting haircut: medium-dark skin tone +1F487 1F3FF 200D 2640 FE0F ; fully-qualified # 💇🏿‍♀️ E4.0 woman getting haircut: dark skin tone +1F487 1F3FF 200D 2640 ; minimally-qualified # 💇🏿‍♀ E4.0 woman getting haircut: dark skin tone +1F6B6 ; fully-qualified # 🚶 E0.6 person walking +1F6B6 1F3FB ; fully-qualified # 🚶🏻 E1.0 person walking: light skin tone +1F6B6 1F3FC ; fully-qualified # 🚶🏼 E1.0 person walking: medium-light skin tone +1F6B6 1F3FD ; fully-qualified # 🚶🏽 E1.0 person walking: medium skin tone +1F6B6 1F3FE ; fully-qualified # 🚶🏾 E1.0 person walking: medium-dark skin tone +1F6B6 1F3FF ; fully-qualified # 🚶🏿 E1.0 person walking: dark skin tone +1F6B6 200D 2642 FE0F ; fully-qualified # 🚶‍♂️ E4.0 man walking +1F6B6 200D 2642 ; minimally-qualified # 🚶‍♂ E4.0 man walking +1F6B6 1F3FB 200D 2642 FE0F ; fully-qualified # 🚶🏻‍♂️ E4.0 man walking: light skin tone +1F6B6 1F3FB 200D 2642 ; minimally-qualified # 🚶🏻‍♂ E4.0 man walking: light skin tone +1F6B6 1F3FC 200D 2642 FE0F ; fully-qualified # 🚶🏼‍♂️ E4.0 man walking: medium-light skin tone +1F6B6 1F3FC 200D 2642 ; minimally-qualified # 🚶🏼‍♂ E4.0 man walking: medium-light skin tone +1F6B6 1F3FD 200D 2642 FE0F ; fully-qualified # 🚶🏽‍♂️ E4.0 man walking: medium skin tone +1F6B6 1F3FD 200D 2642 ; minimally-qualified # 🚶🏽‍♂ E4.0 man walking: medium skin tone +1F6B6 1F3FE 200D 2642 FE0F ; fully-qualified # 🚶🏾‍♂️ E4.0 man walking: medium-dark skin tone +1F6B6 1F3FE 200D 2642 ; minimally-qualified # 🚶🏾‍♂ E4.0 man walking: medium-dark skin tone +1F6B6 1F3FF 200D 2642 FE0F ; fully-qualified # 🚶🏿‍♂️ E4.0 man walking: dark skin tone +1F6B6 1F3FF 200D 2642 ; minimally-qualified # 🚶🏿‍♂ E4.0 man walking: dark skin tone +1F6B6 200D 2640 FE0F ; fully-qualified # 🚶‍♀️ E4.0 woman walking +1F6B6 200D 2640 ; minimally-qualified # 🚶‍♀ E4.0 woman walking +1F6B6 1F3FB 200D 2640 FE0F ; fully-qualified # 🚶🏻‍♀️ E4.0 woman walking: light skin tone +1F6B6 1F3FB 200D 2640 ; minimally-qualified # 🚶🏻‍♀ E4.0 woman walking: light skin tone +1F6B6 1F3FC 200D 2640 FE0F ; fully-qualified # 🚶🏼‍♀️ E4.0 woman walking: medium-light skin tone +1F6B6 1F3FC 200D 2640 ; minimally-qualified # 🚶🏼‍♀ E4.0 woman walking: medium-light skin tone +1F6B6 1F3FD 200D 2640 FE0F ; fully-qualified # 🚶🏽‍♀️ E4.0 woman walking: medium skin tone +1F6B6 1F3FD 200D 2640 ; minimally-qualified # 🚶🏽‍♀ E4.0 woman walking: medium skin tone +1F6B6 1F3FE 200D 2640 FE0F ; fully-qualified # 🚶🏾‍♀️ E4.0 woman walking: medium-dark skin tone +1F6B6 1F3FE 200D 2640 ; minimally-qualified # 🚶🏾‍♀ E4.0 woman walking: medium-dark skin tone +1F6B6 1F3FF 200D 2640 FE0F ; fully-qualified # 🚶🏿‍♀️ E4.0 woman walking: dark skin tone +1F6B6 1F3FF 200D 2640 ; minimally-qualified # 🚶🏿‍♀ E4.0 woman walking: dark skin tone +1F9CD ; fully-qualified # 🧍 E12.0 person standing +1F9CD 1F3FB ; fully-qualified # 🧍🏻 E12.0 person standing: light skin tone +1F9CD 1F3FC ; fully-qualified # 🧍🏼 E12.0 person standing: medium-light skin tone +1F9CD 1F3FD ; fully-qualified # 🧍🏽 E12.0 person standing: medium skin tone +1F9CD 1F3FE ; fully-qualified # 🧍🏾 E12.0 person standing: medium-dark skin tone +1F9CD 1F3FF ; fully-qualified # 🧍🏿 E12.0 person standing: dark skin tone +1F9CD 200D 2642 FE0F ; fully-qualified # 🧍‍♂️ E12.0 man standing +1F9CD 200D 2642 ; minimally-qualified # 🧍‍♂ E12.0 man standing +1F9CD 1F3FB 200D 2642 FE0F ; fully-qualified # 🧍🏻‍♂️ E12.0 man standing: light skin tone +1F9CD 1F3FB 200D 2642 ; minimally-qualified # 🧍🏻‍♂ E12.0 man standing: light skin tone +1F9CD 1F3FC 200D 2642 FE0F ; fully-qualified # 🧍🏼‍♂️ E12.0 man standing: medium-light skin tone +1F9CD 1F3FC 200D 2642 ; minimally-qualified # 🧍🏼‍♂ E12.0 man standing: medium-light skin tone +1F9CD 1F3FD 200D 2642 FE0F ; fully-qualified # 🧍🏽‍♂️ E12.0 man standing: medium skin tone +1F9CD 1F3FD 200D 2642 ; minimally-qualified # 🧍🏽‍♂ E12.0 man standing: medium skin tone +1F9CD 1F3FE 200D 2642 FE0F ; fully-qualified # 🧍🏾‍♂️ E12.0 man standing: medium-dark skin tone +1F9CD 1F3FE 200D 2642 ; minimally-qualified # 🧍🏾‍♂ E12.0 man standing: medium-dark skin tone +1F9CD 1F3FF 200D 2642 FE0F ; fully-qualified # 🧍🏿‍♂️ E12.0 man standing: dark skin tone +1F9CD 1F3FF 200D 2642 ; minimally-qualified # 🧍🏿‍♂ E12.0 man standing: dark skin tone +1F9CD 200D 2640 FE0F ; fully-qualified # 🧍‍♀️ E12.0 woman standing +1F9CD 200D 2640 ; minimally-qualified # 🧍‍♀ E12.0 woman standing +1F9CD 1F3FB 200D 2640 FE0F ; fully-qualified # 🧍🏻‍♀️ E12.0 woman standing: light skin tone +1F9CD 1F3FB 200D 2640 ; minimally-qualified # 🧍🏻‍♀ E12.0 woman standing: light skin tone +1F9CD 1F3FC 200D 2640 FE0F ; fully-qualified # 🧍🏼‍♀️ E12.0 woman standing: medium-light skin tone +1F9CD 1F3FC 200D 2640 ; minimally-qualified # 🧍🏼‍♀ E12.0 woman standing: medium-light skin tone +1F9CD 1F3FD 200D 2640 FE0F ; fully-qualified # 🧍🏽‍♀️ E12.0 woman standing: medium skin tone +1F9CD 1F3FD 200D 2640 ; minimally-qualified # 🧍🏽‍♀ E12.0 woman standing: medium skin tone +1F9CD 1F3FE 200D 2640 FE0F ; fully-qualified # 🧍🏾‍♀️ E12.0 woman standing: medium-dark skin tone +1F9CD 1F3FE 200D 2640 ; minimally-qualified # 🧍🏾‍♀ E12.0 woman standing: medium-dark skin tone +1F9CD 1F3FF 200D 2640 FE0F ; fully-qualified # 🧍🏿‍♀️ E12.0 woman standing: dark skin tone +1F9CD 1F3FF 200D 2640 ; minimally-qualified # 🧍🏿‍♀ E12.0 woman standing: dark skin tone +1F9CE ; fully-qualified # 🧎 E12.0 person kneeling +1F9CE 1F3FB ; fully-qualified # 🧎🏻 E12.0 person kneeling: light skin tone +1F9CE 1F3FC ; fully-qualified # 🧎🏼 E12.0 person kneeling: medium-light skin tone +1F9CE 1F3FD ; fully-qualified # 🧎🏽 E12.0 person kneeling: medium skin tone +1F9CE 1F3FE ; fully-qualified # 🧎🏾 E12.0 person kneeling: medium-dark skin tone +1F9CE 1F3FF ; fully-qualified # 🧎🏿 E12.0 person kneeling: dark skin tone +1F9CE 200D 2642 FE0F ; fully-qualified # 🧎‍♂️ E12.0 man kneeling +1F9CE 200D 2642 ; minimally-qualified # 🧎‍♂ E12.0 man kneeling +1F9CE 1F3FB 200D 2642 FE0F ; fully-qualified # 🧎🏻‍♂️ E12.0 man kneeling: light skin tone +1F9CE 1F3FB 200D 2642 ; minimally-qualified # 🧎🏻‍♂ E12.0 man kneeling: light skin tone +1F9CE 1F3FC 200D 2642 FE0F ; fully-qualified # 🧎🏼‍♂️ E12.0 man kneeling: medium-light skin tone +1F9CE 1F3FC 200D 2642 ; minimally-qualified # 🧎🏼‍♂ E12.0 man kneeling: medium-light skin tone +1F9CE 1F3FD 200D 2642 FE0F ; fully-qualified # 🧎🏽‍♂️ E12.0 man kneeling: medium skin tone +1F9CE 1F3FD 200D 2642 ; minimally-qualified # 🧎🏽‍♂ E12.0 man kneeling: medium skin tone +1F9CE 1F3FE 200D 2642 FE0F ; fully-qualified # 🧎🏾‍♂️ E12.0 man kneeling: medium-dark skin tone +1F9CE 1F3FE 200D 2642 ; minimally-qualified # 🧎🏾‍♂ E12.0 man kneeling: medium-dark skin tone +1F9CE 1F3FF 200D 2642 FE0F ; fully-qualified # 🧎🏿‍♂️ E12.0 man kneeling: dark skin tone +1F9CE 1F3FF 200D 2642 ; minimally-qualified # 🧎🏿‍♂ E12.0 man kneeling: dark skin tone +1F9CE 200D 2640 FE0F ; fully-qualified # 🧎‍♀️ E12.0 woman kneeling +1F9CE 200D 2640 ; minimally-qualified # 🧎‍♀ E12.0 woman kneeling +1F9CE 1F3FB 200D 2640 FE0F ; fully-qualified # 🧎🏻‍♀️ E12.0 woman kneeling: light skin tone +1F9CE 1F3FB 200D 2640 ; minimally-qualified # 🧎🏻‍♀ E12.0 woman kneeling: light skin tone +1F9CE 1F3FC 200D 2640 FE0F ; fully-qualified # 🧎🏼‍♀️ E12.0 woman kneeling: medium-light skin tone +1F9CE 1F3FC 200D 2640 ; minimally-qualified # 🧎🏼‍♀ E12.0 woman kneeling: medium-light skin tone +1F9CE 1F3FD 200D 2640 FE0F ; fully-qualified # 🧎🏽‍♀️ E12.0 woman kneeling: medium skin tone +1F9CE 1F3FD 200D 2640 ; minimally-qualified # 🧎🏽‍♀ E12.0 woman kneeling: medium skin tone +1F9CE 1F3FE 200D 2640 FE0F ; fully-qualified # 🧎🏾‍♀️ E12.0 woman kneeling: medium-dark skin tone +1F9CE 1F3FE 200D 2640 ; minimally-qualified # 🧎🏾‍♀ E12.0 woman kneeling: medium-dark skin tone +1F9CE 1F3FF 200D 2640 FE0F ; fully-qualified # 🧎🏿‍♀️ E12.0 woman kneeling: dark skin tone +1F9CE 1F3FF 200D 2640 ; minimally-qualified # 🧎🏿‍♀ E12.0 woman kneeling: dark skin tone +1F9D1 200D 1F9AF ; fully-qualified # 🧑‍🦯 E12.1 person with white cane +1F9D1 1F3FB 200D 1F9AF ; fully-qualified # 🧑🏻‍🦯 E12.1 person with white cane: light skin tone +1F9D1 1F3FC 200D 1F9AF ; fully-qualified # 🧑🏼‍🦯 E12.1 person with white cane: medium-light skin tone +1F9D1 1F3FD 200D 1F9AF ; fully-qualified # 🧑🏽‍🦯 E12.1 person with white cane: medium skin tone +1F9D1 1F3FE 200D 1F9AF ; fully-qualified # 🧑🏾‍🦯 E12.1 person with white cane: medium-dark skin tone +1F9D1 1F3FF 200D 1F9AF ; fully-qualified # 🧑🏿‍🦯 E12.1 person with white cane: dark skin tone +1F468 200D 1F9AF ; fully-qualified # 👨‍🦯 E12.0 man with white cane +1F468 1F3FB 200D 1F9AF ; fully-qualified # 👨🏻‍🦯 E12.0 man with white cane: light skin tone +1F468 1F3FC 200D 1F9AF ; fully-qualified # 👨🏼‍🦯 E12.0 man with white cane: medium-light skin tone +1F468 1F3FD 200D 1F9AF ; fully-qualified # 👨🏽‍🦯 E12.0 man with white cane: medium skin tone +1F468 1F3FE 200D 1F9AF ; fully-qualified # 👨🏾‍🦯 E12.0 man with white cane: medium-dark skin tone +1F468 1F3FF 200D 1F9AF ; fully-qualified # 👨🏿‍🦯 E12.0 man with white cane: dark skin tone +1F469 200D 1F9AF ; fully-qualified # 👩‍🦯 E12.0 woman with white cane +1F469 1F3FB 200D 1F9AF ; fully-qualified # 👩🏻‍🦯 E12.0 woman with white cane: light skin tone +1F469 1F3FC 200D 1F9AF ; fully-qualified # 👩🏼‍🦯 E12.0 woman with white cane: medium-light skin tone +1F469 1F3FD 200D 1F9AF ; fully-qualified # 👩🏽‍🦯 E12.0 woman with white cane: medium skin tone +1F469 1F3FE 200D 1F9AF ; fully-qualified # 👩🏾‍🦯 E12.0 woman with white cane: medium-dark skin tone +1F469 1F3FF 200D 1F9AF ; fully-qualified # 👩🏿‍🦯 E12.0 woman with white cane: dark skin tone +1F9D1 200D 1F9BC ; fully-qualified # 🧑‍🦼 E12.1 person in motorized wheelchair +1F9D1 1F3FB 200D 1F9BC ; fully-qualified # 🧑🏻‍🦼 E12.1 person in motorized wheelchair: light skin tone +1F9D1 1F3FC 200D 1F9BC ; fully-qualified # 🧑🏼‍🦼 E12.1 person in motorized wheelchair: medium-light skin tone +1F9D1 1F3FD 200D 1F9BC ; fully-qualified # 🧑🏽‍🦼 E12.1 person in motorized wheelchair: medium skin tone +1F9D1 1F3FE 200D 1F9BC ; fully-qualified # 🧑🏾‍🦼 E12.1 person in motorized wheelchair: medium-dark skin tone +1F9D1 1F3FF 200D 1F9BC ; fully-qualified # 🧑🏿‍🦼 E12.1 person in motorized wheelchair: dark skin tone +1F468 200D 1F9BC ; fully-qualified # 👨‍🦼 E12.0 man in motorized wheelchair +1F468 1F3FB 200D 1F9BC ; fully-qualified # 👨🏻‍🦼 E12.0 man in motorized wheelchair: light skin tone +1F468 1F3FC 200D 1F9BC ; fully-qualified # 👨🏼‍🦼 E12.0 man in motorized wheelchair: medium-light skin tone +1F468 1F3FD 200D 1F9BC ; fully-qualified # 👨🏽‍🦼 E12.0 man in motorized wheelchair: medium skin tone +1F468 1F3FE 200D 1F9BC ; fully-qualified # 👨🏾‍🦼 E12.0 man in motorized wheelchair: medium-dark skin tone +1F468 1F3FF 200D 1F9BC ; fully-qualified # 👨🏿‍🦼 E12.0 man in motorized wheelchair: dark skin tone +1F469 200D 1F9BC ; fully-qualified # 👩‍🦼 E12.0 woman in motorized wheelchair +1F469 1F3FB 200D 1F9BC ; fully-qualified # 👩🏻‍🦼 E12.0 woman in motorized wheelchair: light skin tone +1F469 1F3FC 200D 1F9BC ; fully-qualified # 👩🏼‍🦼 E12.0 woman in motorized wheelchair: medium-light skin tone +1F469 1F3FD 200D 1F9BC ; fully-qualified # 👩🏽‍🦼 E12.0 woman in motorized wheelchair: medium skin tone +1F469 1F3FE 200D 1F9BC ; fully-qualified # 👩🏾‍🦼 E12.0 woman in motorized wheelchair: medium-dark skin tone +1F469 1F3FF 200D 1F9BC ; fully-qualified # 👩🏿‍🦼 E12.0 woman in motorized wheelchair: dark skin tone +1F9D1 200D 1F9BD ; fully-qualified # 🧑‍🦽 E12.1 person in manual wheelchair +1F9D1 1F3FB 200D 1F9BD ; fully-qualified # 🧑🏻‍🦽 E12.1 person in manual wheelchair: light skin tone +1F9D1 1F3FC 200D 1F9BD ; fully-qualified # 🧑🏼‍🦽 E12.1 person in manual wheelchair: medium-light skin tone +1F9D1 1F3FD 200D 1F9BD ; fully-qualified # 🧑🏽‍🦽 E12.1 person in manual wheelchair: medium skin tone +1F9D1 1F3FE 200D 1F9BD ; fully-qualified # 🧑🏾‍🦽 E12.1 person in manual wheelchair: medium-dark skin tone +1F9D1 1F3FF 200D 1F9BD ; fully-qualified # 🧑🏿‍🦽 E12.1 person in manual wheelchair: dark skin tone +1F468 200D 1F9BD ; fully-qualified # 👨‍🦽 E12.0 man in manual wheelchair +1F468 1F3FB 200D 1F9BD ; fully-qualified # 👨🏻‍🦽 E12.0 man in manual wheelchair: light skin tone +1F468 1F3FC 200D 1F9BD ; fully-qualified # 👨🏼‍🦽 E12.0 man in manual wheelchair: medium-light skin tone +1F468 1F3FD 200D 1F9BD ; fully-qualified # 👨🏽‍🦽 E12.0 man in manual wheelchair: medium skin tone +1F468 1F3FE 200D 1F9BD ; fully-qualified # 👨🏾‍🦽 E12.0 man in manual wheelchair: medium-dark skin tone +1F468 1F3FF 200D 1F9BD ; fully-qualified # 👨🏿‍🦽 E12.0 man in manual wheelchair: dark skin tone +1F469 200D 1F9BD ; fully-qualified # 👩‍🦽 E12.0 woman in manual wheelchair +1F469 1F3FB 200D 1F9BD ; fully-qualified # 👩🏻‍🦽 E12.0 woman in manual wheelchair: light skin tone +1F469 1F3FC 200D 1F9BD ; fully-qualified # 👩🏼‍🦽 E12.0 woman in manual wheelchair: medium-light skin tone +1F469 1F3FD 200D 1F9BD ; fully-qualified # 👩🏽‍🦽 E12.0 woman in manual wheelchair: medium skin tone +1F469 1F3FE 200D 1F9BD ; fully-qualified # 👩🏾‍🦽 E12.0 woman in manual wheelchair: medium-dark skin tone +1F469 1F3FF 200D 1F9BD ; fully-qualified # 👩🏿‍🦽 E12.0 woman in manual wheelchair: dark skin tone +1F3C3 ; fully-qualified # 🏃 E0.6 person running +1F3C3 1F3FB ; fully-qualified # 🏃🏻 E1.0 person running: light skin tone +1F3C3 1F3FC ; fully-qualified # 🏃🏼 E1.0 person running: medium-light skin tone +1F3C3 1F3FD ; fully-qualified # 🏃🏽 E1.0 person running: medium skin tone +1F3C3 1F3FE ; fully-qualified # 🏃🏾 E1.0 person running: medium-dark skin tone +1F3C3 1F3FF ; fully-qualified # 🏃🏿 E1.0 person running: dark skin tone +1F3C3 200D 2642 FE0F ; fully-qualified # 🏃‍♂️ E4.0 man running +1F3C3 200D 2642 ; minimally-qualified # 🏃‍♂ E4.0 man running +1F3C3 1F3FB 200D 2642 FE0F ; fully-qualified # 🏃🏻‍♂️ E4.0 man running: light skin tone +1F3C3 1F3FB 200D 2642 ; minimally-qualified # 🏃🏻‍♂ E4.0 man running: light skin tone +1F3C3 1F3FC 200D 2642 FE0F ; fully-qualified # 🏃🏼‍♂️ E4.0 man running: medium-light skin tone +1F3C3 1F3FC 200D 2642 ; minimally-qualified # 🏃🏼‍♂ E4.0 man running: medium-light skin tone +1F3C3 1F3FD 200D 2642 FE0F ; fully-qualified # 🏃🏽‍♂️ E4.0 man running: medium skin tone +1F3C3 1F3FD 200D 2642 ; minimally-qualified # 🏃🏽‍♂ E4.0 man running: medium skin tone +1F3C3 1F3FE 200D 2642 FE0F ; fully-qualified # 🏃🏾‍♂️ E4.0 man running: medium-dark skin tone +1F3C3 1F3FE 200D 2642 ; minimally-qualified # 🏃🏾‍♂ E4.0 man running: medium-dark skin tone +1F3C3 1F3FF 200D 2642 FE0F ; fully-qualified # 🏃🏿‍♂️ E4.0 man running: dark skin tone +1F3C3 1F3FF 200D 2642 ; minimally-qualified # 🏃🏿‍♂ E4.0 man running: dark skin tone +1F3C3 200D 2640 FE0F ; fully-qualified # 🏃‍♀️ E4.0 woman running +1F3C3 200D 2640 ; minimally-qualified # 🏃‍♀ E4.0 woman running +1F3C3 1F3FB 200D 2640 FE0F ; fully-qualified # 🏃🏻‍♀️ E4.0 woman running: light skin tone +1F3C3 1F3FB 200D 2640 ; minimally-qualified # 🏃🏻‍♀ E4.0 woman running: light skin tone +1F3C3 1F3FC 200D 2640 FE0F ; fully-qualified # 🏃🏼‍♀️ E4.0 woman running: medium-light skin tone +1F3C3 1F3FC 200D 2640 ; minimally-qualified # 🏃🏼‍♀ E4.0 woman running: medium-light skin tone +1F3C3 1F3FD 200D 2640 FE0F ; fully-qualified # 🏃🏽‍♀️ E4.0 woman running: medium skin tone +1F3C3 1F3FD 200D 2640 ; minimally-qualified # 🏃🏽‍♀ E4.0 woman running: medium skin tone +1F3C3 1F3FE 200D 2640 FE0F ; fully-qualified # 🏃🏾‍♀️ E4.0 woman running: medium-dark skin tone +1F3C3 1F3FE 200D 2640 ; minimally-qualified # 🏃🏾‍♀ E4.0 woman running: medium-dark skin tone +1F3C3 1F3FF 200D 2640 FE0F ; fully-qualified # 🏃🏿‍♀️ E4.0 woman running: dark skin tone +1F3C3 1F3FF 200D 2640 ; minimally-qualified # 🏃🏿‍♀ E4.0 woman running: dark skin tone +1F483 ; fully-qualified # 💃 E0.6 woman dancing +1F483 1F3FB ; fully-qualified # 💃🏻 E1.0 woman dancing: light skin tone +1F483 1F3FC ; fully-qualified # 💃🏼 E1.0 woman dancing: medium-light skin tone +1F483 1F3FD ; fully-qualified # 💃🏽 E1.0 woman dancing: medium skin tone +1F483 1F3FE ; fully-qualified # 💃🏾 E1.0 woman dancing: medium-dark skin tone +1F483 1F3FF ; fully-qualified # 💃🏿 E1.0 woman dancing: dark skin tone +1F57A ; fully-qualified # 🕺 E3.0 man dancing +1F57A 1F3FB ; fully-qualified # 🕺🏻 E3.0 man dancing: light skin tone +1F57A 1F3FC ; fully-qualified # 🕺🏼 E3.0 man dancing: medium-light skin tone +1F57A 1F3FD ; fully-qualified # 🕺🏽 E3.0 man dancing: medium skin tone +1F57A 1F3FE ; fully-qualified # 🕺🏾 E3.0 man dancing: medium-dark skin tone +1F57A 1F3FF ; fully-qualified # 🕺🏿 E3.0 man dancing: dark skin tone +1F574 FE0F ; fully-qualified # 🕴️ E0.7 person in suit levitating +1F574 ; unqualified # 🕴 E0.7 person in suit levitating +1F574 1F3FB ; fully-qualified # 🕴🏻 E4.0 person in suit levitating: light skin tone +1F574 1F3FC ; fully-qualified # 🕴🏼 E4.0 person in suit levitating: medium-light skin tone +1F574 1F3FD ; fully-qualified # 🕴🏽 E4.0 person in suit levitating: medium skin tone +1F574 1F3FE ; fully-qualified # 🕴🏾 E4.0 person in suit levitating: medium-dark skin tone +1F574 1F3FF ; fully-qualified # 🕴🏿 E4.0 person in suit levitating: dark skin tone +1F46F ; fully-qualified # 👯 E0.6 people with bunny ears +1F46F 200D 2642 FE0F ; fully-qualified # 👯‍♂️ E4.0 men with bunny ears +1F46F 200D 2642 ; minimally-qualified # 👯‍♂ E4.0 men with bunny ears +1F46F 200D 2640 FE0F ; fully-qualified # 👯‍♀️ E4.0 women with bunny ears +1F46F 200D 2640 ; minimally-qualified # 👯‍♀ E4.0 women with bunny ears +1F9D6 ; fully-qualified # 🧖 E5.0 person in steamy room +1F9D6 1F3FB ; fully-qualified # 🧖🏻 E5.0 person in steamy room: light skin tone +1F9D6 1F3FC ; fully-qualified # 🧖🏼 E5.0 person in steamy room: medium-light skin tone +1F9D6 1F3FD ; fully-qualified # 🧖🏽 E5.0 person in steamy room: medium skin tone +1F9D6 1F3FE ; fully-qualified # 🧖🏾 E5.0 person in steamy room: medium-dark skin tone +1F9D6 1F3FF ; fully-qualified # 🧖🏿 E5.0 person in steamy room: dark skin tone +1F9D6 200D 2642 FE0F ; fully-qualified # 🧖‍♂️ E5.0 man in steamy room +1F9D6 200D 2642 ; minimally-qualified # 🧖‍♂ E5.0 man in steamy room +1F9D6 1F3FB 200D 2642 FE0F ; fully-qualified # 🧖🏻‍♂️ E5.0 man in steamy room: light skin tone +1F9D6 1F3FB 200D 2642 ; minimally-qualified # 🧖🏻‍♂ E5.0 man in steamy room: light skin tone +1F9D6 1F3FC 200D 2642 FE0F ; fully-qualified # 🧖🏼‍♂️ E5.0 man in steamy room: medium-light skin tone +1F9D6 1F3FC 200D 2642 ; minimally-qualified # 🧖🏼‍♂ E5.0 man in steamy room: medium-light skin tone +1F9D6 1F3FD 200D 2642 FE0F ; fully-qualified # 🧖🏽‍♂️ E5.0 man in steamy room: medium skin tone +1F9D6 1F3FD 200D 2642 ; minimally-qualified # 🧖🏽‍♂ E5.0 man in steamy room: medium skin tone +1F9D6 1F3FE 200D 2642 FE0F ; fully-qualified # 🧖🏾‍♂️ E5.0 man in steamy room: medium-dark skin tone +1F9D6 1F3FE 200D 2642 ; minimally-qualified # 🧖🏾‍♂ E5.0 man in steamy room: medium-dark skin tone +1F9D6 1F3FF 200D 2642 FE0F ; fully-qualified # 🧖🏿‍♂️ E5.0 man in steamy room: dark skin tone +1F9D6 1F3FF 200D 2642 ; minimally-qualified # 🧖🏿‍♂ E5.0 man in steamy room: dark skin tone +1F9D6 200D 2640 FE0F ; fully-qualified # 🧖‍♀️ E5.0 woman in steamy room +1F9D6 200D 2640 ; minimally-qualified # 🧖‍♀ E5.0 woman in steamy room +1F9D6 1F3FB 200D 2640 FE0F ; fully-qualified # 🧖🏻‍♀️ E5.0 woman in steamy room: light skin tone +1F9D6 1F3FB 200D 2640 ; minimally-qualified # 🧖🏻‍♀ E5.0 woman in steamy room: light skin tone +1F9D6 1F3FC 200D 2640 FE0F ; fully-qualified # 🧖🏼‍♀️ E5.0 woman in steamy room: medium-light skin tone +1F9D6 1F3FC 200D 2640 ; minimally-qualified # 🧖🏼‍♀ E5.0 woman in steamy room: medium-light skin tone +1F9D6 1F3FD 200D 2640 FE0F ; fully-qualified # 🧖🏽‍♀️ E5.0 woman in steamy room: medium skin tone +1F9D6 1F3FD 200D 2640 ; minimally-qualified # 🧖🏽‍♀ E5.0 woman in steamy room: medium skin tone +1F9D6 1F3FE 200D 2640 FE0F ; fully-qualified # 🧖🏾‍♀️ E5.0 woman in steamy room: medium-dark skin tone +1F9D6 1F3FE 200D 2640 ; minimally-qualified # 🧖🏾‍♀ E5.0 woman in steamy room: medium-dark skin tone +1F9D6 1F3FF 200D 2640 FE0F ; fully-qualified # 🧖🏿‍♀️ E5.0 woman in steamy room: dark skin tone +1F9D6 1F3FF 200D 2640 ; minimally-qualified # 🧖🏿‍♀ E5.0 woman in steamy room: dark skin tone +1F9D7 ; fully-qualified # 🧗 E5.0 person climbing +1F9D7 1F3FB ; fully-qualified # 🧗🏻 E5.0 person climbing: light skin tone +1F9D7 1F3FC ; fully-qualified # 🧗🏼 E5.0 person climbing: medium-light skin tone +1F9D7 1F3FD ; fully-qualified # 🧗🏽 E5.0 person climbing: medium skin tone +1F9D7 1F3FE ; fully-qualified # 🧗🏾 E5.0 person climbing: medium-dark skin tone +1F9D7 1F3FF ; fully-qualified # 🧗🏿 E5.0 person climbing: dark skin tone +1F9D7 200D 2642 FE0F ; fully-qualified # 🧗‍♂️ E5.0 man climbing +1F9D7 200D 2642 ; minimally-qualified # 🧗‍♂ E5.0 man climbing +1F9D7 1F3FB 200D 2642 FE0F ; fully-qualified # 🧗🏻‍♂️ E5.0 man climbing: light skin tone +1F9D7 1F3FB 200D 2642 ; minimally-qualified # 🧗🏻‍♂ E5.0 man climbing: light skin tone +1F9D7 1F3FC 200D 2642 FE0F ; fully-qualified # 🧗🏼‍♂️ E5.0 man climbing: medium-light skin tone +1F9D7 1F3FC 200D 2642 ; minimally-qualified # 🧗🏼‍♂ E5.0 man climbing: medium-light skin tone +1F9D7 1F3FD 200D 2642 FE0F ; fully-qualified # 🧗🏽‍♂️ E5.0 man climbing: medium skin tone +1F9D7 1F3FD 200D 2642 ; minimally-qualified # 🧗🏽‍♂ E5.0 man climbing: medium skin tone +1F9D7 1F3FE 200D 2642 FE0F ; fully-qualified # 🧗🏾‍♂️ E5.0 man climbing: medium-dark skin tone +1F9D7 1F3FE 200D 2642 ; minimally-qualified # 🧗🏾‍♂ E5.0 man climbing: medium-dark skin tone +1F9D7 1F3FF 200D 2642 FE0F ; fully-qualified # 🧗🏿‍♂️ E5.0 man climbing: dark skin tone +1F9D7 1F3FF 200D 2642 ; minimally-qualified # 🧗🏿‍♂ E5.0 man climbing: dark skin tone +1F9D7 200D 2640 FE0F ; fully-qualified # 🧗‍♀️ E5.0 woman climbing +1F9D7 200D 2640 ; minimally-qualified # 🧗‍♀ E5.0 woman climbing +1F9D7 1F3FB 200D 2640 FE0F ; fully-qualified # 🧗🏻‍♀️ E5.0 woman climbing: light skin tone +1F9D7 1F3FB 200D 2640 ; minimally-qualified # 🧗🏻‍♀ E5.0 woman climbing: light skin tone +1F9D7 1F3FC 200D 2640 FE0F ; fully-qualified # 🧗🏼‍♀️ E5.0 woman climbing: medium-light skin tone +1F9D7 1F3FC 200D 2640 ; minimally-qualified # 🧗🏼‍♀ E5.0 woman climbing: medium-light skin tone +1F9D7 1F3FD 200D 2640 FE0F ; fully-qualified # 🧗🏽‍♀️ E5.0 woman climbing: medium skin tone +1F9D7 1F3FD 200D 2640 ; minimally-qualified # 🧗🏽‍♀ E5.0 woman climbing: medium skin tone +1F9D7 1F3FE 200D 2640 FE0F ; fully-qualified # 🧗🏾‍♀️ E5.0 woman climbing: medium-dark skin tone +1F9D7 1F3FE 200D 2640 ; minimally-qualified # 🧗🏾‍♀ E5.0 woman climbing: medium-dark skin tone +1F9D7 1F3FF 200D 2640 FE0F ; fully-qualified # 🧗🏿‍♀️ E5.0 woman climbing: dark skin tone +1F9D7 1F3FF 200D 2640 ; minimally-qualified # 🧗🏿‍♀ E5.0 woman climbing: dark skin tone + +# subgroup: person-sport +1F93A ; fully-qualified # 🤺 E3.0 person fencing +1F3C7 ; fully-qualified # 🏇 E1.0 horse racing +1F3C7 1F3FB ; fully-qualified # 🏇🏻 E1.0 horse racing: light skin tone +1F3C7 1F3FC ; fully-qualified # 🏇🏼 E1.0 horse racing: medium-light skin tone +1F3C7 1F3FD ; fully-qualified # 🏇🏽 E1.0 horse racing: medium skin tone +1F3C7 1F3FE ; fully-qualified # 🏇🏾 E1.0 horse racing: medium-dark skin tone +1F3C7 1F3FF ; fully-qualified # 🏇🏿 E1.0 horse racing: dark skin tone +26F7 FE0F ; fully-qualified # ⛷️ E0.7 skier +26F7 ; unqualified # ⛷ E0.7 skier +1F3C2 ; fully-qualified # 🏂 E0.6 snowboarder +1F3C2 1F3FB ; fully-qualified # 🏂🏻 E1.0 snowboarder: light skin tone +1F3C2 1F3FC ; fully-qualified # 🏂🏼 E1.0 snowboarder: medium-light skin tone +1F3C2 1F3FD ; fully-qualified # 🏂🏽 E1.0 snowboarder: medium skin tone +1F3C2 1F3FE ; fully-qualified # 🏂🏾 E1.0 snowboarder: medium-dark skin tone +1F3C2 1F3FF ; fully-qualified # 🏂🏿 E1.0 snowboarder: dark skin tone +1F3CC FE0F ; fully-qualified # 🏌️ E0.7 person golfing +1F3CC ; unqualified # 🏌 E0.7 person golfing +1F3CC 1F3FB ; fully-qualified # 🏌🏻 E4.0 person golfing: light skin tone +1F3CC 1F3FC ; fully-qualified # 🏌🏼 E4.0 person golfing: medium-light skin tone +1F3CC 1F3FD ; fully-qualified # 🏌🏽 E4.0 person golfing: medium skin tone +1F3CC 1F3FE ; fully-qualified # 🏌🏾 E4.0 person golfing: medium-dark skin tone +1F3CC 1F3FF ; fully-qualified # 🏌🏿 E4.0 person golfing: dark skin tone +1F3CC FE0F 200D 2642 FE0F ; fully-qualified # 🏌️‍♂️ E4.0 man golfing +1F3CC 200D 2642 FE0F ; unqualified # 🏌‍♂️ E4.0 man golfing +1F3CC FE0F 200D 2642 ; minimally-qualified # 🏌️‍♂ E4.0 man golfing +1F3CC 200D 2642 ; unqualified # 🏌‍♂ E4.0 man golfing +1F3CC 1F3FB 200D 2642 FE0F ; fully-qualified # 🏌🏻‍♂️ E4.0 man golfing: light skin tone +1F3CC 1F3FB 200D 2642 ; minimally-qualified # 🏌🏻‍♂ E4.0 man golfing: light skin tone +1F3CC 1F3FC 200D 2642 FE0F ; fully-qualified # 🏌🏼‍♂️ E4.0 man golfing: medium-light skin tone +1F3CC 1F3FC 200D 2642 ; minimally-qualified # 🏌🏼‍♂ E4.0 man golfing: medium-light skin tone +1F3CC 1F3FD 200D 2642 FE0F ; fully-qualified # 🏌🏽‍♂️ E4.0 man golfing: medium skin tone +1F3CC 1F3FD 200D 2642 ; minimally-qualified # 🏌🏽‍♂ E4.0 man golfing: medium skin tone +1F3CC 1F3FE 200D 2642 FE0F ; fully-qualified # 🏌🏾‍♂️ E4.0 man golfing: medium-dark skin tone +1F3CC 1F3FE 200D 2642 ; minimally-qualified # 🏌🏾‍♂ E4.0 man golfing: medium-dark skin tone +1F3CC 1F3FF 200D 2642 FE0F ; fully-qualified # 🏌🏿‍♂️ E4.0 man golfing: dark skin tone +1F3CC 1F3FF 200D 2642 ; minimally-qualified # 🏌🏿‍♂ E4.0 man golfing: dark skin tone +1F3CC FE0F 200D 2640 FE0F ; fully-qualified # 🏌️‍♀️ E4.0 woman golfing +1F3CC 200D 2640 FE0F ; unqualified # 🏌‍♀️ E4.0 woman golfing +1F3CC FE0F 200D 2640 ; minimally-qualified # 🏌️‍♀ E4.0 woman golfing +1F3CC 200D 2640 ; unqualified # 🏌‍♀ E4.0 woman golfing +1F3CC 1F3FB 200D 2640 FE0F ; fully-qualified # 🏌🏻‍♀️ E4.0 woman golfing: light skin tone +1F3CC 1F3FB 200D 2640 ; minimally-qualified # 🏌🏻‍♀ E4.0 woman golfing: light skin tone +1F3CC 1F3FC 200D 2640 FE0F ; fully-qualified # 🏌🏼‍♀️ E4.0 woman golfing: medium-light skin tone +1F3CC 1F3FC 200D 2640 ; minimally-qualified # 🏌🏼‍♀ E4.0 woman golfing: medium-light skin tone +1F3CC 1F3FD 200D 2640 FE0F ; fully-qualified # 🏌🏽‍♀️ E4.0 woman golfing: medium skin tone +1F3CC 1F3FD 200D 2640 ; minimally-qualified # 🏌🏽‍♀ E4.0 woman golfing: medium skin tone +1F3CC 1F3FE 200D 2640 FE0F ; fully-qualified # 🏌🏾‍♀️ E4.0 woman golfing: medium-dark skin tone +1F3CC 1F3FE 200D 2640 ; minimally-qualified # 🏌🏾‍♀ E4.0 woman golfing: medium-dark skin tone +1F3CC 1F3FF 200D 2640 FE0F ; fully-qualified # 🏌🏿‍♀️ E4.0 woman golfing: dark skin tone +1F3CC 1F3FF 200D 2640 ; minimally-qualified # 🏌🏿‍♀ E4.0 woman golfing: dark skin tone +1F3C4 ; fully-qualified # 🏄 E0.6 person surfing +1F3C4 1F3FB ; fully-qualified # 🏄🏻 E1.0 person surfing: light skin tone +1F3C4 1F3FC ; fully-qualified # 🏄🏼 E1.0 person surfing: medium-light skin tone +1F3C4 1F3FD ; fully-qualified # 🏄🏽 E1.0 person surfing: medium skin tone +1F3C4 1F3FE ; fully-qualified # 🏄🏾 E1.0 person surfing: medium-dark skin tone +1F3C4 1F3FF ; fully-qualified # 🏄🏿 E1.0 person surfing: dark skin tone +1F3C4 200D 2642 FE0F ; fully-qualified # 🏄‍♂️ E4.0 man surfing +1F3C4 200D 2642 ; minimally-qualified # 🏄‍♂ E4.0 man surfing +1F3C4 1F3FB 200D 2642 FE0F ; fully-qualified # 🏄🏻‍♂️ E4.0 man surfing: light skin tone +1F3C4 1F3FB 200D 2642 ; minimally-qualified # 🏄🏻‍♂ E4.0 man surfing: light skin tone +1F3C4 1F3FC 200D 2642 FE0F ; fully-qualified # 🏄🏼‍♂️ E4.0 man surfing: medium-light skin tone +1F3C4 1F3FC 200D 2642 ; minimally-qualified # 🏄🏼‍♂ E4.0 man surfing: medium-light skin tone +1F3C4 1F3FD 200D 2642 FE0F ; fully-qualified # 🏄🏽‍♂️ E4.0 man surfing: medium skin tone +1F3C4 1F3FD 200D 2642 ; minimally-qualified # 🏄🏽‍♂ E4.0 man surfing: medium skin tone +1F3C4 1F3FE 200D 2642 FE0F ; fully-qualified # 🏄🏾‍♂️ E4.0 man surfing: medium-dark skin tone +1F3C4 1F3FE 200D 2642 ; minimally-qualified # 🏄🏾‍♂ E4.0 man surfing: medium-dark skin tone +1F3C4 1F3FF 200D 2642 FE0F ; fully-qualified # 🏄🏿‍♂️ E4.0 man surfing: dark skin tone +1F3C4 1F3FF 200D 2642 ; minimally-qualified # 🏄🏿‍♂ E4.0 man surfing: dark skin tone +1F3C4 200D 2640 FE0F ; fully-qualified # 🏄‍♀️ E4.0 woman surfing +1F3C4 200D 2640 ; minimally-qualified # 🏄‍♀ E4.0 woman surfing +1F3C4 1F3FB 200D 2640 FE0F ; fully-qualified # 🏄🏻‍♀️ E4.0 woman surfing: light skin tone +1F3C4 1F3FB 200D 2640 ; minimally-qualified # 🏄🏻‍♀ E4.0 woman surfing: light skin tone +1F3C4 1F3FC 200D 2640 FE0F ; fully-qualified # 🏄🏼‍♀️ E4.0 woman surfing: medium-light skin tone +1F3C4 1F3FC 200D 2640 ; minimally-qualified # 🏄🏼‍♀ E4.0 woman surfing: medium-light skin tone +1F3C4 1F3FD 200D 2640 FE0F ; fully-qualified # 🏄🏽‍♀️ E4.0 woman surfing: medium skin tone +1F3C4 1F3FD 200D 2640 ; minimally-qualified # 🏄🏽‍♀ E4.0 woman surfing: medium skin tone +1F3C4 1F3FE 200D 2640 FE0F ; fully-qualified # 🏄🏾‍♀️ E4.0 woman surfing: medium-dark skin tone +1F3C4 1F3FE 200D 2640 ; minimally-qualified # 🏄🏾‍♀ E4.0 woman surfing: medium-dark skin tone +1F3C4 1F3FF 200D 2640 FE0F ; fully-qualified # 🏄🏿‍♀️ E4.0 woman surfing: dark skin tone +1F3C4 1F3FF 200D 2640 ; minimally-qualified # 🏄🏿‍♀ E4.0 woman surfing: dark skin tone +1F6A3 ; fully-qualified # 🚣 E1.0 person rowing boat +1F6A3 1F3FB ; fully-qualified # 🚣🏻 E1.0 person rowing boat: light skin tone +1F6A3 1F3FC ; fully-qualified # 🚣🏼 E1.0 person rowing boat: medium-light skin tone +1F6A3 1F3FD ; fully-qualified # 🚣🏽 E1.0 person rowing boat: medium skin tone +1F6A3 1F3FE ; fully-qualified # 🚣🏾 E1.0 person rowing boat: medium-dark skin tone +1F6A3 1F3FF ; fully-qualified # 🚣🏿 E1.0 person rowing boat: dark skin tone +1F6A3 200D 2642 FE0F ; fully-qualified # 🚣‍♂️ E4.0 man rowing boat +1F6A3 200D 2642 ; minimally-qualified # 🚣‍♂ E4.0 man rowing boat +1F6A3 1F3FB 200D 2642 FE0F ; fully-qualified # 🚣🏻‍♂️ E4.0 man rowing boat: light skin tone +1F6A3 1F3FB 200D 2642 ; minimally-qualified # 🚣🏻‍♂ E4.0 man rowing boat: light skin tone +1F6A3 1F3FC 200D 2642 FE0F ; fully-qualified # 🚣🏼‍♂️ E4.0 man rowing boat: medium-light skin tone +1F6A3 1F3FC 200D 2642 ; minimally-qualified # 🚣🏼‍♂ E4.0 man rowing boat: medium-light skin tone +1F6A3 1F3FD 200D 2642 FE0F ; fully-qualified # 🚣🏽‍♂️ E4.0 man rowing boat: medium skin tone +1F6A3 1F3FD 200D 2642 ; minimally-qualified # 🚣🏽‍♂ E4.0 man rowing boat: medium skin tone +1F6A3 1F3FE 200D 2642 FE0F ; fully-qualified # 🚣🏾‍♂️ E4.0 man rowing boat: medium-dark skin tone +1F6A3 1F3FE 200D 2642 ; minimally-qualified # 🚣🏾‍♂ E4.0 man rowing boat: medium-dark skin tone +1F6A3 1F3FF 200D 2642 FE0F ; fully-qualified # 🚣🏿‍♂️ E4.0 man rowing boat: dark skin tone +1F6A3 1F3FF 200D 2642 ; minimally-qualified # 🚣🏿‍♂ E4.0 man rowing boat: dark skin tone +1F6A3 200D 2640 FE0F ; fully-qualified # 🚣‍♀️ E4.0 woman rowing boat +1F6A3 200D 2640 ; minimally-qualified # 🚣‍♀ E4.0 woman rowing boat +1F6A3 1F3FB 200D 2640 FE0F ; fully-qualified # 🚣🏻‍♀️ E4.0 woman rowing boat: light skin tone +1F6A3 1F3FB 200D 2640 ; minimally-qualified # 🚣🏻‍♀ E4.0 woman rowing boat: light skin tone +1F6A3 1F3FC 200D 2640 FE0F ; fully-qualified # 🚣🏼‍♀️ E4.0 woman rowing boat: medium-light skin tone +1F6A3 1F3FC 200D 2640 ; minimally-qualified # 🚣🏼‍♀ E4.0 woman rowing boat: medium-light skin tone +1F6A3 1F3FD 200D 2640 FE0F ; fully-qualified # 🚣🏽‍♀️ E4.0 woman rowing boat: medium skin tone +1F6A3 1F3FD 200D 2640 ; minimally-qualified # 🚣🏽‍♀ E4.0 woman rowing boat: medium skin tone +1F6A3 1F3FE 200D 2640 FE0F ; fully-qualified # 🚣🏾‍♀️ E4.0 woman rowing boat: medium-dark skin tone +1F6A3 1F3FE 200D 2640 ; minimally-qualified # 🚣🏾‍♀ E4.0 woman rowing boat: medium-dark skin tone +1F6A3 1F3FF 200D 2640 FE0F ; fully-qualified # 🚣🏿‍♀️ E4.0 woman rowing boat: dark skin tone +1F6A3 1F3FF 200D 2640 ; minimally-qualified # 🚣🏿‍♀ E4.0 woman rowing boat: dark skin tone +1F3CA ; fully-qualified # 🏊 E0.6 person swimming +1F3CA 1F3FB ; fully-qualified # 🏊🏻 E1.0 person swimming: light skin tone +1F3CA 1F3FC ; fully-qualified # 🏊🏼 E1.0 person swimming: medium-light skin tone +1F3CA 1F3FD ; fully-qualified # 🏊🏽 E1.0 person swimming: medium skin tone +1F3CA 1F3FE ; fully-qualified # 🏊🏾 E1.0 person swimming: medium-dark skin tone +1F3CA 1F3FF ; fully-qualified # 🏊🏿 E1.0 person swimming: dark skin tone +1F3CA 200D 2642 FE0F ; fully-qualified # 🏊‍♂️ E4.0 man swimming +1F3CA 200D 2642 ; minimally-qualified # 🏊‍♂ E4.0 man swimming +1F3CA 1F3FB 200D 2642 FE0F ; fully-qualified # 🏊🏻‍♂️ E4.0 man swimming: light skin tone +1F3CA 1F3FB 200D 2642 ; minimally-qualified # 🏊🏻‍♂ E4.0 man swimming: light skin tone +1F3CA 1F3FC 200D 2642 FE0F ; fully-qualified # 🏊🏼‍♂️ E4.0 man swimming: medium-light skin tone +1F3CA 1F3FC 200D 2642 ; minimally-qualified # 🏊🏼‍♂ E4.0 man swimming: medium-light skin tone +1F3CA 1F3FD 200D 2642 FE0F ; fully-qualified # 🏊🏽‍♂️ E4.0 man swimming: medium skin tone +1F3CA 1F3FD 200D 2642 ; minimally-qualified # 🏊🏽‍♂ E4.0 man swimming: medium skin tone +1F3CA 1F3FE 200D 2642 FE0F ; fully-qualified # 🏊🏾‍♂️ E4.0 man swimming: medium-dark skin tone +1F3CA 1F3FE 200D 2642 ; minimally-qualified # 🏊🏾‍♂ E4.0 man swimming: medium-dark skin tone +1F3CA 1F3FF 200D 2642 FE0F ; fully-qualified # 🏊🏿‍♂️ E4.0 man swimming: dark skin tone +1F3CA 1F3FF 200D 2642 ; minimally-qualified # 🏊🏿‍♂ E4.0 man swimming: dark skin tone +1F3CA 200D 2640 FE0F ; fully-qualified # 🏊‍♀️ E4.0 woman swimming +1F3CA 200D 2640 ; minimally-qualified # 🏊‍♀ E4.0 woman swimming +1F3CA 1F3FB 200D 2640 FE0F ; fully-qualified # 🏊🏻‍♀️ E4.0 woman swimming: light skin tone +1F3CA 1F3FB 200D 2640 ; minimally-qualified # 🏊🏻‍♀ E4.0 woman swimming: light skin tone +1F3CA 1F3FC 200D 2640 FE0F ; fully-qualified # 🏊🏼‍♀️ E4.0 woman swimming: medium-light skin tone +1F3CA 1F3FC 200D 2640 ; minimally-qualified # 🏊🏼‍♀ E4.0 woman swimming: medium-light skin tone +1F3CA 1F3FD 200D 2640 FE0F ; fully-qualified # 🏊🏽‍♀️ E4.0 woman swimming: medium skin tone +1F3CA 1F3FD 200D 2640 ; minimally-qualified # 🏊🏽‍♀ E4.0 woman swimming: medium skin tone +1F3CA 1F3FE 200D 2640 FE0F ; fully-qualified # 🏊🏾‍♀️ E4.0 woman swimming: medium-dark skin tone +1F3CA 1F3FE 200D 2640 ; minimally-qualified # 🏊🏾‍♀ E4.0 woman swimming: medium-dark skin tone +1F3CA 1F3FF 200D 2640 FE0F ; fully-qualified # 🏊🏿‍♀️ E4.0 woman swimming: dark skin tone +1F3CA 1F3FF 200D 2640 ; minimally-qualified # 🏊🏿‍♀ E4.0 woman swimming: dark skin tone +26F9 FE0F ; fully-qualified # ⛹️ E0.7 person bouncing ball +26F9 ; unqualified # ⛹ E0.7 person bouncing ball +26F9 1F3FB ; fully-qualified # ⛹🏻 E2.0 person bouncing ball: light skin tone +26F9 1F3FC ; fully-qualified # ⛹🏼 E2.0 person bouncing ball: medium-light skin tone +26F9 1F3FD ; fully-qualified # ⛹🏽 E2.0 person bouncing ball: medium skin tone +26F9 1F3FE ; fully-qualified # ⛹🏾 E2.0 person bouncing ball: medium-dark skin tone +26F9 1F3FF ; fully-qualified # ⛹🏿 E2.0 person bouncing ball: dark skin tone +26F9 FE0F 200D 2642 FE0F ; fully-qualified # ⛹️‍♂️ E4.0 man bouncing ball +26F9 200D 2642 FE0F ; unqualified # ⛹‍♂️ E4.0 man bouncing ball +26F9 FE0F 200D 2642 ; minimally-qualified # ⛹️‍♂ E4.0 man bouncing ball +26F9 200D 2642 ; unqualified # ⛹‍♂ E4.0 man bouncing ball +26F9 1F3FB 200D 2642 FE0F ; fully-qualified # ⛹🏻‍♂️ E4.0 man bouncing ball: light skin tone +26F9 1F3FB 200D 2642 ; minimally-qualified # ⛹🏻‍♂ E4.0 man bouncing ball: light skin tone +26F9 1F3FC 200D 2642 FE0F ; fully-qualified # ⛹🏼‍♂️ E4.0 man bouncing ball: medium-light skin tone +26F9 1F3FC 200D 2642 ; minimally-qualified # ⛹🏼‍♂ E4.0 man bouncing ball: medium-light skin tone +26F9 1F3FD 200D 2642 FE0F ; fully-qualified # ⛹🏽‍♂️ E4.0 man bouncing ball: medium skin tone +26F9 1F3FD 200D 2642 ; minimally-qualified # ⛹🏽‍♂ E4.0 man bouncing ball: medium skin tone +26F9 1F3FE 200D 2642 FE0F ; fully-qualified # ⛹🏾‍♂️ E4.0 man bouncing ball: medium-dark skin tone +26F9 1F3FE 200D 2642 ; minimally-qualified # ⛹🏾‍♂ E4.0 man bouncing ball: medium-dark skin tone +26F9 1F3FF 200D 2642 FE0F ; fully-qualified # ⛹🏿‍♂️ E4.0 man bouncing ball: dark skin tone +26F9 1F3FF 200D 2642 ; minimally-qualified # ⛹🏿‍♂ E4.0 man bouncing ball: dark skin tone +26F9 FE0F 200D 2640 FE0F ; fully-qualified # ⛹️‍♀️ E4.0 woman bouncing ball +26F9 200D 2640 FE0F ; unqualified # ⛹‍♀️ E4.0 woman bouncing ball +26F9 FE0F 200D 2640 ; minimally-qualified # ⛹️‍♀ E4.0 woman bouncing ball +26F9 200D 2640 ; unqualified # ⛹‍♀ E4.0 woman bouncing ball +26F9 1F3FB 200D 2640 FE0F ; fully-qualified # ⛹🏻‍♀️ E4.0 woman bouncing ball: light skin tone +26F9 1F3FB 200D 2640 ; minimally-qualified # ⛹🏻‍♀ E4.0 woman bouncing ball: light skin tone +26F9 1F3FC 200D 2640 FE0F ; fully-qualified # ⛹🏼‍♀️ E4.0 woman bouncing ball: medium-light skin tone +26F9 1F3FC 200D 2640 ; minimally-qualified # ⛹🏼‍♀ E4.0 woman bouncing ball: medium-light skin tone +26F9 1F3FD 200D 2640 FE0F ; fully-qualified # ⛹🏽‍♀️ E4.0 woman bouncing ball: medium skin tone +26F9 1F3FD 200D 2640 ; minimally-qualified # ⛹🏽‍♀ E4.0 woman bouncing ball: medium skin tone +26F9 1F3FE 200D 2640 FE0F ; fully-qualified # ⛹🏾‍♀️ E4.0 woman bouncing ball: medium-dark skin tone +26F9 1F3FE 200D 2640 ; minimally-qualified # ⛹🏾‍♀ E4.0 woman bouncing ball: medium-dark skin tone +26F9 1F3FF 200D 2640 FE0F ; fully-qualified # ⛹🏿‍♀️ E4.0 woman bouncing ball: dark skin tone +26F9 1F3FF 200D 2640 ; minimally-qualified # ⛹🏿‍♀ E4.0 woman bouncing ball: dark skin tone +1F3CB FE0F ; fully-qualified # 🏋️ E0.7 person lifting weights +1F3CB ; unqualified # 🏋 E0.7 person lifting weights +1F3CB 1F3FB ; fully-qualified # 🏋🏻 E2.0 person lifting weights: light skin tone +1F3CB 1F3FC ; fully-qualified # 🏋🏼 E2.0 person lifting weights: medium-light skin tone +1F3CB 1F3FD ; fully-qualified # 🏋🏽 E2.0 person lifting weights: medium skin tone +1F3CB 1F3FE ; fully-qualified # 🏋🏾 E2.0 person lifting weights: medium-dark skin tone +1F3CB 1F3FF ; fully-qualified # 🏋🏿 E2.0 person lifting weights: dark skin tone +1F3CB FE0F 200D 2642 FE0F ; fully-qualified # 🏋️‍♂️ E4.0 man lifting weights +1F3CB 200D 2642 FE0F ; unqualified # 🏋‍♂️ E4.0 man lifting weights +1F3CB FE0F 200D 2642 ; minimally-qualified # 🏋️‍♂ E4.0 man lifting weights +1F3CB 200D 2642 ; unqualified # 🏋‍♂ E4.0 man lifting weights +1F3CB 1F3FB 200D 2642 FE0F ; fully-qualified # 🏋🏻‍♂️ E4.0 man lifting weights: light skin tone +1F3CB 1F3FB 200D 2642 ; minimally-qualified # 🏋🏻‍♂ E4.0 man lifting weights: light skin tone +1F3CB 1F3FC 200D 2642 FE0F ; fully-qualified # 🏋🏼‍♂️ E4.0 man lifting weights: medium-light skin tone +1F3CB 1F3FC 200D 2642 ; minimally-qualified # 🏋🏼‍♂ E4.0 man lifting weights: medium-light skin tone +1F3CB 1F3FD 200D 2642 FE0F ; fully-qualified # 🏋🏽‍♂️ E4.0 man lifting weights: medium skin tone +1F3CB 1F3FD 200D 2642 ; minimally-qualified # 🏋🏽‍♂ E4.0 man lifting weights: medium skin tone +1F3CB 1F3FE 200D 2642 FE0F ; fully-qualified # 🏋🏾‍♂️ E4.0 man lifting weights: medium-dark skin tone +1F3CB 1F3FE 200D 2642 ; minimally-qualified # 🏋🏾‍♂ E4.0 man lifting weights: medium-dark skin tone +1F3CB 1F3FF 200D 2642 FE0F ; fully-qualified # 🏋🏿‍♂️ E4.0 man lifting weights: dark skin tone +1F3CB 1F3FF 200D 2642 ; minimally-qualified # 🏋🏿‍♂ E4.0 man lifting weights: dark skin tone +1F3CB FE0F 200D 2640 FE0F ; fully-qualified # 🏋️‍♀️ E4.0 woman lifting weights +1F3CB 200D 2640 FE0F ; unqualified # 🏋‍♀️ E4.0 woman lifting weights +1F3CB FE0F 200D 2640 ; minimally-qualified # 🏋️‍♀ E4.0 woman lifting weights +1F3CB 200D 2640 ; unqualified # 🏋‍♀ E4.0 woman lifting weights +1F3CB 1F3FB 200D 2640 FE0F ; fully-qualified # 🏋🏻‍♀️ E4.0 woman lifting weights: light skin tone +1F3CB 1F3FB 200D 2640 ; minimally-qualified # 🏋🏻‍♀ E4.0 woman lifting weights: light skin tone +1F3CB 1F3FC 200D 2640 FE0F ; fully-qualified # 🏋🏼‍♀️ E4.0 woman lifting weights: medium-light skin tone +1F3CB 1F3FC 200D 2640 ; minimally-qualified # 🏋🏼‍♀ E4.0 woman lifting weights: medium-light skin tone +1F3CB 1F3FD 200D 2640 FE0F ; fully-qualified # 🏋🏽‍♀️ E4.0 woman lifting weights: medium skin tone +1F3CB 1F3FD 200D 2640 ; minimally-qualified # 🏋🏽‍♀ E4.0 woman lifting weights: medium skin tone +1F3CB 1F3FE 200D 2640 FE0F ; fully-qualified # 🏋🏾‍♀️ E4.0 woman lifting weights: medium-dark skin tone +1F3CB 1F3FE 200D 2640 ; minimally-qualified # 🏋🏾‍♀ E4.0 woman lifting weights: medium-dark skin tone +1F3CB 1F3FF 200D 2640 FE0F ; fully-qualified # 🏋🏿‍♀️ E4.0 woman lifting weights: dark skin tone +1F3CB 1F3FF 200D 2640 ; minimally-qualified # 🏋🏿‍♀ E4.0 woman lifting weights: dark skin tone +1F6B4 ; fully-qualified # 🚴 E1.0 person biking +1F6B4 1F3FB ; fully-qualified # 🚴🏻 E1.0 person biking: light skin tone +1F6B4 1F3FC ; fully-qualified # 🚴🏼 E1.0 person biking: medium-light skin tone +1F6B4 1F3FD ; fully-qualified # 🚴🏽 E1.0 person biking: medium skin tone +1F6B4 1F3FE ; fully-qualified # 🚴🏾 E1.0 person biking: medium-dark skin tone +1F6B4 1F3FF ; fully-qualified # 🚴🏿 E1.0 person biking: dark skin tone +1F6B4 200D 2642 FE0F ; fully-qualified # 🚴‍♂️ E4.0 man biking +1F6B4 200D 2642 ; minimally-qualified # 🚴‍♂ E4.0 man biking +1F6B4 1F3FB 200D 2642 FE0F ; fully-qualified # 🚴🏻‍♂️ E4.0 man biking: light skin tone +1F6B4 1F3FB 200D 2642 ; minimally-qualified # 🚴🏻‍♂ E4.0 man biking: light skin tone +1F6B4 1F3FC 200D 2642 FE0F ; fully-qualified # 🚴🏼‍♂️ E4.0 man biking: medium-light skin tone +1F6B4 1F3FC 200D 2642 ; minimally-qualified # 🚴🏼‍♂ E4.0 man biking: medium-light skin tone +1F6B4 1F3FD 200D 2642 FE0F ; fully-qualified # 🚴🏽‍♂️ E4.0 man biking: medium skin tone +1F6B4 1F3FD 200D 2642 ; minimally-qualified # 🚴🏽‍♂ E4.0 man biking: medium skin tone +1F6B4 1F3FE 200D 2642 FE0F ; fully-qualified # 🚴🏾‍♂️ E4.0 man biking: medium-dark skin tone +1F6B4 1F3FE 200D 2642 ; minimally-qualified # 🚴🏾‍♂ E4.0 man biking: medium-dark skin tone +1F6B4 1F3FF 200D 2642 FE0F ; fully-qualified # 🚴🏿‍♂️ E4.0 man biking: dark skin tone +1F6B4 1F3FF 200D 2642 ; minimally-qualified # 🚴🏿‍♂ E4.0 man biking: dark skin tone +1F6B4 200D 2640 FE0F ; fully-qualified # 🚴‍♀️ E4.0 woman biking +1F6B4 200D 2640 ; minimally-qualified # 🚴‍♀ E4.0 woman biking +1F6B4 1F3FB 200D 2640 FE0F ; fully-qualified # 🚴🏻‍♀️ E4.0 woman biking: light skin tone +1F6B4 1F3FB 200D 2640 ; minimally-qualified # 🚴🏻‍♀ E4.0 woman biking: light skin tone +1F6B4 1F3FC 200D 2640 FE0F ; fully-qualified # 🚴🏼‍♀️ E4.0 woman biking: medium-light skin tone +1F6B4 1F3FC 200D 2640 ; minimally-qualified # 🚴🏼‍♀ E4.0 woman biking: medium-light skin tone +1F6B4 1F3FD 200D 2640 FE0F ; fully-qualified # 🚴🏽‍♀️ E4.0 woman biking: medium skin tone +1F6B4 1F3FD 200D 2640 ; minimally-qualified # 🚴🏽‍♀ E4.0 woman biking: medium skin tone +1F6B4 1F3FE 200D 2640 FE0F ; fully-qualified # 🚴🏾‍♀️ E4.0 woman biking: medium-dark skin tone +1F6B4 1F3FE 200D 2640 ; minimally-qualified # 🚴🏾‍♀ E4.0 woman biking: medium-dark skin tone +1F6B4 1F3FF 200D 2640 FE0F ; fully-qualified # 🚴🏿‍♀️ E4.0 woman biking: dark skin tone +1F6B4 1F3FF 200D 2640 ; minimally-qualified # 🚴🏿‍♀ E4.0 woman biking: dark skin tone +1F6B5 ; fully-qualified # 🚵 E1.0 person mountain biking +1F6B5 1F3FB ; fully-qualified # 🚵🏻 E1.0 person mountain biking: light skin tone +1F6B5 1F3FC ; fully-qualified # 🚵🏼 E1.0 person mountain biking: medium-light skin tone +1F6B5 1F3FD ; fully-qualified # 🚵🏽 E1.0 person mountain biking: medium skin tone +1F6B5 1F3FE ; fully-qualified # 🚵🏾 E1.0 person mountain biking: medium-dark skin tone +1F6B5 1F3FF ; fully-qualified # 🚵🏿 E1.0 person mountain biking: dark skin tone +1F6B5 200D 2642 FE0F ; fully-qualified # 🚵‍♂️ E4.0 man mountain biking +1F6B5 200D 2642 ; minimally-qualified # 🚵‍♂ E4.0 man mountain biking +1F6B5 1F3FB 200D 2642 FE0F ; fully-qualified # 🚵🏻‍♂️ E4.0 man mountain biking: light skin tone +1F6B5 1F3FB 200D 2642 ; minimally-qualified # 🚵🏻‍♂ E4.0 man mountain biking: light skin tone +1F6B5 1F3FC 200D 2642 FE0F ; fully-qualified # 🚵🏼‍♂️ E4.0 man mountain biking: medium-light skin tone +1F6B5 1F3FC 200D 2642 ; minimally-qualified # 🚵🏼‍♂ E4.0 man mountain biking: medium-light skin tone +1F6B5 1F3FD 200D 2642 FE0F ; fully-qualified # 🚵🏽‍♂️ E4.0 man mountain biking: medium skin tone +1F6B5 1F3FD 200D 2642 ; minimally-qualified # 🚵🏽‍♂ E4.0 man mountain biking: medium skin tone +1F6B5 1F3FE 200D 2642 FE0F ; fully-qualified # 🚵🏾‍♂️ E4.0 man mountain biking: medium-dark skin tone +1F6B5 1F3FE 200D 2642 ; minimally-qualified # 🚵🏾‍♂ E4.0 man mountain biking: medium-dark skin tone +1F6B5 1F3FF 200D 2642 FE0F ; fully-qualified # 🚵🏿‍♂️ E4.0 man mountain biking: dark skin tone +1F6B5 1F3FF 200D 2642 ; minimally-qualified # 🚵🏿‍♂ E4.0 man mountain biking: dark skin tone +1F6B5 200D 2640 FE0F ; fully-qualified # 🚵‍♀️ E4.0 woman mountain biking +1F6B5 200D 2640 ; minimally-qualified # 🚵‍♀ E4.0 woman mountain biking +1F6B5 1F3FB 200D 2640 FE0F ; fully-qualified # 🚵🏻‍♀️ E4.0 woman mountain biking: light skin tone +1F6B5 1F3FB 200D 2640 ; minimally-qualified # 🚵🏻‍♀ E4.0 woman mountain biking: light skin tone +1F6B5 1F3FC 200D 2640 FE0F ; fully-qualified # 🚵🏼‍♀️ E4.0 woman mountain biking: medium-light skin tone +1F6B5 1F3FC 200D 2640 ; minimally-qualified # 🚵🏼‍♀ E4.0 woman mountain biking: medium-light skin tone +1F6B5 1F3FD 200D 2640 FE0F ; fully-qualified # 🚵🏽‍♀️ E4.0 woman mountain biking: medium skin tone +1F6B5 1F3FD 200D 2640 ; minimally-qualified # 🚵🏽‍♀ E4.0 woman mountain biking: medium skin tone +1F6B5 1F3FE 200D 2640 FE0F ; fully-qualified # 🚵🏾‍♀️ E4.0 woman mountain biking: medium-dark skin tone +1F6B5 1F3FE 200D 2640 ; minimally-qualified # 🚵🏾‍♀ E4.0 woman mountain biking: medium-dark skin tone +1F6B5 1F3FF 200D 2640 FE0F ; fully-qualified # 🚵🏿‍♀️ E4.0 woman mountain biking: dark skin tone +1F6B5 1F3FF 200D 2640 ; minimally-qualified # 🚵🏿‍♀ E4.0 woman mountain biking: dark skin tone +1F938 ; fully-qualified # 🤸 E3.0 person cartwheeling +1F938 1F3FB ; fully-qualified # 🤸🏻 E3.0 person cartwheeling: light skin tone +1F938 1F3FC ; fully-qualified # 🤸🏼 E3.0 person cartwheeling: medium-light skin tone +1F938 1F3FD ; fully-qualified # 🤸🏽 E3.0 person cartwheeling: medium skin tone +1F938 1F3FE ; fully-qualified # 🤸🏾 E3.0 person cartwheeling: medium-dark skin tone +1F938 1F3FF ; fully-qualified # 🤸🏿 E3.0 person cartwheeling: dark skin tone +1F938 200D 2642 FE0F ; fully-qualified # 🤸‍♂️ E4.0 man cartwheeling +1F938 200D 2642 ; minimally-qualified # 🤸‍♂ E4.0 man cartwheeling +1F938 1F3FB 200D 2642 FE0F ; fully-qualified # 🤸🏻‍♂️ E4.0 man cartwheeling: light skin tone +1F938 1F3FB 200D 2642 ; minimally-qualified # 🤸🏻‍♂ E4.0 man cartwheeling: light skin tone +1F938 1F3FC 200D 2642 FE0F ; fully-qualified # 🤸🏼‍♂️ E4.0 man cartwheeling: medium-light skin tone +1F938 1F3FC 200D 2642 ; minimally-qualified # 🤸🏼‍♂ E4.0 man cartwheeling: medium-light skin tone +1F938 1F3FD 200D 2642 FE0F ; fully-qualified # 🤸🏽‍♂️ E4.0 man cartwheeling: medium skin tone +1F938 1F3FD 200D 2642 ; minimally-qualified # 🤸🏽‍♂ E4.0 man cartwheeling: medium skin tone +1F938 1F3FE 200D 2642 FE0F ; fully-qualified # 🤸🏾‍♂️ E4.0 man cartwheeling: medium-dark skin tone +1F938 1F3FE 200D 2642 ; minimally-qualified # 🤸🏾‍♂ E4.0 man cartwheeling: medium-dark skin tone +1F938 1F3FF 200D 2642 FE0F ; fully-qualified # 🤸🏿‍♂️ E4.0 man cartwheeling: dark skin tone +1F938 1F3FF 200D 2642 ; minimally-qualified # 🤸🏿‍♂ E4.0 man cartwheeling: dark skin tone +1F938 200D 2640 FE0F ; fully-qualified # 🤸‍♀️ E4.0 woman cartwheeling +1F938 200D 2640 ; minimally-qualified # 🤸‍♀ E4.0 woman cartwheeling +1F938 1F3FB 200D 2640 FE0F ; fully-qualified # 🤸🏻‍♀️ E4.0 woman cartwheeling: light skin tone +1F938 1F3FB 200D 2640 ; minimally-qualified # 🤸🏻‍♀ E4.0 woman cartwheeling: light skin tone +1F938 1F3FC 200D 2640 FE0F ; fully-qualified # 🤸🏼‍♀️ E4.0 woman cartwheeling: medium-light skin tone +1F938 1F3FC 200D 2640 ; minimally-qualified # 🤸🏼‍♀ E4.0 woman cartwheeling: medium-light skin tone +1F938 1F3FD 200D 2640 FE0F ; fully-qualified # 🤸🏽‍♀️ E4.0 woman cartwheeling: medium skin tone +1F938 1F3FD 200D 2640 ; minimally-qualified # 🤸🏽‍♀ E4.0 woman cartwheeling: medium skin tone +1F938 1F3FE 200D 2640 FE0F ; fully-qualified # 🤸🏾‍♀️ E4.0 woman cartwheeling: medium-dark skin tone +1F938 1F3FE 200D 2640 ; minimally-qualified # 🤸🏾‍♀ E4.0 woman cartwheeling: medium-dark skin tone +1F938 1F3FF 200D 2640 FE0F ; fully-qualified # 🤸🏿‍♀️ E4.0 woman cartwheeling: dark skin tone +1F938 1F3FF 200D 2640 ; minimally-qualified # 🤸🏿‍♀ E4.0 woman cartwheeling: dark skin tone +1F93C ; fully-qualified # 🤼 E3.0 people wrestling +1F93C 200D 2642 FE0F ; fully-qualified # 🤼‍♂️ E4.0 men wrestling +1F93C 200D 2642 ; minimally-qualified # 🤼‍♂ E4.0 men wrestling +1F93C 200D 2640 FE0F ; fully-qualified # 🤼‍♀️ E4.0 women wrestling +1F93C 200D 2640 ; minimally-qualified # 🤼‍♀ E4.0 women wrestling +1F93D ; fully-qualified # 🤽 E3.0 person playing water polo +1F93D 1F3FB ; fully-qualified # 🤽🏻 E3.0 person playing water polo: light skin tone +1F93D 1F3FC ; fully-qualified # 🤽🏼 E3.0 person playing water polo: medium-light skin tone +1F93D 1F3FD ; fully-qualified # 🤽🏽 E3.0 person playing water polo: medium skin tone +1F93D 1F3FE ; fully-qualified # 🤽🏾 E3.0 person playing water polo: medium-dark skin tone +1F93D 1F3FF ; fully-qualified # 🤽🏿 E3.0 person playing water polo: dark skin tone +1F93D 200D 2642 FE0F ; fully-qualified # 🤽‍♂️ E4.0 man playing water polo +1F93D 200D 2642 ; minimally-qualified # 🤽‍♂ E4.0 man playing water polo +1F93D 1F3FB 200D 2642 FE0F ; fully-qualified # 🤽🏻‍♂️ E4.0 man playing water polo: light skin tone +1F93D 1F3FB 200D 2642 ; minimally-qualified # 🤽🏻‍♂ E4.0 man playing water polo: light skin tone +1F93D 1F3FC 200D 2642 FE0F ; fully-qualified # 🤽🏼‍♂️ E4.0 man playing water polo: medium-light skin tone +1F93D 1F3FC 200D 2642 ; minimally-qualified # 🤽🏼‍♂ E4.0 man playing water polo: medium-light skin tone +1F93D 1F3FD 200D 2642 FE0F ; fully-qualified # 🤽🏽‍♂️ E4.0 man playing water polo: medium skin tone +1F93D 1F3FD 200D 2642 ; minimally-qualified # 🤽🏽‍♂ E4.0 man playing water polo: medium skin tone +1F93D 1F3FE 200D 2642 FE0F ; fully-qualified # 🤽🏾‍♂️ E4.0 man playing water polo: medium-dark skin tone +1F93D 1F3FE 200D 2642 ; minimally-qualified # 🤽🏾‍♂ E4.0 man playing water polo: medium-dark skin tone +1F93D 1F3FF 200D 2642 FE0F ; fully-qualified # 🤽🏿‍♂️ E4.0 man playing water polo: dark skin tone +1F93D 1F3FF 200D 2642 ; minimally-qualified # 🤽🏿‍♂ E4.0 man playing water polo: dark skin tone +1F93D 200D 2640 FE0F ; fully-qualified # 🤽‍♀️ E4.0 woman playing water polo +1F93D 200D 2640 ; minimally-qualified # 🤽‍♀ E4.0 woman playing water polo +1F93D 1F3FB 200D 2640 FE0F ; fully-qualified # 🤽🏻‍♀️ E4.0 woman playing water polo: light skin tone +1F93D 1F3FB 200D 2640 ; minimally-qualified # 🤽🏻‍♀ E4.0 woman playing water polo: light skin tone +1F93D 1F3FC 200D 2640 FE0F ; fully-qualified # 🤽🏼‍♀️ E4.0 woman playing water polo: medium-light skin tone +1F93D 1F3FC 200D 2640 ; minimally-qualified # 🤽🏼‍♀ E4.0 woman playing water polo: medium-light skin tone +1F93D 1F3FD 200D 2640 FE0F ; fully-qualified # 🤽🏽‍♀️ E4.0 woman playing water polo: medium skin tone +1F93D 1F3FD 200D 2640 ; minimally-qualified # 🤽🏽‍♀ E4.0 woman playing water polo: medium skin tone +1F93D 1F3FE 200D 2640 FE0F ; fully-qualified # 🤽🏾‍♀️ E4.0 woman playing water polo: medium-dark skin tone +1F93D 1F3FE 200D 2640 ; minimally-qualified # 🤽🏾‍♀ E4.0 woman playing water polo: medium-dark skin tone +1F93D 1F3FF 200D 2640 FE0F ; fully-qualified # 🤽🏿‍♀️ E4.0 woman playing water polo: dark skin tone +1F93D 1F3FF 200D 2640 ; minimally-qualified # 🤽🏿‍♀ E4.0 woman playing water polo: dark skin tone +1F93E ; fully-qualified # 🤾 E3.0 person playing handball +1F93E 1F3FB ; fully-qualified # 🤾🏻 E3.0 person playing handball: light skin tone +1F93E 1F3FC ; fully-qualified # 🤾🏼 E3.0 person playing handball: medium-light skin tone +1F93E 1F3FD ; fully-qualified # 🤾🏽 E3.0 person playing handball: medium skin tone +1F93E 1F3FE ; fully-qualified # 🤾🏾 E3.0 person playing handball: medium-dark skin tone +1F93E 1F3FF ; fully-qualified # 🤾🏿 E3.0 person playing handball: dark skin tone +1F93E 200D 2642 FE0F ; fully-qualified # 🤾‍♂️ E4.0 man playing handball +1F93E 200D 2642 ; minimally-qualified # 🤾‍♂ E4.0 man playing handball +1F93E 1F3FB 200D 2642 FE0F ; fully-qualified # 🤾🏻‍♂️ E4.0 man playing handball: light skin tone +1F93E 1F3FB 200D 2642 ; minimally-qualified # 🤾🏻‍♂ E4.0 man playing handball: light skin tone +1F93E 1F3FC 200D 2642 FE0F ; fully-qualified # 🤾🏼‍♂️ E4.0 man playing handball: medium-light skin tone +1F93E 1F3FC 200D 2642 ; minimally-qualified # 🤾🏼‍♂ E4.0 man playing handball: medium-light skin tone +1F93E 1F3FD 200D 2642 FE0F ; fully-qualified # 🤾🏽‍♂️ E4.0 man playing handball: medium skin tone +1F93E 1F3FD 200D 2642 ; minimally-qualified # 🤾🏽‍♂ E4.0 man playing handball: medium skin tone +1F93E 1F3FE 200D 2642 FE0F ; fully-qualified # 🤾🏾‍♂️ E4.0 man playing handball: medium-dark skin tone +1F93E 1F3FE 200D 2642 ; minimally-qualified # 🤾🏾‍♂ E4.0 man playing handball: medium-dark skin tone +1F93E 1F3FF 200D 2642 FE0F ; fully-qualified # 🤾🏿‍♂️ E4.0 man playing handball: dark skin tone +1F93E 1F3FF 200D 2642 ; minimally-qualified # 🤾🏿‍♂ E4.0 man playing handball: dark skin tone +1F93E 200D 2640 FE0F ; fully-qualified # 🤾‍♀️ E4.0 woman playing handball +1F93E 200D 2640 ; minimally-qualified # 🤾‍♀ E4.0 woman playing handball +1F93E 1F3FB 200D 2640 FE0F ; fully-qualified # 🤾🏻‍♀️ E4.0 woman playing handball: light skin tone +1F93E 1F3FB 200D 2640 ; minimally-qualified # 🤾🏻‍♀ E4.0 woman playing handball: light skin tone +1F93E 1F3FC 200D 2640 FE0F ; fully-qualified # 🤾🏼‍♀️ E4.0 woman playing handball: medium-light skin tone +1F93E 1F3FC 200D 2640 ; minimally-qualified # 🤾🏼‍♀ E4.0 woman playing handball: medium-light skin tone +1F93E 1F3FD 200D 2640 FE0F ; fully-qualified # 🤾🏽‍♀️ E4.0 woman playing handball: medium skin tone +1F93E 1F3FD 200D 2640 ; minimally-qualified # 🤾🏽‍♀ E4.0 woman playing handball: medium skin tone +1F93E 1F3FE 200D 2640 FE0F ; fully-qualified # 🤾🏾‍♀️ E4.0 woman playing handball: medium-dark skin tone +1F93E 1F3FE 200D 2640 ; minimally-qualified # 🤾🏾‍♀ E4.0 woman playing handball: medium-dark skin tone +1F93E 1F3FF 200D 2640 FE0F ; fully-qualified # 🤾🏿‍♀️ E4.0 woman playing handball: dark skin tone +1F93E 1F3FF 200D 2640 ; minimally-qualified # 🤾🏿‍♀ E4.0 woman playing handball: dark skin tone +1F939 ; fully-qualified # 🤹 E3.0 person juggling +1F939 1F3FB ; fully-qualified # 🤹🏻 E3.0 person juggling: light skin tone +1F939 1F3FC ; fully-qualified # 🤹🏼 E3.0 person juggling: medium-light skin tone +1F939 1F3FD ; fully-qualified # 🤹🏽 E3.0 person juggling: medium skin tone +1F939 1F3FE ; fully-qualified # 🤹🏾 E3.0 person juggling: medium-dark skin tone +1F939 1F3FF ; fully-qualified # 🤹🏿 E3.0 person juggling: dark skin tone +1F939 200D 2642 FE0F ; fully-qualified # 🤹‍♂️ E4.0 man juggling +1F939 200D 2642 ; minimally-qualified # 🤹‍♂ E4.0 man juggling +1F939 1F3FB 200D 2642 FE0F ; fully-qualified # 🤹🏻‍♂️ E4.0 man juggling: light skin tone +1F939 1F3FB 200D 2642 ; minimally-qualified # 🤹🏻‍♂ E4.0 man juggling: light skin tone +1F939 1F3FC 200D 2642 FE0F ; fully-qualified # 🤹🏼‍♂️ E4.0 man juggling: medium-light skin tone +1F939 1F3FC 200D 2642 ; minimally-qualified # 🤹🏼‍♂ E4.0 man juggling: medium-light skin tone +1F939 1F3FD 200D 2642 FE0F ; fully-qualified # 🤹🏽‍♂️ E4.0 man juggling: medium skin tone +1F939 1F3FD 200D 2642 ; minimally-qualified # 🤹🏽‍♂ E4.0 man juggling: medium skin tone +1F939 1F3FE 200D 2642 FE0F ; fully-qualified # 🤹🏾‍♂️ E4.0 man juggling: medium-dark skin tone +1F939 1F3FE 200D 2642 ; minimally-qualified # 🤹🏾‍♂ E4.0 man juggling: medium-dark skin tone +1F939 1F3FF 200D 2642 FE0F ; fully-qualified # 🤹🏿‍♂️ E4.0 man juggling: dark skin tone +1F939 1F3FF 200D 2642 ; minimally-qualified # 🤹🏿‍♂ E4.0 man juggling: dark skin tone +1F939 200D 2640 FE0F ; fully-qualified # 🤹‍♀️ E4.0 woman juggling +1F939 200D 2640 ; minimally-qualified # 🤹‍♀ E4.0 woman juggling +1F939 1F3FB 200D 2640 FE0F ; fully-qualified # 🤹🏻‍♀️ E4.0 woman juggling: light skin tone +1F939 1F3FB 200D 2640 ; minimally-qualified # 🤹🏻‍♀ E4.0 woman juggling: light skin tone +1F939 1F3FC 200D 2640 FE0F ; fully-qualified # 🤹🏼‍♀️ E4.0 woman juggling: medium-light skin tone +1F939 1F3FC 200D 2640 ; minimally-qualified # 🤹🏼‍♀ E4.0 woman juggling: medium-light skin tone +1F939 1F3FD 200D 2640 FE0F ; fully-qualified # 🤹🏽‍♀️ E4.0 woman juggling: medium skin tone +1F939 1F3FD 200D 2640 ; minimally-qualified # 🤹🏽‍♀ E4.0 woman juggling: medium skin tone +1F939 1F3FE 200D 2640 FE0F ; fully-qualified # 🤹🏾‍♀️ E4.0 woman juggling: medium-dark skin tone +1F939 1F3FE 200D 2640 ; minimally-qualified # 🤹🏾‍♀ E4.0 woman juggling: medium-dark skin tone +1F939 1F3FF 200D 2640 FE0F ; fully-qualified # 🤹🏿‍♀️ E4.0 woman juggling: dark skin tone +1F939 1F3FF 200D 2640 ; minimally-qualified # 🤹🏿‍♀ E4.0 woman juggling: dark skin tone + +# subgroup: person-resting +1F9D8 ; fully-qualified # 🧘 E5.0 person in lotus position +1F9D8 1F3FB ; fully-qualified # 🧘🏻 E5.0 person in lotus position: light skin tone +1F9D8 1F3FC ; fully-qualified # 🧘🏼 E5.0 person in lotus position: medium-light skin tone +1F9D8 1F3FD ; fully-qualified # 🧘🏽 E5.0 person in lotus position: medium skin tone +1F9D8 1F3FE ; fully-qualified # 🧘🏾 E5.0 person in lotus position: medium-dark skin tone +1F9D8 1F3FF ; fully-qualified # 🧘🏿 E5.0 person in lotus position: dark skin tone +1F9D8 200D 2642 FE0F ; fully-qualified # 🧘‍♂️ E5.0 man in lotus position +1F9D8 200D 2642 ; minimally-qualified # 🧘‍♂ E5.0 man in lotus position +1F9D8 1F3FB 200D 2642 FE0F ; fully-qualified # 🧘🏻‍♂️ E5.0 man in lotus position: light skin tone +1F9D8 1F3FB 200D 2642 ; minimally-qualified # 🧘🏻‍♂ E5.0 man in lotus position: light skin tone +1F9D8 1F3FC 200D 2642 FE0F ; fully-qualified # 🧘🏼‍♂️ E5.0 man in lotus position: medium-light skin tone +1F9D8 1F3FC 200D 2642 ; minimally-qualified # 🧘🏼‍♂ E5.0 man in lotus position: medium-light skin tone +1F9D8 1F3FD 200D 2642 FE0F ; fully-qualified # 🧘🏽‍♂️ E5.0 man in lotus position: medium skin tone +1F9D8 1F3FD 200D 2642 ; minimally-qualified # 🧘🏽‍♂ E5.0 man in lotus position: medium skin tone +1F9D8 1F3FE 200D 2642 FE0F ; fully-qualified # 🧘🏾‍♂️ E5.0 man in lotus position: medium-dark skin tone +1F9D8 1F3FE 200D 2642 ; minimally-qualified # 🧘🏾‍♂ E5.0 man in lotus position: medium-dark skin tone +1F9D8 1F3FF 200D 2642 FE0F ; fully-qualified # 🧘🏿‍♂️ E5.0 man in lotus position: dark skin tone +1F9D8 1F3FF 200D 2642 ; minimally-qualified # 🧘🏿‍♂ E5.0 man in lotus position: dark skin tone +1F9D8 200D 2640 FE0F ; fully-qualified # 🧘‍♀️ E5.0 woman in lotus position +1F9D8 200D 2640 ; minimally-qualified # 🧘‍♀ E5.0 woman in lotus position +1F9D8 1F3FB 200D 2640 FE0F ; fully-qualified # 🧘🏻‍♀️ E5.0 woman in lotus position: light skin tone +1F9D8 1F3FB 200D 2640 ; minimally-qualified # 🧘🏻‍♀ E5.0 woman in lotus position: light skin tone +1F9D8 1F3FC 200D 2640 FE0F ; fully-qualified # 🧘🏼‍♀️ E5.0 woman in lotus position: medium-light skin tone +1F9D8 1F3FC 200D 2640 ; minimally-qualified # 🧘🏼‍♀ E5.0 woman in lotus position: medium-light skin tone +1F9D8 1F3FD 200D 2640 FE0F ; fully-qualified # 🧘🏽‍♀️ E5.0 woman in lotus position: medium skin tone +1F9D8 1F3FD 200D 2640 ; minimally-qualified # 🧘🏽‍♀ E5.0 woman in lotus position: medium skin tone +1F9D8 1F3FE 200D 2640 FE0F ; fully-qualified # 🧘🏾‍♀️ E5.0 woman in lotus position: medium-dark skin tone +1F9D8 1F3FE 200D 2640 ; minimally-qualified # 🧘🏾‍♀ E5.0 woman in lotus position: medium-dark skin tone +1F9D8 1F3FF 200D 2640 FE0F ; fully-qualified # 🧘🏿‍♀️ E5.0 woman in lotus position: dark skin tone +1F9D8 1F3FF 200D 2640 ; minimally-qualified # 🧘🏿‍♀ E5.0 woman in lotus position: dark skin tone +1F6C0 ; fully-qualified # 🛀 E0.6 person taking bath +1F6C0 1F3FB ; fully-qualified # 🛀🏻 E1.0 person taking bath: light skin tone +1F6C0 1F3FC ; fully-qualified # 🛀🏼 E1.0 person taking bath: medium-light skin tone +1F6C0 1F3FD ; fully-qualified # 🛀🏽 E1.0 person taking bath: medium skin tone +1F6C0 1F3FE ; fully-qualified # 🛀🏾 E1.0 person taking bath: medium-dark skin tone +1F6C0 1F3FF ; fully-qualified # 🛀🏿 E1.0 person taking bath: dark skin tone +1F6CC ; fully-qualified # 🛌 E1.0 person in bed +1F6CC 1F3FB ; fully-qualified # 🛌🏻 E4.0 person in bed: light skin tone +1F6CC 1F3FC ; fully-qualified # 🛌🏼 E4.0 person in bed: medium-light skin tone +1F6CC 1F3FD ; fully-qualified # 🛌🏽 E4.0 person in bed: medium skin tone +1F6CC 1F3FE ; fully-qualified # 🛌🏾 E4.0 person in bed: medium-dark skin tone +1F6CC 1F3FF ; fully-qualified # 🛌🏿 E4.0 person in bed: dark skin tone + +# subgroup: family +1F9D1 200D 1F91D 200D 1F9D1 ; fully-qualified # 🧑‍🤝‍🧑 E12.0 people holding hands +1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏻‍🤝‍🧑🏻 E12.0 people holding hands: light skin tone +1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏻‍🤝‍🧑🏼 E12.1 people holding hands: light skin tone, medium-light skin tone +1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏻‍🤝‍🧑🏽 E12.1 people holding hands: light skin tone, medium skin tone +1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏻‍🤝‍🧑🏾 E12.1 people holding hands: light skin tone, medium-dark skin tone +1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏻‍🤝‍🧑🏿 E12.1 people holding hands: light skin tone, dark skin tone +1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏼‍🤝‍🧑🏻 E12.0 people holding hands: medium-light skin tone, light skin tone +1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏼‍🤝‍🧑🏼 E12.0 people holding hands: medium-light skin tone +1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏼‍🤝‍🧑🏽 E12.1 people holding hands: medium-light skin tone, medium skin tone +1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏼‍🤝‍🧑🏾 E12.1 people holding hands: medium-light skin tone, medium-dark skin tone +1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏼‍🤝‍🧑🏿 E12.1 people holding hands: medium-light skin tone, dark skin tone +1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏽‍🤝‍🧑🏻 E12.0 people holding hands: medium skin tone, light skin tone +1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏽‍🤝‍🧑🏼 E12.0 people holding hands: medium skin tone, medium-light skin tone +1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏽‍🤝‍🧑🏽 E12.0 people holding hands: medium skin tone +1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏽‍🤝‍🧑🏾 E12.1 people holding hands: medium skin tone, medium-dark skin tone +1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏽‍🤝‍🧑🏿 E12.1 people holding hands: medium skin tone, dark skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏾‍🤝‍🧑🏻 E12.0 people holding hands: medium-dark skin tone, light skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏾‍🤝‍🧑🏼 E12.0 people holding hands: medium-dark skin tone, medium-light skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏾‍🤝‍🧑🏽 E12.0 people holding hands: medium-dark skin tone, medium skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏾‍🤝‍🧑🏾 E12.0 people holding hands: medium-dark skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏾‍🤝‍🧑🏿 E12.1 people holding hands: medium-dark skin tone, dark skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏿‍🤝‍🧑🏻 E12.0 people holding hands: dark skin tone, light skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏿‍🤝‍🧑🏼 E12.0 people holding hands: dark skin tone, medium-light skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏿‍🤝‍🧑🏽 E12.0 people holding hands: dark skin tone, medium skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏿‍🤝‍🧑🏾 E12.0 people holding hands: dark skin tone, medium-dark skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏿‍🤝‍🧑🏿 E12.0 people holding hands: dark skin tone +1F46D ; fully-qualified # 👭 E1.0 women holding hands +1F46D 1F3FB ; fully-qualified # 👭🏻 E12.0 women holding hands: light skin tone +1F469 1F3FB 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏻‍🤝‍👩🏼 E12.1 women holding hands: light skin tone, medium-light skin tone +1F469 1F3FB 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏻‍🤝‍👩🏽 E12.1 women holding hands: light skin tone, medium skin tone +1F469 1F3FB 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏻‍🤝‍👩🏾 E12.1 women holding hands: light skin tone, medium-dark skin tone +1F469 1F3FB 200D 1F91D 200D 1F469 1F3FF ; fully-qualified # 👩🏻‍🤝‍👩🏿 E12.1 women holding hands: light skin tone, dark skin tone +1F469 1F3FC 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏼‍🤝‍👩🏻 E12.0 women holding hands: medium-light skin tone, light skin tone +1F46D 1F3FC ; fully-qualified # 👭🏼 E12.0 women holding hands: medium-light skin tone +1F469 1F3FC 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏼‍🤝‍👩🏽 E12.1 women holding hands: medium-light skin tone, medium skin tone +1F469 1F3FC 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏼‍🤝‍👩🏾 E12.1 women holding hands: medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 1F91D 200D 1F469 1F3FF ; fully-qualified # 👩🏼‍🤝‍👩🏿 E12.1 women holding hands: medium-light skin tone, dark skin tone +1F469 1F3FD 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏽‍🤝‍👩🏻 E12.0 women holding hands: medium skin tone, light skin tone +1F469 1F3FD 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏽‍🤝‍👩🏼 E12.0 women holding hands: medium skin tone, medium-light skin tone +1F46D 1F3FD ; fully-qualified # 👭🏽 E12.0 women holding hands: medium skin tone +1F469 1F3FD 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏽‍🤝‍👩🏾 E12.1 women holding hands: medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 1F91D 200D 1F469 1F3FF ; fully-qualified # 👩🏽‍🤝‍👩🏿 E12.1 women holding hands: medium skin tone, dark skin tone +1F469 1F3FE 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏾‍🤝‍👩🏻 E12.0 women holding hands: medium-dark skin tone, light skin tone +1F469 1F3FE 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏾‍🤝‍👩🏼 E12.0 women holding hands: medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏾‍🤝‍👩🏽 E12.0 women holding hands: medium-dark skin tone, medium skin tone +1F46D 1F3FE ; fully-qualified # 👭🏾 E12.0 women holding hands: medium-dark skin tone +1F469 1F3FE 200D 1F91D 200D 1F469 1F3FF ; fully-qualified # 👩🏾‍🤝‍👩🏿 E12.1 women holding hands: medium-dark skin tone, dark skin tone +1F469 1F3FF 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏿‍🤝‍👩🏻 E12.0 women holding hands: dark skin tone, light skin tone +1F469 1F3FF 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏿‍🤝‍👩🏼 E12.0 women holding hands: dark skin tone, medium-light skin tone +1F469 1F3FF 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏿‍🤝‍👩🏽 E12.0 women holding hands: dark skin tone, medium skin tone +1F469 1F3FF 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏿‍🤝‍👩🏾 E12.0 women holding hands: dark skin tone, medium-dark skin tone +1F46D 1F3FF ; fully-qualified # 👭🏿 E12.0 women holding hands: dark skin tone +1F46B ; fully-qualified # 👫 E0.6 woman and man holding hands +1F46B 1F3FB ; fully-qualified # 👫🏻 E12.0 woman and man holding hands: light skin tone +1F469 1F3FB 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏻‍🤝‍👨🏼 E12.0 woman and man holding hands: light skin tone, medium-light skin tone +1F469 1F3FB 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏻‍🤝‍👨🏽 E12.0 woman and man holding hands: light skin tone, medium skin tone +1F469 1F3FB 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏻‍🤝‍👨🏾 E12.0 woman and man holding hands: light skin tone, medium-dark skin tone +1F469 1F3FB 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏻‍🤝‍👨🏿 E12.0 woman and man holding hands: light skin tone, dark skin tone +1F469 1F3FC 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏼‍🤝‍👨🏻 E12.0 woman and man holding hands: medium-light skin tone, light skin tone +1F46B 1F3FC ; fully-qualified # 👫🏼 E12.0 woman and man holding hands: medium-light skin tone +1F469 1F3FC 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏼‍🤝‍👨🏽 E12.0 woman and man holding hands: medium-light skin tone, medium skin tone +1F469 1F3FC 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏼‍🤝‍👨🏾 E12.0 woman and man holding hands: medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏼‍🤝‍👨🏿 E12.0 woman and man holding hands: medium-light skin tone, dark skin tone +1F469 1F3FD 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏽‍🤝‍👨🏻 E12.0 woman and man holding hands: medium skin tone, light skin tone +1F469 1F3FD 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏽‍🤝‍👨🏼 E12.0 woman and man holding hands: medium skin tone, medium-light skin tone +1F46B 1F3FD ; fully-qualified # 👫🏽 E12.0 woman and man holding hands: medium skin tone +1F469 1F3FD 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏽‍🤝‍👨🏾 E12.0 woman and man holding hands: medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏽‍🤝‍👨🏿 E12.0 woman and man holding hands: medium skin tone, dark skin tone +1F469 1F3FE 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏾‍🤝‍👨🏻 E12.0 woman and man holding hands: medium-dark skin tone, light skin tone +1F469 1F3FE 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏾‍🤝‍👨🏼 E12.0 woman and man holding hands: medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏾‍🤝‍👨🏽 E12.0 woman and man holding hands: medium-dark skin tone, medium skin tone +1F46B 1F3FE ; fully-qualified # 👫🏾 E12.0 woman and man holding hands: medium-dark skin tone +1F469 1F3FE 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏾‍🤝‍👨🏿 E12.0 woman and man holding hands: medium-dark skin tone, dark skin tone +1F469 1F3FF 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏿‍🤝‍👨🏻 E12.0 woman and man holding hands: dark skin tone, light skin tone +1F469 1F3FF 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏿‍🤝‍👨🏼 E12.0 woman and man holding hands: dark skin tone, medium-light skin tone +1F469 1F3FF 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏿‍🤝‍👨🏽 E12.0 woman and man holding hands: dark skin tone, medium skin tone +1F469 1F3FF 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏿‍🤝‍👨🏾 E12.0 woman and man holding hands: dark skin tone, medium-dark skin tone +1F46B 1F3FF ; fully-qualified # 👫🏿 E12.0 woman and man holding hands: dark skin tone +1F46C ; fully-qualified # 👬 E1.0 men holding hands +1F46C 1F3FB ; fully-qualified # 👬🏻 E12.0 men holding hands: light skin tone +1F468 1F3FB 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏻‍🤝‍👨🏼 E12.1 men holding hands: light skin tone, medium-light skin tone +1F468 1F3FB 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏻‍🤝‍👨🏽 E12.1 men holding hands: light skin tone, medium skin tone +1F468 1F3FB 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏻‍🤝‍👨🏾 E12.1 men holding hands: light skin tone, medium-dark skin tone +1F468 1F3FB 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👨🏻‍🤝‍👨🏿 E12.1 men holding hands: light skin tone, dark skin tone +1F468 1F3FC 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏼‍🤝‍👨🏻 E12.0 men holding hands: medium-light skin tone, light skin tone +1F46C 1F3FC ; fully-qualified # 👬🏼 E12.0 men holding hands: medium-light skin tone +1F468 1F3FC 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏼‍🤝‍👨🏽 E12.1 men holding hands: medium-light skin tone, medium skin tone +1F468 1F3FC 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏼‍🤝‍👨🏾 E12.1 men holding hands: medium-light skin tone, medium-dark skin tone +1F468 1F3FC 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👨🏼‍🤝‍👨🏿 E12.1 men holding hands: medium-light skin tone, dark skin tone +1F468 1F3FD 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏽‍🤝‍👨🏻 E12.0 men holding hands: medium skin tone, light skin tone +1F468 1F3FD 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏽‍🤝‍👨🏼 E12.0 men holding hands: medium skin tone, medium-light skin tone +1F46C 1F3FD ; fully-qualified # 👬🏽 E12.0 men holding hands: medium skin tone +1F468 1F3FD 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏽‍🤝‍👨🏾 E12.1 men holding hands: medium skin tone, medium-dark skin tone +1F468 1F3FD 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👨🏽‍🤝‍👨🏿 E12.1 men holding hands: medium skin tone, dark skin tone +1F468 1F3FE 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏾‍🤝‍👨🏻 E12.0 men holding hands: medium-dark skin tone, light skin tone +1F468 1F3FE 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏾‍🤝‍👨🏼 E12.0 men holding hands: medium-dark skin tone, medium-light skin tone +1F468 1F3FE 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏾‍🤝‍👨🏽 E12.0 men holding hands: medium-dark skin tone, medium skin tone +1F46C 1F3FE ; fully-qualified # 👬🏾 E12.0 men holding hands: medium-dark skin tone +1F468 1F3FE 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👨🏾‍🤝‍👨🏿 E12.1 men holding hands: medium-dark skin tone, dark skin tone +1F468 1F3FF 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏿‍🤝‍👨🏻 E12.0 men holding hands: dark skin tone, light skin tone +1F468 1F3FF 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏿‍🤝‍👨🏼 E12.0 men holding hands: dark skin tone, medium-light skin tone +1F468 1F3FF 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏿‍🤝‍👨🏽 E12.0 men holding hands: dark skin tone, medium skin tone +1F468 1F3FF 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏿‍🤝‍👨🏾 E12.0 men holding hands: dark skin tone, medium-dark skin tone +1F46C 1F3FF ; fully-qualified # 👬🏿 E12.0 men holding hands: dark skin tone +1F48F ; fully-qualified # 💏 E0.6 kiss +1F48F 1F3FB ; fully-qualified # 💏🏻 E13.1 kiss: light skin tone +1F48F 1F3FC ; fully-qualified # 💏🏼 E13.1 kiss: medium-light skin tone +1F48F 1F3FD ; fully-qualified # 💏🏽 E13.1 kiss: medium skin tone +1F48F 1F3FE ; fully-qualified # 💏🏾 E13.1 kiss: medium-dark skin tone +1F48F 1F3FF ; fully-qualified # 💏🏿 E13.1 kiss: dark skin tone +1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏻‍❤️‍💋‍🧑🏼 E13.1 kiss: person, person, light skin tone, medium-light skin tone +1F9D1 1F3FB 200D 2764 200D 1F48B 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏻‍❤‍💋‍🧑🏼 E13.1 kiss: person, person, light skin tone, medium-light skin tone +1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏻‍❤️‍💋‍🧑🏽 E13.1 kiss: person, person, light skin tone, medium skin tone +1F9D1 1F3FB 200D 2764 200D 1F48B 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏻‍❤‍💋‍🧑🏽 E13.1 kiss: person, person, light skin tone, medium skin tone +1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏻‍❤️‍💋‍🧑🏾 E13.1 kiss: person, person, light skin tone, medium-dark skin tone +1F9D1 1F3FB 200D 2764 200D 1F48B 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏻‍❤‍💋‍🧑🏾 E13.1 kiss: person, person, light skin tone, medium-dark skin tone +1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏻‍❤️‍💋‍🧑🏿 E13.1 kiss: person, person, light skin tone, dark skin tone +1F9D1 1F3FB 200D 2764 200D 1F48B 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏻‍❤‍💋‍🧑🏿 E13.1 kiss: person, person, light skin tone, dark skin tone +1F9D1 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏼‍❤️‍💋‍🧑🏻 E13.1 kiss: person, person, medium-light skin tone, light skin tone +1F9D1 1F3FC 200D 2764 200D 1F48B 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏼‍❤‍💋‍🧑🏻 E13.1 kiss: person, person, medium-light skin tone, light skin tone +1F9D1 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏼‍❤️‍💋‍🧑🏽 E13.1 kiss: person, person, medium-light skin tone, medium skin tone +1F9D1 1F3FC 200D 2764 200D 1F48B 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏼‍❤‍💋‍🧑🏽 E13.1 kiss: person, person, medium-light skin tone, medium skin tone +1F9D1 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏼‍❤️‍💋‍🧑🏾 E13.1 kiss: person, person, medium-light skin tone, medium-dark skin tone +1F9D1 1F3FC 200D 2764 200D 1F48B 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏼‍❤‍💋‍🧑🏾 E13.1 kiss: person, person, medium-light skin tone, medium-dark skin tone +1F9D1 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏼‍❤️‍💋‍🧑🏿 E13.1 kiss: person, person, medium-light skin tone, dark skin tone +1F9D1 1F3FC 200D 2764 200D 1F48B 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏼‍❤‍💋‍🧑🏿 E13.1 kiss: person, person, medium-light skin tone, dark skin tone +1F9D1 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏽‍❤️‍💋‍🧑🏻 E13.1 kiss: person, person, medium skin tone, light skin tone +1F9D1 1F3FD 200D 2764 200D 1F48B 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏽‍❤‍💋‍🧑🏻 E13.1 kiss: person, person, medium skin tone, light skin tone +1F9D1 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏽‍❤️‍💋‍🧑🏼 E13.1 kiss: person, person, medium skin tone, medium-light skin tone +1F9D1 1F3FD 200D 2764 200D 1F48B 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏽‍❤‍💋‍🧑🏼 E13.1 kiss: person, person, medium skin tone, medium-light skin tone +1F9D1 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏽‍❤️‍💋‍🧑🏾 E13.1 kiss: person, person, medium skin tone, medium-dark skin tone +1F9D1 1F3FD 200D 2764 200D 1F48B 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏽‍❤‍💋‍🧑🏾 E13.1 kiss: person, person, medium skin tone, medium-dark skin tone +1F9D1 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏽‍❤️‍💋‍🧑🏿 E13.1 kiss: person, person, medium skin tone, dark skin tone +1F9D1 1F3FD 200D 2764 200D 1F48B 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏽‍❤‍💋‍🧑🏿 E13.1 kiss: person, person, medium skin tone, dark skin tone +1F9D1 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏾‍❤️‍💋‍🧑🏻 E13.1 kiss: person, person, medium-dark skin tone, light skin tone +1F9D1 1F3FE 200D 2764 200D 1F48B 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏾‍❤‍💋‍🧑🏻 E13.1 kiss: person, person, medium-dark skin tone, light skin tone +1F9D1 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏾‍❤️‍💋‍🧑🏼 E13.1 kiss: person, person, medium-dark skin tone, medium-light skin tone +1F9D1 1F3FE 200D 2764 200D 1F48B 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏾‍❤‍💋‍🧑🏼 E13.1 kiss: person, person, medium-dark skin tone, medium-light skin tone +1F9D1 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏾‍❤️‍💋‍🧑🏽 E13.1 kiss: person, person, medium-dark skin tone, medium skin tone +1F9D1 1F3FE 200D 2764 200D 1F48B 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏾‍❤‍💋‍🧑🏽 E13.1 kiss: person, person, medium-dark skin tone, medium skin tone +1F9D1 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏾‍❤️‍💋‍🧑🏿 E13.1 kiss: person, person, medium-dark skin tone, dark skin tone +1F9D1 1F3FE 200D 2764 200D 1F48B 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏾‍❤‍💋‍🧑🏿 E13.1 kiss: person, person, medium-dark skin tone, dark skin tone +1F9D1 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏿‍❤️‍💋‍🧑🏻 E13.1 kiss: person, person, dark skin tone, light skin tone +1F9D1 1F3FF 200D 2764 200D 1F48B 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏿‍❤‍💋‍🧑🏻 E13.1 kiss: person, person, dark skin tone, light skin tone +1F9D1 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏿‍❤️‍💋‍🧑🏼 E13.1 kiss: person, person, dark skin tone, medium-light skin tone +1F9D1 1F3FF 200D 2764 200D 1F48B 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏿‍❤‍💋‍🧑🏼 E13.1 kiss: person, person, dark skin tone, medium-light skin tone +1F9D1 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏿‍❤️‍💋‍🧑🏽 E13.1 kiss: person, person, dark skin tone, medium skin tone +1F9D1 1F3FF 200D 2764 200D 1F48B 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏿‍❤‍💋‍🧑🏽 E13.1 kiss: person, person, dark skin tone, medium skin tone +1F9D1 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏿‍❤️‍💋‍🧑🏾 E13.1 kiss: person, person, dark skin tone, medium-dark skin tone +1F9D1 1F3FF 200D 2764 200D 1F48B 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏿‍❤‍💋‍🧑🏾 E13.1 kiss: person, person, dark skin tone, medium-dark skin tone +1F469 200D 2764 FE0F 200D 1F48B 200D 1F468 ; fully-qualified # 👩‍❤️‍💋‍👨 E2.0 kiss: woman, man +1F469 200D 2764 200D 1F48B 200D 1F468 ; minimally-qualified # 👩‍❤‍💋‍👨 E2.0 kiss: woman, man +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, light skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, light skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, light skin tone, medium-light skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, light skin tone, medium-light skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, light skin tone, medium skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, light skin tone, medium skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, light skin tone, medium-dark skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, light skin tone, medium-dark skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, light skin tone, dark skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, light skin tone, dark skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, medium-light skin tone, light skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, medium-light skin tone, light skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, medium-light skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, medium-light skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, medium-light skin tone, medium skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, medium-light skin tone, medium skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, medium-light skin tone, dark skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, medium-light skin tone, dark skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, medium skin tone, light skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, medium skin tone, light skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, medium skin tone, medium-light skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, medium skin tone, medium-light skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, medium skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, medium skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, medium skin tone, dark skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, medium skin tone, dark skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, medium-dark skin tone, light skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, medium-dark skin tone, light skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, medium-dark skin tone, medium skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, medium-dark skin tone, medium skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, medium-dark skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, medium-dark skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, medium-dark skin tone, dark skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, medium-dark skin tone, dark skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, dark skin tone, light skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, dark skin tone, light skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, dark skin tone, medium-light skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, dark skin tone, medium-light skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, dark skin tone, medium skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, dark skin tone, medium skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, dark skin tone, medium-dark skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, dark skin tone, medium-dark skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, dark skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, dark skin tone +1F468 200D 2764 FE0F 200D 1F48B 200D 1F468 ; fully-qualified # 👨‍❤️‍💋‍👨 E2.0 kiss: man, man +1F468 200D 2764 200D 1F48B 200D 1F468 ; minimally-qualified # 👨‍❤‍💋‍👨 E2.0 kiss: man, man +1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, light skin tone +1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏻 E13.1 kiss: man, man, light skin tone +1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, light skin tone, medium-light skin tone +1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏼 E13.1 kiss: man, man, light skin tone, medium-light skin tone +1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, light skin tone, medium skin tone +1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏽 E13.1 kiss: man, man, light skin tone, medium skin tone +1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, light skin tone, medium-dark skin tone +1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏾 E13.1 kiss: man, man, light skin tone, medium-dark skin tone +1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, light skin tone, dark skin tone +1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏿 E13.1 kiss: man, man, light skin tone, dark skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, medium-light skin tone, light skin tone +1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏻 E13.1 kiss: man, man, medium-light skin tone, light skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, medium-light skin tone +1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏼 E13.1 kiss: man, man, medium-light skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, medium-light skin tone, medium skin tone +1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏽 E13.1 kiss: man, man, medium-light skin tone, medium skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, medium-light skin tone, medium-dark skin tone +1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏾 E13.1 kiss: man, man, medium-light skin tone, medium-dark skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, medium-light skin tone, dark skin tone +1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏿 E13.1 kiss: man, man, medium-light skin tone, dark skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, medium skin tone, light skin tone +1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏻 E13.1 kiss: man, man, medium skin tone, light skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, medium skin tone, medium-light skin tone +1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏼 E13.1 kiss: man, man, medium skin tone, medium-light skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, medium skin tone +1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏽 E13.1 kiss: man, man, medium skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, medium skin tone, medium-dark skin tone +1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏾 E13.1 kiss: man, man, medium skin tone, medium-dark skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, medium skin tone, dark skin tone +1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏿 E13.1 kiss: man, man, medium skin tone, dark skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, medium-dark skin tone, light skin tone +1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏻 E13.1 kiss: man, man, medium-dark skin tone, light skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, medium-dark skin tone, medium-light skin tone +1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏼 E13.1 kiss: man, man, medium-dark skin tone, medium-light skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, medium-dark skin tone, medium skin tone +1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏽 E13.1 kiss: man, man, medium-dark skin tone, medium skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, medium-dark skin tone +1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏾 E13.1 kiss: man, man, medium-dark skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, medium-dark skin tone, dark skin tone +1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏿 E13.1 kiss: man, man, medium-dark skin tone, dark skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, dark skin tone, light skin tone +1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏻 E13.1 kiss: man, man, dark skin tone, light skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, dark skin tone, medium-light skin tone +1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏼 E13.1 kiss: man, man, dark skin tone, medium-light skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, dark skin tone, medium skin tone +1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏽 E13.1 kiss: man, man, dark skin tone, medium skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, dark skin tone, medium-dark skin tone +1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏾 E13.1 kiss: man, man, dark skin tone, medium-dark skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, dark skin tone +1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏿 E13.1 kiss: man, man, dark skin tone +1F469 200D 2764 FE0F 200D 1F48B 200D 1F469 ; fully-qualified # 👩‍❤️‍💋‍👩 E2.0 kiss: woman, woman +1F469 200D 2764 200D 1F48B 200D 1F469 ; minimally-qualified # 👩‍❤‍💋‍👩 E2.0 kiss: woman, woman +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, light skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, light skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, light skin tone, medium-light skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, light skin tone, medium-light skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, light skin tone, medium skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, light skin tone, medium skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, light skin tone, medium-dark skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, light skin tone, medium-dark skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, light skin tone, dark skin tone +1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, light skin tone, dark skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, medium-light skin tone, light skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, medium-light skin tone, light skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, medium-light skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, medium-light skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, medium-light skin tone, medium skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, medium-light skin tone, medium skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, medium-light skin tone, dark skin tone +1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, medium-light skin tone, dark skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, medium skin tone, light skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, medium skin tone, light skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, medium skin tone, medium-light skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, medium skin tone, medium-light skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, medium skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, medium skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, medium skin tone, dark skin tone +1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, medium skin tone, dark skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, medium-dark skin tone, light skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, medium-dark skin tone, light skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, medium-dark skin tone, medium skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, medium-dark skin tone, medium skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, medium-dark skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, medium-dark skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, medium-dark skin tone, dark skin tone +1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, medium-dark skin tone, dark skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, dark skin tone, light skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, dark skin tone, light skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, dark skin tone, medium-light skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, dark skin tone, medium-light skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, dark skin tone, medium skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, dark skin tone, medium skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, dark skin tone, medium-dark skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, dark skin tone, medium-dark skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, dark skin tone +1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, dark skin tone +1F491 ; fully-qualified # 💑 E0.6 couple with heart +1F491 1F3FB ; fully-qualified # 💑🏻 E13.1 couple with heart: light skin tone +1F491 1F3FC ; fully-qualified # 💑🏼 E13.1 couple with heart: medium-light skin tone +1F491 1F3FD ; fully-qualified # 💑🏽 E13.1 couple with heart: medium skin tone +1F491 1F3FE ; fully-qualified # 💑🏾 E13.1 couple with heart: medium-dark skin tone +1F491 1F3FF ; fully-qualified # 💑🏿 E13.1 couple with heart: dark skin tone +1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏻‍❤️‍🧑🏼 E13.1 couple with heart: person, person, light skin tone, medium-light skin tone +1F9D1 1F3FB 200D 2764 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏻‍❤‍🧑🏼 E13.1 couple with heart: person, person, light skin tone, medium-light skin tone +1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏻‍❤️‍🧑🏽 E13.1 couple with heart: person, person, light skin tone, medium skin tone +1F9D1 1F3FB 200D 2764 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏻‍❤‍🧑🏽 E13.1 couple with heart: person, person, light skin tone, medium skin tone +1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏻‍❤️‍🧑🏾 E13.1 couple with heart: person, person, light skin tone, medium-dark skin tone +1F9D1 1F3FB 200D 2764 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏻‍❤‍🧑🏾 E13.1 couple with heart: person, person, light skin tone, medium-dark skin tone +1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏻‍❤️‍🧑🏿 E13.1 couple with heart: person, person, light skin tone, dark skin tone +1F9D1 1F3FB 200D 2764 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏻‍❤‍🧑🏿 E13.1 couple with heart: person, person, light skin tone, dark skin tone +1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏼‍❤️‍🧑🏻 E13.1 couple with heart: person, person, medium-light skin tone, light skin tone +1F9D1 1F3FC 200D 2764 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏼‍❤‍🧑🏻 E13.1 couple with heart: person, person, medium-light skin tone, light skin tone +1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏼‍❤️‍🧑🏽 E13.1 couple with heart: person, person, medium-light skin tone, medium skin tone +1F9D1 1F3FC 200D 2764 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏼‍❤‍🧑🏽 E13.1 couple with heart: person, person, medium-light skin tone, medium skin tone +1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏼‍❤️‍🧑🏾 E13.1 couple with heart: person, person, medium-light skin tone, medium-dark skin tone +1F9D1 1F3FC 200D 2764 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏼‍❤‍🧑🏾 E13.1 couple with heart: person, person, medium-light skin tone, medium-dark skin tone +1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏼‍❤️‍🧑🏿 E13.1 couple with heart: person, person, medium-light skin tone, dark skin tone +1F9D1 1F3FC 200D 2764 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏼‍❤‍🧑🏿 E13.1 couple with heart: person, person, medium-light skin tone, dark skin tone +1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏽‍❤️‍🧑🏻 E13.1 couple with heart: person, person, medium skin tone, light skin tone +1F9D1 1F3FD 200D 2764 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏽‍❤‍🧑🏻 E13.1 couple with heart: person, person, medium skin tone, light skin tone +1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏽‍❤️‍🧑🏼 E13.1 couple with heart: person, person, medium skin tone, medium-light skin tone +1F9D1 1F3FD 200D 2764 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏽‍❤‍🧑🏼 E13.1 couple with heart: person, person, medium skin tone, medium-light skin tone +1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏽‍❤️‍🧑🏾 E13.1 couple with heart: person, person, medium skin tone, medium-dark skin tone +1F9D1 1F3FD 200D 2764 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏽‍❤‍🧑🏾 E13.1 couple with heart: person, person, medium skin tone, medium-dark skin tone +1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏽‍❤️‍🧑🏿 E13.1 couple with heart: person, person, medium skin tone, dark skin tone +1F9D1 1F3FD 200D 2764 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏽‍❤‍🧑🏿 E13.1 couple with heart: person, person, medium skin tone, dark skin tone +1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏾‍❤️‍🧑🏻 E13.1 couple with heart: person, person, medium-dark skin tone, light skin tone +1F9D1 1F3FE 200D 2764 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏾‍❤‍🧑🏻 E13.1 couple with heart: person, person, medium-dark skin tone, light skin tone +1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏾‍❤️‍🧑🏼 E13.1 couple with heart: person, person, medium-dark skin tone, medium-light skin tone +1F9D1 1F3FE 200D 2764 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏾‍❤‍🧑🏼 E13.1 couple with heart: person, person, medium-dark skin tone, medium-light skin tone +1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏾‍❤️‍🧑🏽 E13.1 couple with heart: person, person, medium-dark skin tone, medium skin tone +1F9D1 1F3FE 200D 2764 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏾‍❤‍🧑🏽 E13.1 couple with heart: person, person, medium-dark skin tone, medium skin tone +1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏾‍❤️‍🧑🏿 E13.1 couple with heart: person, person, medium-dark skin tone, dark skin tone +1F9D1 1F3FE 200D 2764 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏾‍❤‍🧑🏿 E13.1 couple with heart: person, person, medium-dark skin tone, dark skin tone +1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏿‍❤️‍🧑🏻 E13.1 couple with heart: person, person, dark skin tone, light skin tone +1F9D1 1F3FF 200D 2764 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏿‍❤‍🧑🏻 E13.1 couple with heart: person, person, dark skin tone, light skin tone +1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏿‍❤️‍🧑🏼 E13.1 couple with heart: person, person, dark skin tone, medium-light skin tone +1F9D1 1F3FF 200D 2764 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏿‍❤‍🧑🏼 E13.1 couple with heart: person, person, dark skin tone, medium-light skin tone +1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏿‍❤️‍🧑🏽 E13.1 couple with heart: person, person, dark skin tone, medium skin tone +1F9D1 1F3FF 200D 2764 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏿‍❤‍🧑🏽 E13.1 couple with heart: person, person, dark skin tone, medium skin tone +1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏿‍❤️‍🧑🏾 E13.1 couple with heart: person, person, dark skin tone, medium-dark skin tone +1F9D1 1F3FF 200D 2764 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏿‍❤‍🧑🏾 E13.1 couple with heart: person, person, dark skin tone, medium-dark skin tone +1F469 200D 2764 FE0F 200D 1F468 ; fully-qualified # 👩‍❤️‍👨 E2.0 couple with heart: woman, man +1F469 200D 2764 200D 1F468 ; minimally-qualified # 👩‍❤‍👨 E2.0 couple with heart: woman, man +1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏻‍❤️‍👨🏻 E13.1 couple with heart: woman, man, light skin tone +1F469 1F3FB 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏻‍❤‍👨🏻 E13.1 couple with heart: woman, man, light skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏻‍❤️‍👨🏼 E13.1 couple with heart: woman, man, light skin tone, medium-light skin tone +1F469 1F3FB 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏻‍❤‍👨🏼 E13.1 couple with heart: woman, man, light skin tone, medium-light skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏻‍❤️‍👨🏽 E13.1 couple with heart: woman, man, light skin tone, medium skin tone +1F469 1F3FB 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏻‍❤‍👨🏽 E13.1 couple with heart: woman, man, light skin tone, medium skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏻‍❤️‍👨🏾 E13.1 couple with heart: woman, man, light skin tone, medium-dark skin tone +1F469 1F3FB 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏻‍❤‍👨🏾 E13.1 couple with heart: woman, man, light skin tone, medium-dark skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏻‍❤️‍👨🏿 E13.1 couple with heart: woman, man, light skin tone, dark skin tone +1F469 1F3FB 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏻‍❤‍👨🏿 E13.1 couple with heart: woman, man, light skin tone, dark skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏼‍❤️‍👨🏻 E13.1 couple with heart: woman, man, medium-light skin tone, light skin tone +1F469 1F3FC 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏼‍❤‍👨🏻 E13.1 couple with heart: woman, man, medium-light skin tone, light skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏼‍❤️‍👨🏼 E13.1 couple with heart: woman, man, medium-light skin tone +1F469 1F3FC 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏼‍❤‍👨🏼 E13.1 couple with heart: woman, man, medium-light skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏼‍❤️‍👨🏽 E13.1 couple with heart: woman, man, medium-light skin tone, medium skin tone +1F469 1F3FC 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏼‍❤‍👨🏽 E13.1 couple with heart: woman, man, medium-light skin tone, medium skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏼‍❤️‍👨🏾 E13.1 couple with heart: woman, man, medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏼‍❤‍👨🏾 E13.1 couple with heart: woman, man, medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏼‍❤️‍👨🏿 E13.1 couple with heart: woman, man, medium-light skin tone, dark skin tone +1F469 1F3FC 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏼‍❤‍👨🏿 E13.1 couple with heart: woman, man, medium-light skin tone, dark skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏽‍❤️‍👨🏻 E13.1 couple with heart: woman, man, medium skin tone, light skin tone +1F469 1F3FD 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏽‍❤‍👨🏻 E13.1 couple with heart: woman, man, medium skin tone, light skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏽‍❤️‍👨🏼 E13.1 couple with heart: woman, man, medium skin tone, medium-light skin tone +1F469 1F3FD 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏽‍❤‍👨🏼 E13.1 couple with heart: woman, man, medium skin tone, medium-light skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏽‍❤️‍👨🏽 E13.1 couple with heart: woman, man, medium skin tone +1F469 1F3FD 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏽‍❤‍👨🏽 E13.1 couple with heart: woman, man, medium skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏽‍❤️‍👨🏾 E13.1 couple with heart: woman, man, medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏽‍❤‍👨🏾 E13.1 couple with heart: woman, man, medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏽‍❤️‍👨🏿 E13.1 couple with heart: woman, man, medium skin tone, dark skin tone +1F469 1F3FD 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏽‍❤‍👨🏿 E13.1 couple with heart: woman, man, medium skin tone, dark skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏾‍❤️‍👨🏻 E13.1 couple with heart: woman, man, medium-dark skin tone, light skin tone +1F469 1F3FE 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏾‍❤‍👨🏻 E13.1 couple with heart: woman, man, medium-dark skin tone, light skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏾‍❤️‍👨🏼 E13.1 couple with heart: woman, man, medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏾‍❤‍👨🏼 E13.1 couple with heart: woman, man, medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏾‍❤️‍👨🏽 E13.1 couple with heart: woman, man, medium-dark skin tone, medium skin tone +1F469 1F3FE 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏾‍❤‍👨🏽 E13.1 couple with heart: woman, man, medium-dark skin tone, medium skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏾‍❤️‍👨🏾 E13.1 couple with heart: woman, man, medium-dark skin tone +1F469 1F3FE 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏾‍❤‍👨🏾 E13.1 couple with heart: woman, man, medium-dark skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏾‍❤️‍👨🏿 E13.1 couple with heart: woman, man, medium-dark skin tone, dark skin tone +1F469 1F3FE 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏾‍❤‍👨🏿 E13.1 couple with heart: woman, man, medium-dark skin tone, dark skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏿‍❤️‍👨🏻 E13.1 couple with heart: woman, man, dark skin tone, light skin tone +1F469 1F3FF 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏿‍❤‍👨🏻 E13.1 couple with heart: woman, man, dark skin tone, light skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏿‍❤️‍👨🏼 E13.1 couple with heart: woman, man, dark skin tone, medium-light skin tone +1F469 1F3FF 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏿‍❤‍👨🏼 E13.1 couple with heart: woman, man, dark skin tone, medium-light skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏿‍❤️‍👨🏽 E13.1 couple with heart: woman, man, dark skin tone, medium skin tone +1F469 1F3FF 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏿‍❤‍👨🏽 E13.1 couple with heart: woman, man, dark skin tone, medium skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏿‍❤️‍👨🏾 E13.1 couple with heart: woman, man, dark skin tone, medium-dark skin tone +1F469 1F3FF 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏿‍❤‍👨🏾 E13.1 couple with heart: woman, man, dark skin tone, medium-dark skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏿‍❤️‍👨🏿 E13.1 couple with heart: woman, man, dark skin tone +1F469 1F3FF 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏿‍❤‍👨🏿 E13.1 couple with heart: woman, man, dark skin tone +1F468 200D 2764 FE0F 200D 1F468 ; fully-qualified # 👨‍❤️‍👨 E2.0 couple with heart: man, man +1F468 200D 2764 200D 1F468 ; minimally-qualified # 👨‍❤‍👨 E2.0 couple with heart: man, man +1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏻‍❤️‍👨🏻 E13.1 couple with heart: man, man, light skin tone +1F468 1F3FB 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏻‍❤‍👨🏻 E13.1 couple with heart: man, man, light skin tone +1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏻‍❤️‍👨🏼 E13.1 couple with heart: man, man, light skin tone, medium-light skin tone +1F468 1F3FB 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏻‍❤‍👨🏼 E13.1 couple with heart: man, man, light skin tone, medium-light skin tone +1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏻‍❤️‍👨🏽 E13.1 couple with heart: man, man, light skin tone, medium skin tone +1F468 1F3FB 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏻‍❤‍👨🏽 E13.1 couple with heart: man, man, light skin tone, medium skin tone +1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏻‍❤️‍👨🏾 E13.1 couple with heart: man, man, light skin tone, medium-dark skin tone +1F468 1F3FB 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏻‍❤‍👨🏾 E13.1 couple with heart: man, man, light skin tone, medium-dark skin tone +1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏻‍❤️‍👨🏿 E13.1 couple with heart: man, man, light skin tone, dark skin tone +1F468 1F3FB 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏻‍❤‍👨🏿 E13.1 couple with heart: man, man, light skin tone, dark skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏼‍❤️‍👨🏻 E13.1 couple with heart: man, man, medium-light skin tone, light skin tone +1F468 1F3FC 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏼‍❤‍👨🏻 E13.1 couple with heart: man, man, medium-light skin tone, light skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏼‍❤️‍👨🏼 E13.1 couple with heart: man, man, medium-light skin tone +1F468 1F3FC 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏼‍❤‍👨🏼 E13.1 couple with heart: man, man, medium-light skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏼‍❤️‍👨🏽 E13.1 couple with heart: man, man, medium-light skin tone, medium skin tone +1F468 1F3FC 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏼‍❤‍👨🏽 E13.1 couple with heart: man, man, medium-light skin tone, medium skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏼‍❤️‍👨🏾 E13.1 couple with heart: man, man, medium-light skin tone, medium-dark skin tone +1F468 1F3FC 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏼‍❤‍👨🏾 E13.1 couple with heart: man, man, medium-light skin tone, medium-dark skin tone +1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏼‍❤️‍👨🏿 E13.1 couple with heart: man, man, medium-light skin tone, dark skin tone +1F468 1F3FC 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏼‍❤‍👨🏿 E13.1 couple with heart: man, man, medium-light skin tone, dark skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏽‍❤️‍👨🏻 E13.1 couple with heart: man, man, medium skin tone, light skin tone +1F468 1F3FD 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏽‍❤‍👨🏻 E13.1 couple with heart: man, man, medium skin tone, light skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏽‍❤️‍👨🏼 E13.1 couple with heart: man, man, medium skin tone, medium-light skin tone +1F468 1F3FD 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏽‍❤‍👨🏼 E13.1 couple with heart: man, man, medium skin tone, medium-light skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏽‍❤️‍👨🏽 E13.1 couple with heart: man, man, medium skin tone +1F468 1F3FD 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏽‍❤‍👨🏽 E13.1 couple with heart: man, man, medium skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏽‍❤️‍👨🏾 E13.1 couple with heart: man, man, medium skin tone, medium-dark skin tone +1F468 1F3FD 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏽‍❤‍👨🏾 E13.1 couple with heart: man, man, medium skin tone, medium-dark skin tone +1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏽‍❤️‍👨🏿 E13.1 couple with heart: man, man, medium skin tone, dark skin tone +1F468 1F3FD 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏽‍❤‍👨🏿 E13.1 couple with heart: man, man, medium skin tone, dark skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏾‍❤️‍👨🏻 E13.1 couple with heart: man, man, medium-dark skin tone, light skin tone +1F468 1F3FE 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏾‍❤‍👨🏻 E13.1 couple with heart: man, man, medium-dark skin tone, light skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏾‍❤️‍👨🏼 E13.1 couple with heart: man, man, medium-dark skin tone, medium-light skin tone +1F468 1F3FE 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏾‍❤‍👨🏼 E13.1 couple with heart: man, man, medium-dark skin tone, medium-light skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏾‍❤️‍👨🏽 E13.1 couple with heart: man, man, medium-dark skin tone, medium skin tone +1F468 1F3FE 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏾‍❤‍👨🏽 E13.1 couple with heart: man, man, medium-dark skin tone, medium skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏾‍❤️‍👨🏾 E13.1 couple with heart: man, man, medium-dark skin tone +1F468 1F3FE 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏾‍❤‍👨🏾 E13.1 couple with heart: man, man, medium-dark skin tone +1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏾‍❤️‍👨🏿 E13.1 couple with heart: man, man, medium-dark skin tone, dark skin tone +1F468 1F3FE 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏾‍❤‍👨🏿 E13.1 couple with heart: man, man, medium-dark skin tone, dark skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏿‍❤️‍👨🏻 E13.1 couple with heart: man, man, dark skin tone, light skin tone +1F468 1F3FF 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏿‍❤‍👨🏻 E13.1 couple with heart: man, man, dark skin tone, light skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏿‍❤️‍👨🏼 E13.1 couple with heart: man, man, dark skin tone, medium-light skin tone +1F468 1F3FF 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏿‍❤‍👨🏼 E13.1 couple with heart: man, man, dark skin tone, medium-light skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏿‍❤️‍👨🏽 E13.1 couple with heart: man, man, dark skin tone, medium skin tone +1F468 1F3FF 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏿‍❤‍👨🏽 E13.1 couple with heart: man, man, dark skin tone, medium skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏿‍❤️‍👨🏾 E13.1 couple with heart: man, man, dark skin tone, medium-dark skin tone +1F468 1F3FF 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏿‍❤‍👨🏾 E13.1 couple with heart: man, man, dark skin tone, medium-dark skin tone +1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏿‍❤️‍👨🏿 E13.1 couple with heart: man, man, dark skin tone +1F468 1F3FF 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏿‍❤‍👨🏿 E13.1 couple with heart: man, man, dark skin tone +1F469 200D 2764 FE0F 200D 1F469 ; fully-qualified # 👩‍❤️‍👩 E2.0 couple with heart: woman, woman +1F469 200D 2764 200D 1F469 ; minimally-qualified # 👩‍❤‍👩 E2.0 couple with heart: woman, woman +1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏻‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, light skin tone +1F469 1F3FB 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏻‍❤‍👩🏻 E13.1 couple with heart: woman, woman, light skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏻‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, light skin tone, medium-light skin tone +1F469 1F3FB 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏻‍❤‍👩🏼 E13.1 couple with heart: woman, woman, light skin tone, medium-light skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏻‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, light skin tone, medium skin tone +1F469 1F3FB 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏻‍❤‍👩🏽 E13.1 couple with heart: woman, woman, light skin tone, medium skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏻‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, light skin tone, medium-dark skin tone +1F469 1F3FB 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏻‍❤‍👩🏾 E13.1 couple with heart: woman, woman, light skin tone, medium-dark skin tone +1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏻‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, light skin tone, dark skin tone +1F469 1F3FB 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏻‍❤‍👩🏿 E13.1 couple with heart: woman, woman, light skin tone, dark skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏼‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, medium-light skin tone, light skin tone +1F469 1F3FC 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏼‍❤‍👩🏻 E13.1 couple with heart: woman, woman, medium-light skin tone, light skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏼‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, medium-light skin tone +1F469 1F3FC 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏼‍❤‍👩🏼 E13.1 couple with heart: woman, woman, medium-light skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏼‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, medium-light skin tone, medium skin tone +1F469 1F3FC 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏼‍❤‍👩🏽 E13.1 couple with heart: woman, woman, medium-light skin tone, medium skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏼‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏼‍❤‍👩🏾 E13.1 couple with heart: woman, woman, medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏼‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, medium-light skin tone, dark skin tone +1F469 1F3FC 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏼‍❤‍👩🏿 E13.1 couple with heart: woman, woman, medium-light skin tone, dark skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏽‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, medium skin tone, light skin tone +1F469 1F3FD 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏽‍❤‍👩🏻 E13.1 couple with heart: woman, woman, medium skin tone, light skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏽‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, medium skin tone, medium-light skin tone +1F469 1F3FD 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏽‍❤‍👩🏼 E13.1 couple with heart: woman, woman, medium skin tone, medium-light skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏽‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, medium skin tone +1F469 1F3FD 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏽‍❤‍👩🏽 E13.1 couple with heart: woman, woman, medium skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏽‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏽‍❤‍👩🏾 E13.1 couple with heart: woman, woman, medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏽‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, medium skin tone, dark skin tone +1F469 1F3FD 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏽‍❤‍👩🏿 E13.1 couple with heart: woman, woman, medium skin tone, dark skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏾‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, medium-dark skin tone, light skin tone +1F469 1F3FE 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏾‍❤‍👩🏻 E13.1 couple with heart: woman, woman, medium-dark skin tone, light skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏾‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏾‍❤‍👩🏼 E13.1 couple with heart: woman, woman, medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏾‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, medium-dark skin tone, medium skin tone +1F469 1F3FE 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏾‍❤‍👩🏽 E13.1 couple with heart: woman, woman, medium-dark skin tone, medium skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏾‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, medium-dark skin tone +1F469 1F3FE 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏾‍❤‍👩🏾 E13.1 couple with heart: woman, woman, medium-dark skin tone +1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏾‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, medium-dark skin tone, dark skin tone +1F469 1F3FE 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏾‍❤‍👩🏿 E13.1 couple with heart: woman, woman, medium-dark skin tone, dark skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏿‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, dark skin tone, light skin tone +1F469 1F3FF 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏿‍❤‍👩🏻 E13.1 couple with heart: woman, woman, dark skin tone, light skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏿‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, dark skin tone, medium-light skin tone +1F469 1F3FF 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏿‍❤‍👩🏼 E13.1 couple with heart: woman, woman, dark skin tone, medium-light skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏿‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, dark skin tone, medium skin tone +1F469 1F3FF 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏿‍❤‍👩🏽 E13.1 couple with heart: woman, woman, dark skin tone, medium skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏿‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, dark skin tone, medium-dark skin tone +1F469 1F3FF 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏿‍❤‍👩🏾 E13.1 couple with heart: woman, woman, dark skin tone, medium-dark skin tone +1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏿‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, dark skin tone +1F469 1F3FF 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏿‍❤‍👩🏿 E13.1 couple with heart: woman, woman, dark skin tone +1F46A ; fully-qualified # 👪 E0.6 family +1F468 200D 1F469 200D 1F466 ; fully-qualified # 👨‍👩‍👦 E2.0 family: man, woman, boy +1F468 200D 1F469 200D 1F467 ; fully-qualified # 👨‍👩‍👧 E2.0 family: man, woman, girl +1F468 200D 1F469 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👩‍👧‍👦 E2.0 family: man, woman, girl, boy +1F468 200D 1F469 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👩‍👦‍👦 E2.0 family: man, woman, boy, boy +1F468 200D 1F469 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👩‍👧‍👧 E2.0 family: man, woman, girl, girl +1F468 200D 1F468 200D 1F466 ; fully-qualified # 👨‍👨‍👦 E2.0 family: man, man, boy +1F468 200D 1F468 200D 1F467 ; fully-qualified # 👨‍👨‍👧 E2.0 family: man, man, girl +1F468 200D 1F468 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👨‍👧‍👦 E2.0 family: man, man, girl, boy +1F468 200D 1F468 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👨‍👦‍👦 E2.0 family: man, man, boy, boy +1F468 200D 1F468 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👨‍👧‍👧 E2.0 family: man, man, girl, girl +1F469 200D 1F469 200D 1F466 ; fully-qualified # 👩‍👩‍👦 E2.0 family: woman, woman, boy +1F469 200D 1F469 200D 1F467 ; fully-qualified # 👩‍👩‍👧 E2.0 family: woman, woman, girl +1F469 200D 1F469 200D 1F467 200D 1F466 ; fully-qualified # 👩‍👩‍👧‍👦 E2.0 family: woman, woman, girl, boy +1F469 200D 1F469 200D 1F466 200D 1F466 ; fully-qualified # 👩‍👩‍👦‍👦 E2.0 family: woman, woman, boy, boy +1F469 200D 1F469 200D 1F467 200D 1F467 ; fully-qualified # 👩‍👩‍👧‍👧 E2.0 family: woman, woman, girl, girl +1F468 200D 1F466 ; fully-qualified # 👨‍👦 E4.0 family: man, boy +1F468 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👦‍👦 E4.0 family: man, boy, boy +1F468 200D 1F467 ; fully-qualified # 👨‍👧 E4.0 family: man, girl +1F468 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👧‍👦 E4.0 family: man, girl, boy +1F468 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👧‍👧 E4.0 family: man, girl, girl +1F469 200D 1F466 ; fully-qualified # 👩‍👦 E4.0 family: woman, boy +1F469 200D 1F466 200D 1F466 ; fully-qualified # 👩‍👦‍👦 E4.0 family: woman, boy, boy +1F469 200D 1F467 ; fully-qualified # 👩‍👧 E4.0 family: woman, girl +1F469 200D 1F467 200D 1F466 ; fully-qualified # 👩‍👧‍👦 E4.0 family: woman, girl, boy +1F469 200D 1F467 200D 1F467 ; fully-qualified # 👩‍👧‍👧 E4.0 family: woman, girl, girl + +# subgroup: person-symbol +1F5E3 FE0F ; fully-qualified # 🗣️ E0.7 speaking head +1F5E3 ; unqualified # 🗣 E0.7 speaking head +1F464 ; fully-qualified # 👤 E0.6 bust in silhouette +1F465 ; fully-qualified # 👥 E1.0 busts in silhouette +1FAC2 ; fully-qualified # 🫂 E13.0 people hugging +1F463 ; fully-qualified # 👣 E0.6 footprints + +# People & Body subtotal: 2998 +# People & Body subtotal: 508 w/o modifiers + +# group: Component + +# subgroup: skin-tone +1F3FB ; component # 🏻 E1.0 light skin tone +1F3FC ; component # 🏼 E1.0 medium-light skin tone +1F3FD ; component # 🏽 E1.0 medium skin tone +1F3FE ; component # 🏾 E1.0 medium-dark skin tone +1F3FF ; component # 🏿 E1.0 dark skin tone + +# subgroup: hair-style +1F9B0 ; component # 🦰 E11.0 red hair +1F9B1 ; component # 🦱 E11.0 curly hair +1F9B3 ; component # 🦳 E11.0 white hair +1F9B2 ; component # 🦲 E11.0 bald + +# Component subtotal: 9 +# Component subtotal: 4 w/o modifiers + +# group: Animals & Nature + +# subgroup: animal-mammal +1F435 ; fully-qualified # 🐵 E0.6 monkey face +1F412 ; fully-qualified # 🐒 E0.6 monkey +1F98D ; fully-qualified # 🦍 E3.0 gorilla +1F9A7 ; fully-qualified # 🦧 E12.0 orangutan +1F436 ; fully-qualified # 🐶 E0.6 dog face +1F415 ; fully-qualified # 🐕 E0.7 dog +1F9AE ; fully-qualified # 🦮 E12.0 guide dog +1F415 200D 1F9BA ; fully-qualified # 🐕‍🦺 E12.0 service dog +1F429 ; fully-qualified # 🐩 E0.6 poodle +1F43A ; fully-qualified # 🐺 E0.6 wolf +1F98A ; fully-qualified # 🦊 E3.0 fox +1F99D ; fully-qualified # 🦝 E11.0 raccoon +1F431 ; fully-qualified # 🐱 E0.6 cat face +1F408 ; fully-qualified # 🐈 E0.7 cat +1F408 200D 2B1B ; fully-qualified # 🐈‍⬛ E13.0 black cat +1F981 ; fully-qualified # 🦁 E1.0 lion +1F42F ; fully-qualified # 🐯 E0.6 tiger face +1F405 ; fully-qualified # 🐅 E1.0 tiger +1F406 ; fully-qualified # 🐆 E1.0 leopard +1F434 ; fully-qualified # 🐴 E0.6 horse face +1FACE ; fully-qualified # 🫎 E15.0 moose +1FACF ; fully-qualified # 🫏 E15.0 donkey +1F40E ; fully-qualified # 🐎 E0.6 horse +1F984 ; fully-qualified # 🦄 E1.0 unicorn +1F993 ; fully-qualified # 🦓 E5.0 zebra +1F98C ; fully-qualified # 🦌 E3.0 deer +1F9AC ; fully-qualified # 🦬 E13.0 bison +1F42E ; fully-qualified # 🐮 E0.6 cow face +1F402 ; fully-qualified # 🐂 E1.0 ox +1F403 ; fully-qualified # 🐃 E1.0 water buffalo +1F404 ; fully-qualified # 🐄 E1.0 cow +1F437 ; fully-qualified # 🐷 E0.6 pig face +1F416 ; fully-qualified # 🐖 E1.0 pig +1F417 ; fully-qualified # 🐗 E0.6 boar +1F43D ; fully-qualified # 🐽 E0.6 pig nose +1F40F ; fully-qualified # 🐏 E1.0 ram +1F411 ; fully-qualified # 🐑 E0.6 ewe +1F410 ; fully-qualified # 🐐 E1.0 goat +1F42A ; fully-qualified # 🐪 E1.0 camel +1F42B ; fully-qualified # 🐫 E0.6 two-hump camel +1F999 ; fully-qualified # 🦙 E11.0 llama +1F992 ; fully-qualified # 🦒 E5.0 giraffe +1F418 ; fully-qualified # 🐘 E0.6 elephant +1F9A3 ; fully-qualified # 🦣 E13.0 mammoth +1F98F ; fully-qualified # 🦏 E3.0 rhinoceros +1F99B ; fully-qualified # 🦛 E11.0 hippopotamus +1F42D ; fully-qualified # 🐭 E0.6 mouse face +1F401 ; fully-qualified # 🐁 E1.0 mouse +1F400 ; fully-qualified # 🐀 E1.0 rat +1F439 ; fully-qualified # 🐹 E0.6 hamster +1F430 ; fully-qualified # 🐰 E0.6 rabbit face +1F407 ; fully-qualified # 🐇 E1.0 rabbit +1F43F FE0F ; fully-qualified # 🐿️ E0.7 chipmunk +1F43F ; unqualified # 🐿 E0.7 chipmunk +1F9AB ; fully-qualified # 🦫 E13.0 beaver +1F994 ; fully-qualified # 🦔 E5.0 hedgehog +1F987 ; fully-qualified # 🦇 E3.0 bat +1F43B ; fully-qualified # 🐻 E0.6 bear +1F43B 200D 2744 FE0F ; fully-qualified # 🐻‍❄️ E13.0 polar bear +1F43B 200D 2744 ; minimally-qualified # 🐻‍❄ E13.0 polar bear +1F428 ; fully-qualified # 🐨 E0.6 koala +1F43C ; fully-qualified # 🐼 E0.6 panda +1F9A5 ; fully-qualified # 🦥 E12.0 sloth +1F9A6 ; fully-qualified # 🦦 E12.0 otter +1F9A8 ; fully-qualified # 🦨 E12.0 skunk +1F998 ; fully-qualified # 🦘 E11.0 kangaroo +1F9A1 ; fully-qualified # 🦡 E11.0 badger +1F43E ; fully-qualified # 🐾 E0.6 paw prints + +# subgroup: animal-bird +1F983 ; fully-qualified # 🦃 E1.0 turkey +1F414 ; fully-qualified # 🐔 E0.6 chicken +1F413 ; fully-qualified # 🐓 E1.0 rooster +1F423 ; fully-qualified # 🐣 E0.6 hatching chick +1F424 ; fully-qualified # 🐤 E0.6 baby chick +1F425 ; fully-qualified # 🐥 E0.6 front-facing baby chick +1F426 ; fully-qualified # 🐦 E0.6 bird +1F427 ; fully-qualified # 🐧 E0.6 penguin +1F54A FE0F ; fully-qualified # 🕊️ E0.7 dove +1F54A ; unqualified # 🕊 E0.7 dove +1F985 ; fully-qualified # 🦅 E3.0 eagle +1F986 ; fully-qualified # 🦆 E3.0 duck +1F9A2 ; fully-qualified # 🦢 E11.0 swan +1F989 ; fully-qualified # 🦉 E3.0 owl +1F9A4 ; fully-qualified # 🦤 E13.0 dodo +1FAB6 ; fully-qualified # 🪶 E13.0 feather +1F9A9 ; fully-qualified # 🦩 E12.0 flamingo +1F99A ; fully-qualified # 🦚 E11.0 peacock +1F99C ; fully-qualified # 🦜 E11.0 parrot +1FABD ; fully-qualified # 🪽 E15.0 wing +1F426 200D 2B1B ; fully-qualified # 🐦‍⬛ E15.0 black bird +1FABF ; fully-qualified # 🪿 E15.0 goose + +# subgroup: animal-amphibian +1F438 ; fully-qualified # 🐸 E0.6 frog + +# subgroup: animal-reptile +1F40A ; fully-qualified # 🐊 E1.0 crocodile +1F422 ; fully-qualified # 🐢 E0.6 turtle +1F98E ; fully-qualified # 🦎 E3.0 lizard +1F40D ; fully-qualified # 🐍 E0.6 snake +1F432 ; fully-qualified # 🐲 E0.6 dragon face +1F409 ; fully-qualified # 🐉 E1.0 dragon +1F995 ; fully-qualified # 🦕 E5.0 sauropod +1F996 ; fully-qualified # 🦖 E5.0 T-Rex + +# subgroup: animal-marine +1F433 ; fully-qualified # 🐳 E0.6 spouting whale +1F40B ; fully-qualified # 🐋 E1.0 whale +1F42C ; fully-qualified # 🐬 E0.6 dolphin +1F9AD ; fully-qualified # 🦭 E13.0 seal +1F41F ; fully-qualified # 🐟 E0.6 fish +1F420 ; fully-qualified # 🐠 E0.6 tropical fish +1F421 ; fully-qualified # 🐡 E0.6 blowfish +1F988 ; fully-qualified # 🦈 E3.0 shark +1F419 ; fully-qualified # 🐙 E0.6 octopus +1F41A ; fully-qualified # 🐚 E0.6 spiral shell +1FAB8 ; fully-qualified # 🪸 E14.0 coral +1FABC ; fully-qualified # 🪼 E15.0 jellyfish + +# subgroup: animal-bug +1F40C ; fully-qualified # 🐌 E0.6 snail +1F98B ; fully-qualified # 🦋 E3.0 butterfly +1F41B ; fully-qualified # 🐛 E0.6 bug +1F41C ; fully-qualified # 🐜 E0.6 ant +1F41D ; fully-qualified # 🐝 E0.6 honeybee +1FAB2 ; fully-qualified # 🪲 E13.0 beetle +1F41E ; fully-qualified # 🐞 E0.6 lady beetle +1F997 ; fully-qualified # 🦗 E5.0 cricket +1FAB3 ; fully-qualified # 🪳 E13.0 cockroach +1F577 FE0F ; fully-qualified # 🕷️ E0.7 spider +1F577 ; unqualified # 🕷 E0.7 spider +1F578 FE0F ; fully-qualified # 🕸️ E0.7 spider web +1F578 ; unqualified # 🕸 E0.7 spider web +1F982 ; fully-qualified # 🦂 E1.0 scorpion +1F99F ; fully-qualified # 🦟 E11.0 mosquito +1FAB0 ; fully-qualified # 🪰 E13.0 fly +1FAB1 ; fully-qualified # 🪱 E13.0 worm +1F9A0 ; fully-qualified # 🦠 E11.0 microbe + +# subgroup: plant-flower +1F490 ; fully-qualified # 💐 E0.6 bouquet +1F338 ; fully-qualified # 🌸 E0.6 cherry blossom +1F4AE ; fully-qualified # 💮 E0.6 white flower +1FAB7 ; fully-qualified # 🪷 E14.0 lotus +1F3F5 FE0F ; fully-qualified # 🏵️ E0.7 rosette +1F3F5 ; unqualified # 🏵 E0.7 rosette +1F339 ; fully-qualified # 🌹 E0.6 rose +1F940 ; fully-qualified # 🥀 E3.0 wilted flower +1F33A ; fully-qualified # 🌺 E0.6 hibiscus +1F33B ; fully-qualified # 🌻 E0.6 sunflower +1F33C ; fully-qualified # 🌼 E0.6 blossom +1F337 ; fully-qualified # 🌷 E0.6 tulip +1FABB ; fully-qualified # 🪻 E15.0 hyacinth + +# subgroup: plant-other +1F331 ; fully-qualified # 🌱 E0.6 seedling +1FAB4 ; fully-qualified # 🪴 E13.0 potted plant +1F332 ; fully-qualified # 🌲 E1.0 evergreen tree +1F333 ; fully-qualified # 🌳 E1.0 deciduous tree +1F334 ; fully-qualified # 🌴 E0.6 palm tree +1F335 ; fully-qualified # 🌵 E0.6 cactus +1F33E ; fully-qualified # 🌾 E0.6 sheaf of rice +1F33F ; fully-qualified # 🌿 E0.6 herb +2618 FE0F ; fully-qualified # ☘️ E1.0 shamrock +2618 ; unqualified # ☘ E1.0 shamrock +1F340 ; fully-qualified # 🍀 E0.6 four leaf clover +1F341 ; fully-qualified # 🍁 E0.6 maple leaf +1F342 ; fully-qualified # 🍂 E0.6 fallen leaf +1F343 ; fully-qualified # 🍃 E0.6 leaf fluttering in wind +1FAB9 ; fully-qualified # 🪹 E14.0 empty nest +1FABA ; fully-qualified # 🪺 E14.0 nest with eggs +1F344 ; fully-qualified # 🍄 E0.6 mushroom + +# Animals & Nature subtotal: 159 +# Animals & Nature subtotal: 159 w/o modifiers + +# group: Food & Drink + +# subgroup: food-fruit +1F347 ; fully-qualified # 🍇 E0.6 grapes +1F348 ; fully-qualified # 🍈 E0.6 melon +1F349 ; fully-qualified # 🍉 E0.6 watermelon +1F34A ; fully-qualified # 🍊 E0.6 tangerine +1F34B ; fully-qualified # 🍋 E1.0 lemon +1F34C ; fully-qualified # 🍌 E0.6 banana +1F34D ; fully-qualified # 🍍 E0.6 pineapple +1F96D ; fully-qualified # 🥭 E11.0 mango +1F34E ; fully-qualified # 🍎 E0.6 red apple +1F34F ; fully-qualified # 🍏 E0.6 green apple +1F350 ; fully-qualified # 🍐 E1.0 pear +1F351 ; fully-qualified # 🍑 E0.6 peach +1F352 ; fully-qualified # 🍒 E0.6 cherries +1F353 ; fully-qualified # 🍓 E0.6 strawberry +1FAD0 ; fully-qualified # 🫐 E13.0 blueberries +1F95D ; fully-qualified # 🥝 E3.0 kiwi fruit +1F345 ; fully-qualified # 🍅 E0.6 tomato +1FAD2 ; fully-qualified # 🫒 E13.0 olive +1F965 ; fully-qualified # 🥥 E5.0 coconut + +# subgroup: food-vegetable +1F951 ; fully-qualified # 🥑 E3.0 avocado +1F346 ; fully-qualified # 🍆 E0.6 eggplant +1F954 ; fully-qualified # 🥔 E3.0 potato +1F955 ; fully-qualified # 🥕 E3.0 carrot +1F33D ; fully-qualified # 🌽 E0.6 ear of corn +1F336 FE0F ; fully-qualified # 🌶️ E0.7 hot pepper +1F336 ; unqualified # 🌶 E0.7 hot pepper +1FAD1 ; fully-qualified # 🫑 E13.0 bell pepper +1F952 ; fully-qualified # 🥒 E3.0 cucumber +1F96C ; fully-qualified # 🥬 E11.0 leafy green +1F966 ; fully-qualified # 🥦 E5.0 broccoli +1F9C4 ; fully-qualified # 🧄 E12.0 garlic +1F9C5 ; fully-qualified # 🧅 E12.0 onion +1F95C ; fully-qualified # 🥜 E3.0 peanuts +1FAD8 ; fully-qualified # 🫘 E14.0 beans +1F330 ; fully-qualified # 🌰 E0.6 chestnut +1FADA ; fully-qualified # 🫚 E15.0 ginger root +1FADB ; fully-qualified # 🫛 E15.0 pea pod + +# subgroup: food-prepared +1F35E ; fully-qualified # 🍞 E0.6 bread +1F950 ; fully-qualified # 🥐 E3.0 croissant +1F956 ; fully-qualified # 🥖 E3.0 baguette bread +1FAD3 ; fully-qualified # 🫓 E13.0 flatbread +1F968 ; fully-qualified # 🥨 E5.0 pretzel +1F96F ; fully-qualified # 🥯 E11.0 bagel +1F95E ; fully-qualified # 🥞 E3.0 pancakes +1F9C7 ; fully-qualified # 🧇 E12.0 waffle +1F9C0 ; fully-qualified # 🧀 E1.0 cheese wedge +1F356 ; fully-qualified # 🍖 E0.6 meat on bone +1F357 ; fully-qualified # 🍗 E0.6 poultry leg +1F969 ; fully-qualified # 🥩 E5.0 cut of meat +1F953 ; fully-qualified # 🥓 E3.0 bacon +1F354 ; fully-qualified # 🍔 E0.6 hamburger +1F35F ; fully-qualified # 🍟 E0.6 french fries +1F355 ; fully-qualified # 🍕 E0.6 pizza +1F32D ; fully-qualified # 🌭 E1.0 hot dog +1F96A ; fully-qualified # 🥪 E5.0 sandwich +1F32E ; fully-qualified # 🌮 E1.0 taco +1F32F ; fully-qualified # 🌯 E1.0 burrito +1FAD4 ; fully-qualified # 🫔 E13.0 tamale +1F959 ; fully-qualified # 🥙 E3.0 stuffed flatbread +1F9C6 ; fully-qualified # 🧆 E12.0 falafel +1F95A ; fully-qualified # 🥚 E3.0 egg +1F373 ; fully-qualified # 🍳 E0.6 cooking +1F958 ; fully-qualified # 🥘 E3.0 shallow pan of food +1F372 ; fully-qualified # 🍲 E0.6 pot of food +1FAD5 ; fully-qualified # 🫕 E13.0 fondue +1F963 ; fully-qualified # 🥣 E5.0 bowl with spoon +1F957 ; fully-qualified # 🥗 E3.0 green salad +1F37F ; fully-qualified # 🍿 E1.0 popcorn +1F9C8 ; fully-qualified # 🧈 E12.0 butter +1F9C2 ; fully-qualified # 🧂 E11.0 salt +1F96B ; fully-qualified # 🥫 E5.0 canned food + +# subgroup: food-asian +1F371 ; fully-qualified # 🍱 E0.6 bento box +1F358 ; fully-qualified # 🍘 E0.6 rice cracker +1F359 ; fully-qualified # 🍙 E0.6 rice ball +1F35A ; fully-qualified # 🍚 E0.6 cooked rice +1F35B ; fully-qualified # 🍛 E0.6 curry rice +1F35C ; fully-qualified # 🍜 E0.6 steaming bowl +1F35D ; fully-qualified # 🍝 E0.6 spaghetti +1F360 ; fully-qualified # 🍠 E0.6 roasted sweet potato +1F362 ; fully-qualified # 🍢 E0.6 oden +1F363 ; fully-qualified # 🍣 E0.6 sushi +1F364 ; fully-qualified # 🍤 E0.6 fried shrimp +1F365 ; fully-qualified # 🍥 E0.6 fish cake with swirl +1F96E ; fully-qualified # 🥮 E11.0 moon cake +1F361 ; fully-qualified # 🍡 E0.6 dango +1F95F ; fully-qualified # 🥟 E5.0 dumpling +1F960 ; fully-qualified # 🥠 E5.0 fortune cookie +1F961 ; fully-qualified # 🥡 E5.0 takeout box + +# subgroup: food-marine +1F980 ; fully-qualified # 🦀 E1.0 crab +1F99E ; fully-qualified # 🦞 E11.0 lobster +1F990 ; fully-qualified # 🦐 E3.0 shrimp +1F991 ; fully-qualified # 🦑 E3.0 squid +1F9AA ; fully-qualified # 🦪 E12.0 oyster + +# subgroup: food-sweet +1F366 ; fully-qualified # 🍦 E0.6 soft ice cream +1F367 ; fully-qualified # 🍧 E0.6 shaved ice +1F368 ; fully-qualified # 🍨 E0.6 ice cream +1F369 ; fully-qualified # 🍩 E0.6 doughnut +1F36A ; fully-qualified # 🍪 E0.6 cookie +1F382 ; fully-qualified # 🎂 E0.6 birthday cake +1F370 ; fully-qualified # 🍰 E0.6 shortcake +1F9C1 ; fully-qualified # 🧁 E11.0 cupcake +1F967 ; fully-qualified # 🥧 E5.0 pie +1F36B ; fully-qualified # 🍫 E0.6 chocolate bar +1F36C ; fully-qualified # 🍬 E0.6 candy +1F36D ; fully-qualified # 🍭 E0.6 lollipop +1F36E ; fully-qualified # 🍮 E0.6 custard +1F36F ; fully-qualified # 🍯 E0.6 honey pot + +# subgroup: drink +1F37C ; fully-qualified # 🍼 E1.0 baby bottle +1F95B ; fully-qualified # 🥛 E3.0 glass of milk +2615 ; fully-qualified # ☕ E0.6 hot beverage +1FAD6 ; fully-qualified # 🫖 E13.0 teapot +1F375 ; fully-qualified # 🍵 E0.6 teacup without handle +1F376 ; fully-qualified # 🍶 E0.6 sake +1F37E ; fully-qualified # 🍾 E1.0 bottle with popping cork +1F377 ; fully-qualified # 🍷 E0.6 wine glass +1F378 ; fully-qualified # 🍸 E0.6 cocktail glass +1F379 ; fully-qualified # 🍹 E0.6 tropical drink +1F37A ; fully-qualified # 🍺 E0.6 beer mug +1F37B ; fully-qualified # 🍻 E0.6 clinking beer mugs +1F942 ; fully-qualified # 🥂 E3.0 clinking glasses +1F943 ; fully-qualified # 🥃 E3.0 tumbler glass +1FAD7 ; fully-qualified # 🫗 E14.0 pouring liquid +1F964 ; fully-qualified # 🥤 E5.0 cup with straw +1F9CB ; fully-qualified # 🧋 E13.0 bubble tea +1F9C3 ; fully-qualified # 🧃 E12.0 beverage box +1F9C9 ; fully-qualified # 🧉 E12.0 mate +1F9CA ; fully-qualified # 🧊 E12.0 ice + +# subgroup: dishware +1F962 ; fully-qualified # 🥢 E5.0 chopsticks +1F37D FE0F ; fully-qualified # 🍽️ E0.7 fork and knife with plate +1F37D ; unqualified # 🍽 E0.7 fork and knife with plate +1F374 ; fully-qualified # 🍴 E0.6 fork and knife +1F944 ; fully-qualified # 🥄 E3.0 spoon +1F52A ; fully-qualified # 🔪 E0.6 kitchen knife +1FAD9 ; fully-qualified # 🫙 E14.0 jar +1F3FA ; fully-qualified # 🏺 E1.0 amphora + +# Food & Drink subtotal: 135 +# Food & Drink subtotal: 135 w/o modifiers + +# group: Travel & Places + +# subgroup: place-map +1F30D ; fully-qualified # 🌍 E0.7 globe showing Europe-Africa +1F30E ; fully-qualified # 🌎 E0.7 globe showing Americas +1F30F ; fully-qualified # 🌏 E0.6 globe showing Asia-Australia +1F310 ; fully-qualified # 🌐 E1.0 globe with meridians +1F5FA FE0F ; fully-qualified # 🗺️ E0.7 world map +1F5FA ; unqualified # 🗺 E0.7 world map +1F5FE ; fully-qualified # 🗾 E0.6 map of Japan +1F9ED ; fully-qualified # 🧭 E11.0 compass + +# subgroup: place-geographic +1F3D4 FE0F ; fully-qualified # 🏔️ E0.7 snow-capped mountain +1F3D4 ; unqualified # 🏔 E0.7 snow-capped mountain +26F0 FE0F ; fully-qualified # ⛰️ E0.7 mountain +26F0 ; unqualified # ⛰ E0.7 mountain +1F30B ; fully-qualified # 🌋 E0.6 volcano +1F5FB ; fully-qualified # 🗻 E0.6 mount fuji +1F3D5 FE0F ; fully-qualified # 🏕️ E0.7 camping +1F3D5 ; unqualified # 🏕 E0.7 camping +1F3D6 FE0F ; fully-qualified # 🏖️ E0.7 beach with umbrella +1F3D6 ; unqualified # 🏖 E0.7 beach with umbrella +1F3DC FE0F ; fully-qualified # 🏜️ E0.7 desert +1F3DC ; unqualified # 🏜 E0.7 desert +1F3DD FE0F ; fully-qualified # 🏝️ E0.7 desert island +1F3DD ; unqualified # 🏝 E0.7 desert island +1F3DE FE0F ; fully-qualified # 🏞️ E0.7 national park +1F3DE ; unqualified # 🏞 E0.7 national park + +# subgroup: place-building +1F3DF FE0F ; fully-qualified # 🏟️ E0.7 stadium +1F3DF ; unqualified # 🏟 E0.7 stadium +1F3DB FE0F ; fully-qualified # 🏛️ E0.7 classical building +1F3DB ; unqualified # 🏛 E0.7 classical building +1F3D7 FE0F ; fully-qualified # 🏗️ E0.7 building construction +1F3D7 ; unqualified # 🏗 E0.7 building construction +1F9F1 ; fully-qualified # 🧱 E11.0 brick +1FAA8 ; fully-qualified # 🪨 E13.0 rock +1FAB5 ; fully-qualified # 🪵 E13.0 wood +1F6D6 ; fully-qualified # 🛖 E13.0 hut +1F3D8 FE0F ; fully-qualified # 🏘️ E0.7 houses +1F3D8 ; unqualified # 🏘 E0.7 houses +1F3DA FE0F ; fully-qualified # 🏚️ E0.7 derelict house +1F3DA ; unqualified # 🏚 E0.7 derelict house +1F3E0 ; fully-qualified # 🏠 E0.6 house +1F3E1 ; fully-qualified # 🏡 E0.6 house with garden +1F3E2 ; fully-qualified # 🏢 E0.6 office building +1F3E3 ; fully-qualified # 🏣 E0.6 Japanese post office +1F3E4 ; fully-qualified # 🏤 E1.0 post office +1F3E5 ; fully-qualified # 🏥 E0.6 hospital +1F3E6 ; fully-qualified # 🏦 E0.6 bank +1F3E8 ; fully-qualified # 🏨 E0.6 hotel +1F3E9 ; fully-qualified # 🏩 E0.6 love hotel +1F3EA ; fully-qualified # 🏪 E0.6 convenience store +1F3EB ; fully-qualified # 🏫 E0.6 school +1F3EC ; fully-qualified # 🏬 E0.6 department store +1F3ED ; fully-qualified # 🏭 E0.6 factory +1F3EF ; fully-qualified # 🏯 E0.6 Japanese castle +1F3F0 ; fully-qualified # 🏰 E0.6 castle +1F492 ; fully-qualified # 💒 E0.6 wedding +1F5FC ; fully-qualified # 🗼 E0.6 Tokyo tower +1F5FD ; fully-qualified # 🗽 E0.6 Statue of Liberty + +# subgroup: place-religious +26EA ; fully-qualified # ⛪ E0.6 church +1F54C ; fully-qualified # 🕌 E1.0 mosque +1F6D5 ; fully-qualified # 🛕 E12.0 hindu temple +1F54D ; fully-qualified # 🕍 E1.0 synagogue +26E9 FE0F ; fully-qualified # ⛩️ E0.7 shinto shrine +26E9 ; unqualified # ⛩ E0.7 shinto shrine +1F54B ; fully-qualified # 🕋 E1.0 kaaba + +# subgroup: place-other +26F2 ; fully-qualified # ⛲ E0.6 fountain +26FA ; fully-qualified # ⛺ E0.6 tent +1F301 ; fully-qualified # 🌁 E0.6 foggy +1F303 ; fully-qualified # 🌃 E0.6 night with stars +1F3D9 FE0F ; fully-qualified # 🏙️ E0.7 cityscape +1F3D9 ; unqualified # 🏙 E0.7 cityscape +1F304 ; fully-qualified # 🌄 E0.6 sunrise over mountains +1F305 ; fully-qualified # 🌅 E0.6 sunrise +1F306 ; fully-qualified # 🌆 E0.6 cityscape at dusk +1F307 ; fully-qualified # 🌇 E0.6 sunset +1F309 ; fully-qualified # 🌉 E0.6 bridge at night +2668 FE0F ; fully-qualified # ♨️ E0.6 hot springs +2668 ; unqualified # ♨ E0.6 hot springs +1F3A0 ; fully-qualified # 🎠 E0.6 carousel horse +1F6DD ; fully-qualified # 🛝 E14.0 playground slide +1F3A1 ; fully-qualified # 🎡 E0.6 ferris wheel +1F3A2 ; fully-qualified # 🎢 E0.6 roller coaster +1F488 ; fully-qualified # 💈 E0.6 barber pole +1F3AA ; fully-qualified # 🎪 E0.6 circus tent + +# subgroup: transport-ground +1F682 ; fully-qualified # 🚂 E1.0 locomotive +1F683 ; fully-qualified # 🚃 E0.6 railway car +1F684 ; fully-qualified # 🚄 E0.6 high-speed train +1F685 ; fully-qualified # 🚅 E0.6 bullet train +1F686 ; fully-qualified # 🚆 E1.0 train +1F687 ; fully-qualified # 🚇 E0.6 metro +1F688 ; fully-qualified # 🚈 E1.0 light rail +1F689 ; fully-qualified # 🚉 E0.6 station +1F68A ; fully-qualified # 🚊 E1.0 tram +1F69D ; fully-qualified # 🚝 E1.0 monorail +1F69E ; fully-qualified # 🚞 E1.0 mountain railway +1F68B ; fully-qualified # 🚋 E1.0 tram car +1F68C ; fully-qualified # 🚌 E0.6 bus +1F68D ; fully-qualified # 🚍 E0.7 oncoming bus +1F68E ; fully-qualified # 🚎 E1.0 trolleybus +1F690 ; fully-qualified # 🚐 E1.0 minibus +1F691 ; fully-qualified # 🚑 E0.6 ambulance +1F692 ; fully-qualified # 🚒 E0.6 fire engine +1F693 ; fully-qualified # 🚓 E0.6 police car +1F694 ; fully-qualified # 🚔 E0.7 oncoming police car +1F695 ; fully-qualified # 🚕 E0.6 taxi +1F696 ; fully-qualified # 🚖 E1.0 oncoming taxi +1F697 ; fully-qualified # 🚗 E0.6 automobile +1F698 ; fully-qualified # 🚘 E0.7 oncoming automobile +1F699 ; fully-qualified # 🚙 E0.6 sport utility vehicle +1F6FB ; fully-qualified # 🛻 E13.0 pickup truck +1F69A ; fully-qualified # 🚚 E0.6 delivery truck +1F69B ; fully-qualified # 🚛 E1.0 articulated lorry +1F69C ; fully-qualified # 🚜 E1.0 tractor +1F3CE FE0F ; fully-qualified # 🏎️ E0.7 racing car +1F3CE ; unqualified # 🏎 E0.7 racing car +1F3CD FE0F ; fully-qualified # 🏍️ E0.7 motorcycle +1F3CD ; unqualified # 🏍 E0.7 motorcycle +1F6F5 ; fully-qualified # 🛵 E3.0 motor scooter +1F9BD ; fully-qualified # 🦽 E12.0 manual wheelchair +1F9BC ; fully-qualified # 🦼 E12.0 motorized wheelchair +1F6FA ; fully-qualified # 🛺 E12.0 auto rickshaw +1F6B2 ; fully-qualified # 🚲 E0.6 bicycle +1F6F4 ; fully-qualified # 🛴 E3.0 kick scooter +1F6F9 ; fully-qualified # 🛹 E11.0 skateboard +1F6FC ; fully-qualified # 🛼 E13.0 roller skate +1F68F ; fully-qualified # 🚏 E0.6 bus stop +1F6E3 FE0F ; fully-qualified # 🛣️ E0.7 motorway +1F6E3 ; unqualified # 🛣 E0.7 motorway +1F6E4 FE0F ; fully-qualified # 🛤️ E0.7 railway track +1F6E4 ; unqualified # 🛤 E0.7 railway track +1F6E2 FE0F ; fully-qualified # 🛢️ E0.7 oil drum +1F6E2 ; unqualified # 🛢 E0.7 oil drum +26FD ; fully-qualified # ⛽ E0.6 fuel pump +1F6DE ; fully-qualified # 🛞 E14.0 wheel +1F6A8 ; fully-qualified # 🚨 E0.6 police car light +1F6A5 ; fully-qualified # 🚥 E0.6 horizontal traffic light +1F6A6 ; fully-qualified # 🚦 E1.0 vertical traffic light +1F6D1 ; fully-qualified # 🛑 E3.0 stop sign +1F6A7 ; fully-qualified # 🚧 E0.6 construction + +# subgroup: transport-water +2693 ; fully-qualified # ⚓ E0.6 anchor +1F6DF ; fully-qualified # 🛟 E14.0 ring buoy +26F5 ; fully-qualified # ⛵ E0.6 sailboat +1F6F6 ; fully-qualified # 🛶 E3.0 canoe +1F6A4 ; fully-qualified # 🚤 E0.6 speedboat +1F6F3 FE0F ; fully-qualified # 🛳️ E0.7 passenger ship +1F6F3 ; unqualified # 🛳 E0.7 passenger ship +26F4 FE0F ; fully-qualified # ⛴️ E0.7 ferry +26F4 ; unqualified # ⛴ E0.7 ferry +1F6E5 FE0F ; fully-qualified # 🛥️ E0.7 motor boat +1F6E5 ; unqualified # 🛥 E0.7 motor boat +1F6A2 ; fully-qualified # 🚢 E0.6 ship + +# subgroup: transport-air +2708 FE0F ; fully-qualified # ✈️ E0.6 airplane +2708 ; unqualified # ✈ E0.6 airplane +1F6E9 FE0F ; fully-qualified # 🛩️ E0.7 small airplane +1F6E9 ; unqualified # 🛩 E0.7 small airplane +1F6EB ; fully-qualified # 🛫 E1.0 airplane departure +1F6EC ; fully-qualified # 🛬 E1.0 airplane arrival +1FA82 ; fully-qualified # 🪂 E12.0 parachute +1F4BA ; fully-qualified # 💺 E0.6 seat +1F681 ; fully-qualified # 🚁 E1.0 helicopter +1F69F ; fully-qualified # 🚟 E1.0 suspension railway +1F6A0 ; fully-qualified # 🚠 E1.0 mountain cableway +1F6A1 ; fully-qualified # 🚡 E1.0 aerial tramway +1F6F0 FE0F ; fully-qualified # 🛰️ E0.7 satellite +1F6F0 ; unqualified # 🛰 E0.7 satellite +1F680 ; fully-qualified # 🚀 E0.6 rocket +1F6F8 ; fully-qualified # 🛸 E5.0 flying saucer + +# subgroup: hotel +1F6CE FE0F ; fully-qualified # 🛎️ E0.7 bellhop bell +1F6CE ; unqualified # 🛎 E0.7 bellhop bell +1F9F3 ; fully-qualified # 🧳 E11.0 luggage + +# subgroup: time +231B ; fully-qualified # ⌛ E0.6 hourglass done +23F3 ; fully-qualified # ⏳ E0.6 hourglass not done +231A ; fully-qualified # ⌚ E0.6 watch +23F0 ; fully-qualified # ⏰ E0.6 alarm clock +23F1 FE0F ; fully-qualified # ⏱️ E1.0 stopwatch +23F1 ; unqualified # ⏱ E1.0 stopwatch +23F2 FE0F ; fully-qualified # ⏲️ E1.0 timer clock +23F2 ; unqualified # ⏲ E1.0 timer clock +1F570 FE0F ; fully-qualified # 🕰️ E0.7 mantelpiece clock +1F570 ; unqualified # 🕰 E0.7 mantelpiece clock +1F55B ; fully-qualified # 🕛 E0.6 twelve o’clock +1F567 ; fully-qualified # 🕧 E0.7 twelve-thirty +1F550 ; fully-qualified # 🕐 E0.6 one o’clock +1F55C ; fully-qualified # 🕜 E0.7 one-thirty +1F551 ; fully-qualified # 🕑 E0.6 two o’clock +1F55D ; fully-qualified # 🕝 E0.7 two-thirty +1F552 ; fully-qualified # 🕒 E0.6 three o’clock +1F55E ; fully-qualified # 🕞 E0.7 three-thirty +1F553 ; fully-qualified # 🕓 E0.6 four o’clock +1F55F ; fully-qualified # 🕟 E0.7 four-thirty +1F554 ; fully-qualified # 🕔 E0.6 five o’clock +1F560 ; fully-qualified # 🕠 E0.7 five-thirty +1F555 ; fully-qualified # 🕕 E0.6 six o’clock +1F561 ; fully-qualified # 🕡 E0.7 six-thirty +1F556 ; fully-qualified # 🕖 E0.6 seven o’clock +1F562 ; fully-qualified # 🕢 E0.7 seven-thirty +1F557 ; fully-qualified # 🕗 E0.6 eight o’clock +1F563 ; fully-qualified # 🕣 E0.7 eight-thirty +1F558 ; fully-qualified # 🕘 E0.6 nine o’clock +1F564 ; fully-qualified # 🕤 E0.7 nine-thirty +1F559 ; fully-qualified # 🕙 E0.6 ten o’clock +1F565 ; fully-qualified # 🕥 E0.7 ten-thirty +1F55A ; fully-qualified # 🕚 E0.6 eleven o’clock +1F566 ; fully-qualified # 🕦 E0.7 eleven-thirty + +# subgroup: sky & weather +1F311 ; fully-qualified # 🌑 E0.6 new moon +1F312 ; fully-qualified # 🌒 E1.0 waxing crescent moon +1F313 ; fully-qualified # 🌓 E0.6 first quarter moon +1F314 ; fully-qualified # 🌔 E0.6 waxing gibbous moon +1F315 ; fully-qualified # 🌕 E0.6 full moon +1F316 ; fully-qualified # 🌖 E1.0 waning gibbous moon +1F317 ; fully-qualified # 🌗 E1.0 last quarter moon +1F318 ; fully-qualified # 🌘 E1.0 waning crescent moon +1F319 ; fully-qualified # 🌙 E0.6 crescent moon +1F31A ; fully-qualified # 🌚 E1.0 new moon face +1F31B ; fully-qualified # 🌛 E0.6 first quarter moon face +1F31C ; fully-qualified # 🌜 E0.7 last quarter moon face +1F321 FE0F ; fully-qualified # 🌡️ E0.7 thermometer +1F321 ; unqualified # 🌡 E0.7 thermometer +2600 FE0F ; fully-qualified # ☀️ E0.6 sun +2600 ; unqualified # ☀ E0.6 sun +1F31D ; fully-qualified # 🌝 E1.0 full moon face +1F31E ; fully-qualified # 🌞 E1.0 sun with face +1FA90 ; fully-qualified # 🪐 E12.0 ringed planet +2B50 ; fully-qualified # ⭐ E0.6 star +1F31F ; fully-qualified # 🌟 E0.6 glowing star +1F320 ; fully-qualified # 🌠 E0.6 shooting star +1F30C ; fully-qualified # 🌌 E0.6 milky way +2601 FE0F ; fully-qualified # ☁️ E0.6 cloud +2601 ; unqualified # ☁ E0.6 cloud +26C5 ; fully-qualified # ⛅ E0.6 sun behind cloud +26C8 FE0F ; fully-qualified # ⛈️ E0.7 cloud with lightning and rain +26C8 ; unqualified # ⛈ E0.7 cloud with lightning and rain +1F324 FE0F ; fully-qualified # 🌤️ E0.7 sun behind small cloud +1F324 ; unqualified # 🌤 E0.7 sun behind small cloud +1F325 FE0F ; fully-qualified # 🌥️ E0.7 sun behind large cloud +1F325 ; unqualified # 🌥 E0.7 sun behind large cloud +1F326 FE0F ; fully-qualified # 🌦️ E0.7 sun behind rain cloud +1F326 ; unqualified # 🌦 E0.7 sun behind rain cloud +1F327 FE0F ; fully-qualified # 🌧️ E0.7 cloud with rain +1F327 ; unqualified # 🌧 E0.7 cloud with rain +1F328 FE0F ; fully-qualified # 🌨️ E0.7 cloud with snow +1F328 ; unqualified # 🌨 E0.7 cloud with snow +1F329 FE0F ; fully-qualified # 🌩️ E0.7 cloud with lightning +1F329 ; unqualified # 🌩 E0.7 cloud with lightning +1F32A FE0F ; fully-qualified # 🌪️ E0.7 tornado +1F32A ; unqualified # 🌪 E0.7 tornado +1F32B FE0F ; fully-qualified # 🌫️ E0.7 fog +1F32B ; unqualified # 🌫 E0.7 fog +1F32C FE0F ; fully-qualified # 🌬️ E0.7 wind face +1F32C ; unqualified # 🌬 E0.7 wind face +1F300 ; fully-qualified # 🌀 E0.6 cyclone +1F308 ; fully-qualified # 🌈 E0.6 rainbow +1F302 ; fully-qualified # 🌂 E0.6 closed umbrella +2602 FE0F ; fully-qualified # ☂️ E0.7 umbrella +2602 ; unqualified # ☂ E0.7 umbrella +2614 ; fully-qualified # ☔ E0.6 umbrella with rain drops +26F1 FE0F ; fully-qualified # ⛱️ E0.7 umbrella on ground +26F1 ; unqualified # ⛱ E0.7 umbrella on ground +26A1 ; fully-qualified # ⚡ E0.6 high voltage +2744 FE0F ; fully-qualified # ❄️ E0.6 snowflake +2744 ; unqualified # ❄ E0.6 snowflake +2603 FE0F ; fully-qualified # ☃️ E0.7 snowman +2603 ; unqualified # ☃ E0.7 snowman +26C4 ; fully-qualified # ⛄ E0.6 snowman without snow +2604 FE0F ; fully-qualified # ☄️ E1.0 comet +2604 ; unqualified # ☄ E1.0 comet +1F525 ; fully-qualified # 🔥 E0.6 fire +1F4A7 ; fully-qualified # 💧 E0.6 droplet +1F30A ; fully-qualified # 🌊 E0.6 water wave + +# Travel & Places subtotal: 267 +# Travel & Places subtotal: 267 w/o modifiers + +# group: Activities + +# subgroup: event +1F383 ; fully-qualified # 🎃 E0.6 jack-o-lantern +1F384 ; fully-qualified # 🎄 E0.6 Christmas tree +1F386 ; fully-qualified # 🎆 E0.6 fireworks +1F387 ; fully-qualified # 🎇 E0.6 sparkler +1F9E8 ; fully-qualified # 🧨 E11.0 firecracker +2728 ; fully-qualified # ✨ E0.6 sparkles +1F388 ; fully-qualified # 🎈 E0.6 balloon +1F389 ; fully-qualified # 🎉 E0.6 party popper +1F38A ; fully-qualified # 🎊 E0.6 confetti ball +1F38B ; fully-qualified # 🎋 E0.6 tanabata tree +1F38D ; fully-qualified # 🎍 E0.6 pine decoration +1F38E ; fully-qualified # 🎎 E0.6 Japanese dolls +1F38F ; fully-qualified # 🎏 E0.6 carp streamer +1F390 ; fully-qualified # 🎐 E0.6 wind chime +1F391 ; fully-qualified # 🎑 E0.6 moon viewing ceremony +1F9E7 ; fully-qualified # 🧧 E11.0 red envelope +1F380 ; fully-qualified # 🎀 E0.6 ribbon +1F381 ; fully-qualified # 🎁 E0.6 wrapped gift +1F397 FE0F ; fully-qualified # 🎗️ E0.7 reminder ribbon +1F397 ; unqualified # 🎗 E0.7 reminder ribbon +1F39F FE0F ; fully-qualified # 🎟️ E0.7 admission tickets +1F39F ; unqualified # 🎟 E0.7 admission tickets +1F3AB ; fully-qualified # 🎫 E0.6 ticket + +# subgroup: award-medal +1F396 FE0F ; fully-qualified # 🎖️ E0.7 military medal +1F396 ; unqualified # 🎖 E0.7 military medal +1F3C6 ; fully-qualified # 🏆 E0.6 trophy +1F3C5 ; fully-qualified # 🏅 E1.0 sports medal +1F947 ; fully-qualified # 🥇 E3.0 1st place medal +1F948 ; fully-qualified # 🥈 E3.0 2nd place medal +1F949 ; fully-qualified # 🥉 E3.0 3rd place medal + +# subgroup: sport +26BD ; fully-qualified # ⚽ E0.6 soccer ball +26BE ; fully-qualified # ⚾ E0.6 baseball +1F94E ; fully-qualified # 🥎 E11.0 softball +1F3C0 ; fully-qualified # 🏀 E0.6 basketball +1F3D0 ; fully-qualified # 🏐 E1.0 volleyball +1F3C8 ; fully-qualified # 🏈 E0.6 american football +1F3C9 ; fully-qualified # 🏉 E1.0 rugby football +1F3BE ; fully-qualified # 🎾 E0.6 tennis +1F94F ; fully-qualified # 🥏 E11.0 flying disc +1F3B3 ; fully-qualified # 🎳 E0.6 bowling +1F3CF ; fully-qualified # 🏏 E1.0 cricket game +1F3D1 ; fully-qualified # 🏑 E1.0 field hockey +1F3D2 ; fully-qualified # 🏒 E1.0 ice hockey +1F94D ; fully-qualified # 🥍 E11.0 lacrosse +1F3D3 ; fully-qualified # 🏓 E1.0 ping pong +1F3F8 ; fully-qualified # 🏸 E1.0 badminton +1F94A ; fully-qualified # 🥊 E3.0 boxing glove +1F94B ; fully-qualified # 🥋 E3.0 martial arts uniform +1F945 ; fully-qualified # 🥅 E3.0 goal net +26F3 ; fully-qualified # ⛳ E0.6 flag in hole +26F8 FE0F ; fully-qualified # ⛸️ E0.7 ice skate +26F8 ; unqualified # ⛸ E0.7 ice skate +1F3A3 ; fully-qualified # 🎣 E0.6 fishing pole +1F93F ; fully-qualified # 🤿 E12.0 diving mask +1F3BD ; fully-qualified # 🎽 E0.6 running shirt +1F3BF ; fully-qualified # 🎿 E0.6 skis +1F6F7 ; fully-qualified # 🛷 E5.0 sled +1F94C ; fully-qualified # 🥌 E5.0 curling stone + +# subgroup: game +1F3AF ; fully-qualified # 🎯 E0.6 bullseye +1FA80 ; fully-qualified # 🪀 E12.0 yo-yo +1FA81 ; fully-qualified # 🪁 E12.0 kite +1F52B ; fully-qualified # 🔫 E0.6 water pistol +1F3B1 ; fully-qualified # 🎱 E0.6 pool 8 ball +1F52E ; fully-qualified # 🔮 E0.6 crystal ball +1FA84 ; fully-qualified # 🪄 E13.0 magic wand +1F3AE ; fully-qualified # 🎮 E0.6 video game +1F579 FE0F ; fully-qualified # 🕹️ E0.7 joystick +1F579 ; unqualified # 🕹 E0.7 joystick +1F3B0 ; fully-qualified # 🎰 E0.6 slot machine +1F3B2 ; fully-qualified # 🎲 E0.6 game die +1F9E9 ; fully-qualified # 🧩 E11.0 puzzle piece +1F9F8 ; fully-qualified # 🧸 E11.0 teddy bear +1FA85 ; fully-qualified # 🪅 E13.0 piñata +1FAA9 ; fully-qualified # 🪩 E14.0 mirror ball +1FA86 ; fully-qualified # 🪆 E13.0 nesting dolls +2660 FE0F ; fully-qualified # ♠️ E0.6 spade suit +2660 ; unqualified # ♠ E0.6 spade suit +2665 FE0F ; fully-qualified # ♥️ E0.6 heart suit +2665 ; unqualified # ♥ E0.6 heart suit +2666 FE0F ; fully-qualified # ♦️ E0.6 diamond suit +2666 ; unqualified # ♦ E0.6 diamond suit +2663 FE0F ; fully-qualified # ♣️ E0.6 club suit +2663 ; unqualified # ♣ E0.6 club suit +265F FE0F ; fully-qualified # ♟️ E11.0 chess pawn +265F ; unqualified # ♟ E11.0 chess pawn +1F0CF ; fully-qualified # 🃏 E0.6 joker +1F004 ; fully-qualified # 🀄 E0.6 mahjong red dragon +1F3B4 ; fully-qualified # 🎴 E0.6 flower playing cards + +# subgroup: arts & crafts +1F3AD ; fully-qualified # 🎭 E0.6 performing arts +1F5BC FE0F ; fully-qualified # 🖼️ E0.7 framed picture +1F5BC ; unqualified # 🖼 E0.7 framed picture +1F3A8 ; fully-qualified # 🎨 E0.6 artist palette +1F9F5 ; fully-qualified # 🧵 E11.0 thread +1FAA1 ; fully-qualified # 🪡 E13.0 sewing needle +1F9F6 ; fully-qualified # 🧶 E11.0 yarn +1FAA2 ; fully-qualified # 🪢 E13.0 knot + +# Activities subtotal: 96 +# Activities subtotal: 96 w/o modifiers + +# group: Objects + +# subgroup: clothing +1F453 ; fully-qualified # 👓 E0.6 glasses +1F576 FE0F ; fully-qualified # 🕶️ E0.7 sunglasses +1F576 ; unqualified # 🕶 E0.7 sunglasses +1F97D ; fully-qualified # 🥽 E11.0 goggles +1F97C ; fully-qualified # 🥼 E11.0 lab coat +1F9BA ; fully-qualified # 🦺 E12.0 safety vest +1F454 ; fully-qualified # 👔 E0.6 necktie +1F455 ; fully-qualified # 👕 E0.6 t-shirt +1F456 ; fully-qualified # 👖 E0.6 jeans +1F9E3 ; fully-qualified # 🧣 E5.0 scarf +1F9E4 ; fully-qualified # 🧤 E5.0 gloves +1F9E5 ; fully-qualified # 🧥 E5.0 coat +1F9E6 ; fully-qualified # 🧦 E5.0 socks +1F457 ; fully-qualified # 👗 E0.6 dress +1F458 ; fully-qualified # 👘 E0.6 kimono +1F97B ; fully-qualified # 🥻 E12.0 sari +1FA71 ; fully-qualified # 🩱 E12.0 one-piece swimsuit +1FA72 ; fully-qualified # 🩲 E12.0 briefs +1FA73 ; fully-qualified # 🩳 E12.0 shorts +1F459 ; fully-qualified # 👙 E0.6 bikini +1F45A ; fully-qualified # 👚 E0.6 woman’s clothes +1FAAD ; fully-qualified # 🪭 E15.0 folding hand fan +1F45B ; fully-qualified # 👛 E0.6 purse +1F45C ; fully-qualified # 👜 E0.6 handbag +1F45D ; fully-qualified # 👝 E0.6 clutch bag +1F6CD FE0F ; fully-qualified # 🛍️ E0.7 shopping bags +1F6CD ; unqualified # 🛍 E0.7 shopping bags +1F392 ; fully-qualified # 🎒 E0.6 backpack +1FA74 ; fully-qualified # 🩴 E13.0 thong sandal +1F45E ; fully-qualified # 👞 E0.6 man’s shoe +1F45F ; fully-qualified # 👟 E0.6 running shoe +1F97E ; fully-qualified # 🥾 E11.0 hiking boot +1F97F ; fully-qualified # 🥿 E11.0 flat shoe +1F460 ; fully-qualified # 👠 E0.6 high-heeled shoe +1F461 ; fully-qualified # 👡 E0.6 woman’s sandal +1FA70 ; fully-qualified # 🩰 E12.0 ballet shoes +1F462 ; fully-qualified # 👢 E0.6 woman’s boot +1FAAE ; fully-qualified # 🪮 E15.0 hair pick +1F451 ; fully-qualified # 👑 E0.6 crown +1F452 ; fully-qualified # 👒 E0.6 woman’s hat +1F3A9 ; fully-qualified # 🎩 E0.6 top hat +1F393 ; fully-qualified # 🎓 E0.6 graduation cap +1F9E2 ; fully-qualified # 🧢 E5.0 billed cap +1FA96 ; fully-qualified # 🪖 E13.0 military helmet +26D1 FE0F ; fully-qualified # ⛑️ E0.7 rescue worker’s helmet +26D1 ; unqualified # ⛑ E0.7 rescue worker’s helmet +1F4FF ; fully-qualified # 📿 E1.0 prayer beads +1F484 ; fully-qualified # 💄 E0.6 lipstick +1F48D ; fully-qualified # 💍 E0.6 ring +1F48E ; fully-qualified # 💎 E0.6 gem stone + +# subgroup: sound +1F507 ; fully-qualified # 🔇 E1.0 muted speaker +1F508 ; fully-qualified # 🔈 E0.7 speaker low volume +1F509 ; fully-qualified # 🔉 E1.0 speaker medium volume +1F50A ; fully-qualified # 🔊 E0.6 speaker high volume +1F4E2 ; fully-qualified # 📢 E0.6 loudspeaker +1F4E3 ; fully-qualified # 📣 E0.6 megaphone +1F4EF ; fully-qualified # 📯 E1.0 postal horn +1F514 ; fully-qualified # 🔔 E0.6 bell +1F515 ; fully-qualified # 🔕 E1.0 bell with slash + +# subgroup: music +1F3BC ; fully-qualified # 🎼 E0.6 musical score +1F3B5 ; fully-qualified # 🎵 E0.6 musical note +1F3B6 ; fully-qualified # 🎶 E0.6 musical notes +1F399 FE0F ; fully-qualified # 🎙️ E0.7 studio microphone +1F399 ; unqualified # 🎙 E0.7 studio microphone +1F39A FE0F ; fully-qualified # 🎚️ E0.7 level slider +1F39A ; unqualified # 🎚 E0.7 level slider +1F39B FE0F ; fully-qualified # 🎛️ E0.7 control knobs +1F39B ; unqualified # 🎛 E0.7 control knobs +1F3A4 ; fully-qualified # 🎤 E0.6 microphone +1F3A7 ; fully-qualified # 🎧 E0.6 headphone +1F4FB ; fully-qualified # 📻 E0.6 radio + +# subgroup: musical-instrument +1F3B7 ; fully-qualified # 🎷 E0.6 saxophone +1FA97 ; fully-qualified # 🪗 E13.0 accordion +1F3B8 ; fully-qualified # 🎸 E0.6 guitar +1F3B9 ; fully-qualified # 🎹 E0.6 musical keyboard +1F3BA ; fully-qualified # 🎺 E0.6 trumpet +1F3BB ; fully-qualified # 🎻 E0.6 violin +1FA95 ; fully-qualified # 🪕 E12.0 banjo +1F941 ; fully-qualified # 🥁 E3.0 drum +1FA98 ; fully-qualified # 🪘 E13.0 long drum +1FA87 ; fully-qualified # 🪇 E15.0 maracas +1FA88 ; fully-qualified # 🪈 E15.0 flute + +# subgroup: phone +1F4F1 ; fully-qualified # 📱 E0.6 mobile phone +1F4F2 ; fully-qualified # 📲 E0.6 mobile phone with arrow +260E FE0F ; fully-qualified # ☎️ E0.6 telephone +260E ; unqualified # ☎ E0.6 telephone +1F4DE ; fully-qualified # 📞 E0.6 telephone receiver +1F4DF ; fully-qualified # 📟 E0.6 pager +1F4E0 ; fully-qualified # 📠 E0.6 fax machine + +# subgroup: computer +1F50B ; fully-qualified # 🔋 E0.6 battery +1FAAB ; fully-qualified # 🪫 E14.0 low battery +1F50C ; fully-qualified # 🔌 E0.6 electric plug +1F4BB ; fully-qualified # 💻 E0.6 laptop +1F5A5 FE0F ; fully-qualified # 🖥️ E0.7 desktop computer +1F5A5 ; unqualified # 🖥 E0.7 desktop computer +1F5A8 FE0F ; fully-qualified # 🖨️ E0.7 printer +1F5A8 ; unqualified # 🖨 E0.7 printer +2328 FE0F ; fully-qualified # ⌨️ E1.0 keyboard +2328 ; unqualified # ⌨ E1.0 keyboard +1F5B1 FE0F ; fully-qualified # 🖱️ E0.7 computer mouse +1F5B1 ; unqualified # 🖱 E0.7 computer mouse +1F5B2 FE0F ; fully-qualified # 🖲️ E0.7 trackball +1F5B2 ; unqualified # 🖲 E0.7 trackball +1F4BD ; fully-qualified # 💽 E0.6 computer disk +1F4BE ; fully-qualified # 💾 E0.6 floppy disk +1F4BF ; fully-qualified # 💿 E0.6 optical disk +1F4C0 ; fully-qualified # 📀 E0.6 dvd +1F9EE ; fully-qualified # 🧮 E11.0 abacus + +# subgroup: light & video +1F3A5 ; fully-qualified # 🎥 E0.6 movie camera +1F39E FE0F ; fully-qualified # 🎞️ E0.7 film frames +1F39E ; unqualified # 🎞 E0.7 film frames +1F4FD FE0F ; fully-qualified # 📽️ E0.7 film projector +1F4FD ; unqualified # 📽 E0.7 film projector +1F3AC ; fully-qualified # 🎬 E0.6 clapper board +1F4FA ; fully-qualified # 📺 E0.6 television +1F4F7 ; fully-qualified # 📷 E0.6 camera +1F4F8 ; fully-qualified # 📸 E1.0 camera with flash +1F4F9 ; fully-qualified # 📹 E0.6 video camera +1F4FC ; fully-qualified # 📼 E0.6 videocassette +1F50D ; fully-qualified # 🔍 E0.6 magnifying glass tilted left +1F50E ; fully-qualified # 🔎 E0.6 magnifying glass tilted right +1F56F FE0F ; fully-qualified # 🕯️ E0.7 candle +1F56F ; unqualified # 🕯 E0.7 candle +1F4A1 ; fully-qualified # 💡 E0.6 light bulb +1F526 ; fully-qualified # 🔦 E0.6 flashlight +1F3EE ; fully-qualified # 🏮 E0.6 red paper lantern +1FA94 ; fully-qualified # 🪔 E12.0 diya lamp + +# subgroup: book-paper +1F4D4 ; fully-qualified # 📔 E0.6 notebook with decorative cover +1F4D5 ; fully-qualified # 📕 E0.6 closed book +1F4D6 ; fully-qualified # 📖 E0.6 open book +1F4D7 ; fully-qualified # 📗 E0.6 green book +1F4D8 ; fully-qualified # 📘 E0.6 blue book +1F4D9 ; fully-qualified # 📙 E0.6 orange book +1F4DA ; fully-qualified # 📚 E0.6 books +1F4D3 ; fully-qualified # 📓 E0.6 notebook +1F4D2 ; fully-qualified # 📒 E0.6 ledger +1F4C3 ; fully-qualified # 📃 E0.6 page with curl +1F4DC ; fully-qualified # 📜 E0.6 scroll +1F4C4 ; fully-qualified # 📄 E0.6 page facing up +1F4F0 ; fully-qualified # 📰 E0.6 newspaper +1F5DE FE0F ; fully-qualified # 🗞️ E0.7 rolled-up newspaper +1F5DE ; unqualified # 🗞 E0.7 rolled-up newspaper +1F4D1 ; fully-qualified # 📑 E0.6 bookmark tabs +1F516 ; fully-qualified # 🔖 E0.6 bookmark +1F3F7 FE0F ; fully-qualified # 🏷️ E0.7 label +1F3F7 ; unqualified # 🏷 E0.7 label + +# subgroup: money +1F4B0 ; fully-qualified # 💰 E0.6 money bag +1FA99 ; fully-qualified # 🪙 E13.0 coin +1F4B4 ; fully-qualified # 💴 E0.6 yen banknote +1F4B5 ; fully-qualified # 💵 E0.6 dollar banknote +1F4B6 ; fully-qualified # 💶 E1.0 euro banknote +1F4B7 ; fully-qualified # 💷 E1.0 pound banknote +1F4B8 ; fully-qualified # 💸 E0.6 money with wings +1F4B3 ; fully-qualified # 💳 E0.6 credit card +1F9FE ; fully-qualified # 🧾 E11.0 receipt +1F4B9 ; fully-qualified # 💹 E0.6 chart increasing with yen + +# subgroup: mail +2709 FE0F ; fully-qualified # ✉️ E0.6 envelope +2709 ; unqualified # ✉ E0.6 envelope +1F4E7 ; fully-qualified # 📧 E0.6 e-mail +1F4E8 ; fully-qualified # 📨 E0.6 incoming envelope +1F4E9 ; fully-qualified # 📩 E0.6 envelope with arrow +1F4E4 ; fully-qualified # 📤 E0.6 outbox tray +1F4E5 ; fully-qualified # 📥 E0.6 inbox tray +1F4E6 ; fully-qualified # 📦 E0.6 package +1F4EB ; fully-qualified # 📫 E0.6 closed mailbox with raised flag +1F4EA ; fully-qualified # 📪 E0.6 closed mailbox with lowered flag +1F4EC ; fully-qualified # 📬 E0.7 open mailbox with raised flag +1F4ED ; fully-qualified # 📭 E0.7 open mailbox with lowered flag +1F4EE ; fully-qualified # 📮 E0.6 postbox +1F5F3 FE0F ; fully-qualified # 🗳️ E0.7 ballot box with ballot +1F5F3 ; unqualified # 🗳 E0.7 ballot box with ballot + +# subgroup: writing +270F FE0F ; fully-qualified # ✏️ E0.6 pencil +270F ; unqualified # ✏ E0.6 pencil +2712 FE0F ; fully-qualified # ✒️ E0.6 black nib +2712 ; unqualified # ✒ E0.6 black nib +1F58B FE0F ; fully-qualified # 🖋️ E0.7 fountain pen +1F58B ; unqualified # 🖋 E0.7 fountain pen +1F58A FE0F ; fully-qualified # 🖊️ E0.7 pen +1F58A ; unqualified # 🖊 E0.7 pen +1F58C FE0F ; fully-qualified # 🖌️ E0.7 paintbrush +1F58C ; unqualified # 🖌 E0.7 paintbrush +1F58D FE0F ; fully-qualified # 🖍️ E0.7 crayon +1F58D ; unqualified # 🖍 E0.7 crayon +1F4DD ; fully-qualified # 📝 E0.6 memo + +# subgroup: office +1F4BC ; fully-qualified # 💼 E0.6 briefcase +1F4C1 ; fully-qualified # 📁 E0.6 file folder +1F4C2 ; fully-qualified # 📂 E0.6 open file folder +1F5C2 FE0F ; fully-qualified # 🗂️ E0.7 card index dividers +1F5C2 ; unqualified # 🗂 E0.7 card index dividers +1F4C5 ; fully-qualified # 📅 E0.6 calendar +1F4C6 ; fully-qualified # 📆 E0.6 tear-off calendar +1F5D2 FE0F ; fully-qualified # 🗒️ E0.7 spiral notepad +1F5D2 ; unqualified # 🗒 E0.7 spiral notepad +1F5D3 FE0F ; fully-qualified # 🗓️ E0.7 spiral calendar +1F5D3 ; unqualified # 🗓 E0.7 spiral calendar +1F4C7 ; fully-qualified # 📇 E0.6 card index +1F4C8 ; fully-qualified # 📈 E0.6 chart increasing +1F4C9 ; fully-qualified # 📉 E0.6 chart decreasing +1F4CA ; fully-qualified # 📊 E0.6 bar chart +1F4CB ; fully-qualified # 📋 E0.6 clipboard +1F4CC ; fully-qualified # 📌 E0.6 pushpin +1F4CD ; fully-qualified # 📍 E0.6 round pushpin +1F4CE ; fully-qualified # 📎 E0.6 paperclip +1F587 FE0F ; fully-qualified # 🖇️ E0.7 linked paperclips +1F587 ; unqualified # 🖇 E0.7 linked paperclips +1F4CF ; fully-qualified # 📏 E0.6 straight ruler +1F4D0 ; fully-qualified # 📐 E0.6 triangular ruler +2702 FE0F ; fully-qualified # ✂️ E0.6 scissors +2702 ; unqualified # ✂ E0.6 scissors +1F5C3 FE0F ; fully-qualified # 🗃️ E0.7 card file box +1F5C3 ; unqualified # 🗃 E0.7 card file box +1F5C4 FE0F ; fully-qualified # 🗄️ E0.7 file cabinet +1F5C4 ; unqualified # 🗄 E0.7 file cabinet +1F5D1 FE0F ; fully-qualified # 🗑️ E0.7 wastebasket +1F5D1 ; unqualified # 🗑 E0.7 wastebasket + +# subgroup: lock +1F512 ; fully-qualified # 🔒 E0.6 locked +1F513 ; fully-qualified # 🔓 E0.6 unlocked +1F50F ; fully-qualified # 🔏 E0.6 locked with pen +1F510 ; fully-qualified # 🔐 E0.6 locked with key +1F511 ; fully-qualified # 🔑 E0.6 key +1F5DD FE0F ; fully-qualified # 🗝️ E0.7 old key +1F5DD ; unqualified # 🗝 E0.7 old key + +# subgroup: tool +1F528 ; fully-qualified # 🔨 E0.6 hammer +1FA93 ; fully-qualified # 🪓 E12.0 axe +26CF FE0F ; fully-qualified # ⛏️ E0.7 pick +26CF ; unqualified # ⛏ E0.7 pick +2692 FE0F ; fully-qualified # ⚒️ E1.0 hammer and pick +2692 ; unqualified # ⚒ E1.0 hammer and pick +1F6E0 FE0F ; fully-qualified # 🛠️ E0.7 hammer and wrench +1F6E0 ; unqualified # 🛠 E0.7 hammer and wrench +1F5E1 FE0F ; fully-qualified # 🗡️ E0.7 dagger +1F5E1 ; unqualified # 🗡 E0.7 dagger +2694 FE0F ; fully-qualified # ⚔️ E1.0 crossed swords +2694 ; unqualified # ⚔ E1.0 crossed swords +1F4A3 ; fully-qualified # 💣 E0.6 bomb +1FA83 ; fully-qualified # 🪃 E13.0 boomerang +1F3F9 ; fully-qualified # 🏹 E1.0 bow and arrow +1F6E1 FE0F ; fully-qualified # 🛡️ E0.7 shield +1F6E1 ; unqualified # 🛡 E0.7 shield +1FA9A ; fully-qualified # 🪚 E13.0 carpentry saw +1F527 ; fully-qualified # 🔧 E0.6 wrench +1FA9B ; fully-qualified # 🪛 E13.0 screwdriver +1F529 ; fully-qualified # 🔩 E0.6 nut and bolt +2699 FE0F ; fully-qualified # ⚙️ E1.0 gear +2699 ; unqualified # ⚙ E1.0 gear +1F5DC FE0F ; fully-qualified # 🗜️ E0.7 clamp +1F5DC ; unqualified # 🗜 E0.7 clamp +2696 FE0F ; fully-qualified # ⚖️ E1.0 balance scale +2696 ; unqualified # ⚖ E1.0 balance scale +1F9AF ; fully-qualified # 🦯 E12.0 white cane +1F517 ; fully-qualified # 🔗 E0.6 link +26D3 FE0F ; fully-qualified # ⛓️ E0.7 chains +26D3 ; unqualified # ⛓ E0.7 chains +1FA9D ; fully-qualified # 🪝 E13.0 hook +1F9F0 ; fully-qualified # 🧰 E11.0 toolbox +1F9F2 ; fully-qualified # 🧲 E11.0 magnet +1FA9C ; fully-qualified # 🪜 E13.0 ladder + +# subgroup: science +2697 FE0F ; fully-qualified # ⚗️ E1.0 alembic +2697 ; unqualified # ⚗ E1.0 alembic +1F9EA ; fully-qualified # 🧪 E11.0 test tube +1F9EB ; fully-qualified # 🧫 E11.0 petri dish +1F9EC ; fully-qualified # 🧬 E11.0 dna +1F52C ; fully-qualified # 🔬 E1.0 microscope +1F52D ; fully-qualified # 🔭 E1.0 telescope +1F4E1 ; fully-qualified # 📡 E0.6 satellite antenna + +# subgroup: medical +1F489 ; fully-qualified # 💉 E0.6 syringe +1FA78 ; fully-qualified # 🩸 E12.0 drop of blood +1F48A ; fully-qualified # 💊 E0.6 pill +1FA79 ; fully-qualified # 🩹 E12.0 adhesive bandage +1FA7C ; fully-qualified # 🩼 E14.0 crutch +1FA7A ; fully-qualified # 🩺 E12.0 stethoscope +1FA7B ; fully-qualified # 🩻 E14.0 x-ray + +# subgroup: household +1F6AA ; fully-qualified # 🚪 E0.6 door +1F6D7 ; fully-qualified # 🛗 E13.0 elevator +1FA9E ; fully-qualified # 🪞 E13.0 mirror +1FA9F ; fully-qualified # 🪟 E13.0 window +1F6CF FE0F ; fully-qualified # 🛏️ E0.7 bed +1F6CF ; unqualified # 🛏 E0.7 bed +1F6CB FE0F ; fully-qualified # 🛋️ E0.7 couch and lamp +1F6CB ; unqualified # 🛋 E0.7 couch and lamp +1FA91 ; fully-qualified # 🪑 E12.0 chair +1F6BD ; fully-qualified # 🚽 E0.6 toilet +1FAA0 ; fully-qualified # 🪠 E13.0 plunger +1F6BF ; fully-qualified # 🚿 E1.0 shower +1F6C1 ; fully-qualified # 🛁 E1.0 bathtub +1FAA4 ; fully-qualified # 🪤 E13.0 mouse trap +1FA92 ; fully-qualified # 🪒 E12.0 razor +1F9F4 ; fully-qualified # 🧴 E11.0 lotion bottle +1F9F7 ; fully-qualified # 🧷 E11.0 safety pin +1F9F9 ; fully-qualified # 🧹 E11.0 broom +1F9FA ; fully-qualified # 🧺 E11.0 basket +1F9FB ; fully-qualified # 🧻 E11.0 roll of paper +1FAA3 ; fully-qualified # 🪣 E13.0 bucket +1F9FC ; fully-qualified # 🧼 E11.0 soap +1FAE7 ; fully-qualified # 🫧 E14.0 bubbles +1FAA5 ; fully-qualified # 🪥 E13.0 toothbrush +1F9FD ; fully-qualified # 🧽 E11.0 sponge +1F9EF ; fully-qualified # 🧯 E11.0 fire extinguisher +1F6D2 ; fully-qualified # 🛒 E3.0 shopping cart + +# subgroup: other-object +1F6AC ; fully-qualified # 🚬 E0.6 cigarette +26B0 FE0F ; fully-qualified # ⚰️ E1.0 coffin +26B0 ; unqualified # ⚰ E1.0 coffin +1FAA6 ; fully-qualified # 🪦 E13.0 headstone +26B1 FE0F ; fully-qualified # ⚱️ E1.0 funeral urn +26B1 ; unqualified # ⚱ E1.0 funeral urn +1F9FF ; fully-qualified # 🧿 E11.0 nazar amulet +1FAAC ; fully-qualified # 🪬 E14.0 hamsa +1F5FF ; fully-qualified # 🗿 E0.6 moai +1FAA7 ; fully-qualified # 🪧 E13.0 placard +1FAAA ; fully-qualified # 🪪 E14.0 identification card + +# Objects subtotal: 310 +# Objects subtotal: 310 w/o modifiers + +# group: Symbols + +# subgroup: transport-sign +1F3E7 ; fully-qualified # 🏧 E0.6 ATM sign +1F6AE ; fully-qualified # 🚮 E1.0 litter in bin sign +1F6B0 ; fully-qualified # 🚰 E1.0 potable water +267F ; fully-qualified # ♿ E0.6 wheelchair symbol +1F6B9 ; fully-qualified # 🚹 E0.6 men’s room +1F6BA ; fully-qualified # 🚺 E0.6 women’s room +1F6BB ; fully-qualified # 🚻 E0.6 restroom +1F6BC ; fully-qualified # 🚼 E0.6 baby symbol +1F6BE ; fully-qualified # 🚾 E0.6 water closet +1F6C2 ; fully-qualified # 🛂 E1.0 passport control +1F6C3 ; fully-qualified # 🛃 E1.0 customs +1F6C4 ; fully-qualified # 🛄 E1.0 baggage claim +1F6C5 ; fully-qualified # 🛅 E1.0 left luggage + +# subgroup: warning +26A0 FE0F ; fully-qualified # ⚠️ E0.6 warning +26A0 ; unqualified # ⚠ E0.6 warning +1F6B8 ; fully-qualified # 🚸 E1.0 children crossing +26D4 ; fully-qualified # ⛔ E0.6 no entry +1F6AB ; fully-qualified # 🚫 E0.6 prohibited +1F6B3 ; fully-qualified # 🚳 E1.0 no bicycles +1F6AD ; fully-qualified # 🚭 E0.6 no smoking +1F6AF ; fully-qualified # 🚯 E1.0 no littering +1F6B1 ; fully-qualified # 🚱 E1.0 non-potable water +1F6B7 ; fully-qualified # 🚷 E1.0 no pedestrians +1F4F5 ; fully-qualified # 📵 E1.0 no mobile phones +1F51E ; fully-qualified # 🔞 E0.6 no one under eighteen +2622 FE0F ; fully-qualified # ☢️ E1.0 radioactive +2622 ; unqualified # ☢ E1.0 radioactive +2623 FE0F ; fully-qualified # ☣️ E1.0 biohazard +2623 ; unqualified # ☣ E1.0 biohazard + +# subgroup: arrow +2B06 FE0F ; fully-qualified # ⬆️ E0.6 up arrow +2B06 ; unqualified # ⬆ E0.6 up arrow +2197 FE0F ; fully-qualified # ↗️ E0.6 up-right arrow +2197 ; unqualified # ↗ E0.6 up-right arrow +27A1 FE0F ; fully-qualified # ➡️ E0.6 right arrow +27A1 ; unqualified # ➡ E0.6 right arrow +2198 FE0F ; fully-qualified # ↘️ E0.6 down-right arrow +2198 ; unqualified # ↘ E0.6 down-right arrow +2B07 FE0F ; fully-qualified # ⬇️ E0.6 down arrow +2B07 ; unqualified # ⬇ E0.6 down arrow +2199 FE0F ; fully-qualified # ↙️ E0.6 down-left arrow +2199 ; unqualified # ↙ E0.6 down-left arrow +2B05 FE0F ; fully-qualified # ⬅️ E0.6 left arrow +2B05 ; unqualified # ⬅ E0.6 left arrow +2196 FE0F ; fully-qualified # ↖️ E0.6 up-left arrow +2196 ; unqualified # ↖ E0.6 up-left arrow +2195 FE0F ; fully-qualified # ↕️ E0.6 up-down arrow +2195 ; unqualified # ↕ E0.6 up-down arrow +2194 FE0F ; fully-qualified # ↔️ E0.6 left-right arrow +2194 ; unqualified # ↔ E0.6 left-right arrow +21A9 FE0F ; fully-qualified # ↩️ E0.6 right arrow curving left +21A9 ; unqualified # ↩ E0.6 right arrow curving left +21AA FE0F ; fully-qualified # ↪️ E0.6 left arrow curving right +21AA ; unqualified # ↪ E0.6 left arrow curving right +2934 FE0F ; fully-qualified # ⤴️ E0.6 right arrow curving up +2934 ; unqualified # ⤴ E0.6 right arrow curving up +2935 FE0F ; fully-qualified # ⤵️ E0.6 right arrow curving down +2935 ; unqualified # ⤵ E0.6 right arrow curving down +1F503 ; fully-qualified # 🔃 E0.6 clockwise vertical arrows +1F504 ; fully-qualified # 🔄 E1.0 counterclockwise arrows button +1F519 ; fully-qualified # 🔙 E0.6 BACK arrow +1F51A ; fully-qualified # 🔚 E0.6 END arrow +1F51B ; fully-qualified # 🔛 E0.6 ON! arrow +1F51C ; fully-qualified # 🔜 E0.6 SOON arrow +1F51D ; fully-qualified # 🔝 E0.6 TOP arrow + +# subgroup: religion +1F6D0 ; fully-qualified # 🛐 E1.0 place of worship +269B FE0F ; fully-qualified # ⚛️ E1.0 atom symbol +269B ; unqualified # ⚛ E1.0 atom symbol +1F549 FE0F ; fully-qualified # 🕉️ E0.7 om +1F549 ; unqualified # 🕉 E0.7 om +2721 FE0F ; fully-qualified # ✡️ E0.7 star of David +2721 ; unqualified # ✡ E0.7 star of David +2638 FE0F ; fully-qualified # ☸️ E0.7 wheel of dharma +2638 ; unqualified # ☸ E0.7 wheel of dharma +262F FE0F ; fully-qualified # ☯️ E0.7 yin yang +262F ; unqualified # ☯ E0.7 yin yang +271D FE0F ; fully-qualified # ✝️ E0.7 latin cross +271D ; unqualified # ✝ E0.7 latin cross +2626 FE0F ; fully-qualified # ☦️ E1.0 orthodox cross +2626 ; unqualified # ☦ E1.0 orthodox cross +262A FE0F ; fully-qualified # ☪️ E0.7 star and crescent +262A ; unqualified # ☪ E0.7 star and crescent +262E FE0F ; fully-qualified # ☮️ E1.0 peace symbol +262E ; unqualified # ☮ E1.0 peace symbol +1F54E ; fully-qualified # 🕎 E1.0 menorah +1F52F ; fully-qualified # 🔯 E0.6 dotted six-pointed star +1FAAF ; fully-qualified # 🪯 E15.0 khanda + +# subgroup: zodiac +2648 ; fully-qualified # ♈ E0.6 Aries +2649 ; fully-qualified # ♉ E0.6 Taurus +264A ; fully-qualified # ♊ E0.6 Gemini +264B ; fully-qualified # ♋ E0.6 Cancer +264C ; fully-qualified # ♌ E0.6 Leo +264D ; fully-qualified # ♍ E0.6 Virgo +264E ; fully-qualified # ♎ E0.6 Libra +264F ; fully-qualified # ♏ E0.6 Scorpio +2650 ; fully-qualified # ♐ E0.6 Sagittarius +2651 ; fully-qualified # ♑ E0.6 Capricorn +2652 ; fully-qualified # ♒ E0.6 Aquarius +2653 ; fully-qualified # ♓ E0.6 Pisces +26CE ; fully-qualified # ⛎ E0.6 Ophiuchus + +# subgroup: av-symbol +1F500 ; fully-qualified # 🔀 E1.0 shuffle tracks button +1F501 ; fully-qualified # 🔁 E1.0 repeat button +1F502 ; fully-qualified # 🔂 E1.0 repeat single button +25B6 FE0F ; fully-qualified # ▶️ E0.6 play button +25B6 ; unqualified # ▶ E0.6 play button +23E9 ; fully-qualified # ⏩ E0.6 fast-forward button +23ED FE0F ; fully-qualified # ⏭️ E0.7 next track button +23ED ; unqualified # ⏭ E0.7 next track button +23EF FE0F ; fully-qualified # ⏯️ E1.0 play or pause button +23EF ; unqualified # ⏯ E1.0 play or pause button +25C0 FE0F ; fully-qualified # ◀️ E0.6 reverse button +25C0 ; unqualified # ◀ E0.6 reverse button +23EA ; fully-qualified # ⏪ E0.6 fast reverse button +23EE FE0F ; fully-qualified # ⏮️ E0.7 last track button +23EE ; unqualified # ⏮ E0.7 last track button +1F53C ; fully-qualified # 🔼 E0.6 upwards button +23EB ; fully-qualified # ⏫ E0.6 fast up button +1F53D ; fully-qualified # 🔽 E0.6 downwards button +23EC ; fully-qualified # ⏬ E0.6 fast down button +23F8 FE0F ; fully-qualified # ⏸️ E0.7 pause button +23F8 ; unqualified # ⏸ E0.7 pause button +23F9 FE0F ; fully-qualified # ⏹️ E0.7 stop button +23F9 ; unqualified # ⏹ E0.7 stop button +23FA FE0F ; fully-qualified # ⏺️ E0.7 record button +23FA ; unqualified # ⏺ E0.7 record button +23CF FE0F ; fully-qualified # ⏏️ E1.0 eject button +23CF ; unqualified # ⏏ E1.0 eject button +1F3A6 ; fully-qualified # 🎦 E0.6 cinema +1F505 ; fully-qualified # 🔅 E1.0 dim button +1F506 ; fully-qualified # 🔆 E1.0 bright button +1F4F6 ; fully-qualified # 📶 E0.6 antenna bars +1F6DC ; fully-qualified # 🛜 E15.0 wireless +1F4F3 ; fully-qualified # 📳 E0.6 vibration mode +1F4F4 ; fully-qualified # 📴 E0.6 mobile phone off + +# subgroup: gender +2640 FE0F ; fully-qualified # ♀️ E4.0 female sign +2640 ; unqualified # ♀ E4.0 female sign +2642 FE0F ; fully-qualified # ♂️ E4.0 male sign +2642 ; unqualified # ♂ E4.0 male sign +26A7 FE0F ; fully-qualified # ⚧️ E13.0 transgender symbol +26A7 ; unqualified # ⚧ E13.0 transgender symbol + +# subgroup: math +2716 FE0F ; fully-qualified # ✖️ E0.6 multiply +2716 ; unqualified # ✖ E0.6 multiply +2795 ; fully-qualified # ➕ E0.6 plus +2796 ; fully-qualified # ➖ E0.6 minus +2797 ; fully-qualified # ➗ E0.6 divide +1F7F0 ; fully-qualified # 🟰 E14.0 heavy equals sign +267E FE0F ; fully-qualified # ♾️ E11.0 infinity +267E ; unqualified # ♾ E11.0 infinity + +# subgroup: punctuation +203C FE0F ; fully-qualified # ‼️ E0.6 double exclamation mark +203C ; unqualified # ‼ E0.6 double exclamation mark +2049 FE0F ; fully-qualified # ⁉️ E0.6 exclamation question mark +2049 ; unqualified # ⁉ E0.6 exclamation question mark +2753 ; fully-qualified # ❓ E0.6 red question mark +2754 ; fully-qualified # ❔ E0.6 white question mark +2755 ; fully-qualified # ❕ E0.6 white exclamation mark +2757 ; fully-qualified # ❗ E0.6 red exclamation mark +3030 FE0F ; fully-qualified # 〰️ E0.6 wavy dash +3030 ; unqualified # 〰 E0.6 wavy dash + +# subgroup: currency +1F4B1 ; fully-qualified # 💱 E0.6 currency exchange +1F4B2 ; fully-qualified # 💲 E0.6 heavy dollar sign + +# subgroup: other-symbol +2695 FE0F ; fully-qualified # ⚕️ E4.0 medical symbol +2695 ; unqualified # ⚕ E4.0 medical symbol +267B FE0F ; fully-qualified # ♻️ E0.6 recycling symbol +267B ; unqualified # ♻ E0.6 recycling symbol +269C FE0F ; fully-qualified # ⚜️ E1.0 fleur-de-lis +269C ; unqualified # ⚜ E1.0 fleur-de-lis +1F531 ; fully-qualified # 🔱 E0.6 trident emblem +1F4DB ; fully-qualified # 📛 E0.6 name badge +1F530 ; fully-qualified # 🔰 E0.6 Japanese symbol for beginner +2B55 ; fully-qualified # ⭕ E0.6 hollow red circle +2705 ; fully-qualified # ✅ E0.6 check mark button +2611 FE0F ; fully-qualified # ☑️ E0.6 check box with check +2611 ; unqualified # ☑ E0.6 check box with check +2714 FE0F ; fully-qualified # ✔️ E0.6 check mark +2714 ; unqualified # ✔ E0.6 check mark +274C ; fully-qualified # ❌ E0.6 cross mark +274E ; fully-qualified # ❎ E0.6 cross mark button +27B0 ; fully-qualified # ➰ E0.6 curly loop +27BF ; fully-qualified # ➿ E1.0 double curly loop +303D FE0F ; fully-qualified # 〽️ E0.6 part alternation mark +303D ; unqualified # 〽 E0.6 part alternation mark +2733 FE0F ; fully-qualified # ✳️ E0.6 eight-spoked asterisk +2733 ; unqualified # ✳ E0.6 eight-spoked asterisk +2734 FE0F ; fully-qualified # ✴️ E0.6 eight-pointed star +2734 ; unqualified # ✴ E0.6 eight-pointed star +2747 FE0F ; fully-qualified # ❇️ E0.6 sparkle +2747 ; unqualified # ❇ E0.6 sparkle +00A9 FE0F ; fully-qualified # ©️ E0.6 copyright +00A9 ; unqualified # © E0.6 copyright +00AE FE0F ; fully-qualified # ®️ E0.6 registered +00AE ; unqualified # ® E0.6 registered +2122 FE0F ; fully-qualified # ™️ E0.6 trade mark +2122 ; unqualified # ™ E0.6 trade mark + +# subgroup: keycap +0023 FE0F 20E3 ; fully-qualified # #️⃣ E0.6 keycap: # +0023 20E3 ; unqualified # #⃣ E0.6 keycap: # +002A FE0F 20E3 ; fully-qualified # *️⃣ E2.0 keycap: * +002A 20E3 ; unqualified # *⃣ E2.0 keycap: * +0030 FE0F 20E3 ; fully-qualified # 0️⃣ E0.6 keycap: 0 +0030 20E3 ; unqualified # 0⃣ E0.6 keycap: 0 +0031 FE0F 20E3 ; fully-qualified # 1️⃣ E0.6 keycap: 1 +0031 20E3 ; unqualified # 1⃣ E0.6 keycap: 1 +0032 FE0F 20E3 ; fully-qualified # 2️⃣ E0.6 keycap: 2 +0032 20E3 ; unqualified # 2⃣ E0.6 keycap: 2 +0033 FE0F 20E3 ; fully-qualified # 3️⃣ E0.6 keycap: 3 +0033 20E3 ; unqualified # 3⃣ E0.6 keycap: 3 +0034 FE0F 20E3 ; fully-qualified # 4️⃣ E0.6 keycap: 4 +0034 20E3 ; unqualified # 4⃣ E0.6 keycap: 4 +0035 FE0F 20E3 ; fully-qualified # 5️⃣ E0.6 keycap: 5 +0035 20E3 ; unqualified # 5⃣ E0.6 keycap: 5 +0036 FE0F 20E3 ; fully-qualified # 6️⃣ E0.6 keycap: 6 +0036 20E3 ; unqualified # 6⃣ E0.6 keycap: 6 +0037 FE0F 20E3 ; fully-qualified # 7️⃣ E0.6 keycap: 7 +0037 20E3 ; unqualified # 7⃣ E0.6 keycap: 7 +0038 FE0F 20E3 ; fully-qualified # 8️⃣ E0.6 keycap: 8 +0038 20E3 ; unqualified # 8⃣ E0.6 keycap: 8 +0039 FE0F 20E3 ; fully-qualified # 9️⃣ E0.6 keycap: 9 +0039 20E3 ; unqualified # 9⃣ E0.6 keycap: 9 +1F51F ; fully-qualified # 🔟 E0.6 keycap: 10 + +# subgroup: alphanum +1F520 ; fully-qualified # 🔠 E0.6 input latin uppercase +1F521 ; fully-qualified # 🔡 E0.6 input latin lowercase +1F522 ; fully-qualified # 🔢 E0.6 input numbers +1F523 ; fully-qualified # 🔣 E0.6 input symbols +1F524 ; fully-qualified # 🔤 E0.6 input latin letters +1F170 FE0F ; fully-qualified # 🅰️ E0.6 A button (blood type) +1F170 ; unqualified # 🅰 E0.6 A button (blood type) +1F18E ; fully-qualified # 🆎 E0.6 AB button (blood type) +1F171 FE0F ; fully-qualified # 🅱️ E0.6 B button (blood type) +1F171 ; unqualified # 🅱 E0.6 B button (blood type) +1F191 ; fully-qualified # 🆑 E0.6 CL button +1F192 ; fully-qualified # 🆒 E0.6 COOL button +1F193 ; fully-qualified # 🆓 E0.6 FREE button +2139 FE0F ; fully-qualified # ℹ️ E0.6 information +2139 ; unqualified # ℹ E0.6 information +1F194 ; fully-qualified # 🆔 E0.6 ID button +24C2 FE0F ; fully-qualified # Ⓜ️ E0.6 circled M +24C2 ; unqualified # Ⓜ E0.6 circled M +1F195 ; fully-qualified # 🆕 E0.6 NEW button +1F196 ; fully-qualified # 🆖 E0.6 NG button +1F17E FE0F ; fully-qualified # 🅾️ E0.6 O button (blood type) +1F17E ; unqualified # 🅾 E0.6 O button (blood type) +1F197 ; fully-qualified # 🆗 E0.6 OK button +1F17F FE0F ; fully-qualified # 🅿️ E0.6 P button +1F17F ; unqualified # 🅿 E0.6 P button +1F198 ; fully-qualified # 🆘 E0.6 SOS button +1F199 ; fully-qualified # 🆙 E0.6 UP! button +1F19A ; fully-qualified # 🆚 E0.6 VS button +1F201 ; fully-qualified # 🈁 E0.6 Japanese “here” button +1F202 FE0F ; fully-qualified # 🈂️ E0.6 Japanese “service charge” button +1F202 ; unqualified # 🈂 E0.6 Japanese “service charge” button +1F237 FE0F ; fully-qualified # 🈷️ E0.6 Japanese “monthly amount” button +1F237 ; unqualified # 🈷 E0.6 Japanese “monthly amount” button +1F236 ; fully-qualified # 🈶 E0.6 Japanese “not free of charge” button +1F22F ; fully-qualified # 🈯 E0.6 Japanese “reserved” button +1F250 ; fully-qualified # 🉐 E0.6 Japanese “bargain” button +1F239 ; fully-qualified # 🈹 E0.6 Japanese “discount” button +1F21A ; fully-qualified # 🈚 E0.6 Japanese “free of charge” button +1F232 ; fully-qualified # 🈲 E0.6 Japanese “prohibited” button +1F251 ; fully-qualified # 🉑 E0.6 Japanese “acceptable” button +1F238 ; fully-qualified # 🈸 E0.6 Japanese “application” button +1F234 ; fully-qualified # 🈴 E0.6 Japanese “passing grade” button +1F233 ; fully-qualified # 🈳 E0.6 Japanese “vacancy” button +3297 FE0F ; fully-qualified # ㊗️ E0.6 Japanese “congratulations” button +3297 ; unqualified # ㊗ E0.6 Japanese “congratulations” button +3299 FE0F ; fully-qualified # ㊙️ E0.6 Japanese “secret” button +3299 ; unqualified # ㊙ E0.6 Japanese “secret” button +1F23A ; fully-qualified # 🈺 E0.6 Japanese “open for business” button +1F235 ; fully-qualified # 🈵 E0.6 Japanese “no vacancy” button + +# subgroup: geometric +1F534 ; fully-qualified # 🔴 E0.6 red circle +1F7E0 ; fully-qualified # 🟠 E12.0 orange circle +1F7E1 ; fully-qualified # 🟡 E12.0 yellow circle +1F7E2 ; fully-qualified # 🟢 E12.0 green circle +1F535 ; fully-qualified # 🔵 E0.6 blue circle +1F7E3 ; fully-qualified # 🟣 E12.0 purple circle +1F7E4 ; fully-qualified # 🟤 E12.0 brown circle +26AB ; fully-qualified # ⚫ E0.6 black circle +26AA ; fully-qualified # ⚪ E0.6 white circle +1F7E5 ; fully-qualified # 🟥 E12.0 red square +1F7E7 ; fully-qualified # 🟧 E12.0 orange square +1F7E8 ; fully-qualified # 🟨 E12.0 yellow square +1F7E9 ; fully-qualified # 🟩 E12.0 green square +1F7E6 ; fully-qualified # 🟦 E12.0 blue square +1F7EA ; fully-qualified # 🟪 E12.0 purple square +1F7EB ; fully-qualified # 🟫 E12.0 brown square +2B1B ; fully-qualified # ⬛ E0.6 black large square +2B1C ; fully-qualified # ⬜ E0.6 white large square +25FC FE0F ; fully-qualified # ◼️ E0.6 black medium square +25FC ; unqualified # ◼ E0.6 black medium square +25FB FE0F ; fully-qualified # ◻️ E0.6 white medium square +25FB ; unqualified # ◻ E0.6 white medium square +25FE ; fully-qualified # ◾ E0.6 black medium-small square +25FD ; fully-qualified # ◽ E0.6 white medium-small square +25AA FE0F ; fully-qualified # ▪️ E0.6 black small square +25AA ; unqualified # ▪ E0.6 black small square +25AB FE0F ; fully-qualified # ▫️ E0.6 white small square +25AB ; unqualified # ▫ E0.6 white small square +1F536 ; fully-qualified # 🔶 E0.6 large orange diamond +1F537 ; fully-qualified # 🔷 E0.6 large blue diamond +1F538 ; fully-qualified # 🔸 E0.6 small orange diamond +1F539 ; fully-qualified # 🔹 E0.6 small blue diamond +1F53A ; fully-qualified # 🔺 E0.6 red triangle pointed up +1F53B ; fully-qualified # 🔻 E0.6 red triangle pointed down +1F4A0 ; fully-qualified # 💠 E0.6 diamond with a dot +1F518 ; fully-qualified # 🔘 E0.6 radio button +1F533 ; fully-qualified # 🔳 E0.6 white square button +1F532 ; fully-qualified # 🔲 E0.6 black square button + +# Symbols subtotal: 304 +# Symbols subtotal: 304 w/o modifiers + +# group: Flags + +# subgroup: flag +1F3C1 ; fully-qualified # 🏁 E0.6 chequered flag +1F6A9 ; fully-qualified # 🚩 E0.6 triangular flag +1F38C ; fully-qualified # 🎌 E0.6 crossed flags +1F3F4 ; fully-qualified # 🏴 E1.0 black flag +1F3F3 FE0F ; fully-qualified # 🏳️ E0.7 white flag +1F3F3 ; unqualified # 🏳 E0.7 white flag +1F3F3 FE0F 200D 1F308 ; fully-qualified # 🏳️‍🌈 E4.0 rainbow flag +1F3F3 200D 1F308 ; unqualified # 🏳‍🌈 E4.0 rainbow flag +1F3F3 FE0F 200D 26A7 FE0F ; fully-qualified # 🏳️‍⚧️ E13.0 transgender flag +1F3F3 200D 26A7 FE0F ; unqualified # 🏳‍⚧️ E13.0 transgender flag +1F3F3 FE0F 200D 26A7 ; minimally-qualified # 🏳️‍⚧ E13.0 transgender flag +1F3F3 200D 26A7 ; unqualified # 🏳‍⚧ E13.0 transgender flag +1F3F4 200D 2620 FE0F ; fully-qualified # 🏴‍☠️ E11.0 pirate flag +1F3F4 200D 2620 ; minimally-qualified # 🏴‍☠ E11.0 pirate flag + +# subgroup: country-flag +1F1E6 1F1E8 ; fully-qualified # 🇦🇨 E2.0 flag: Ascension Island +1F1E6 1F1E9 ; fully-qualified # 🇦🇩 E2.0 flag: Andorra +1F1E6 1F1EA ; fully-qualified # 🇦🇪 E2.0 flag: United Arab Emirates +1F1E6 1F1EB ; fully-qualified # 🇦🇫 E2.0 flag: Afghanistan +1F1E6 1F1EC ; fully-qualified # 🇦🇬 E2.0 flag: Antigua & Barbuda +1F1E6 1F1EE ; fully-qualified # 🇦🇮 E2.0 flag: Anguilla +1F1E6 1F1F1 ; fully-qualified # 🇦🇱 E2.0 flag: Albania +1F1E6 1F1F2 ; fully-qualified # 🇦🇲 E2.0 flag: Armenia +1F1E6 1F1F4 ; fully-qualified # 🇦🇴 E2.0 flag: Angola +1F1E6 1F1F6 ; fully-qualified # 🇦🇶 E2.0 flag: Antarctica +1F1E6 1F1F7 ; fully-qualified # 🇦🇷 E2.0 flag: Argentina +1F1E6 1F1F8 ; fully-qualified # 🇦🇸 E2.0 flag: American Samoa +1F1E6 1F1F9 ; fully-qualified # 🇦🇹 E2.0 flag: Austria +1F1E6 1F1FA ; fully-qualified # 🇦🇺 E2.0 flag: Australia +1F1E6 1F1FC ; fully-qualified # 🇦🇼 E2.0 flag: Aruba +1F1E6 1F1FD ; fully-qualified # 🇦🇽 E2.0 flag: Åland Islands +1F1E6 1F1FF ; fully-qualified # 🇦🇿 E2.0 flag: Azerbaijan +1F1E7 1F1E6 ; fully-qualified # 🇧🇦 E2.0 flag: Bosnia & Herzegovina +1F1E7 1F1E7 ; fully-qualified # 🇧🇧 E2.0 flag: Barbados +1F1E7 1F1E9 ; fully-qualified # 🇧🇩 E2.0 flag: Bangladesh +1F1E7 1F1EA ; fully-qualified # 🇧🇪 E2.0 flag: Belgium +1F1E7 1F1EB ; fully-qualified # 🇧🇫 E2.0 flag: Burkina Faso +1F1E7 1F1EC ; fully-qualified # 🇧🇬 E2.0 flag: Bulgaria +1F1E7 1F1ED ; fully-qualified # 🇧🇭 E2.0 flag: Bahrain +1F1E7 1F1EE ; fully-qualified # 🇧🇮 E2.0 flag: Burundi +1F1E7 1F1EF ; fully-qualified # 🇧🇯 E2.0 flag: Benin +1F1E7 1F1F1 ; fully-qualified # 🇧🇱 E2.0 flag: St. Barthélemy +1F1E7 1F1F2 ; fully-qualified # 🇧🇲 E2.0 flag: Bermuda +1F1E7 1F1F3 ; fully-qualified # 🇧🇳 E2.0 flag: Brunei +1F1E7 1F1F4 ; fully-qualified # 🇧🇴 E2.0 flag: Bolivia +1F1E7 1F1F6 ; fully-qualified # 🇧🇶 E2.0 flag: Caribbean Netherlands +1F1E7 1F1F7 ; fully-qualified # 🇧🇷 E2.0 flag: Brazil +1F1E7 1F1F8 ; fully-qualified # 🇧🇸 E2.0 flag: Bahamas +1F1E7 1F1F9 ; fully-qualified # 🇧🇹 E2.0 flag: Bhutan +1F1E7 1F1FB ; fully-qualified # 🇧🇻 E2.0 flag: Bouvet Island +1F1E7 1F1FC ; fully-qualified # 🇧🇼 E2.0 flag: Botswana +1F1E7 1F1FE ; fully-qualified # 🇧🇾 E2.0 flag: Belarus +1F1E7 1F1FF ; fully-qualified # 🇧🇿 E2.0 flag: Belize +1F1E8 1F1E6 ; fully-qualified # 🇨🇦 E2.0 flag: Canada +1F1E8 1F1E8 ; fully-qualified # 🇨🇨 E2.0 flag: Cocos (Keeling) Islands +1F1E8 1F1E9 ; fully-qualified # 🇨🇩 E2.0 flag: Congo - Kinshasa +1F1E8 1F1EB ; fully-qualified # 🇨🇫 E2.0 flag: Central African Republic +1F1E8 1F1EC ; fully-qualified # 🇨🇬 E2.0 flag: Congo - Brazzaville +1F1E8 1F1ED ; fully-qualified # 🇨🇭 E2.0 flag: Switzerland +1F1E8 1F1EE ; fully-qualified # 🇨🇮 E2.0 flag: Côte d’Ivoire +1F1E8 1F1F0 ; fully-qualified # 🇨🇰 E2.0 flag: Cook Islands +1F1E8 1F1F1 ; fully-qualified # 🇨🇱 E2.0 flag: Chile +1F1E8 1F1F2 ; fully-qualified # 🇨🇲 E2.0 flag: Cameroon +1F1E8 1F1F3 ; fully-qualified # 🇨🇳 E0.6 flag: China +1F1E8 1F1F4 ; fully-qualified # 🇨🇴 E2.0 flag: Colombia +1F1E8 1F1F5 ; fully-qualified # 🇨🇵 E2.0 flag: Clipperton Island +1F1E8 1F1F7 ; fully-qualified # 🇨🇷 E2.0 flag: Costa Rica +1F1E8 1F1FA ; fully-qualified # 🇨🇺 E2.0 flag: Cuba +1F1E8 1F1FB ; fully-qualified # 🇨🇻 E2.0 flag: Cape Verde +1F1E8 1F1FC ; fully-qualified # 🇨🇼 E2.0 flag: Curaçao +1F1E8 1F1FD ; fully-qualified # 🇨🇽 E2.0 flag: Christmas Island +1F1E8 1F1FE ; fully-qualified # 🇨🇾 E2.0 flag: Cyprus +1F1E8 1F1FF ; fully-qualified # 🇨🇿 E2.0 flag: Czechia +1F1E9 1F1EA ; fully-qualified # 🇩🇪 E0.6 flag: Germany +1F1E9 1F1EC ; fully-qualified # 🇩🇬 E2.0 flag: Diego Garcia +1F1E9 1F1EF ; fully-qualified # 🇩🇯 E2.0 flag: Djibouti +1F1E9 1F1F0 ; fully-qualified # 🇩🇰 E2.0 flag: Denmark +1F1E9 1F1F2 ; fully-qualified # 🇩🇲 E2.0 flag: Dominica +1F1E9 1F1F4 ; fully-qualified # 🇩🇴 E2.0 flag: Dominican Republic +1F1E9 1F1FF ; fully-qualified # 🇩🇿 E2.0 flag: Algeria +1F1EA 1F1E6 ; fully-qualified # 🇪🇦 E2.0 flag: Ceuta & Melilla +1F1EA 1F1E8 ; fully-qualified # 🇪🇨 E2.0 flag: Ecuador +1F1EA 1F1EA ; fully-qualified # 🇪🇪 E2.0 flag: Estonia +1F1EA 1F1EC ; fully-qualified # 🇪🇬 E2.0 flag: Egypt +1F1EA 1F1ED ; fully-qualified # 🇪🇭 E2.0 flag: Western Sahara +1F1EA 1F1F7 ; fully-qualified # 🇪🇷 E2.0 flag: Eritrea +1F1EA 1F1F8 ; fully-qualified # 🇪🇸 E0.6 flag: Spain +1F1EA 1F1F9 ; fully-qualified # 🇪🇹 E2.0 flag: Ethiopia +1F1EA 1F1FA ; fully-qualified # 🇪🇺 E2.0 flag: European Union +1F1EB 1F1EE ; fully-qualified # 🇫🇮 E2.0 flag: Finland +1F1EB 1F1EF ; fully-qualified # 🇫🇯 E2.0 flag: Fiji +1F1EB 1F1F0 ; fully-qualified # 🇫🇰 E2.0 flag: Falkland Islands +1F1EB 1F1F2 ; fully-qualified # 🇫🇲 E2.0 flag: Micronesia +1F1EB 1F1F4 ; fully-qualified # 🇫🇴 E2.0 flag: Faroe Islands +1F1EB 1F1F7 ; fully-qualified # 🇫🇷 E0.6 flag: France +1F1EC 1F1E6 ; fully-qualified # 🇬🇦 E2.0 flag: Gabon +1F1EC 1F1E7 ; fully-qualified # 🇬🇧 E0.6 flag: United Kingdom +1F1EC 1F1E9 ; fully-qualified # 🇬🇩 E2.0 flag: Grenada +1F1EC 1F1EA ; fully-qualified # 🇬🇪 E2.0 flag: Georgia +1F1EC 1F1EB ; fully-qualified # 🇬🇫 E2.0 flag: French Guiana +1F1EC 1F1EC ; fully-qualified # 🇬🇬 E2.0 flag: Guernsey +1F1EC 1F1ED ; fully-qualified # 🇬🇭 E2.0 flag: Ghana +1F1EC 1F1EE ; fully-qualified # 🇬🇮 E2.0 flag: Gibraltar +1F1EC 1F1F1 ; fully-qualified # 🇬🇱 E2.0 flag: Greenland +1F1EC 1F1F2 ; fully-qualified # 🇬🇲 E2.0 flag: Gambia +1F1EC 1F1F3 ; fully-qualified # 🇬🇳 E2.0 flag: Guinea +1F1EC 1F1F5 ; fully-qualified # 🇬🇵 E2.0 flag: Guadeloupe +1F1EC 1F1F6 ; fully-qualified # 🇬🇶 E2.0 flag: Equatorial Guinea +1F1EC 1F1F7 ; fully-qualified # 🇬🇷 E2.0 flag: Greece +1F1EC 1F1F8 ; fully-qualified # 🇬🇸 E2.0 flag: South Georgia & South Sandwich Islands +1F1EC 1F1F9 ; fully-qualified # 🇬🇹 E2.0 flag: Guatemala +1F1EC 1F1FA ; fully-qualified # 🇬🇺 E2.0 flag: Guam +1F1EC 1F1FC ; fully-qualified # 🇬🇼 E2.0 flag: Guinea-Bissau +1F1EC 1F1FE ; fully-qualified # 🇬🇾 E2.0 flag: Guyana +1F1ED 1F1F0 ; fully-qualified # 🇭🇰 E2.0 flag: Hong Kong SAR China +1F1ED 1F1F2 ; fully-qualified # 🇭🇲 E2.0 flag: Heard & McDonald Islands +1F1ED 1F1F3 ; fully-qualified # 🇭🇳 E2.0 flag: Honduras +1F1ED 1F1F7 ; fully-qualified # 🇭🇷 E2.0 flag: Croatia +1F1ED 1F1F9 ; fully-qualified # 🇭🇹 E2.0 flag: Haiti +1F1ED 1F1FA ; fully-qualified # 🇭🇺 E2.0 flag: Hungary +1F1EE 1F1E8 ; fully-qualified # 🇮🇨 E2.0 flag: Canary Islands +1F1EE 1F1E9 ; fully-qualified # 🇮🇩 E2.0 flag: Indonesia +1F1EE 1F1EA ; fully-qualified # 🇮🇪 E2.0 flag: Ireland +1F1EE 1F1F1 ; fully-qualified # 🇮🇱 E2.0 flag: Israel +1F1EE 1F1F2 ; fully-qualified # 🇮🇲 E2.0 flag: Isle of Man +1F1EE 1F1F3 ; fully-qualified # 🇮🇳 E2.0 flag: India +1F1EE 1F1F4 ; fully-qualified # 🇮🇴 E2.0 flag: British Indian Ocean Territory +1F1EE 1F1F6 ; fully-qualified # 🇮🇶 E2.0 flag: Iraq +1F1EE 1F1F7 ; fully-qualified # 🇮🇷 E2.0 flag: Iran +1F1EE 1F1F8 ; fully-qualified # 🇮🇸 E2.0 flag: Iceland +1F1EE 1F1F9 ; fully-qualified # 🇮🇹 E0.6 flag: Italy +1F1EF 1F1EA ; fully-qualified # 🇯🇪 E2.0 flag: Jersey +1F1EF 1F1F2 ; fully-qualified # 🇯🇲 E2.0 flag: Jamaica +1F1EF 1F1F4 ; fully-qualified # 🇯🇴 E2.0 flag: Jordan +1F1EF 1F1F5 ; fully-qualified # 🇯🇵 E0.6 flag: Japan +1F1F0 1F1EA ; fully-qualified # 🇰🇪 E2.0 flag: Kenya +1F1F0 1F1EC ; fully-qualified # 🇰🇬 E2.0 flag: Kyrgyzstan +1F1F0 1F1ED ; fully-qualified # 🇰🇭 E2.0 flag: Cambodia +1F1F0 1F1EE ; fully-qualified # 🇰🇮 E2.0 flag: Kiribati +1F1F0 1F1F2 ; fully-qualified # 🇰🇲 E2.0 flag: Comoros +1F1F0 1F1F3 ; fully-qualified # 🇰🇳 E2.0 flag: St. Kitts & Nevis +1F1F0 1F1F5 ; fully-qualified # 🇰🇵 E2.0 flag: North Korea +1F1F0 1F1F7 ; fully-qualified # 🇰🇷 E0.6 flag: South Korea +1F1F0 1F1FC ; fully-qualified # 🇰🇼 E2.0 flag: Kuwait +1F1F0 1F1FE ; fully-qualified # 🇰🇾 E2.0 flag: Cayman Islands +1F1F0 1F1FF ; fully-qualified # 🇰🇿 E2.0 flag: Kazakhstan +1F1F1 1F1E6 ; fully-qualified # 🇱🇦 E2.0 flag: Laos +1F1F1 1F1E7 ; fully-qualified # 🇱🇧 E2.0 flag: Lebanon +1F1F1 1F1E8 ; fully-qualified # 🇱🇨 E2.0 flag: St. Lucia +1F1F1 1F1EE ; fully-qualified # 🇱🇮 E2.0 flag: Liechtenstein +1F1F1 1F1F0 ; fully-qualified # 🇱🇰 E2.0 flag: Sri Lanka +1F1F1 1F1F7 ; fully-qualified # 🇱🇷 E2.0 flag: Liberia +1F1F1 1F1F8 ; fully-qualified # 🇱🇸 E2.0 flag: Lesotho +1F1F1 1F1F9 ; fully-qualified # 🇱🇹 E2.0 flag: Lithuania +1F1F1 1F1FA ; fully-qualified # 🇱🇺 E2.0 flag: Luxembourg +1F1F1 1F1FB ; fully-qualified # 🇱🇻 E2.0 flag: Latvia +1F1F1 1F1FE ; fully-qualified # 🇱🇾 E2.0 flag: Libya +1F1F2 1F1E6 ; fully-qualified # 🇲🇦 E2.0 flag: Morocco +1F1F2 1F1E8 ; fully-qualified # 🇲🇨 E2.0 flag: Monaco +1F1F2 1F1E9 ; fully-qualified # 🇲🇩 E2.0 flag: Moldova +1F1F2 1F1EA ; fully-qualified # 🇲🇪 E2.0 flag: Montenegro +1F1F2 1F1EB ; fully-qualified # 🇲🇫 E2.0 flag: St. Martin +1F1F2 1F1EC ; fully-qualified # 🇲🇬 E2.0 flag: Madagascar +1F1F2 1F1ED ; fully-qualified # 🇲🇭 E2.0 flag: Marshall Islands +1F1F2 1F1F0 ; fully-qualified # 🇲🇰 E2.0 flag: North Macedonia +1F1F2 1F1F1 ; fully-qualified # 🇲🇱 E2.0 flag: Mali +1F1F2 1F1F2 ; fully-qualified # 🇲🇲 E2.0 flag: Myanmar (Burma) +1F1F2 1F1F3 ; fully-qualified # 🇲🇳 E2.0 flag: Mongolia +1F1F2 1F1F4 ; fully-qualified # 🇲🇴 E2.0 flag: Macao SAR China +1F1F2 1F1F5 ; fully-qualified # 🇲🇵 E2.0 flag: Northern Mariana Islands +1F1F2 1F1F6 ; fully-qualified # 🇲🇶 E2.0 flag: Martinique +1F1F2 1F1F7 ; fully-qualified # 🇲🇷 E2.0 flag: Mauritania +1F1F2 1F1F8 ; fully-qualified # 🇲🇸 E2.0 flag: Montserrat +1F1F2 1F1F9 ; fully-qualified # 🇲🇹 E2.0 flag: Malta +1F1F2 1F1FA ; fully-qualified # 🇲🇺 E2.0 flag: Mauritius +1F1F2 1F1FB ; fully-qualified # 🇲🇻 E2.0 flag: Maldives +1F1F2 1F1FC ; fully-qualified # 🇲🇼 E2.0 flag: Malawi +1F1F2 1F1FD ; fully-qualified # 🇲🇽 E2.0 flag: Mexico +1F1F2 1F1FE ; fully-qualified # 🇲🇾 E2.0 flag: Malaysia +1F1F2 1F1FF ; fully-qualified # 🇲🇿 E2.0 flag: Mozambique +1F1F3 1F1E6 ; fully-qualified # 🇳🇦 E2.0 flag: Namibia +1F1F3 1F1E8 ; fully-qualified # 🇳🇨 E2.0 flag: New Caledonia +1F1F3 1F1EA ; fully-qualified # 🇳🇪 E2.0 flag: Niger +1F1F3 1F1EB ; fully-qualified # 🇳🇫 E2.0 flag: Norfolk Island +1F1F3 1F1EC ; fully-qualified # 🇳🇬 E2.0 flag: Nigeria +1F1F3 1F1EE ; fully-qualified # 🇳🇮 E2.0 flag: Nicaragua +1F1F3 1F1F1 ; fully-qualified # 🇳🇱 E2.0 flag: Netherlands +1F1F3 1F1F4 ; fully-qualified # 🇳🇴 E2.0 flag: Norway +1F1F3 1F1F5 ; fully-qualified # 🇳🇵 E2.0 flag: Nepal +1F1F3 1F1F7 ; fully-qualified # 🇳🇷 E2.0 flag: Nauru +1F1F3 1F1FA ; fully-qualified # 🇳🇺 E2.0 flag: Niue +1F1F3 1F1FF ; fully-qualified # 🇳🇿 E2.0 flag: New Zealand +1F1F4 1F1F2 ; fully-qualified # 🇴🇲 E2.0 flag: Oman +1F1F5 1F1E6 ; fully-qualified # 🇵🇦 E2.0 flag: Panama +1F1F5 1F1EA ; fully-qualified # 🇵🇪 E2.0 flag: Peru +1F1F5 1F1EB ; fully-qualified # 🇵🇫 E2.0 flag: French Polynesia +1F1F5 1F1EC ; fully-qualified # 🇵🇬 E2.0 flag: Papua New Guinea +1F1F5 1F1ED ; fully-qualified # 🇵🇭 E2.0 flag: Philippines +1F1F5 1F1F0 ; fully-qualified # 🇵🇰 E2.0 flag: Pakistan +1F1F5 1F1F1 ; fully-qualified # 🇵🇱 E2.0 flag: Poland +1F1F5 1F1F2 ; fully-qualified # 🇵🇲 E2.0 flag: St. Pierre & Miquelon +1F1F5 1F1F3 ; fully-qualified # 🇵🇳 E2.0 flag: Pitcairn Islands +1F1F5 1F1F7 ; fully-qualified # 🇵🇷 E2.0 flag: Puerto Rico +1F1F5 1F1F8 ; fully-qualified # 🇵🇸 E2.0 flag: Palestinian Territories +1F1F5 1F1F9 ; fully-qualified # 🇵🇹 E2.0 flag: Portugal +1F1F5 1F1FC ; fully-qualified # 🇵🇼 E2.0 flag: Palau +1F1F5 1F1FE ; fully-qualified # 🇵🇾 E2.0 flag: Paraguay +1F1F6 1F1E6 ; fully-qualified # 🇶🇦 E2.0 flag: Qatar +1F1F7 1F1EA ; fully-qualified # 🇷🇪 E2.0 flag: Réunion +1F1F7 1F1F4 ; fully-qualified # 🇷🇴 E2.0 flag: Romania +1F1F7 1F1F8 ; fully-qualified # 🇷🇸 E2.0 flag: Serbia +1F1F7 1F1FA ; fully-qualified # 🇷🇺 E0.6 flag: Russia +1F1F7 1F1FC ; fully-qualified # 🇷🇼 E2.0 flag: Rwanda +1F1F8 1F1E6 ; fully-qualified # 🇸🇦 E2.0 flag: Saudi Arabia +1F1F8 1F1E7 ; fully-qualified # 🇸🇧 E2.0 flag: Solomon Islands +1F1F8 1F1E8 ; fully-qualified # 🇸🇨 E2.0 flag: Seychelles +1F1F8 1F1E9 ; fully-qualified # 🇸🇩 E2.0 flag: Sudan +1F1F8 1F1EA ; fully-qualified # 🇸🇪 E2.0 flag: Sweden +1F1F8 1F1EC ; fully-qualified # 🇸🇬 E2.0 flag: Singapore +1F1F8 1F1ED ; fully-qualified # 🇸🇭 E2.0 flag: St. Helena +1F1F8 1F1EE ; fully-qualified # 🇸🇮 E2.0 flag: Slovenia +1F1F8 1F1EF ; fully-qualified # 🇸🇯 E2.0 flag: Svalbard & Jan Mayen +1F1F8 1F1F0 ; fully-qualified # 🇸🇰 E2.0 flag: Slovakia +1F1F8 1F1F1 ; fully-qualified # 🇸🇱 E2.0 flag: Sierra Leone +1F1F8 1F1F2 ; fully-qualified # 🇸🇲 E2.0 flag: San Marino +1F1F8 1F1F3 ; fully-qualified # 🇸🇳 E2.0 flag: Senegal +1F1F8 1F1F4 ; fully-qualified # 🇸🇴 E2.0 flag: Somalia +1F1F8 1F1F7 ; fully-qualified # 🇸🇷 E2.0 flag: Suriname +1F1F8 1F1F8 ; fully-qualified # 🇸🇸 E2.0 flag: South Sudan +1F1F8 1F1F9 ; fully-qualified # 🇸🇹 E2.0 flag: São Tomé & Príncipe +1F1F8 1F1FB ; fully-qualified # 🇸🇻 E2.0 flag: El Salvador +1F1F8 1F1FD ; fully-qualified # 🇸🇽 E2.0 flag: Sint Maarten +1F1F8 1F1FE ; fully-qualified # 🇸🇾 E2.0 flag: Syria +1F1F8 1F1FF ; fully-qualified # 🇸🇿 E2.0 flag: Eswatini +1F1F9 1F1E6 ; fully-qualified # 🇹🇦 E2.0 flag: Tristan da Cunha +1F1F9 1F1E8 ; fully-qualified # 🇹🇨 E2.0 flag: Turks & Caicos Islands +1F1F9 1F1E9 ; fully-qualified # 🇹🇩 E2.0 flag: Chad +1F1F9 1F1EB ; fully-qualified # 🇹🇫 E2.0 flag: French Southern Territories +1F1F9 1F1EC ; fully-qualified # 🇹🇬 E2.0 flag: Togo +1F1F9 1F1ED ; fully-qualified # 🇹🇭 E2.0 flag: Thailand +1F1F9 1F1EF ; fully-qualified # 🇹🇯 E2.0 flag: Tajikistan +1F1F9 1F1F0 ; fully-qualified # 🇹🇰 E2.0 flag: Tokelau +1F1F9 1F1F1 ; fully-qualified # 🇹🇱 E2.0 flag: Timor-Leste +1F1F9 1F1F2 ; fully-qualified # 🇹🇲 E2.0 flag: Turkmenistan +1F1F9 1F1F3 ; fully-qualified # 🇹🇳 E2.0 flag: Tunisia +1F1F9 1F1F4 ; fully-qualified # 🇹🇴 E2.0 flag: Tonga +1F1F9 1F1F7 ; fully-qualified # 🇹🇷 E2.0 flag: Turkey +1F1F9 1F1F9 ; fully-qualified # 🇹🇹 E2.0 flag: Trinidad & Tobago +1F1F9 1F1FB ; fully-qualified # 🇹🇻 E2.0 flag: Tuvalu +1F1F9 1F1FC ; fully-qualified # 🇹🇼 E2.0 flag: Taiwan +1F1F9 1F1FF ; fully-qualified # 🇹🇿 E2.0 flag: Tanzania +1F1FA 1F1E6 ; fully-qualified # 🇺🇦 E2.0 flag: Ukraine +1F1FA 1F1EC ; fully-qualified # 🇺🇬 E2.0 flag: Uganda +1F1FA 1F1F2 ; fully-qualified # 🇺🇲 E2.0 flag: U.S. Outlying Islands +1F1FA 1F1F3 ; fully-qualified # 🇺🇳 E4.0 flag: United Nations +1F1FA 1F1F8 ; fully-qualified # 🇺🇸 E0.6 flag: United States +1F1FA 1F1FE ; fully-qualified # 🇺🇾 E2.0 flag: Uruguay +1F1FA 1F1FF ; fully-qualified # 🇺🇿 E2.0 flag: Uzbekistan +1F1FB 1F1E6 ; fully-qualified # 🇻🇦 E2.0 flag: Vatican City +1F1FB 1F1E8 ; fully-qualified # 🇻🇨 E2.0 flag: St. Vincent & Grenadines +1F1FB 1F1EA ; fully-qualified # 🇻🇪 E2.0 flag: Venezuela +1F1FB 1F1EC ; fully-qualified # 🇻🇬 E2.0 flag: British Virgin Islands +1F1FB 1F1EE ; fully-qualified # 🇻🇮 E2.0 flag: U.S. Virgin Islands +1F1FB 1F1F3 ; fully-qualified # 🇻🇳 E2.0 flag: Vietnam +1F1FB 1F1FA ; fully-qualified # 🇻🇺 E2.0 flag: Vanuatu +1F1FC 1F1EB ; fully-qualified # 🇼🇫 E2.0 flag: Wallis & Futuna +1F1FC 1F1F8 ; fully-qualified # 🇼🇸 E2.0 flag: Samoa +1F1FD 1F1F0 ; fully-qualified # 🇽🇰 E2.0 flag: Kosovo +1F1FE 1F1EA ; fully-qualified # 🇾🇪 E2.0 flag: Yemen +1F1FE 1F1F9 ; fully-qualified # 🇾🇹 E2.0 flag: Mayotte +1F1FF 1F1E6 ; fully-qualified # 🇿🇦 E2.0 flag: South Africa +1F1FF 1F1F2 ; fully-qualified # 🇿🇲 E2.0 flag: Zambia +1F1FF 1F1FC ; fully-qualified # 🇿🇼 E2.0 flag: Zimbabwe + +# subgroup: subdivision-flag +1F3F4 E0067 E0062 E0065 E006E E0067 E007F ; fully-qualified # 🏴󠁧󠁢󠁥󠁮󠁧󠁿 E5.0 flag: England +1F3F4 E0067 E0062 E0073 E0063 E0074 E007F ; fully-qualified # 🏴󠁧󠁢󠁳󠁣󠁴󠁿 E5.0 flag: Scotland +1F3F4 E0067 E0062 E0077 E006C E0073 E007F ; fully-qualified # 🏴󠁧󠁢󠁷󠁬󠁳󠁿 E5.0 flag: Wales + +# Flags subtotal: 275 +# Flags subtotal: 275 w/o modifiers + +# Status Counts +# fully-qualified : 3655 +# minimally-qualified : 827 +# unqualified : 242 +# component : 9 + +#EOF diff --git a/emoji/scrape_aliases b/emoji/scrape_aliases new file mode 100755 index 00000000..3290d80b --- /dev/null +++ b/emoji/scrape_aliases @@ -0,0 +1,68 @@ +#!/usr/bin/env python +import asyncio +import json +import re + +from requests_html import AsyncHTMLSession +from rich.progress import track + +LINE_RE = re.compile( + r""" + ^ + (?P .*\S) + \s*;\s* + (?P \S+) + \s*\#\s* + (?P \S+) + \s* + (?P E\d+.\d+) + \s* + (?P .+) + $ +""", + re.VERBOSE, +) + + +async def get_aliases(session, name): + emojipedia_name = name.replace(" ", "-") + url = f"https://emojipedia.org/{emojipedia_name}/" + r = await session.get(url) + if r.status_code != 200: + return (name, []) + + aliases = r.html.find(".aliases li") + res = [] + for alias in aliases: + alias = alias.text.split(maxsplit=1)[1] + alias = alias.replace("\N{NO-BREAK SPACE}", " ") # Replace nbsp + res.append(alias) + return (name, res) + + +async def main(): + session = AsyncHTMLSession() + aliases = {} + + aws = [] + with open("emoji-test.txt") as f: + for l in f: + if m := LINE_RE.match(l): + d = m.groupdict() + if d["status"] != "fully-qualified": + continue + + aws.append(get_aliases(session, d["name"])) + + for aw in track(asyncio.as_completed(aws), total=len(aws)): + name, res = await aw + if res: + aliases[name] = res + + print(name, res) + + with open("aliases.json", "w") as f: + json.dump(aliases, f) + + +asyncio.run(main()) From 1a84f77a217ac03a66d26be7ac8e1c91a26f9a26 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 30 Mar 2023 10:55:43 +0300 Subject: [PATCH 108/355] [dice_roll] iid:0.5 v1.0 --- dice_roll/README.md | 13 ++++ dice_roll/__init__.py | 156 +++++++++++++++++++++++++++++++++++++++ dice_roll/icons/d10.svg | 3 + dice_roll/icons/d100.svg | 3 + dice_roll/icons/d12.svg | 3 + dice_roll/icons/d2.svg | 3 + dice_roll/icons/d20.svg | 3 + dice_roll/icons/d4.svg | 3 + dice_roll/icons/d6.svg | 3 + dice_roll/icons/d8.svg | 3 + dice_roll/icons/dice.svg | 3 + 11 files changed, 196 insertions(+) create mode 100644 dice_roll/README.md create mode 100644 dice_roll/__init__.py create mode 100644 dice_roll/icons/d10.svg create mode 100644 dice_roll/icons/d100.svg create mode 100644 dice_roll/icons/d12.svg create mode 100644 dice_roll/icons/d2.svg create mode 100644 dice_roll/icons/d20.svg create mode 100644 dice_roll/icons/d4.svg create mode 100644 dice_roll/icons/d6.svg create mode 100644 dice_roll/icons/d8.svg create mode 100644 dice_roll/icons/dice.svg diff --git a/dice_roll/README.md b/dice_roll/README.md new file mode 100644 index 00000000..955d6c3c --- /dev/null +++ b/dice_roll/README.md @@ -0,0 +1,13 @@ +# Dice Roll + +Extension for rolling dice + +![image](https://user-images.githubusercontent.com/20955511/211666706-eae9c9f2-849f-4b9c-9a59-39d71940b83d.png) + +## Usage + +Roll any number of dice using the format `_d_`. + +Synopsis: ` d [d ...]` + +Example: `"roll 2d6 3d8 1d20"` diff --git a/dice_roll/__init__.py b/dice_roll/__init__.py new file mode 100644 index 00000000..4606d541 --- /dev/null +++ b/dice_roll/__init__.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- + +from __future__ import annotations + +import random +import re +from pathlib import Path + +import albert + +__doc__ = f""" +Roll any number of dice using the format `_d_`. + +Example: "roll 2d6 3d8 1d20" +""" + +md_iid = "0.5" +md_version = "1.0" +md_name = "Dice Roll" +md_description = "Roll any number of dice" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python" +md_maintainers = "@DenverCoder1" + + +def get_icon_path(num_sides: int | None) -> str: + """Get the path to the icon for a die with num_sides sides. + + Args: + num_sides (Optional[int]): Number of sides on the die or None for the overall total. + + Returns: + str: The path to the icon. + """ + icons_path = Path(__file__).parent / "icons" + # get the icon for the number of sides or d20 if there is no icon for that number + icon = f"d{num_sides}" if Path(icons_path / f"d{num_sides}.svg").exists() else "d20" + # use the overall total icon if the number of sides is None + if num_sides is None: + icon = "dice" + # return the path to the icon + return str(icons_path / f"{icon}.svg") + + +def roll_dice(num_dice: int, num_sides: int) -> tuple[int, list[int]]: + """Roll multiple dice with num_sides sides. + + Args: + num_dice (int): Number of dice to roll. + num_sides (int): Number of sides on each die. + + Returns: + Tuple[int, List[int]]: The total and a list of the rolls. + """ + rolls = [random.randint(1, num_sides) for _ in range(num_dice)] + return sum(rolls), rolls + + +def get_item_from_rolls( + rolls: list[int], + sum_rolls: int, + num_sides: int | None = None, +) -> albert.Item: + """Creates an Albert Item from a list of rolls, the total, and the number of sides. + If num_sides is not provided, an "Overall Total" summary item is created. + + Args: + rolls (List[int]): List of rolls. + sum_rolls (int): Total of all rolls. + num_sides (Optional[int]): Number of sides on each die. + + Returns: + albert.Item: The item to be added to the list of results. + """ + return albert.Item( + id=get_icon_path(num_sides), + icon=[get_icon_path(num_sides)], + text=( + f"Rolled {len(rolls)}d{num_sides} - Total: {sum_rolls}" + if num_sides + else f"Overall Total: {sum_rolls}" + ), + subtext=f"Rolls: {', '.join(map(str, rolls))}", + actions=[ + albert.Action( + id="copytotal", + text="Copy result to clipboard", + callable=lambda: albert.setClipboardText(text=str(sum_rolls)), + ), + albert.Action( + id="copyrolls", + text="Copy result to clipboard", + callable=lambda: albert.setClipboardText(text=", ".join(map(str, rolls))), + ), + ], + ) + + +def get_items(query_string: str) -> list[albert.Item]: + """Convert a query string of dice rolls into a list of Albert Items. + + Args: + query_string (str): The query string to be parsed. + + Returns: + List[albert.Item]: The list of items to display. + """ + results = [] + sum_all_rolls = 0 + all_rolls = [] + # get (num_dice, num_sides) pairs from query string + dice_regex = re.compile(r"(\d+)d(\d+)", re.I) + matches = dice_regex.findall(query_string) + # roll each pair + for match in matches: + num_dice, num_sides = int(match[0]), int(match[1]) + # get random numbers from 1 to num_sides for each die + sum_rolls, rolls = roll_dice(num_dice, num_sides) + # add rolls and total to aggregators + sum_all_rolls += sum_rolls + all_rolls.extend(rolls) + # create item for the dice rolls + results.append(get_item_from_rolls(rolls, sum_rolls, num_sides)) + # if there are multiple dice types, add a summary item + if len(matches) > 1: + # prepend the summary item to the list of results + results.insert(0, get_item_from_rolls(all_rolls, sum_all_rolls)) + return results + + +class Plugin(albert.QueryHandler): + """A plugin to roll dice""" + + def id(self) -> str: + return __name__ + + def name(self) -> str: + return md_name + + def description(self) -> str: + return md_description + + def synopsis(self) -> str: + return "d [d ...]" + + def defaultTrigger(self) -> str: + return "roll " + + def handleQuery(self, query: albert.Query) -> None: + query_string = query.string.strip() + try: + items = get_items(query_string) + query.add(items) + except Exception as e: + albert.warning(e) + albert.info("Something went wrong. Make sure you're using the correct format.") diff --git a/dice_roll/icons/d10.svg b/dice_roll/icons/d10.svg new file mode 100644 index 00000000..1f155355 --- /dev/null +++ b/dice_roll/icons/d10.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dice_roll/icons/d100.svg b/dice_roll/icons/d100.svg new file mode 100644 index 00000000..4c133a01 --- /dev/null +++ b/dice_roll/icons/d100.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dice_roll/icons/d12.svg b/dice_roll/icons/d12.svg new file mode 100644 index 00000000..d88b4cad --- /dev/null +++ b/dice_roll/icons/d12.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dice_roll/icons/d2.svg b/dice_roll/icons/d2.svg new file mode 100644 index 00000000..fe35afa0 --- /dev/null +++ b/dice_roll/icons/d2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dice_roll/icons/d20.svg b/dice_roll/icons/d20.svg new file mode 100644 index 00000000..13562d7c --- /dev/null +++ b/dice_roll/icons/d20.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dice_roll/icons/d4.svg b/dice_roll/icons/d4.svg new file mode 100644 index 00000000..c9952782 --- /dev/null +++ b/dice_roll/icons/d4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dice_roll/icons/d6.svg b/dice_roll/icons/d6.svg new file mode 100644 index 00000000..b0f892b2 --- /dev/null +++ b/dice_roll/icons/d6.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dice_roll/icons/d8.svg b/dice_roll/icons/d8.svg new file mode 100644 index 00000000..381b5f80 --- /dev/null +++ b/dice_roll/icons/d8.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dice_roll/icons/dice.svg b/dice_roll/icons/dice.svg new file mode 100644 index 00000000..880f7b9d --- /dev/null +++ b/dice_roll/icons/dice.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file From dbcefab7e357e4c634933f5871b1602f67ad4751 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 30 Mar 2023 13:53:05 +0200 Subject: [PATCH 109/355] [kill] fix id --- kill/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kill/__init__.py b/kill/__init__.py index a43677d4..4ed37d4b 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -19,7 +19,7 @@ class Plugin(QueryHandler): icon_path = "xdg:process-stop" def id(self): - return __name__ + return md_id def name(self): return md_name From 29582644bfc992f66d306ff91057b7fdb9d0682e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 30 Mar 2023 14:35:25 +0200 Subject: [PATCH 110/355] [vbox:v1.3] Port iid:0.5 --- .archive/virtualbox/README.md | 20 ------ .archive/virtualbox/__init__.py | 118 -------------------------------- virtualbox/__init__.py | 100 +++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 138 deletions(-) delete mode 100644 .archive/virtualbox/README.md delete mode 100644 .archive/virtualbox/__init__.py create mode 100644 virtualbox/__init__.py diff --git a/.archive/virtualbox/README.md b/.archive/virtualbox/README.md deleted file mode 100644 index d7b8c8b4..00000000 --- a/.archive/virtualbox/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Python virtualbox - - -```bash -cd /usr/lib/virtualbox -URL="https://download.virtualbox.org/virtualbox/6.1.16/VirtualBoxSDK-6.1.16-140961.zip" -wget "$URL" -unzip $(basename $URL) - -cd sdk/installer - -export VBOX_INSTALL_PATH=/usr/lib/virtualbox -export VBOX_SDK_PATH=/usr/lib/virtualbox/sdk -export PYTHONPATH=/usr/lib/virtualbox/sdk/bindings/xpcom/python -python vboxapisetup.py install - - -Gave it up here - -``` diff --git a/.archive/virtualbox/__init__.py b/.archive/virtualbox/__init__.py deleted file mode 100644 index d42dcdbe..00000000 --- a/.archive/virtualbox/__init__.py +++ /dev/null @@ -1,118 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Manage your VirtualBox machines. - -Synopsis: - - [filter]""" - -from virtualbox import Session, VirtualBox -from virtualbox.library import (LockType, MachineState, OleErrorInvalidarg, - OleErrorUnexpected, VBoxErrorFileError, - VBoxErrorHostError, - VBoxErrorInvalidObjectState, - VBoxErrorInvalidVmState, VBoxErrorIprtError, - VBoxErrorObjectNotFound) - -from albert import FuncAction, Item, critical, iconLookup - -__title__ = "Virtual Box" -__version__ = "0.4.2" -__triggers__ = "vbox " -__authors__ = "Manuel S." -__py_deps__ = ['virtualbox'] - -vbox = None - -iconPath = iconLookup(["virtualbox", "unknown"]) - -def initialize(): - global vbox - vbox = VirtualBox() - -def finalize(): - pass - -def startVm(vm): - try: - with Session() as session: - vm.launch_vm_process(session, 'gui', '') - except OleErrorUnexpected as e: - warning("OleErrorUnexpected") - except OleErrorInvalidarg as e: - warning("OleErrorInvalidarg") - except VBoxErrorObjectNotFound as e: - warning("VBoxErrorObjectNotFound") - except VBoxErrorInvalidObjectState as e: - warning("VBoxErrorInvalidObjectState") - except VBoxErrorInvalidVmState as e: - warning("VBoxErrorInvalidVmState") - except VBoxErrorIprtError as e: - warning("VBoxErrorIprtError") - except VBoxErrorHostError as e: - warning("VBoxErrorHostError") - except VBoxErrorFileError as e: - warning("VBoxErrorFileError") - -def acpiPowerVm(vm): - with vm.create_session(LockType.shared) as session: - session.console.power_button() - -def stopVm(vm): - with vm.create_session(LockType.shared) as session: - session.console.power_down() - -def saveVm(vm): - with vm.create_session(LockType.shared) as session: - session.machine.save_state() - -def discardSavedVm(vm): - with vm.create_session(LockType.shared) as session: - session.machine.discard_save_state(True); - -def resumeVm(vm): - with vm.create_session(LockType.shared) as session: - session.console.resume() - -def pauseVm(vm): - with vm.create_session(LockType.shared) as session: - session.console.pause() - -def buildVmItem(vm): - item = Item( - id=vm.__uuid__, - icon=iconPath, - text=vm.name, - subtext="{vm.state}".format(vm=vm), - completion=vm.name - ) - - if vm.state == MachineState.powered_off: #1 - item.addAction(FuncAction(text="Start virtual machine", callable=lambda: startVm(vm))) - if vm.state == MachineState.saved: #2 - item.addAction(FuncAction(text="Restore virtual machine", callable=lambda: startVm(vm))) - item.addAction(FuncAction(text="Discard saved state", callable=lambda: discardSavedVm(vm))) - if vm.state == MachineState.aborted: #4 - item.addAction(FuncAction(text="Start virtual machine", callable=lambda: startVm(vm))) - if vm.state == MachineState.running: #5 - item.addAction(FuncAction(text="Save virtual machine", callable=lambda: saveVm(vm))) - item.addAction(FuncAction(text="Power off via ACPI event (Power button)", callable=lambda: acpiPowerVm(vm))) - item.addAction(FuncAction(text="Turn off virtual machine", callable=lambda: stopVm(vm))) - item.addAction(FuncAction(text="Pause virtual machine", callable=lambda: pauseVm(vm))) - if vm.state == MachineState.paused: #6 - item.addAction(FuncAction(text="Resume virtual machine", callable=lambda: resumeVm(vm))) - - return item - - -def handleQuery(query): - pattern = query.string.strip().lower() - results = [] - try: - for vm in vbox.machines: - albert.critical(vm.name) - if (pattern and pattern in vm.name.lower() or not pattern and query.isTriggered): - results.append(buildVmItem(vm)) - except Exception as e: - critical(str(e)) - return results diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py new file mode 100644 index 00000000..7b789696 --- /dev/null +++ b/virtualbox/__init__.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- + +import virtualbox +from virtualbox.library import LockType, MachineState + +from albert import * + +md_iid = "0.5" +md_version = "1.3" +md_name = "VirtualBox" +md_description = "Manage your VirtualBox machines" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/virtualbox" +md_maintainers = "@manuelschneid3r" +md_lib_dependencies = ['virtualbox'] + + +def startVm(vm): + try: + with virtualbox.Session() as session: + progress = vm.launch_vm_process(session, 'gui', []) + progress.wait_for_completion() + except Exception as e: + warning(str(e)) + +def acpiPowerVm(vm): + with vm.create_session(LockType.shared) as session: + session.console.power_button() + +def stopVm(vm): + with vm.create_session(LockType.shared) as session: + session.console.power_down() + +def saveVm(vm): + with vm.create_session(LockType.shared) as session: + session.machine.save_state() + +def discardSavedVm(vm): + with vm.create_session(LockType.shared) as session: + session.machine.discard_save_state(True); + +def resumeVm(vm): + with vm.create_session(LockType.shared) as session: + session.console.resume() + +def pauseVm(vm): + with vm.create_session(LockType.shared) as session: + session.console.pause() + +class Plugin(QueryHandler): + iconUrls = ["xdg:virtualbox", ":unknown"] + + def id(self): + return md_id + + def name(self): + return md_name + + def description(self): + return md_description + + def synopsis(self): + return "" + + def defaultTrigger(self): + return "vbox " + + def handleQuery(self, query): + items = [] + pattern = query.string.strip().lower() + try: + for vm in filter(lambda vm: pattern in vm.name.lower(), virtualbox.VirtualBox().machines): + actions = [] + if vm.state == MachineState.powered_off or vm.state == MachineState.aborted: #1 #4 + actions.append(Action("startvm", "Start virtual machine", lambda vm=vm: startVm(vm))) + if vm.state == MachineState.saved: #2 + actions.append(Action("restorevm", "Start saved virtual machine", lambda vm=vm: startVm(vm))) + actions.append(Action("discardvm", "Discard saved state", lambda vm=vm: discardSavedVm(vm))) + if vm.state == MachineState.running: #5 + actions.append(Action("savevm", "Save virtual machine", lambda vm=vm: saveVm(vm))) + actions.append(Action("poweroffvm", "Power off via ACPI event (Power button)", lambda vm=vm: acpiPowerVm(vm))) + actions.append(Action("stopvm", "Turn off virtual machine", lambda vm=vm: stopVm(vm))) + actions.append(Action("pausevm", "Pause virtual machine", lambda vm=vm: pauseVm(vm))) + if vm.state == MachineState.paused: #6 + actions.append(Action("resumevm", "Resume virtual machine", lambda vm=vm: resumeVm(vm))) + + items.append( + Item( + id=vm.__uuid__, + text=vm.name, + subtext="{vm.state}".format(vm=vm), + completion=vm.name, + icon=self.iconUrls, + actions=actions + ) + ) + except Exception as e: + warning(str(e)) + + query.add(items) From b7ddaea0528076c579b6eff826d195d202576426 Mon Sep 17 00:00:00 2001 From: Thomas Queste Date: Mon, 17 Apr 2023 15:12:05 +0200 Subject: [PATCH 111/355] [jetbrains_projects] handle missing projectOpenTimestamp The new version of Intellij IDEA can contain a "liveEdit" project type in its recentProjects.xml. This XML entry has no "recent" tag, which make the convertion `int(None)` fails. --- jetbrains_projects/__init__.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 21a019db..48f3b5d4 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -16,7 +16,7 @@ from albert import * md_iid = "0.5" -md_version = "1.1" +md_version = "1.2" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "GPL-3" @@ -71,15 +71,11 @@ def _parse_recent_projects(self, recent_projects_file: Path) -> list[Project]: project_path = entry.attrib["key"].replace("$USER_HOME$", str(Path.home())) tag_opened = entry.find(".//option[@name='projectOpenTimestamp']") - last_opened = int( - tag_opened.attrib["value"] - if tag_opened is not None and "value" in tag_opened.attrib - else None - ) + last_opened = tag_opened.attrib["value"] if tag_opened is not None and "value" in tag_opened.attrib else None if project_path and last_opened: projects.append( - Project(name=Path(project_path).name, path=project_path, last_opened=last_opened) + Project(name=Path(project_path).name, path=project_path, last_opened=int(last_opened)) ) return projects except ElementTree.ParseError: From 43f3b931dd9bccf4cf69a362c7aeba8973d4596e Mon Sep 17 00:00:00 2001 From: Gaganpreet Date: Mon, 24 Apr 2023 12:06:02 +0200 Subject: [PATCH 112/355] [aur:1.6] Fix install action --- aur/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aur/__init__.py b/aur/__init__.py index f49326f9..9a5f3a5b 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -15,7 +15,7 @@ import os md_iid = "0.5" -md_version = "1.5" +md_version = "1.6" md_name = "AUR" md_description = "Query and install AUR packages" md_license = "BSD-3" @@ -106,7 +106,7 @@ def handleQuery(self, query): actions = [] if self.install_cmdline: - pacman = install_cmdline.split(" ", 1)[0] + pacman = self.install_cmdline.split(" ", 1)[0] actions.append(Action( id="inst", text="Install using %s" % pacman, From 16b3b1887715125ccbcae1b8f5ca35a8cadfb0fa Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 1 May 2023 15:22:04 +0200 Subject: [PATCH 113/355] remove api_test --- api_test/__init__.py | 133 ------------------------------------------- api_test/plugin.svg | 1 - 2 files changed, 134 deletions(-) delete mode 100644 api_test/__init__.py delete mode 100644 api_test/plugin.svg diff --git a/api_test/__init__.py b/api_test/__init__.py deleted file mode 100644 index 5e088e50..00000000 --- a/api_test/__init__.py +++ /dev/null @@ -1,133 +0,0 @@ -# -*- coding: utf-8 -*- - -"""This is a simple python template extension. - -This extension should show the API in a comprehensible way. Use the module docstring to provide a \ -description of the extension. The docstring should have three paragraphs: A brief description in \ -the first line, an optional elaborate description of the plugin, and finally the synopsis of the \ -extension. - -Synopsis: [delay|throw] """ - -# Copyright (c) 2022-2023 Manuel Schneider - -from albert import * -import os -from time import sleep - -md_iid = "0.5" -md_version = "1.3" -md_name = "API Test" -md_description = "Test the python API 0.5" -md_license = "BSD-3" -md_url = "https://github.com/albertlauncher/python/tree/master/api_test" -md_maintainers = "@manuelschneid3r" - - -class Plugin(QueryHandler): - def id(self): - return "test"; - - def name(self): - return "somename"; - - def description(self): - return "somedesc"; - - def initialize(self): - info("initialize") - - def finalize(self): - info("finalize") - - def extensions(self): - return [self.e] - - def handleQuery(self, query): - # Note that when storing a reference to query, e.g. in a closure, you must not use - # query.isValid. Apart from the query being invalid anyway it will crash the application. - # The Python type holds a pointer to the C++ type used for isValid(). The C++ type will be - # deleted when the query is finished. Therefore getting isValid will result in a SEGFAULT. - - if query.string.startswith("delay"): - sleep(2) - return query.add(Item(id=md_id, - text="Delayed test item", - subtext="Query string: %s" % query.string, - icon=[os.path.dirname(__file__)+"/plugin.svg"])) - - if query.string.startswith("throw"): - raise ValueError('EXPLICITLY REQUESTED TEST EXCEPTION!') - - info(query.string) - info(query.trigger) - info(str(query.isValid)) - - critical(query.string) - warning(query.string) - debug(query.string) - debug(query.string) - - results = [] - - item = Item() - - item.icon = ['xdg:albert'] - item.text = 'Python item containing %s' % query.string - item.subtext = 'Python description' - item.completion = 'Completion test' - info(item.icon) - info(item.text) - info(item.subtext) - info(item.completion) - results.append(item) - - item = Item(id=md_id, - text="This is the primary text", - subtext="This is the subtext, some kind of description", - completion='Hellooohooo!', - icon=[os.path.dirname(__file__)+"/plugin.svg"], - actions=[ - Action( - id="clip", - text="setClipboardText (ClipAction)", - callable=lambda: setClipboardText(text=configLocation()) - ), - Action( - id="url", - text="openUrl (UrlAction)", - callable=lambda: openUrl(url="https://www.google.de") - ), - Action( - id="run", - text="runDetachedProcess (ProcAction)", - callable=lambda: runDetachedProcess( - cmdln=["espeak", "hello"], - workdir="~" - ) - ), - Action( - id="term", - text="runTerminal (TermAction)", - callable=lambda: runTerminal( - script="[ -e issue ] && cat issue | echo /etc/issue not found.", - workdir="/etc", - close_on_exit=False - ) - ), - Action( - id="notify", - text="sendTrayNotification", - callable=lambda: sendTrayNotification( - title="Title", - msg="Message" - ) - ) - ]) - results.append(item) - - info(configLocation()) - info(cacheLocation()) - info(dataLocation()) - - query.add(results) diff --git a/api_test/plugin.svg b/api_test/plugin.svg deleted file mode 100644 index 6cbefc6d..00000000 --- a/api_test/plugin.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 68e11eb334b74a8cee5a8ce023394fc1d97a410f Mon Sep 17 00:00:00 2001 From: Thomas Queste Date: Mon, 1 May 2023 15:27:30 +0200 Subject: [PATCH 114/355] [locate:1.7] Fix lambda capture Fix: https://github.com/albertlauncher/python/issues/167 --- locate/__init__.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/locate/__init__.py b/locate/__init__.py index d0c14ab0..180e76a5 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -11,17 +11,17 @@ import os import pathlib import shlex -import re import subprocess md_iid = "0.5" -md_version = "1.6" +md_version = "1.7" md_name = "Locate" -md_description = "Find ond open files using locate" +md_description = "Find and open files using locate" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/locate" md_bin_dependencies = "locate" + class Plugin(QueryHandler): def id(self): @@ -57,9 +57,11 @@ def handleQuery(self, query): return result = subprocess.run(['locate', *args], stdout=subprocess.PIPE, text=True) - if not query.isValid: return + if not query.isValid: + return lines = sorted(result.stdout.splitlines(), reverse=True) - if not query.isValid: return + if not query.isValid: + return for path in lines: basename = os.path.basename(path) @@ -70,7 +72,7 @@ def handleQuery(self, query): subtext=path, icon=self.icons, actions=[ - Action("open", "Open", lambda: openUrl("file://%s" % path)) + Action("open", "Open", lambda p=path: openUrl("file://%s" % p)) ] ) ) @@ -86,9 +88,3 @@ def handleQuery(self, query): ] ) ) - - - - - - From 962a832cc35377d5c719147800368a3e83703646 Mon Sep 17 00:00:00 2001 From: Oskar Haarklou Veileborg Date: Mon, 1 May 2023 15:30:00 +0200 Subject: [PATCH 115/355] [python_eval:1.3] Fix type of result in item subtext --- python_eval/__init__.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/python_eval/__init__.py b/python_eval/__init__.py index 5834792b..6f962eb3 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -7,7 +7,7 @@ import os md_iid = "0.5" -md_version = "1.2" +md_version = "1.3" md_name = "Python Eval" md_description = "Evaluate Python code" md_license = "BSD-3" @@ -39,18 +39,20 @@ def handleQuery(self, query): stripped = query.string.strip() if stripped: try: - result = str(eval(stripped)) + result = eval(stripped) except Exception as ex: - result = str(ex) + result = ex + + result_str = str(result) query.add(Item( id=md_id, - text=str(result), + text=result_str, subtext=type(result).__name__, - completion=query.trigger + result, + completion=query.trigger + result_str, icon=[self.iconPath], actions = [ - Action("copy", "Copy result to clipboard", lambda r=str(result): setClipboardText(r)), - Action("exec", "Execute python code", lambda r=str(result): exec(stripped)), + Action("copy", "Copy result to clipboard", lambda r=result_str: setClipboardText(r)), + Action("exec", "Execute python code", lambda r=result_str: exec(stripped)), ] )) From 7e07e375852527cdf5b472a606b360b4ddee0137 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 17 May 2023 10:40:13 +0200 Subject: [PATCH 116/355] Add telegram issue notifier workflow --- .github/workflows/telegram_notify_issues.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/telegram_notify_issues.yml diff --git a/.github/workflows/telegram_notify_issues.yml b/.github/workflows/telegram_notify_issues.yml new file mode 100644 index 00000000..533f66b9 --- /dev/null +++ b/.github/workflows/telegram_notify_issues.yml @@ -0,0 +1,16 @@ +name: Telegram Notifications + +on: + issues: + types: [opened, reopened, deleted, closed] + +jobs: + notify: + + runs-on: ubuntu-latest + + steps: + - name: Send notifications to Telegram + run: curl -s -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_NOTIFIER_BOT_TOKEN }}/sendMessage -d chat_id=${{ secrets.TELEGRAM_ALBERT_CHAT_ID }} -d text="${MESSAGE}" >> /dev/null + env: + MESSAGE: "Issue ${{ github.event.action }}: \n${{ github.event.issue.html_url }}" From c5f707534ef64e303851042e15ea23b1796f670f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 3 May 2023 15:52:50 +0200 Subject: [PATCH 117/355] [all] Adopt iid v1.0 --- arch_wiki/__init__.py | 8 ++-- aur/__init__.py | 8 ++-- bitwarden/__init__.py | 8 ++-- copyq/__init__.py | 8 ++-- dice_roll/__init__.py | 8 ++-- docker/__init__.py | 86 +++++++++++++++++++--------------- emoji/__init__.py | 8 ++-- goldendict/__init__.py | 10 ++-- googletrans/__init__.py | 8 ++-- jetbrains_projects/__init__.py | 10 ++-- kill/__init__.py | 8 ++-- locate/__init__.py | 8 ++-- pacman/__init__.py | 10 ++-- pass/__init__.py | 8 ++-- pomodoro/__init__.py | 8 ++-- python_eval/__init__.py | 8 ++-- tex_to_unicode/__init__.py | 8 ++-- timer/__init__.py | 8 ++-- unit_converter/__init__.py | 8 ++-- virtualbox/__init__.py | 8 ++-- vpn/__init__.py | 8 ++-- wikipedia/__init__.py | 8 ++-- youtube/__init__.py | 10 ++-- 23 files changed, 141 insertions(+), 129 deletions(-) diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index f6474431..0c531506 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -7,8 +7,8 @@ import json import os -md_iid = "0.5" -md_version = "1.2" +md_iid = '1.0' +md_version = "1.3" md_name = "ArchLinux Wiki" md_description = "Search ArchLinux Wiki articles" md_license = "BSD-3" @@ -16,7 +16,7 @@ md_maintainers = "@manuelschneid3r" -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): icon = [os.path.dirname(__file__) + "/ArchWiki.svg"] baseurl = 'https://wiki.archlinux.org/api.php' @@ -35,7 +35,7 @@ def description(self): def defaultTrigger(self): return "awiki " - def handleQuery(self, query): + def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: diff --git a/aur/__init__.py b/aur/__init__.py index 9a5f3a5b..6d9e6c13 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -14,8 +14,8 @@ import json import os -md_iid = "0.5" -md_version = "1.6" +md_iid = '1.0' +md_version = "1.7" md_name = "AUR" md_description = "Query and install AUR packages" md_license = "BSD-3" @@ -23,7 +23,7 @@ md_maintainers = "@manuelschneid3r" -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): aur_url = "https://aur.archlinux.org/packages/" baseurl = 'https://aur.archlinux.org/rpc/' @@ -55,7 +55,7 @@ def initialize(self): info("No supported AUR helper found.") self.install_cmdline = None - def handleQuery(self, query): + def handleTriggerQuery(self, query): for number in range(50): sleep(0.01) if not query.isValid: diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 3f482cfa..0185358b 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = "0.5" -md_version = "1.1" +md_iid = '1.0' +md_version = "1.2" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" md_license = "BSD-3" @@ -15,7 +15,7 @@ md_credits = "Original author: @tylio" md_bin_dependencies = ["rbw"] -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self): return md_id @@ -51,7 +51,7 @@ def _get_passwords(self): return passwords - def handleQuery(self, query): + def handleTriggerQuery(self, query): if query.string.strip().lower() == "unlock": query.add( Item( diff --git a/copyq/__init__.py b/copyq/__init__.py index fa1104c0..7c241b55 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = "0.5" -md_version = "1.2" +md_iid = '1.0' +md_version = "1.3" md_name = "CopyQ" md_description = "Access CopyQ clipboard" md_license = "BSD-2-Clause" @@ -45,7 +45,7 @@ """ -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self): return md_id @@ -61,7 +61,7 @@ def synopsis(self): def defaultTrigger(self): return "cq " - def handleQuery(self, query): + def handleTriggerQuery(self, query): items = [] q_string = query.string diff --git a/dice_roll/__init__.py b/dice_roll/__init__.py index 4606d541..944e054c 100644 --- a/dice_roll/__init__.py +++ b/dice_roll/__init__.py @@ -14,8 +14,8 @@ Example: "roll 2d6 3d8 1d20" """ -md_iid = "0.5" -md_version = "1.0" +md_iid = '1.0' +md_version = "1.1" md_name = "Dice Roll" md_description = "Roll any number of dice" md_license = "MIT" @@ -128,7 +128,7 @@ def get_items(query_string: str) -> list[albert.Item]: return results -class Plugin(albert.QueryHandler): +class Plugin(albert.TriggerQueryHandler): """A plugin to roll dice""" def id(self) -> str: @@ -146,7 +146,7 @@ def synopsis(self) -> str: def defaultTrigger(self) -> str: return "roll " - def handleQuery(self, query: albert.Query) -> None: + def handleTriggerQuery(self, query: albert.TriggerQuery) -> None: query_string = query.string.strip() try: items = get_items(query_string) diff --git a/docker/__init__.py b/docker/__init__.py index a6f2ec28..eb8fb412 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -8,8 +8,8 @@ import pathlib import docker -md_iid = "0.5" -md_version = "1.3" +md_iid = "1.0" +md_version = "1.4" md_name = "Docker" md_description = "Control your docker instance" md_license = "BSD-3" @@ -41,43 +41,55 @@ def initialize(self): if not self.client: raise "Failed to initialize client." + def handleGlobalQuery(self, query): + rank_items = [] - def handleQuery(self, query): for container in self.client.containers.list(all=True): + if query.string in container.name: + # Create dynamic actions + if container.status == 'running': + actions = [ + Action("stop", "Stop container", lambda c=container: c.stop()), + Action("restart", "Restart container", lambda c=container: c.restart()) + ] + else: + actions = [ + Action("start", "Start container", lambda c=container: c.start()) + ] + actions.extend([ + Action("logs", "Logs", lambda c=container.id: runTerminal("docker logs -f %s" % c, close_on_exit=False)), + Action("remove", "Remove (forced, with volumes)", lambda c=container: c.remove(v=True, force=True)), + Action("copy-id", "Copy id to clipboard", lambda id=container.id: setClipboardText(id)) + ]) - # Create dynamic actions - if container.status == 'running': - actions = [ - Action("stop", "Stop container", lambda c=container: c.stop()), - Action("restart", "Restart container", lambda c=container: c.restart()) - ] - else: - actions = [ - Action("start", "Start container", lambda c=container: c.start()) - ] - actions.extend([ - Action("logs", "Logs", lambda c=container.id: runTerminal("docker logs -f %s" % c, close_on_exit=False)), - Action("remove", "Remove (forced, with volumes)", lambda c=container: c.remove(v=True, force=True)), - Action("copy-id", "Copy id to clipboard", lambda id=container.id: setClipboardText(id)) - ]) - - query.add(Item( - id=container.id, - text="%s (%s)" % (container.name, ", ".join(container.image.tags)), - subtext=container.id, - icon=self.icon_running if container.status == 'running' else self.icon_stopped, - actions=actions - )) + rank_items.append(RankItem( + item=Item( + id=container.id, + text="%s (%s)" % (container.name, ", ".join(container.image.tags)), + subtext="Container: %s" % container.id, + icon=self.icon_running if container.status == 'running' else self.icon_stopped, + actions=actions + ), + score=0 # len(query.string)/len(container.name) + )) for image in reversed(self.client.images.list()): - query.add(Item( - id=image.short_id, - text=str(image.tags), - subtext=image.id, - icon=self.icon_stopped, - actions=[ - Action("run", "Run with command: %s" % query.string, - lambda i=image, s=query.string: client.containers.run(i, s)), - Action("rmi", "Remove image", lambda i=image: i.remove()) - ] - )) + if any([query.string in tag for tag in image.tags]): + rank_items.append(RankItem( + item=Item( + id=image.short_id, + text=", ".join(image.tags), + subtext="Image: %s" % image.id, + icon=self.icon_stopped, + actions=[ + Action("run", "Run with command: %s" % query.string, + lambda i=image, s=query.string: client.containers.run(i, s)), + Action("rmi", "Remove image", lambda i=image: i.remove()) + ] + ), + score=0 + )) + + + return rank_items + diff --git a/emoji/__init__.py b/emoji/__init__.py index e8df5a88..9b4304ea 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -13,8 +13,8 @@ from albert import Action, Item, QueryHandler, cacheLocation, setClipboardText -md_iid = "0.5" -md_version = "1.0" +md_iid = '1.0' +md_version = "1.1" md_name = "Emoji Picker" md_description = "Find emojis by name" md_license = "GPL-3.0" @@ -60,7 +60,7 @@ def schedule_create_missing_icons(emojis): return executor -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self): return __name__ @@ -126,7 +126,7 @@ def matched_emojis(self, query_tokens): yield emoji - def handleQuery(self, query): + def handleTriggerQuery(self, query): query_tokens = query.string.strip().lower().split() if not query_tokens: return diff --git a/goldendict/__init__.py b/goldendict/__init__.py index 6f9c516f..c1bbd3db 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -1,7 +1,7 @@ -from albert import Action, Item, Query, QueryHandler, runDetachedProcess # pylint: disable=import-error +from albert import Action, Item, TriggerQuery, TriggerQueryHandler, runDetachedProcess # pylint: disable=import-error -md_iid = '0.5' -md_version = '1.1' +md_iid = '1.0' +md_version = '1.2' md_name = 'GoldenDict' md_description = 'Searches in GoldenDict' md_url = 'https://github.com/albertlauncher/python/' @@ -12,7 +12,7 @@ ICON_PATH = '/usr/share/pixmaps/goldendict.png' -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self) -> str: return __name__ @@ -28,7 +28,7 @@ def defaultTrigger(self) -> str: def synopsis(self) -> str: return 'query' - def handleQuery(self, query: Query) -> None: + def handleTriggerQuery(self, query: TriggerQuery) -> None: query_str = query.string.strip() if not query_str: return diff --git a/googletrans/__init__.py b/googletrans/__init__.py index c89f7c54..65e3873d 100644 --- a/googletrans/__init__.py +++ b/googletrans/__init__.py @@ -10,8 +10,8 @@ from time import sleep import os -md_iid = "0.5" -md_version = "1.0" +md_iid = '1.0' +md_version = "1.1" md_name = "Google Translate" md_description = "Translate sentences using googletrans" md_license = "BSD-3" @@ -19,7 +19,7 @@ md_lib_dependencies = "googletrans==3.1.0a0" md_maintainers = "@manuelschneid3r" -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self): return md_id @@ -41,7 +41,7 @@ def initialize(self): self.translator = Translator() self.lang = getdefaultlocale()[0][0:2] - def handleQuery(self, query): + def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: for number in range(50): diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 48f3b5d4..43ca93cc 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -15,8 +15,8 @@ from xml.etree import ElementTree from albert import * -md_iid = "0.5" -md_version = "1.2" +md_iid = '1.0' +md_version = "1.3" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "GPL-3" @@ -82,7 +82,7 @@ def _parse_recent_projects(self, recent_projects_file: Path) -> list[Project]: return [] -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): executables = [] def id(self): @@ -161,7 +161,7 @@ def initialize(self): ] self.editors = [e for e in editors if e.binary is not None] - def handleQuery(self, query: Query): + def handleTriggerQuery(self, query: TriggerQuery): editor_project_pairs = [] for editor in self.editors: projects = editor.list_projects() @@ -174,7 +174,7 @@ def handleQuery(self, query: Query): query.add([self._make_item(editor, project, query) for editor, project in editor_project_pairs]) - def _make_item(self, editor: Editor, project: Project, query: Query) -> Item: + def _make_item(self, editor: Editor, project: Project, query: TriggerQuery) -> Item: return Item( id="%s-%s-%s" % (editor.binary, project.path, project.last_opened), text=project.name, diff --git a/kill/__init__.py b/kill/__init__.py index 4ed37d4b..7aec13c8 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = "0.5" -md_version = "1.1" +md_iid = '1.0' +md_version = "1.2" md_name = "Kill Process" md_description = "Kill processes" md_license = "BSD-3" @@ -15,7 +15,7 @@ md_credits = "Original idea by Benedict Dudel & Manuel Schneider" -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): icon_path = "xdg:process-stop" def id(self): @@ -33,7 +33,7 @@ def initialize(self): def defaultTrigger(self): return "kill " - def handleQuery(self, query): + def handleTriggerQuery(self, query): if not query.isValid: return results = [] diff --git a/locate/__init__.py b/locate/__init__.py index 180e76a5..40fef9bb 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -13,8 +13,8 @@ import shlex import subprocess -md_iid = "0.5" -md_version = "1.7" +md_iid = '1.0' +md_version = "1.8" md_name = "Locate" md_description = "Find and open files using locate" md_license = "BSD-3" @@ -22,7 +22,7 @@ md_bin_dependencies = "locate" -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self): return md_id @@ -48,7 +48,7 @@ def initialize(self): str(pathlib.Path(__file__).parent / "locate.svg") ] - def handleQuery(self, query): + def handleTriggerQuery(self, query): if len(query.string) > 2: try: diff --git a/pacman/__init__.py b/pacman/__init__.py index a15efefe..0b2ee192 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -9,10 +9,10 @@ from time import sleep import pathlib -from albert import Action, Item, QueryHandler, runTerminal, openUrl +from albert import Action, Item, TriggerQueryHandler, runTerminal, openUrl -md_iid = "0.5" -md_version = "1.6" +md_iid = '1.0' +md_version = "1.7" md_name = "PacMan" md_description = "Search, install and remove packages" md_license = "BSD-3" @@ -20,7 +20,7 @@ md_bin_dependencies = ["pacman", "expac"] -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): pkgs_url = "https://www.archlinux.org/packages/" @@ -46,7 +46,7 @@ def initialize(self): str(pathlib.Path(__file__).parent / "arch.svg") ] - def handleQuery(self, query): + def handleTriggerQuery(self, query): stripped = query.string.strip() # Update item on empty queries diff --git a/pass/__init__.py b/pass/__init__.py index 7bd3b62c..0a76a51f 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -4,8 +4,8 @@ import os from albert import * -md_iid = "0.5" -md_version = "1.2" +md_iid = '1.0' +md_version = "1.3" md_name = "Pass" md_description = "Manage passwords in pass" md_bin_dependencies = ["pass"] @@ -16,7 +16,7 @@ PASS_DIR = os.environ.get("PASSWORD_STORE_DIR", os.path.join(HOME_DIR, ".password-store/")) ICON = ["xdg:dialog-password"] -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self): return md_id @@ -33,7 +33,7 @@ def synopsis(self): def defaultTrigger(self): return "pass " - def handleQuery(self, query): + def handleTriggerQuery(self, query): if query.string.strip().startswith("generate"): self.generatePassword(query) else: diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 24cef355..53faba9b 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -11,8 +11,8 @@ import time import os -md_iid = "0.5" -md_version = "1.1" +md_iid = '1.0' +md_version = "1.2" md_name = "Pomodoro" md_description = "Set up a Pomodoro timer" md_license = "BSD-3" @@ -66,7 +66,7 @@ def isActive(self): return self.timer is not None -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): icon = [os.path.dirname(__file__) + "/pomodoro.svg"] default_pomodoro_duration = 25 @@ -92,7 +92,7 @@ def initialize(self): def synopsis(self): return "[duration [break duration [long break duration [count]]]]" - def handleQuery(self, query): + def handleTriggerQuery(self, query): item = Item( id=md_id, icon=self.icon, diff --git a/python_eval/__init__.py b/python_eval/__init__.py index 6f962eb3..71a480ff 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -6,8 +6,8 @@ from math import * import os -md_iid = "0.5" -md_version = "1.3" +md_iid = '1.0' +md_version = "1.4" md_name = "Python Eval" md_description = "Evaluate Python code" md_license = "BSD-3" @@ -15,7 +15,7 @@ md_maintainers = "@manuelschneid3r" -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self): return md_id @@ -35,7 +35,7 @@ def synopsis(self): def initialize(self): self.iconPath = os.path.dirname(__file__)+"/python.svg" - def handleQuery(self, query): + def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: try: diff --git a/tex_to_unicode/__init__.py b/tex_to_unicode/__init__.py index e0e38eb5..4fbdffed 100644 --- a/tex_to_unicode/__init__.py +++ b/tex_to_unicode/__init__.py @@ -9,8 +9,8 @@ from albert import * from pylatexenc.latex2text import LatexNodes2Text -md_iid = "0.5" -md_version = "1.0" +md_iid = '1.0' +md_version = "1.1" md_name = "TeX to Unicode" md_description = "Convert TeX mathmode commands to unicode characters" md_license = "GPL-3.0" @@ -19,7 +19,7 @@ md_maintainers = "@DenverCoder1" -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def id(self) -> str: return md_id @@ -57,7 +57,7 @@ def _create_item(self, text: str, subtext: str, can_copy: bool) -> Item: actions=actions, ) - def handleQuery(self, query: Query) -> None: + def handleTriggerQuery(self, query: Query) -> None: stripped = query.string.strip() if not stripped: diff --git a/timer/__init__.py b/timer/__init__.py index a6ce8ae9..5fc96bbb 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -18,8 +18,8 @@ import os import subprocess -md_iid = "0.5" -md_version = "1.4" +md_iid = '1.0' +md_version = "1.5" md_name = "Timer" md_description = "Set up timers" md_license = "BSD-2" @@ -37,7 +37,7 @@ def __init__(self, interval, name, callback): self.start() -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): def initialize(self): self.icons = [os.path.dirname(__file__)+"/time.svg"] @@ -83,7 +83,7 @@ def defaultTrigger(self): def synopsis(self): return '[[hrs:]mins:]secs [name]' - def handleQuery(self, query): + def handleTriggerQuery(self, query): if not query.isValid: return diff --git a/unit_converter/__init__.py b/unit_converter/__init__.py index 3a4a840d..d25f547f 100644 --- a/unit_converter/__init__.py +++ b/unit_converter/__init__.py @@ -29,8 +29,8 @@ import pint -md_iid = "0.5" -md_version = "1.2" +md_iid = '1.0' +md_version = "1.3" md_name = "Unit Converter" md_description = "Convert between units" md_license = "MIT" @@ -309,7 +309,7 @@ def convert(self, amount: float, from_unit: str, to_unit: str) -> ConversionResu ) -class Plugin(albert.QueryHandler): +class Plugin(albert.TriggerQueryHandler): """The plugin class""" unit_convert_regex = re.compile( @@ -370,7 +370,7 @@ def synopsis(self) -> str: def defaultTrigger(self) -> str: return "convert " - def handleQuery(self, query: albert.Query) -> None: + def handleTriggerQuery(self, query: albert.TriggerQuery) -> None: query_string = query.string.strip() match = self.unit_convert_regex.fullmatch(query_string) if match: diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py index 7b789696..f084bcfe 100644 --- a/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = "0.5" -md_version = "1.3" +md_iid = '1.0' +md_version = "1.4" md_name = "VirtualBox" md_description = "Manage your VirtualBox machines" md_license = "BSD-3" @@ -47,7 +47,7 @@ def pauseVm(vm): with vm.create_session(LockType.shared) as session: session.console.pause() -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): iconUrls = ["xdg:virtualbox", ":unknown"] def id(self): @@ -65,7 +65,7 @@ def synopsis(self): def defaultTrigger(self): return "vbox " - def handleQuery(self, query): + def handleTriggerQuery(self, query): items = [] pattern = query.string.strip().lower() try: diff --git a/vpn/__init__.py b/vpn/__init__.py index 44af6857..3d6fae20 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -2,8 +2,8 @@ from collections import namedtuple import subprocess -md_iid = "0.5" -md_version = "1.2" +md_iid = '1.0' +md_version = "1.3" md_id = "vpn" md_name = "VPN" md_description = "Manage NetworkManager VPN connections" @@ -14,7 +14,7 @@ md_bin_dependencies = ["nmcli"] -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): iconPath = ['xdg:network-wired'] @@ -56,7 +56,7 @@ def buildItem(self,con): ) - def handleQuery(self,query): + def handleTriggerQuery(self,query): if query.isValid: connections = self.getVPNConnections() if query.string: diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 99f39a93..b4a9c921 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -10,8 +10,8 @@ import json import os -md_iid = "0.5" -md_version = "1.5" +md_iid = '1.0' +md_version = "1.6" md_name = "Wikipedia" md_description = "Search Wikipedia articles." md_license = "BSD-3" @@ -19,7 +19,7 @@ md_maintainers = "@manuelschneid3r" -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): iconPath = ":wikipedia" baseurl = 'https://en.wikipedia.org/w/api.php' @@ -63,7 +63,7 @@ def initialize(self): critical('Error getting languages (%s). Defaulting to EN.' % error) - def handleQuery(self, query): + def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: # avoid rate limiting diff --git a/youtube/__init__.py b/youtube/__init__.py index 598422f8..17f5bc9e 100644 --- a/youtube/__init__.py +++ b/youtube/__init__.py @@ -8,11 +8,11 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen -from albert import Action, Item, Query, QueryHandler, critical, info, openUrl # pylint: disable=import-error +from albert import Action, Item, TriggerQuery, TriggerQueryHandler, critical, info, openUrl # pylint: disable=import-error -md_iid = '0.5' -md_version = '1.3' +md_iid = '1.0' +md_version = '1.4' md_name = 'YouTube' md_description = 'Query and open YouTube videos and channels' md_url = 'https://github.com/albertlauncher/python/' @@ -111,7 +111,7 @@ def results_to_items(results: dict) -> list[Item]: return items -class Plugin(QueryHandler): +class Plugin(TriggerQueryHandler): temp_dir = None def id(self) -> str: @@ -137,7 +137,7 @@ def defaultTrigger(self) -> str: def synopsis(self) -> str: return 'query' - def handleQuery(self, query: Query) -> None: + def handleTriggerQuery(self, query: TriggerQuery) -> None: query_str = query.string.strip() if not query_str: return From 62c76a769b87dc85fae5f7ba8c3dd4d47b5ae776 Mon Sep 17 00:00:00 2001 From: Thomas Queste Date: Sat, 27 May 2023 15:14:24 +0200 Subject: [PATCH 118/355] [emoji:v1.2] Set correct import for iid 1.0 --- emoji/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index 9b4304ea..6e79c0c9 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -10,11 +10,10 @@ from concurrent.futures import ThreadPoolExecutor from itertools import islice from pathlib import Path - -from albert import Action, Item, QueryHandler, cacheLocation, setClipboardText +from albert import * md_iid = '1.0' -md_version = "1.1" +md_version = "1.2" md_name = "Emoji Picker" md_description = "Find emojis by name" md_license = "GPL-3.0" From 4940cc2efa82ed58346669e9e31476d31f8e9569 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 13 Jun 2023 11:53:05 +0200 Subject: [PATCH 119/355] adjust telegram notifications --- .../workflows/telegram_notify_comments.yml | 25 +++++++++++++++++++ .github/workflows/telegram_notify_issues.yml | 14 ++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/telegram_notify_comments.yml diff --git a/.github/workflows/telegram_notify_comments.yml b/.github/workflows/telegram_notify_comments.yml new file mode 100644 index 00000000..a7658abd --- /dev/null +++ b/.github/workflows/telegram_notify_comments.yml @@ -0,0 +1,25 @@ +name: Telegram Notifications + +on: + + issue_comment: + types: [created] + +jobs: + notify: + + runs-on: ubuntu-latest + + steps: + - name: Send notifications to Telegram + run: > + curl -s + -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_NOTIFIER_BOT_TOKEN }}/sendMessage + -d chat_id=${{ secrets.TELEGRAM_ALBERT_CHAT_ID }} + -d text="${MESSAGE}" + -d parse_mode=HTML + -d disable_web_page_preview=true + >> /dev/null + env: + MESSAGE: "${{ github.event.comment.user.login }} on
${{ github.event.repository.name }}#${{ github.event.issue.number }}: ${{ github.event.issue.title }}%0A${{ github.event.comment.body }}" + diff --git a/.github/workflows/telegram_notify_issues.yml b/.github/workflows/telegram_notify_issues.yml index 533f66b9..dfcc0ab4 100644 --- a/.github/workflows/telegram_notify_issues.yml +++ b/.github/workflows/telegram_notify_issues.yml @@ -2,7 +2,7 @@ name: Telegram Notifications on: issues: - types: [opened, reopened, deleted, closed] + types: [opened, reopened] jobs: notify: @@ -11,6 +11,14 @@ jobs: steps: - name: Send notifications to Telegram - run: curl -s -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_NOTIFIER_BOT_TOKEN }}/sendMessage -d chat_id=${{ secrets.TELEGRAM_ALBERT_CHAT_ID }} -d text="${MESSAGE}" >> /dev/null + run: > + curl -s + -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_NOTIFIER_BOT_TOKEN }}/sendMessage + -d chat_id=${{ secrets.TELEGRAM_ALBERT_CHAT_ID }} + -d text="${MESSAGE}" + -d parse_mode=HTML + -d disable_web_page_preview=true + >> /dev/null env: - MESSAGE: "Issue ${{ github.event.action }}: \n${{ github.event.issue.html_url }}" + MESSAGE: "New issue:%0A${{ github.event.repository.name }}#${{ github.event.issue.number }}: ${{ github.event.issue.title }}" + From 926e119ecf2dd2aa66209e047b41f1466d7b7b2f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 18 Jun 2023 09:41:21 +0200 Subject: [PATCH 120/355] [zeal] Port to iid v1.0 --- .archive/zeal/__init__.py | 29 ---------------------------- zeal/__init__.py | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 29 deletions(-) delete mode 100644 .archive/zeal/__init__.py create mode 100644 zeal/__init__.py diff --git a/.archive/zeal/__init__.py b/.archive/zeal/__init__.py deleted file mode 100644 index 83db8f85..00000000 --- a/.archive/zeal/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Open and search in Zeal offline docs. - - Synopsis: """ - -# Copyright (c) 2022 Manuel Schneider - -from subprocess import run -from albert import * - -__title__ = "Zeal" -__version__ = "0.4.0" -__triggers__ = "zl " -__authors__ = "Manuel S." -__exec_deps__ = ["zeal"] - -iconPath = iconLookup('zeal') - -def handleQuery(query): - if query.isTriggered: - return Item( - id=__title__, - icon=iconPath, - text=__title__, - subtext="Look up %s" % __title__, - actions=[ProcAction("Start query in %s" % __title__, - ["zeal", query.string])] - ) diff --git a/zeal/__init__.py b/zeal/__init__.py new file mode 100644 index 00000000..5677ecba --- /dev/null +++ b/zeal/__init__.py @@ -0,0 +1,40 @@ +"""Search in Zeal offline docs.""" + +from subprocess import run +from albert import * + +md_iid = '1.0' +md_version = '1.1' +md_name = 'Zeal' +md_description = 'Search in Zeal docs' +md_url = 'https://github.com/albertlauncher/python/zeal' +md_bin_dependencies = ['zeal'] + + +class Plugin(TriggerQueryHandler): + iconUrl = "xdg:zeal" + + def id(self): + return md_id + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return 'z ' + + def handleTriggerQuery(self, query): + stripped = query.string.strip() + if stripped: + query.add( + Item( + id=md_name, + text=md_name, + subtext=f"Search '{stripped}' in Zeal", + icon=[Plugin.iconUrl], + actions=[Action("zeal", "Search in Zeal", lambda s=stripped: runDetachedProcess(['zeal', s]))] + ) + ) From 271e0d6021941497e9f61071a67a03422d595283 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 18 Jun 2023 14:29:14 +0200 Subject: [PATCH 121/355] [coingecko] Add extension --- .archive/coinmarketcap/__init__.py | 150 ----------------------- .archive/coinmarketcap/emblem-money.svg | 1 - coingecko/__init__.py | 154 ++++++++++++++++++++++++ coingecko/coingecko.png | Bin 0 -> 21568 bytes 4 files changed, 154 insertions(+), 151 deletions(-) delete mode 100644 .archive/coinmarketcap/__init__.py delete mode 100644 .archive/coinmarketcap/emblem-money.svg create mode 100644 coingecko/__init__.py create mode 100644 coingecko/coingecko.png diff --git a/.archive/coinmarketcap/__init__.py b/.archive/coinmarketcap/__init__.py deleted file mode 100644 index ae024db4..00000000 --- a/.archive/coinmarketcap/__init__.py +++ /dev/null @@ -1,150 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Show and access crypto currencies on CoinmMarketCap.com. - -The values of "Change" are the hourly, daily and weekly changes of the price in percent. "Cap" is \ -the market capitalisation in USD. Volume is the volume of the last 24 hours in USD. - -Synopsis: [filter]""" - -from albert import * -from threading import Thread, Event -from locale import format as lformat -from urllib import request -from urllib.parse import urlencode -import re -import os -import json - -__title__ = "CoinMarketCap" -__version__ = "0.4.4" -__triggers__ = "cmc " -__authors__ = "Manuel S." - -iconPath = os.path.dirname(__file__)+"/emblem-money.svg" -thread = None -coins = None - - -class Coin(): - def __init__(self, identifier, name, symbol, rank, price, - cap, vol, change_hour, change_day, change_week): - self.identifier = identifier - self.name = name - self.symbol = symbol - self.rank = rank - self.price = price - self.cap = cap - self.vol = vol - self.change_hour = change_hour - self.change_day = change_day - self.change_week = change_week - - -class UpdateThread(Thread): - def __init__(self): - super().__init__() - self._stopevent = Event() - - def run(self): - - while True: - url = "%s?%s" % ("https://api.coinmarketcap.com/v1/ticker/", urlencode({'limit': 0})) - req = request.Request(url) - with request.urlopen(req) as response: - if self._stopevent.is_set(): - return - - def colorize_float(value: str): - if value is None: - return value - elif float(value) < 0: - return "%s" % value - elif float(value) > 0: - return "%s" % value - else: - return value - - # Get coin data - data = json.loads(response.read().decode('utf-8')) - newCoins = [] - for coindata in data: - cap = coindata['market_cap_usd'] - cap = lformat("%d", float(cap), True) if cap else "?" - vol = coindata['24h_volume_usd'] - vol = lformat("%d", float(vol), True) if vol else "?" - price = coindata['price_usd'] - price_precision = "%.2f" if float(price) > 1 else "%.6f" - price = lformat(price_precision, float(price), True) if price else "?" - if "," in price: - price = price.rstrip("0").rstrip(",") - newCoins.append(Coin(identifier=coindata['id'], - name=coindata['name'], - symbol=coindata['symbol'], - rank=coindata['rank'], - price=price, - cap=cap, - vol=vol, - change_hour=colorize_float(coindata['percent_change_1h']), - change_day=colorize_float(coindata['percent_change_24h']), - change_week=colorize_float(coindata['percent_change_7d']))) - global coins - coins = newCoins - - self._stopevent.wait(900) # Sleep 15 min, wakeup on stop event - if self._stopevent.is_set(): - return - - def stop(self): - self._stop_event.set() - - -def initialize(): - thread = UpdateThread() - thread.start() - - -def finalize(): - if thread is not None: - thread.stop() - thread.join() - - -def handleQuery(query): - if not query.isTriggered or coins is None: - return - - stripped = query.string.strip().lower() - items = [] - if stripped: - pattern = re.compile(stripped, re.IGNORECASE) - for coin in coins: - if coin.name.lower().startswith(stripped) or coin.symbol.lower().startswith(stripped): - url = "https://coinmarketcap.com/currencies/%s/" % coin.identifier - items.append(Item( - id=__title__, - icon=iconPath, - text="#%s %s (%s) %s$" % (coin.rank, pattern.sub(lambda m: "%s" % m.group(0), coin.name), - pattern.sub(lambda m: "%s" % m.group(0), coin.symbol), coin.price), - subtext="Change: %s/%s/%s, Cap: %s, Volume: %s" % (coin.change_hour, coin.change_day, coin.change_week, coin.cap, coin.vol), - completion=coin.price, - actions=[ - UrlAction("Show on CoinMarketCap website", url), - ClipAction('Copy URL to clipboard', url) - ] - )) - else: - for coin in coins: - url = "https://coinmarketcap.com/currencies/%s/" % coin.identifier - items.append(Item( - id=__title__, - icon=iconPath, - text="#%s %s (%s) %s$" % (coin.rank, coin.name, coin.symbol, coin.price), - subtext="Change: %s/%s/%s, Cap: %s, Volume: %s" % (coin.change_hour, coin.change_day, coin.change_week, coin.cap, coin.vol), - completion=coin.price, - actions=[ - UrlAction("Show on CoinMarketCap website", url), - ClipAction('Copy URL to clipboard', url) - ] - )) - return items diff --git a/.archive/coinmarketcap/emblem-money.svg b/.archive/coinmarketcap/emblem-money.svg deleted file mode 100644 index 256f9cd8..00000000 --- a/.archive/coinmarketcap/emblem-money.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/coingecko/__init__.py b/coingecko/__init__.py new file mode 100644 index 00000000..2d0ff769 --- /dev/null +++ b/coingecko/__init__.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- + +"""Show and access crypto currencies on CoinGecko.com.""" + +from albert import * +from time import time +from urllib import request +from json import load, loads, dumps +from pathlib import Path +from threading import Thread, Event + +md_iid = "1.0" +md_version = "1.0" +md_name = "CoinGecko" +md_description = "Access CoinGecko" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/coingecko" + + +class CoinFetcherThread(Thread): + def __init__(self, callback): + super().__init__() + self._stop_event = Event() + self.callback = callback + + def _fetchCoins(self): + url = "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250" + debug(f"Fetching data from {url}") + try: + response = request.urlopen(url, timeout=5) + if response.getcode() == 200: + json_data = loads(response.read().decode('utf-8')) + with open(Plugin.coinCacheFilePath, 'w') as f: + f.write(dumps(json_data)) + else: + warning("Request failed with status code:", response.getcode()) + except Exception as e: + warning("Request failed:", str(e)) + + def run(self): + while True: + # update if older than 1h + if not Plugin.coinCacheFilePath.is_file() or (time() - Plugin.coinCacheFilePath.lstat().st_mtime) > 3600: + self._fetchCoins() + self.callback() + self._stop_event.wait(300) # Check every 5 mins, wakeup on stop event + if self._stop_event.is_set(): + return + + def stop(self): + self._stop_event.set() + + +class CoinItem(AbstractItem): + def __init__(self, + identifier: str, + name: str, + symbol: str, + rank: int, + price: float, + cap: float, + vol: float, + change24h: float): + AbstractItem.__init__(self) + self.identifier = identifier + self.name = name + self.symbol = symbol + self.rank = rank + self.price = price + self.cap = cap + self.vol = vol + self.change24h = change24h + + def id(self): + return self.identifier + + def text(self): + return f"{self.name} {self.price} {self.symbol}/$" + + def subtext(self): + return f"#{self.rank}, 24h: {self.change24h}%, Cap: {self.cap:n} $, Vol: {self.vol:n} $" + + def completion(self): + return str(self.price) + + def icon(self): + return [Plugin.iconPath] + + def actions(self): + return [ + Action("show", f"Show {self.name} on CoinGecko", + lambda id=self.identifier: openUrl(Plugin.coinsUrl + id)), + Action("url", "Copy URL to clipboard", + lambda id=self.identifier: setClipboardText(Plugin.coinsUrl + id)) + ] + + +class Plugin(IndexQueryHandler): + iconPath = str(Path(__file__).parents[0] / "coingecko.png") + coinsUrl = "https://www.coingecko.com/en/coins/" + coinCacheFilePath = Path(cacheLocation()) / md_id / "coins.json" + + def initialize(self): + self.items = [] + self.mtime = 0 + self.thread = CoinFetcherThread(self.updateIndexItems) + self.thread.start() + + def finalize(self): + self.thread.stop() + self.thread.join() + + def id(self): + return md_id + + def name(self): + return md_name + + def description(self): + return md_description + + def defaultTrigger(self): + return "cg " + + def updateIndexItems(self): + mtime = Plugin.coinCacheFilePath.lstat().st_mtime + if self.coinCacheFilePath.is_file() and mtime > self.mtime: + self.mtime = mtime + with open(self.coinCacheFilePath) as f: + self.items.clear() + for json_object in load(f): + self.items.append(CoinItem( + identifier = json_object['id'], + name = json_object['name'], + symbol = json_object['symbol'].upper(), + rank = json_object['market_cap_rank'], + price = json_object['current_price'], + cap = json_object['market_cap'], + vol = json_object['total_volume'], + change24h = json_object['price_change_percentage_24h'] + )) + + index_items = [] + for item in self.items: + index_items.append(IndexItem(item=item, string=item.name)) + index_items.append(IndexItem(item=item, string=item.symbol)) + self.setIndexItems(index_items) + + # override default trigger handling to sort by rank + def handleTriggerQuery(self, query): + qs = query.string.strip().lower() + for item in self.items: + if qs in item.name.lower() or qs in item.symbol.lower(): + query.add(item) diff --git a/coingecko/coingecko.png b/coingecko/coingecko.png new file mode 100644 index 0000000000000000000000000000000000000000..ad08ef142b2851fc18639264c11c82d8e7794dde GIT binary patch literal 21568 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 E1yzWTIsgCw literal 0 HcmV?d00001 From b0053a90bdf3be5e3576c47d0b66623889385526 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 19 Jun 2023 18:10:52 +0200 Subject: [PATCH 122/355] [jb] proper id --- jetbrains_projects/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 43ca93cc..7cf16638 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -86,7 +86,7 @@ class Plugin(TriggerQueryHandler): executables = [] def id(self): - return __name__ + return md_id def name(self): return md_name From 6a76444233548984d87efbd313b1853babe0321b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 19 Jun 2023 18:16:24 +0200 Subject: [PATCH 123/355] [wiki:1.7] Add icon. Provide fallback item. --- wikipedia/__init__.py | 30 +++++++++++++++++++++--------- wikipedia/wikipedia.png | Bin 0 -> 38692 bytes 2 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 wikipedia/wikipedia.png diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index b4a9c921..6896c01c 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -11,18 +11,18 @@ import os md_iid = '1.0' -md_version = "1.6" +md_version = "1.7" md_name = "Wikipedia" md_description = "Search Wikipedia articles." md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/wikipedia" -md_maintainers = "@manuelschneid3r" class Plugin(TriggerQueryHandler): - iconPath = ":wikipedia" + iconPath = os.path.dirname(__file__) + "/wikipedia.png" baseurl = 'https://en.wikipedia.org/w/api.php' + searchUrl = 'https://%s.wikipedia.org/wiki/Special:Search/%s' user_agent = "org.albert.wikipedia" limit = 20 @@ -38,7 +38,6 @@ def description(self): def defaultTrigger(self): return "wiki " - def initialize(self): params = { 'action': 'query', @@ -48,21 +47,21 @@ def initialize(self): 'format': 'json' } + self.local_lang_code = getdefaultlocale()[0][0:2] + get_url = "%s?%s" % (self.baseurl, parse.urlencode(params)) req = request.Request(get_url, headers={'User-Agent': self.user_agent}) try: with request.urlopen(req, timeout=5) as response: data = json.loads(response.read().decode('utf-8')) languages = [lang['code'] for lang in data['query']['languages']] - local_lang_code = getdefaultlocale()[0][0:2] - if local_lang_code in languages: - self.baseurl = self.baseurl.replace("en", local_lang_code) + if self.local_lang_code in languages: + self.baseurl = self.baseurl.replace("en", self.local_lang_code) except timeout: critical('Error getting languages - socket timed out. Defaulting to EN.') except Exception as error: critical('Error getting languages (%s). Defaulting to EN.' % error) - def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: @@ -100,10 +99,23 @@ def handleTriggerQuery(self, query): Action("open", "Open article on Wikipedia", lambda u=url: openUrl(u)), Action("copy", "Copy URL to clipboard", lambda u=url: setClipboardText(u)) ])) - + if not results: + results.append(self._createFallbackItem(stripped)) query.add(results) else: query.add(Item(id=md_id, text=md_name, subtext="Enter a query to search on Wikipedia", icon=[self.iconPath])) + + def _createFallbackItem(self, query_string): + return Item( + id=md_id, + text=md_name, + subtext="Search '%s' on Wiki" % query_string, + icon=[self.iconPath], + actions=[ + Action("wiki_search", "Search on Wikipedia", + lambda url=Plugin.searchUrl % (self.local_lang_code, query_string): openUrl(url)) + ] + ) \ No newline at end of file diff --git a/wikipedia/wikipedia.png b/wikipedia/wikipedia.png new file mode 100644 index 0000000000000000000000000000000000000000..a2a40bbd3a962e9e111267d634cb0f3bc6152811 GIT binary patch literal 38692 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 Date: Tue, 20 Jun 2023 11:24:11 +0200 Subject: [PATCH 124/355] Add stub file --- albert.pyi | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 albert.pyi diff --git a/albert.pyi b/albert.pyi new file mode 100644 index 00000000..0ef2e93a --- /dev/null +++ b/albert.pyi @@ -0,0 +1,302 @@ +#!/usr/bin/env python3 + +"""Albert Python module interface v1.0""" + +from enum import Enum +from typing import Any +from typing import Callable +from typing import List +from typing import Optional +from typing import Union + +class Action: + """Action object for items.""" + def __init__(self, + id: str, + text: str, + callable: Callable): + """ + Args: + id: The identifier of the action + text: The title of the action + callable: The callable invoked on activation + """ + + +class AbstractItem: + """The abstract item base class. Serves as result item. Represents albert::Item interface class.""" + + +class Item(AbstractItem): + """Standard result item. Represents albert::StandardItem.""" + + def __init__(self, + id: str = '', + text: str = '', + subtext: str = '', + completion: Optional[str] = '', + icon: List[str] = [], + actions: List[Action] = []): + ... + + id: str + """Per extension unique identifier. Must not be empty.""" + + text: str + """The primary text of the item.""" + + subtext: str + """The secondary text of the item. This text should have informative character.""" + + completion: str + """ + The completion string of the item. This string will be used to replace the + input line when the user hits the Tab key on an item. Note that the + semantics may vary depending on the context. + """ + + icon: List[str] + """ + Icon urls used for the icon lookup. Supported url schemes: + * 'xdg:' performs freedesktop icon theme specification lookup (linux only). + * 'qfip:' uses QFileIconProvider to get the icon for the file. + * ':' is a QResource path. + * '' is interpreted as path to a local image file. + """ + + actions: List[Action] + """The actions of the item.""" + + +class Extension: + """Abstract bae class for all extensions.""" + + @abstractmethod + def id(self) -> str: + """The unique identifier of the extension.""" + + @abstractmethod + def name(self) -> str: + """The human readable name of the extension.""" + + @abstractmethod + def description(self) -> str: + """Brief description of the service provided.""" + + +class TriggerQuery: + """Represents a triggered, exclusive query execution.""" + + @property + def trigger(self) -> str: + """The trigger that has been used to start this extension.""" + + @property + def string(self) -> str: + """The actual query string (without the trigger).""" + + @property + def isValid(self) -> bool: + """This flag indicates that this the query is still valid. Cancel query processing if it is not.""" + + @overload + def add(self, item: AbstractItem): + """Add a single result item.""" + + @overload + def add(self, item: List[AbstractItem]): + """Add a list of result items.""" + + +class TriggerQueryHandler(Extension): + """Abstract class to be subclassed to implement such an extension.""" + + @abstractmethod + def synopsis(self) -> str: + """Implement to return a synopsis, displayed on empty query. Defaults to empty.""" + + @abstractmethod + def defaultTrigger(self) -> str: + """Implement to set a default trigger. Defaults to Extension::id().""" + + @abstractmethod + def allowTriggerRemap(self) -> bool: + """Implement to set trigger remapping permissions. Defaults to false.""" + + @abstractmethod + def handleTriggerQuery(self, query: TriggerQuery) -> None: + """Implement to handle the triggered query.""" + + +class GlobalQuery: + """Represents a triggered, exclusive query execution.""" + + @property + def string(self) -> str: + """The actual query string (without the trigger).""" + + @property + def isValid(self) -> bool: + """This flag indicates that this the query is still valid. Cancel query processing if it is not.""" + + +class RankItem: + """Result item with score for use in GlobalQueryHandler.""" + + def __init__(self, item: AbstractItem, score: float): + ... + + item: AbstractItem + """The result item.""" + + score: float + """The score of the item. From 0 to 1. Modulus applied""" + + +class GlobalQueryHandler(Extension): + """Abstract class to be subclassed to implement such an extension.""" + + @abstractmethod + def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: + """Implement to handle the global query.""" + + +class QueryHandler(TriggerQueryHandler, GlobalQueryHandler): + """ + Abstract convenience class to be subclassed to implement such an extension. + Combines Trigger- and GlobalQueryHandler. Implements `handleTriggerQuery` by + getting, sorting and adding the results of the handleGlobalQuery to the query. + """ + + def handleTriggerQuery(self, query: TriggerQuery) -> None: + """Calls `handleGlobalQuery` and sorts and adds the results to the query.""" + + +class IndexItem: + """Index item with index string for use in IndexQueryHandler.""" + + def __init__(self, item: AbstractItem, string: str): + ... + + item: AbstractItem + """The indexed item.""" + + string: str + """The index string used to look up this item.""" + + +class IndexQueryHandler(QueryHandler): + """ + Abstract convenience class to be subclassed to implement such an extension. + Maintains an index and does matching and scoring for you. + """ + + def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: + """Handles a global query by using the internal index.""" + + def setIndexItems(self, indexItems: List[RankItem]) -> None: + """Handles a global query by using the internal index.""" + + @abstractmethod + def updateIndexItems(self) -> None: + """Implement to populate the index. Use `setIndexItems`.""" + + +def debug(arg: Any) -> None: + """ + Log a message to stdout at the "debug" log level. Note that debug is + effectively a NOP in release builds + Args: + arg: The object to be logged. + """ + + +def info(arg: Any) -> None: + """ + Log a message to stdout at the "info" log level. + Args: + arg: The object to be logged. + """ + + +def warning(arg: Any) -> None: + """ + Log a message to stdout at the "warning" log level. + Args: + arg: The object to be logged. + """ + + +def critical(arg: Any) -> None: + """ + Log a message to stdout at the "critical" log level. + Args: + arg: The object to be logged. + """ + + +def cacheLocation() -> str: + """ + Returns: + The writable cache location of the app. + """ + + +def configLocation() -> str: + """ + Returns: + The writable config location of the app. + """ + + +def dataLocation() -> str: + """ + Returns: + The writable data location of the app. + """ + + +def setClipboardText(text: str='') -> None: + """ + Set the system clipboard text. + Args: + text: The text used to set the clipboard + """ + + +def openUrl(url:str='') -> None: + """ + Open an URL using QDesktopServices::openUrl. + Args: + url: The URL to open + """ + + +def runDetachedProcess(cmdln: List[str] = [], workdir: str = '') -> None: + """ + Run a detached process. + Args: + cmdln: The commandline to run in the terminal (argv) + workdir: The working directory used to run the terminal + """ + + +def runTerminal(script: str='', workdir: str = '', close_on_exit: bool = False) -> None: + """ + Run a script the user shell in the user specified terminal. + Args: + script: The script to be executed. + workdir: The working directory used to run the process + close_on_exit: Close the terminal on exit. Otherwise exec $SHELL. + """ + + +def sendTrayNotification(title: str='', msg: str = '', ms: int = 10000) -> None: + """ + Send a tray notification. + Args: + title: The notification title + msg: The notification body + ms: The display time (if supported by the system) + """ + From f67cf4177a31167a5eb52e460a970467a9b0ebe0 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 20 Jun 2023 12:16:48 +0200 Subject: [PATCH 125/355] Add interface info to stub file --- albert.pyi | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/albert.pyi b/albert.pyi index 0ef2e93a..8a682d6f 100644 --- a/albert.pyi +++ b/albert.pyi @@ -1,6 +1,45 @@ #!/usr/bin/env python3 -"""Albert Python module interface v1.0""" +""" +Albert Python interface specification v1.0 + +A Python plugin module is required to have the metadata described below and contain a +class named `Plugin` which will be instantiated when the plugin is loaded. + + +# Metadata + +Mandatory metadata variables: + +md_iid: str Interface version (.) +md_version: str Plugin version (.) +md_name: str Human readable name +md_description: str A brief, imperative description. (Like "Launch apps" or "Open files") + +Optional metadata variables: + +md_id Identifier overwrite. [a-zA-Z0-9_]. Defaults to module name. + Note `__name__` gets `albert.` prepended to avoid conflicts. +__doc__ The docstring of the module is used as long description/readme of the extension. +md_license: str Short form e.g. BSD-2-Clause or GPL-3.0 +md_url: str Browsable source, issues etc +md_maintainers: [str|List(str)] Active maintainer(s). Preferrably using mentionable Github usernames. +md_bin_dependencies: [str|List(str)] Required executable(s). Have to match the name of the executable in $PATH. +md_lib_dependencies: [str|List(str)] Required Python package(s). Have to match the PyPI package name. +md_credits: [str|List(str)] Third party credit(s) and license notes + + +# The Plugin class + +* The plugin class is the entry point for a plugin and instantiated on plugin initialization. +* Implement extensions by subclassing (one!) extension class provided by the built-in `albert` module. + Due to the differences in type systems multiple inheritance of extensions is not supported. + If the Plugin class inherits an extension it will be automatically registered. +* Define an "extensions() -> List[Extension]" instance function if you want to provide multiple extensions. +* Define initialize() and/or finalize() instance functions if needed. + Do not use the constructor, since PyBind11 imposes some inconvenient boilerplate on them. +""" + from enum import Enum from typing import Any From 49b2f18905c0ab9aa77d3a322ee12fb552f344fc Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 20 Jun 2023 16:18:45 +0200 Subject: [PATCH 126/355] [jb:1.4] Add idea.sh to the list of possible binaries --- jetbrains_projects/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 7cf16638..871ef63e 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -16,7 +16,7 @@ from albert import * md_iid = '1.0' -md_version = "1.3" +md_version = "1.4" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "GPL-3" @@ -130,7 +130,7 @@ def initialize(self): name="IntelliJ IDEA", icon=plugin_dir / "idea.svg", config_dir_prefix="JetBrains/IntelliJIdea", - binaries=["idea", "idea-ultimate", "idea-ce-eap", "idea-ue-eap", "intellij-idea-ce", + binaries=["idea", "idea.sh", "idea-ultimate", "idea-ce-eap", "idea-ue-eap", "intellij-idea-ce", "intellij-idea-ce-eap", "intellij-idea-ue-bundled-jre", "intellij-idea-ultimate-edition", "intellij-idea-community-edition-jre", "intellij-idea-community-edition-no-jre"]), Editor( From e0ce45ead9b3f2712ca8672ef4f9f7d7ed2e2069 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 20 Jun 2023 16:25:03 +0200 Subject: [PATCH 127/355] [wiki:1.8] Add fallback provider --- wikipedia/__init__.py | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 6896c01c..58c468ce 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -11,13 +11,29 @@ import os md_iid = '1.0' -md_version = "1.7" +md_version = "1.8" md_name = "Wikipedia" md_description = "Search Wikipedia articles." md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/wikipedia" +class FallbackProvider(FallbackHandler): + + def id(self): + return f"{md_id}_fb" + + def name(self): + return md_name + + def description(self): + return md_description + + def fallbacks(self, query_string): + stripped = query_string.strip() + return [Plugin.createFallbackItem(query_string)] if stripped else [] + + class Plugin(TriggerQueryHandler): iconPath = os.path.dirname(__file__) + "/wikipedia.png" @@ -26,6 +42,9 @@ class Plugin(TriggerQueryHandler): user_agent = "org.albert.wikipedia" limit = 20 + def extensions(self): + return [self, FallbackProvider()] + def id(self): return md_id @@ -47,7 +66,7 @@ def initialize(self): 'format': 'json' } - self.local_lang_code = getdefaultlocale()[0][0:2] + Plugin.local_lang_code = getdefaultlocale()[0][0:2] get_url = "%s?%s" % (self.baseurl, parse.urlencode(params)) req = request.Request(get_url, headers={'User-Agent': self.user_agent}) @@ -100,7 +119,7 @@ def handleTriggerQuery(self, query): Action("copy", "Copy URL to clipboard", lambda u=url: setClipboardText(u)) ])) if not results: - results.append(self._createFallbackItem(stripped)) + results.append(Plugin.createFallbackItem(stripped)) query.add(results) else: query.add(Item(id=md_id, @@ -108,14 +127,15 @@ def handleTriggerQuery(self, query): subtext="Enter a query to search on Wikipedia", icon=[self.iconPath])) - def _createFallbackItem(self, query_string): + @staticmethod + def createFallbackItem(query_string): return Item( id=md_id, text=md_name, subtext="Search '%s' on Wiki" % query_string, - icon=[self.iconPath], + icon=[Plugin.iconPath], actions=[ Action("wiki_search", "Search on Wikipedia", - lambda url=Plugin.searchUrl % (self.local_lang_code, query_string): openUrl(url)) + lambda url=Plugin.searchUrl % (Plugin.local_lang_code, query_string): openUrl(url)) ] ) \ No newline at end of file From 40bcdaea0e25cc1b47ab101c212e3ded58710080 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 20 Jun 2023 16:27:05 +0200 Subject: [PATCH 128/355] [stub] Add FallbackHandler. --- albert.pyi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/albert.pyi b/albert.pyi index 8a682d6f..3253bf6f 100644 --- a/albert.pyi +++ b/albert.pyi @@ -123,6 +123,13 @@ class Extension: """Brief description of the service provided.""" +class FallbackHandler(Extension): + """Base class for a fallback providing extensions.""" + @abstractmethod + def fallbacks(self, query: str) -> List[AbstractItem]: + """Implement to handle the fallback query.""" + + class TriggerQuery: """Represents a triggered, exclusive query execution.""" From d5f2ef3b54449bc04f7ac0481d4e756365af8501 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 20 Jun 2023 16:27:20 +0200 Subject: [PATCH 129/355] [stub] Minor documentation changes --- albert.pyi | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/albert.pyi b/albert.pyi index 3253bf6f..de91781b 100644 --- a/albert.pyi +++ b/albert.pyi @@ -155,7 +155,7 @@ class TriggerQuery: class TriggerQueryHandler(Extension): - """Abstract class to be subclassed to implement such an extension.""" + """Base class for a triggered query handling extensions.""" @abstractmethod def synopsis(self) -> str: @@ -200,7 +200,7 @@ class RankItem: class GlobalQueryHandler(Extension): - """Abstract class to be subclassed to implement such an extension.""" + """Base class for a global query handling extensions.""" @abstractmethod def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: @@ -209,9 +209,8 @@ class GlobalQueryHandler(Extension): class QueryHandler(TriggerQueryHandler, GlobalQueryHandler): """ - Abstract convenience class to be subclassed to implement such an extension. - Combines Trigger- and GlobalQueryHandler. Implements `handleTriggerQuery` by - getting, sorting and adding the results of the handleGlobalQuery to the query. + Convenience base class that combines Trigger- and GlobalQueryHandler. Implements `handleTriggerQuery` + by getting, sorting and adding the results of the handleGlobalQuery to the query. """ def handleTriggerQuery(self, query: TriggerQuery) -> None: @@ -233,8 +232,7 @@ class IndexItem: class IndexQueryHandler(QueryHandler): """ - Abstract convenience class to be subclassed to implement such an extension. - Maintains an index and does matching and scoring for you. + Convenience base class that combines maintains an index and does matching and scoring for you. """ def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: From 330999a7ddcd513291b2dfee981eda9fe920450a Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 21 Jun 2023 13:07:31 +0200 Subject: [PATCH 130/355] [stub] Minor documentation changes --- albert.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/albert.pyi b/albert.pyi index de91781b..db8c7c16 100644 --- a/albert.pyi +++ b/albert.pyi @@ -196,7 +196,7 @@ class RankItem: """The result item.""" score: float - """The score of the item. From 0 to 1. Modulus applied""" + """The score of the item (0,1]. No checks applied for performance.""" class GlobalQueryHandler(Extension): From 574a9be00c63488949e6cf3298ff6cf0bfa2c4b4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 22 Jun 2023 12:00:24 +0200 Subject: [PATCH 131/355] [stub] iid:1.0 Add extension.cache-, config- and dataLocation --- albert.pyi | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/albert.pyi b/albert.pyi index db8c7c16..4ebe4e27 100644 --- a/albert.pyi +++ b/albert.pyi @@ -122,6 +122,33 @@ class Extension: def description(self) -> str: """Brief description of the service provided.""" + def cacheDir(self) -> str: + """ + The recommended cache location for this extension. + Creates the directory if necessary. + Since iid v1.0. + Returns: + The writable cache location of the extension. + """ + + def configDir(self) -> str: + """ + The recommended config location for this extension. + Creates the directory if necessary. + Since iid v1.0. + Returns: + The writable config location of the extension. + """ + + def dataDir(self) -> str: + """ + The recommended data location for this extension. + Creates the directory if necessary. + Since iid v1.0. + Returns: + The writable data location of the extension. + """ + class FallbackHandler(Extension): """Base class for a fallback providing extensions.""" @@ -281,22 +308,31 @@ def critical(arg: Any) -> None: def cacheLocation() -> str: """ + Deprecated: Use Extension.cacheLocation instead + + Note that this is the _app_ cache location. Returns: - The writable cache location of the app. + The writable app cache location. """ def configLocation() -> str: """ + Deprecated: Use Extension.configLocation instead + + Note that this is the _app_ config location. Returns: - The writable config location of the app. + The writable app config location. """ def dataLocation() -> str: """ + Deprecated: Use Extension.dataLocation instead + + Note that this is the _app_ data location. Returns: - The writable data location of the app. + The writable app data location. """ From 6ed1f9caf659237c10b37b7cd575df8b0074a7bb Mon Sep 17 00:00:00 2001 From: Asger Hautop Drewsen Date: Thu, 22 Jun 2023 20:47:31 +0200 Subject: [PATCH 132/355] [mathematica] iid:1.0 port --- .archive/mathematica_eval/__init__.py | 42 --------------- mathematica_eval/__init__.py | 77 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 42 deletions(-) delete mode 100644 .archive/mathematica_eval/__init__.py create mode 100644 mathematica_eval/__init__.py diff --git a/.archive/mathematica_eval/__init__.py b/.archive/mathematica_eval/__init__.py deleted file mode 100644 index 6941121e..00000000 --- a/.archive/mathematica_eval/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Evaluate Mathematica expressions. - -Synopsis: [expr]""" - -# Copyright (c) 2022 Manuel Schneider - -import subprocess -from tempfile import NamedTemporaryFile - -from albert import ClipAction, Item, iconLookup - -__title__ = 'Mathematica eval' -__version__ = '0.4.0' -__triggers__ = 'mma ' -__authors__ = 'Asger Hautop Drewsen' -__exec_deps__ = ['wolframscript'] - -ICON_PATH = iconLookup('wolfram-mathematica') - -def handleQuery(query): - if not query.isTriggered: - return - - item = Item(icon=ICON_PATH) - stripped = query.string.strip() - - if stripped: - with NamedTemporaryFile() as f: - f.write(bytes(stripped, 'utf-8')) - f.flush() - output = subprocess.check_output(['wolframscript', '-print', '-f', f.name]) - result = str(output.strip(), 'utf-8') - item.text = result - item.subtext = 'Result' - item.addAction(ClipAction('Copy result to clipboard', result)) - else: - item.text = '' - item.subtext = 'Type a Mathematica expression' - - return item diff --git a/mathematica_eval/__init__.py b/mathematica_eval/__init__.py new file mode 100644 index 00000000..e988fc67 --- /dev/null +++ b/mathematica_eval/__init__.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +import subprocess +from tempfile import NamedTemporaryFile +from threading import Lock + +from albert import (Action, Item, TriggerQuery, TriggerQueryHandler, + setClipboardText) + +md_iid = "1.0" +md_version = "1.0" +md_name = "Mathematica Eval" +md_description = "Evaluate Mathemtica code" +md_license = "GPL-3.0" +md_url = "https://github.com/albertlauncher/python/tree/master/mathematica_eval" +md_maintainers = "@tyilo" +md_bin_dependencies = ["wolframscript"] + + +class Plugin(TriggerQueryHandler): + def id(self) -> str: + return md_id + + def name(self) -> str: + return md_name + + def description(self) -> str: + return md_description + + def defaultTrigger(self) -> str: + return "mma " + + def synopsis(self) -> str: + return "" + + def handleTriggerQuery(self, query: TriggerQuery) -> None: + stripped = query.string.strip() + if not stripped: + return + + with NamedTemporaryFile("w") as f: + f.write(stripped) + f.flush() + process = subprocess.Popen( + ["wolframscript", "-print", "-f", f.name], + encoding="utf-8", + stdout=subprocess.PIPE, + ) + + while True: + if not query.isValid: + process.kill() + return + + try: + output, _ = process.communicate(timeout=0.1) + break + except subprocess.TimeoutExpired: + pass + + result_str = output.strip() + + query.add( + Item( + id=md_id, + text=result_str, + completion=query.trigger + result_str, + icon=["xdg:wolfram-mathematica"], + actions=[ + Action( + "copy", + "Copy result to clipboard", + lambda r=result_str: setClipboardText(r), + ), + ], + ) + ) From 1529fba03bb47cf83f29a3d0dcc025c1e355f296 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 22 Jun 2023 20:56:24 +0200 Subject: [PATCH 133/355] [stub] iid:1.0 Drop deprecated cache/config/dataLocation --- albert.pyi | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/albert.pyi b/albert.pyi index 4ebe4e27..91f368e9 100644 --- a/albert.pyi +++ b/albert.pyi @@ -122,7 +122,7 @@ class Extension: def description(self) -> str: """Brief description of the service provided.""" - def cacheDir(self) -> str: + def cacheLocation(self) -> str: """ The recommended cache location for this extension. Creates the directory if necessary. @@ -131,7 +131,7 @@ class Extension: The writable cache location of the extension. """ - def configDir(self) -> str: + def configLocation(self) -> str: """ The recommended config location for this extension. Creates the directory if necessary. @@ -140,7 +140,7 @@ class Extension: The writable config location of the extension. """ - def dataDir(self) -> str: + def dataLocation(self) -> str: """ The recommended data location for this extension. Creates the directory if necessary. @@ -306,36 +306,6 @@ def critical(arg: Any) -> None: """ -def cacheLocation() -> str: - """ - Deprecated: Use Extension.cacheLocation instead - - Note that this is the _app_ cache location. - Returns: - The writable app cache location. - """ - - -def configLocation() -> str: - """ - Deprecated: Use Extension.configLocation instead - - Note that this is the _app_ config location. - Returns: - The writable app config location. - """ - - -def dataLocation() -> str: - """ - Deprecated: Use Extension.dataLocation instead - - Note that this is the _app_ data location. - Returns: - The writable app data location. - """ - - def setClipboardText(text: str='') -> None: """ Set the system clipboard text. @@ -363,7 +333,7 @@ def runDetachedProcess(cmdln: List[str] = [], workdir: str = '') -> None: def runTerminal(script: str='', workdir: str = '', close_on_exit: bool = False) -> None: """ - Run a script the user shell in the user specified terminal. + Run a script in the users shell and terminal. Args: script: The script to be executed. workdir: The working directory used to run the process From 6fe50e9d7b63f04328ab3800f7c21b3eaa9140bc Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 22 Jun 2023 20:56:53 +0200 Subject: [PATCH 134/355] [coingecko] Adjust to latest changes --- coingecko/__init__.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index 2d0ff769..61b0019b 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -18,10 +18,11 @@ class CoinFetcherThread(Thread): - def __init__(self, callback): + def __init__(self, callback, path: Path): super().__init__() self._stop_event = Event() self.callback = callback + self.path = path def _fetchCoins(self): url = "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250" @@ -30,17 +31,17 @@ def _fetchCoins(self): response = request.urlopen(url, timeout=5) if response.getcode() == 200: json_data = loads(response.read().decode('utf-8')) - with open(Plugin.coinCacheFilePath, 'w') as f: + with open(self.path, 'w') as f: f.write(dumps(json_data)) else: - warning("Request failed with status code:", response.getcode()) + warning(f"Request failed with status code: {response.getcode()}") except Exception as e: - warning("Request failed:", str(e)) + warning(f"Request failed: {str(e)}") def run(self): while True: # update if older than 1h - if not Plugin.coinCacheFilePath.is_file() or (time() - Plugin.coinCacheFilePath.lstat().st_mtime) > 3600: + if not self.path.is_file() or (time() - self.path.lstat().st_mtime) > 3600: self._fetchCoins() self.callback() self._stop_event.wait(300) # Check every 5 mins, wakeup on stop event @@ -98,12 +99,12 @@ def actions(self): class Plugin(IndexQueryHandler): iconPath = str(Path(__file__).parents[0] / "coingecko.png") coinsUrl = "https://www.coingecko.com/en/coins/" - coinCacheFilePath = Path(cacheLocation()) / md_id / "coins.json" def initialize(self): self.items = [] self.mtime = 0 - self.thread = CoinFetcherThread(self.updateIndexItems) + self.coinCacheFilePath = Path(self.cacheLocation()) / "coins.json" + self.thread = CoinFetcherThread(self.updateIndexItems, self.coinCacheFilePath) self.thread.start() def finalize(self): @@ -123,7 +124,7 @@ def defaultTrigger(self): return "cg " def updateIndexItems(self): - mtime = Plugin.coinCacheFilePath.lstat().st_mtime + mtime = self.coinCacheFilePath.lstat().st_mtime if self.coinCacheFilePath.is_file() and mtime > self.mtime: self.mtime = mtime with open(self.coinCacheFilePath) as f: From 98320216746c23cd7e3aa1e7c0018e62c33cb667 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 22 Jun 2023 21:19:44 +0200 Subject: [PATCH 135/355] [emoji:1.3] Adjust to cache/config/data changes --- emoji/__init__.py | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index 6e79c0c9..2467b19e 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -1,9 +1,5 @@ # -*- coding: utf-8 -*- -"""Find emojis by name. - -Synopsis: """ - import json import re import subprocess @@ -13,7 +9,7 @@ from albert import * md_iid = '1.0' -md_version = "1.2" +md_version = "1.3" md_name = "Emoji Picker" md_description = "Find emojis by name" md_license = "GPL-3.0" @@ -25,14 +21,6 @@ EXTENSION_DIR = Path(__file__).parent ALIASES_PATH = EXTENSION_DIR / "aliases.json" EMOJI_PATH = EXTENSION_DIR / "emoji-test.txt" -ICON_DIR = Path(cacheLocation()) / "emojis" - - -ICON_DIR.mkdir(exist_ok=True, parents=True) - - -def icon_path(emoji): - return ICON_DIR / f"{emoji}.png" def convert_to_png(emoji, output_path): @@ -49,10 +37,10 @@ def convert_to_png(emoji, output_path): ) -def schedule_create_missing_icons(emojis): +def schedule_create_missing_icons(emojis, icon_dir_path: str): executor = ThreadPoolExecutor() for emoji in emojis: - path = icon_path(emoji["emoji"]) + path = icon_dir_path / f"{emoji['emoji']}.png" if not path.exists(): executor.submit(convert_to_png, emoji["emoji"], path) @@ -76,6 +64,8 @@ def synopsis(self): return "" def initialize(self): + self.icon_dir_path = Path(cacheLocation()) + line_re = re.compile( r""" ^ @@ -112,7 +102,7 @@ def initialize(self): e["search_tokens"] = search_tokens self.emojis.append(e) - self.icon_executor = schedule_create_missing_icons(self.emojis) + self.icon_executor = schedule_create_missing_icons(self.emojis, self.icon_dir_path) def finalize(self): self.icon_executor.shutdown(wait=True, cancel_futures=True) @@ -136,7 +126,7 @@ def handleTriggerQuery(self, query): id=f"emoji_{emoji['emoji']}", text=f"{emoji['emoji']} {emoji['name']}", subtext=emoji["modifiers"] or "", - icon=[str(icon_path(emoji["emoji"]))], + icon=[str(self.icon_dir_path / f"{emoji['emoji']}.png")], actions=[ Action( "copy", From 1d3a1869b25a2ac147c52c779186856355794c45 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 22 Jun 2023 21:22:01 +0200 Subject: [PATCH 136/355] [stub] Fix abstract methods --- albert.pyi | 3 --- 1 file changed, 3 deletions(-) diff --git a/albert.pyi b/albert.pyi index 91f368e9..f3ede40b 100644 --- a/albert.pyi +++ b/albert.pyi @@ -184,15 +184,12 @@ class TriggerQuery: class TriggerQueryHandler(Extension): """Base class for a triggered query handling extensions.""" - @abstractmethod def synopsis(self) -> str: """Implement to return a synopsis, displayed on empty query. Defaults to empty.""" - @abstractmethod def defaultTrigger(self) -> str: """Implement to set a default trigger. Defaults to Extension::id().""" - @abstractmethod def allowTriggerRemap(self) -> bool: """Implement to set trigger remapping permissions. Defaults to false.""" From ab402b25cb191d6ec93a348884e6249f13291a29 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 23 Jun 2023 16:11:23 +0200 Subject: [PATCH 137/355] [stub] Abstract item documentation --- albert.pyi | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/albert.pyi b/albert.pyi index f3ede40b..12845d24 100644 --- a/albert.pyi +++ b/albert.pyi @@ -65,9 +65,50 @@ class Action: class AbstractItem: """The abstract item base class. Serves as result item. Represents albert::Item interface class.""" + @property + @abstractmethod + def id(self) -> str: + """Per extension unique identifier. Must not be empty.""" + + @property + @abstractmethod + def text(self) -> str: + """The primary text of the item.""" + + @property + @abstractmethod + def subtext(self) -> str: + """The secondary text of the item. This text should have informative character.""" + + @property + @abstractmethod + def icon(self) -> List[str]: + """ + Icon urls used for the icon lookup. Supported url schemes: + * 'xdg:' performs freedesktop icon theme specification lookup (linux only). + * 'qfip:' uses QFileIconProvider to get the icon for the file. + * ':' is a QResource path. + * '' is interpreted as path to a local image file. + """ + + @property + def completion(self) -> str: + """ + The completion string of the item. This string will be used to replace the + input line when the user hits the Tab key on an item. Note that the + semantics may vary depending on the context. Default empty. + """ + + @property + def actions(self) -> List[Action]: + """The actions of the item. Default empty.""" class Item(AbstractItem): - """Standard result item. Represents albert::StandardItem.""" + """ + Standard result item. + Represents albert::StandardItem. + See AbstractItem for more information + """ def __init__(self, id: str = '', @@ -108,7 +149,7 @@ class Item(AbstractItem): class Extension: - """Abstract bae class for all extensions.""" + """Abstract base class for all extensions.""" @abstractmethod def id(self) -> str: From 9daf769316bb768970c50e035efc2aa9b2f9db60 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 23 Jun 2023 23:04:38 +0200 Subject: [PATCH 138/355] [jb] Fix md_url --- jetbrains_projects/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 871ef63e..10bb9aa4 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -20,7 +20,7 @@ md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "GPL-3" -md_url = "https://github.com/tomsquest/albert-jetbrains-projects-plugin" +md_url = "https://github.com/albertlauncher/python/" md_maintainers = ["@mqus", "@tomsquest"] From 2f6a6d8a8a6397d1acfbd07e6fed595d309f9f16 Mon Sep 17 00:00:00 2001 From: Naman Sood Date: Tue, 27 Jun 2023 06:09:45 -0400 Subject: [PATCH 139/355] [emoji] Fix #179. Call cacheLocation as method of self. --- emoji/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index 2467b19e..52f7fb5e 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -64,7 +64,7 @@ def synopsis(self): return "" def initialize(self): - self.icon_dir_path = Path(cacheLocation()) + self.icon_dir_path = Path(self.cacheLocation()) line_re = re.compile( r""" From d7fc7e3a9c4f78bb5d179919cb3bb80578499517 Mon Sep 17 00:00:00 2001 From: Oskar Haarklou Veileborg Date: Tue, 27 Jun 2023 12:11:47 +0200 Subject: [PATCH 140/355] [emoji] Proper type hinting --- emoji/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index 52f7fb5e..12943ff4 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -37,7 +37,7 @@ def convert_to_png(emoji, output_path): ) -def schedule_create_missing_icons(emojis, icon_dir_path: str): +def schedule_create_missing_icons(emojis, icon_dir_path: Path): executor = ThreadPoolExecutor() for emoji in emojis: path = icon_dir_path / f"{emoji['emoji']}.png" From 538ec37b326e6c93c825065a3deb6281f80c1793 Mon Sep 17 00:00:00 2001 From: Oskar Haarklou Veileborg Date: Tue, 27 Jun 2023 12:12:22 +0200 Subject: [PATCH 141/355] [tex_to_unicode] Fix crash due to wrong type annotation --- tex_to_unicode/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tex_to_unicode/__init__.py b/tex_to_unicode/__init__.py index 4fbdffed..6393ed43 100644 --- a/tex_to_unicode/__init__.py +++ b/tex_to_unicode/__init__.py @@ -57,7 +57,7 @@ def _create_item(self, text: str, subtext: str, can_copy: bool) -> Item: actions=actions, ) - def handleTriggerQuery(self, query: Query) -> None: + def handleTriggerQuery(self, query: TriggerQuery) -> None: stripped = query.string.strip() if not stripped: From 0f024aacbe2c95e1a413852a0409bd8de0b0c53a Mon Sep 17 00:00:00 2001 From: Oskar Haarklou Veileborg Date: Tue, 27 Jun 2023 12:13:00 +0200 Subject: [PATCH 142/355] [stub] Add missing imports to stub file --- albert.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/albert.pyi b/albert.pyi index 12845d24..3b9e4f99 100644 --- a/albert.pyi +++ b/albert.pyi @@ -41,12 +41,14 @@ md_credits: [str|List(str)] Third party credit(s) and license notes """ +from abc import abstractmethod from enum import Enum from typing import Any from typing import Callable from typing import List from typing import Optional from typing import Union +from typing import overload class Action: """Action object for items.""" From 67690b762b3e7ea6ad5f0022bd17ca48e2978ce5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:39:03 +0200 Subject: [PATCH 143/355] Interface v2.0 --- albert.pyi | 419 ++++++++++++++++++++++++----------------------------- 1 file changed, 191 insertions(+), 228 deletions(-) diff --git a/albert.pyi b/albert.pyi index 3b9e4f99..f9b824bf 100644 --- a/albert.pyi +++ b/albert.pyi @@ -1,47 +1,46 @@ -#!/usr/bin/env python3 - """ -Albert Python interface specification v1.0 -A Python plugin module is required to have the metadata described below and contain a -class named `Plugin` which will be instantiated when the plugin is loaded. +# Albert Python interface v2.0 + + +The Python interface is a subset of the internal C++ interface exposed to Python with some minor adjustments. A Python +plugin is required to contain the mandatory metadata and a plugin class, both described below. To get started read the +top level classes and function names in this file. Most of them are self explanatory. In case of questions see the C++ +documentation at https://albertlauncher.github.io/reference/namespacealbert.html -# Metadata +## Mandatory metadata variables -Mandatory metadata variables: +md_iid: str | Interface version (.) +md_version: str | Plugin version (.) +md_name: str | Human readable name +md_description: str | A brief, imperative description. (Like "Launch apps" or "Open files") -md_iid: str Interface version (.) -md_version: str Plugin version (.) -md_name: str Human readable name -md_description: str A brief, imperative description. (Like "Launch apps" or "Open files") -Optional metadata variables: +## Optional metadata variables: -md_id Identifier overwrite. [a-zA-Z0-9_]. Defaults to module name. - Note `__name__` gets `albert.` prepended to avoid conflicts. -__doc__ The docstring of the module is used as long description/readme of the extension. -md_license: str Short form e.g. BSD-2-Clause or GPL-3.0 -md_url: str Browsable source, issues etc -md_maintainers: [str|List(str)] Active maintainer(s). Preferrably using mentionable Github usernames. -md_bin_dependencies: [str|List(str)] Required executable(s). Have to match the name of the executable in $PATH. -md_lib_dependencies: [str|List(str)] Required Python package(s). Have to match the PyPI package name. -md_credits: [str|List(str)] Third party credit(s) and license notes +md_id | Identifier overwrite. [a-zA-Z0-9_]. Defaults to module name. +__doc__ | The docstring of the module is used as long description/readme of the extension. +md_license: str | Short form e.g. BSD-2-Clause or GPL-3.0 +md_url: str | Browsable source, issues etc +md_maintainers: [str|List(str)] | Active maintainer(s). Preferrably using mentionable Github usernames. +md_bin_dependencies: [str|List(str)] | Required executable(s). Have to match the name of the executable in $PATH. +md_lib_dependencies: [str|List(str)] | Required Python package(s). Have to match the PyPI package name. +md_credits: [str|List(str)] | Third party credit(s) and license notes -# The Plugin class +## The Plugin class + +The plugin class is the entry point for a Python plugin. It is instantiated on plugin initialization and has to subclass +PluginInstance. Implement extension(s) by subclassing _one_ extension class (TriggerQueryHandler etc…) provided by the +built-in `albert` module and pass the list of your extensions to the PluginInstance init function. Due to the +differences in type systems multiple inheritance of extensions is not supported. (Python does not support virtual +inheritance, which is used in the C++ space to inherit from 'Extension'). For more details see -* The plugin class is the entry point for a plugin and instantiated on plugin initialization. -* Implement extensions by subclassing (one!) extension class provided by the built-in `albert` module. - Due to the differences in type systems multiple inheritance of extensions is not supported. - If the Plugin class inherits an extension it will be automatically registered. -* Define an "extensions() -> List[Extension]" instance function if you want to provide multiple extensions. -* Define initialize() and/or finalize() instance functions if needed. - Do not use the constructor, since PyBind11 imposes some inconvenient boilerplate on them. """ -from abc import abstractmethod +from abc import abstractmethod, ABC from enum import Enum from typing import Any from typing import Callable @@ -50,303 +49,267 @@ from typing import Optional from typing import Union from typing import overload + +class PluginInstance(ABC): + """https://albertlauncher.github.io/reference/classalbert_1_1_plugin_instance.html""" + + def __init__(self, extensions: List[Extension] = []): + ... + + @property + def id(self) -> str: + ... + + @property + def name(self) -> str: + ... + + @property + def description(self) -> str: + ... + + @property + def cacheLocation(self) -> pathlib.Path: + ... + + @property + def configLocation(self) -> pathlib.Path: + ... + + @property + def dataLocation(self) -> pathlib.Path: + ... + + @property + def extensions(self) -> List[Extension]: + ... + + def initialize(self): + ... + + def finalize(self): + ... + + class Action: - """Action object for items.""" + """https://albertlauncher.github.io/reference/classalbert_1_1_action.html""" + def __init__(self, id: str, text: str, callable: Callable): - """ - Args: - id: The identifier of the action - text: The title of the action - callable: The callable invoked on activation - """ + ... -class AbstractItem: - """The abstract item base class. Serves as result item. Represents albert::Item interface class.""" +class Item(ABC): + """https://albertlauncher.github.io/reference/classalbert_1_1_item.html""" - @property @abstractmethod def id(self) -> str: - """Per extension unique identifier. Must not be empty.""" + ... - @property @abstractmethod def text(self) -> str: - """The primary text of the item.""" + ... - @property @abstractmethod def subtext(self) -> str: - """The secondary text of the item. This text should have informative character.""" + ... - @property @abstractmethod - def icon(self) -> List[str]: - """ - Icon urls used for the icon lookup. Supported url schemes: - * 'xdg:' performs freedesktop icon theme specification lookup (linux only). - * 'qfip:' uses QFileIconProvider to get the icon for the file. - * ':' is a QResource path. - * '' is interpreted as path to a local image file. - """ + def inputActionText(self) -> str: + ... - @property - def completion(self) -> str: - """ - The completion string of the item. This string will be used to replace the - input line when the user hits the Tab key on an item. Note that the - semantics may vary depending on the context. Default empty. - """ + @abstractmethod + def iconUrls(self) -> List[str]: + """See https://albertlauncher.github.io/reference/classalbert_1_1_icon_provider.html""" - @property + @abstractmethod def actions(self) -> List[Action]: - """The actions of the item. Default empty.""" + ... -class Item(AbstractItem): - """ - Standard result item. - Represents albert::StandardItem. - See AbstractItem for more information - """ + +class StandardItem(Item): + """https://albertlauncher.github.io/reference/structalbert_1_1_standard_item.html""" def __init__(self, id: str = '', text: str = '', subtext: str = '', - completion: Optional[str] = '', - icon: List[str] = [], - actions: List[Action] = []): + iconUrls: List[str] = [], + actions: List[Action] = [], + inputActionText: Optional[str] = ''): ... id: str - """Per extension unique identifier. Must not be empty.""" - text: str - """The primary text of the item.""" - subtext: str - """The secondary text of the item. This text should have informative character.""" - - completion: str - """ - The completion string of the item. This string will be used to replace the - input line when the user hits the Tab key on an item. Note that the - semantics may vary depending on the context. - """ - - icon: List[str] - """ - Icon urls used for the icon lookup. Supported url schemes: - * 'xdg:' performs freedesktop icon theme specification lookup (linux only). - * 'qfip:' uses QFileIconProvider to get the icon for the file. - * ':' is a QResource path. - * '' is interpreted as path to a local image file. - """ - + iconUrls: List[str] actions: List[Action] - """The actions of the item.""" + inputActionText: str -class Extension: - """Abstract base class for all extensions.""" +class Extension(ABC): + """https://albertlauncher.github.io/reference/classalbert_1_1_extension.html""" - @abstractmethod + @property def id(self) -> str: - """The unique identifier of the extension.""" + ... - @abstractmethod + @property def name(self) -> str: - """The human readable name of the extension.""" + ... - @abstractmethod + @property def description(self) -> str: - """Brief description of the service provided.""" - - def cacheLocation(self) -> str: - """ - The recommended cache location for this extension. - Creates the directory if necessary. - Since iid v1.0. - Returns: - The writable cache location of the extension. - """ - - def configLocation(self) -> str: - """ - The recommended config location for this extension. - Creates the directory if necessary. - Since iid v1.0. - Returns: - The writable config location of the extension. - """ - - def dataLocation(self) -> str: - """ - The recommended data location for this extension. - Creates the directory if necessary. - Since iid v1.0. - Returns: - The writable data location of the extension. - """ - - -class FallbackHandler(Extension): - """Base class for a fallback providing extensions.""" + ... + + +class FallbackHandler(ABC): + """https://albertlauncher.github.io/reference/classalbert_1_1_fallback_handler.html""" + @abstractmethod - def fallbacks(self, query: str) -> List[AbstractItem]: - """Implement to handle the fallback query.""" + def fallbacks(self, query: str ) ->List[Item]: + ... -class TriggerQuery: - """Represents a triggered, exclusive query execution.""" +class TriggerQuery(ABC): + """https://albertlauncher.github.io/reference/classalbert_1_1_trigger_query_handler_1_1_trigger_query.html""" @property def trigger(self) -> str: - """The trigger that has been used to start this extension.""" + ... @property def string(self) -> str: - """The actual query string (without the trigger).""" + ... @property def isValid(self) -> bool: - """This flag indicates that this the query is still valid. Cancel query processing if it is not.""" + ... @overload - def add(self, item: AbstractItem): - """Add a single result item.""" + def add(self, item: Item): + ... @overload - def add(self, item: List[AbstractItem]): - """Add a list of result items.""" + def add(self, item: List[Item]): + ... class TriggerQueryHandler(Extension): - """Base class for a triggered query handling extensions.""" + """https://albertlauncher.github.io/reference/classalbert_1_1_trigger_query_handler.html""" + def __init__(self, + id: str, + name: str, + description: str, + synopsis: str = '', + defaultTrigger: str = f'{id} ', + allowTriggerRemap: str = true, + supportsFuzzyMatching: bool = False): + ... + + @property def synopsis(self) -> str: - """Implement to return a synopsis, displayed on empty query. Defaults to empty.""" + ... + + @property + def trigger(self) -> str: + ... + @property def defaultTrigger(self) -> str: - """Implement to set a default trigger. Defaults to Extension::id().""" + ... + @property def allowTriggerRemap(self) -> bool: - """Implement to set trigger remapping permissions. Defaults to false.""" - - @abstractmethod - def handleTriggerQuery(self, query: TriggerQuery) -> None: - """Implement to handle the triggered query.""" - - -class GlobalQuery: - """Represents a triggered, exclusive query execution.""" + ... @property - def string(self) -> str: - """The actual query string (without the trigger).""" + def supportsFuzzyMatching(self) -> bool: + ... @property - def isValid(self) -> bool: - """This flag indicates that this the query is still valid. Cancel query processing if it is not.""" + def fuzzyMatching(self) -> bool: + ... + + @fuzzyMatching.setter + def setFuzzyMatching(self, enabled: bool): + ... + + @abstractmethod + def handleTriggerQuery(self, query: TriggerQuery): + ... class RankItem: - """Result item with score for use in GlobalQueryHandler.""" + """https://albertlauncher.github.io/reference/classalbert_1_1_rank_item.html""" - def __init__(self, item: AbstractItem, score: float): + def __init__(self, item: Item, score: float): ... - item: AbstractItem - """The result item.""" - + item: Item score: float - """The score of the item (0,1]. No checks applied for performance.""" -class GlobalQueryHandler(Extension): - """Base class for a global query handling extensions.""" +class GlobalQuery(ABC): + """https://albertlauncher.github.io/reference/classalbert_1_1_global_query_handler_1_1_global_query.html""" + + @property + def string(self) -> str: + ... + + @property + def isValid(self) -> bool: + ... + + +class GlobalQueryHandler(TriggerQueryHandler): + """https://albertlauncher.github.io/reference/classalbert_1_1_global_query_handler.html""" @abstractmethod def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: - """Implement to handle the global query.""" - + ... -class QueryHandler(TriggerQueryHandler, GlobalQueryHandler): - """ - Convenience base class that combines Trigger- and GlobalQueryHandler. Implements `handleTriggerQuery` - by getting, sorting and adding the results of the handleGlobalQuery to the query. - """ + def applyUsageScore(self, rank_items: List[RankItem]): + ... - def handleTriggerQuery(self, query: TriggerQuery) -> None: - """Calls `handleGlobalQuery` and sorts and adds the results to the query.""" + def handleTriggerQuery(self, query: TriggerQuery): + ... class IndexItem: - """Index item with index string for use in IndexQueryHandler.""" + """https://albertlauncher.github.io/reference/classalbert_1_1_index_item.html""" def __init__(self, item: AbstractItem, string: str): ... item: AbstractItem - """The indexed item.""" - string: str - """The index string used to look up this item.""" -class IndexQueryHandler(QueryHandler): - """ - Convenience base class that combines maintains an index and does matching and scoring for you. - """ - - def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: - """Handles a global query by using the internal index.""" - - def setIndexItems(self, indexItems: List[RankItem]) -> None: - """Handles a global query by using the internal index.""" +class IndexQueryHandler(GlobalQueryHandler): + """https://albertlauncher.github.io/reference/classalbert_1_1_index_query_handler.html""" @abstractmethod - def updateIndexItems(self) -> None: - """Implement to populate the index. Use `setIndexItems`.""" - - -def debug(arg: Any) -> None: - """ - Log a message to stdout at the "debug" log level. Note that debug is - effectively a NOP in release builds - Args: - arg: The object to be logged. - """ - - -def info(arg: Any) -> None: - """ - Log a message to stdout at the "info" log level. - Args: - arg: The object to be logged. - """ + def updateIndexItems(self): + ... + def setIndexItems(self, indexItems: List[RankItem]): + ... -def warning(arg: Any) -> None: - """ - Log a message to stdout at the "warning" log level. - Args: - arg: The object to be logged. - """ + def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: + ... -def critical(arg: Any) -> None: - """ - Log a message to stdout at the "critical" log level. - Args: - arg: The object to be logged. - """ +def debug(arg: Any):... +def info(arg: Any):... +def warning(arg: Any):... +def critical(arg: Any):... -def setClipboardText(text: str='') -> None: +def setClipboardText(text: str=''): """ Set the system clipboard text. Args: @@ -354,7 +317,7 @@ def setClipboardText(text: str='') -> None: """ -def openUrl(url:str='') -> None: +def openUrl(url: str = ''): """ Open an URL using QDesktopServices::openUrl. Args: @@ -362,7 +325,7 @@ def openUrl(url:str='') -> None: """ -def runDetachedProcess(cmdln: List[str] = [], workdir: str = '') -> None: +def runDetachedProcess(cmdln: List[str] = [], workdir: str = ''): """ Run a detached process. Args: @@ -371,7 +334,7 @@ def runDetachedProcess(cmdln: List[str] = [], workdir: str = '') -> None: """ -def runTerminal(script: str='', workdir: str = '', close_on_exit: bool = False) -> None: +def runTerminal(script: str = '', workdir: str = '', close_on_exit: bool = False): """ Run a script in the users shell and terminal. Args: @@ -381,7 +344,7 @@ def runTerminal(script: str='', workdir: str = '', close_on_exit: bool = False) """ -def sendTrayNotification(title: str='', msg: str = '', ms: int = 10000) -> None: +def sendTrayNotification(title: str = '', msg: str = '', ms: int = 10000): """ Send a tray notification. Args: From 2a1dbc4889051decc48bcce074962258ac1c373a Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:32:30 +0200 Subject: [PATCH 144/355] [wiki] Interface v2.0 --- wikipedia/__init__.py | 84 ++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 58c468ce..b44aac5c 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -8,56 +8,46 @@ from time import sleep from urllib import request, parse import json -import os +from pathlib import Path -md_iid = '1.0' -md_version = "1.8" +md_iid = '2.0' +md_version = "1.9" md_name = "Wikipedia" -md_description = "Search Wikipedia articles." +md_description = "Search Wikipedia articles" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/wikipedia" -class FallbackProvider(FallbackHandler): - - def id(self): - return f"{md_id}_fb" - - def name(self): - return md_name - - def description(self): - return md_description +class WikiFallbackHandler(FallbackHandler): + def __init__(self): + FallbackHandler.__init__(self, + id=f"{md_id}_fb", + name=f"{md_name} fallback", + description="Wikipedia fallback search") def fallbacks(self, query_string): stripped = query_string.strip() return [Plugin.createFallbackItem(query_string)] if stripped else [] -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): - iconPath = os.path.dirname(__file__) + "/wikipedia.png" baseurl = 'https://en.wikipedia.org/w/api.php' searchUrl = 'https://%s.wikipedia.org/wiki/Special:Search/%s' user_agent = "org.albert.wikipedia" limit = 20 + iconUrls = [f"file:{Path(__file__).parent}/wikipedia.png"] - def extensions(self): - return [self, FallbackProvider()] - - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='wiki ') + self.wiki_fb = WikiFallbackHandler() + PluginInstance.__init__(self, extensions=[self, self.wiki_fb]) - def defaultTrigger(self): - return "wiki " - def initialize(self): params = { 'action': 'query', 'meta': 'siteinfo', @@ -110,32 +100,36 @@ def handleTriggerQuery(self, query): summary = data[2][i] url = data[3][i] - results.append(Item(id=md_id, - text=title, - subtext=summary if summary else url, - icon=[self.iconPath], - actions=[ - Action("open", "Open article on Wikipedia", lambda u=url: openUrl(u)), - Action("copy", "Copy URL to clipboard", lambda u=url: setClipboardText(u)) - ])) + results.append(StandardItem(id=md_id, + text=title, + subtext=summary if summary else url, + iconUrls=self.iconUrls, + actions=[ + Action("open", "Open article on Wikipedia", lambda u=url: openUrl(u)), + Action("copy", "Copy URL to clipboard", lambda u=url: setClipboardText(u)) + ])) if not results: results.append(Plugin.createFallbackItem(stripped)) query.add(results) else: - query.add(Item(id=md_id, - text=md_name, - subtext="Enter a query to search on Wikipedia", - icon=[self.iconPath])) + query.add( + StandardItem( + id=md_id, + text=md_name, + subtext="Enter a query to search on Wikipedia", + iconUrls=self.iconUrls + ) + ) @staticmethod def createFallbackItem(query_string): - return Item( + return StandardItem( id=md_id, text=md_name, subtext="Search '%s' on Wiki" % query_string, - icon=[Plugin.iconPath], + iconUrls=Plugin.iconUrls, actions=[ Action("wiki_search", "Search on Wikipedia", lambda url=Plugin.searchUrl % (Plugin.local_lang_code, query_string): openUrl(url)) ] - ) \ No newline at end of file + ) From 58c471366637dc0df6e82807dd35c6a81f5451f4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:32:54 +0200 Subject: [PATCH 145/355] [zeal] Interface v2.0 --- zeal/__init__.py | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/zeal/__init__.py b/zeal/__init__.py index 5677ecba..843eee45 100644 --- a/zeal/__init__.py +++ b/zeal/__init__.py @@ -1,40 +1,33 @@ """Search in Zeal offline docs.""" -from subprocess import run from albert import * -md_iid = '1.0' -md_version = '1.1' +md_iid = '2.0' +md_version = '1.2' md_name = 'Zeal' md_description = 'Search in Zeal docs' md_url = 'https://github.com/albertlauncher/python/zeal' md_bin_dependencies = ['zeal'] -class Plugin(TriggerQueryHandler): - iconUrl = "xdg:zeal" - - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return 'z ' +class Plugin(PluginInstance, TriggerQueryHandler): + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='z ') + PluginInstance.__init__(self, extensions=[self]) def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: query.add( - Item( + StandardItem( id=md_name, text=md_name, subtext=f"Search '{stripped}' in Zeal", - icon=[Plugin.iconUrl], + iconUrls=["xdg:zeal"], actions=[Action("zeal", "Search in Zeal", lambda s=stripped: runDetachedProcess(['zeal', s]))] ) ) From d14fdb4e23ac9bab5f30e5eebc93136a4ab8a36f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:46:40 +0200 Subject: [PATCH 146/355] [arch_wiki] Interface v2.0 --- arch_wiki/__init__.py | 73 +++++++++++++--------------- arch_wiki/{ArchWiki.svg => arch.svg} | 0 2 files changed, 34 insertions(+), 39 deletions(-) rename arch_wiki/{ArchWiki.svg => arch.svg} (100%) diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index 0c531506..cc70f54e 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -1,49 +1,44 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2022-2023 Manuel Schneider -from albert import * +import json +from pathlib import Path from time import sleep from urllib import request, parse -import json -import os -md_iid = '1.0' -md_version = "1.3" +from albert import * + +md_iid = '2.0' +md_version = "1.4" md_name = "ArchLinux Wiki" md_description = "Search ArchLinux Wiki articles" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/awiki" -md_maintainers = "@manuelschneid3r" -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): - icon = [os.path.dirname(__file__) + "/ArchWiki.svg"] baseurl = 'https://wiki.archlinux.org/api.php' search_url = "https://wiki.archlinux.org/index.php?search=%s" user_agent = "org.albert.extension.python.archwiki" - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return "awiki " + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='awiki ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = [f"file:{Path(__file__).parent}/arch.svg"] def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: # avoid rate limiting - for number in range(50): + for _ in range(50): sleep(0.01) if not query.isValid: - return; + return results = [] @@ -65,25 +60,25 @@ def handleTriggerQuery(self, query): summary = data[2][i] url = data[3][i] - results.append(Item(id=md_id, - text=title, - subtext=summary if summary else url, - icon=self.icon, - actions=[ - Action("open", "Open article", lambda u=url: openUrl(u)), - Action("copy", "Copy URL", lambda u=url: setClipboardText(u)) - ])) + results.append(StandardItem(id=md_id, + text=title, + subtext=summary if summary else url, + iconUrls=self.iconUrls, + actions=[ + Action("open", "Open article", lambda u=url: openUrl(u)), + Action("copy", "Copy URL", lambda u=url: setClipboardText(u)) + ])) if results: query.add(results) else: - query.add(Item(id=md_id, - text="Search '%s'" % query.string, - subtext="No results. Start online search on Arch Wiki", - icon=self.icon, - actions=[Action("search", "Open search", lambda s=query.string: self.search_url % s)])) + query.add(StandardItem(id=md_id, + text="Search '%s'" % query.string, + subtext="No results. Start online search on Arch Wiki", + iconUrls=self.iconUrls, + actions=[Action("search", "Open search", lambda s=query.string: self.search_url % s)])) else: - query.add(Item(id=md_id, - text=md_name, - icon=self.icon, - subtext="Enter a query to search on the Arch Wiki")) + query.add(StandardItem(id=md_id, + text=md_name, + iconUrls=self.iconUrls, + subtext="Enter a query to search on the Arch Wiki")) diff --git a/arch_wiki/ArchWiki.svg b/arch_wiki/arch.svg similarity index 100% rename from arch_wiki/ArchWiki.svg rename to arch_wiki/arch.svg From 27b6995994b169f75d02e9dea7a7b019e734415c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:51:41 +0200 Subject: [PATCH 147/355] [aur] Interface v2.0 --- aur/__init__.py | 60 +++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/aur/__init__.py b/aur/__init__.py index 6d9e6c13..a2bcb1e2 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -6,42 +6,38 @@ quickly install the packages. If you are missing your favorite AUR helper tool send a PR. """ -from albert import * -from shutil import which +import json from datetime import datetime -from urllib import request, parse +from pathlib import Path +from shutil import which from time import sleep -import json -import os +from urllib import request, parse + +from albert import * -md_iid = '1.0' -md_version = "1.7" +md_iid = '2.0' +md_version = "1.8" md_name = "AUR" md_description = "Query and install AUR packages" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/aur" -md_maintainers = "@manuelschneid3r" +# md_platforms = ["Linux"] -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): aur_url = "https://aur.archlinux.org/packages/" baseurl = 'https://aur.archlinux.org/rpc/' - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return "aur " + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='aur ') + PluginInstance.__init__(self, extensions=[self]) - def initialize(self): - self.icon = [os.path.dirname(__file__)+"/arch.svg"] + self.iconUrls = [f"file:{Path(__file__).parent}/arch.svg"] if which("yaourt"): self.install_cmdline = "yaourt -S aur/%s" @@ -56,7 +52,7 @@ def initialize(self): self.install_cmdline = None def handleTriggerQuery(self, query): - for number in range(50): + for _ in range(50): sleep(0.01) if not query.isValid: return @@ -75,11 +71,11 @@ def handleTriggerQuery(self, query): with request.urlopen(req) as response: data = json.loads(response.read().decode()) if data['type'] == "error": - query.add(Item( + query.add(StandardItem( id=md_id, text="Error", subtext=data['error'], - icon=self.icon + iconUrls=self.iconUrls )) else: results = [] @@ -89,13 +85,13 @@ def handleTriggerQuery(self, query): for entry in results_json: name = entry['Name'] - item = Item( - id = md_id, - icon = self.icon, - text = f"{entry['Name']} {entry['Version']}" + item = StandardItem( + id=md_id, + iconUrls=self.iconUrls, + text=f"{entry['Name']} {entry['Version']}" ) - subtext = f"☆{entry['NumVotes']}" + subtext = f"⭐{entry['NumVotes']}" if entry['Maintainer'] is None: subtext += ', Unmaintained!' if entry['OutOfDate']: @@ -136,10 +132,10 @@ def handleTriggerQuery(self, query): query.add(results) else: - query.add(Item( + query.add(StandardItem( id=md_id, text=md_name, subtext="Enter a query to search the AUR", - icon=self.icon, + iconUrls=self.iconUrls, actions=[Action("open-aur", "Open AUR packages website", lambda: openUrl(self.aur_url))] )) From 2277ff74d521431f6a00fea9fa7c9a12c3c4cafe Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:52:39 +0200 Subject: [PATCH 148/355] [bitwarden] Interface v2.0 --- bitwarden/__init__.py | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 0185358b..78d39f51 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -import os +from pathlib import Path from subprocess import run, CalledProcessError from albert import * -md_iid = '1.0' -md_version = "1.2" +md_iid = '2.0' +md_version = "1.3" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" md_license = "BSD-3" @@ -15,21 +15,17 @@ md_credits = "Original author: @tylio" md_bin_dependencies = ["rbw"] -class Plugin(TriggerQueryHandler): - def id(self): - return md_id - def name(self): - return md_name +class Plugin(PluginInstance, TriggerQueryHandler): - def description(self): - return md_description - - def defaultTrigger(self): - return "bw " - - def initialize(self): - self.icon = [os.path.dirname(__file__) + "/bw.svg"] + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='bw ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = [f"file:{Path(__file__).parent}/bw.svg"] def _get_passwords(self): field_names = ["id", "name", "user", "folder"] @@ -54,17 +50,17 @@ def _get_passwords(self): def handleTriggerQuery(self, query): if query.string.strip().lower() == "unlock": query.add( - Item( + StandardItem( id="unlock", text="Unlock Bitwarden Vault", - icon=self.icon, + iconUrls=self.iconUrls, actions=[ Action( id="unlock", text="Unlocking Bitwarden Vault", callable=lambda: runTerminal( - script="rbw stop-agent && rbw unlock", - close_on_exit=True + script="rbw stop-agent && rbw unlock", + close_on_exit=True ) ) ] @@ -105,11 +101,11 @@ def handleTriggerQuery(self, query): except CalledProcessError as err: code = run (["echo"], capture_output=True,encoding="utf-8", check=True) query.add( - Item( + StandardItem( id=p["id"], text=p["path"], subtext=p["user"], - icon=self.icon, + iconUrls=self.iconUrls, actions=[ Action( id="copy", From 8c688ecfaf5e39b3fbf5e6e1bc6ebf442ec352fd Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:52:59 +0200 Subject: [PATCH 149/355] [coingecko] Interface v2.0 --- coingecko/__init__.py | 94 +++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 57 deletions(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index 61b0019b..328f5e6b 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -9,8 +9,8 @@ from pathlib import Path from threading import Thread, Event -md_iid = "1.0" -md_version = "1.0" +md_iid = "2.0" +md_version = "1.1" md_name = "CoinGecko" md_description = "Access CoinGecko" md_license = "BSD-3" @@ -52,7 +52,7 @@ def stop(self): self._stop_event.set() -class CoinItem(AbstractItem): +class NameItem(StandardItem): def __init__(self, identifier: str, name: str, @@ -62,48 +62,40 @@ def __init__(self, cap: float, vol: float, change24h: float): - AbstractItem.__init__(self) - self.identifier = identifier + StandardItem.__init__( + self, + id=identifier, + text=f"{name} {price} {symbol}/$", + subtext=f"#{rank}, 24h: {change24h}%, Cap: {cap:n} $, Vol: {vol:n} $", + inputActionText=str(price), + iconUrls=Plugin.iconUrls, + actions=[ + Action("show", f"Show {name} on CoinGecko", + lambda id=identifier: openUrl(Plugin.coinsUrl + id)), + Action("url", "Copy URL to clipboard", + lambda id=identifier: setClipboardText(Plugin.coinsUrl + id)) + ] + ) self.name = name self.symbol = symbol - self.rank = rank - self.price = price - self.cap = cap - self.vol = vol - self.change24h = change24h - def id(self): - return self.identifier - def text(self): - return f"{self.name} {self.price} {self.symbol}/$" +class Plugin(PluginInstance, IndexQueryHandler): - def subtext(self): - return f"#{self.rank}, 24h: {self.change24h}%, Cap: {self.cap:n} $, Vol: {self.vol:n} $" - - def completion(self): - return str(self.price) - - def icon(self): - return [Plugin.iconPath] - - def actions(self): - return [ - Action("show", f"Show {self.name} on CoinGecko", - lambda id=self.identifier: openUrl(Plugin.coinsUrl + id)), - Action("url", "Copy URL to clipboard", - lambda id=self.identifier: setClipboardText(Plugin.coinsUrl + id)) - ] - - -class Plugin(IndexQueryHandler): - iconPath = str(Path(__file__).parents[0] / "coingecko.png") coinsUrl = "https://www.coingecko.com/en/coins/" + iconUrls = [f"file:{Path(__file__).parent}/coingecko.png"] + + def __init__(self): + IndexQueryHandler.__init__( + self, md_id, md_name, md_description, + defaultTrigger='cg ', + synopsis='< symbol | name >' + ) + PluginInstance.__init__(self, extensions=[self]) - def initialize(self): self.items = [] self.mtime = 0 - self.coinCacheFilePath = Path(self.cacheLocation()) / "coins.json" + self.coinCacheFilePath = self.cacheLocation / "coins.json" self.thread = CoinFetcherThread(self.updateIndexItems, self.coinCacheFilePath) self.thread.start() @@ -111,18 +103,6 @@ def finalize(self): self.thread.stop() self.thread.join() - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return "cg " - def updateIndexItems(self): mtime = self.coinCacheFilePath.lstat().st_mtime if self.coinCacheFilePath.is_file() and mtime > self.mtime: @@ -130,15 +110,15 @@ def updateIndexItems(self): with open(self.coinCacheFilePath) as f: self.items.clear() for json_object in load(f): - self.items.append(CoinItem( - identifier = json_object['id'], - name = json_object['name'], - symbol = json_object['symbol'].upper(), - rank = json_object['market_cap_rank'], - price = json_object['current_price'], - cap = json_object['market_cap'], - vol = json_object['total_volume'], - change24h = json_object['price_change_percentage_24h'] + self.items.append(NameItem( + identifier=json_object['id'], + name=json_object['name'], + symbol=json_object['symbol'].upper(), + rank=json_object['market_cap_rank'], + price=json_object['current_price'], + cap=json_object['market_cap'], + vol=json_object['total_volume'], + change24h=json_object['price_change_percentage_24h'] )) index_items = [] From e3eb2bd3e5e3f7d8a08139887965d9fe0c290dc7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:53:19 +0200 Subject: [PATCH 150/355] [copyq] Interface v2.0 --- copyq/__init__.py | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/copyq/__init__.py b/copyq/__init__.py index 7c241b55..ae418eb5 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = '1.0' -md_version = "1.3" +md_iid = '2.0' +md_version = "1.4" md_name = "CopyQ" md_description = "Access CopyQ clipboard" md_license = "BSD-2-Clause" @@ -45,21 +45,16 @@ """ -class Plugin(TriggerQueryHandler): - def id(self): - return md_id +class Plugin(PluginInstance, TriggerQueryHandler): - def name(self): - return md_name - - def description(self): - return md_description - - def synopsis(self): - return "" - - def defaultTrigger(self): - return "cq " + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis="", + defaultTrigger='cq ') + PluginInstance.__init__(self, extensions=[self]) def handleTriggerQuery(self, query): items = [] @@ -81,9 +76,9 @@ def handleTriggerQuery(self, query): lambda: runDetachedProcess(["copyq", script % row]) ) items.append( - Item( + StandardItem( id=md_id, - icon=["xdg:copyq"], + iconUrls=["xdg:copyq"], text=text, subtext="%s: %s" % (row, ", ".join(json_obj["mimetypes"])), actions=[ From 8252377dd282310f59997ec5ed51adbec5b06898 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:55:03 +0200 Subject: [PATCH 151/355] [dice_roll] Interface v2.0 --- dice_roll/__init__.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/dice_roll/__init__.py b/dice_roll/__init__.py index 944e054c..5a338b75 100644 --- a/dice_roll/__init__.py +++ b/dice_roll/__init__.py @@ -14,8 +14,8 @@ Example: "roll 2d6 3d8 1d20" """ -md_iid = '1.0' -md_version = "1.1" +md_iid = '2.0' +md_version = "1.2" md_name = "Dice Roll" md_description = "Roll any number of dice" md_license = "MIT" @@ -39,7 +39,7 @@ def get_icon_path(num_sides: int | None) -> str: if num_sides is None: icon = "dice" # return the path to the icon - return str(icons_path / f"{icon}.svg") + return str("file:" + icons_path / f"{icon}.svg") def roll_dice(num_dice: int, num_sides: int) -> tuple[int, list[int]]: @@ -57,10 +57,9 @@ def roll_dice(num_dice: int, num_sides: int) -> tuple[int, list[int]]: def get_item_from_rolls( - rolls: list[int], - sum_rolls: int, - num_sides: int | None = None, -) -> albert.Item: + rolls: list[int], + sum_rolls: int, + num_sides: int | None = None) -> albert.Item: """Creates an Albert Item from a list of rolls, the total, and the number of sides. If num_sides is not provided, an "Overall Total" summary item is created. @@ -72,9 +71,9 @@ def get_item_from_rolls( Returns: albert.Item: The item to be added to the list of results. """ - return albert.Item( + return albert.StandardItem( id=get_icon_path(num_sides), - icon=[get_icon_path(num_sides)], + iconUrls=[get_icon_path(num_sides)], text=( f"Rolled {len(rolls)}d{num_sides} - Total: {sum_rolls}" if num_sides @@ -132,7 +131,7 @@ class Plugin(albert.TriggerQueryHandler): """A plugin to roll dice""" def id(self) -> str: - return __name__ + return md_id def name(self) -> str: return md_name From 534faef2bb1edddc8c42908130ff2665c46c293b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:55:31 +0200 Subject: [PATCH 152/355] [docker] Interface v2.0 --- docker/__init__.py | 93 +++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 51 deletions(-) diff --git a/docker/__init__.py b/docker/__init__.py index eb8fb412..547762f2 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -2,39 +2,34 @@ Docker wrapper (prototype) """ -# Copyright (c) 2022-2023 Manuel Schneider +from pathlib import Path -from albert import * -import pathlib import docker +from albert import * -md_iid = "1.0" -md_version = "1.4" +md_iid = "2.0" +md_version = "1.5" md_name = "Docker" -md_description = "Control your docker instance" +md_description = "Manage docker images and containers" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/docker" md_bin_dependencies = "docker" md_lib_dependencies = "docker" -class Plugin(QueryHandler): - - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description +class Plugin(PluginInstance, GlobalQueryHandler): - def defaultTrigger(self): - return "d " + def __init__(self): + GlobalQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='d ', + synopsis='') + PluginInstance.__init__(self, extensions=[self]) - def initialize(self): - self.icon_running = [str(pathlib.Path(__file__).parent / "running.png")] - self.icon_stopped = [str(pathlib.Path(__file__).parent / "stopped.png")] + self.icon_urls_running = [f"file:{Path(__file__).parent}/running.png"] + self.icon_urls_stopped = [f"file:{Path(__file__).parent}/stopped.png"] self.client = docker.from_env() if not self.client: self.client = docker.DockerClient(base_url='unix://var/run/docker.sock') @@ -48,48 +43,44 @@ def handleGlobalQuery(self, query): if query.string in container.name: # Create dynamic actions if container.status == 'running': - actions = [ - Action("stop", "Stop container", lambda c=container: c.stop()), - Action("restart", "Restart container", lambda c=container: c.restart()) - ] + actions = [Action("stop", "Stop container", lambda c=container: c.stop()), + Action("restart", "Restart container", lambda c=container: c.restart())] else: - actions = [ - Action("start", "Start container", lambda c=container: c.start()) - ] + actions = [Action("start", "Start container", lambda c=container: c.start())] actions.extend([ - Action("logs", "Logs", lambda c=container.id: runTerminal("docker logs -f %s" % c, close_on_exit=False)), - Action("remove", "Remove (forced, with volumes)", lambda c=container: c.remove(v=True, force=True)), - Action("copy-id", "Copy id to clipboard", lambda id=container.id: setClipboardText(id)) + Action("logs", "Logs", + lambda c=container.id: runTerminal("docker logs -f %s" % c, close_on_exit=False)), + Action("remove", "Remove (forced, with volumes)", + lambda c=container: c.remove(v=True, force=True)), + Action("copy-id", "Copy id to clipboard", + lambda id=container.id: setClipboardText(id)) ]) rank_items.append(RankItem( - item=Item( + item=StandardItem( id=container.id, text="%s (%s)" % (container.name, ", ".join(container.image.tags)), subtext="Container: %s" % container.id, - icon=self.icon_running if container.status == 'running' else self.icon_stopped, + iconUrls=self.icon_urls_running if container.status == 'running' else self.icon_urls_stopped, actions=actions ), - score=0 # len(query.string)/len(container.name) + score=len(query.string)/len(container.name) )) for image in reversed(self.client.images.list()): - if any([query.string in tag for tag in image.tags]): - rank_items.append(RankItem( - item=Item( - id=image.short_id, - text=", ".join(image.tags), - subtext="Image: %s" % image.id, - icon=self.icon_stopped, - actions=[ - Action("run", "Run with command: %s" % query.string, - lambda i=image, s=query.string: client.containers.run(i, s)), - Action("rmi", "Remove image", lambda i=image: i.remove()) - ] - ), - score=0 - )) - + for tag in sorted(image.tags, key=len): # order by resulting score + if query.string in tag: + rank_items.append(RankItem( + item=StandardItem( + id=image.short_id, + text=", ".join(image.tags), + subtext="Image: %s" % image.id, + iconUrls=self.icon_urls_stopped, + actions=[Action("run", "Run with command: %s" % query.string, + lambda i=image, s=query.string: client.containers.run(i, s)), + Action("rmi", "Remove image", lambda i=image: i.remove())] + ), + score=len(query.string)/len(tag) + )) return rank_items - From c3bf76b097f376a768310e836918de3923ad39a2 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:56:07 +0200 Subject: [PATCH 153/355] [emoji] Drop old linux emoji implementation --- emoji/__init__.py | 138 -- emoji/aliases.json | 1 - emoji/emoji-test.txt | 5024 ------------------------------------------ emoji/scrape_aliases | 68 - 4 files changed, 5231 deletions(-) delete mode 100644 emoji/__init__.py delete mode 100644 emoji/aliases.json delete mode 100644 emoji/emoji-test.txt delete mode 100755 emoji/scrape_aliases diff --git a/emoji/__init__.py b/emoji/__init__.py deleted file mode 100644 index 12943ff4..00000000 --- a/emoji/__init__.py +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: utf-8 -*- - -import json -import re -import subprocess -from concurrent.futures import ThreadPoolExecutor -from itertools import islice -from pathlib import Path -from albert import * - -md_iid = '1.0' -md_version = "1.3" -md_name = "Emoji Picker" -md_description = "Find emojis by name" -md_license = "GPL-3.0" -md_url = "https://github.com/albertlauncher/python/tree/master/emoji" -md_maintainers = "@tyilo" -md_bin_dependencies = ["convert"] - - -EXTENSION_DIR = Path(__file__).parent -ALIASES_PATH = EXTENSION_DIR / "aliases.json" -EMOJI_PATH = EXTENSION_DIR / "emoji-test.txt" - - -def convert_to_png(emoji, output_path): - subprocess.run( - [ - "convert", - "-pointsize", - "64", - "-background", - "transparent", - f"pango:{emoji}", - output_path, - ] - ) - - -def schedule_create_missing_icons(emojis, icon_dir_path: Path): - executor = ThreadPoolExecutor() - for emoji in emojis: - path = icon_dir_path / f"{emoji['emoji']}.png" - if not path.exists(): - executor.submit(convert_to_png, emoji["emoji"], path) - - return executor - - -class Plugin(TriggerQueryHandler): - def id(self): - return __name__ - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return ": " - - def synopsis(self): - return "" - - def initialize(self): - self.icon_dir_path = Path(self.cacheLocation()) - - line_re = re.compile( - r""" - ^ - (?P .*\S) - \s*;\s* - (?P \S+) - \s*\#\s* - (?P \S+) - \s* - (?P E\d+.\d+) - \s* - (?P [^:]+) - (?: : \s* (?P .+))? - \n - $ - """, - re.VERBOSE, - ) - - with ALIASES_PATH.open("r") as f: - aliases = json.load(f) - - self.emojis = [] - with EMOJI_PATH.open("r") as f: - for line in f: - if m := line_re.match(line): - e = m.groupdict() - if e["status"] == "fully-qualified": - search_tokens = [e["name"]] - if e["modifiers"]: - search_tokens.append(e["modifiers"]) - e["aliases"] = [a.lower() for a in aliases.get(e["name"], [])] - search_tokens += e["aliases"] - e["search_tokens"] = search_tokens - self.emojis.append(e) - - self.icon_executor = schedule_create_missing_icons(self.emojis, self.icon_dir_path) - - def finalize(self): - self.icon_executor.shutdown(wait=True, cancel_futures=True) - - def matched_emojis(self, query_tokens): - for emoji in self.emojis: - for w in query_tokens: - if w not in " ".join(emoji["search_tokens"]): - break - - yield emoji - - def handleTriggerQuery(self, query): - query_tokens = query.string.strip().lower().split() - if not query_tokens: - return - - for emoji in islice(self.matched_emojis(query_tokens), 100): - query.add( - Item( - id=f"emoji_{emoji['emoji']}", - text=f"{emoji['emoji']} {emoji['name']}", - subtext=emoji["modifiers"] or "", - icon=[str(self.icon_dir_path / f"{emoji['emoji']}.png")], - actions=[ - Action( - "copy", - "Copy to clipboard", - lambda r=emoji["emoji"]: setClipboardText(r), - ), - ], - ) - ) diff --git a/emoji/aliases.json b/emoji/aliases.json deleted file mode 100644 index 55b0874d..00000000 --- a/emoji/aliases.json +++ /dev/null @@ -1 +0,0 @@ -{"person walking": ["Walker", "Walking"], "grinning face with sweat": ["Exercise", "Happy Sweat"], "slightly smiling face": ["Slightly Happy", "This Is Fine"], "face with tears of joy": ["Laughing", "Laughing Crying", "Laughing Tears", "LOL"], "upside-down face": ["Sarcasm", "Silly"], "grinning squinting face": ["><", "Big Grin", "Closed-Eyes Smile", "Laughing", "XD"], "smiling face with hearts": ["In Love Face"], "winking face": ["Wink", "Wink Face", "Winky Face"], "rolling on the floor laughing": ["ROFL"], "smiling face with heart-eyes": ["Heart Eyes", "Heart Face"], "face blowing a kiss": ["Blow A Kiss", "Blowing Kiss", "Kissing"], "kissing face": [":-*", "Duck Face", "Kissy Face", "Whistling"], "star-struck": ["Excited", "Star Eyes", "Starry Eyed", "Wow Face"], "smiling face with halo": ["Angel", "Halo"], "kissing face with closed eyes": ["Kiss Face", "Kissy Face"], "smiling face with smiling eyes": ["^^", "Happy Face", "Smile", "Smiley Face"], "face with tongue": ["Cheeky", "Tongue Face", "Tongue-Out"], "face savoring food": ["Goofy", "Hungry"], "smiling face": ["Happy Face", "Smiley Face", "Smiling"], "winking face with tongue": ["Crazy", "Crazy Face"], "kissing face with smiling eyes": ["Kiss Face", "Kissy", "Whistle", "Whistling"], "shushing face": ["Hush", "Quiet", "Shh"], "zany face": ["Crazy Eyes", "Excited", "Wild"], "squinting face with tongue": ["Tongue Out"], "thinking face": ["Chin Thumb", "Thinker", "Throwing Shade"], "zipper-mouth face": ["Lips Sealed", "Sealed Lips", "Zip It"], "face with raised eyebrow": ["Colbert", "The Rock"], "expressionless face": ["Face With Straight Mouth", "Straight Face"], "neutral face": ["Face With Straight Mouth", "Straight Faced"], "smirking face": ["Flirting", "Sexual Face", "Smug Face", "Suggestive Smile"], "face with rolling eyes": ["Eye Roll"], "grimacing face": ["Awkward", "Eek", "Foot In Mouth", "Nervous", "Snapchat Mutual #1 Best Friend"], "face in clouds": ["Brain Fog", "Forgetful", "Haze"], "face without mouth": ["Blank Face", "Mouthless", "Silence", "Silent"], "pensive face": ["Pensive", "Sad", "Sadface", "Sorrowful"], "money-mouth face": ["Dollar Sign Eyes", "Money Face", "Rich"], "face exhaling": ["Sigh"], "lying face": ["Liar", "Long Nose", "Pinocchio"], "sleepy face": ["Side-Tear", "Snot Bubble"], "sleeping face": ["Sleep Face", "Snoring", "Zzz Face"], "face with medical mask": ["Coronavirus", "COVID-19", "Mask Face", "Surgical Mask"], "face with thermometer": ["Ill", "Sick"], "relieved face": ["Content", "Pleased"], "drooling face": ["Drool"], "face with head-bandage": ["Bandaged Head", "Clumsy", "Injured"], "nauseated face": ["Disgust", "Green Face", "Vomit"], "sneezing face": ["Gesundheit"], "woozy face": ["Drunk Face"], "unamused face": ["Dissatisfied", "Meh", "Side-Eye", "Unimpressed"], "exploding head": ["Mind Blown"], "cowboy hat face": ["Cowboy"], "smiling face with sunglasses": ["Cool", "Mutual Best Friends (Snapchat)", "Sunglasses"], "nerd face": ["Nerdy"], "face with spiral eyes": ["Dizzy Face"], "confused face": ["Nonplussed", "Puzzled", ":S"], "face vomiting": ["Spew", "Throwing Up", "Vomit"], "frowning face": ["Megafrown"], "slightly frowning face": ["Slightly Sad"], "face with open mouth": ["Open Mouth", "Surprised"], "astonished face": ["Drunk Face", "Gasping Face", "Shocked Face"], "pleading face": ["Begging", "Glossy Eyes", "Simp"], "hushed face": ["Surprise", "Surprised Face"], "frowning face with open mouth": ["Yawning"], "worried face": ["Sad", "Sadface"], "sad but relieved face": ["Eyebrow Sweat"], "loudly crying face": ["Bawling", "Crying", "Sad Tears", "Sobbing"], "crying face": ["Crying", "Tear"], "flushed face": [":$", "Blushing Face", "Embarrassed", "Shame"], "person running": ["Jogging", "Run"], "fearful face": ["Scared", "Surprised"], "anguished face": ["Pained Face"], "anxious face with sweat": ["Blue Face", "Concerned Face", "Nervous Face"], "face screaming in fear": ["Home Alone", "Scream", "Screaming Face"], "man juggling": ["Male Juggler"], "synagogue": ["Jewish", "Synagog", "Temple"], "card index": ["Index Card", "Rolodex", "System Card"], "shinto shrine": ["Kami-no-michi"], "confounded face": ["Quivering Mouth", "Scrunched Face"], "raising hands": ["Arms In The Air", "Banzai", "Festivus Miracle", "Hallelujah", "Praise Hands", "Two Hands"], "chart decreasing": ["Down Pointing Graph", "Negative Chart"], "chart increasing": ["Positive Chart", "Up Pointing Graph"], "fountain": ["Park", "Water Feature", "Water Fountain"], "woman juggling": ["Female Juggler"], "bar chart": ["Bar Graph"], "kaaba": ["Mecca"], "man cook": ["Male Chef"], "tent": ["Camping Tent"], "round pushpin": ["Dropped Pin", "Map Pin", "Pin", "Red Pin"], "foggy": ["Fog", "Foggy City", "Fog Bridge"], "pushpin": ["Thumb Tack"], "night with stars": ["City At Night", "Starry Night"], "sunrise over mountains": ["Morning", "Sunrise"], "woman cook": ["Female Chef"], "paperclip": ["Clippy"], "cityscape at dusk": ["Dusk City", "Orange Sky City"], "sunrise": ["Sunset"], "person in lotus position": ["Meditation", "Yoga"], "triangular ruler": ["Triangle Ruler"], "sunset": ["City Sunset"], "scissors": ["Cutting"], "hot springs": ["Onsen", "Steam"], "carousel horse": ["Carnival", "Fairground", "Merry Go Round"], "file cabinet": ["Filing Cabinet"], "open hands": ["Hug", "Jazz Hands"], "locked": ["Closed Lock", "Padlock"], "bridge at night": ["Bridge", "Golden Gate Bridge"], "roller coaster": ["Rollercoaster", "Theme Park"], "unlocked": ["Open Padlock", "Unlock"], "locked with key": ["Lock And Key"], "palms up together": ["Dua"], "wastebasket": ["Garbage Can", "Rubbish Bin", "Trash Can", "Wastepaper Basket"], "ferris wheel": ["Big Wheel", "Fairground", "Observation Wheel"], "barber pole": ["Barber Shop", "Barber's Stripes", "Hairdresser"], "circus tent": ["Big Top", "Circus"], "locked with pen": ["Lock And Pen", "Lock With Fountain Pen"], "pick": ["Pickaxe"], "key": ["Gold Key"], "train": ["Diesel Train", "Electric Train", "Passenger Train", "Regular Train"], "locomotive": ["Railway Locomotive", "Steam Train"], "hammer": ["Claw Hammer", "Handyman", "Tool"], "railway car": ["Railcar", "Railroad Car", "Railway Carriage", "Railway Wagon"], "handshake": ["Shaking Hands"], "metro": ["Subway", "Tube", "Underground"], "dagger": ["Knife Weapon"], "station": ["Train Platform", "Train Station"], "bullet train": ["Bullet Train", "Shinkansen"], "mountain railway": ["Funicular", "Train And Mountain"], "person taking bath": ["Bathing", "Hot Bath"], "bow and arrow": ["Archery"], "oncoming bus": ["Front Of Bus"], "bus": ["School Bus"], "wrench": ["Spanner"], "nut and bolt": ["Bolt", "Screw"], "trolleybus": ["Electric Bus", "Trolley Bus"], "minibus": ["Minivan", "People-Mover"], "fire engine": ["Fire Department", "Fire Truck"], "taxi": ["New York Taxi", "Side Of Taxi", "Taxicab"], "balance scale": ["Scales of Justice"], "police car": ["Cop Car", "Side Of Police Car"], "oncoming police car": ["\ud83d\ude93 Front Of Police Car", "\ud83d\ude93 Cop Car"], "link": ["Chain", "Hyperlink", "Linked Chain"], "clamp": ["Clamp", "Table Vice", "WinZip"], "people holding hands": ["Gender Inclusive Couple", "Gender Neutral Couple", "Gender Nonconforming Couple"], "oncoming taxi": ["Front Of Taxi", "Taxicab"], "automobile": ["Car", "Red Car", "Side Of Car"], "oncoming automobile": ["Front Of Car"], "sport utility vehicle": ["Campervan", "Motorhome", "RV"], "articulated lorry": ["Green Truck", "Truck"], "tractor": ["Farm", "Farming"], "racing car": ["F1", "Formula One"], "microscope": ["Magnify", "Science"], "motorcycle": ["Motorbike", "Motorcycle"], "telescope": ["Stargazing"], "syringe": ["Vaccination"], "auto rickshaw": ["Tuk Tuk"], "pill": ["Capsule", "Drugs", "Tablet"], "motor scooter": ["Motor Bike", "Motor Cycle", "Vespa"], "drop of blood": ["Blood Donation", "Menstruation", "Period"], "bicycle": ["Bike", "Push Bike"], "man office worker": ["Businessman", "CEO"], "roller skate": ["Inline Skate", "Roller Derby"], "adhesive bandage": ["Band Aid", "Plaster"], "door": ["Doorway", "Front Door"], "fuel pump": ["Gas Pump", "Petrol Pump"], "bed": ["Bedroom"], "police car light": ["Emergency Light", "Flashing Light", "Police Siren", "Siren"], "motorway": ["Highway", "Interstate", "Road"], "couch and lamp": ["Lounge", "Settee", "Sofa"], "horizontal traffic light": ["Traffic Light"], "folded hands": ["Namaste", "Please", "Prayer", "Thank You"], "toilet": ["Bathroom", "Loo", "Restroom"], "stop sign": ["Stop Sign"], "woman office worker": ["Businesswoman", "CEO"], "vertical traffic light": ["Traffic Light"], "bathtub": ["Bubble Bath"], "ring buoy": ["Life Preserver", "Life Ring"], "sailboat": ["Dinghy", "Yacht"], "anchor": ["Admiralty Pattern Anchor", "Fisherman"], "construction": ["Black And Yellow Striped Sign", "Roadwork", "Roadwork Sign"], "shower": ["Shower Head"], "speedboat": ["Motorboat", "Powerboat"], "broom": ["Brush", "Sweep"], "nail polish": ["Fingers", "Manicure", "Nonchalant"], "ship": ["Cruise", "Cruise Ship"], "airplane": ["Aeroplane", "Plane"], "roll of paper": ["Toilet Paper"], "airplane arrival": ["Aeroplane Landing", "Plane Landing"], "selfie": ["Phone Camera", "Selfie Hand"], "small airplane": ["Small Aeroplane", "Small Plane"], "seat": ["Aeroplane Seat", "Airplane Seat", "Bus Seat", "Train Seat"], "cigarette": ["Cigarette", "Smoke"], "women holding hands": ["Lesbian Couple"], "airplane departure": ["Aeroplane Taking Off", "Plane Taking Off"], "shopping cart": ["Shopping Cart"], "coffin": ["Casket", "Funeral"], "aerial tramway": ["Cable Car", "Gondola", "Ropeway"], "funeral urn": ["Vase"], "nazar amulet": ["Evil Eye Talisman", "Nazar Boncu\u011fu"], "flexed biceps": ["Feats of Strength", "Flexing Arm Muscles", "Muscle", "Strong"], "rocket": ["Rocket Ship", "Space Shuttle"], "placard": ["Lawn Sign", "Protest Sign", "Sign", "Sign on Post"], "flying saucer": ["UFO"], "man technologist": ["Male Blogger"], "moai": ["Easter Island", "Human Rock Carving", "Moai", "Moyai Statue"], "luggage": ["Suitcase"], "alarm clock": ["Alarm", "Clock"], "woman technologist": ["Female Blogger"], "litter in bin sign": ["Person With Trash", "Put Litter In Trash"], "potable water": ["Thirst", "Thirsty", "Water Tap"], "watch": ["Apple Watch", "Timepiece", "Wrist Watch"], "restroom": ["Bathroom Sign", "Toilet Sign"], "wheelchair symbol": ["Accessible Bathroom"], "baby symbol": ["Baby Change Station", "Baby Change Symbol", "Nursery"], "water closet": ["Toilet WC", "WC"], "passport control": ["Border Control"], "warning": ["Alert Symbol"], "children crossing": ["Kids Crossing", "School Crossing"], "man singer": ["Aladdin Sane", "Bowie"], "ear": ["Ears", "Hearing", "Listening"], "prohibited": ["Banned", "Circle Backslash", "No", "Red Circle Crossed", "Restricted"], "left luggage": ["Bag With Key", "Locked Suitcase"], "non-potable water": ["No Drinking Water", "No Water"], "no mobile phones": ["No Cell Phones", "No Phones", "No Smartphones"], "no bicycles": ["No Bikes Sign"], "radioactive": ["International Radiation Symbol", "Nuclear"], "no one under eighteen": ["NSFW"], "no pedestrians": ["No People", "No Walking"], "nose": ["Smelling", "Sniffing", "Stinky"], "up arrow": ["Arrow Pointing Up", "Up Arrow"], "left arrow": ["Arrow Pointing Left", "Left Arrow"], "down arrow": ["Arrow Pointing Down", "Down Arrow"], "up-right arrow": ["Diagonal Up-Right Arrow"], "right arrow": ["Arrow Pointing Right", "Right Arrow"], "up-left arrow": ["Diagonal Up-Left Arrow"], "down-right arrow": ["Diagonal Down-Right Arrow"], "down-left arrow": ["Diagonal Down-Left Arrow"], "left-right arrow": ["Horizontal Arrows", "Sideways Arrows"], "right arrow curving left": ["Email Reply", "Left Curved Arrow"], "up-down arrow": ["Vertical Arrows"], "right arrow curving down": ["Curved Down Arrow"], "woman and man holding hands": ["Heterosexual Couple", "Straight Couple"], "eyes": ["Eyeballs", "Shifty Eyes", "Wide Eyes"], "new moon": ["Dark Moon", "Shadow Moon", "Solar Eclipse"], "tongue": ["Tongue Out"], "eye": ["Single Eye"], "left arrow curving right": ["Email Forward", "Right Curved Arrow"], "baby": ["Child", "Toddler"], "mouth": ["Kissing Lips", "Lips"], "counterclockwise arrows button": ["Refresh", "Rotate", "Switch"], "place of worship": ["Religious Building"], "new moon face": ["Creepy Moon", "Dark Moon Face", "Molester Moon"], "bread": ["Loaf Of Bread"], "pancakes": ["Cr\u00eapes", "Hotcakes"], "baguette bread": ["French Bread"], "cut of meat": ["Meat", "Steak"], "cheese wedge": ["Cheese"], "poultry leg": ["Drumstick", "Turkey Leg"], "chestnut": ["Acorn", "Nut"], "hamburger": ["Burger", "Cheeseburger"], "pizza": ["Pepperoni Pizza", "Pizza"], "meat on bone": ["Barbecue", "BBQ", "Manga Meat"], "flatbread": ["Arepa"], "bacon": ["Rashers"], "tamale": ["Tamal"], "french fries": ["Chips", "Fries", "McDonald's Fries"], "burrito": ["Wrap"], "stuffed flatbread": ["Doner Kebab", "Gyro", "Shawarma"], "shallow pan of food": ["Paella"], "bowl with spoon": ["Cereal Bowl"], "cooking": ["Breakfast", "Fried Egg", "Frying Pan"], "popcorn": ["Popping Corn"], "pot of food": ["Bowl Of Food", "Soup", "Stew"], "canned food": ["Can of Food", "Tin Can", "Tinned Food"], "rice cracker": ["Cracker"], "rice ball": ["Onigiri"], "steaming bowl": ["Noodles", "Noodles With Chopsticks", "Ramen"], "hot dog": ["Hotdog", "Sausage"], "bento box": ["Lunch Box"], "curry rice": ["Curry", "Indian Food"], "sushi": ["Sashimi", "Seafood"], "fried shrimp": ["Fried Prawn", "Shrimp Tempura"], "oden": ["Kebab", "Skewer"], "fish cake with swirl": ["Fishcake", "Pink Swirl"], "cooked rice": ["Boiled Rice", "Bowl Of Rice", "Rice", "Steamed Rice"], "dumpling": ["Empanada", "Pierogi"], "takeout box": ["Chinese Food Box", "Oyster Pail"], "roasted sweet potato": ["Goguma", "Sweet Potato", "Yam"], "dango": ["Dessert Stick", "Pink White Green Balls"], "shrimp": ["Prawn"], "soft ice cream": ["Mr. Whippy", "Soft Serve"], "green salad": ["Salad"], "shaved ice": ["Snow Cone"], "ice cream": ["Bowl Of Ice Cream", "Dessert"], "doughnut": ["Donut"], "birthday cake": ["Birthday", "Cake", "Cake With Candles"], "shortcake": ["Cake", "Piece Of Cake", "Strawberry Shortcake"], "spaghetti": ["Pasta"], "cupcake": ["Fairy Cake"], "candy": ["Lolly", "Sweet"], "lollipop": ["Lollypop", "Sucker"], "custard": ["Creme Caramel", "Dessert", "Flan", "Pudding"], "teacup without handle": ["Green Tea", "Matcha", "Matcha Green Tea"], "chocolate bar": ["Candy Bar", "Chocolate"], "wine glass": ["Alcohol", "Red Wine", "Wine"], "cookie": ["Biscuit", "Chocolate Chip Cookie"], "honey pot": ["Honey", "Pot"], "sake": ["Bottle", "Rice Wine"], "glass of milk": ["Milk"], "bottle with popping cork": ["Celebration", "Champagne", "Sparkling Wine"], "hot beverage": ["Coffee", "Espresso", "Hot Chocolate", "Tea"], "tropical drink": ["Fruit Punch", "Tiki Drink"], "beer mug": ["Beer", "Beer Stein"], "cocktail glass": ["Cocktail", "Martini"], "bubble tea": ["Boba"], "tumbler glass": ["Bourbon", "Liquor", "Rum", "Whiskey", "Whisky"], "clinking glasses": ["Celebration", "Champagne Glasses", "Cheers"], "cup with straw": ["Milkshake", "Smoothie", "Soda Pop", "Soft Drink"], "clinking beer mugs": ["Beers", "Cheers"], "beverage box": ["Juice Box"], "mate": ["Chimarr\u00e3o", "Cimarr\u00f3n", "Yerba Mate"], "fork and knife with plate": ["Dinner"], "baby bottle": ["Bottle Feeding"], "kitchen knife": ["Butchers Knife", "Kitchen Knife", "Knife"], "amphora": ["Jar", "Vase"], "family": ["Parents With Child"], "globe with meridians": ["Internet", "World Wide Web", "WWW"], "fork and knife": ["Cutlery", "Knife And Fork", "Silverware"], "mount fuji": ["Fuji-san", "Snow-capped Mountain"], "stadium": ["Grandstand", "Sport Stadium"], "camping": ["Campsite"], "building construction": ["Crane"], "derelict house": ["Abandoned House", "Haunted House", "Old House"], "house": ["Home"], "office building": ["City Building", "High-Rise Building"], "house with garden": ["House And Tree"], "hospital": ["Emergency Room", "Medical", "Red Cross"], "hotel": ["Accommodation", "H Building"], "bank": ["Bakkureru", "Bank Branch", "BK"], "department store": ["Shopping Center", "Shops"], "factory": ["Industrial", "Industry", "Pollution", "Smog"], "convenience store": ["24-Hour Store", "7-Eleven\u00ae", "Corner Shop", "Kwik-E-Mart"], "love hotel": ["Heart Hospital", "Love Heart Hotel"], "school": ["Clock Tower", "Elementary School", "High School", "Middle School"], "post office": ["Post Office"], "church": ["Church Building", "Cross"], "wedding": ["Church Heart", "Church Wedding", "Marriage"], "mosque": ["Domed Roof", "Minaret"], "clutch bag": ["Clutch", "Small Bag"], "castle": ["Castle", "Turrets"], "pinched fingers": ["Finger Purse", "Ma Che Vuoi"], "thong sandal": ["Flip Flops", "Jandals", "Thongs"], "running shoe": ["Runner", "Sneaker", "Trainer"], "backpack": ["Backpack", "Bag", "School Bag"], "grinning face with big eyes": ["Grinning Face", "Happy", "Happy Face", "Smiley Face"], "grinning face with smiling eyes": ["Grinning Face", "Happy Face", "Smiley Face"], "ballet shoes": ["Pointe Shoe"], "victory hand": ["Air Quotes", "Peace", "Peace Sign", "V Sign"], "high-heeled shoe": ["High Heels", "Stiletto"], "crown": ["King", "Queen", "Royal"], "top hat": ["Formal Wear", "Groom"], "person facepalming": ["Facepalm", "Hitting Head", "Picard", "SMH"], "graduation cap": ["College", "Graduate", "Mortar Board", "Square Academic Cap", "University"], "crossed fingers": ["Fingers Crossed", "Good Luck"], "billed cap": ["Baseball Cap"], "lipstick": ["Lip Gloss", "Makeup"], "prayer beads": ["Dhikr Beads", "Rosary Beads"], "gem stone": ["Diamond", "Gem", "Jewel"], "person lifting weights": ["Bodybuilder"], "mage": ["Sorcerer", "Sorceress", "Witch", "Wizard"], "speaker low volume": ["Volume"], "ring": ["Diamond Ring", "Engagement Ring"], "speaker medium volume": ["Reduce Volume"], "muted speaker": ["Mute Volume"], "speaker high volume": ["Increase Volume"], "megaphone": ["Megaphone"], "person shrugging": ["\u00af\\_(\u30c4)_/\u00af", "Shrug", "Shruggie"], "loudspeaker": ["Announcement", "PA System"], "man mage": ["Wizard"], "bell": ["Liberty Bell", "Ringer", "Wedding Bell"], "postal horn": ["Bugle", "French Horn"], "bell with slash": ["Notifications", "Ringer Disabled"], "musical score": ["Sheet Music", "Treble Clef"], "musical note": ["Beamed Pair Of Eighth Notes", "Beamed Pair Of Quavers", "Music Note"], "musical notes": ["Music", "Music Notes", "Singing"], "microphone": ["Karaoke", "Singing"], "sign of the horns": ["Devil Fingers", "Heavy Metal", "Rock On"], "headphone": ["Earphone", "Headphones", "iPod"], "woman mage": ["Witch"], "person biking": ["Bicycle", "Bike", "Cyclist", "Person On Bike"], "radio": ["Digital Radio", "Wireless"], "saxophone": ["Jazz", "Sax"], "guitar": ["Acoustic Guitar", "Bass Guitar", "Electric Guitar"], "call me hand": ["Phone Hand", "Shaka"], "trumpet": ["Horn", "Jazz"], "musical keyboard": ["Piano"], "violin": ["String Quartet", "World\u2019s Smallest Violin"], "man biking": ["Male Cyclist"], "backhand index pointing left": ["Pointing Left"], "woman biking": ["Female Cyclist"], "mobile phone with arrow": ["Phone Call", "Phone With Arrow", "Pointing To Phone"], "mobile phone": ["Cell Phone", "iPhone", "Smartphone"], "telephone": ["Rotary Phone", "Telephone"], "man health worker": ["Male Doctor", "Male Nurse"], "pager": ["Beeper", "Bleeper"], "fax machine": ["Facsimile", "Fax"], "telephone receiver": ["Handset", "Phone"], "person mountain biking": ["Mountain Bike", "Person On Bike"], "backhand index pointing right": ["Pointing Right"], "vampire": ["Dracula"], "low battery": ["No Battery", "Red Battery"], "woman health worker": ["Female Doctor", "Female Nurse"], "laptop": ["Laptop", "Notebook"], "electric plug": ["AC Adaptor", "Power Cable", "Power Plug"], "desktop computer": ["iMac"], "battery": ["AA Battery", "Phone Battery"], "floppy disk": ["3.5\u2033 Disk", "Disk"], "man vampire": ["Dracula"], "optical disk": ["CD", "CD-ROM", "Compact Disc"], "backhand index pointing up": ["Middle Finger", "Pointing Up"], "movie camera": ["Film Camera", "Hollywood", "Movie"], "middle finger": ["Dito Medio", "Flipping The Bird", "Middle Finger", "Rude Finger"], "dvd": ["DVD-ROM", "DVD Video"], "clapper board": ["Clapboard", "Director", "Film Slate"], "camera": ["Digital Camera"], "person cartwheeling": ["Gymnast", "Gymnastics"], "merperson": ["Merboy", "Mergirl", "Mermaid", "Merman"], "television": ["TV"], "videocassette": ["VCR", "VHS", "Video Tape"], "backhand index pointing down": ["Pointing Down"], "video camera": ["Camcorder"], "magnifying glass tilted left": ["Magnifier", "Magnifying Glass", "Search Icon"], "light bulb": ["Idea", "Light Bulb"], "magnifying glass tilted right": ["Magnifier", "Magnifying Glass", "Search Icon"], "flashlight": ["Flashlight", "Torch"], "diya lamp": ["Oil Lamp"], "index pointing up": ["Pointing Up", "Secret"], "open book": ["Book", "Novel"], "red paper lantern": ["Asian Lantern", "Japanese Lantern", "Red Lantern"], "closed book": ["Red Book"], "elf": ["Legolas"], "books": ["Pile Of Books", "Stack Of Books"], "ledger": ["Binder", "Spiral Bound Book", "Yellow Book"], "people wrestling": ["Wrestling"], "notebook": ["Black And White Book"], "page with curl": ["Curled Page", "Curly Page"], "scroll": ["Degree", "Parchment"], "page facing up": ["Printed Page"], "thumbs up": ["Like", "Thumbs Up", "Yes"], "rolled-up newspaper": ["Newspaper Delivery"], "bookmark": ["Price Tag", "Tag"], "yen banknote": ["\u00a51000 Note", "Yen Note"], "dollar banknote": ["$1 Note", "American Dollar", "Dollar Bill"], "thumbs down": ["Bad", "Dislike", "No"], "money bag": ["Moneybags", "Rich"], "pound banknote": ["\u00a320 Note", "Pound Note", "Twenty Quid Note"], "euro banknote": ["\u20ac100 Note", "Euro"], "genie": ["Djinni", "Jinni"], "money with wings": ["Flying Money", "Losing Money"], "credit card": ["AMEX", "Diners Club", "Mastercard", "VISA Card"], "raised fist": ["Fist Pump"], "envelope": ["\u2709 Letter"], "envelope with arrow": ["Down Arrow Envelope", "Insert In Envelope"], "incoming envelope": ["Envelope With Lines", "Fast Envelope"], "e-mail": ["Email"], "chart increasing with yen": ["Yen Exchange Rate", "Yen Graph"], "outbox tray": ["Outbox"], "person getting massage": ["Head Massage", "Massaging"], "package": ["Box", "Parcel"], "inbox tray": ["Inbox"], "oncoming fist": ["Bro Fist / Brofist", "Fist Bump", "Punch"], "open mailbox with raised flag": ["Open Mailbox"], "ballot box with ballot": ["Vote Box", "Voting"], "left-facing fist": ["Left Fist Bump"], "pencil": ["\u270f Lead Pencil"], "black nib": ["\u2712 Pen Nib", "\u2712 Fountain Pen"], "paintbrush": ["Brush"], "right-facing fist": ["Right Fist Bump"], "memo": ["Memorandum", "Note", "Pencil And Paper"], "briefcase": ["Suitcase"], "person juggling": ["Juggler"], "clapping hands": ["Applause", "Clap", "Clapping", "Golf Clap", "Round Of Applause"], "calendar": ["July 17", "World Emoji Day"], "grinning face": ["Happy Face", "Smiley Face"], "file folder": ["Folder", "Manilla Folder"], "person getting haircut": ["Cutting Hair", "Hairdresser"], "tear-off calendar": ["Day Calendar", "Desk Calendar"], "open file folder": ["Open Folder"], "disappointed face": [":(", "Sad", "Sadface"], "persevering face": ["Helpless Face", "Scrunched Eyes"], "downcast face with sweat": ["Hard Work", "Sad Sweat Face"], "tired face": ["Exhausted", "Fed Up"], "face with steam from nose": ["Airing of Grievances", "Frustrated", "Mad Face", "Steaming"], "smiling face with horns": ["Devil", "Devil Horns", "Happy Devil", "Purple Devil", "Red Devil"], "face with symbols on mouth": ["Cursing", "Cussing", "Grawlix", "Swearing"], "old woman": ["Elderly Woman", "Grandma", "Nanna", "Old Lady"], "angry face with horns": ["Devil", "Devil Horns", "Purple Devil", "Purple Goblin", "Sad Devil"], "weary face": ["Distraught Face", "Wailing"], "old man": ["Elderly Man", "Grandpa", "Old Man"], "skull": ["Death", "Grey Skull", "Skeleton"], "angry face": ["Angry", "Grumpy Face"], "ghost": ["Disappear", "Ghoul", "Halloween"], "ogre": ["Mask Face", "Oni", "Red Monster"], "goblin": ["Long Nose Face", "Red Mask", "Tengu"], "grinning cat": ["Happy Cat", "Smiling Cat"], "grinning cat with smiling eyes": ["Grinning Cat", "Happy Cat"], "robot": ["Robot"], "smiling cat with heart-eyes": ["Heart Eyes Cat", "Loving Cat"], "cat with wry smile": ["Smirking Cat"], "pile of poo": ["Dog Dirt", "Smiling Poop"], "kissing cat": ["Kissing Cat"], "alien": ["Alien", "ET"], "love letter": ["Heart Envelope", "Love Note"], "person frowning": ["Sad Person", "Woman Frowning"], "heart with arrow": ["Cupid Arrow", "Lovestruck"], "alien monster": ["Space Invader", "Video Game Monster"], "cat with tears of joy": ["Happy Tears Cat", "Laughing Cat"], "person pouting": ["Blank Look", "Fed Up"], "heart with ribbon": ["Chocolate Box", "Gift Box", "Gift Heart"], "sparkling heart": ["Sparkle Heart", "Sparkly Heart", "Stars Heart"], "hear-no-evil monkey": ["Kikazaru", "Monkey Covering Ears"], "growing heart": ["Multiple Heart", "Triple Heart"], "revolving hearts": ["Two Hearts"], "heart exclamation": ["Heart Above Dot"], "two hearts": ["Small Hearts", "Two Pink Hearts"], "mending heart": ["Bandaged Heart", "Healing Heart", "Unbroken Heart"], "red heart": ["Heart", "Love Heart", "Red Heart"], "beating heart": ["Heart Alarm", "Heartbeat", "Wifi Heart"], "weary cat": ["Scared Cat", "Screaming Cat"], "green heart": ["NCT Heart"], "crying cat": ["Crying Cat", "Sad Cat"], "see-no-evil monkey": ["Mizaru", "Monkey Covering Eyes"], "pouting cat": ["Grumpy Cat"], "purple heart": ["BTS Emoji"], "speak-no-evil monkey": ["Iwazaru", "Monkey Covering Mouth", "No Speaking"], "black heart": ["Dark Heart"], "yellow heart": ["#1 BF Snapchat", "Gold Heart"], "hundred points": ["100", "Keep It 100", "Perfect Score"], "blue heart": ["Brand Heart", "Neutral Heart"], "broken heart": ["Breaking Heart", "Brokenhearted", "Heart Broken"], "dizzy": ["Circle And Star", "Dizzy"], "anger symbol": ["Anger Sign", "Vein Pop"], "collision": ["Bang", "Explode", "Impact", "Red Spark"], "speech balloon": ["Chat Bubble", "Speech Bubble"], "dashing away": ["Fast", "Steam", "Vaping", "Wind"], "eye in speech bubble": ["I Am A Witness"], "thought balloon": ["Thinking Bubble", "Thought Bubble"], "kiss mark": ["Kissing Lips"], "waving hand": ["Goodbye", "Hand Wave", "Hello", "Waving"], "right anger bubble": ["Zig Zag Bubble"], "sweat droplets": ["Plewds", "Splashing Water", "Water Drops"], "hand with fingers splayed": ["Five Hand", "Splayed Hand"], "person tipping hand": ["Bellhop", "Concierge", "Hair Flick", "Sassy Girl"], "raised hand": ["High Five", "Stop"], "person raising hand": ["Answering Question", "Hand Up"], "raised back of hand": ["Backhand"], "vulcan salute": ["Spock", "Star Trek", "Vulcan Salute"], "person bowing": ["Bowing Man", "Cute Boy", "Dogeza", "Massage"], "llama": ["Alpaca"], "rhinoceros": ["Rhino"], "hippopotamus": ["Hippo"], "mouse face": ["Mouse"], "mouse": ["Dormouse", "Mice", "Rodent"], "rabbit face": ["Easter Bunny"], "chipmunk": ["Squirrel"], "rat": ["Rodent"], "rabbit": ["Bunny", "Bunny Rabbit"], "bear": ["Teddy Bear"], "koala": ["Koala Bear"], "person with skullcap": ["Asian Man"], "kangaroo": ["Roo"], "person wearing turban": ["Arab", "Muslim", "Sikh", "Turban"], "bat": ["Batman"], "chicken": ["Hen"], "rooster": ["Cock", "Cockerel"], "baby chick": ["Yellow Bird"], "hamster": ["Hamster"], "eagle": ["Bald Eagle"], "person in tuxedo": ["Groom", "Man In Suit"], "paw prints": ["Cat Paw Prints", "Dog Paw Prints", "Kitten Paw Prints", "Puppy Paw Prints"], "turkey": ["Thanksgiving Turkey", "Wild Turkey"], "front-facing baby chick": ["Baby Chick"], "hatching chick": ["Baby Chicken", "Chick Hatching"], "crocodile": ["Alligator", "Croc"], "turtle": ["Tortoise"], "snake": ["Serpent"], "frog": ["Frog", "Toad"], "dragon face": ["Dragon Head"], "lizard": ["Gecko"], "tropical fish": ["Fish", "Yellow-Blue Fish"], "sauropod": ["Brachiosaurus", "Brontosaurus", "Dinosaur"], "fish": ["Freshwater Fish"], "spouting whale": ["Cute Whale"], "snail": ["Garden Snail", "Slug"], "blowfish": ["Fugu", "Pufferfish"], "ant": ["Bug", "Insect"], "honeybee": ["Bee", "Bumblebee"], "bug": ["Caterpillar", "Insect"], "shark": ["Great White Shark"], "lady beetle": ["Ladybird", "Ladybug", "Lady Bug"], "pregnant woman": ["Pregnancy", "Pregnant Lady"], "spiral shell": ["Beach", "Seashell", "Shell"], "cricket": ["Grasshopper"], "spider web": ["Cobweb", "Web"], "microbe": ["Cell", "Coronavirus", "COVID-19", "Germ", "Microorganism", "Virus"], "rose": ["Red Flower", "Red Rose"], "breast-feeding": ["Breastfeeding"], "bouquet": ["Bouquet Of Flowers"], "cherry blossom": ["Pink Flower", "Sakura"], "white flower": ["Cherry Blossom", "Paper Doily", "Well Done Stamp"], "wilted flower": ["Dead Flower", "Drooping Flower"], "blossom": ["Blossoming Flower", "Daisy", "Yellow Flower"], "potted plant": ["Houseplant"], "sunflower": ["Yellow Flower"], "deciduous tree": ["Rounded Tree"], "seedling": ["Spring", "Sprout", "Sprouting"], "sheaf of rice": ["Crop", "Farming", "Wheat"], "herb": ["Crop", "Plant"], "shamrock": ["Clover", "Trefoil"], "evergreen tree": ["Fir Tree", "Pine Tree", "Tree"], "fallen leaf": ["Autumn Leaves", "Brown Leaves", "Fall Leaves"], "cactus": ["Desert"], "baby angel": ["Angel", "Cherub", "Cupid", "Putto"], "mushroom": ["Shroom", "Toadstool"], "maple leaf": ["Canada", "Canadian", "Maple"], "palm tree": ["Coconut Tree"], "tangerine": ["Mandarin", "Orange"], "four leaf clover": ["Clover", "Ireland", "Lucky"], "banana": ["Plantain"], "leaf fluttering in wind": ["Green Leaves", "Spring"], "red apple": ["Red Delicious Apple"], "grapes": ["Grape"], "cherries": ["Cherry", "Wild Cherry"], "lemon": ["Lemonade"], "coconut": ["Cocoanut"], "green apple": ["Golden Delicious Apple", "Granny Smith Apple"], "peach": ["Bottom", "Butt"], "eggplant": ["Eggplant", "Phallic", "Purple Vegetable"], "potato": ["Baked Potato", "Idaho Potato"], "ear of corn": ["Corn", "Corn On The Cob", "Maize"], "melon": ["Cantaloupe", "Honeydew", "Muskmelon"], "kiwi fruit": ["Chinese Gooseberry", "Kiwi"], "hot pepper": ["Chili Pepper", "Spicy"], "cucumber": ["Gherkin", "Pickle"], "child": ["Gender Inclusive Child", "Gender Neutral Child"], "leafy green": ["Bok Choy", "Chinese Cabbage", "Cos Lettuce", "Romaine Lettuce"], "peanuts": ["Nuts"], "thermometer": ["Hot Weather", "Temperature"], "om": ["Aumkara", "Omkara", "Pranava"], "sun": ["Sun", "Sunshine"], "full moon face": ["Moonface", "Smiley Moon", "Smiling Moon"], "woman running": ["Boy Runner"], "sun with face": ["Smiley Sun", "Smiling Sun", "Sunface"], "ringed planet": ["Saturn"], "wheel of dharma": ["Helm"], "woman dancing": ["Red Dress Woman", "Salsa Dancer"], "peace symbol": ["Peace Sign"], "latin cross": ["Christian Cross"], "red square": ["Red Card"], "shooting star": ["Meteoroid", "When You Wish Upon A Star"], "star": ["Gold Star"], "yellow square": ["Yellow Card"], "menorah": ["Candelabrum", "Candles", "Chanukiah", "Menorah"], "glowing star": ["Shining Star"], "milky way": ["Galaxy", "Night Sky", "Space", "Stars", "Universe"], "cloud": ["Cloudy", "Overcast"], "man dancing": ["Disco Dancer", "Male Dancer"], "person": ["Gender Inclusive Adult", "Gender Neutral Adult", "Person"], "person in suit levitating": ["Hovering Man", "Rude Boy", "Walt Jabsco"], "man astronaut": ["Man Cosmonaut"], "rainbow": ["Gay Pride", "Primary Rainbow"], "wind face": ["Blowing Wind", "Mother Nature"], "cyclone": ["Hurricane", "Spiral", "Swirl", "Tornado"], "closed umbrella": ["Collapsed Umbrella", "Pink Umbrella"], "repeat button": ["Loop Symbol", "Retweet"], "diamond with a dot": ["Cuteness", "Diamond Flower", "Kawaii"], "woman astronaut": ["Woman Cosmonaut"], "play button": ["Play Button", "Right Triangle"], "umbrella": ["Umbrella"], "high voltage": ["Lightning Bolt", "Thunderbolt"], "repeat single button": ["Circle Arrows With Number 1", "Loop Once Symbol"], "next track button": ["Next Track"], "man": ["Male", "Moustache Man"], "people with bunny ears": ["Ballet", "Dancing Girls", "Let's Party", "Showgirls"], "snowman": ["Snowing Snowman"], "snowflake": ["Snow", "Snowing"], "umbrella with rain drops": ["Raining", "Rainy"], "snowman without snow": ["Frosty The Snowman", "Olaf", "Snowman"], "chequered flag": ["Checkered Flag", "Grid Girl", "Racing Flag"], "person in steamy room": ["Sauna"], "play or pause button": ["Play-Pause"], "fast-forward button": ["Fast Forward"], "fast reverse button": ["Rewind"], "reverse button": ["Left Triangle"], "triangular flag": ["Flag on Pole", "Red Flag"], "crossed flags": ["Two Flags"], "rainbow flag": ["Pride Flag"], "water wave": ["Beach", "Ocean Wave", "Sea", "Waves"], "last track button": ["Previous Track"], "pirate flag": ["Jolly Roger"], "fire": ["Flame", "Hot", "Lit", "Snapstreak"], "droplet": ["Water", "Water Drop"], "jack-o-lantern": ["Gourd", "Halloween", "Pumpkin"], "fireworks": ["Explosion"], "upwards button": ["Up Triangle"], "transgender flag": ["Blue, Pink, and White Flag", "Trans Flag"], "sparkler": ["Senko Hanabi"], "downwards button": ["Down Triangle"], "stop button": ["Stop"], "sparkles": ["Glitter", "Shiny"], "cinema": ["Cinema Screen", "Movies"], "pause button": ["Pause"], "party popper": ["Celebration", "Party Hat"], "dim button": ["Decrease Brightness"], "tanabata tree": ["Tanabata", "Wish Tree"], "firecracker": ["Dynamite"], "record button": ["Record"], "antenna bars": ["Reception Bars", "Signal Strength", "Stairs"], "vibration mode": ["Phone Heart", "Silent Mode"], "balloon": ["Party", "Red Balloon"], "carp streamer": ["Fish Flag", "Koinobori", "Wind Socks"], "bright button": ["Increase Brightness"], "wind chime": ["Furin", "Jellyfish", "Wind Bell"], "confetti ball": ["Confetti"], "police officer": ["Cop", "Police", "Policeman", "Policewoman"], "moon viewing ceremony": ["Grass, Dumplings and Moon", "Harvest Moon", "Mid-Autumn Festival", "Tsukimi"], "pine decoration": ["Bamboo", "Kadomatsu", "New Year Decoration"], "ribbon": ["Bow", "Pink Bow"], "person climbing": ["Climber", "Rock Climbing"], "male sign": ["Man Symbol", "Mars Symbol"], "transgender symbol": ["Transgender Sign"], "female sign": ["Venus Symbol", "Woman Symbol"], "wrapped gift": ["Birthday Present", "Christmas Present", "Gift", "Gift Box"], "red envelope": ["Ang Pao", "H\u00f3ngb\u0101o", "Lai See", "Red Packet"], "ticket": ["Ticket Stub", "World Tour TIcket"], "military medal": ["Medal", "Medallion", "Military Decoration"], "man climbing": ["Male Rock Climber", "Man Climber"], "trophy": ["Championship Trophy", "Winners Trophy"], "woman climbing": ["Female Rock Climber", "Woman Climber"], "2nd place medal": ["Silver Medal"], "infinity": ["Infinity"], "3rd place medal": ["Bronze Medal"], "soccer ball": ["Football", "Soccer"], "baseball": ["Softball"], "wavy dash": ["\u3030 Wave"], "basketball": ["Basketball", "Orange Ball"], "heavy dollar sign": ["Dollar", "Dollar Sign"], "horse racing": ["Horse Race", "Jockey"], "medical symbol": ["Aesculapius", "Asklepios", "Rod of Asclepius"], "recycling symbol": ["Recycle Logo"], "1st place medal": ["Gold Medal"], "detective": ["Detective", "Private Eye", "Sleuth", "Spy"], "rugby football": ["Football", "League", "Rugby", "Union"], "fleur-de-lis": ["New Orleans Saints", "Scouts"], "trident emblem": ["Pitchfork", "Trident"], "name badge": ["Fire Tag", "Name Tag", "Tofu On Fire"], "bowling": ["Bowling Ball", "Pins", "Skittles", "Ten Pin Bowling"], "cricket game": ["Cricket"], "hollow red circle": ["Circle", "Correct", "Red Circle"], "american football": ["Football", "Gridiron", "Superbowl"], "snowboarder": ["Snowboard", "Snowboarding"], "field hockey": ["Field Hockey", "Hockey"], "check box with check": ["Checkbox", "Check Mark In Box"], "tennis": ["Tennis", "Tennis Ball", "Tennis Racket", "Tennis Racquet"], "woman": ["Female", "Lady", "Yellow Woman"], "cross mark": ["Cross", "X"], "cross mark button": ["Cross", "X"], "check mark button": ["Green Check Mark", "Green Tick"], "ice hockey": ["Ice Hockey"], "check mark": ["Check", "Tick"], "ping pong": ["Ping Pong", "Table Tennis"], "martial arts uniform": ["Judo"], "curly loop": ["Curling Loop", "Loop"], "double curly loop": ["Double Curling Loop", "Voicemail"], "part alternation mark": ["M", "McDonald\u2019s"], "person golfing": ["Golf", "Golf Club"], "fishing pole": ["Fishing", "Fishing Rod"], "ice skate": ["Ice Skating"], "flag in hole": ["Golf", "Golf Flag"], "guard": ["British Guardsman", "Foot Guard"], "running shirt": ["Running Shirt", "Singlet"], "eight-pointed star": ["Orange Star"], "skis": ["Skiing", "Skis"], "trade mark": ["\u2122 TM", "\u2122 Trademark"], "yo-yo": ["Yoyo"], "crystal ball": ["Clairvoyant", "Fortune Teller", "Psychic", "Purple Crystal"], "pool 8 ball": ["8 Ball", "Cue Ball", "Magic 8 Ball", "Pool", "Snooker"], "video game": ["Gamepad", "Playstation", "Wii U", "Xbox"], "person surfing": ["Surf", "Surfing"], "game die": ["Dice"], "slot machine": ["Casino", "Fruit Machine", "Gambling", "Poker Machine"], "speaking head": ["Mansplaining", "Shout", "Shouting"], "busts in silhouette": ["Shadows", "Silhouettes", "Users"], "teddy bear": ["Toy"], "bust in silhouette": ["Shadow", "Silhouette", "User"], "input numbers": ["1234", "Numbers", "Numeric Input"], "input symbols": ["Symbols", "Symbol Input"], "input latin uppercase": ["ABCD", "Uppercase"], "monkey face": ["Monkey Head"], "nesting dolls": ["Matryoshka", "Russian Dolls"], "input latin lowercase": ["ABCD", "Lowercase"], "monkey": ["Cheeky Monkey"], "spade suit": ["Spades"], "heart suit": ["Card With Heart", "Hearts"], "mirror ball": ["Disco Ball"], "input latin letters": ["ABC", "Alphabet", "Letters"], "footprints": ["Feet", "Footsteps"], "dog face": ["Dog", "Puppy"], "club suit": ["Clubs"], "dog": ["Doggo"], "diamond suit": ["Diamonds"], "guide dog": ["Seeing Eye Dog"], "information": ["Info", "Lowercase I", "Tourist Information"], "joker": ["Joker", "Joker Card"], "poodle": ["Miniature Poodle", "Standard Poodle", "Toy Poodle"], "flower playing cards": ["Deck Of Cards", "Hanafuda", "Hwatu", "Playing Cards"], "construction worker": ["Builder", "Face With Hat", "Hard-Hat", "Safety Helmet"], "mahjong red dragon": ["Mahjong", "Mahjong Tile", "\u4e2d"], "performing arts": ["Drama Masks", "Greek Theatre Masks", "Theatre Logo", "Tragedy and Comedy Masks"], "fox": ["Fox"], "framed picture": ["Painting", "Picture Frame"], "artist palette": ["Art", "Painting"], "cat face": [":3", "Kitten", "Kitty"], "cat": ["Domestic Cat", "Feline", "Housecat"], "person rowing boat": ["Boat With Paddles", "Rowing"], "glasses": ["Glasses"], "tiger face": ["Cute Tiger"], "tiger": ["Bengal Tiger"], "leopard": ["African Leopard", "Jaguar"], "horse face": ["Horse Head"], "necktie": ["Business Shirt", "Shirt And Tie", "Tie"], "horse": ["Galloping Horse", "Racehorse"], "unicorn": ["Unicorn"], "jeans": ["Denim", "Pants", "Trousers"], "t-shirt": ["Polo Shirt", "Tee Shirt"], "deer": ["Buck", "Reindeer", "Stag"], "cow face": ["Cow", "Happy Cow"], "bison": ["buffalo"], "ox": ["Bull", "Bullock", "Oxen", "Steer"], "water buffalo": ["Buffalo", "Domestic Water Buffalo"], "person swimming": ["Swimming"], "pig face": ["Pig Head"], "dress": ["Gown", "Skirt"], "pig": ["Hog", "Sow"], "kimono": ["Dressing Gown", "Japanese Dress"], "sari": ["Saree", "Shari"], "cow": ["Dairy Cow"], "bikini": ["Bathers", "Swimsuit"], "pig nose": ["Pig Snout"], "ram": ["Sheep"], "ewe": ["Ewe", "Lamb"], "princess": ["Blonde Girl", "Girl With Crown", "Girl With Tiara"], "camel": ["Arabian Camel", "Dromedary Camel", "One-Bump Camel"], "purse": ["Wallet"], "two-hump camel": ["Asian Camel", "Bactrian Camel", "Two-Bump Camel"], "older person": ["Gender Neutral Older Adult"], "handbag": ["Women\u2019s Bag"], "boar": ["Warthog", "Wild Boar", "Wild Pig"], "men holding hands": ["Gay Couple"], "kiss": ["Couple Kissing", "Gender Neutral Couple Kissing"], "couple with heart": ["Couple In Love", "Gender Neutral Couple", "Loving Couple"]} \ No newline at end of file diff --git a/emoji/emoji-test.txt b/emoji/emoji-test.txt deleted file mode 100644 index 87d093d6..00000000 --- a/emoji/emoji-test.txt +++ /dev/null @@ -1,5024 +0,0 @@ -# emoji-test.txt -# Date: 2022-08-12, 20:24:39 GMT -# © 2022 Unicode®, Inc. -# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. -# For terms of use, see https://www.unicode.org/terms_of_use.html -# -# Emoji Keyboard/Display Test Data for UTS #51 -# Version: 15.0 -# -# For documentation and usage, see https://www.unicode.org/reports/tr51 -# -# This file provides data for testing which emoji forms should be in keyboards and which should also be displayed/processed. -# Format: code points; status # emoji name -# Code points — list of one or more hex code points, separated by spaces -# Status -# component — an Emoji_Component, -# excluding Regional_Indicators, ASCII, and non-Emoji. -# fully-qualified — a fully-qualified emoji (see ED-18 in UTS #51), -# excluding Emoji_Component -# minimally-qualified — a minimally-qualified emoji (see ED-18a in UTS #51) -# unqualified — a unqualified emoji (See ED-19 in UTS #51) -# Notes: -# • This includes the emoji components that need emoji presentation (skin tone and hair) -# when isolated, but omits the components that need not have an emoji -# presentation when isolated. -# • The RGI set is covered by the listed fully-qualified emoji. -# • The listed minimally-qualified and unqualified cover all cases where an -# element of the RGI set is missing one or more emoji presentation selectors. -# • The file is in CLDR order, not codepoint order. This is recommended (but not required!) for keyboard palettes. -# • The groups and subgroups are illustrative. See the Emoji Order chart for more information. - - -# group: Smileys & Emotion - -# subgroup: face-smiling -1F600 ; fully-qualified # 😀 E1.0 grinning face -1F603 ; fully-qualified # 😃 E0.6 grinning face with big eyes -1F604 ; fully-qualified # 😄 E0.6 grinning face with smiling eyes -1F601 ; fully-qualified # 😁 E0.6 beaming face with smiling eyes -1F606 ; fully-qualified # 😆 E0.6 grinning squinting face -1F605 ; fully-qualified # 😅 E0.6 grinning face with sweat -1F923 ; fully-qualified # 🤣 E3.0 rolling on the floor laughing -1F602 ; fully-qualified # 😂 E0.6 face with tears of joy -1F642 ; fully-qualified # 🙂 E1.0 slightly smiling face -1F643 ; fully-qualified # 🙃 E1.0 upside-down face -1FAE0 ; fully-qualified # 🫠 E14.0 melting face -1F609 ; fully-qualified # 😉 E0.6 winking face -1F60A ; fully-qualified # 😊 E0.6 smiling face with smiling eyes -1F607 ; fully-qualified # 😇 E1.0 smiling face with halo - -# subgroup: face-affection -1F970 ; fully-qualified # 🥰 E11.0 smiling face with hearts -1F60D ; fully-qualified # 😍 E0.6 smiling face with heart-eyes -1F929 ; fully-qualified # 🤩 E5.0 star-struck -1F618 ; fully-qualified # 😘 E0.6 face blowing a kiss -1F617 ; fully-qualified # 😗 E1.0 kissing face -263A FE0F ; fully-qualified # ☺️ E0.6 smiling face -263A ; unqualified # ☺ E0.6 smiling face -1F61A ; fully-qualified # 😚 E0.6 kissing face with closed eyes -1F619 ; fully-qualified # 😙 E1.0 kissing face with smiling eyes -1F972 ; fully-qualified # 🥲 E13.0 smiling face with tear - -# subgroup: face-tongue -1F60B ; fully-qualified # 😋 E0.6 face savoring food -1F61B ; fully-qualified # 😛 E1.0 face with tongue -1F61C ; fully-qualified # 😜 E0.6 winking face with tongue -1F92A ; fully-qualified # 🤪 E5.0 zany face -1F61D ; fully-qualified # 😝 E0.6 squinting face with tongue -1F911 ; fully-qualified # 🤑 E1.0 money-mouth face - -# subgroup: face-hand -1F917 ; fully-qualified # 🤗 E1.0 smiling face with open hands -1F92D ; fully-qualified # 🤭 E5.0 face with hand over mouth -1FAE2 ; fully-qualified # 🫢 E14.0 face with open eyes and hand over mouth -1FAE3 ; fully-qualified # 🫣 E14.0 face with peeking eye -1F92B ; fully-qualified # 🤫 E5.0 shushing face -1F914 ; fully-qualified # 🤔 E1.0 thinking face -1FAE1 ; fully-qualified # 🫡 E14.0 saluting face - -# subgroup: face-neutral-skeptical -1F910 ; fully-qualified # 🤐 E1.0 zipper-mouth face -1F928 ; fully-qualified # 🤨 E5.0 face with raised eyebrow -1F610 ; fully-qualified # 😐 E0.7 neutral face -1F611 ; fully-qualified # 😑 E1.0 expressionless face -1F636 ; fully-qualified # 😶 E1.0 face without mouth -1FAE5 ; fully-qualified # 🫥 E14.0 dotted line face -1F636 200D 1F32B FE0F ; fully-qualified # 😶‍🌫️ E13.1 face in clouds -1F636 200D 1F32B ; minimally-qualified # 😶‍🌫 E13.1 face in clouds -1F60F ; fully-qualified # 😏 E0.6 smirking face -1F612 ; fully-qualified # 😒 E0.6 unamused face -1F644 ; fully-qualified # 🙄 E1.0 face with rolling eyes -1F62C ; fully-qualified # 😬 E1.0 grimacing face -1F62E 200D 1F4A8 ; fully-qualified # 😮‍💨 E13.1 face exhaling -1F925 ; fully-qualified # 🤥 E3.0 lying face -1FAE8 ; fully-qualified # 🫨 E15.0 shaking face - -# subgroup: face-sleepy -1F60C ; fully-qualified # 😌 E0.6 relieved face -1F614 ; fully-qualified # 😔 E0.6 pensive face -1F62A ; fully-qualified # 😪 E0.6 sleepy face -1F924 ; fully-qualified # 🤤 E3.0 drooling face -1F634 ; fully-qualified # 😴 E1.0 sleeping face - -# subgroup: face-unwell -1F637 ; fully-qualified # 😷 E0.6 face with medical mask -1F912 ; fully-qualified # 🤒 E1.0 face with thermometer -1F915 ; fully-qualified # 🤕 E1.0 face with head-bandage -1F922 ; fully-qualified # 🤢 E3.0 nauseated face -1F92E ; fully-qualified # 🤮 E5.0 face vomiting -1F927 ; fully-qualified # 🤧 E3.0 sneezing face -1F975 ; fully-qualified # 🥵 E11.0 hot face -1F976 ; fully-qualified # 🥶 E11.0 cold face -1F974 ; fully-qualified # 🥴 E11.0 woozy face -1F635 ; fully-qualified # 😵 E0.6 face with crossed-out eyes -1F635 200D 1F4AB ; fully-qualified # 😵‍💫 E13.1 face with spiral eyes -1F92F ; fully-qualified # 🤯 E5.0 exploding head - -# subgroup: face-hat -1F920 ; fully-qualified # 🤠 E3.0 cowboy hat face -1F973 ; fully-qualified # 🥳 E11.0 partying face -1F978 ; fully-qualified # 🥸 E13.0 disguised face - -# subgroup: face-glasses -1F60E ; fully-qualified # 😎 E1.0 smiling face with sunglasses -1F913 ; fully-qualified # 🤓 E1.0 nerd face -1F9D0 ; fully-qualified # 🧐 E5.0 face with monocle - -# subgroup: face-concerned -1F615 ; fully-qualified # 😕 E1.0 confused face -1FAE4 ; fully-qualified # 🫤 E14.0 face with diagonal mouth -1F61F ; fully-qualified # 😟 E1.0 worried face -1F641 ; fully-qualified # 🙁 E1.0 slightly frowning face -2639 FE0F ; fully-qualified # ☹️ E0.7 frowning face -2639 ; unqualified # ☹ E0.7 frowning face -1F62E ; fully-qualified # 😮 E1.0 face with open mouth -1F62F ; fully-qualified # 😯 E1.0 hushed face -1F632 ; fully-qualified # 😲 E0.6 astonished face -1F633 ; fully-qualified # 😳 E0.6 flushed face -1F97A ; fully-qualified # 🥺 E11.0 pleading face -1F979 ; fully-qualified # 🥹 E14.0 face holding back tears -1F626 ; fully-qualified # 😦 E1.0 frowning face with open mouth -1F627 ; fully-qualified # 😧 E1.0 anguished face -1F628 ; fully-qualified # 😨 E0.6 fearful face -1F630 ; fully-qualified # 😰 E0.6 anxious face with sweat -1F625 ; fully-qualified # 😥 E0.6 sad but relieved face -1F622 ; fully-qualified # 😢 E0.6 crying face -1F62D ; fully-qualified # 😭 E0.6 loudly crying face -1F631 ; fully-qualified # 😱 E0.6 face screaming in fear -1F616 ; fully-qualified # 😖 E0.6 confounded face -1F623 ; fully-qualified # 😣 E0.6 persevering face -1F61E ; fully-qualified # 😞 E0.6 disappointed face -1F613 ; fully-qualified # 😓 E0.6 downcast face with sweat -1F629 ; fully-qualified # 😩 E0.6 weary face -1F62B ; fully-qualified # 😫 E0.6 tired face -1F971 ; fully-qualified # 🥱 E12.0 yawning face - -# subgroup: face-negative -1F624 ; fully-qualified # 😤 E0.6 face with steam from nose -1F621 ; fully-qualified # 😡 E0.6 enraged face -1F620 ; fully-qualified # 😠 E0.6 angry face -1F92C ; fully-qualified # 🤬 E5.0 face with symbols on mouth -1F608 ; fully-qualified # 😈 E1.0 smiling face with horns -1F47F ; fully-qualified # 👿 E0.6 angry face with horns -1F480 ; fully-qualified # 💀 E0.6 skull -2620 FE0F ; fully-qualified # ☠️ E1.0 skull and crossbones -2620 ; unqualified # ☠ E1.0 skull and crossbones - -# subgroup: face-costume -1F4A9 ; fully-qualified # 💩 E0.6 pile of poo -1F921 ; fully-qualified # 🤡 E3.0 clown face -1F479 ; fully-qualified # 👹 E0.6 ogre -1F47A ; fully-qualified # 👺 E0.6 goblin -1F47B ; fully-qualified # 👻 E0.6 ghost -1F47D ; fully-qualified # 👽 E0.6 alien -1F47E ; fully-qualified # 👾 E0.6 alien monster -1F916 ; fully-qualified # 🤖 E1.0 robot - -# subgroup: cat-face -1F63A ; fully-qualified # 😺 E0.6 grinning cat -1F638 ; fully-qualified # 😸 E0.6 grinning cat with smiling eyes -1F639 ; fully-qualified # 😹 E0.6 cat with tears of joy -1F63B ; fully-qualified # 😻 E0.6 smiling cat with heart-eyes -1F63C ; fully-qualified # 😼 E0.6 cat with wry smile -1F63D ; fully-qualified # 😽 E0.6 kissing cat -1F640 ; fully-qualified # 🙀 E0.6 weary cat -1F63F ; fully-qualified # 😿 E0.6 crying cat -1F63E ; fully-qualified # 😾 E0.6 pouting cat - -# subgroup: monkey-face -1F648 ; fully-qualified # 🙈 E0.6 see-no-evil monkey -1F649 ; fully-qualified # 🙉 E0.6 hear-no-evil monkey -1F64A ; fully-qualified # 🙊 E0.6 speak-no-evil monkey - -# subgroup: heart -1F48C ; fully-qualified # 💌 E0.6 love letter -1F498 ; fully-qualified # 💘 E0.6 heart with arrow -1F49D ; fully-qualified # 💝 E0.6 heart with ribbon -1F496 ; fully-qualified # 💖 E0.6 sparkling heart -1F497 ; fully-qualified # 💗 E0.6 growing heart -1F493 ; fully-qualified # 💓 E0.6 beating heart -1F49E ; fully-qualified # 💞 E0.6 revolving hearts -1F495 ; fully-qualified # 💕 E0.6 two hearts -1F49F ; fully-qualified # 💟 E0.6 heart decoration -2763 FE0F ; fully-qualified # ❣️ E1.0 heart exclamation -2763 ; unqualified # ❣ E1.0 heart exclamation -1F494 ; fully-qualified # 💔 E0.6 broken heart -2764 FE0F 200D 1F525 ; fully-qualified # ❤️‍🔥 E13.1 heart on fire -2764 200D 1F525 ; unqualified # ❤‍🔥 E13.1 heart on fire -2764 FE0F 200D 1FA79 ; fully-qualified # ❤️‍🩹 E13.1 mending heart -2764 200D 1FA79 ; unqualified # ❤‍🩹 E13.1 mending heart -2764 FE0F ; fully-qualified # ❤️ E0.6 red heart -2764 ; unqualified # ❤ E0.6 red heart -1FA77 ; fully-qualified # 🩷 E15.0 pink heart -1F9E1 ; fully-qualified # 🧡 E5.0 orange heart -1F49B ; fully-qualified # 💛 E0.6 yellow heart -1F49A ; fully-qualified # 💚 E0.6 green heart -1F499 ; fully-qualified # 💙 E0.6 blue heart -1FA75 ; fully-qualified # 🩵 E15.0 light blue heart -1F49C ; fully-qualified # 💜 E0.6 purple heart -1F90E ; fully-qualified # 🤎 E12.0 brown heart -1F5A4 ; fully-qualified # 🖤 E3.0 black heart -1FA76 ; fully-qualified # 🩶 E15.0 grey heart -1F90D ; fully-qualified # 🤍 E12.0 white heart - -# subgroup: emotion -1F48B ; fully-qualified # 💋 E0.6 kiss mark -1F4AF ; fully-qualified # 💯 E0.6 hundred points -1F4A2 ; fully-qualified # 💢 E0.6 anger symbol -1F4A5 ; fully-qualified # 💥 E0.6 collision -1F4AB ; fully-qualified # 💫 E0.6 dizzy -1F4A6 ; fully-qualified # 💦 E0.6 sweat droplets -1F4A8 ; fully-qualified # 💨 E0.6 dashing away -1F573 FE0F ; fully-qualified # 🕳️ E0.7 hole -1F573 ; unqualified # 🕳 E0.7 hole -1F4AC ; fully-qualified # 💬 E0.6 speech balloon -1F441 FE0F 200D 1F5E8 FE0F ; fully-qualified # 👁️‍🗨️ E2.0 eye in speech bubble -1F441 200D 1F5E8 FE0F ; unqualified # 👁‍🗨️ E2.0 eye in speech bubble -1F441 FE0F 200D 1F5E8 ; minimally-qualified # 👁️‍🗨 E2.0 eye in speech bubble -1F441 200D 1F5E8 ; unqualified # 👁‍🗨 E2.0 eye in speech bubble -1F5E8 FE0F ; fully-qualified # 🗨️ E2.0 left speech bubble -1F5E8 ; unqualified # 🗨 E2.0 left speech bubble -1F5EF FE0F ; fully-qualified # 🗯️ E0.7 right anger bubble -1F5EF ; unqualified # 🗯 E0.7 right anger bubble -1F4AD ; fully-qualified # 💭 E1.0 thought balloon -1F4A4 ; fully-qualified # 💤 E0.6 ZZZ - -# Smileys & Emotion subtotal: 180 -# Smileys & Emotion subtotal: 180 w/o modifiers - -# group: People & Body - -# subgroup: hand-fingers-open -1F44B ; fully-qualified # 👋 E0.6 waving hand -1F44B 1F3FB ; fully-qualified # 👋🏻 E1.0 waving hand: light skin tone -1F44B 1F3FC ; fully-qualified # 👋🏼 E1.0 waving hand: medium-light skin tone -1F44B 1F3FD ; fully-qualified # 👋🏽 E1.0 waving hand: medium skin tone -1F44B 1F3FE ; fully-qualified # 👋🏾 E1.0 waving hand: medium-dark skin tone -1F44B 1F3FF ; fully-qualified # 👋🏿 E1.0 waving hand: dark skin tone -1F91A ; fully-qualified # 🤚 E3.0 raised back of hand -1F91A 1F3FB ; fully-qualified # 🤚🏻 E3.0 raised back of hand: light skin tone -1F91A 1F3FC ; fully-qualified # 🤚🏼 E3.0 raised back of hand: medium-light skin tone -1F91A 1F3FD ; fully-qualified # 🤚🏽 E3.0 raised back of hand: medium skin tone -1F91A 1F3FE ; fully-qualified # 🤚🏾 E3.0 raised back of hand: medium-dark skin tone -1F91A 1F3FF ; fully-qualified # 🤚🏿 E3.0 raised back of hand: dark skin tone -1F590 FE0F ; fully-qualified # 🖐️ E0.7 hand with fingers splayed -1F590 ; unqualified # 🖐 E0.7 hand with fingers splayed -1F590 1F3FB ; fully-qualified # 🖐🏻 E1.0 hand with fingers splayed: light skin tone -1F590 1F3FC ; fully-qualified # 🖐🏼 E1.0 hand with fingers splayed: medium-light skin tone -1F590 1F3FD ; fully-qualified # 🖐🏽 E1.0 hand with fingers splayed: medium skin tone -1F590 1F3FE ; fully-qualified # 🖐🏾 E1.0 hand with fingers splayed: medium-dark skin tone -1F590 1F3FF ; fully-qualified # 🖐🏿 E1.0 hand with fingers splayed: dark skin tone -270B ; fully-qualified # ✋ E0.6 raised hand -270B 1F3FB ; fully-qualified # ✋🏻 E1.0 raised hand: light skin tone -270B 1F3FC ; fully-qualified # ✋🏼 E1.0 raised hand: medium-light skin tone -270B 1F3FD ; fully-qualified # ✋🏽 E1.0 raised hand: medium skin tone -270B 1F3FE ; fully-qualified # ✋🏾 E1.0 raised hand: medium-dark skin tone -270B 1F3FF ; fully-qualified # ✋🏿 E1.0 raised hand: dark skin tone -1F596 ; fully-qualified # 🖖 E1.0 vulcan salute -1F596 1F3FB ; fully-qualified # 🖖🏻 E1.0 vulcan salute: light skin tone -1F596 1F3FC ; fully-qualified # 🖖🏼 E1.0 vulcan salute: medium-light skin tone -1F596 1F3FD ; fully-qualified # 🖖🏽 E1.0 vulcan salute: medium skin tone -1F596 1F3FE ; fully-qualified # 🖖🏾 E1.0 vulcan salute: medium-dark skin tone -1F596 1F3FF ; fully-qualified # 🖖🏿 E1.0 vulcan salute: dark skin tone -1FAF1 ; fully-qualified # 🫱 E14.0 rightwards hand -1FAF1 1F3FB ; fully-qualified # 🫱🏻 E14.0 rightwards hand: light skin tone -1FAF1 1F3FC ; fully-qualified # 🫱🏼 E14.0 rightwards hand: medium-light skin tone -1FAF1 1F3FD ; fully-qualified # 🫱🏽 E14.0 rightwards hand: medium skin tone -1FAF1 1F3FE ; fully-qualified # 🫱🏾 E14.0 rightwards hand: medium-dark skin tone -1FAF1 1F3FF ; fully-qualified # 🫱🏿 E14.0 rightwards hand: dark skin tone -1FAF2 ; fully-qualified # 🫲 E14.0 leftwards hand -1FAF2 1F3FB ; fully-qualified # 🫲🏻 E14.0 leftwards hand: light skin tone -1FAF2 1F3FC ; fully-qualified # 🫲🏼 E14.0 leftwards hand: medium-light skin tone -1FAF2 1F3FD ; fully-qualified # 🫲🏽 E14.0 leftwards hand: medium skin tone -1FAF2 1F3FE ; fully-qualified # 🫲🏾 E14.0 leftwards hand: medium-dark skin tone -1FAF2 1F3FF ; fully-qualified # 🫲🏿 E14.0 leftwards hand: dark skin tone -1FAF3 ; fully-qualified # 🫳 E14.0 palm down hand -1FAF3 1F3FB ; fully-qualified # 🫳🏻 E14.0 palm down hand: light skin tone -1FAF3 1F3FC ; fully-qualified # 🫳🏼 E14.0 palm down hand: medium-light skin tone -1FAF3 1F3FD ; fully-qualified # 🫳🏽 E14.0 palm down hand: medium skin tone -1FAF3 1F3FE ; fully-qualified # 🫳🏾 E14.0 palm down hand: medium-dark skin tone -1FAF3 1F3FF ; fully-qualified # 🫳🏿 E14.0 palm down hand: dark skin tone -1FAF4 ; fully-qualified # 🫴 E14.0 palm up hand -1FAF4 1F3FB ; fully-qualified # 🫴🏻 E14.0 palm up hand: light skin tone -1FAF4 1F3FC ; fully-qualified # 🫴🏼 E14.0 palm up hand: medium-light skin tone -1FAF4 1F3FD ; fully-qualified # 🫴🏽 E14.0 palm up hand: medium skin tone -1FAF4 1F3FE ; fully-qualified # 🫴🏾 E14.0 palm up hand: medium-dark skin tone -1FAF4 1F3FF ; fully-qualified # 🫴🏿 E14.0 palm up hand: dark skin tone -1FAF7 ; fully-qualified # 🫷 E15.0 leftwards pushing hand -1FAF7 1F3FB ; fully-qualified # 🫷🏻 E15.0 leftwards pushing hand: light skin tone -1FAF7 1F3FC ; fully-qualified # 🫷🏼 E15.0 leftwards pushing hand: medium-light skin tone -1FAF7 1F3FD ; fully-qualified # 🫷🏽 E15.0 leftwards pushing hand: medium skin tone -1FAF7 1F3FE ; fully-qualified # 🫷🏾 E15.0 leftwards pushing hand: medium-dark skin tone -1FAF7 1F3FF ; fully-qualified # 🫷🏿 E15.0 leftwards pushing hand: dark skin tone -1FAF8 ; fully-qualified # 🫸 E15.0 rightwards pushing hand -1FAF8 1F3FB ; fully-qualified # 🫸🏻 E15.0 rightwards pushing hand: light skin tone -1FAF8 1F3FC ; fully-qualified # 🫸🏼 E15.0 rightwards pushing hand: medium-light skin tone -1FAF8 1F3FD ; fully-qualified # 🫸🏽 E15.0 rightwards pushing hand: medium skin tone -1FAF8 1F3FE ; fully-qualified # 🫸🏾 E15.0 rightwards pushing hand: medium-dark skin tone -1FAF8 1F3FF ; fully-qualified # 🫸🏿 E15.0 rightwards pushing hand: dark skin tone - -# subgroup: hand-fingers-partial -1F44C ; fully-qualified # 👌 E0.6 OK hand -1F44C 1F3FB ; fully-qualified # 👌🏻 E1.0 OK hand: light skin tone -1F44C 1F3FC ; fully-qualified # 👌🏼 E1.0 OK hand: medium-light skin tone -1F44C 1F3FD ; fully-qualified # 👌🏽 E1.0 OK hand: medium skin tone -1F44C 1F3FE ; fully-qualified # 👌🏾 E1.0 OK hand: medium-dark skin tone -1F44C 1F3FF ; fully-qualified # 👌🏿 E1.0 OK hand: dark skin tone -1F90C ; fully-qualified # 🤌 E13.0 pinched fingers -1F90C 1F3FB ; fully-qualified # 🤌🏻 E13.0 pinched fingers: light skin tone -1F90C 1F3FC ; fully-qualified # 🤌🏼 E13.0 pinched fingers: medium-light skin tone -1F90C 1F3FD ; fully-qualified # 🤌🏽 E13.0 pinched fingers: medium skin tone -1F90C 1F3FE ; fully-qualified # 🤌🏾 E13.0 pinched fingers: medium-dark skin tone -1F90C 1F3FF ; fully-qualified # 🤌🏿 E13.0 pinched fingers: dark skin tone -1F90F ; fully-qualified # 🤏 E12.0 pinching hand -1F90F 1F3FB ; fully-qualified # 🤏🏻 E12.0 pinching hand: light skin tone -1F90F 1F3FC ; fully-qualified # 🤏🏼 E12.0 pinching hand: medium-light skin tone -1F90F 1F3FD ; fully-qualified # 🤏🏽 E12.0 pinching hand: medium skin tone -1F90F 1F3FE ; fully-qualified # 🤏🏾 E12.0 pinching hand: medium-dark skin tone -1F90F 1F3FF ; fully-qualified # 🤏🏿 E12.0 pinching hand: dark skin tone -270C FE0F ; fully-qualified # ✌️ E0.6 victory hand -270C ; unqualified # ✌ E0.6 victory hand -270C 1F3FB ; fully-qualified # ✌🏻 E1.0 victory hand: light skin tone -270C 1F3FC ; fully-qualified # ✌🏼 E1.0 victory hand: medium-light skin tone -270C 1F3FD ; fully-qualified # ✌🏽 E1.0 victory hand: medium skin tone -270C 1F3FE ; fully-qualified # ✌🏾 E1.0 victory hand: medium-dark skin tone -270C 1F3FF ; fully-qualified # ✌🏿 E1.0 victory hand: dark skin tone -1F91E ; fully-qualified # 🤞 E3.0 crossed fingers -1F91E 1F3FB ; fully-qualified # 🤞🏻 E3.0 crossed fingers: light skin tone -1F91E 1F3FC ; fully-qualified # 🤞🏼 E3.0 crossed fingers: medium-light skin tone -1F91E 1F3FD ; fully-qualified # 🤞🏽 E3.0 crossed fingers: medium skin tone -1F91E 1F3FE ; fully-qualified # 🤞🏾 E3.0 crossed fingers: medium-dark skin tone -1F91E 1F3FF ; fully-qualified # 🤞🏿 E3.0 crossed fingers: dark skin tone -1FAF0 ; fully-qualified # 🫰 E14.0 hand with index finger and thumb crossed -1FAF0 1F3FB ; fully-qualified # 🫰🏻 E14.0 hand with index finger and thumb crossed: light skin tone -1FAF0 1F3FC ; fully-qualified # 🫰🏼 E14.0 hand with index finger and thumb crossed: medium-light skin tone -1FAF0 1F3FD ; fully-qualified # 🫰🏽 E14.0 hand with index finger and thumb crossed: medium skin tone -1FAF0 1F3FE ; fully-qualified # 🫰🏾 E14.0 hand with index finger and thumb crossed: medium-dark skin tone -1FAF0 1F3FF ; fully-qualified # 🫰🏿 E14.0 hand with index finger and thumb crossed: dark skin tone -1F91F ; fully-qualified # 🤟 E5.0 love-you gesture -1F91F 1F3FB ; fully-qualified # 🤟🏻 E5.0 love-you gesture: light skin tone -1F91F 1F3FC ; fully-qualified # 🤟🏼 E5.0 love-you gesture: medium-light skin tone -1F91F 1F3FD ; fully-qualified # 🤟🏽 E5.0 love-you gesture: medium skin tone -1F91F 1F3FE ; fully-qualified # 🤟🏾 E5.0 love-you gesture: medium-dark skin tone -1F91F 1F3FF ; fully-qualified # 🤟🏿 E5.0 love-you gesture: dark skin tone -1F918 ; fully-qualified # 🤘 E1.0 sign of the horns -1F918 1F3FB ; fully-qualified # 🤘🏻 E1.0 sign of the horns: light skin tone -1F918 1F3FC ; fully-qualified # 🤘🏼 E1.0 sign of the horns: medium-light skin tone -1F918 1F3FD ; fully-qualified # 🤘🏽 E1.0 sign of the horns: medium skin tone -1F918 1F3FE ; fully-qualified # 🤘🏾 E1.0 sign of the horns: medium-dark skin tone -1F918 1F3FF ; fully-qualified # 🤘🏿 E1.0 sign of the horns: dark skin tone -1F919 ; fully-qualified # 🤙 E3.0 call me hand -1F919 1F3FB ; fully-qualified # 🤙🏻 E3.0 call me hand: light skin tone -1F919 1F3FC ; fully-qualified # 🤙🏼 E3.0 call me hand: medium-light skin tone -1F919 1F3FD ; fully-qualified # 🤙🏽 E3.0 call me hand: medium skin tone -1F919 1F3FE ; fully-qualified # 🤙🏾 E3.0 call me hand: medium-dark skin tone -1F919 1F3FF ; fully-qualified # 🤙🏿 E3.0 call me hand: dark skin tone - -# subgroup: hand-single-finger -1F448 ; fully-qualified # 👈 E0.6 backhand index pointing left -1F448 1F3FB ; fully-qualified # 👈🏻 E1.0 backhand index pointing left: light skin tone -1F448 1F3FC ; fully-qualified # 👈🏼 E1.0 backhand index pointing left: medium-light skin tone -1F448 1F3FD ; fully-qualified # 👈🏽 E1.0 backhand index pointing left: medium skin tone -1F448 1F3FE ; fully-qualified # 👈🏾 E1.0 backhand index pointing left: medium-dark skin tone -1F448 1F3FF ; fully-qualified # 👈🏿 E1.0 backhand index pointing left: dark skin tone -1F449 ; fully-qualified # 👉 E0.6 backhand index pointing right -1F449 1F3FB ; fully-qualified # 👉🏻 E1.0 backhand index pointing right: light skin tone -1F449 1F3FC ; fully-qualified # 👉🏼 E1.0 backhand index pointing right: medium-light skin tone -1F449 1F3FD ; fully-qualified # 👉🏽 E1.0 backhand index pointing right: medium skin tone -1F449 1F3FE ; fully-qualified # 👉🏾 E1.0 backhand index pointing right: medium-dark skin tone -1F449 1F3FF ; fully-qualified # 👉🏿 E1.0 backhand index pointing right: dark skin tone -1F446 ; fully-qualified # 👆 E0.6 backhand index pointing up -1F446 1F3FB ; fully-qualified # 👆🏻 E1.0 backhand index pointing up: light skin tone -1F446 1F3FC ; fully-qualified # 👆🏼 E1.0 backhand index pointing up: medium-light skin tone -1F446 1F3FD ; fully-qualified # 👆🏽 E1.0 backhand index pointing up: medium skin tone -1F446 1F3FE ; fully-qualified # 👆🏾 E1.0 backhand index pointing up: medium-dark skin tone -1F446 1F3FF ; fully-qualified # 👆🏿 E1.0 backhand index pointing up: dark skin tone -1F595 ; fully-qualified # 🖕 E1.0 middle finger -1F595 1F3FB ; fully-qualified # 🖕🏻 E1.0 middle finger: light skin tone -1F595 1F3FC ; fully-qualified # 🖕🏼 E1.0 middle finger: medium-light skin tone -1F595 1F3FD ; fully-qualified # 🖕🏽 E1.0 middle finger: medium skin tone -1F595 1F3FE ; fully-qualified # 🖕🏾 E1.0 middle finger: medium-dark skin tone -1F595 1F3FF ; fully-qualified # 🖕🏿 E1.0 middle finger: dark skin tone -1F447 ; fully-qualified # 👇 E0.6 backhand index pointing down -1F447 1F3FB ; fully-qualified # 👇🏻 E1.0 backhand index pointing down: light skin tone -1F447 1F3FC ; fully-qualified # 👇🏼 E1.0 backhand index pointing down: medium-light skin tone -1F447 1F3FD ; fully-qualified # 👇🏽 E1.0 backhand index pointing down: medium skin tone -1F447 1F3FE ; fully-qualified # 👇🏾 E1.0 backhand index pointing down: medium-dark skin tone -1F447 1F3FF ; fully-qualified # 👇🏿 E1.0 backhand index pointing down: dark skin tone -261D FE0F ; fully-qualified # ☝️ E0.6 index pointing up -261D ; unqualified # ☝ E0.6 index pointing up -261D 1F3FB ; fully-qualified # ☝🏻 E1.0 index pointing up: light skin tone -261D 1F3FC ; fully-qualified # ☝🏼 E1.0 index pointing up: medium-light skin tone -261D 1F3FD ; fully-qualified # ☝🏽 E1.0 index pointing up: medium skin tone -261D 1F3FE ; fully-qualified # ☝🏾 E1.0 index pointing up: medium-dark skin tone -261D 1F3FF ; fully-qualified # ☝🏿 E1.0 index pointing up: dark skin tone -1FAF5 ; fully-qualified # 🫵 E14.0 index pointing at the viewer -1FAF5 1F3FB ; fully-qualified # 🫵🏻 E14.0 index pointing at the viewer: light skin tone -1FAF5 1F3FC ; fully-qualified # 🫵🏼 E14.0 index pointing at the viewer: medium-light skin tone -1FAF5 1F3FD ; fully-qualified # 🫵🏽 E14.0 index pointing at the viewer: medium skin tone -1FAF5 1F3FE ; fully-qualified # 🫵🏾 E14.0 index pointing at the viewer: medium-dark skin tone -1FAF5 1F3FF ; fully-qualified # 🫵🏿 E14.0 index pointing at the viewer: dark skin tone - -# subgroup: hand-fingers-closed -1F44D ; fully-qualified # 👍 E0.6 thumbs up -1F44D 1F3FB ; fully-qualified # 👍🏻 E1.0 thumbs up: light skin tone -1F44D 1F3FC ; fully-qualified # 👍🏼 E1.0 thumbs up: medium-light skin tone -1F44D 1F3FD ; fully-qualified # 👍🏽 E1.0 thumbs up: medium skin tone -1F44D 1F3FE ; fully-qualified # 👍🏾 E1.0 thumbs up: medium-dark skin tone -1F44D 1F3FF ; fully-qualified # 👍🏿 E1.0 thumbs up: dark skin tone -1F44E ; fully-qualified # 👎 E0.6 thumbs down -1F44E 1F3FB ; fully-qualified # 👎🏻 E1.0 thumbs down: light skin tone -1F44E 1F3FC ; fully-qualified # 👎🏼 E1.0 thumbs down: medium-light skin tone -1F44E 1F3FD ; fully-qualified # 👎🏽 E1.0 thumbs down: medium skin tone -1F44E 1F3FE ; fully-qualified # 👎🏾 E1.0 thumbs down: medium-dark skin tone -1F44E 1F3FF ; fully-qualified # 👎🏿 E1.0 thumbs down: dark skin tone -270A ; fully-qualified # ✊ E0.6 raised fist -270A 1F3FB ; fully-qualified # ✊🏻 E1.0 raised fist: light skin tone -270A 1F3FC ; fully-qualified # ✊🏼 E1.0 raised fist: medium-light skin tone -270A 1F3FD ; fully-qualified # ✊🏽 E1.0 raised fist: medium skin tone -270A 1F3FE ; fully-qualified # ✊🏾 E1.0 raised fist: medium-dark skin tone -270A 1F3FF ; fully-qualified # ✊🏿 E1.0 raised fist: dark skin tone -1F44A ; fully-qualified # 👊 E0.6 oncoming fist -1F44A 1F3FB ; fully-qualified # 👊🏻 E1.0 oncoming fist: light skin tone -1F44A 1F3FC ; fully-qualified # 👊🏼 E1.0 oncoming fist: medium-light skin tone -1F44A 1F3FD ; fully-qualified # 👊🏽 E1.0 oncoming fist: medium skin tone -1F44A 1F3FE ; fully-qualified # 👊🏾 E1.0 oncoming fist: medium-dark skin tone -1F44A 1F3FF ; fully-qualified # 👊🏿 E1.0 oncoming fist: dark skin tone -1F91B ; fully-qualified # 🤛 E3.0 left-facing fist -1F91B 1F3FB ; fully-qualified # 🤛🏻 E3.0 left-facing fist: light skin tone -1F91B 1F3FC ; fully-qualified # 🤛🏼 E3.0 left-facing fist: medium-light skin tone -1F91B 1F3FD ; fully-qualified # 🤛🏽 E3.0 left-facing fist: medium skin tone -1F91B 1F3FE ; fully-qualified # 🤛🏾 E3.0 left-facing fist: medium-dark skin tone -1F91B 1F3FF ; fully-qualified # 🤛🏿 E3.0 left-facing fist: dark skin tone -1F91C ; fully-qualified # 🤜 E3.0 right-facing fist -1F91C 1F3FB ; fully-qualified # 🤜🏻 E3.0 right-facing fist: light skin tone -1F91C 1F3FC ; fully-qualified # 🤜🏼 E3.0 right-facing fist: medium-light skin tone -1F91C 1F3FD ; fully-qualified # 🤜🏽 E3.0 right-facing fist: medium skin tone -1F91C 1F3FE ; fully-qualified # 🤜🏾 E3.0 right-facing fist: medium-dark skin tone -1F91C 1F3FF ; fully-qualified # 🤜🏿 E3.0 right-facing fist: dark skin tone - -# subgroup: hands -1F44F ; fully-qualified # 👏 E0.6 clapping hands -1F44F 1F3FB ; fully-qualified # 👏🏻 E1.0 clapping hands: light skin tone -1F44F 1F3FC ; fully-qualified # 👏🏼 E1.0 clapping hands: medium-light skin tone -1F44F 1F3FD ; fully-qualified # 👏🏽 E1.0 clapping hands: medium skin tone -1F44F 1F3FE ; fully-qualified # 👏🏾 E1.0 clapping hands: medium-dark skin tone -1F44F 1F3FF ; fully-qualified # 👏🏿 E1.0 clapping hands: dark skin tone -1F64C ; fully-qualified # 🙌 E0.6 raising hands -1F64C 1F3FB ; fully-qualified # 🙌🏻 E1.0 raising hands: light skin tone -1F64C 1F3FC ; fully-qualified # 🙌🏼 E1.0 raising hands: medium-light skin tone -1F64C 1F3FD ; fully-qualified # 🙌🏽 E1.0 raising hands: medium skin tone -1F64C 1F3FE ; fully-qualified # 🙌🏾 E1.0 raising hands: medium-dark skin tone -1F64C 1F3FF ; fully-qualified # 🙌🏿 E1.0 raising hands: dark skin tone -1FAF6 ; fully-qualified # 🫶 E14.0 heart hands -1FAF6 1F3FB ; fully-qualified # 🫶🏻 E14.0 heart hands: light skin tone -1FAF6 1F3FC ; fully-qualified # 🫶🏼 E14.0 heart hands: medium-light skin tone -1FAF6 1F3FD ; fully-qualified # 🫶🏽 E14.0 heart hands: medium skin tone -1FAF6 1F3FE ; fully-qualified # 🫶🏾 E14.0 heart hands: medium-dark skin tone -1FAF6 1F3FF ; fully-qualified # 🫶🏿 E14.0 heart hands: dark skin tone -1F450 ; fully-qualified # 👐 E0.6 open hands -1F450 1F3FB ; fully-qualified # 👐🏻 E1.0 open hands: light skin tone -1F450 1F3FC ; fully-qualified # 👐🏼 E1.0 open hands: medium-light skin tone -1F450 1F3FD ; fully-qualified # 👐🏽 E1.0 open hands: medium skin tone -1F450 1F3FE ; fully-qualified # 👐🏾 E1.0 open hands: medium-dark skin tone -1F450 1F3FF ; fully-qualified # 👐🏿 E1.0 open hands: dark skin tone -1F932 ; fully-qualified # 🤲 E5.0 palms up together -1F932 1F3FB ; fully-qualified # 🤲🏻 E5.0 palms up together: light skin tone -1F932 1F3FC ; fully-qualified # 🤲🏼 E5.0 palms up together: medium-light skin tone -1F932 1F3FD ; fully-qualified # 🤲🏽 E5.0 palms up together: medium skin tone -1F932 1F3FE ; fully-qualified # 🤲🏾 E5.0 palms up together: medium-dark skin tone -1F932 1F3FF ; fully-qualified # 🤲🏿 E5.0 palms up together: dark skin tone -1F91D ; fully-qualified # 🤝 E3.0 handshake -1F91D 1F3FB ; fully-qualified # 🤝🏻 E14.0 handshake: light skin tone -1F91D 1F3FC ; fully-qualified # 🤝🏼 E14.0 handshake: medium-light skin tone -1F91D 1F3FD ; fully-qualified # 🤝🏽 E14.0 handshake: medium skin tone -1F91D 1F3FE ; fully-qualified # 🤝🏾 E14.0 handshake: medium-dark skin tone -1F91D 1F3FF ; fully-qualified # 🤝🏿 E14.0 handshake: dark skin tone -1FAF1 1F3FB 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏻‍🫲🏼 E14.0 handshake: light skin tone, medium-light skin tone -1FAF1 1F3FB 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏻‍🫲🏽 E14.0 handshake: light skin tone, medium skin tone -1FAF1 1F3FB 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏻‍🫲🏾 E14.0 handshake: light skin tone, medium-dark skin tone -1FAF1 1F3FB 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏻‍🫲🏿 E14.0 handshake: light skin tone, dark skin tone -1FAF1 1F3FC 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏼‍🫲🏻 E14.0 handshake: medium-light skin tone, light skin tone -1FAF1 1F3FC 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏼‍🫲🏽 E14.0 handshake: medium-light skin tone, medium skin tone -1FAF1 1F3FC 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏼‍🫲🏾 E14.0 handshake: medium-light skin tone, medium-dark skin tone -1FAF1 1F3FC 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏼‍🫲🏿 E14.0 handshake: medium-light skin tone, dark skin tone -1FAF1 1F3FD 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏽‍🫲🏻 E14.0 handshake: medium skin tone, light skin tone -1FAF1 1F3FD 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏽‍🫲🏼 E14.0 handshake: medium skin tone, medium-light skin tone -1FAF1 1F3FD 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏽‍🫲🏾 E14.0 handshake: medium skin tone, medium-dark skin tone -1FAF1 1F3FD 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏽‍🫲🏿 E14.0 handshake: medium skin tone, dark skin tone -1FAF1 1F3FE 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏾‍🫲🏻 E14.0 handshake: medium-dark skin tone, light skin tone -1FAF1 1F3FE 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏾‍🫲🏼 E14.0 handshake: medium-dark skin tone, medium-light skin tone -1FAF1 1F3FE 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏾‍🫲🏽 E14.0 handshake: medium-dark skin tone, medium skin tone -1FAF1 1F3FE 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏾‍🫲🏿 E14.0 handshake: medium-dark skin tone, dark skin tone -1FAF1 1F3FF 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏿‍🫲🏻 E14.0 handshake: dark skin tone, light skin tone -1FAF1 1F3FF 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏿‍🫲🏼 E14.0 handshake: dark skin tone, medium-light skin tone -1FAF1 1F3FF 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏿‍🫲🏽 E14.0 handshake: dark skin tone, medium skin tone -1FAF1 1F3FF 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏿‍🫲🏾 E14.0 handshake: dark skin tone, medium-dark skin tone -1F64F ; fully-qualified # 🙏 E0.6 folded hands -1F64F 1F3FB ; fully-qualified # 🙏🏻 E1.0 folded hands: light skin tone -1F64F 1F3FC ; fully-qualified # 🙏🏼 E1.0 folded hands: medium-light skin tone -1F64F 1F3FD ; fully-qualified # 🙏🏽 E1.0 folded hands: medium skin tone -1F64F 1F3FE ; fully-qualified # 🙏🏾 E1.0 folded hands: medium-dark skin tone -1F64F 1F3FF ; fully-qualified # 🙏🏿 E1.0 folded hands: dark skin tone - -# subgroup: hand-prop -270D FE0F ; fully-qualified # ✍️ E0.7 writing hand -270D ; unqualified # ✍ E0.7 writing hand -270D 1F3FB ; fully-qualified # ✍🏻 E1.0 writing hand: light skin tone -270D 1F3FC ; fully-qualified # ✍🏼 E1.0 writing hand: medium-light skin tone -270D 1F3FD ; fully-qualified # ✍🏽 E1.0 writing hand: medium skin tone -270D 1F3FE ; fully-qualified # ✍🏾 E1.0 writing hand: medium-dark skin tone -270D 1F3FF ; fully-qualified # ✍🏿 E1.0 writing hand: dark skin tone -1F485 ; fully-qualified # 💅 E0.6 nail polish -1F485 1F3FB ; fully-qualified # 💅🏻 E1.0 nail polish: light skin tone -1F485 1F3FC ; fully-qualified # 💅🏼 E1.0 nail polish: medium-light skin tone -1F485 1F3FD ; fully-qualified # 💅🏽 E1.0 nail polish: medium skin tone -1F485 1F3FE ; fully-qualified # 💅🏾 E1.0 nail polish: medium-dark skin tone -1F485 1F3FF ; fully-qualified # 💅🏿 E1.0 nail polish: dark skin tone -1F933 ; fully-qualified # 🤳 E3.0 selfie -1F933 1F3FB ; fully-qualified # 🤳🏻 E3.0 selfie: light skin tone -1F933 1F3FC ; fully-qualified # 🤳🏼 E3.0 selfie: medium-light skin tone -1F933 1F3FD ; fully-qualified # 🤳🏽 E3.0 selfie: medium skin tone -1F933 1F3FE ; fully-qualified # 🤳🏾 E3.0 selfie: medium-dark skin tone -1F933 1F3FF ; fully-qualified # 🤳🏿 E3.0 selfie: dark skin tone - -# subgroup: body-parts -1F4AA ; fully-qualified # 💪 E0.6 flexed biceps -1F4AA 1F3FB ; fully-qualified # 💪🏻 E1.0 flexed biceps: light skin tone -1F4AA 1F3FC ; fully-qualified # 💪🏼 E1.0 flexed biceps: medium-light skin tone -1F4AA 1F3FD ; fully-qualified # 💪🏽 E1.0 flexed biceps: medium skin tone -1F4AA 1F3FE ; fully-qualified # 💪🏾 E1.0 flexed biceps: medium-dark skin tone -1F4AA 1F3FF ; fully-qualified # 💪🏿 E1.0 flexed biceps: dark skin tone -1F9BE ; fully-qualified # 🦾 E12.0 mechanical arm -1F9BF ; fully-qualified # 🦿 E12.0 mechanical leg -1F9B5 ; fully-qualified # 🦵 E11.0 leg -1F9B5 1F3FB ; fully-qualified # 🦵🏻 E11.0 leg: light skin tone -1F9B5 1F3FC ; fully-qualified # 🦵🏼 E11.0 leg: medium-light skin tone -1F9B5 1F3FD ; fully-qualified # 🦵🏽 E11.0 leg: medium skin tone -1F9B5 1F3FE ; fully-qualified # 🦵🏾 E11.0 leg: medium-dark skin tone -1F9B5 1F3FF ; fully-qualified # 🦵🏿 E11.0 leg: dark skin tone -1F9B6 ; fully-qualified # 🦶 E11.0 foot -1F9B6 1F3FB ; fully-qualified # 🦶🏻 E11.0 foot: light skin tone -1F9B6 1F3FC ; fully-qualified # 🦶🏼 E11.0 foot: medium-light skin tone -1F9B6 1F3FD ; fully-qualified # 🦶🏽 E11.0 foot: medium skin tone -1F9B6 1F3FE ; fully-qualified # 🦶🏾 E11.0 foot: medium-dark skin tone -1F9B6 1F3FF ; fully-qualified # 🦶🏿 E11.0 foot: dark skin tone -1F442 ; fully-qualified # 👂 E0.6 ear -1F442 1F3FB ; fully-qualified # 👂🏻 E1.0 ear: light skin tone -1F442 1F3FC ; fully-qualified # 👂🏼 E1.0 ear: medium-light skin tone -1F442 1F3FD ; fully-qualified # 👂🏽 E1.0 ear: medium skin tone -1F442 1F3FE ; fully-qualified # 👂🏾 E1.0 ear: medium-dark skin tone -1F442 1F3FF ; fully-qualified # 👂🏿 E1.0 ear: dark skin tone -1F9BB ; fully-qualified # 🦻 E12.0 ear with hearing aid -1F9BB 1F3FB ; fully-qualified # 🦻🏻 E12.0 ear with hearing aid: light skin tone -1F9BB 1F3FC ; fully-qualified # 🦻🏼 E12.0 ear with hearing aid: medium-light skin tone -1F9BB 1F3FD ; fully-qualified # 🦻🏽 E12.0 ear with hearing aid: medium skin tone -1F9BB 1F3FE ; fully-qualified # 🦻🏾 E12.0 ear with hearing aid: medium-dark skin tone -1F9BB 1F3FF ; fully-qualified # 🦻🏿 E12.0 ear with hearing aid: dark skin tone -1F443 ; fully-qualified # 👃 E0.6 nose -1F443 1F3FB ; fully-qualified # 👃🏻 E1.0 nose: light skin tone -1F443 1F3FC ; fully-qualified # 👃🏼 E1.0 nose: medium-light skin tone -1F443 1F3FD ; fully-qualified # 👃🏽 E1.0 nose: medium skin tone -1F443 1F3FE ; fully-qualified # 👃🏾 E1.0 nose: medium-dark skin tone -1F443 1F3FF ; fully-qualified # 👃🏿 E1.0 nose: dark skin tone -1F9E0 ; fully-qualified # 🧠 E5.0 brain -1FAC0 ; fully-qualified # 🫀 E13.0 anatomical heart -1FAC1 ; fully-qualified # 🫁 E13.0 lungs -1F9B7 ; fully-qualified # 🦷 E11.0 tooth -1F9B4 ; fully-qualified # 🦴 E11.0 bone -1F440 ; fully-qualified # 👀 E0.6 eyes -1F441 FE0F ; fully-qualified # 👁️ E0.7 eye -1F441 ; unqualified # 👁 E0.7 eye -1F445 ; fully-qualified # 👅 E0.6 tongue -1F444 ; fully-qualified # 👄 E0.6 mouth -1FAE6 ; fully-qualified # 🫦 E14.0 biting lip - -# subgroup: person -1F476 ; fully-qualified # 👶 E0.6 baby -1F476 1F3FB ; fully-qualified # 👶🏻 E1.0 baby: light skin tone -1F476 1F3FC ; fully-qualified # 👶🏼 E1.0 baby: medium-light skin tone -1F476 1F3FD ; fully-qualified # 👶🏽 E1.0 baby: medium skin tone -1F476 1F3FE ; fully-qualified # 👶🏾 E1.0 baby: medium-dark skin tone -1F476 1F3FF ; fully-qualified # 👶🏿 E1.0 baby: dark skin tone -1F9D2 ; fully-qualified # 🧒 E5.0 child -1F9D2 1F3FB ; fully-qualified # 🧒🏻 E5.0 child: light skin tone -1F9D2 1F3FC ; fully-qualified # 🧒🏼 E5.0 child: medium-light skin tone -1F9D2 1F3FD ; fully-qualified # 🧒🏽 E5.0 child: medium skin tone -1F9D2 1F3FE ; fully-qualified # 🧒🏾 E5.0 child: medium-dark skin tone -1F9D2 1F3FF ; fully-qualified # 🧒🏿 E5.0 child: dark skin tone -1F466 ; fully-qualified # 👦 E0.6 boy -1F466 1F3FB ; fully-qualified # 👦🏻 E1.0 boy: light skin tone -1F466 1F3FC ; fully-qualified # 👦🏼 E1.0 boy: medium-light skin tone -1F466 1F3FD ; fully-qualified # 👦🏽 E1.0 boy: medium skin tone -1F466 1F3FE ; fully-qualified # 👦🏾 E1.0 boy: medium-dark skin tone -1F466 1F3FF ; fully-qualified # 👦🏿 E1.0 boy: dark skin tone -1F467 ; fully-qualified # 👧 E0.6 girl -1F467 1F3FB ; fully-qualified # 👧🏻 E1.0 girl: light skin tone -1F467 1F3FC ; fully-qualified # 👧🏼 E1.0 girl: medium-light skin tone -1F467 1F3FD ; fully-qualified # 👧🏽 E1.0 girl: medium skin tone -1F467 1F3FE ; fully-qualified # 👧🏾 E1.0 girl: medium-dark skin tone -1F467 1F3FF ; fully-qualified # 👧🏿 E1.0 girl: dark skin tone -1F9D1 ; fully-qualified # 🧑 E5.0 person -1F9D1 1F3FB ; fully-qualified # 🧑🏻 E5.0 person: light skin tone -1F9D1 1F3FC ; fully-qualified # 🧑🏼 E5.0 person: medium-light skin tone -1F9D1 1F3FD ; fully-qualified # 🧑🏽 E5.0 person: medium skin tone -1F9D1 1F3FE ; fully-qualified # 🧑🏾 E5.0 person: medium-dark skin tone -1F9D1 1F3FF ; fully-qualified # 🧑🏿 E5.0 person: dark skin tone -1F471 ; fully-qualified # 👱 E0.6 person: blond hair -1F471 1F3FB ; fully-qualified # 👱🏻 E1.0 person: light skin tone, blond hair -1F471 1F3FC ; fully-qualified # 👱🏼 E1.0 person: medium-light skin tone, blond hair -1F471 1F3FD ; fully-qualified # 👱🏽 E1.0 person: medium skin tone, blond hair -1F471 1F3FE ; fully-qualified # 👱🏾 E1.0 person: medium-dark skin tone, blond hair -1F471 1F3FF ; fully-qualified # 👱🏿 E1.0 person: dark skin tone, blond hair -1F468 ; fully-qualified # 👨 E0.6 man -1F468 1F3FB ; fully-qualified # 👨🏻 E1.0 man: light skin tone -1F468 1F3FC ; fully-qualified # 👨🏼 E1.0 man: medium-light skin tone -1F468 1F3FD ; fully-qualified # 👨🏽 E1.0 man: medium skin tone -1F468 1F3FE ; fully-qualified # 👨🏾 E1.0 man: medium-dark skin tone -1F468 1F3FF ; fully-qualified # 👨🏿 E1.0 man: dark skin tone -1F9D4 ; fully-qualified # 🧔 E5.0 person: beard -1F9D4 1F3FB ; fully-qualified # 🧔🏻 E5.0 person: light skin tone, beard -1F9D4 1F3FC ; fully-qualified # 🧔🏼 E5.0 person: medium-light skin tone, beard -1F9D4 1F3FD ; fully-qualified # 🧔🏽 E5.0 person: medium skin tone, beard -1F9D4 1F3FE ; fully-qualified # 🧔🏾 E5.0 person: medium-dark skin tone, beard -1F9D4 1F3FF ; fully-qualified # 🧔🏿 E5.0 person: dark skin tone, beard -1F9D4 200D 2642 FE0F ; fully-qualified # 🧔‍♂️ E13.1 man: beard -1F9D4 200D 2642 ; minimally-qualified # 🧔‍♂ E13.1 man: beard -1F9D4 1F3FB 200D 2642 FE0F ; fully-qualified # 🧔🏻‍♂️ E13.1 man: light skin tone, beard -1F9D4 1F3FB 200D 2642 ; minimally-qualified # 🧔🏻‍♂ E13.1 man: light skin tone, beard -1F9D4 1F3FC 200D 2642 FE0F ; fully-qualified # 🧔🏼‍♂️ E13.1 man: medium-light skin tone, beard -1F9D4 1F3FC 200D 2642 ; minimally-qualified # 🧔🏼‍♂ E13.1 man: medium-light skin tone, beard -1F9D4 1F3FD 200D 2642 FE0F ; fully-qualified # 🧔🏽‍♂️ E13.1 man: medium skin tone, beard -1F9D4 1F3FD 200D 2642 ; minimally-qualified # 🧔🏽‍♂ E13.1 man: medium skin tone, beard -1F9D4 1F3FE 200D 2642 FE0F ; fully-qualified # 🧔🏾‍♂️ E13.1 man: medium-dark skin tone, beard -1F9D4 1F3FE 200D 2642 ; minimally-qualified # 🧔🏾‍♂ E13.1 man: medium-dark skin tone, beard -1F9D4 1F3FF 200D 2642 FE0F ; fully-qualified # 🧔🏿‍♂️ E13.1 man: dark skin tone, beard -1F9D4 1F3FF 200D 2642 ; minimally-qualified # 🧔🏿‍♂ E13.1 man: dark skin tone, beard -1F9D4 200D 2640 FE0F ; fully-qualified # 🧔‍♀️ E13.1 woman: beard -1F9D4 200D 2640 ; minimally-qualified # 🧔‍♀ E13.1 woman: beard -1F9D4 1F3FB 200D 2640 FE0F ; fully-qualified # 🧔🏻‍♀️ E13.1 woman: light skin tone, beard -1F9D4 1F3FB 200D 2640 ; minimally-qualified # 🧔🏻‍♀ E13.1 woman: light skin tone, beard -1F9D4 1F3FC 200D 2640 FE0F ; fully-qualified # 🧔🏼‍♀️ E13.1 woman: medium-light skin tone, beard -1F9D4 1F3FC 200D 2640 ; minimally-qualified # 🧔🏼‍♀ E13.1 woman: medium-light skin tone, beard -1F9D4 1F3FD 200D 2640 FE0F ; fully-qualified # 🧔🏽‍♀️ E13.1 woman: medium skin tone, beard -1F9D4 1F3FD 200D 2640 ; minimally-qualified # 🧔🏽‍♀ E13.1 woman: medium skin tone, beard -1F9D4 1F3FE 200D 2640 FE0F ; fully-qualified # 🧔🏾‍♀️ E13.1 woman: medium-dark skin tone, beard -1F9D4 1F3FE 200D 2640 ; minimally-qualified # 🧔🏾‍♀ E13.1 woman: medium-dark skin tone, beard -1F9D4 1F3FF 200D 2640 FE0F ; fully-qualified # 🧔🏿‍♀️ E13.1 woman: dark skin tone, beard -1F9D4 1F3FF 200D 2640 ; minimally-qualified # 🧔🏿‍♀ E13.1 woman: dark skin tone, beard -1F468 200D 1F9B0 ; fully-qualified # 👨‍🦰 E11.0 man: red hair -1F468 1F3FB 200D 1F9B0 ; fully-qualified # 👨🏻‍🦰 E11.0 man: light skin tone, red hair -1F468 1F3FC 200D 1F9B0 ; fully-qualified # 👨🏼‍🦰 E11.0 man: medium-light skin tone, red hair -1F468 1F3FD 200D 1F9B0 ; fully-qualified # 👨🏽‍🦰 E11.0 man: medium skin tone, red hair -1F468 1F3FE 200D 1F9B0 ; fully-qualified # 👨🏾‍🦰 E11.0 man: medium-dark skin tone, red hair -1F468 1F3FF 200D 1F9B0 ; fully-qualified # 👨🏿‍🦰 E11.0 man: dark skin tone, red hair -1F468 200D 1F9B1 ; fully-qualified # 👨‍🦱 E11.0 man: curly hair -1F468 1F3FB 200D 1F9B1 ; fully-qualified # 👨🏻‍🦱 E11.0 man: light skin tone, curly hair -1F468 1F3FC 200D 1F9B1 ; fully-qualified # 👨🏼‍🦱 E11.0 man: medium-light skin tone, curly hair -1F468 1F3FD 200D 1F9B1 ; fully-qualified # 👨🏽‍🦱 E11.0 man: medium skin tone, curly hair -1F468 1F3FE 200D 1F9B1 ; fully-qualified # 👨🏾‍🦱 E11.0 man: medium-dark skin tone, curly hair -1F468 1F3FF 200D 1F9B1 ; fully-qualified # 👨🏿‍🦱 E11.0 man: dark skin tone, curly hair -1F468 200D 1F9B3 ; fully-qualified # 👨‍🦳 E11.0 man: white hair -1F468 1F3FB 200D 1F9B3 ; fully-qualified # 👨🏻‍🦳 E11.0 man: light skin tone, white hair -1F468 1F3FC 200D 1F9B3 ; fully-qualified # 👨🏼‍🦳 E11.0 man: medium-light skin tone, white hair -1F468 1F3FD 200D 1F9B3 ; fully-qualified # 👨🏽‍🦳 E11.0 man: medium skin tone, white hair -1F468 1F3FE 200D 1F9B3 ; fully-qualified # 👨🏾‍🦳 E11.0 man: medium-dark skin tone, white hair -1F468 1F3FF 200D 1F9B3 ; fully-qualified # 👨🏿‍🦳 E11.0 man: dark skin tone, white hair -1F468 200D 1F9B2 ; fully-qualified # 👨‍🦲 E11.0 man: bald -1F468 1F3FB 200D 1F9B2 ; fully-qualified # 👨🏻‍🦲 E11.0 man: light skin tone, bald -1F468 1F3FC 200D 1F9B2 ; fully-qualified # 👨🏼‍🦲 E11.0 man: medium-light skin tone, bald -1F468 1F3FD 200D 1F9B2 ; fully-qualified # 👨🏽‍🦲 E11.0 man: medium skin tone, bald -1F468 1F3FE 200D 1F9B2 ; fully-qualified # 👨🏾‍🦲 E11.0 man: medium-dark skin tone, bald -1F468 1F3FF 200D 1F9B2 ; fully-qualified # 👨🏿‍🦲 E11.0 man: dark skin tone, bald -1F469 ; fully-qualified # 👩 E0.6 woman -1F469 1F3FB ; fully-qualified # 👩🏻 E1.0 woman: light skin tone -1F469 1F3FC ; fully-qualified # 👩🏼 E1.0 woman: medium-light skin tone -1F469 1F3FD ; fully-qualified # 👩🏽 E1.0 woman: medium skin tone -1F469 1F3FE ; fully-qualified # 👩🏾 E1.0 woman: medium-dark skin tone -1F469 1F3FF ; fully-qualified # 👩🏿 E1.0 woman: dark skin tone -1F469 200D 1F9B0 ; fully-qualified # 👩‍🦰 E11.0 woman: red hair -1F469 1F3FB 200D 1F9B0 ; fully-qualified # 👩🏻‍🦰 E11.0 woman: light skin tone, red hair -1F469 1F3FC 200D 1F9B0 ; fully-qualified # 👩🏼‍🦰 E11.0 woman: medium-light skin tone, red hair -1F469 1F3FD 200D 1F9B0 ; fully-qualified # 👩🏽‍🦰 E11.0 woman: medium skin tone, red hair -1F469 1F3FE 200D 1F9B0 ; fully-qualified # 👩🏾‍🦰 E11.0 woman: medium-dark skin tone, red hair -1F469 1F3FF 200D 1F9B0 ; fully-qualified # 👩🏿‍🦰 E11.0 woman: dark skin tone, red hair -1F9D1 200D 1F9B0 ; fully-qualified # 🧑‍🦰 E12.1 person: red hair -1F9D1 1F3FB 200D 1F9B0 ; fully-qualified # 🧑🏻‍🦰 E12.1 person: light skin tone, red hair -1F9D1 1F3FC 200D 1F9B0 ; fully-qualified # 🧑🏼‍🦰 E12.1 person: medium-light skin tone, red hair -1F9D1 1F3FD 200D 1F9B0 ; fully-qualified # 🧑🏽‍🦰 E12.1 person: medium skin tone, red hair -1F9D1 1F3FE 200D 1F9B0 ; fully-qualified # 🧑🏾‍🦰 E12.1 person: medium-dark skin tone, red hair -1F9D1 1F3FF 200D 1F9B0 ; fully-qualified # 🧑🏿‍🦰 E12.1 person: dark skin tone, red hair -1F469 200D 1F9B1 ; fully-qualified # 👩‍🦱 E11.0 woman: curly hair -1F469 1F3FB 200D 1F9B1 ; fully-qualified # 👩🏻‍🦱 E11.0 woman: light skin tone, curly hair -1F469 1F3FC 200D 1F9B1 ; fully-qualified # 👩🏼‍🦱 E11.0 woman: medium-light skin tone, curly hair -1F469 1F3FD 200D 1F9B1 ; fully-qualified # 👩🏽‍🦱 E11.0 woman: medium skin tone, curly hair -1F469 1F3FE 200D 1F9B1 ; fully-qualified # 👩🏾‍🦱 E11.0 woman: medium-dark skin tone, curly hair -1F469 1F3FF 200D 1F9B1 ; fully-qualified # 👩🏿‍🦱 E11.0 woman: dark skin tone, curly hair -1F9D1 200D 1F9B1 ; fully-qualified # 🧑‍🦱 E12.1 person: curly hair -1F9D1 1F3FB 200D 1F9B1 ; fully-qualified # 🧑🏻‍🦱 E12.1 person: light skin tone, curly hair -1F9D1 1F3FC 200D 1F9B1 ; fully-qualified # 🧑🏼‍🦱 E12.1 person: medium-light skin tone, curly hair -1F9D1 1F3FD 200D 1F9B1 ; fully-qualified # 🧑🏽‍🦱 E12.1 person: medium skin tone, curly hair -1F9D1 1F3FE 200D 1F9B1 ; fully-qualified # 🧑🏾‍🦱 E12.1 person: medium-dark skin tone, curly hair -1F9D1 1F3FF 200D 1F9B1 ; fully-qualified # 🧑🏿‍🦱 E12.1 person: dark skin tone, curly hair -1F469 200D 1F9B3 ; fully-qualified # 👩‍🦳 E11.0 woman: white hair -1F469 1F3FB 200D 1F9B3 ; fully-qualified # 👩🏻‍🦳 E11.0 woman: light skin tone, white hair -1F469 1F3FC 200D 1F9B3 ; fully-qualified # 👩🏼‍🦳 E11.0 woman: medium-light skin tone, white hair -1F469 1F3FD 200D 1F9B3 ; fully-qualified # 👩🏽‍🦳 E11.0 woman: medium skin tone, white hair -1F469 1F3FE 200D 1F9B3 ; fully-qualified # 👩🏾‍🦳 E11.0 woman: medium-dark skin tone, white hair -1F469 1F3FF 200D 1F9B3 ; fully-qualified # 👩🏿‍🦳 E11.0 woman: dark skin tone, white hair -1F9D1 200D 1F9B3 ; fully-qualified # 🧑‍🦳 E12.1 person: white hair -1F9D1 1F3FB 200D 1F9B3 ; fully-qualified # 🧑🏻‍🦳 E12.1 person: light skin tone, white hair -1F9D1 1F3FC 200D 1F9B3 ; fully-qualified # 🧑🏼‍🦳 E12.1 person: medium-light skin tone, white hair -1F9D1 1F3FD 200D 1F9B3 ; fully-qualified # 🧑🏽‍🦳 E12.1 person: medium skin tone, white hair -1F9D1 1F3FE 200D 1F9B3 ; fully-qualified # 🧑🏾‍🦳 E12.1 person: medium-dark skin tone, white hair -1F9D1 1F3FF 200D 1F9B3 ; fully-qualified # 🧑🏿‍🦳 E12.1 person: dark skin tone, white hair -1F469 200D 1F9B2 ; fully-qualified # 👩‍🦲 E11.0 woman: bald -1F469 1F3FB 200D 1F9B2 ; fully-qualified # 👩🏻‍🦲 E11.0 woman: light skin tone, bald -1F469 1F3FC 200D 1F9B2 ; fully-qualified # 👩🏼‍🦲 E11.0 woman: medium-light skin tone, bald -1F469 1F3FD 200D 1F9B2 ; fully-qualified # 👩🏽‍🦲 E11.0 woman: medium skin tone, bald -1F469 1F3FE 200D 1F9B2 ; fully-qualified # 👩🏾‍🦲 E11.0 woman: medium-dark skin tone, bald -1F469 1F3FF 200D 1F9B2 ; fully-qualified # 👩🏿‍🦲 E11.0 woman: dark skin tone, bald -1F9D1 200D 1F9B2 ; fully-qualified # 🧑‍🦲 E12.1 person: bald -1F9D1 1F3FB 200D 1F9B2 ; fully-qualified # 🧑🏻‍🦲 E12.1 person: light skin tone, bald -1F9D1 1F3FC 200D 1F9B2 ; fully-qualified # 🧑🏼‍🦲 E12.1 person: medium-light skin tone, bald -1F9D1 1F3FD 200D 1F9B2 ; fully-qualified # 🧑🏽‍🦲 E12.1 person: medium skin tone, bald -1F9D1 1F3FE 200D 1F9B2 ; fully-qualified # 🧑🏾‍🦲 E12.1 person: medium-dark skin tone, bald -1F9D1 1F3FF 200D 1F9B2 ; fully-qualified # 🧑🏿‍🦲 E12.1 person: dark skin tone, bald -1F471 200D 2640 FE0F ; fully-qualified # 👱‍♀️ E4.0 woman: blond hair -1F471 200D 2640 ; minimally-qualified # 👱‍♀ E4.0 woman: blond hair -1F471 1F3FB 200D 2640 FE0F ; fully-qualified # 👱🏻‍♀️ E4.0 woman: light skin tone, blond hair -1F471 1F3FB 200D 2640 ; minimally-qualified # 👱🏻‍♀ E4.0 woman: light skin tone, blond hair -1F471 1F3FC 200D 2640 FE0F ; fully-qualified # 👱🏼‍♀️ E4.0 woman: medium-light skin tone, blond hair -1F471 1F3FC 200D 2640 ; minimally-qualified # 👱🏼‍♀ E4.0 woman: medium-light skin tone, blond hair -1F471 1F3FD 200D 2640 FE0F ; fully-qualified # 👱🏽‍♀️ E4.0 woman: medium skin tone, blond hair -1F471 1F3FD 200D 2640 ; minimally-qualified # 👱🏽‍♀ E4.0 woman: medium skin tone, blond hair -1F471 1F3FE 200D 2640 FE0F ; fully-qualified # 👱🏾‍♀️ E4.0 woman: medium-dark skin tone, blond hair -1F471 1F3FE 200D 2640 ; minimally-qualified # 👱🏾‍♀ E4.0 woman: medium-dark skin tone, blond hair -1F471 1F3FF 200D 2640 FE0F ; fully-qualified # 👱🏿‍♀️ E4.0 woman: dark skin tone, blond hair -1F471 1F3FF 200D 2640 ; minimally-qualified # 👱🏿‍♀ E4.0 woman: dark skin tone, blond hair -1F471 200D 2642 FE0F ; fully-qualified # 👱‍♂️ E4.0 man: blond hair -1F471 200D 2642 ; minimally-qualified # 👱‍♂ E4.0 man: blond hair -1F471 1F3FB 200D 2642 FE0F ; fully-qualified # 👱🏻‍♂️ E4.0 man: light skin tone, blond hair -1F471 1F3FB 200D 2642 ; minimally-qualified # 👱🏻‍♂ E4.0 man: light skin tone, blond hair -1F471 1F3FC 200D 2642 FE0F ; fully-qualified # 👱🏼‍♂️ E4.0 man: medium-light skin tone, blond hair -1F471 1F3FC 200D 2642 ; minimally-qualified # 👱🏼‍♂ E4.0 man: medium-light skin tone, blond hair -1F471 1F3FD 200D 2642 FE0F ; fully-qualified # 👱🏽‍♂️ E4.0 man: medium skin tone, blond hair -1F471 1F3FD 200D 2642 ; minimally-qualified # 👱🏽‍♂ E4.0 man: medium skin tone, blond hair -1F471 1F3FE 200D 2642 FE0F ; fully-qualified # 👱🏾‍♂️ E4.0 man: medium-dark skin tone, blond hair -1F471 1F3FE 200D 2642 ; minimally-qualified # 👱🏾‍♂ E4.0 man: medium-dark skin tone, blond hair -1F471 1F3FF 200D 2642 FE0F ; fully-qualified # 👱🏿‍♂️ E4.0 man: dark skin tone, blond hair -1F471 1F3FF 200D 2642 ; minimally-qualified # 👱🏿‍♂ E4.0 man: dark skin tone, blond hair -1F9D3 ; fully-qualified # 🧓 E5.0 older person -1F9D3 1F3FB ; fully-qualified # 🧓🏻 E5.0 older person: light skin tone -1F9D3 1F3FC ; fully-qualified # 🧓🏼 E5.0 older person: medium-light skin tone -1F9D3 1F3FD ; fully-qualified # 🧓🏽 E5.0 older person: medium skin tone -1F9D3 1F3FE ; fully-qualified # 🧓🏾 E5.0 older person: medium-dark skin tone -1F9D3 1F3FF ; fully-qualified # 🧓🏿 E5.0 older person: dark skin tone -1F474 ; fully-qualified # 👴 E0.6 old man -1F474 1F3FB ; fully-qualified # 👴🏻 E1.0 old man: light skin tone -1F474 1F3FC ; fully-qualified # 👴🏼 E1.0 old man: medium-light skin tone -1F474 1F3FD ; fully-qualified # 👴🏽 E1.0 old man: medium skin tone -1F474 1F3FE ; fully-qualified # 👴🏾 E1.0 old man: medium-dark skin tone -1F474 1F3FF ; fully-qualified # 👴🏿 E1.0 old man: dark skin tone -1F475 ; fully-qualified # 👵 E0.6 old woman -1F475 1F3FB ; fully-qualified # 👵🏻 E1.0 old woman: light skin tone -1F475 1F3FC ; fully-qualified # 👵🏼 E1.0 old woman: medium-light skin tone -1F475 1F3FD ; fully-qualified # 👵🏽 E1.0 old woman: medium skin tone -1F475 1F3FE ; fully-qualified # 👵🏾 E1.0 old woman: medium-dark skin tone -1F475 1F3FF ; fully-qualified # 👵🏿 E1.0 old woman: dark skin tone - -# subgroup: person-gesture -1F64D ; fully-qualified # 🙍 E0.6 person frowning -1F64D 1F3FB ; fully-qualified # 🙍🏻 E1.0 person frowning: light skin tone -1F64D 1F3FC ; fully-qualified # 🙍🏼 E1.0 person frowning: medium-light skin tone -1F64D 1F3FD ; fully-qualified # 🙍🏽 E1.0 person frowning: medium skin tone -1F64D 1F3FE ; fully-qualified # 🙍🏾 E1.0 person frowning: medium-dark skin tone -1F64D 1F3FF ; fully-qualified # 🙍🏿 E1.0 person frowning: dark skin tone -1F64D 200D 2642 FE0F ; fully-qualified # 🙍‍♂️ E4.0 man frowning -1F64D 200D 2642 ; minimally-qualified # 🙍‍♂ E4.0 man frowning -1F64D 1F3FB 200D 2642 FE0F ; fully-qualified # 🙍🏻‍♂️ E4.0 man frowning: light skin tone -1F64D 1F3FB 200D 2642 ; minimally-qualified # 🙍🏻‍♂ E4.0 man frowning: light skin tone -1F64D 1F3FC 200D 2642 FE0F ; fully-qualified # 🙍🏼‍♂️ E4.0 man frowning: medium-light skin tone -1F64D 1F3FC 200D 2642 ; minimally-qualified # 🙍🏼‍♂ E4.0 man frowning: medium-light skin tone -1F64D 1F3FD 200D 2642 FE0F ; fully-qualified # 🙍🏽‍♂️ E4.0 man frowning: medium skin tone -1F64D 1F3FD 200D 2642 ; minimally-qualified # 🙍🏽‍♂ E4.0 man frowning: medium skin tone -1F64D 1F3FE 200D 2642 FE0F ; fully-qualified # 🙍🏾‍♂️ E4.0 man frowning: medium-dark skin tone -1F64D 1F3FE 200D 2642 ; minimally-qualified # 🙍🏾‍♂ E4.0 man frowning: medium-dark skin tone -1F64D 1F3FF 200D 2642 FE0F ; fully-qualified # 🙍🏿‍♂️ E4.0 man frowning: dark skin tone -1F64D 1F3FF 200D 2642 ; minimally-qualified # 🙍🏿‍♂ E4.0 man frowning: dark skin tone -1F64D 200D 2640 FE0F ; fully-qualified # 🙍‍♀️ E4.0 woman frowning -1F64D 200D 2640 ; minimally-qualified # 🙍‍♀ E4.0 woman frowning -1F64D 1F3FB 200D 2640 FE0F ; fully-qualified # 🙍🏻‍♀️ E4.0 woman frowning: light skin tone -1F64D 1F3FB 200D 2640 ; minimally-qualified # 🙍🏻‍♀ E4.0 woman frowning: light skin tone -1F64D 1F3FC 200D 2640 FE0F ; fully-qualified # 🙍🏼‍♀️ E4.0 woman frowning: medium-light skin tone -1F64D 1F3FC 200D 2640 ; minimally-qualified # 🙍🏼‍♀ E4.0 woman frowning: medium-light skin tone -1F64D 1F3FD 200D 2640 FE0F ; fully-qualified # 🙍🏽‍♀️ E4.0 woman frowning: medium skin tone -1F64D 1F3FD 200D 2640 ; minimally-qualified # 🙍🏽‍♀ E4.0 woman frowning: medium skin tone -1F64D 1F3FE 200D 2640 FE0F ; fully-qualified # 🙍🏾‍♀️ E4.0 woman frowning: medium-dark skin tone -1F64D 1F3FE 200D 2640 ; minimally-qualified # 🙍🏾‍♀ E4.0 woman frowning: medium-dark skin tone -1F64D 1F3FF 200D 2640 FE0F ; fully-qualified # 🙍🏿‍♀️ E4.0 woman frowning: dark skin tone -1F64D 1F3FF 200D 2640 ; minimally-qualified # 🙍🏿‍♀ E4.0 woman frowning: dark skin tone -1F64E ; fully-qualified # 🙎 E0.6 person pouting -1F64E 1F3FB ; fully-qualified # 🙎🏻 E1.0 person pouting: light skin tone -1F64E 1F3FC ; fully-qualified # 🙎🏼 E1.0 person pouting: medium-light skin tone -1F64E 1F3FD ; fully-qualified # 🙎🏽 E1.0 person pouting: medium skin tone -1F64E 1F3FE ; fully-qualified # 🙎🏾 E1.0 person pouting: medium-dark skin tone -1F64E 1F3FF ; fully-qualified # 🙎🏿 E1.0 person pouting: dark skin tone -1F64E 200D 2642 FE0F ; fully-qualified # 🙎‍♂️ E4.0 man pouting -1F64E 200D 2642 ; minimally-qualified # 🙎‍♂ E4.0 man pouting -1F64E 1F3FB 200D 2642 FE0F ; fully-qualified # 🙎🏻‍♂️ E4.0 man pouting: light skin tone -1F64E 1F3FB 200D 2642 ; minimally-qualified # 🙎🏻‍♂ E4.0 man pouting: light skin tone -1F64E 1F3FC 200D 2642 FE0F ; fully-qualified # 🙎🏼‍♂️ E4.0 man pouting: medium-light skin tone -1F64E 1F3FC 200D 2642 ; minimally-qualified # 🙎🏼‍♂ E4.0 man pouting: medium-light skin tone -1F64E 1F3FD 200D 2642 FE0F ; fully-qualified # 🙎🏽‍♂️ E4.0 man pouting: medium skin tone -1F64E 1F3FD 200D 2642 ; minimally-qualified # 🙎🏽‍♂ E4.0 man pouting: medium skin tone -1F64E 1F3FE 200D 2642 FE0F ; fully-qualified # 🙎🏾‍♂️ E4.0 man pouting: medium-dark skin tone -1F64E 1F3FE 200D 2642 ; minimally-qualified # 🙎🏾‍♂ E4.0 man pouting: medium-dark skin tone -1F64E 1F3FF 200D 2642 FE0F ; fully-qualified # 🙎🏿‍♂️ E4.0 man pouting: dark skin tone -1F64E 1F3FF 200D 2642 ; minimally-qualified # 🙎🏿‍♂ E4.0 man pouting: dark skin tone -1F64E 200D 2640 FE0F ; fully-qualified # 🙎‍♀️ E4.0 woman pouting -1F64E 200D 2640 ; minimally-qualified # 🙎‍♀ E4.0 woman pouting -1F64E 1F3FB 200D 2640 FE0F ; fully-qualified # 🙎🏻‍♀️ E4.0 woman pouting: light skin tone -1F64E 1F3FB 200D 2640 ; minimally-qualified # 🙎🏻‍♀ E4.0 woman pouting: light skin tone -1F64E 1F3FC 200D 2640 FE0F ; fully-qualified # 🙎🏼‍♀️ E4.0 woman pouting: medium-light skin tone -1F64E 1F3FC 200D 2640 ; minimally-qualified # 🙎🏼‍♀ E4.0 woman pouting: medium-light skin tone -1F64E 1F3FD 200D 2640 FE0F ; fully-qualified # 🙎🏽‍♀️ E4.0 woman pouting: medium skin tone -1F64E 1F3FD 200D 2640 ; minimally-qualified # 🙎🏽‍♀ E4.0 woman pouting: medium skin tone -1F64E 1F3FE 200D 2640 FE0F ; fully-qualified # 🙎🏾‍♀️ E4.0 woman pouting: medium-dark skin tone -1F64E 1F3FE 200D 2640 ; minimally-qualified # 🙎🏾‍♀ E4.0 woman pouting: medium-dark skin tone -1F64E 1F3FF 200D 2640 FE0F ; fully-qualified # 🙎🏿‍♀️ E4.0 woman pouting: dark skin tone -1F64E 1F3FF 200D 2640 ; minimally-qualified # 🙎🏿‍♀ E4.0 woman pouting: dark skin tone -1F645 ; fully-qualified # 🙅 E0.6 person gesturing NO -1F645 1F3FB ; fully-qualified # 🙅🏻 E1.0 person gesturing NO: light skin tone -1F645 1F3FC ; fully-qualified # 🙅🏼 E1.0 person gesturing NO: medium-light skin tone -1F645 1F3FD ; fully-qualified # 🙅🏽 E1.0 person gesturing NO: medium skin tone -1F645 1F3FE ; fully-qualified # 🙅🏾 E1.0 person gesturing NO: medium-dark skin tone -1F645 1F3FF ; fully-qualified # 🙅🏿 E1.0 person gesturing NO: dark skin tone -1F645 200D 2642 FE0F ; fully-qualified # 🙅‍♂️ E4.0 man gesturing NO -1F645 200D 2642 ; minimally-qualified # 🙅‍♂ E4.0 man gesturing NO -1F645 1F3FB 200D 2642 FE0F ; fully-qualified # 🙅🏻‍♂️ E4.0 man gesturing NO: light skin tone -1F645 1F3FB 200D 2642 ; minimally-qualified # 🙅🏻‍♂ E4.0 man gesturing NO: light skin tone -1F645 1F3FC 200D 2642 FE0F ; fully-qualified # 🙅🏼‍♂️ E4.0 man gesturing NO: medium-light skin tone -1F645 1F3FC 200D 2642 ; minimally-qualified # 🙅🏼‍♂ E4.0 man gesturing NO: medium-light skin tone -1F645 1F3FD 200D 2642 FE0F ; fully-qualified # 🙅🏽‍♂️ E4.0 man gesturing NO: medium skin tone -1F645 1F3FD 200D 2642 ; minimally-qualified # 🙅🏽‍♂ E4.0 man gesturing NO: medium skin tone -1F645 1F3FE 200D 2642 FE0F ; fully-qualified # 🙅🏾‍♂️ E4.0 man gesturing NO: medium-dark skin tone -1F645 1F3FE 200D 2642 ; minimally-qualified # 🙅🏾‍♂ E4.0 man gesturing NO: medium-dark skin tone -1F645 1F3FF 200D 2642 FE0F ; fully-qualified # 🙅🏿‍♂️ E4.0 man gesturing NO: dark skin tone -1F645 1F3FF 200D 2642 ; minimally-qualified # 🙅🏿‍♂ E4.0 man gesturing NO: dark skin tone -1F645 200D 2640 FE0F ; fully-qualified # 🙅‍♀️ E4.0 woman gesturing NO -1F645 200D 2640 ; minimally-qualified # 🙅‍♀ E4.0 woman gesturing NO -1F645 1F3FB 200D 2640 FE0F ; fully-qualified # 🙅🏻‍♀️ E4.0 woman gesturing NO: light skin tone -1F645 1F3FB 200D 2640 ; minimally-qualified # 🙅🏻‍♀ E4.0 woman gesturing NO: light skin tone -1F645 1F3FC 200D 2640 FE0F ; fully-qualified # 🙅🏼‍♀️ E4.0 woman gesturing NO: medium-light skin tone -1F645 1F3FC 200D 2640 ; minimally-qualified # 🙅🏼‍♀ E4.0 woman gesturing NO: medium-light skin tone -1F645 1F3FD 200D 2640 FE0F ; fully-qualified # 🙅🏽‍♀️ E4.0 woman gesturing NO: medium skin tone -1F645 1F3FD 200D 2640 ; minimally-qualified # 🙅🏽‍♀ E4.0 woman gesturing NO: medium skin tone -1F645 1F3FE 200D 2640 FE0F ; fully-qualified # 🙅🏾‍♀️ E4.0 woman gesturing NO: medium-dark skin tone -1F645 1F3FE 200D 2640 ; minimally-qualified # 🙅🏾‍♀ E4.0 woman gesturing NO: medium-dark skin tone -1F645 1F3FF 200D 2640 FE0F ; fully-qualified # 🙅🏿‍♀️ E4.0 woman gesturing NO: dark skin tone -1F645 1F3FF 200D 2640 ; minimally-qualified # 🙅🏿‍♀ E4.0 woman gesturing NO: dark skin tone -1F646 ; fully-qualified # 🙆 E0.6 person gesturing OK -1F646 1F3FB ; fully-qualified # 🙆🏻 E1.0 person gesturing OK: light skin tone -1F646 1F3FC ; fully-qualified # 🙆🏼 E1.0 person gesturing OK: medium-light skin tone -1F646 1F3FD ; fully-qualified # 🙆🏽 E1.0 person gesturing OK: medium skin tone -1F646 1F3FE ; fully-qualified # 🙆🏾 E1.0 person gesturing OK: medium-dark skin tone -1F646 1F3FF ; fully-qualified # 🙆🏿 E1.0 person gesturing OK: dark skin tone -1F646 200D 2642 FE0F ; fully-qualified # 🙆‍♂️ E4.0 man gesturing OK -1F646 200D 2642 ; minimally-qualified # 🙆‍♂ E4.0 man gesturing OK -1F646 1F3FB 200D 2642 FE0F ; fully-qualified # 🙆🏻‍♂️ E4.0 man gesturing OK: light skin tone -1F646 1F3FB 200D 2642 ; minimally-qualified # 🙆🏻‍♂ E4.0 man gesturing OK: light skin tone -1F646 1F3FC 200D 2642 FE0F ; fully-qualified # 🙆🏼‍♂️ E4.0 man gesturing OK: medium-light skin tone -1F646 1F3FC 200D 2642 ; minimally-qualified # 🙆🏼‍♂ E4.0 man gesturing OK: medium-light skin tone -1F646 1F3FD 200D 2642 FE0F ; fully-qualified # 🙆🏽‍♂️ E4.0 man gesturing OK: medium skin tone -1F646 1F3FD 200D 2642 ; minimally-qualified # 🙆🏽‍♂ E4.0 man gesturing OK: medium skin tone -1F646 1F3FE 200D 2642 FE0F ; fully-qualified # 🙆🏾‍♂️ E4.0 man gesturing OK: medium-dark skin tone -1F646 1F3FE 200D 2642 ; minimally-qualified # 🙆🏾‍♂ E4.0 man gesturing OK: medium-dark skin tone -1F646 1F3FF 200D 2642 FE0F ; fully-qualified # 🙆🏿‍♂️ E4.0 man gesturing OK: dark skin tone -1F646 1F3FF 200D 2642 ; minimally-qualified # 🙆🏿‍♂ E4.0 man gesturing OK: dark skin tone -1F646 200D 2640 FE0F ; fully-qualified # 🙆‍♀️ E4.0 woman gesturing OK -1F646 200D 2640 ; minimally-qualified # 🙆‍♀ E4.0 woman gesturing OK -1F646 1F3FB 200D 2640 FE0F ; fully-qualified # 🙆🏻‍♀️ E4.0 woman gesturing OK: light skin tone -1F646 1F3FB 200D 2640 ; minimally-qualified # 🙆🏻‍♀ E4.0 woman gesturing OK: light skin tone -1F646 1F3FC 200D 2640 FE0F ; fully-qualified # 🙆🏼‍♀️ E4.0 woman gesturing OK: medium-light skin tone -1F646 1F3FC 200D 2640 ; minimally-qualified # 🙆🏼‍♀ E4.0 woman gesturing OK: medium-light skin tone -1F646 1F3FD 200D 2640 FE0F ; fully-qualified # 🙆🏽‍♀️ E4.0 woman gesturing OK: medium skin tone -1F646 1F3FD 200D 2640 ; minimally-qualified # 🙆🏽‍♀ E4.0 woman gesturing OK: medium skin tone -1F646 1F3FE 200D 2640 FE0F ; fully-qualified # 🙆🏾‍♀️ E4.0 woman gesturing OK: medium-dark skin tone -1F646 1F3FE 200D 2640 ; minimally-qualified # 🙆🏾‍♀ E4.0 woman gesturing OK: medium-dark skin tone -1F646 1F3FF 200D 2640 FE0F ; fully-qualified # 🙆🏿‍♀️ E4.0 woman gesturing OK: dark skin tone -1F646 1F3FF 200D 2640 ; minimally-qualified # 🙆🏿‍♀ E4.0 woman gesturing OK: dark skin tone -1F481 ; fully-qualified # 💁 E0.6 person tipping hand -1F481 1F3FB ; fully-qualified # 💁🏻 E1.0 person tipping hand: light skin tone -1F481 1F3FC ; fully-qualified # 💁🏼 E1.0 person tipping hand: medium-light skin tone -1F481 1F3FD ; fully-qualified # 💁🏽 E1.0 person tipping hand: medium skin tone -1F481 1F3FE ; fully-qualified # 💁🏾 E1.0 person tipping hand: medium-dark skin tone -1F481 1F3FF ; fully-qualified # 💁🏿 E1.0 person tipping hand: dark skin tone -1F481 200D 2642 FE0F ; fully-qualified # 💁‍♂️ E4.0 man tipping hand -1F481 200D 2642 ; minimally-qualified # 💁‍♂ E4.0 man tipping hand -1F481 1F3FB 200D 2642 FE0F ; fully-qualified # 💁🏻‍♂️ E4.0 man tipping hand: light skin tone -1F481 1F3FB 200D 2642 ; minimally-qualified # 💁🏻‍♂ E4.0 man tipping hand: light skin tone -1F481 1F3FC 200D 2642 FE0F ; fully-qualified # 💁🏼‍♂️ E4.0 man tipping hand: medium-light skin tone -1F481 1F3FC 200D 2642 ; minimally-qualified # 💁🏼‍♂ E4.0 man tipping hand: medium-light skin tone -1F481 1F3FD 200D 2642 FE0F ; fully-qualified # 💁🏽‍♂️ E4.0 man tipping hand: medium skin tone -1F481 1F3FD 200D 2642 ; minimally-qualified # 💁🏽‍♂ E4.0 man tipping hand: medium skin tone -1F481 1F3FE 200D 2642 FE0F ; fully-qualified # 💁🏾‍♂️ E4.0 man tipping hand: medium-dark skin tone -1F481 1F3FE 200D 2642 ; minimally-qualified # 💁🏾‍♂ E4.0 man tipping hand: medium-dark skin tone -1F481 1F3FF 200D 2642 FE0F ; fully-qualified # 💁🏿‍♂️ E4.0 man tipping hand: dark skin tone -1F481 1F3FF 200D 2642 ; minimally-qualified # 💁🏿‍♂ E4.0 man tipping hand: dark skin tone -1F481 200D 2640 FE0F ; fully-qualified # 💁‍♀️ E4.0 woman tipping hand -1F481 200D 2640 ; minimally-qualified # 💁‍♀ E4.0 woman tipping hand -1F481 1F3FB 200D 2640 FE0F ; fully-qualified # 💁🏻‍♀️ E4.0 woman tipping hand: light skin tone -1F481 1F3FB 200D 2640 ; minimally-qualified # 💁🏻‍♀ E4.0 woman tipping hand: light skin tone -1F481 1F3FC 200D 2640 FE0F ; fully-qualified # 💁🏼‍♀️ E4.0 woman tipping hand: medium-light skin tone -1F481 1F3FC 200D 2640 ; minimally-qualified # 💁🏼‍♀ E4.0 woman tipping hand: medium-light skin tone -1F481 1F3FD 200D 2640 FE0F ; fully-qualified # 💁🏽‍♀️ E4.0 woman tipping hand: medium skin tone -1F481 1F3FD 200D 2640 ; minimally-qualified # 💁🏽‍♀ E4.0 woman tipping hand: medium skin tone -1F481 1F3FE 200D 2640 FE0F ; fully-qualified # 💁🏾‍♀️ E4.0 woman tipping hand: medium-dark skin tone -1F481 1F3FE 200D 2640 ; minimally-qualified # 💁🏾‍♀ E4.0 woman tipping hand: medium-dark skin tone -1F481 1F3FF 200D 2640 FE0F ; fully-qualified # 💁🏿‍♀️ E4.0 woman tipping hand: dark skin tone -1F481 1F3FF 200D 2640 ; minimally-qualified # 💁🏿‍♀ E4.0 woman tipping hand: dark skin tone -1F64B ; fully-qualified # 🙋 E0.6 person raising hand -1F64B 1F3FB ; fully-qualified # 🙋🏻 E1.0 person raising hand: light skin tone -1F64B 1F3FC ; fully-qualified # 🙋🏼 E1.0 person raising hand: medium-light skin tone -1F64B 1F3FD ; fully-qualified # 🙋🏽 E1.0 person raising hand: medium skin tone -1F64B 1F3FE ; fully-qualified # 🙋🏾 E1.0 person raising hand: medium-dark skin tone -1F64B 1F3FF ; fully-qualified # 🙋🏿 E1.0 person raising hand: dark skin tone -1F64B 200D 2642 FE0F ; fully-qualified # 🙋‍♂️ E4.0 man raising hand -1F64B 200D 2642 ; minimally-qualified # 🙋‍♂ E4.0 man raising hand -1F64B 1F3FB 200D 2642 FE0F ; fully-qualified # 🙋🏻‍♂️ E4.0 man raising hand: light skin tone -1F64B 1F3FB 200D 2642 ; minimally-qualified # 🙋🏻‍♂ E4.0 man raising hand: light skin tone -1F64B 1F3FC 200D 2642 FE0F ; fully-qualified # 🙋🏼‍♂️ E4.0 man raising hand: medium-light skin tone -1F64B 1F3FC 200D 2642 ; minimally-qualified # 🙋🏼‍♂ E4.0 man raising hand: medium-light skin tone -1F64B 1F3FD 200D 2642 FE0F ; fully-qualified # 🙋🏽‍♂️ E4.0 man raising hand: medium skin tone -1F64B 1F3FD 200D 2642 ; minimally-qualified # 🙋🏽‍♂ E4.0 man raising hand: medium skin tone -1F64B 1F3FE 200D 2642 FE0F ; fully-qualified # 🙋🏾‍♂️ E4.0 man raising hand: medium-dark skin tone -1F64B 1F3FE 200D 2642 ; minimally-qualified # 🙋🏾‍♂ E4.0 man raising hand: medium-dark skin tone -1F64B 1F3FF 200D 2642 FE0F ; fully-qualified # 🙋🏿‍♂️ E4.0 man raising hand: dark skin tone -1F64B 1F3FF 200D 2642 ; minimally-qualified # 🙋🏿‍♂ E4.0 man raising hand: dark skin tone -1F64B 200D 2640 FE0F ; fully-qualified # 🙋‍♀️ E4.0 woman raising hand -1F64B 200D 2640 ; minimally-qualified # 🙋‍♀ E4.0 woman raising hand -1F64B 1F3FB 200D 2640 FE0F ; fully-qualified # 🙋🏻‍♀️ E4.0 woman raising hand: light skin tone -1F64B 1F3FB 200D 2640 ; minimally-qualified # 🙋🏻‍♀ E4.0 woman raising hand: light skin tone -1F64B 1F3FC 200D 2640 FE0F ; fully-qualified # 🙋🏼‍♀️ E4.0 woman raising hand: medium-light skin tone -1F64B 1F3FC 200D 2640 ; minimally-qualified # 🙋🏼‍♀ E4.0 woman raising hand: medium-light skin tone -1F64B 1F3FD 200D 2640 FE0F ; fully-qualified # 🙋🏽‍♀️ E4.0 woman raising hand: medium skin tone -1F64B 1F3FD 200D 2640 ; minimally-qualified # 🙋🏽‍♀ E4.0 woman raising hand: medium skin tone -1F64B 1F3FE 200D 2640 FE0F ; fully-qualified # 🙋🏾‍♀️ E4.0 woman raising hand: medium-dark skin tone -1F64B 1F3FE 200D 2640 ; minimally-qualified # 🙋🏾‍♀ E4.0 woman raising hand: medium-dark skin tone -1F64B 1F3FF 200D 2640 FE0F ; fully-qualified # 🙋🏿‍♀️ E4.0 woman raising hand: dark skin tone -1F64B 1F3FF 200D 2640 ; minimally-qualified # 🙋🏿‍♀ E4.0 woman raising hand: dark skin tone -1F9CF ; fully-qualified # 🧏 E12.0 deaf person -1F9CF 1F3FB ; fully-qualified # 🧏🏻 E12.0 deaf person: light skin tone -1F9CF 1F3FC ; fully-qualified # 🧏🏼 E12.0 deaf person: medium-light skin tone -1F9CF 1F3FD ; fully-qualified # 🧏🏽 E12.0 deaf person: medium skin tone -1F9CF 1F3FE ; fully-qualified # 🧏🏾 E12.0 deaf person: medium-dark skin tone -1F9CF 1F3FF ; fully-qualified # 🧏🏿 E12.0 deaf person: dark skin tone -1F9CF 200D 2642 FE0F ; fully-qualified # 🧏‍♂️ E12.0 deaf man -1F9CF 200D 2642 ; minimally-qualified # 🧏‍♂ E12.0 deaf man -1F9CF 1F3FB 200D 2642 FE0F ; fully-qualified # 🧏🏻‍♂️ E12.0 deaf man: light skin tone -1F9CF 1F3FB 200D 2642 ; minimally-qualified # 🧏🏻‍♂ E12.0 deaf man: light skin tone -1F9CF 1F3FC 200D 2642 FE0F ; fully-qualified # 🧏🏼‍♂️ E12.0 deaf man: medium-light skin tone -1F9CF 1F3FC 200D 2642 ; minimally-qualified # 🧏🏼‍♂ E12.0 deaf man: medium-light skin tone -1F9CF 1F3FD 200D 2642 FE0F ; fully-qualified # 🧏🏽‍♂️ E12.0 deaf man: medium skin tone -1F9CF 1F3FD 200D 2642 ; minimally-qualified # 🧏🏽‍♂ E12.0 deaf man: medium skin tone -1F9CF 1F3FE 200D 2642 FE0F ; fully-qualified # 🧏🏾‍♂️ E12.0 deaf man: medium-dark skin tone -1F9CF 1F3FE 200D 2642 ; minimally-qualified # 🧏🏾‍♂ E12.0 deaf man: medium-dark skin tone -1F9CF 1F3FF 200D 2642 FE0F ; fully-qualified # 🧏🏿‍♂️ E12.0 deaf man: dark skin tone -1F9CF 1F3FF 200D 2642 ; minimally-qualified # 🧏🏿‍♂ E12.0 deaf man: dark skin tone -1F9CF 200D 2640 FE0F ; fully-qualified # 🧏‍♀️ E12.0 deaf woman -1F9CF 200D 2640 ; minimally-qualified # 🧏‍♀ E12.0 deaf woman -1F9CF 1F3FB 200D 2640 FE0F ; fully-qualified # 🧏🏻‍♀️ E12.0 deaf woman: light skin tone -1F9CF 1F3FB 200D 2640 ; minimally-qualified # 🧏🏻‍♀ E12.0 deaf woman: light skin tone -1F9CF 1F3FC 200D 2640 FE0F ; fully-qualified # 🧏🏼‍♀️ E12.0 deaf woman: medium-light skin tone -1F9CF 1F3FC 200D 2640 ; minimally-qualified # 🧏🏼‍♀ E12.0 deaf woman: medium-light skin tone -1F9CF 1F3FD 200D 2640 FE0F ; fully-qualified # 🧏🏽‍♀️ E12.0 deaf woman: medium skin tone -1F9CF 1F3FD 200D 2640 ; minimally-qualified # 🧏🏽‍♀ E12.0 deaf woman: medium skin tone -1F9CF 1F3FE 200D 2640 FE0F ; fully-qualified # 🧏🏾‍♀️ E12.0 deaf woman: medium-dark skin tone -1F9CF 1F3FE 200D 2640 ; minimally-qualified # 🧏🏾‍♀ E12.0 deaf woman: medium-dark skin tone -1F9CF 1F3FF 200D 2640 FE0F ; fully-qualified # 🧏🏿‍♀️ E12.0 deaf woman: dark skin tone -1F9CF 1F3FF 200D 2640 ; minimally-qualified # 🧏🏿‍♀ E12.0 deaf woman: dark skin tone -1F647 ; fully-qualified # 🙇 E0.6 person bowing -1F647 1F3FB ; fully-qualified # 🙇🏻 E1.0 person bowing: light skin tone -1F647 1F3FC ; fully-qualified # 🙇🏼 E1.0 person bowing: medium-light skin tone -1F647 1F3FD ; fully-qualified # 🙇🏽 E1.0 person bowing: medium skin tone -1F647 1F3FE ; fully-qualified # 🙇🏾 E1.0 person bowing: medium-dark skin tone -1F647 1F3FF ; fully-qualified # 🙇🏿 E1.0 person bowing: dark skin tone -1F647 200D 2642 FE0F ; fully-qualified # 🙇‍♂️ E4.0 man bowing -1F647 200D 2642 ; minimally-qualified # 🙇‍♂ E4.0 man bowing -1F647 1F3FB 200D 2642 FE0F ; fully-qualified # 🙇🏻‍♂️ E4.0 man bowing: light skin tone -1F647 1F3FB 200D 2642 ; minimally-qualified # 🙇🏻‍♂ E4.0 man bowing: light skin tone -1F647 1F3FC 200D 2642 FE0F ; fully-qualified # 🙇🏼‍♂️ E4.0 man bowing: medium-light skin tone -1F647 1F3FC 200D 2642 ; minimally-qualified # 🙇🏼‍♂ E4.0 man bowing: medium-light skin tone -1F647 1F3FD 200D 2642 FE0F ; fully-qualified # 🙇🏽‍♂️ E4.0 man bowing: medium skin tone -1F647 1F3FD 200D 2642 ; minimally-qualified # 🙇🏽‍♂ E4.0 man bowing: medium skin tone -1F647 1F3FE 200D 2642 FE0F ; fully-qualified # 🙇🏾‍♂️ E4.0 man bowing: medium-dark skin tone -1F647 1F3FE 200D 2642 ; minimally-qualified # 🙇🏾‍♂ E4.0 man bowing: medium-dark skin tone -1F647 1F3FF 200D 2642 FE0F ; fully-qualified # 🙇🏿‍♂️ E4.0 man bowing: dark skin tone -1F647 1F3FF 200D 2642 ; minimally-qualified # 🙇🏿‍♂ E4.0 man bowing: dark skin tone -1F647 200D 2640 FE0F ; fully-qualified # 🙇‍♀️ E4.0 woman bowing -1F647 200D 2640 ; minimally-qualified # 🙇‍♀ E4.0 woman bowing -1F647 1F3FB 200D 2640 FE0F ; fully-qualified # 🙇🏻‍♀️ E4.0 woman bowing: light skin tone -1F647 1F3FB 200D 2640 ; minimally-qualified # 🙇🏻‍♀ E4.0 woman bowing: light skin tone -1F647 1F3FC 200D 2640 FE0F ; fully-qualified # 🙇🏼‍♀️ E4.0 woman bowing: medium-light skin tone -1F647 1F3FC 200D 2640 ; minimally-qualified # 🙇🏼‍♀ E4.0 woman bowing: medium-light skin tone -1F647 1F3FD 200D 2640 FE0F ; fully-qualified # 🙇🏽‍♀️ E4.0 woman bowing: medium skin tone -1F647 1F3FD 200D 2640 ; minimally-qualified # 🙇🏽‍♀ E4.0 woman bowing: medium skin tone -1F647 1F3FE 200D 2640 FE0F ; fully-qualified # 🙇🏾‍♀️ E4.0 woman bowing: medium-dark skin tone -1F647 1F3FE 200D 2640 ; minimally-qualified # 🙇🏾‍♀ E4.0 woman bowing: medium-dark skin tone -1F647 1F3FF 200D 2640 FE0F ; fully-qualified # 🙇🏿‍♀️ E4.0 woman bowing: dark skin tone -1F647 1F3FF 200D 2640 ; minimally-qualified # 🙇🏿‍♀ E4.0 woman bowing: dark skin tone -1F926 ; fully-qualified # 🤦 E3.0 person facepalming -1F926 1F3FB ; fully-qualified # 🤦🏻 E3.0 person facepalming: light skin tone -1F926 1F3FC ; fully-qualified # 🤦🏼 E3.0 person facepalming: medium-light skin tone -1F926 1F3FD ; fully-qualified # 🤦🏽 E3.0 person facepalming: medium skin tone -1F926 1F3FE ; fully-qualified # 🤦🏾 E3.0 person facepalming: medium-dark skin tone -1F926 1F3FF ; fully-qualified # 🤦🏿 E3.0 person facepalming: dark skin tone -1F926 200D 2642 FE0F ; fully-qualified # 🤦‍♂️ E4.0 man facepalming -1F926 200D 2642 ; minimally-qualified # 🤦‍♂ E4.0 man facepalming -1F926 1F3FB 200D 2642 FE0F ; fully-qualified # 🤦🏻‍♂️ E4.0 man facepalming: light skin tone -1F926 1F3FB 200D 2642 ; minimally-qualified # 🤦🏻‍♂ E4.0 man facepalming: light skin tone -1F926 1F3FC 200D 2642 FE0F ; fully-qualified # 🤦🏼‍♂️ E4.0 man facepalming: medium-light skin tone -1F926 1F3FC 200D 2642 ; minimally-qualified # 🤦🏼‍♂ E4.0 man facepalming: medium-light skin tone -1F926 1F3FD 200D 2642 FE0F ; fully-qualified # 🤦🏽‍♂️ E4.0 man facepalming: medium skin tone -1F926 1F3FD 200D 2642 ; minimally-qualified # 🤦🏽‍♂ E4.0 man facepalming: medium skin tone -1F926 1F3FE 200D 2642 FE0F ; fully-qualified # 🤦🏾‍♂️ E4.0 man facepalming: medium-dark skin tone -1F926 1F3FE 200D 2642 ; minimally-qualified # 🤦🏾‍♂ E4.0 man facepalming: medium-dark skin tone -1F926 1F3FF 200D 2642 FE0F ; fully-qualified # 🤦🏿‍♂️ E4.0 man facepalming: dark skin tone -1F926 1F3FF 200D 2642 ; minimally-qualified # 🤦🏿‍♂ E4.0 man facepalming: dark skin tone -1F926 200D 2640 FE0F ; fully-qualified # 🤦‍♀️ E4.0 woman facepalming -1F926 200D 2640 ; minimally-qualified # 🤦‍♀ E4.0 woman facepalming -1F926 1F3FB 200D 2640 FE0F ; fully-qualified # 🤦🏻‍♀️ E4.0 woman facepalming: light skin tone -1F926 1F3FB 200D 2640 ; minimally-qualified # 🤦🏻‍♀ E4.0 woman facepalming: light skin tone -1F926 1F3FC 200D 2640 FE0F ; fully-qualified # 🤦🏼‍♀️ E4.0 woman facepalming: medium-light skin tone -1F926 1F3FC 200D 2640 ; minimally-qualified # 🤦🏼‍♀ E4.0 woman facepalming: medium-light skin tone -1F926 1F3FD 200D 2640 FE0F ; fully-qualified # 🤦🏽‍♀️ E4.0 woman facepalming: medium skin tone -1F926 1F3FD 200D 2640 ; minimally-qualified # 🤦🏽‍♀ E4.0 woman facepalming: medium skin tone -1F926 1F3FE 200D 2640 FE0F ; fully-qualified # 🤦🏾‍♀️ E4.0 woman facepalming: medium-dark skin tone -1F926 1F3FE 200D 2640 ; minimally-qualified # 🤦🏾‍♀ E4.0 woman facepalming: medium-dark skin tone -1F926 1F3FF 200D 2640 FE0F ; fully-qualified # 🤦🏿‍♀️ E4.0 woman facepalming: dark skin tone -1F926 1F3FF 200D 2640 ; minimally-qualified # 🤦🏿‍♀ E4.0 woman facepalming: dark skin tone -1F937 ; fully-qualified # 🤷 E3.0 person shrugging -1F937 1F3FB ; fully-qualified # 🤷🏻 E3.0 person shrugging: light skin tone -1F937 1F3FC ; fully-qualified # 🤷🏼 E3.0 person shrugging: medium-light skin tone -1F937 1F3FD ; fully-qualified # 🤷🏽 E3.0 person shrugging: medium skin tone -1F937 1F3FE ; fully-qualified # 🤷🏾 E3.0 person shrugging: medium-dark skin tone -1F937 1F3FF ; fully-qualified # 🤷🏿 E3.0 person shrugging: dark skin tone -1F937 200D 2642 FE0F ; fully-qualified # 🤷‍♂️ E4.0 man shrugging -1F937 200D 2642 ; minimally-qualified # 🤷‍♂ E4.0 man shrugging -1F937 1F3FB 200D 2642 FE0F ; fully-qualified # 🤷🏻‍♂️ E4.0 man shrugging: light skin tone -1F937 1F3FB 200D 2642 ; minimally-qualified # 🤷🏻‍♂ E4.0 man shrugging: light skin tone -1F937 1F3FC 200D 2642 FE0F ; fully-qualified # 🤷🏼‍♂️ E4.0 man shrugging: medium-light skin tone -1F937 1F3FC 200D 2642 ; minimally-qualified # 🤷🏼‍♂ E4.0 man shrugging: medium-light skin tone -1F937 1F3FD 200D 2642 FE0F ; fully-qualified # 🤷🏽‍♂️ E4.0 man shrugging: medium skin tone -1F937 1F3FD 200D 2642 ; minimally-qualified # 🤷🏽‍♂ E4.0 man shrugging: medium skin tone -1F937 1F3FE 200D 2642 FE0F ; fully-qualified # 🤷🏾‍♂️ E4.0 man shrugging: medium-dark skin tone -1F937 1F3FE 200D 2642 ; minimally-qualified # 🤷🏾‍♂ E4.0 man shrugging: medium-dark skin tone -1F937 1F3FF 200D 2642 FE0F ; fully-qualified # 🤷🏿‍♂️ E4.0 man shrugging: dark skin tone -1F937 1F3FF 200D 2642 ; minimally-qualified # 🤷🏿‍♂ E4.0 man shrugging: dark skin tone -1F937 200D 2640 FE0F ; fully-qualified # 🤷‍♀️ E4.0 woman shrugging -1F937 200D 2640 ; minimally-qualified # 🤷‍♀ E4.0 woman shrugging -1F937 1F3FB 200D 2640 FE0F ; fully-qualified # 🤷🏻‍♀️ E4.0 woman shrugging: light skin tone -1F937 1F3FB 200D 2640 ; minimally-qualified # 🤷🏻‍♀ E4.0 woman shrugging: light skin tone -1F937 1F3FC 200D 2640 FE0F ; fully-qualified # 🤷🏼‍♀️ E4.0 woman shrugging: medium-light skin tone -1F937 1F3FC 200D 2640 ; minimally-qualified # 🤷🏼‍♀ E4.0 woman shrugging: medium-light skin tone -1F937 1F3FD 200D 2640 FE0F ; fully-qualified # 🤷🏽‍♀️ E4.0 woman shrugging: medium skin tone -1F937 1F3FD 200D 2640 ; minimally-qualified # 🤷🏽‍♀ E4.0 woman shrugging: medium skin tone -1F937 1F3FE 200D 2640 FE0F ; fully-qualified # 🤷🏾‍♀️ E4.0 woman shrugging: medium-dark skin tone -1F937 1F3FE 200D 2640 ; minimally-qualified # 🤷🏾‍♀ E4.0 woman shrugging: medium-dark skin tone -1F937 1F3FF 200D 2640 FE0F ; fully-qualified # 🤷🏿‍♀️ E4.0 woman shrugging: dark skin tone -1F937 1F3FF 200D 2640 ; minimally-qualified # 🤷🏿‍♀ E4.0 woman shrugging: dark skin tone - -# subgroup: person-role -1F9D1 200D 2695 FE0F ; fully-qualified # 🧑‍⚕️ E12.1 health worker -1F9D1 200D 2695 ; minimally-qualified # 🧑‍⚕ E12.1 health worker -1F9D1 1F3FB 200D 2695 FE0F ; fully-qualified # 🧑🏻‍⚕️ E12.1 health worker: light skin tone -1F9D1 1F3FB 200D 2695 ; minimally-qualified # 🧑🏻‍⚕ E12.1 health worker: light skin tone -1F9D1 1F3FC 200D 2695 FE0F ; fully-qualified # 🧑🏼‍⚕️ E12.1 health worker: medium-light skin tone -1F9D1 1F3FC 200D 2695 ; minimally-qualified # 🧑🏼‍⚕ E12.1 health worker: medium-light skin tone -1F9D1 1F3FD 200D 2695 FE0F ; fully-qualified # 🧑🏽‍⚕️ E12.1 health worker: medium skin tone -1F9D1 1F3FD 200D 2695 ; minimally-qualified # 🧑🏽‍⚕ E12.1 health worker: medium skin tone -1F9D1 1F3FE 200D 2695 FE0F ; fully-qualified # 🧑🏾‍⚕️ E12.1 health worker: medium-dark skin tone -1F9D1 1F3FE 200D 2695 ; minimally-qualified # 🧑🏾‍⚕ E12.1 health worker: medium-dark skin tone -1F9D1 1F3FF 200D 2695 FE0F ; fully-qualified # 🧑🏿‍⚕️ E12.1 health worker: dark skin tone -1F9D1 1F3FF 200D 2695 ; minimally-qualified # 🧑🏿‍⚕ E12.1 health worker: dark skin tone -1F468 200D 2695 FE0F ; fully-qualified # 👨‍⚕️ E4.0 man health worker -1F468 200D 2695 ; minimally-qualified # 👨‍⚕ E4.0 man health worker -1F468 1F3FB 200D 2695 FE0F ; fully-qualified # 👨🏻‍⚕️ E4.0 man health worker: light skin tone -1F468 1F3FB 200D 2695 ; minimally-qualified # 👨🏻‍⚕ E4.0 man health worker: light skin tone -1F468 1F3FC 200D 2695 FE0F ; fully-qualified # 👨🏼‍⚕️ E4.0 man health worker: medium-light skin tone -1F468 1F3FC 200D 2695 ; minimally-qualified # 👨🏼‍⚕ E4.0 man health worker: medium-light skin tone -1F468 1F3FD 200D 2695 FE0F ; fully-qualified # 👨🏽‍⚕️ E4.0 man health worker: medium skin tone -1F468 1F3FD 200D 2695 ; minimally-qualified # 👨🏽‍⚕ E4.0 man health worker: medium skin tone -1F468 1F3FE 200D 2695 FE0F ; fully-qualified # 👨🏾‍⚕️ E4.0 man health worker: medium-dark skin tone -1F468 1F3FE 200D 2695 ; minimally-qualified # 👨🏾‍⚕ E4.0 man health worker: medium-dark skin tone -1F468 1F3FF 200D 2695 FE0F ; fully-qualified # 👨🏿‍⚕️ E4.0 man health worker: dark skin tone -1F468 1F3FF 200D 2695 ; minimally-qualified # 👨🏿‍⚕ E4.0 man health worker: dark skin tone -1F469 200D 2695 FE0F ; fully-qualified # 👩‍⚕️ E4.0 woman health worker -1F469 200D 2695 ; minimally-qualified # 👩‍⚕ E4.0 woman health worker -1F469 1F3FB 200D 2695 FE0F ; fully-qualified # 👩🏻‍⚕️ E4.0 woman health worker: light skin tone -1F469 1F3FB 200D 2695 ; minimally-qualified # 👩🏻‍⚕ E4.0 woman health worker: light skin tone -1F469 1F3FC 200D 2695 FE0F ; fully-qualified # 👩🏼‍⚕️ E4.0 woman health worker: medium-light skin tone -1F469 1F3FC 200D 2695 ; minimally-qualified # 👩🏼‍⚕ E4.0 woman health worker: medium-light skin tone -1F469 1F3FD 200D 2695 FE0F ; fully-qualified # 👩🏽‍⚕️ E4.0 woman health worker: medium skin tone -1F469 1F3FD 200D 2695 ; minimally-qualified # 👩🏽‍⚕ E4.0 woman health worker: medium skin tone -1F469 1F3FE 200D 2695 FE0F ; fully-qualified # 👩🏾‍⚕️ E4.0 woman health worker: medium-dark skin tone -1F469 1F3FE 200D 2695 ; minimally-qualified # 👩🏾‍⚕ E4.0 woman health worker: medium-dark skin tone -1F469 1F3FF 200D 2695 FE0F ; fully-qualified # 👩🏿‍⚕️ E4.0 woman health worker: dark skin tone -1F469 1F3FF 200D 2695 ; minimally-qualified # 👩🏿‍⚕ E4.0 woman health worker: dark skin tone -1F9D1 200D 1F393 ; fully-qualified # 🧑‍🎓 E12.1 student -1F9D1 1F3FB 200D 1F393 ; fully-qualified # 🧑🏻‍🎓 E12.1 student: light skin tone -1F9D1 1F3FC 200D 1F393 ; fully-qualified # 🧑🏼‍🎓 E12.1 student: medium-light skin tone -1F9D1 1F3FD 200D 1F393 ; fully-qualified # 🧑🏽‍🎓 E12.1 student: medium skin tone -1F9D1 1F3FE 200D 1F393 ; fully-qualified # 🧑🏾‍🎓 E12.1 student: medium-dark skin tone -1F9D1 1F3FF 200D 1F393 ; fully-qualified # 🧑🏿‍🎓 E12.1 student: dark skin tone -1F468 200D 1F393 ; fully-qualified # 👨‍🎓 E4.0 man student -1F468 1F3FB 200D 1F393 ; fully-qualified # 👨🏻‍🎓 E4.0 man student: light skin tone -1F468 1F3FC 200D 1F393 ; fully-qualified # 👨🏼‍🎓 E4.0 man student: medium-light skin tone -1F468 1F3FD 200D 1F393 ; fully-qualified # 👨🏽‍🎓 E4.0 man student: medium skin tone -1F468 1F3FE 200D 1F393 ; fully-qualified # 👨🏾‍🎓 E4.0 man student: medium-dark skin tone -1F468 1F3FF 200D 1F393 ; fully-qualified # 👨🏿‍🎓 E4.0 man student: dark skin tone -1F469 200D 1F393 ; fully-qualified # 👩‍🎓 E4.0 woman student -1F469 1F3FB 200D 1F393 ; fully-qualified # 👩🏻‍🎓 E4.0 woman student: light skin tone -1F469 1F3FC 200D 1F393 ; fully-qualified # 👩🏼‍🎓 E4.0 woman student: medium-light skin tone -1F469 1F3FD 200D 1F393 ; fully-qualified # 👩🏽‍🎓 E4.0 woman student: medium skin tone -1F469 1F3FE 200D 1F393 ; fully-qualified # 👩🏾‍🎓 E4.0 woman student: medium-dark skin tone -1F469 1F3FF 200D 1F393 ; fully-qualified # 👩🏿‍🎓 E4.0 woman student: dark skin tone -1F9D1 200D 1F3EB ; fully-qualified # 🧑‍🏫 E12.1 teacher -1F9D1 1F3FB 200D 1F3EB ; fully-qualified # 🧑🏻‍🏫 E12.1 teacher: light skin tone -1F9D1 1F3FC 200D 1F3EB ; fully-qualified # 🧑🏼‍🏫 E12.1 teacher: medium-light skin tone -1F9D1 1F3FD 200D 1F3EB ; fully-qualified # 🧑🏽‍🏫 E12.1 teacher: medium skin tone -1F9D1 1F3FE 200D 1F3EB ; fully-qualified # 🧑🏾‍🏫 E12.1 teacher: medium-dark skin tone -1F9D1 1F3FF 200D 1F3EB ; fully-qualified # 🧑🏿‍🏫 E12.1 teacher: dark skin tone -1F468 200D 1F3EB ; fully-qualified # 👨‍🏫 E4.0 man teacher -1F468 1F3FB 200D 1F3EB ; fully-qualified # 👨🏻‍🏫 E4.0 man teacher: light skin tone -1F468 1F3FC 200D 1F3EB ; fully-qualified # 👨🏼‍🏫 E4.0 man teacher: medium-light skin tone -1F468 1F3FD 200D 1F3EB ; fully-qualified # 👨🏽‍🏫 E4.0 man teacher: medium skin tone -1F468 1F3FE 200D 1F3EB ; fully-qualified # 👨🏾‍🏫 E4.0 man teacher: medium-dark skin tone -1F468 1F3FF 200D 1F3EB ; fully-qualified # 👨🏿‍🏫 E4.0 man teacher: dark skin tone -1F469 200D 1F3EB ; fully-qualified # 👩‍🏫 E4.0 woman teacher -1F469 1F3FB 200D 1F3EB ; fully-qualified # 👩🏻‍🏫 E4.0 woman teacher: light skin tone -1F469 1F3FC 200D 1F3EB ; fully-qualified # 👩🏼‍🏫 E4.0 woman teacher: medium-light skin tone -1F469 1F3FD 200D 1F3EB ; fully-qualified # 👩🏽‍🏫 E4.0 woman teacher: medium skin tone -1F469 1F3FE 200D 1F3EB ; fully-qualified # 👩🏾‍🏫 E4.0 woman teacher: medium-dark skin tone -1F469 1F3FF 200D 1F3EB ; fully-qualified # 👩🏿‍🏫 E4.0 woman teacher: dark skin tone -1F9D1 200D 2696 FE0F ; fully-qualified # 🧑‍⚖️ E12.1 judge -1F9D1 200D 2696 ; minimally-qualified # 🧑‍⚖ E12.1 judge -1F9D1 1F3FB 200D 2696 FE0F ; fully-qualified # 🧑🏻‍⚖️ E12.1 judge: light skin tone -1F9D1 1F3FB 200D 2696 ; minimally-qualified # 🧑🏻‍⚖ E12.1 judge: light skin tone -1F9D1 1F3FC 200D 2696 FE0F ; fully-qualified # 🧑🏼‍⚖️ E12.1 judge: medium-light skin tone -1F9D1 1F3FC 200D 2696 ; minimally-qualified # 🧑🏼‍⚖ E12.1 judge: medium-light skin tone -1F9D1 1F3FD 200D 2696 FE0F ; fully-qualified # 🧑🏽‍⚖️ E12.1 judge: medium skin tone -1F9D1 1F3FD 200D 2696 ; minimally-qualified # 🧑🏽‍⚖ E12.1 judge: medium skin tone -1F9D1 1F3FE 200D 2696 FE0F ; fully-qualified # 🧑🏾‍⚖️ E12.1 judge: medium-dark skin tone -1F9D1 1F3FE 200D 2696 ; minimally-qualified # 🧑🏾‍⚖ E12.1 judge: medium-dark skin tone -1F9D1 1F3FF 200D 2696 FE0F ; fully-qualified # 🧑🏿‍⚖️ E12.1 judge: dark skin tone -1F9D1 1F3FF 200D 2696 ; minimally-qualified # 🧑🏿‍⚖ E12.1 judge: dark skin tone -1F468 200D 2696 FE0F ; fully-qualified # 👨‍⚖️ E4.0 man judge -1F468 200D 2696 ; minimally-qualified # 👨‍⚖ E4.0 man judge -1F468 1F3FB 200D 2696 FE0F ; fully-qualified # 👨🏻‍⚖️ E4.0 man judge: light skin tone -1F468 1F3FB 200D 2696 ; minimally-qualified # 👨🏻‍⚖ E4.0 man judge: light skin tone -1F468 1F3FC 200D 2696 FE0F ; fully-qualified # 👨🏼‍⚖️ E4.0 man judge: medium-light skin tone -1F468 1F3FC 200D 2696 ; minimally-qualified # 👨🏼‍⚖ E4.0 man judge: medium-light skin tone -1F468 1F3FD 200D 2696 FE0F ; fully-qualified # 👨🏽‍⚖️ E4.0 man judge: medium skin tone -1F468 1F3FD 200D 2696 ; minimally-qualified # 👨🏽‍⚖ E4.0 man judge: medium skin tone -1F468 1F3FE 200D 2696 FE0F ; fully-qualified # 👨🏾‍⚖️ E4.0 man judge: medium-dark skin tone -1F468 1F3FE 200D 2696 ; minimally-qualified # 👨🏾‍⚖ E4.0 man judge: medium-dark skin tone -1F468 1F3FF 200D 2696 FE0F ; fully-qualified # 👨🏿‍⚖️ E4.0 man judge: dark skin tone -1F468 1F3FF 200D 2696 ; minimally-qualified # 👨🏿‍⚖ E4.0 man judge: dark skin tone -1F469 200D 2696 FE0F ; fully-qualified # 👩‍⚖️ E4.0 woman judge -1F469 200D 2696 ; minimally-qualified # 👩‍⚖ E4.0 woman judge -1F469 1F3FB 200D 2696 FE0F ; fully-qualified # 👩🏻‍⚖️ E4.0 woman judge: light skin tone -1F469 1F3FB 200D 2696 ; minimally-qualified # 👩🏻‍⚖ E4.0 woman judge: light skin tone -1F469 1F3FC 200D 2696 FE0F ; fully-qualified # 👩🏼‍⚖️ E4.0 woman judge: medium-light skin tone -1F469 1F3FC 200D 2696 ; minimally-qualified # 👩🏼‍⚖ E4.0 woman judge: medium-light skin tone -1F469 1F3FD 200D 2696 FE0F ; fully-qualified # 👩🏽‍⚖️ E4.0 woman judge: medium skin tone -1F469 1F3FD 200D 2696 ; minimally-qualified # 👩🏽‍⚖ E4.0 woman judge: medium skin tone -1F469 1F3FE 200D 2696 FE0F ; fully-qualified # 👩🏾‍⚖️ E4.0 woman judge: medium-dark skin tone -1F469 1F3FE 200D 2696 ; minimally-qualified # 👩🏾‍⚖ E4.0 woman judge: medium-dark skin tone -1F469 1F3FF 200D 2696 FE0F ; fully-qualified # 👩🏿‍⚖️ E4.0 woman judge: dark skin tone -1F469 1F3FF 200D 2696 ; minimally-qualified # 👩🏿‍⚖ E4.0 woman judge: dark skin tone -1F9D1 200D 1F33E ; fully-qualified # 🧑‍🌾 E12.1 farmer -1F9D1 1F3FB 200D 1F33E ; fully-qualified # 🧑🏻‍🌾 E12.1 farmer: light skin tone -1F9D1 1F3FC 200D 1F33E ; fully-qualified # 🧑🏼‍🌾 E12.1 farmer: medium-light skin tone -1F9D1 1F3FD 200D 1F33E ; fully-qualified # 🧑🏽‍🌾 E12.1 farmer: medium skin tone -1F9D1 1F3FE 200D 1F33E ; fully-qualified # 🧑🏾‍🌾 E12.1 farmer: medium-dark skin tone -1F9D1 1F3FF 200D 1F33E ; fully-qualified # 🧑🏿‍🌾 E12.1 farmer: dark skin tone -1F468 200D 1F33E ; fully-qualified # 👨‍🌾 E4.0 man farmer -1F468 1F3FB 200D 1F33E ; fully-qualified # 👨🏻‍🌾 E4.0 man farmer: light skin tone -1F468 1F3FC 200D 1F33E ; fully-qualified # 👨🏼‍🌾 E4.0 man farmer: medium-light skin tone -1F468 1F3FD 200D 1F33E ; fully-qualified # 👨🏽‍🌾 E4.0 man farmer: medium skin tone -1F468 1F3FE 200D 1F33E ; fully-qualified # 👨🏾‍🌾 E4.0 man farmer: medium-dark skin tone -1F468 1F3FF 200D 1F33E ; fully-qualified # 👨🏿‍🌾 E4.0 man farmer: dark skin tone -1F469 200D 1F33E ; fully-qualified # 👩‍🌾 E4.0 woman farmer -1F469 1F3FB 200D 1F33E ; fully-qualified # 👩🏻‍🌾 E4.0 woman farmer: light skin tone -1F469 1F3FC 200D 1F33E ; fully-qualified # 👩🏼‍🌾 E4.0 woman farmer: medium-light skin tone -1F469 1F3FD 200D 1F33E ; fully-qualified # 👩🏽‍🌾 E4.0 woman farmer: medium skin tone -1F469 1F3FE 200D 1F33E ; fully-qualified # 👩🏾‍🌾 E4.0 woman farmer: medium-dark skin tone -1F469 1F3FF 200D 1F33E ; fully-qualified # 👩🏿‍🌾 E4.0 woman farmer: dark skin tone -1F9D1 200D 1F373 ; fully-qualified # 🧑‍🍳 E12.1 cook -1F9D1 1F3FB 200D 1F373 ; fully-qualified # 🧑🏻‍🍳 E12.1 cook: light skin tone -1F9D1 1F3FC 200D 1F373 ; fully-qualified # 🧑🏼‍🍳 E12.1 cook: medium-light skin tone -1F9D1 1F3FD 200D 1F373 ; fully-qualified # 🧑🏽‍🍳 E12.1 cook: medium skin tone -1F9D1 1F3FE 200D 1F373 ; fully-qualified # 🧑🏾‍🍳 E12.1 cook: medium-dark skin tone -1F9D1 1F3FF 200D 1F373 ; fully-qualified # 🧑🏿‍🍳 E12.1 cook: dark skin tone -1F468 200D 1F373 ; fully-qualified # 👨‍🍳 E4.0 man cook -1F468 1F3FB 200D 1F373 ; fully-qualified # 👨🏻‍🍳 E4.0 man cook: light skin tone -1F468 1F3FC 200D 1F373 ; fully-qualified # 👨🏼‍🍳 E4.0 man cook: medium-light skin tone -1F468 1F3FD 200D 1F373 ; fully-qualified # 👨🏽‍🍳 E4.0 man cook: medium skin tone -1F468 1F3FE 200D 1F373 ; fully-qualified # 👨🏾‍🍳 E4.0 man cook: medium-dark skin tone -1F468 1F3FF 200D 1F373 ; fully-qualified # 👨🏿‍🍳 E4.0 man cook: dark skin tone -1F469 200D 1F373 ; fully-qualified # 👩‍🍳 E4.0 woman cook -1F469 1F3FB 200D 1F373 ; fully-qualified # 👩🏻‍🍳 E4.0 woman cook: light skin tone -1F469 1F3FC 200D 1F373 ; fully-qualified # 👩🏼‍🍳 E4.0 woman cook: medium-light skin tone -1F469 1F3FD 200D 1F373 ; fully-qualified # 👩🏽‍🍳 E4.0 woman cook: medium skin tone -1F469 1F3FE 200D 1F373 ; fully-qualified # 👩🏾‍🍳 E4.0 woman cook: medium-dark skin tone -1F469 1F3FF 200D 1F373 ; fully-qualified # 👩🏿‍🍳 E4.0 woman cook: dark skin tone -1F9D1 200D 1F527 ; fully-qualified # 🧑‍🔧 E12.1 mechanic -1F9D1 1F3FB 200D 1F527 ; fully-qualified # 🧑🏻‍🔧 E12.1 mechanic: light skin tone -1F9D1 1F3FC 200D 1F527 ; fully-qualified # 🧑🏼‍🔧 E12.1 mechanic: medium-light skin tone -1F9D1 1F3FD 200D 1F527 ; fully-qualified # 🧑🏽‍🔧 E12.1 mechanic: medium skin tone -1F9D1 1F3FE 200D 1F527 ; fully-qualified # 🧑🏾‍🔧 E12.1 mechanic: medium-dark skin tone -1F9D1 1F3FF 200D 1F527 ; fully-qualified # 🧑🏿‍🔧 E12.1 mechanic: dark skin tone -1F468 200D 1F527 ; fully-qualified # 👨‍🔧 E4.0 man mechanic -1F468 1F3FB 200D 1F527 ; fully-qualified # 👨🏻‍🔧 E4.0 man mechanic: light skin tone -1F468 1F3FC 200D 1F527 ; fully-qualified # 👨🏼‍🔧 E4.0 man mechanic: medium-light skin tone -1F468 1F3FD 200D 1F527 ; fully-qualified # 👨🏽‍🔧 E4.0 man mechanic: medium skin tone -1F468 1F3FE 200D 1F527 ; fully-qualified # 👨🏾‍🔧 E4.0 man mechanic: medium-dark skin tone -1F468 1F3FF 200D 1F527 ; fully-qualified # 👨🏿‍🔧 E4.0 man mechanic: dark skin tone -1F469 200D 1F527 ; fully-qualified # 👩‍🔧 E4.0 woman mechanic -1F469 1F3FB 200D 1F527 ; fully-qualified # 👩🏻‍🔧 E4.0 woman mechanic: light skin tone -1F469 1F3FC 200D 1F527 ; fully-qualified # 👩🏼‍🔧 E4.0 woman mechanic: medium-light skin tone -1F469 1F3FD 200D 1F527 ; fully-qualified # 👩🏽‍🔧 E4.0 woman mechanic: medium skin tone -1F469 1F3FE 200D 1F527 ; fully-qualified # 👩🏾‍🔧 E4.0 woman mechanic: medium-dark skin tone -1F469 1F3FF 200D 1F527 ; fully-qualified # 👩🏿‍🔧 E4.0 woman mechanic: dark skin tone -1F9D1 200D 1F3ED ; fully-qualified # 🧑‍🏭 E12.1 factory worker -1F9D1 1F3FB 200D 1F3ED ; fully-qualified # 🧑🏻‍🏭 E12.1 factory worker: light skin tone -1F9D1 1F3FC 200D 1F3ED ; fully-qualified # 🧑🏼‍🏭 E12.1 factory worker: medium-light skin tone -1F9D1 1F3FD 200D 1F3ED ; fully-qualified # 🧑🏽‍🏭 E12.1 factory worker: medium skin tone -1F9D1 1F3FE 200D 1F3ED ; fully-qualified # 🧑🏾‍🏭 E12.1 factory worker: medium-dark skin tone -1F9D1 1F3FF 200D 1F3ED ; fully-qualified # 🧑🏿‍🏭 E12.1 factory worker: dark skin tone -1F468 200D 1F3ED ; fully-qualified # 👨‍🏭 E4.0 man factory worker -1F468 1F3FB 200D 1F3ED ; fully-qualified # 👨🏻‍🏭 E4.0 man factory worker: light skin tone -1F468 1F3FC 200D 1F3ED ; fully-qualified # 👨🏼‍🏭 E4.0 man factory worker: medium-light skin tone -1F468 1F3FD 200D 1F3ED ; fully-qualified # 👨🏽‍🏭 E4.0 man factory worker: medium skin tone -1F468 1F3FE 200D 1F3ED ; fully-qualified # 👨🏾‍🏭 E4.0 man factory worker: medium-dark skin tone -1F468 1F3FF 200D 1F3ED ; fully-qualified # 👨🏿‍🏭 E4.0 man factory worker: dark skin tone -1F469 200D 1F3ED ; fully-qualified # 👩‍🏭 E4.0 woman factory worker -1F469 1F3FB 200D 1F3ED ; fully-qualified # 👩🏻‍🏭 E4.0 woman factory worker: light skin tone -1F469 1F3FC 200D 1F3ED ; fully-qualified # 👩🏼‍🏭 E4.0 woman factory worker: medium-light skin tone -1F469 1F3FD 200D 1F3ED ; fully-qualified # 👩🏽‍🏭 E4.0 woman factory worker: medium skin tone -1F469 1F3FE 200D 1F3ED ; fully-qualified # 👩🏾‍🏭 E4.0 woman factory worker: medium-dark skin tone -1F469 1F3FF 200D 1F3ED ; fully-qualified # 👩🏿‍🏭 E4.0 woman factory worker: dark skin tone -1F9D1 200D 1F4BC ; fully-qualified # 🧑‍💼 E12.1 office worker -1F9D1 1F3FB 200D 1F4BC ; fully-qualified # 🧑🏻‍💼 E12.1 office worker: light skin tone -1F9D1 1F3FC 200D 1F4BC ; fully-qualified # 🧑🏼‍💼 E12.1 office worker: medium-light skin tone -1F9D1 1F3FD 200D 1F4BC ; fully-qualified # 🧑🏽‍💼 E12.1 office worker: medium skin tone -1F9D1 1F3FE 200D 1F4BC ; fully-qualified # 🧑🏾‍💼 E12.1 office worker: medium-dark skin tone -1F9D1 1F3FF 200D 1F4BC ; fully-qualified # 🧑🏿‍💼 E12.1 office worker: dark skin tone -1F468 200D 1F4BC ; fully-qualified # 👨‍💼 E4.0 man office worker -1F468 1F3FB 200D 1F4BC ; fully-qualified # 👨🏻‍💼 E4.0 man office worker: light skin tone -1F468 1F3FC 200D 1F4BC ; fully-qualified # 👨🏼‍💼 E4.0 man office worker: medium-light skin tone -1F468 1F3FD 200D 1F4BC ; fully-qualified # 👨🏽‍💼 E4.0 man office worker: medium skin tone -1F468 1F3FE 200D 1F4BC ; fully-qualified # 👨🏾‍💼 E4.0 man office worker: medium-dark skin tone -1F468 1F3FF 200D 1F4BC ; fully-qualified # 👨🏿‍💼 E4.0 man office worker: dark skin tone -1F469 200D 1F4BC ; fully-qualified # 👩‍💼 E4.0 woman office worker -1F469 1F3FB 200D 1F4BC ; fully-qualified # 👩🏻‍💼 E4.0 woman office worker: light skin tone -1F469 1F3FC 200D 1F4BC ; fully-qualified # 👩🏼‍💼 E4.0 woman office worker: medium-light skin tone -1F469 1F3FD 200D 1F4BC ; fully-qualified # 👩🏽‍💼 E4.0 woman office worker: medium skin tone -1F469 1F3FE 200D 1F4BC ; fully-qualified # 👩🏾‍💼 E4.0 woman office worker: medium-dark skin tone -1F469 1F3FF 200D 1F4BC ; fully-qualified # 👩🏿‍💼 E4.0 woman office worker: dark skin tone -1F9D1 200D 1F52C ; fully-qualified # 🧑‍🔬 E12.1 scientist -1F9D1 1F3FB 200D 1F52C ; fully-qualified # 🧑🏻‍🔬 E12.1 scientist: light skin tone -1F9D1 1F3FC 200D 1F52C ; fully-qualified # 🧑🏼‍🔬 E12.1 scientist: medium-light skin tone -1F9D1 1F3FD 200D 1F52C ; fully-qualified # 🧑🏽‍🔬 E12.1 scientist: medium skin tone -1F9D1 1F3FE 200D 1F52C ; fully-qualified # 🧑🏾‍🔬 E12.1 scientist: medium-dark skin tone -1F9D1 1F3FF 200D 1F52C ; fully-qualified # 🧑🏿‍🔬 E12.1 scientist: dark skin tone -1F468 200D 1F52C ; fully-qualified # 👨‍🔬 E4.0 man scientist -1F468 1F3FB 200D 1F52C ; fully-qualified # 👨🏻‍🔬 E4.0 man scientist: light skin tone -1F468 1F3FC 200D 1F52C ; fully-qualified # 👨🏼‍🔬 E4.0 man scientist: medium-light skin tone -1F468 1F3FD 200D 1F52C ; fully-qualified # 👨🏽‍🔬 E4.0 man scientist: medium skin tone -1F468 1F3FE 200D 1F52C ; fully-qualified # 👨🏾‍🔬 E4.0 man scientist: medium-dark skin tone -1F468 1F3FF 200D 1F52C ; fully-qualified # 👨🏿‍🔬 E4.0 man scientist: dark skin tone -1F469 200D 1F52C ; fully-qualified # 👩‍🔬 E4.0 woman scientist -1F469 1F3FB 200D 1F52C ; fully-qualified # 👩🏻‍🔬 E4.0 woman scientist: light skin tone -1F469 1F3FC 200D 1F52C ; fully-qualified # 👩🏼‍🔬 E4.0 woman scientist: medium-light skin tone -1F469 1F3FD 200D 1F52C ; fully-qualified # 👩🏽‍🔬 E4.0 woman scientist: medium skin tone -1F469 1F3FE 200D 1F52C ; fully-qualified # 👩🏾‍🔬 E4.0 woman scientist: medium-dark skin tone -1F469 1F3FF 200D 1F52C ; fully-qualified # 👩🏿‍🔬 E4.0 woman scientist: dark skin tone -1F9D1 200D 1F4BB ; fully-qualified # 🧑‍💻 E12.1 technologist -1F9D1 1F3FB 200D 1F4BB ; fully-qualified # 🧑🏻‍💻 E12.1 technologist: light skin tone -1F9D1 1F3FC 200D 1F4BB ; fully-qualified # 🧑🏼‍💻 E12.1 technologist: medium-light skin tone -1F9D1 1F3FD 200D 1F4BB ; fully-qualified # 🧑🏽‍💻 E12.1 technologist: medium skin tone -1F9D1 1F3FE 200D 1F4BB ; fully-qualified # 🧑🏾‍💻 E12.1 technologist: medium-dark skin tone -1F9D1 1F3FF 200D 1F4BB ; fully-qualified # 🧑🏿‍💻 E12.1 technologist: dark skin tone -1F468 200D 1F4BB ; fully-qualified # 👨‍💻 E4.0 man technologist -1F468 1F3FB 200D 1F4BB ; fully-qualified # 👨🏻‍💻 E4.0 man technologist: light skin tone -1F468 1F3FC 200D 1F4BB ; fully-qualified # 👨🏼‍💻 E4.0 man technologist: medium-light skin tone -1F468 1F3FD 200D 1F4BB ; fully-qualified # 👨🏽‍💻 E4.0 man technologist: medium skin tone -1F468 1F3FE 200D 1F4BB ; fully-qualified # 👨🏾‍💻 E4.0 man technologist: medium-dark skin tone -1F468 1F3FF 200D 1F4BB ; fully-qualified # 👨🏿‍💻 E4.0 man technologist: dark skin tone -1F469 200D 1F4BB ; fully-qualified # 👩‍💻 E4.0 woman technologist -1F469 1F3FB 200D 1F4BB ; fully-qualified # 👩🏻‍💻 E4.0 woman technologist: light skin tone -1F469 1F3FC 200D 1F4BB ; fully-qualified # 👩🏼‍💻 E4.0 woman technologist: medium-light skin tone -1F469 1F3FD 200D 1F4BB ; fully-qualified # 👩🏽‍💻 E4.0 woman technologist: medium skin tone -1F469 1F3FE 200D 1F4BB ; fully-qualified # 👩🏾‍💻 E4.0 woman technologist: medium-dark skin tone -1F469 1F3FF 200D 1F4BB ; fully-qualified # 👩🏿‍💻 E4.0 woman technologist: dark skin tone -1F9D1 200D 1F3A4 ; fully-qualified # 🧑‍🎤 E12.1 singer -1F9D1 1F3FB 200D 1F3A4 ; fully-qualified # 🧑🏻‍🎤 E12.1 singer: light skin tone -1F9D1 1F3FC 200D 1F3A4 ; fully-qualified # 🧑🏼‍🎤 E12.1 singer: medium-light skin tone -1F9D1 1F3FD 200D 1F3A4 ; fully-qualified # 🧑🏽‍🎤 E12.1 singer: medium skin tone -1F9D1 1F3FE 200D 1F3A4 ; fully-qualified # 🧑🏾‍🎤 E12.1 singer: medium-dark skin tone -1F9D1 1F3FF 200D 1F3A4 ; fully-qualified # 🧑🏿‍🎤 E12.1 singer: dark skin tone -1F468 200D 1F3A4 ; fully-qualified # 👨‍🎤 E4.0 man singer -1F468 1F3FB 200D 1F3A4 ; fully-qualified # 👨🏻‍🎤 E4.0 man singer: light skin tone -1F468 1F3FC 200D 1F3A4 ; fully-qualified # 👨🏼‍🎤 E4.0 man singer: medium-light skin tone -1F468 1F3FD 200D 1F3A4 ; fully-qualified # 👨🏽‍🎤 E4.0 man singer: medium skin tone -1F468 1F3FE 200D 1F3A4 ; fully-qualified # 👨🏾‍🎤 E4.0 man singer: medium-dark skin tone -1F468 1F3FF 200D 1F3A4 ; fully-qualified # 👨🏿‍🎤 E4.0 man singer: dark skin tone -1F469 200D 1F3A4 ; fully-qualified # 👩‍🎤 E4.0 woman singer -1F469 1F3FB 200D 1F3A4 ; fully-qualified # 👩🏻‍🎤 E4.0 woman singer: light skin tone -1F469 1F3FC 200D 1F3A4 ; fully-qualified # 👩🏼‍🎤 E4.0 woman singer: medium-light skin tone -1F469 1F3FD 200D 1F3A4 ; fully-qualified # 👩🏽‍🎤 E4.0 woman singer: medium skin tone -1F469 1F3FE 200D 1F3A4 ; fully-qualified # 👩🏾‍🎤 E4.0 woman singer: medium-dark skin tone -1F469 1F3FF 200D 1F3A4 ; fully-qualified # 👩🏿‍🎤 E4.0 woman singer: dark skin tone -1F9D1 200D 1F3A8 ; fully-qualified # 🧑‍🎨 E12.1 artist -1F9D1 1F3FB 200D 1F3A8 ; fully-qualified # 🧑🏻‍🎨 E12.1 artist: light skin tone -1F9D1 1F3FC 200D 1F3A8 ; fully-qualified # 🧑🏼‍🎨 E12.1 artist: medium-light skin tone -1F9D1 1F3FD 200D 1F3A8 ; fully-qualified # 🧑🏽‍🎨 E12.1 artist: medium skin tone -1F9D1 1F3FE 200D 1F3A8 ; fully-qualified # 🧑🏾‍🎨 E12.1 artist: medium-dark skin tone -1F9D1 1F3FF 200D 1F3A8 ; fully-qualified # 🧑🏿‍🎨 E12.1 artist: dark skin tone -1F468 200D 1F3A8 ; fully-qualified # 👨‍🎨 E4.0 man artist -1F468 1F3FB 200D 1F3A8 ; fully-qualified # 👨🏻‍🎨 E4.0 man artist: light skin tone -1F468 1F3FC 200D 1F3A8 ; fully-qualified # 👨🏼‍🎨 E4.0 man artist: medium-light skin tone -1F468 1F3FD 200D 1F3A8 ; fully-qualified # 👨🏽‍🎨 E4.0 man artist: medium skin tone -1F468 1F3FE 200D 1F3A8 ; fully-qualified # 👨🏾‍🎨 E4.0 man artist: medium-dark skin tone -1F468 1F3FF 200D 1F3A8 ; fully-qualified # 👨🏿‍🎨 E4.0 man artist: dark skin tone -1F469 200D 1F3A8 ; fully-qualified # 👩‍🎨 E4.0 woman artist -1F469 1F3FB 200D 1F3A8 ; fully-qualified # 👩🏻‍🎨 E4.0 woman artist: light skin tone -1F469 1F3FC 200D 1F3A8 ; fully-qualified # 👩🏼‍🎨 E4.0 woman artist: medium-light skin tone -1F469 1F3FD 200D 1F3A8 ; fully-qualified # 👩🏽‍🎨 E4.0 woman artist: medium skin tone -1F469 1F3FE 200D 1F3A8 ; fully-qualified # 👩🏾‍🎨 E4.0 woman artist: medium-dark skin tone -1F469 1F3FF 200D 1F3A8 ; fully-qualified # 👩🏿‍🎨 E4.0 woman artist: dark skin tone -1F9D1 200D 2708 FE0F ; fully-qualified # 🧑‍✈️ E12.1 pilot -1F9D1 200D 2708 ; minimally-qualified # 🧑‍✈ E12.1 pilot -1F9D1 1F3FB 200D 2708 FE0F ; fully-qualified # 🧑🏻‍✈️ E12.1 pilot: light skin tone -1F9D1 1F3FB 200D 2708 ; minimally-qualified # 🧑🏻‍✈ E12.1 pilot: light skin tone -1F9D1 1F3FC 200D 2708 FE0F ; fully-qualified # 🧑🏼‍✈️ E12.1 pilot: medium-light skin tone -1F9D1 1F3FC 200D 2708 ; minimally-qualified # 🧑🏼‍✈ E12.1 pilot: medium-light skin tone -1F9D1 1F3FD 200D 2708 FE0F ; fully-qualified # 🧑🏽‍✈️ E12.1 pilot: medium skin tone -1F9D1 1F3FD 200D 2708 ; minimally-qualified # 🧑🏽‍✈ E12.1 pilot: medium skin tone -1F9D1 1F3FE 200D 2708 FE0F ; fully-qualified # 🧑🏾‍✈️ E12.1 pilot: medium-dark skin tone -1F9D1 1F3FE 200D 2708 ; minimally-qualified # 🧑🏾‍✈ E12.1 pilot: medium-dark skin tone -1F9D1 1F3FF 200D 2708 FE0F ; fully-qualified # 🧑🏿‍✈️ E12.1 pilot: dark skin tone -1F9D1 1F3FF 200D 2708 ; minimally-qualified # 🧑🏿‍✈ E12.1 pilot: dark skin tone -1F468 200D 2708 FE0F ; fully-qualified # 👨‍✈️ E4.0 man pilot -1F468 200D 2708 ; minimally-qualified # 👨‍✈ E4.0 man pilot -1F468 1F3FB 200D 2708 FE0F ; fully-qualified # 👨🏻‍✈️ E4.0 man pilot: light skin tone -1F468 1F3FB 200D 2708 ; minimally-qualified # 👨🏻‍✈ E4.0 man pilot: light skin tone -1F468 1F3FC 200D 2708 FE0F ; fully-qualified # 👨🏼‍✈️ E4.0 man pilot: medium-light skin tone -1F468 1F3FC 200D 2708 ; minimally-qualified # 👨🏼‍✈ E4.0 man pilot: medium-light skin tone -1F468 1F3FD 200D 2708 FE0F ; fully-qualified # 👨🏽‍✈️ E4.0 man pilot: medium skin tone -1F468 1F3FD 200D 2708 ; minimally-qualified # 👨🏽‍✈ E4.0 man pilot: medium skin tone -1F468 1F3FE 200D 2708 FE0F ; fully-qualified # 👨🏾‍✈️ E4.0 man pilot: medium-dark skin tone -1F468 1F3FE 200D 2708 ; minimally-qualified # 👨🏾‍✈ E4.0 man pilot: medium-dark skin tone -1F468 1F3FF 200D 2708 FE0F ; fully-qualified # 👨🏿‍✈️ E4.0 man pilot: dark skin tone -1F468 1F3FF 200D 2708 ; minimally-qualified # 👨🏿‍✈ E4.0 man pilot: dark skin tone -1F469 200D 2708 FE0F ; fully-qualified # 👩‍✈️ E4.0 woman pilot -1F469 200D 2708 ; minimally-qualified # 👩‍✈ E4.0 woman pilot -1F469 1F3FB 200D 2708 FE0F ; fully-qualified # 👩🏻‍✈️ E4.0 woman pilot: light skin tone -1F469 1F3FB 200D 2708 ; minimally-qualified # 👩🏻‍✈ E4.0 woman pilot: light skin tone -1F469 1F3FC 200D 2708 FE0F ; fully-qualified # 👩🏼‍✈️ E4.0 woman pilot: medium-light skin tone -1F469 1F3FC 200D 2708 ; minimally-qualified # 👩🏼‍✈ E4.0 woman pilot: medium-light skin tone -1F469 1F3FD 200D 2708 FE0F ; fully-qualified # 👩🏽‍✈️ E4.0 woman pilot: medium skin tone -1F469 1F3FD 200D 2708 ; minimally-qualified # 👩🏽‍✈ E4.0 woman pilot: medium skin tone -1F469 1F3FE 200D 2708 FE0F ; fully-qualified # 👩🏾‍✈️ E4.0 woman pilot: medium-dark skin tone -1F469 1F3FE 200D 2708 ; minimally-qualified # 👩🏾‍✈ E4.0 woman pilot: medium-dark skin tone -1F469 1F3FF 200D 2708 FE0F ; fully-qualified # 👩🏿‍✈️ E4.0 woman pilot: dark skin tone -1F469 1F3FF 200D 2708 ; minimally-qualified # 👩🏿‍✈ E4.0 woman pilot: dark skin tone -1F9D1 200D 1F680 ; fully-qualified # 🧑‍🚀 E12.1 astronaut -1F9D1 1F3FB 200D 1F680 ; fully-qualified # 🧑🏻‍🚀 E12.1 astronaut: light skin tone -1F9D1 1F3FC 200D 1F680 ; fully-qualified # 🧑🏼‍🚀 E12.1 astronaut: medium-light skin tone -1F9D1 1F3FD 200D 1F680 ; fully-qualified # 🧑🏽‍🚀 E12.1 astronaut: medium skin tone -1F9D1 1F3FE 200D 1F680 ; fully-qualified # 🧑🏾‍🚀 E12.1 astronaut: medium-dark skin tone -1F9D1 1F3FF 200D 1F680 ; fully-qualified # 🧑🏿‍🚀 E12.1 astronaut: dark skin tone -1F468 200D 1F680 ; fully-qualified # 👨‍🚀 E4.0 man astronaut -1F468 1F3FB 200D 1F680 ; fully-qualified # 👨🏻‍🚀 E4.0 man astronaut: light skin tone -1F468 1F3FC 200D 1F680 ; fully-qualified # 👨🏼‍🚀 E4.0 man astronaut: medium-light skin tone -1F468 1F3FD 200D 1F680 ; fully-qualified # 👨🏽‍🚀 E4.0 man astronaut: medium skin tone -1F468 1F3FE 200D 1F680 ; fully-qualified # 👨🏾‍🚀 E4.0 man astronaut: medium-dark skin tone -1F468 1F3FF 200D 1F680 ; fully-qualified # 👨🏿‍🚀 E4.0 man astronaut: dark skin tone -1F469 200D 1F680 ; fully-qualified # 👩‍🚀 E4.0 woman astronaut -1F469 1F3FB 200D 1F680 ; fully-qualified # 👩🏻‍🚀 E4.0 woman astronaut: light skin tone -1F469 1F3FC 200D 1F680 ; fully-qualified # 👩🏼‍🚀 E4.0 woman astronaut: medium-light skin tone -1F469 1F3FD 200D 1F680 ; fully-qualified # 👩🏽‍🚀 E4.0 woman astronaut: medium skin tone -1F469 1F3FE 200D 1F680 ; fully-qualified # 👩🏾‍🚀 E4.0 woman astronaut: medium-dark skin tone -1F469 1F3FF 200D 1F680 ; fully-qualified # 👩🏿‍🚀 E4.0 woman astronaut: dark skin tone -1F9D1 200D 1F692 ; fully-qualified # 🧑‍🚒 E12.1 firefighter -1F9D1 1F3FB 200D 1F692 ; fully-qualified # 🧑🏻‍🚒 E12.1 firefighter: light skin tone -1F9D1 1F3FC 200D 1F692 ; fully-qualified # 🧑🏼‍🚒 E12.1 firefighter: medium-light skin tone -1F9D1 1F3FD 200D 1F692 ; fully-qualified # 🧑🏽‍🚒 E12.1 firefighter: medium skin tone -1F9D1 1F3FE 200D 1F692 ; fully-qualified # 🧑🏾‍🚒 E12.1 firefighter: medium-dark skin tone -1F9D1 1F3FF 200D 1F692 ; fully-qualified # 🧑🏿‍🚒 E12.1 firefighter: dark skin tone -1F468 200D 1F692 ; fully-qualified # 👨‍🚒 E4.0 man firefighter -1F468 1F3FB 200D 1F692 ; fully-qualified # 👨🏻‍🚒 E4.0 man firefighter: light skin tone -1F468 1F3FC 200D 1F692 ; fully-qualified # 👨🏼‍🚒 E4.0 man firefighter: medium-light skin tone -1F468 1F3FD 200D 1F692 ; fully-qualified # 👨🏽‍🚒 E4.0 man firefighter: medium skin tone -1F468 1F3FE 200D 1F692 ; fully-qualified # 👨🏾‍🚒 E4.0 man firefighter: medium-dark skin tone -1F468 1F3FF 200D 1F692 ; fully-qualified # 👨🏿‍🚒 E4.0 man firefighter: dark skin tone -1F469 200D 1F692 ; fully-qualified # 👩‍🚒 E4.0 woman firefighter -1F469 1F3FB 200D 1F692 ; fully-qualified # 👩🏻‍🚒 E4.0 woman firefighter: light skin tone -1F469 1F3FC 200D 1F692 ; fully-qualified # 👩🏼‍🚒 E4.0 woman firefighter: medium-light skin tone -1F469 1F3FD 200D 1F692 ; fully-qualified # 👩🏽‍🚒 E4.0 woman firefighter: medium skin tone -1F469 1F3FE 200D 1F692 ; fully-qualified # 👩🏾‍🚒 E4.0 woman firefighter: medium-dark skin tone -1F469 1F3FF 200D 1F692 ; fully-qualified # 👩🏿‍🚒 E4.0 woman firefighter: dark skin tone -1F46E ; fully-qualified # 👮 E0.6 police officer -1F46E 1F3FB ; fully-qualified # 👮🏻 E1.0 police officer: light skin tone -1F46E 1F3FC ; fully-qualified # 👮🏼 E1.0 police officer: medium-light skin tone -1F46E 1F3FD ; fully-qualified # 👮🏽 E1.0 police officer: medium skin tone -1F46E 1F3FE ; fully-qualified # 👮🏾 E1.0 police officer: medium-dark skin tone -1F46E 1F3FF ; fully-qualified # 👮🏿 E1.0 police officer: dark skin tone -1F46E 200D 2642 FE0F ; fully-qualified # 👮‍♂️ E4.0 man police officer -1F46E 200D 2642 ; minimally-qualified # 👮‍♂ E4.0 man police officer -1F46E 1F3FB 200D 2642 FE0F ; fully-qualified # 👮🏻‍♂️ E4.0 man police officer: light skin tone -1F46E 1F3FB 200D 2642 ; minimally-qualified # 👮🏻‍♂ E4.0 man police officer: light skin tone -1F46E 1F3FC 200D 2642 FE0F ; fully-qualified # 👮🏼‍♂️ E4.0 man police officer: medium-light skin tone -1F46E 1F3FC 200D 2642 ; minimally-qualified # 👮🏼‍♂ E4.0 man police officer: medium-light skin tone -1F46E 1F3FD 200D 2642 FE0F ; fully-qualified # 👮🏽‍♂️ E4.0 man police officer: medium skin tone -1F46E 1F3FD 200D 2642 ; minimally-qualified # 👮🏽‍♂ E4.0 man police officer: medium skin tone -1F46E 1F3FE 200D 2642 FE0F ; fully-qualified # 👮🏾‍♂️ E4.0 man police officer: medium-dark skin tone -1F46E 1F3FE 200D 2642 ; minimally-qualified # 👮🏾‍♂ E4.0 man police officer: medium-dark skin tone -1F46E 1F3FF 200D 2642 FE0F ; fully-qualified # 👮🏿‍♂️ E4.0 man police officer: dark skin tone -1F46E 1F3FF 200D 2642 ; minimally-qualified # 👮🏿‍♂ E4.0 man police officer: dark skin tone -1F46E 200D 2640 FE0F ; fully-qualified # 👮‍♀️ E4.0 woman police officer -1F46E 200D 2640 ; minimally-qualified # 👮‍♀ E4.0 woman police officer -1F46E 1F3FB 200D 2640 FE0F ; fully-qualified # 👮🏻‍♀️ E4.0 woman police officer: light skin tone -1F46E 1F3FB 200D 2640 ; minimally-qualified # 👮🏻‍♀ E4.0 woman police officer: light skin tone -1F46E 1F3FC 200D 2640 FE0F ; fully-qualified # 👮🏼‍♀️ E4.0 woman police officer: medium-light skin tone -1F46E 1F3FC 200D 2640 ; minimally-qualified # 👮🏼‍♀ E4.0 woman police officer: medium-light skin tone -1F46E 1F3FD 200D 2640 FE0F ; fully-qualified # 👮🏽‍♀️ E4.0 woman police officer: medium skin tone -1F46E 1F3FD 200D 2640 ; minimally-qualified # 👮🏽‍♀ E4.0 woman police officer: medium skin tone -1F46E 1F3FE 200D 2640 FE0F ; fully-qualified # 👮🏾‍♀️ E4.0 woman police officer: medium-dark skin tone -1F46E 1F3FE 200D 2640 ; minimally-qualified # 👮🏾‍♀ E4.0 woman police officer: medium-dark skin tone -1F46E 1F3FF 200D 2640 FE0F ; fully-qualified # 👮🏿‍♀️ E4.0 woman police officer: dark skin tone -1F46E 1F3FF 200D 2640 ; minimally-qualified # 👮🏿‍♀ E4.0 woman police officer: dark skin tone -1F575 FE0F ; fully-qualified # 🕵️ E0.7 detective -1F575 ; unqualified # 🕵 E0.7 detective -1F575 1F3FB ; fully-qualified # 🕵🏻 E2.0 detective: light skin tone -1F575 1F3FC ; fully-qualified # 🕵🏼 E2.0 detective: medium-light skin tone -1F575 1F3FD ; fully-qualified # 🕵🏽 E2.0 detective: medium skin tone -1F575 1F3FE ; fully-qualified # 🕵🏾 E2.0 detective: medium-dark skin tone -1F575 1F3FF ; fully-qualified # 🕵🏿 E2.0 detective: dark skin tone -1F575 FE0F 200D 2642 FE0F ; fully-qualified # 🕵️‍♂️ E4.0 man detective -1F575 200D 2642 FE0F ; unqualified # 🕵‍♂️ E4.0 man detective -1F575 FE0F 200D 2642 ; minimally-qualified # 🕵️‍♂ E4.0 man detective -1F575 200D 2642 ; unqualified # 🕵‍♂ E4.0 man detective -1F575 1F3FB 200D 2642 FE0F ; fully-qualified # 🕵🏻‍♂️ E4.0 man detective: light skin tone -1F575 1F3FB 200D 2642 ; minimally-qualified # 🕵🏻‍♂ E4.0 man detective: light skin tone -1F575 1F3FC 200D 2642 FE0F ; fully-qualified # 🕵🏼‍♂️ E4.0 man detective: medium-light skin tone -1F575 1F3FC 200D 2642 ; minimally-qualified # 🕵🏼‍♂ E4.0 man detective: medium-light skin tone -1F575 1F3FD 200D 2642 FE0F ; fully-qualified # 🕵🏽‍♂️ E4.0 man detective: medium skin tone -1F575 1F3FD 200D 2642 ; minimally-qualified # 🕵🏽‍♂ E4.0 man detective: medium skin tone -1F575 1F3FE 200D 2642 FE0F ; fully-qualified # 🕵🏾‍♂️ E4.0 man detective: medium-dark skin tone -1F575 1F3FE 200D 2642 ; minimally-qualified # 🕵🏾‍♂ E4.0 man detective: medium-dark skin tone -1F575 1F3FF 200D 2642 FE0F ; fully-qualified # 🕵🏿‍♂️ E4.0 man detective: dark skin tone -1F575 1F3FF 200D 2642 ; minimally-qualified # 🕵🏿‍♂ E4.0 man detective: dark skin tone -1F575 FE0F 200D 2640 FE0F ; fully-qualified # 🕵️‍♀️ E4.0 woman detective -1F575 200D 2640 FE0F ; unqualified # 🕵‍♀️ E4.0 woman detective -1F575 FE0F 200D 2640 ; minimally-qualified # 🕵️‍♀ E4.0 woman detective -1F575 200D 2640 ; unqualified # 🕵‍♀ E4.0 woman detective -1F575 1F3FB 200D 2640 FE0F ; fully-qualified # 🕵🏻‍♀️ E4.0 woman detective: light skin tone -1F575 1F3FB 200D 2640 ; minimally-qualified # 🕵🏻‍♀ E4.0 woman detective: light skin tone -1F575 1F3FC 200D 2640 FE0F ; fully-qualified # 🕵🏼‍♀️ E4.0 woman detective: medium-light skin tone -1F575 1F3FC 200D 2640 ; minimally-qualified # 🕵🏼‍♀ E4.0 woman detective: medium-light skin tone -1F575 1F3FD 200D 2640 FE0F ; fully-qualified # 🕵🏽‍♀️ E4.0 woman detective: medium skin tone -1F575 1F3FD 200D 2640 ; minimally-qualified # 🕵🏽‍♀ E4.0 woman detective: medium skin tone -1F575 1F3FE 200D 2640 FE0F ; fully-qualified # 🕵🏾‍♀️ E4.0 woman detective: medium-dark skin tone -1F575 1F3FE 200D 2640 ; minimally-qualified # 🕵🏾‍♀ E4.0 woman detective: medium-dark skin tone -1F575 1F3FF 200D 2640 FE0F ; fully-qualified # 🕵🏿‍♀️ E4.0 woman detective: dark skin tone -1F575 1F3FF 200D 2640 ; minimally-qualified # 🕵🏿‍♀ E4.0 woman detective: dark skin tone -1F482 ; fully-qualified # 💂 E0.6 guard -1F482 1F3FB ; fully-qualified # 💂🏻 E1.0 guard: light skin tone -1F482 1F3FC ; fully-qualified # 💂🏼 E1.0 guard: medium-light skin tone -1F482 1F3FD ; fully-qualified # 💂🏽 E1.0 guard: medium skin tone -1F482 1F3FE ; fully-qualified # 💂🏾 E1.0 guard: medium-dark skin tone -1F482 1F3FF ; fully-qualified # 💂🏿 E1.0 guard: dark skin tone -1F482 200D 2642 FE0F ; fully-qualified # 💂‍♂️ E4.0 man guard -1F482 200D 2642 ; minimally-qualified # 💂‍♂ E4.0 man guard -1F482 1F3FB 200D 2642 FE0F ; fully-qualified # 💂🏻‍♂️ E4.0 man guard: light skin tone -1F482 1F3FB 200D 2642 ; minimally-qualified # 💂🏻‍♂ E4.0 man guard: light skin tone -1F482 1F3FC 200D 2642 FE0F ; fully-qualified # 💂🏼‍♂️ E4.0 man guard: medium-light skin tone -1F482 1F3FC 200D 2642 ; minimally-qualified # 💂🏼‍♂ E4.0 man guard: medium-light skin tone -1F482 1F3FD 200D 2642 FE0F ; fully-qualified # 💂🏽‍♂️ E4.0 man guard: medium skin tone -1F482 1F3FD 200D 2642 ; minimally-qualified # 💂🏽‍♂ E4.0 man guard: medium skin tone -1F482 1F3FE 200D 2642 FE0F ; fully-qualified # 💂🏾‍♂️ E4.0 man guard: medium-dark skin tone -1F482 1F3FE 200D 2642 ; minimally-qualified # 💂🏾‍♂ E4.0 man guard: medium-dark skin tone -1F482 1F3FF 200D 2642 FE0F ; fully-qualified # 💂🏿‍♂️ E4.0 man guard: dark skin tone -1F482 1F3FF 200D 2642 ; minimally-qualified # 💂🏿‍♂ E4.0 man guard: dark skin tone -1F482 200D 2640 FE0F ; fully-qualified # 💂‍♀️ E4.0 woman guard -1F482 200D 2640 ; minimally-qualified # 💂‍♀ E4.0 woman guard -1F482 1F3FB 200D 2640 FE0F ; fully-qualified # 💂🏻‍♀️ E4.0 woman guard: light skin tone -1F482 1F3FB 200D 2640 ; minimally-qualified # 💂🏻‍♀ E4.0 woman guard: light skin tone -1F482 1F3FC 200D 2640 FE0F ; fully-qualified # 💂🏼‍♀️ E4.0 woman guard: medium-light skin tone -1F482 1F3FC 200D 2640 ; minimally-qualified # 💂🏼‍♀ E4.0 woman guard: medium-light skin tone -1F482 1F3FD 200D 2640 FE0F ; fully-qualified # 💂🏽‍♀️ E4.0 woman guard: medium skin tone -1F482 1F3FD 200D 2640 ; minimally-qualified # 💂🏽‍♀ E4.0 woman guard: medium skin tone -1F482 1F3FE 200D 2640 FE0F ; fully-qualified # 💂🏾‍♀️ E4.0 woman guard: medium-dark skin tone -1F482 1F3FE 200D 2640 ; minimally-qualified # 💂🏾‍♀ E4.0 woman guard: medium-dark skin tone -1F482 1F3FF 200D 2640 FE0F ; fully-qualified # 💂🏿‍♀️ E4.0 woman guard: dark skin tone -1F482 1F3FF 200D 2640 ; minimally-qualified # 💂🏿‍♀ E4.0 woman guard: dark skin tone -1F977 ; fully-qualified # 🥷 E13.0 ninja -1F977 1F3FB ; fully-qualified # 🥷🏻 E13.0 ninja: light skin tone -1F977 1F3FC ; fully-qualified # 🥷🏼 E13.0 ninja: medium-light skin tone -1F977 1F3FD ; fully-qualified # 🥷🏽 E13.0 ninja: medium skin tone -1F977 1F3FE ; fully-qualified # 🥷🏾 E13.0 ninja: medium-dark skin tone -1F977 1F3FF ; fully-qualified # 🥷🏿 E13.0 ninja: dark skin tone -1F477 ; fully-qualified # 👷 E0.6 construction worker -1F477 1F3FB ; fully-qualified # 👷🏻 E1.0 construction worker: light skin tone -1F477 1F3FC ; fully-qualified # 👷🏼 E1.0 construction worker: medium-light skin tone -1F477 1F3FD ; fully-qualified # 👷🏽 E1.0 construction worker: medium skin tone -1F477 1F3FE ; fully-qualified # 👷🏾 E1.0 construction worker: medium-dark skin tone -1F477 1F3FF ; fully-qualified # 👷🏿 E1.0 construction worker: dark skin tone -1F477 200D 2642 FE0F ; fully-qualified # 👷‍♂️ E4.0 man construction worker -1F477 200D 2642 ; minimally-qualified # 👷‍♂ E4.0 man construction worker -1F477 1F3FB 200D 2642 FE0F ; fully-qualified # 👷🏻‍♂️ E4.0 man construction worker: light skin tone -1F477 1F3FB 200D 2642 ; minimally-qualified # 👷🏻‍♂ E4.0 man construction worker: light skin tone -1F477 1F3FC 200D 2642 FE0F ; fully-qualified # 👷🏼‍♂️ E4.0 man construction worker: medium-light skin tone -1F477 1F3FC 200D 2642 ; minimally-qualified # 👷🏼‍♂ E4.0 man construction worker: medium-light skin tone -1F477 1F3FD 200D 2642 FE0F ; fully-qualified # 👷🏽‍♂️ E4.0 man construction worker: medium skin tone -1F477 1F3FD 200D 2642 ; minimally-qualified # 👷🏽‍♂ E4.0 man construction worker: medium skin tone -1F477 1F3FE 200D 2642 FE0F ; fully-qualified # 👷🏾‍♂️ E4.0 man construction worker: medium-dark skin tone -1F477 1F3FE 200D 2642 ; minimally-qualified # 👷🏾‍♂ E4.0 man construction worker: medium-dark skin tone -1F477 1F3FF 200D 2642 FE0F ; fully-qualified # 👷🏿‍♂️ E4.0 man construction worker: dark skin tone -1F477 1F3FF 200D 2642 ; minimally-qualified # 👷🏿‍♂ E4.0 man construction worker: dark skin tone -1F477 200D 2640 FE0F ; fully-qualified # 👷‍♀️ E4.0 woman construction worker -1F477 200D 2640 ; minimally-qualified # 👷‍♀ E4.0 woman construction worker -1F477 1F3FB 200D 2640 FE0F ; fully-qualified # 👷🏻‍♀️ E4.0 woman construction worker: light skin tone -1F477 1F3FB 200D 2640 ; minimally-qualified # 👷🏻‍♀ E4.0 woman construction worker: light skin tone -1F477 1F3FC 200D 2640 FE0F ; fully-qualified # 👷🏼‍♀️ E4.0 woman construction worker: medium-light skin tone -1F477 1F3FC 200D 2640 ; minimally-qualified # 👷🏼‍♀ E4.0 woman construction worker: medium-light skin tone -1F477 1F3FD 200D 2640 FE0F ; fully-qualified # 👷🏽‍♀️ E4.0 woman construction worker: medium skin tone -1F477 1F3FD 200D 2640 ; minimally-qualified # 👷🏽‍♀ E4.0 woman construction worker: medium skin tone -1F477 1F3FE 200D 2640 FE0F ; fully-qualified # 👷🏾‍♀️ E4.0 woman construction worker: medium-dark skin tone -1F477 1F3FE 200D 2640 ; minimally-qualified # 👷🏾‍♀ E4.0 woman construction worker: medium-dark skin tone -1F477 1F3FF 200D 2640 FE0F ; fully-qualified # 👷🏿‍♀️ E4.0 woman construction worker: dark skin tone -1F477 1F3FF 200D 2640 ; minimally-qualified # 👷🏿‍♀ E4.0 woman construction worker: dark skin tone -1FAC5 ; fully-qualified # 🫅 E14.0 person with crown -1FAC5 1F3FB ; fully-qualified # 🫅🏻 E14.0 person with crown: light skin tone -1FAC5 1F3FC ; fully-qualified # 🫅🏼 E14.0 person with crown: medium-light skin tone -1FAC5 1F3FD ; fully-qualified # 🫅🏽 E14.0 person with crown: medium skin tone -1FAC5 1F3FE ; fully-qualified # 🫅🏾 E14.0 person with crown: medium-dark skin tone -1FAC5 1F3FF ; fully-qualified # 🫅🏿 E14.0 person with crown: dark skin tone -1F934 ; fully-qualified # 🤴 E3.0 prince -1F934 1F3FB ; fully-qualified # 🤴🏻 E3.0 prince: light skin tone -1F934 1F3FC ; fully-qualified # 🤴🏼 E3.0 prince: medium-light skin tone -1F934 1F3FD ; fully-qualified # 🤴🏽 E3.0 prince: medium skin tone -1F934 1F3FE ; fully-qualified # 🤴🏾 E3.0 prince: medium-dark skin tone -1F934 1F3FF ; fully-qualified # 🤴🏿 E3.0 prince: dark skin tone -1F478 ; fully-qualified # 👸 E0.6 princess -1F478 1F3FB ; fully-qualified # 👸🏻 E1.0 princess: light skin tone -1F478 1F3FC ; fully-qualified # 👸🏼 E1.0 princess: medium-light skin tone -1F478 1F3FD ; fully-qualified # 👸🏽 E1.0 princess: medium skin tone -1F478 1F3FE ; fully-qualified # 👸🏾 E1.0 princess: medium-dark skin tone -1F478 1F3FF ; fully-qualified # 👸🏿 E1.0 princess: dark skin tone -1F473 ; fully-qualified # 👳 E0.6 person wearing turban -1F473 1F3FB ; fully-qualified # 👳🏻 E1.0 person wearing turban: light skin tone -1F473 1F3FC ; fully-qualified # 👳🏼 E1.0 person wearing turban: medium-light skin tone -1F473 1F3FD ; fully-qualified # 👳🏽 E1.0 person wearing turban: medium skin tone -1F473 1F3FE ; fully-qualified # 👳🏾 E1.0 person wearing turban: medium-dark skin tone -1F473 1F3FF ; fully-qualified # 👳🏿 E1.0 person wearing turban: dark skin tone -1F473 200D 2642 FE0F ; fully-qualified # 👳‍♂️ E4.0 man wearing turban -1F473 200D 2642 ; minimally-qualified # 👳‍♂ E4.0 man wearing turban -1F473 1F3FB 200D 2642 FE0F ; fully-qualified # 👳🏻‍♂️ E4.0 man wearing turban: light skin tone -1F473 1F3FB 200D 2642 ; minimally-qualified # 👳🏻‍♂ E4.0 man wearing turban: light skin tone -1F473 1F3FC 200D 2642 FE0F ; fully-qualified # 👳🏼‍♂️ E4.0 man wearing turban: medium-light skin tone -1F473 1F3FC 200D 2642 ; minimally-qualified # 👳🏼‍♂ E4.0 man wearing turban: medium-light skin tone -1F473 1F3FD 200D 2642 FE0F ; fully-qualified # 👳🏽‍♂️ E4.0 man wearing turban: medium skin tone -1F473 1F3FD 200D 2642 ; minimally-qualified # 👳🏽‍♂ E4.0 man wearing turban: medium skin tone -1F473 1F3FE 200D 2642 FE0F ; fully-qualified # 👳🏾‍♂️ E4.0 man wearing turban: medium-dark skin tone -1F473 1F3FE 200D 2642 ; minimally-qualified # 👳🏾‍♂ E4.0 man wearing turban: medium-dark skin tone -1F473 1F3FF 200D 2642 FE0F ; fully-qualified # 👳🏿‍♂️ E4.0 man wearing turban: dark skin tone -1F473 1F3FF 200D 2642 ; minimally-qualified # 👳🏿‍♂ E4.0 man wearing turban: dark skin tone -1F473 200D 2640 FE0F ; fully-qualified # 👳‍♀️ E4.0 woman wearing turban -1F473 200D 2640 ; minimally-qualified # 👳‍♀ E4.0 woman wearing turban -1F473 1F3FB 200D 2640 FE0F ; fully-qualified # 👳🏻‍♀️ E4.0 woman wearing turban: light skin tone -1F473 1F3FB 200D 2640 ; minimally-qualified # 👳🏻‍♀ E4.0 woman wearing turban: light skin tone -1F473 1F3FC 200D 2640 FE0F ; fully-qualified # 👳🏼‍♀️ E4.0 woman wearing turban: medium-light skin tone -1F473 1F3FC 200D 2640 ; minimally-qualified # 👳🏼‍♀ E4.0 woman wearing turban: medium-light skin tone -1F473 1F3FD 200D 2640 FE0F ; fully-qualified # 👳🏽‍♀️ E4.0 woman wearing turban: medium skin tone -1F473 1F3FD 200D 2640 ; minimally-qualified # 👳🏽‍♀ E4.0 woman wearing turban: medium skin tone -1F473 1F3FE 200D 2640 FE0F ; fully-qualified # 👳🏾‍♀️ E4.0 woman wearing turban: medium-dark skin tone -1F473 1F3FE 200D 2640 ; minimally-qualified # 👳🏾‍♀ E4.0 woman wearing turban: medium-dark skin tone -1F473 1F3FF 200D 2640 FE0F ; fully-qualified # 👳🏿‍♀️ E4.0 woman wearing turban: dark skin tone -1F473 1F3FF 200D 2640 ; minimally-qualified # 👳🏿‍♀ E4.0 woman wearing turban: dark skin tone -1F472 ; fully-qualified # 👲 E0.6 person with skullcap -1F472 1F3FB ; fully-qualified # 👲🏻 E1.0 person with skullcap: light skin tone -1F472 1F3FC ; fully-qualified # 👲🏼 E1.0 person with skullcap: medium-light skin tone -1F472 1F3FD ; fully-qualified # 👲🏽 E1.0 person with skullcap: medium skin tone -1F472 1F3FE ; fully-qualified # 👲🏾 E1.0 person with skullcap: medium-dark skin tone -1F472 1F3FF ; fully-qualified # 👲🏿 E1.0 person with skullcap: dark skin tone -1F9D5 ; fully-qualified # 🧕 E5.0 woman with headscarf -1F9D5 1F3FB ; fully-qualified # 🧕🏻 E5.0 woman with headscarf: light skin tone -1F9D5 1F3FC ; fully-qualified # 🧕🏼 E5.0 woman with headscarf: medium-light skin tone -1F9D5 1F3FD ; fully-qualified # 🧕🏽 E5.0 woman with headscarf: medium skin tone -1F9D5 1F3FE ; fully-qualified # 🧕🏾 E5.0 woman with headscarf: medium-dark skin tone -1F9D5 1F3FF ; fully-qualified # 🧕🏿 E5.0 woman with headscarf: dark skin tone -1F935 ; fully-qualified # 🤵 E3.0 person in tuxedo -1F935 1F3FB ; fully-qualified # 🤵🏻 E3.0 person in tuxedo: light skin tone -1F935 1F3FC ; fully-qualified # 🤵🏼 E3.0 person in tuxedo: medium-light skin tone -1F935 1F3FD ; fully-qualified # 🤵🏽 E3.0 person in tuxedo: medium skin tone -1F935 1F3FE ; fully-qualified # 🤵🏾 E3.0 person in tuxedo: medium-dark skin tone -1F935 1F3FF ; fully-qualified # 🤵🏿 E3.0 person in tuxedo: dark skin tone -1F935 200D 2642 FE0F ; fully-qualified # 🤵‍♂️ E13.0 man in tuxedo -1F935 200D 2642 ; minimally-qualified # 🤵‍♂ E13.0 man in tuxedo -1F935 1F3FB 200D 2642 FE0F ; fully-qualified # 🤵🏻‍♂️ E13.0 man in tuxedo: light skin tone -1F935 1F3FB 200D 2642 ; minimally-qualified # 🤵🏻‍♂ E13.0 man in tuxedo: light skin tone -1F935 1F3FC 200D 2642 FE0F ; fully-qualified # 🤵🏼‍♂️ E13.0 man in tuxedo: medium-light skin tone -1F935 1F3FC 200D 2642 ; minimally-qualified # 🤵🏼‍♂ E13.0 man in tuxedo: medium-light skin tone -1F935 1F3FD 200D 2642 FE0F ; fully-qualified # 🤵🏽‍♂️ E13.0 man in tuxedo: medium skin tone -1F935 1F3FD 200D 2642 ; minimally-qualified # 🤵🏽‍♂ E13.0 man in tuxedo: medium skin tone -1F935 1F3FE 200D 2642 FE0F ; fully-qualified # 🤵🏾‍♂️ E13.0 man in tuxedo: medium-dark skin tone -1F935 1F3FE 200D 2642 ; minimally-qualified # 🤵🏾‍♂ E13.0 man in tuxedo: medium-dark skin tone -1F935 1F3FF 200D 2642 FE0F ; fully-qualified # 🤵🏿‍♂️ E13.0 man in tuxedo: dark skin tone -1F935 1F3FF 200D 2642 ; minimally-qualified # 🤵🏿‍♂ E13.0 man in tuxedo: dark skin tone -1F935 200D 2640 FE0F ; fully-qualified # 🤵‍♀️ E13.0 woman in tuxedo -1F935 200D 2640 ; minimally-qualified # 🤵‍♀ E13.0 woman in tuxedo -1F935 1F3FB 200D 2640 FE0F ; fully-qualified # 🤵🏻‍♀️ E13.0 woman in tuxedo: light skin tone -1F935 1F3FB 200D 2640 ; minimally-qualified # 🤵🏻‍♀ E13.0 woman in tuxedo: light skin tone -1F935 1F3FC 200D 2640 FE0F ; fully-qualified # 🤵🏼‍♀️ E13.0 woman in tuxedo: medium-light skin tone -1F935 1F3FC 200D 2640 ; minimally-qualified # 🤵🏼‍♀ E13.0 woman in tuxedo: medium-light skin tone -1F935 1F3FD 200D 2640 FE0F ; fully-qualified # 🤵🏽‍♀️ E13.0 woman in tuxedo: medium skin tone -1F935 1F3FD 200D 2640 ; minimally-qualified # 🤵🏽‍♀ E13.0 woman in tuxedo: medium skin tone -1F935 1F3FE 200D 2640 FE0F ; fully-qualified # 🤵🏾‍♀️ E13.0 woman in tuxedo: medium-dark skin tone -1F935 1F3FE 200D 2640 ; minimally-qualified # 🤵🏾‍♀ E13.0 woman in tuxedo: medium-dark skin tone -1F935 1F3FF 200D 2640 FE0F ; fully-qualified # 🤵🏿‍♀️ E13.0 woman in tuxedo: dark skin tone -1F935 1F3FF 200D 2640 ; minimally-qualified # 🤵🏿‍♀ E13.0 woman in tuxedo: dark skin tone -1F470 ; fully-qualified # 👰 E0.6 person with veil -1F470 1F3FB ; fully-qualified # 👰🏻 E1.0 person with veil: light skin tone -1F470 1F3FC ; fully-qualified # 👰🏼 E1.0 person with veil: medium-light skin tone -1F470 1F3FD ; fully-qualified # 👰🏽 E1.0 person with veil: medium skin tone -1F470 1F3FE ; fully-qualified # 👰🏾 E1.0 person with veil: medium-dark skin tone -1F470 1F3FF ; fully-qualified # 👰🏿 E1.0 person with veil: dark skin tone -1F470 200D 2642 FE0F ; fully-qualified # 👰‍♂️ E13.0 man with veil -1F470 200D 2642 ; minimally-qualified # 👰‍♂ E13.0 man with veil -1F470 1F3FB 200D 2642 FE0F ; fully-qualified # 👰🏻‍♂️ E13.0 man with veil: light skin tone -1F470 1F3FB 200D 2642 ; minimally-qualified # 👰🏻‍♂ E13.0 man with veil: light skin tone -1F470 1F3FC 200D 2642 FE0F ; fully-qualified # 👰🏼‍♂️ E13.0 man with veil: medium-light skin tone -1F470 1F3FC 200D 2642 ; minimally-qualified # 👰🏼‍♂ E13.0 man with veil: medium-light skin tone -1F470 1F3FD 200D 2642 FE0F ; fully-qualified # 👰🏽‍♂️ E13.0 man with veil: medium skin tone -1F470 1F3FD 200D 2642 ; minimally-qualified # 👰🏽‍♂ E13.0 man with veil: medium skin tone -1F470 1F3FE 200D 2642 FE0F ; fully-qualified # 👰🏾‍♂️ E13.0 man with veil: medium-dark skin tone -1F470 1F3FE 200D 2642 ; minimally-qualified # 👰🏾‍♂ E13.0 man with veil: medium-dark skin tone -1F470 1F3FF 200D 2642 FE0F ; fully-qualified # 👰🏿‍♂️ E13.0 man with veil: dark skin tone -1F470 1F3FF 200D 2642 ; minimally-qualified # 👰🏿‍♂ E13.0 man with veil: dark skin tone -1F470 200D 2640 FE0F ; fully-qualified # 👰‍♀️ E13.0 woman with veil -1F470 200D 2640 ; minimally-qualified # 👰‍♀ E13.0 woman with veil -1F470 1F3FB 200D 2640 FE0F ; fully-qualified # 👰🏻‍♀️ E13.0 woman with veil: light skin tone -1F470 1F3FB 200D 2640 ; minimally-qualified # 👰🏻‍♀ E13.0 woman with veil: light skin tone -1F470 1F3FC 200D 2640 FE0F ; fully-qualified # 👰🏼‍♀️ E13.0 woman with veil: medium-light skin tone -1F470 1F3FC 200D 2640 ; minimally-qualified # 👰🏼‍♀ E13.0 woman with veil: medium-light skin tone -1F470 1F3FD 200D 2640 FE0F ; fully-qualified # 👰🏽‍♀️ E13.0 woman with veil: medium skin tone -1F470 1F3FD 200D 2640 ; minimally-qualified # 👰🏽‍♀ E13.0 woman with veil: medium skin tone -1F470 1F3FE 200D 2640 FE0F ; fully-qualified # 👰🏾‍♀️ E13.0 woman with veil: medium-dark skin tone -1F470 1F3FE 200D 2640 ; minimally-qualified # 👰🏾‍♀ E13.0 woman with veil: medium-dark skin tone -1F470 1F3FF 200D 2640 FE0F ; fully-qualified # 👰🏿‍♀️ E13.0 woman with veil: dark skin tone -1F470 1F3FF 200D 2640 ; minimally-qualified # 👰🏿‍♀ E13.0 woman with veil: dark skin tone -1F930 ; fully-qualified # 🤰 E3.0 pregnant woman -1F930 1F3FB ; fully-qualified # 🤰🏻 E3.0 pregnant woman: light skin tone -1F930 1F3FC ; fully-qualified # 🤰🏼 E3.0 pregnant woman: medium-light skin tone -1F930 1F3FD ; fully-qualified # 🤰🏽 E3.0 pregnant woman: medium skin tone -1F930 1F3FE ; fully-qualified # 🤰🏾 E3.0 pregnant woman: medium-dark skin tone -1F930 1F3FF ; fully-qualified # 🤰🏿 E3.0 pregnant woman: dark skin tone -1FAC3 ; fully-qualified # 🫃 E14.0 pregnant man -1FAC3 1F3FB ; fully-qualified # 🫃🏻 E14.0 pregnant man: light skin tone -1FAC3 1F3FC ; fully-qualified # 🫃🏼 E14.0 pregnant man: medium-light skin tone -1FAC3 1F3FD ; fully-qualified # 🫃🏽 E14.0 pregnant man: medium skin tone -1FAC3 1F3FE ; fully-qualified # 🫃🏾 E14.0 pregnant man: medium-dark skin tone -1FAC3 1F3FF ; fully-qualified # 🫃🏿 E14.0 pregnant man: dark skin tone -1FAC4 ; fully-qualified # 🫄 E14.0 pregnant person -1FAC4 1F3FB ; fully-qualified # 🫄🏻 E14.0 pregnant person: light skin tone -1FAC4 1F3FC ; fully-qualified # 🫄🏼 E14.0 pregnant person: medium-light skin tone -1FAC4 1F3FD ; fully-qualified # 🫄🏽 E14.0 pregnant person: medium skin tone -1FAC4 1F3FE ; fully-qualified # 🫄🏾 E14.0 pregnant person: medium-dark skin tone -1FAC4 1F3FF ; fully-qualified # 🫄🏿 E14.0 pregnant person: dark skin tone -1F931 ; fully-qualified # 🤱 E5.0 breast-feeding -1F931 1F3FB ; fully-qualified # 🤱🏻 E5.0 breast-feeding: light skin tone -1F931 1F3FC ; fully-qualified # 🤱🏼 E5.0 breast-feeding: medium-light skin tone -1F931 1F3FD ; fully-qualified # 🤱🏽 E5.0 breast-feeding: medium skin tone -1F931 1F3FE ; fully-qualified # 🤱🏾 E5.0 breast-feeding: medium-dark skin tone -1F931 1F3FF ; fully-qualified # 🤱🏿 E5.0 breast-feeding: dark skin tone -1F469 200D 1F37C ; fully-qualified # 👩‍🍼 E13.0 woman feeding baby -1F469 1F3FB 200D 1F37C ; fully-qualified # 👩🏻‍🍼 E13.0 woman feeding baby: light skin tone -1F469 1F3FC 200D 1F37C ; fully-qualified # 👩🏼‍🍼 E13.0 woman feeding baby: medium-light skin tone -1F469 1F3FD 200D 1F37C ; fully-qualified # 👩🏽‍🍼 E13.0 woman feeding baby: medium skin tone -1F469 1F3FE 200D 1F37C ; fully-qualified # 👩🏾‍🍼 E13.0 woman feeding baby: medium-dark skin tone -1F469 1F3FF 200D 1F37C ; fully-qualified # 👩🏿‍🍼 E13.0 woman feeding baby: dark skin tone -1F468 200D 1F37C ; fully-qualified # 👨‍🍼 E13.0 man feeding baby -1F468 1F3FB 200D 1F37C ; fully-qualified # 👨🏻‍🍼 E13.0 man feeding baby: light skin tone -1F468 1F3FC 200D 1F37C ; fully-qualified # 👨🏼‍🍼 E13.0 man feeding baby: medium-light skin tone -1F468 1F3FD 200D 1F37C ; fully-qualified # 👨🏽‍🍼 E13.0 man feeding baby: medium skin tone -1F468 1F3FE 200D 1F37C ; fully-qualified # 👨🏾‍🍼 E13.0 man feeding baby: medium-dark skin tone -1F468 1F3FF 200D 1F37C ; fully-qualified # 👨🏿‍🍼 E13.0 man feeding baby: dark skin tone -1F9D1 200D 1F37C ; fully-qualified # 🧑‍🍼 E13.0 person feeding baby -1F9D1 1F3FB 200D 1F37C ; fully-qualified # 🧑🏻‍🍼 E13.0 person feeding baby: light skin tone -1F9D1 1F3FC 200D 1F37C ; fully-qualified # 🧑🏼‍🍼 E13.0 person feeding baby: medium-light skin tone -1F9D1 1F3FD 200D 1F37C ; fully-qualified # 🧑🏽‍🍼 E13.0 person feeding baby: medium skin tone -1F9D1 1F3FE 200D 1F37C ; fully-qualified # 🧑🏾‍🍼 E13.0 person feeding baby: medium-dark skin tone -1F9D1 1F3FF 200D 1F37C ; fully-qualified # 🧑🏿‍🍼 E13.0 person feeding baby: dark skin tone - -# subgroup: person-fantasy -1F47C ; fully-qualified # 👼 E0.6 baby angel -1F47C 1F3FB ; fully-qualified # 👼🏻 E1.0 baby angel: light skin tone -1F47C 1F3FC ; fully-qualified # 👼🏼 E1.0 baby angel: medium-light skin tone -1F47C 1F3FD ; fully-qualified # 👼🏽 E1.0 baby angel: medium skin tone -1F47C 1F3FE ; fully-qualified # 👼🏾 E1.0 baby angel: medium-dark skin tone -1F47C 1F3FF ; fully-qualified # 👼🏿 E1.0 baby angel: dark skin tone -1F385 ; fully-qualified # 🎅 E0.6 Santa Claus -1F385 1F3FB ; fully-qualified # 🎅🏻 E1.0 Santa Claus: light skin tone -1F385 1F3FC ; fully-qualified # 🎅🏼 E1.0 Santa Claus: medium-light skin tone -1F385 1F3FD ; fully-qualified # 🎅🏽 E1.0 Santa Claus: medium skin tone -1F385 1F3FE ; fully-qualified # 🎅🏾 E1.0 Santa Claus: medium-dark skin tone -1F385 1F3FF ; fully-qualified # 🎅🏿 E1.0 Santa Claus: dark skin tone -1F936 ; fully-qualified # 🤶 E3.0 Mrs. Claus -1F936 1F3FB ; fully-qualified # 🤶🏻 E3.0 Mrs. Claus: light skin tone -1F936 1F3FC ; fully-qualified # 🤶🏼 E3.0 Mrs. Claus: medium-light skin tone -1F936 1F3FD ; fully-qualified # 🤶🏽 E3.0 Mrs. Claus: medium skin tone -1F936 1F3FE ; fully-qualified # 🤶🏾 E3.0 Mrs. Claus: medium-dark skin tone -1F936 1F3FF ; fully-qualified # 🤶🏿 E3.0 Mrs. Claus: dark skin tone -1F9D1 200D 1F384 ; fully-qualified # 🧑‍🎄 E13.0 mx claus -1F9D1 1F3FB 200D 1F384 ; fully-qualified # 🧑🏻‍🎄 E13.0 mx claus: light skin tone -1F9D1 1F3FC 200D 1F384 ; fully-qualified # 🧑🏼‍🎄 E13.0 mx claus: medium-light skin tone -1F9D1 1F3FD 200D 1F384 ; fully-qualified # 🧑🏽‍🎄 E13.0 mx claus: medium skin tone -1F9D1 1F3FE 200D 1F384 ; fully-qualified # 🧑🏾‍🎄 E13.0 mx claus: medium-dark skin tone -1F9D1 1F3FF 200D 1F384 ; fully-qualified # 🧑🏿‍🎄 E13.0 mx claus: dark skin tone -1F9B8 ; fully-qualified # 🦸 E11.0 superhero -1F9B8 1F3FB ; fully-qualified # 🦸🏻 E11.0 superhero: light skin tone -1F9B8 1F3FC ; fully-qualified # 🦸🏼 E11.0 superhero: medium-light skin tone -1F9B8 1F3FD ; fully-qualified # 🦸🏽 E11.0 superhero: medium skin tone -1F9B8 1F3FE ; fully-qualified # 🦸🏾 E11.0 superhero: medium-dark skin tone -1F9B8 1F3FF ; fully-qualified # 🦸🏿 E11.0 superhero: dark skin tone -1F9B8 200D 2642 FE0F ; fully-qualified # 🦸‍♂️ E11.0 man superhero -1F9B8 200D 2642 ; minimally-qualified # 🦸‍♂ E11.0 man superhero -1F9B8 1F3FB 200D 2642 FE0F ; fully-qualified # 🦸🏻‍♂️ E11.0 man superhero: light skin tone -1F9B8 1F3FB 200D 2642 ; minimally-qualified # 🦸🏻‍♂ E11.0 man superhero: light skin tone -1F9B8 1F3FC 200D 2642 FE0F ; fully-qualified # 🦸🏼‍♂️ E11.0 man superhero: medium-light skin tone -1F9B8 1F3FC 200D 2642 ; minimally-qualified # 🦸🏼‍♂ E11.0 man superhero: medium-light skin tone -1F9B8 1F3FD 200D 2642 FE0F ; fully-qualified # 🦸🏽‍♂️ E11.0 man superhero: medium skin tone -1F9B8 1F3FD 200D 2642 ; minimally-qualified # 🦸🏽‍♂ E11.0 man superhero: medium skin tone -1F9B8 1F3FE 200D 2642 FE0F ; fully-qualified # 🦸🏾‍♂️ E11.0 man superhero: medium-dark skin tone -1F9B8 1F3FE 200D 2642 ; minimally-qualified # 🦸🏾‍♂ E11.0 man superhero: medium-dark skin tone -1F9B8 1F3FF 200D 2642 FE0F ; fully-qualified # 🦸🏿‍♂️ E11.0 man superhero: dark skin tone -1F9B8 1F3FF 200D 2642 ; minimally-qualified # 🦸🏿‍♂ E11.0 man superhero: dark skin tone -1F9B8 200D 2640 FE0F ; fully-qualified # 🦸‍♀️ E11.0 woman superhero -1F9B8 200D 2640 ; minimally-qualified # 🦸‍♀ E11.0 woman superhero -1F9B8 1F3FB 200D 2640 FE0F ; fully-qualified # 🦸🏻‍♀️ E11.0 woman superhero: light skin tone -1F9B8 1F3FB 200D 2640 ; minimally-qualified # 🦸🏻‍♀ E11.0 woman superhero: light skin tone -1F9B8 1F3FC 200D 2640 FE0F ; fully-qualified # 🦸🏼‍♀️ E11.0 woman superhero: medium-light skin tone -1F9B8 1F3FC 200D 2640 ; minimally-qualified # 🦸🏼‍♀ E11.0 woman superhero: medium-light skin tone -1F9B8 1F3FD 200D 2640 FE0F ; fully-qualified # 🦸🏽‍♀️ E11.0 woman superhero: medium skin tone -1F9B8 1F3FD 200D 2640 ; minimally-qualified # 🦸🏽‍♀ E11.0 woman superhero: medium skin tone -1F9B8 1F3FE 200D 2640 FE0F ; fully-qualified # 🦸🏾‍♀️ E11.0 woman superhero: medium-dark skin tone -1F9B8 1F3FE 200D 2640 ; minimally-qualified # 🦸🏾‍♀ E11.0 woman superhero: medium-dark skin tone -1F9B8 1F3FF 200D 2640 FE0F ; fully-qualified # 🦸🏿‍♀️ E11.0 woman superhero: dark skin tone -1F9B8 1F3FF 200D 2640 ; minimally-qualified # 🦸🏿‍♀ E11.0 woman superhero: dark skin tone -1F9B9 ; fully-qualified # 🦹 E11.0 supervillain -1F9B9 1F3FB ; fully-qualified # 🦹🏻 E11.0 supervillain: light skin tone -1F9B9 1F3FC ; fully-qualified # 🦹🏼 E11.0 supervillain: medium-light skin tone -1F9B9 1F3FD ; fully-qualified # 🦹🏽 E11.0 supervillain: medium skin tone -1F9B9 1F3FE ; fully-qualified # 🦹🏾 E11.0 supervillain: medium-dark skin tone -1F9B9 1F3FF ; fully-qualified # 🦹🏿 E11.0 supervillain: dark skin tone -1F9B9 200D 2642 FE0F ; fully-qualified # 🦹‍♂️ E11.0 man supervillain -1F9B9 200D 2642 ; minimally-qualified # 🦹‍♂ E11.0 man supervillain -1F9B9 1F3FB 200D 2642 FE0F ; fully-qualified # 🦹🏻‍♂️ E11.0 man supervillain: light skin tone -1F9B9 1F3FB 200D 2642 ; minimally-qualified # 🦹🏻‍♂ E11.0 man supervillain: light skin tone -1F9B9 1F3FC 200D 2642 FE0F ; fully-qualified # 🦹🏼‍♂️ E11.0 man supervillain: medium-light skin tone -1F9B9 1F3FC 200D 2642 ; minimally-qualified # 🦹🏼‍♂ E11.0 man supervillain: medium-light skin tone -1F9B9 1F3FD 200D 2642 FE0F ; fully-qualified # 🦹🏽‍♂️ E11.0 man supervillain: medium skin tone -1F9B9 1F3FD 200D 2642 ; minimally-qualified # 🦹🏽‍♂ E11.0 man supervillain: medium skin tone -1F9B9 1F3FE 200D 2642 FE0F ; fully-qualified # 🦹🏾‍♂️ E11.0 man supervillain: medium-dark skin tone -1F9B9 1F3FE 200D 2642 ; minimally-qualified # 🦹🏾‍♂ E11.0 man supervillain: medium-dark skin tone -1F9B9 1F3FF 200D 2642 FE0F ; fully-qualified # 🦹🏿‍♂️ E11.0 man supervillain: dark skin tone -1F9B9 1F3FF 200D 2642 ; minimally-qualified # 🦹🏿‍♂ E11.0 man supervillain: dark skin tone -1F9B9 200D 2640 FE0F ; fully-qualified # 🦹‍♀️ E11.0 woman supervillain -1F9B9 200D 2640 ; minimally-qualified # 🦹‍♀ E11.0 woman supervillain -1F9B9 1F3FB 200D 2640 FE0F ; fully-qualified # 🦹🏻‍♀️ E11.0 woman supervillain: light skin tone -1F9B9 1F3FB 200D 2640 ; minimally-qualified # 🦹🏻‍♀ E11.0 woman supervillain: light skin tone -1F9B9 1F3FC 200D 2640 FE0F ; fully-qualified # 🦹🏼‍♀️ E11.0 woman supervillain: medium-light skin tone -1F9B9 1F3FC 200D 2640 ; minimally-qualified # 🦹🏼‍♀ E11.0 woman supervillain: medium-light skin tone -1F9B9 1F3FD 200D 2640 FE0F ; fully-qualified # 🦹🏽‍♀️ E11.0 woman supervillain: medium skin tone -1F9B9 1F3FD 200D 2640 ; minimally-qualified # 🦹🏽‍♀ E11.0 woman supervillain: medium skin tone -1F9B9 1F3FE 200D 2640 FE0F ; fully-qualified # 🦹🏾‍♀️ E11.0 woman supervillain: medium-dark skin tone -1F9B9 1F3FE 200D 2640 ; minimally-qualified # 🦹🏾‍♀ E11.0 woman supervillain: medium-dark skin tone -1F9B9 1F3FF 200D 2640 FE0F ; fully-qualified # 🦹🏿‍♀️ E11.0 woman supervillain: dark skin tone -1F9B9 1F3FF 200D 2640 ; minimally-qualified # 🦹🏿‍♀ E11.0 woman supervillain: dark skin tone -1F9D9 ; fully-qualified # 🧙 E5.0 mage -1F9D9 1F3FB ; fully-qualified # 🧙🏻 E5.0 mage: light skin tone -1F9D9 1F3FC ; fully-qualified # 🧙🏼 E5.0 mage: medium-light skin tone -1F9D9 1F3FD ; fully-qualified # 🧙🏽 E5.0 mage: medium skin tone -1F9D9 1F3FE ; fully-qualified # 🧙🏾 E5.0 mage: medium-dark skin tone -1F9D9 1F3FF ; fully-qualified # 🧙🏿 E5.0 mage: dark skin tone -1F9D9 200D 2642 FE0F ; fully-qualified # 🧙‍♂️ E5.0 man mage -1F9D9 200D 2642 ; minimally-qualified # 🧙‍♂ E5.0 man mage -1F9D9 1F3FB 200D 2642 FE0F ; fully-qualified # 🧙🏻‍♂️ E5.0 man mage: light skin tone -1F9D9 1F3FB 200D 2642 ; minimally-qualified # 🧙🏻‍♂ E5.0 man mage: light skin tone -1F9D9 1F3FC 200D 2642 FE0F ; fully-qualified # 🧙🏼‍♂️ E5.0 man mage: medium-light skin tone -1F9D9 1F3FC 200D 2642 ; minimally-qualified # 🧙🏼‍♂ E5.0 man mage: medium-light skin tone -1F9D9 1F3FD 200D 2642 FE0F ; fully-qualified # 🧙🏽‍♂️ E5.0 man mage: medium skin tone -1F9D9 1F3FD 200D 2642 ; minimally-qualified # 🧙🏽‍♂ E5.0 man mage: medium skin tone -1F9D9 1F3FE 200D 2642 FE0F ; fully-qualified # 🧙🏾‍♂️ E5.0 man mage: medium-dark skin tone -1F9D9 1F3FE 200D 2642 ; minimally-qualified # 🧙🏾‍♂ E5.0 man mage: medium-dark skin tone -1F9D9 1F3FF 200D 2642 FE0F ; fully-qualified # 🧙🏿‍♂️ E5.0 man mage: dark skin tone -1F9D9 1F3FF 200D 2642 ; minimally-qualified # 🧙🏿‍♂ E5.0 man mage: dark skin tone -1F9D9 200D 2640 FE0F ; fully-qualified # 🧙‍♀️ E5.0 woman mage -1F9D9 200D 2640 ; minimally-qualified # 🧙‍♀ E5.0 woman mage -1F9D9 1F3FB 200D 2640 FE0F ; fully-qualified # 🧙🏻‍♀️ E5.0 woman mage: light skin tone -1F9D9 1F3FB 200D 2640 ; minimally-qualified # 🧙🏻‍♀ E5.0 woman mage: light skin tone -1F9D9 1F3FC 200D 2640 FE0F ; fully-qualified # 🧙🏼‍♀️ E5.0 woman mage: medium-light skin tone -1F9D9 1F3FC 200D 2640 ; minimally-qualified # 🧙🏼‍♀ E5.0 woman mage: medium-light skin tone -1F9D9 1F3FD 200D 2640 FE0F ; fully-qualified # 🧙🏽‍♀️ E5.0 woman mage: medium skin tone -1F9D9 1F3FD 200D 2640 ; minimally-qualified # 🧙🏽‍♀ E5.0 woman mage: medium skin tone -1F9D9 1F3FE 200D 2640 FE0F ; fully-qualified # 🧙🏾‍♀️ E5.0 woman mage: medium-dark skin tone -1F9D9 1F3FE 200D 2640 ; minimally-qualified # 🧙🏾‍♀ E5.0 woman mage: medium-dark skin tone -1F9D9 1F3FF 200D 2640 FE0F ; fully-qualified # 🧙🏿‍♀️ E5.0 woman mage: dark skin tone -1F9D9 1F3FF 200D 2640 ; minimally-qualified # 🧙🏿‍♀ E5.0 woman mage: dark skin tone -1F9DA ; fully-qualified # 🧚 E5.0 fairy -1F9DA 1F3FB ; fully-qualified # 🧚🏻 E5.0 fairy: light skin tone -1F9DA 1F3FC ; fully-qualified # 🧚🏼 E5.0 fairy: medium-light skin tone -1F9DA 1F3FD ; fully-qualified # 🧚🏽 E5.0 fairy: medium skin tone -1F9DA 1F3FE ; fully-qualified # 🧚🏾 E5.0 fairy: medium-dark skin tone -1F9DA 1F3FF ; fully-qualified # 🧚🏿 E5.0 fairy: dark skin tone -1F9DA 200D 2642 FE0F ; fully-qualified # 🧚‍♂️ E5.0 man fairy -1F9DA 200D 2642 ; minimally-qualified # 🧚‍♂ E5.0 man fairy -1F9DA 1F3FB 200D 2642 FE0F ; fully-qualified # 🧚🏻‍♂️ E5.0 man fairy: light skin tone -1F9DA 1F3FB 200D 2642 ; minimally-qualified # 🧚🏻‍♂ E5.0 man fairy: light skin tone -1F9DA 1F3FC 200D 2642 FE0F ; fully-qualified # 🧚🏼‍♂️ E5.0 man fairy: medium-light skin tone -1F9DA 1F3FC 200D 2642 ; minimally-qualified # 🧚🏼‍♂ E5.0 man fairy: medium-light skin tone -1F9DA 1F3FD 200D 2642 FE0F ; fully-qualified # 🧚🏽‍♂️ E5.0 man fairy: medium skin tone -1F9DA 1F3FD 200D 2642 ; minimally-qualified # 🧚🏽‍♂ E5.0 man fairy: medium skin tone -1F9DA 1F3FE 200D 2642 FE0F ; fully-qualified # 🧚🏾‍♂️ E5.0 man fairy: medium-dark skin tone -1F9DA 1F3FE 200D 2642 ; minimally-qualified # 🧚🏾‍♂ E5.0 man fairy: medium-dark skin tone -1F9DA 1F3FF 200D 2642 FE0F ; fully-qualified # 🧚🏿‍♂️ E5.0 man fairy: dark skin tone -1F9DA 1F3FF 200D 2642 ; minimally-qualified # 🧚🏿‍♂ E5.0 man fairy: dark skin tone -1F9DA 200D 2640 FE0F ; fully-qualified # 🧚‍♀️ E5.0 woman fairy -1F9DA 200D 2640 ; minimally-qualified # 🧚‍♀ E5.0 woman fairy -1F9DA 1F3FB 200D 2640 FE0F ; fully-qualified # 🧚🏻‍♀️ E5.0 woman fairy: light skin tone -1F9DA 1F3FB 200D 2640 ; minimally-qualified # 🧚🏻‍♀ E5.0 woman fairy: light skin tone -1F9DA 1F3FC 200D 2640 FE0F ; fully-qualified # 🧚🏼‍♀️ E5.0 woman fairy: medium-light skin tone -1F9DA 1F3FC 200D 2640 ; minimally-qualified # 🧚🏼‍♀ E5.0 woman fairy: medium-light skin tone -1F9DA 1F3FD 200D 2640 FE0F ; fully-qualified # 🧚🏽‍♀️ E5.0 woman fairy: medium skin tone -1F9DA 1F3FD 200D 2640 ; minimally-qualified # 🧚🏽‍♀ E5.0 woman fairy: medium skin tone -1F9DA 1F3FE 200D 2640 FE0F ; fully-qualified # 🧚🏾‍♀️ E5.0 woman fairy: medium-dark skin tone -1F9DA 1F3FE 200D 2640 ; minimally-qualified # 🧚🏾‍♀ E5.0 woman fairy: medium-dark skin tone -1F9DA 1F3FF 200D 2640 FE0F ; fully-qualified # 🧚🏿‍♀️ E5.0 woman fairy: dark skin tone -1F9DA 1F3FF 200D 2640 ; minimally-qualified # 🧚🏿‍♀ E5.0 woman fairy: dark skin tone -1F9DB ; fully-qualified # 🧛 E5.0 vampire -1F9DB 1F3FB ; fully-qualified # 🧛🏻 E5.0 vampire: light skin tone -1F9DB 1F3FC ; fully-qualified # 🧛🏼 E5.0 vampire: medium-light skin tone -1F9DB 1F3FD ; fully-qualified # 🧛🏽 E5.0 vampire: medium skin tone -1F9DB 1F3FE ; fully-qualified # 🧛🏾 E5.0 vampire: medium-dark skin tone -1F9DB 1F3FF ; fully-qualified # 🧛🏿 E5.0 vampire: dark skin tone -1F9DB 200D 2642 FE0F ; fully-qualified # 🧛‍♂️ E5.0 man vampire -1F9DB 200D 2642 ; minimally-qualified # 🧛‍♂ E5.0 man vampire -1F9DB 1F3FB 200D 2642 FE0F ; fully-qualified # 🧛🏻‍♂️ E5.0 man vampire: light skin tone -1F9DB 1F3FB 200D 2642 ; minimally-qualified # 🧛🏻‍♂ E5.0 man vampire: light skin tone -1F9DB 1F3FC 200D 2642 FE0F ; fully-qualified # 🧛🏼‍♂️ E5.0 man vampire: medium-light skin tone -1F9DB 1F3FC 200D 2642 ; minimally-qualified # 🧛🏼‍♂ E5.0 man vampire: medium-light skin tone -1F9DB 1F3FD 200D 2642 FE0F ; fully-qualified # 🧛🏽‍♂️ E5.0 man vampire: medium skin tone -1F9DB 1F3FD 200D 2642 ; minimally-qualified # 🧛🏽‍♂ E5.0 man vampire: medium skin tone -1F9DB 1F3FE 200D 2642 FE0F ; fully-qualified # 🧛🏾‍♂️ E5.0 man vampire: medium-dark skin tone -1F9DB 1F3FE 200D 2642 ; minimally-qualified # 🧛🏾‍♂ E5.0 man vampire: medium-dark skin tone -1F9DB 1F3FF 200D 2642 FE0F ; fully-qualified # 🧛🏿‍♂️ E5.0 man vampire: dark skin tone -1F9DB 1F3FF 200D 2642 ; minimally-qualified # 🧛🏿‍♂ E5.0 man vampire: dark skin tone -1F9DB 200D 2640 FE0F ; fully-qualified # 🧛‍♀️ E5.0 woman vampire -1F9DB 200D 2640 ; minimally-qualified # 🧛‍♀ E5.0 woman vampire -1F9DB 1F3FB 200D 2640 FE0F ; fully-qualified # 🧛🏻‍♀️ E5.0 woman vampire: light skin tone -1F9DB 1F3FB 200D 2640 ; minimally-qualified # 🧛🏻‍♀ E5.0 woman vampire: light skin tone -1F9DB 1F3FC 200D 2640 FE0F ; fully-qualified # 🧛🏼‍♀️ E5.0 woman vampire: medium-light skin tone -1F9DB 1F3FC 200D 2640 ; minimally-qualified # 🧛🏼‍♀ E5.0 woman vampire: medium-light skin tone -1F9DB 1F3FD 200D 2640 FE0F ; fully-qualified # 🧛🏽‍♀️ E5.0 woman vampire: medium skin tone -1F9DB 1F3FD 200D 2640 ; minimally-qualified # 🧛🏽‍♀ E5.0 woman vampire: medium skin tone -1F9DB 1F3FE 200D 2640 FE0F ; fully-qualified # 🧛🏾‍♀️ E5.0 woman vampire: medium-dark skin tone -1F9DB 1F3FE 200D 2640 ; minimally-qualified # 🧛🏾‍♀ E5.0 woman vampire: medium-dark skin tone -1F9DB 1F3FF 200D 2640 FE0F ; fully-qualified # 🧛🏿‍♀️ E5.0 woman vampire: dark skin tone -1F9DB 1F3FF 200D 2640 ; minimally-qualified # 🧛🏿‍♀ E5.0 woman vampire: dark skin tone -1F9DC ; fully-qualified # 🧜 E5.0 merperson -1F9DC 1F3FB ; fully-qualified # 🧜🏻 E5.0 merperson: light skin tone -1F9DC 1F3FC ; fully-qualified # 🧜🏼 E5.0 merperson: medium-light skin tone -1F9DC 1F3FD ; fully-qualified # 🧜🏽 E5.0 merperson: medium skin tone -1F9DC 1F3FE ; fully-qualified # 🧜🏾 E5.0 merperson: medium-dark skin tone -1F9DC 1F3FF ; fully-qualified # 🧜🏿 E5.0 merperson: dark skin tone -1F9DC 200D 2642 FE0F ; fully-qualified # 🧜‍♂️ E5.0 merman -1F9DC 200D 2642 ; minimally-qualified # 🧜‍♂ E5.0 merman -1F9DC 1F3FB 200D 2642 FE0F ; fully-qualified # 🧜🏻‍♂️ E5.0 merman: light skin tone -1F9DC 1F3FB 200D 2642 ; minimally-qualified # 🧜🏻‍♂ E5.0 merman: light skin tone -1F9DC 1F3FC 200D 2642 FE0F ; fully-qualified # 🧜🏼‍♂️ E5.0 merman: medium-light skin tone -1F9DC 1F3FC 200D 2642 ; minimally-qualified # 🧜🏼‍♂ E5.0 merman: medium-light skin tone -1F9DC 1F3FD 200D 2642 FE0F ; fully-qualified # 🧜🏽‍♂️ E5.0 merman: medium skin tone -1F9DC 1F3FD 200D 2642 ; minimally-qualified # 🧜🏽‍♂ E5.0 merman: medium skin tone -1F9DC 1F3FE 200D 2642 FE0F ; fully-qualified # 🧜🏾‍♂️ E5.0 merman: medium-dark skin tone -1F9DC 1F3FE 200D 2642 ; minimally-qualified # 🧜🏾‍♂ E5.0 merman: medium-dark skin tone -1F9DC 1F3FF 200D 2642 FE0F ; fully-qualified # 🧜🏿‍♂️ E5.0 merman: dark skin tone -1F9DC 1F3FF 200D 2642 ; minimally-qualified # 🧜🏿‍♂ E5.0 merman: dark skin tone -1F9DC 200D 2640 FE0F ; fully-qualified # 🧜‍♀️ E5.0 mermaid -1F9DC 200D 2640 ; minimally-qualified # 🧜‍♀ E5.0 mermaid -1F9DC 1F3FB 200D 2640 FE0F ; fully-qualified # 🧜🏻‍♀️ E5.0 mermaid: light skin tone -1F9DC 1F3FB 200D 2640 ; minimally-qualified # 🧜🏻‍♀ E5.0 mermaid: light skin tone -1F9DC 1F3FC 200D 2640 FE0F ; fully-qualified # 🧜🏼‍♀️ E5.0 mermaid: medium-light skin tone -1F9DC 1F3FC 200D 2640 ; minimally-qualified # 🧜🏼‍♀ E5.0 mermaid: medium-light skin tone -1F9DC 1F3FD 200D 2640 FE0F ; fully-qualified # 🧜🏽‍♀️ E5.0 mermaid: medium skin tone -1F9DC 1F3FD 200D 2640 ; minimally-qualified # 🧜🏽‍♀ E5.0 mermaid: medium skin tone -1F9DC 1F3FE 200D 2640 FE0F ; fully-qualified # 🧜🏾‍♀️ E5.0 mermaid: medium-dark skin tone -1F9DC 1F3FE 200D 2640 ; minimally-qualified # 🧜🏾‍♀ E5.0 mermaid: medium-dark skin tone -1F9DC 1F3FF 200D 2640 FE0F ; fully-qualified # 🧜🏿‍♀️ E5.0 mermaid: dark skin tone -1F9DC 1F3FF 200D 2640 ; minimally-qualified # 🧜🏿‍♀ E5.0 mermaid: dark skin tone -1F9DD ; fully-qualified # 🧝 E5.0 elf -1F9DD 1F3FB ; fully-qualified # 🧝🏻 E5.0 elf: light skin tone -1F9DD 1F3FC ; fully-qualified # 🧝🏼 E5.0 elf: medium-light skin tone -1F9DD 1F3FD ; fully-qualified # 🧝🏽 E5.0 elf: medium skin tone -1F9DD 1F3FE ; fully-qualified # 🧝🏾 E5.0 elf: medium-dark skin tone -1F9DD 1F3FF ; fully-qualified # 🧝🏿 E5.0 elf: dark skin tone -1F9DD 200D 2642 FE0F ; fully-qualified # 🧝‍♂️ E5.0 man elf -1F9DD 200D 2642 ; minimally-qualified # 🧝‍♂ E5.0 man elf -1F9DD 1F3FB 200D 2642 FE0F ; fully-qualified # 🧝🏻‍♂️ E5.0 man elf: light skin tone -1F9DD 1F3FB 200D 2642 ; minimally-qualified # 🧝🏻‍♂ E5.0 man elf: light skin tone -1F9DD 1F3FC 200D 2642 FE0F ; fully-qualified # 🧝🏼‍♂️ E5.0 man elf: medium-light skin tone -1F9DD 1F3FC 200D 2642 ; minimally-qualified # 🧝🏼‍♂ E5.0 man elf: medium-light skin tone -1F9DD 1F3FD 200D 2642 FE0F ; fully-qualified # 🧝🏽‍♂️ E5.0 man elf: medium skin tone -1F9DD 1F3FD 200D 2642 ; minimally-qualified # 🧝🏽‍♂ E5.0 man elf: medium skin tone -1F9DD 1F3FE 200D 2642 FE0F ; fully-qualified # 🧝🏾‍♂️ E5.0 man elf: medium-dark skin tone -1F9DD 1F3FE 200D 2642 ; minimally-qualified # 🧝🏾‍♂ E5.0 man elf: medium-dark skin tone -1F9DD 1F3FF 200D 2642 FE0F ; fully-qualified # 🧝🏿‍♂️ E5.0 man elf: dark skin tone -1F9DD 1F3FF 200D 2642 ; minimally-qualified # 🧝🏿‍♂ E5.0 man elf: dark skin tone -1F9DD 200D 2640 FE0F ; fully-qualified # 🧝‍♀️ E5.0 woman elf -1F9DD 200D 2640 ; minimally-qualified # 🧝‍♀ E5.0 woman elf -1F9DD 1F3FB 200D 2640 FE0F ; fully-qualified # 🧝🏻‍♀️ E5.0 woman elf: light skin tone -1F9DD 1F3FB 200D 2640 ; minimally-qualified # 🧝🏻‍♀ E5.0 woman elf: light skin tone -1F9DD 1F3FC 200D 2640 FE0F ; fully-qualified # 🧝🏼‍♀️ E5.0 woman elf: medium-light skin tone -1F9DD 1F3FC 200D 2640 ; minimally-qualified # 🧝🏼‍♀ E5.0 woman elf: medium-light skin tone -1F9DD 1F3FD 200D 2640 FE0F ; fully-qualified # 🧝🏽‍♀️ E5.0 woman elf: medium skin tone -1F9DD 1F3FD 200D 2640 ; minimally-qualified # 🧝🏽‍♀ E5.0 woman elf: medium skin tone -1F9DD 1F3FE 200D 2640 FE0F ; fully-qualified # 🧝🏾‍♀️ E5.0 woman elf: medium-dark skin tone -1F9DD 1F3FE 200D 2640 ; minimally-qualified # 🧝🏾‍♀ E5.0 woman elf: medium-dark skin tone -1F9DD 1F3FF 200D 2640 FE0F ; fully-qualified # 🧝🏿‍♀️ E5.0 woman elf: dark skin tone -1F9DD 1F3FF 200D 2640 ; minimally-qualified # 🧝🏿‍♀ E5.0 woman elf: dark skin tone -1F9DE ; fully-qualified # 🧞 E5.0 genie -1F9DE 200D 2642 FE0F ; fully-qualified # 🧞‍♂️ E5.0 man genie -1F9DE 200D 2642 ; minimally-qualified # 🧞‍♂ E5.0 man genie -1F9DE 200D 2640 FE0F ; fully-qualified # 🧞‍♀️ E5.0 woman genie -1F9DE 200D 2640 ; minimally-qualified # 🧞‍♀ E5.0 woman genie -1F9DF ; fully-qualified # 🧟 E5.0 zombie -1F9DF 200D 2642 FE0F ; fully-qualified # 🧟‍♂️ E5.0 man zombie -1F9DF 200D 2642 ; minimally-qualified # 🧟‍♂ E5.0 man zombie -1F9DF 200D 2640 FE0F ; fully-qualified # 🧟‍♀️ E5.0 woman zombie -1F9DF 200D 2640 ; minimally-qualified # 🧟‍♀ E5.0 woman zombie -1F9CC ; fully-qualified # 🧌 E14.0 troll - -# subgroup: person-activity -1F486 ; fully-qualified # 💆 E0.6 person getting massage -1F486 1F3FB ; fully-qualified # 💆🏻 E1.0 person getting massage: light skin tone -1F486 1F3FC ; fully-qualified # 💆🏼 E1.0 person getting massage: medium-light skin tone -1F486 1F3FD ; fully-qualified # 💆🏽 E1.0 person getting massage: medium skin tone -1F486 1F3FE ; fully-qualified # 💆🏾 E1.0 person getting massage: medium-dark skin tone -1F486 1F3FF ; fully-qualified # 💆🏿 E1.0 person getting massage: dark skin tone -1F486 200D 2642 FE0F ; fully-qualified # 💆‍♂️ E4.0 man getting massage -1F486 200D 2642 ; minimally-qualified # 💆‍♂ E4.0 man getting massage -1F486 1F3FB 200D 2642 FE0F ; fully-qualified # 💆🏻‍♂️ E4.0 man getting massage: light skin tone -1F486 1F3FB 200D 2642 ; minimally-qualified # 💆🏻‍♂ E4.0 man getting massage: light skin tone -1F486 1F3FC 200D 2642 FE0F ; fully-qualified # 💆🏼‍♂️ E4.0 man getting massage: medium-light skin tone -1F486 1F3FC 200D 2642 ; minimally-qualified # 💆🏼‍♂ E4.0 man getting massage: medium-light skin tone -1F486 1F3FD 200D 2642 FE0F ; fully-qualified # 💆🏽‍♂️ E4.0 man getting massage: medium skin tone -1F486 1F3FD 200D 2642 ; minimally-qualified # 💆🏽‍♂ E4.0 man getting massage: medium skin tone -1F486 1F3FE 200D 2642 FE0F ; fully-qualified # 💆🏾‍♂️ E4.0 man getting massage: medium-dark skin tone -1F486 1F3FE 200D 2642 ; minimally-qualified # 💆🏾‍♂ E4.0 man getting massage: medium-dark skin tone -1F486 1F3FF 200D 2642 FE0F ; fully-qualified # 💆🏿‍♂️ E4.0 man getting massage: dark skin tone -1F486 1F3FF 200D 2642 ; minimally-qualified # 💆🏿‍♂ E4.0 man getting massage: dark skin tone -1F486 200D 2640 FE0F ; fully-qualified # 💆‍♀️ E4.0 woman getting massage -1F486 200D 2640 ; minimally-qualified # 💆‍♀ E4.0 woman getting massage -1F486 1F3FB 200D 2640 FE0F ; fully-qualified # 💆🏻‍♀️ E4.0 woman getting massage: light skin tone -1F486 1F3FB 200D 2640 ; minimally-qualified # 💆🏻‍♀ E4.0 woman getting massage: light skin tone -1F486 1F3FC 200D 2640 FE0F ; fully-qualified # 💆🏼‍♀️ E4.0 woman getting massage: medium-light skin tone -1F486 1F3FC 200D 2640 ; minimally-qualified # 💆🏼‍♀ E4.0 woman getting massage: medium-light skin tone -1F486 1F3FD 200D 2640 FE0F ; fully-qualified # 💆🏽‍♀️ E4.0 woman getting massage: medium skin tone -1F486 1F3FD 200D 2640 ; minimally-qualified # 💆🏽‍♀ E4.0 woman getting massage: medium skin tone -1F486 1F3FE 200D 2640 FE0F ; fully-qualified # 💆🏾‍♀️ E4.0 woman getting massage: medium-dark skin tone -1F486 1F3FE 200D 2640 ; minimally-qualified # 💆🏾‍♀ E4.0 woman getting massage: medium-dark skin tone -1F486 1F3FF 200D 2640 FE0F ; fully-qualified # 💆🏿‍♀️ E4.0 woman getting massage: dark skin tone -1F486 1F3FF 200D 2640 ; minimally-qualified # 💆🏿‍♀ E4.0 woman getting massage: dark skin tone -1F487 ; fully-qualified # 💇 E0.6 person getting haircut -1F487 1F3FB ; fully-qualified # 💇🏻 E1.0 person getting haircut: light skin tone -1F487 1F3FC ; fully-qualified # 💇🏼 E1.0 person getting haircut: medium-light skin tone -1F487 1F3FD ; fully-qualified # 💇🏽 E1.0 person getting haircut: medium skin tone -1F487 1F3FE ; fully-qualified # 💇🏾 E1.0 person getting haircut: medium-dark skin tone -1F487 1F3FF ; fully-qualified # 💇🏿 E1.0 person getting haircut: dark skin tone -1F487 200D 2642 FE0F ; fully-qualified # 💇‍♂️ E4.0 man getting haircut -1F487 200D 2642 ; minimally-qualified # 💇‍♂ E4.0 man getting haircut -1F487 1F3FB 200D 2642 FE0F ; fully-qualified # 💇🏻‍♂️ E4.0 man getting haircut: light skin tone -1F487 1F3FB 200D 2642 ; minimally-qualified # 💇🏻‍♂ E4.0 man getting haircut: light skin tone -1F487 1F3FC 200D 2642 FE0F ; fully-qualified # 💇🏼‍♂️ E4.0 man getting haircut: medium-light skin tone -1F487 1F3FC 200D 2642 ; minimally-qualified # 💇🏼‍♂ E4.0 man getting haircut: medium-light skin tone -1F487 1F3FD 200D 2642 FE0F ; fully-qualified # 💇🏽‍♂️ E4.0 man getting haircut: medium skin tone -1F487 1F3FD 200D 2642 ; minimally-qualified # 💇🏽‍♂ E4.0 man getting haircut: medium skin tone -1F487 1F3FE 200D 2642 FE0F ; fully-qualified # 💇🏾‍♂️ E4.0 man getting haircut: medium-dark skin tone -1F487 1F3FE 200D 2642 ; minimally-qualified # 💇🏾‍♂ E4.0 man getting haircut: medium-dark skin tone -1F487 1F3FF 200D 2642 FE0F ; fully-qualified # 💇🏿‍♂️ E4.0 man getting haircut: dark skin tone -1F487 1F3FF 200D 2642 ; minimally-qualified # 💇🏿‍♂ E4.0 man getting haircut: dark skin tone -1F487 200D 2640 FE0F ; fully-qualified # 💇‍♀️ E4.0 woman getting haircut -1F487 200D 2640 ; minimally-qualified # 💇‍♀ E4.0 woman getting haircut -1F487 1F3FB 200D 2640 FE0F ; fully-qualified # 💇🏻‍♀️ E4.0 woman getting haircut: light skin tone -1F487 1F3FB 200D 2640 ; minimally-qualified # 💇🏻‍♀ E4.0 woman getting haircut: light skin tone -1F487 1F3FC 200D 2640 FE0F ; fully-qualified # 💇🏼‍♀️ E4.0 woman getting haircut: medium-light skin tone -1F487 1F3FC 200D 2640 ; minimally-qualified # 💇🏼‍♀ E4.0 woman getting haircut: medium-light skin tone -1F487 1F3FD 200D 2640 FE0F ; fully-qualified # 💇🏽‍♀️ E4.0 woman getting haircut: medium skin tone -1F487 1F3FD 200D 2640 ; minimally-qualified # 💇🏽‍♀ E4.0 woman getting haircut: medium skin tone -1F487 1F3FE 200D 2640 FE0F ; fully-qualified # 💇🏾‍♀️ E4.0 woman getting haircut: medium-dark skin tone -1F487 1F3FE 200D 2640 ; minimally-qualified # 💇🏾‍♀ E4.0 woman getting haircut: medium-dark skin tone -1F487 1F3FF 200D 2640 FE0F ; fully-qualified # 💇🏿‍♀️ E4.0 woman getting haircut: dark skin tone -1F487 1F3FF 200D 2640 ; minimally-qualified # 💇🏿‍♀ E4.0 woman getting haircut: dark skin tone -1F6B6 ; fully-qualified # 🚶 E0.6 person walking -1F6B6 1F3FB ; fully-qualified # 🚶🏻 E1.0 person walking: light skin tone -1F6B6 1F3FC ; fully-qualified # 🚶🏼 E1.0 person walking: medium-light skin tone -1F6B6 1F3FD ; fully-qualified # 🚶🏽 E1.0 person walking: medium skin tone -1F6B6 1F3FE ; fully-qualified # 🚶🏾 E1.0 person walking: medium-dark skin tone -1F6B6 1F3FF ; fully-qualified # 🚶🏿 E1.0 person walking: dark skin tone -1F6B6 200D 2642 FE0F ; fully-qualified # 🚶‍♂️ E4.0 man walking -1F6B6 200D 2642 ; minimally-qualified # 🚶‍♂ E4.0 man walking -1F6B6 1F3FB 200D 2642 FE0F ; fully-qualified # 🚶🏻‍♂️ E4.0 man walking: light skin tone -1F6B6 1F3FB 200D 2642 ; minimally-qualified # 🚶🏻‍♂ E4.0 man walking: light skin tone -1F6B6 1F3FC 200D 2642 FE0F ; fully-qualified # 🚶🏼‍♂️ E4.0 man walking: medium-light skin tone -1F6B6 1F3FC 200D 2642 ; minimally-qualified # 🚶🏼‍♂ E4.0 man walking: medium-light skin tone -1F6B6 1F3FD 200D 2642 FE0F ; fully-qualified # 🚶🏽‍♂️ E4.0 man walking: medium skin tone -1F6B6 1F3FD 200D 2642 ; minimally-qualified # 🚶🏽‍♂ E4.0 man walking: medium skin tone -1F6B6 1F3FE 200D 2642 FE0F ; fully-qualified # 🚶🏾‍♂️ E4.0 man walking: medium-dark skin tone -1F6B6 1F3FE 200D 2642 ; minimally-qualified # 🚶🏾‍♂ E4.0 man walking: medium-dark skin tone -1F6B6 1F3FF 200D 2642 FE0F ; fully-qualified # 🚶🏿‍♂️ E4.0 man walking: dark skin tone -1F6B6 1F3FF 200D 2642 ; minimally-qualified # 🚶🏿‍♂ E4.0 man walking: dark skin tone -1F6B6 200D 2640 FE0F ; fully-qualified # 🚶‍♀️ E4.0 woman walking -1F6B6 200D 2640 ; minimally-qualified # 🚶‍♀ E4.0 woman walking -1F6B6 1F3FB 200D 2640 FE0F ; fully-qualified # 🚶🏻‍♀️ E4.0 woman walking: light skin tone -1F6B6 1F3FB 200D 2640 ; minimally-qualified # 🚶🏻‍♀ E4.0 woman walking: light skin tone -1F6B6 1F3FC 200D 2640 FE0F ; fully-qualified # 🚶🏼‍♀️ E4.0 woman walking: medium-light skin tone -1F6B6 1F3FC 200D 2640 ; minimally-qualified # 🚶🏼‍♀ E4.0 woman walking: medium-light skin tone -1F6B6 1F3FD 200D 2640 FE0F ; fully-qualified # 🚶🏽‍♀️ E4.0 woman walking: medium skin tone -1F6B6 1F3FD 200D 2640 ; minimally-qualified # 🚶🏽‍♀ E4.0 woman walking: medium skin tone -1F6B6 1F3FE 200D 2640 FE0F ; fully-qualified # 🚶🏾‍♀️ E4.0 woman walking: medium-dark skin tone -1F6B6 1F3FE 200D 2640 ; minimally-qualified # 🚶🏾‍♀ E4.0 woman walking: medium-dark skin tone -1F6B6 1F3FF 200D 2640 FE0F ; fully-qualified # 🚶🏿‍♀️ E4.0 woman walking: dark skin tone -1F6B6 1F3FF 200D 2640 ; minimally-qualified # 🚶🏿‍♀ E4.0 woman walking: dark skin tone -1F9CD ; fully-qualified # 🧍 E12.0 person standing -1F9CD 1F3FB ; fully-qualified # 🧍🏻 E12.0 person standing: light skin tone -1F9CD 1F3FC ; fully-qualified # 🧍🏼 E12.0 person standing: medium-light skin tone -1F9CD 1F3FD ; fully-qualified # 🧍🏽 E12.0 person standing: medium skin tone -1F9CD 1F3FE ; fully-qualified # 🧍🏾 E12.0 person standing: medium-dark skin tone -1F9CD 1F3FF ; fully-qualified # 🧍🏿 E12.0 person standing: dark skin tone -1F9CD 200D 2642 FE0F ; fully-qualified # 🧍‍♂️ E12.0 man standing -1F9CD 200D 2642 ; minimally-qualified # 🧍‍♂ E12.0 man standing -1F9CD 1F3FB 200D 2642 FE0F ; fully-qualified # 🧍🏻‍♂️ E12.0 man standing: light skin tone -1F9CD 1F3FB 200D 2642 ; minimally-qualified # 🧍🏻‍♂ E12.0 man standing: light skin tone -1F9CD 1F3FC 200D 2642 FE0F ; fully-qualified # 🧍🏼‍♂️ E12.0 man standing: medium-light skin tone -1F9CD 1F3FC 200D 2642 ; minimally-qualified # 🧍🏼‍♂ E12.0 man standing: medium-light skin tone -1F9CD 1F3FD 200D 2642 FE0F ; fully-qualified # 🧍🏽‍♂️ E12.0 man standing: medium skin tone -1F9CD 1F3FD 200D 2642 ; minimally-qualified # 🧍🏽‍♂ E12.0 man standing: medium skin tone -1F9CD 1F3FE 200D 2642 FE0F ; fully-qualified # 🧍🏾‍♂️ E12.0 man standing: medium-dark skin tone -1F9CD 1F3FE 200D 2642 ; minimally-qualified # 🧍🏾‍♂ E12.0 man standing: medium-dark skin tone -1F9CD 1F3FF 200D 2642 FE0F ; fully-qualified # 🧍🏿‍♂️ E12.0 man standing: dark skin tone -1F9CD 1F3FF 200D 2642 ; minimally-qualified # 🧍🏿‍♂ E12.0 man standing: dark skin tone -1F9CD 200D 2640 FE0F ; fully-qualified # 🧍‍♀️ E12.0 woman standing -1F9CD 200D 2640 ; minimally-qualified # 🧍‍♀ E12.0 woman standing -1F9CD 1F3FB 200D 2640 FE0F ; fully-qualified # 🧍🏻‍♀️ E12.0 woman standing: light skin tone -1F9CD 1F3FB 200D 2640 ; minimally-qualified # 🧍🏻‍♀ E12.0 woman standing: light skin tone -1F9CD 1F3FC 200D 2640 FE0F ; fully-qualified # 🧍🏼‍♀️ E12.0 woman standing: medium-light skin tone -1F9CD 1F3FC 200D 2640 ; minimally-qualified # 🧍🏼‍♀ E12.0 woman standing: medium-light skin tone -1F9CD 1F3FD 200D 2640 FE0F ; fully-qualified # 🧍🏽‍♀️ E12.0 woman standing: medium skin tone -1F9CD 1F3FD 200D 2640 ; minimally-qualified # 🧍🏽‍♀ E12.0 woman standing: medium skin tone -1F9CD 1F3FE 200D 2640 FE0F ; fully-qualified # 🧍🏾‍♀️ E12.0 woman standing: medium-dark skin tone -1F9CD 1F3FE 200D 2640 ; minimally-qualified # 🧍🏾‍♀ E12.0 woman standing: medium-dark skin tone -1F9CD 1F3FF 200D 2640 FE0F ; fully-qualified # 🧍🏿‍♀️ E12.0 woman standing: dark skin tone -1F9CD 1F3FF 200D 2640 ; minimally-qualified # 🧍🏿‍♀ E12.0 woman standing: dark skin tone -1F9CE ; fully-qualified # 🧎 E12.0 person kneeling -1F9CE 1F3FB ; fully-qualified # 🧎🏻 E12.0 person kneeling: light skin tone -1F9CE 1F3FC ; fully-qualified # 🧎🏼 E12.0 person kneeling: medium-light skin tone -1F9CE 1F3FD ; fully-qualified # 🧎🏽 E12.0 person kneeling: medium skin tone -1F9CE 1F3FE ; fully-qualified # 🧎🏾 E12.0 person kneeling: medium-dark skin tone -1F9CE 1F3FF ; fully-qualified # 🧎🏿 E12.0 person kneeling: dark skin tone -1F9CE 200D 2642 FE0F ; fully-qualified # 🧎‍♂️ E12.0 man kneeling -1F9CE 200D 2642 ; minimally-qualified # 🧎‍♂ E12.0 man kneeling -1F9CE 1F3FB 200D 2642 FE0F ; fully-qualified # 🧎🏻‍♂️ E12.0 man kneeling: light skin tone -1F9CE 1F3FB 200D 2642 ; minimally-qualified # 🧎🏻‍♂ E12.0 man kneeling: light skin tone -1F9CE 1F3FC 200D 2642 FE0F ; fully-qualified # 🧎🏼‍♂️ E12.0 man kneeling: medium-light skin tone -1F9CE 1F3FC 200D 2642 ; minimally-qualified # 🧎🏼‍♂ E12.0 man kneeling: medium-light skin tone -1F9CE 1F3FD 200D 2642 FE0F ; fully-qualified # 🧎🏽‍♂️ E12.0 man kneeling: medium skin tone -1F9CE 1F3FD 200D 2642 ; minimally-qualified # 🧎🏽‍♂ E12.0 man kneeling: medium skin tone -1F9CE 1F3FE 200D 2642 FE0F ; fully-qualified # 🧎🏾‍♂️ E12.0 man kneeling: medium-dark skin tone -1F9CE 1F3FE 200D 2642 ; minimally-qualified # 🧎🏾‍♂ E12.0 man kneeling: medium-dark skin tone -1F9CE 1F3FF 200D 2642 FE0F ; fully-qualified # 🧎🏿‍♂️ E12.0 man kneeling: dark skin tone -1F9CE 1F3FF 200D 2642 ; minimally-qualified # 🧎🏿‍♂ E12.0 man kneeling: dark skin tone -1F9CE 200D 2640 FE0F ; fully-qualified # 🧎‍♀️ E12.0 woman kneeling -1F9CE 200D 2640 ; minimally-qualified # 🧎‍♀ E12.0 woman kneeling -1F9CE 1F3FB 200D 2640 FE0F ; fully-qualified # 🧎🏻‍♀️ E12.0 woman kneeling: light skin tone -1F9CE 1F3FB 200D 2640 ; minimally-qualified # 🧎🏻‍♀ E12.0 woman kneeling: light skin tone -1F9CE 1F3FC 200D 2640 FE0F ; fully-qualified # 🧎🏼‍♀️ E12.0 woman kneeling: medium-light skin tone -1F9CE 1F3FC 200D 2640 ; minimally-qualified # 🧎🏼‍♀ E12.0 woman kneeling: medium-light skin tone -1F9CE 1F3FD 200D 2640 FE0F ; fully-qualified # 🧎🏽‍♀️ E12.0 woman kneeling: medium skin tone -1F9CE 1F3FD 200D 2640 ; minimally-qualified # 🧎🏽‍♀ E12.0 woman kneeling: medium skin tone -1F9CE 1F3FE 200D 2640 FE0F ; fully-qualified # 🧎🏾‍♀️ E12.0 woman kneeling: medium-dark skin tone -1F9CE 1F3FE 200D 2640 ; minimally-qualified # 🧎🏾‍♀ E12.0 woman kneeling: medium-dark skin tone -1F9CE 1F3FF 200D 2640 FE0F ; fully-qualified # 🧎🏿‍♀️ E12.0 woman kneeling: dark skin tone -1F9CE 1F3FF 200D 2640 ; minimally-qualified # 🧎🏿‍♀ E12.0 woman kneeling: dark skin tone -1F9D1 200D 1F9AF ; fully-qualified # 🧑‍🦯 E12.1 person with white cane -1F9D1 1F3FB 200D 1F9AF ; fully-qualified # 🧑🏻‍🦯 E12.1 person with white cane: light skin tone -1F9D1 1F3FC 200D 1F9AF ; fully-qualified # 🧑🏼‍🦯 E12.1 person with white cane: medium-light skin tone -1F9D1 1F3FD 200D 1F9AF ; fully-qualified # 🧑🏽‍🦯 E12.1 person with white cane: medium skin tone -1F9D1 1F3FE 200D 1F9AF ; fully-qualified # 🧑🏾‍🦯 E12.1 person with white cane: medium-dark skin tone -1F9D1 1F3FF 200D 1F9AF ; fully-qualified # 🧑🏿‍🦯 E12.1 person with white cane: dark skin tone -1F468 200D 1F9AF ; fully-qualified # 👨‍🦯 E12.0 man with white cane -1F468 1F3FB 200D 1F9AF ; fully-qualified # 👨🏻‍🦯 E12.0 man with white cane: light skin tone -1F468 1F3FC 200D 1F9AF ; fully-qualified # 👨🏼‍🦯 E12.0 man with white cane: medium-light skin tone -1F468 1F3FD 200D 1F9AF ; fully-qualified # 👨🏽‍🦯 E12.0 man with white cane: medium skin tone -1F468 1F3FE 200D 1F9AF ; fully-qualified # 👨🏾‍🦯 E12.0 man with white cane: medium-dark skin tone -1F468 1F3FF 200D 1F9AF ; fully-qualified # 👨🏿‍🦯 E12.0 man with white cane: dark skin tone -1F469 200D 1F9AF ; fully-qualified # 👩‍🦯 E12.0 woman with white cane -1F469 1F3FB 200D 1F9AF ; fully-qualified # 👩🏻‍🦯 E12.0 woman with white cane: light skin tone -1F469 1F3FC 200D 1F9AF ; fully-qualified # 👩🏼‍🦯 E12.0 woman with white cane: medium-light skin tone -1F469 1F3FD 200D 1F9AF ; fully-qualified # 👩🏽‍🦯 E12.0 woman with white cane: medium skin tone -1F469 1F3FE 200D 1F9AF ; fully-qualified # 👩🏾‍🦯 E12.0 woman with white cane: medium-dark skin tone -1F469 1F3FF 200D 1F9AF ; fully-qualified # 👩🏿‍🦯 E12.0 woman with white cane: dark skin tone -1F9D1 200D 1F9BC ; fully-qualified # 🧑‍🦼 E12.1 person in motorized wheelchair -1F9D1 1F3FB 200D 1F9BC ; fully-qualified # 🧑🏻‍🦼 E12.1 person in motorized wheelchair: light skin tone -1F9D1 1F3FC 200D 1F9BC ; fully-qualified # 🧑🏼‍🦼 E12.1 person in motorized wheelchair: medium-light skin tone -1F9D1 1F3FD 200D 1F9BC ; fully-qualified # 🧑🏽‍🦼 E12.1 person in motorized wheelchair: medium skin tone -1F9D1 1F3FE 200D 1F9BC ; fully-qualified # 🧑🏾‍🦼 E12.1 person in motorized wheelchair: medium-dark skin tone -1F9D1 1F3FF 200D 1F9BC ; fully-qualified # 🧑🏿‍🦼 E12.1 person in motorized wheelchair: dark skin tone -1F468 200D 1F9BC ; fully-qualified # 👨‍🦼 E12.0 man in motorized wheelchair -1F468 1F3FB 200D 1F9BC ; fully-qualified # 👨🏻‍🦼 E12.0 man in motorized wheelchair: light skin tone -1F468 1F3FC 200D 1F9BC ; fully-qualified # 👨🏼‍🦼 E12.0 man in motorized wheelchair: medium-light skin tone -1F468 1F3FD 200D 1F9BC ; fully-qualified # 👨🏽‍🦼 E12.0 man in motorized wheelchair: medium skin tone -1F468 1F3FE 200D 1F9BC ; fully-qualified # 👨🏾‍🦼 E12.0 man in motorized wheelchair: medium-dark skin tone -1F468 1F3FF 200D 1F9BC ; fully-qualified # 👨🏿‍🦼 E12.0 man in motorized wheelchair: dark skin tone -1F469 200D 1F9BC ; fully-qualified # 👩‍🦼 E12.0 woman in motorized wheelchair -1F469 1F3FB 200D 1F9BC ; fully-qualified # 👩🏻‍🦼 E12.0 woman in motorized wheelchair: light skin tone -1F469 1F3FC 200D 1F9BC ; fully-qualified # 👩🏼‍🦼 E12.0 woman in motorized wheelchair: medium-light skin tone -1F469 1F3FD 200D 1F9BC ; fully-qualified # 👩🏽‍🦼 E12.0 woman in motorized wheelchair: medium skin tone -1F469 1F3FE 200D 1F9BC ; fully-qualified # 👩🏾‍🦼 E12.0 woman in motorized wheelchair: medium-dark skin tone -1F469 1F3FF 200D 1F9BC ; fully-qualified # 👩🏿‍🦼 E12.0 woman in motorized wheelchair: dark skin tone -1F9D1 200D 1F9BD ; fully-qualified # 🧑‍🦽 E12.1 person in manual wheelchair -1F9D1 1F3FB 200D 1F9BD ; fully-qualified # 🧑🏻‍🦽 E12.1 person in manual wheelchair: light skin tone -1F9D1 1F3FC 200D 1F9BD ; fully-qualified # 🧑🏼‍🦽 E12.1 person in manual wheelchair: medium-light skin tone -1F9D1 1F3FD 200D 1F9BD ; fully-qualified # 🧑🏽‍🦽 E12.1 person in manual wheelchair: medium skin tone -1F9D1 1F3FE 200D 1F9BD ; fully-qualified # 🧑🏾‍🦽 E12.1 person in manual wheelchair: medium-dark skin tone -1F9D1 1F3FF 200D 1F9BD ; fully-qualified # 🧑🏿‍🦽 E12.1 person in manual wheelchair: dark skin tone -1F468 200D 1F9BD ; fully-qualified # 👨‍🦽 E12.0 man in manual wheelchair -1F468 1F3FB 200D 1F9BD ; fully-qualified # 👨🏻‍🦽 E12.0 man in manual wheelchair: light skin tone -1F468 1F3FC 200D 1F9BD ; fully-qualified # 👨🏼‍🦽 E12.0 man in manual wheelchair: medium-light skin tone -1F468 1F3FD 200D 1F9BD ; fully-qualified # 👨🏽‍🦽 E12.0 man in manual wheelchair: medium skin tone -1F468 1F3FE 200D 1F9BD ; fully-qualified # 👨🏾‍🦽 E12.0 man in manual wheelchair: medium-dark skin tone -1F468 1F3FF 200D 1F9BD ; fully-qualified # 👨🏿‍🦽 E12.0 man in manual wheelchair: dark skin tone -1F469 200D 1F9BD ; fully-qualified # 👩‍🦽 E12.0 woman in manual wheelchair -1F469 1F3FB 200D 1F9BD ; fully-qualified # 👩🏻‍🦽 E12.0 woman in manual wheelchair: light skin tone -1F469 1F3FC 200D 1F9BD ; fully-qualified # 👩🏼‍🦽 E12.0 woman in manual wheelchair: medium-light skin tone -1F469 1F3FD 200D 1F9BD ; fully-qualified # 👩🏽‍🦽 E12.0 woman in manual wheelchair: medium skin tone -1F469 1F3FE 200D 1F9BD ; fully-qualified # 👩🏾‍🦽 E12.0 woman in manual wheelchair: medium-dark skin tone -1F469 1F3FF 200D 1F9BD ; fully-qualified # 👩🏿‍🦽 E12.0 woman in manual wheelchair: dark skin tone -1F3C3 ; fully-qualified # 🏃 E0.6 person running -1F3C3 1F3FB ; fully-qualified # 🏃🏻 E1.0 person running: light skin tone -1F3C3 1F3FC ; fully-qualified # 🏃🏼 E1.0 person running: medium-light skin tone -1F3C3 1F3FD ; fully-qualified # 🏃🏽 E1.0 person running: medium skin tone -1F3C3 1F3FE ; fully-qualified # 🏃🏾 E1.0 person running: medium-dark skin tone -1F3C3 1F3FF ; fully-qualified # 🏃🏿 E1.0 person running: dark skin tone -1F3C3 200D 2642 FE0F ; fully-qualified # 🏃‍♂️ E4.0 man running -1F3C3 200D 2642 ; minimally-qualified # 🏃‍♂ E4.0 man running -1F3C3 1F3FB 200D 2642 FE0F ; fully-qualified # 🏃🏻‍♂️ E4.0 man running: light skin tone -1F3C3 1F3FB 200D 2642 ; minimally-qualified # 🏃🏻‍♂ E4.0 man running: light skin tone -1F3C3 1F3FC 200D 2642 FE0F ; fully-qualified # 🏃🏼‍♂️ E4.0 man running: medium-light skin tone -1F3C3 1F3FC 200D 2642 ; minimally-qualified # 🏃🏼‍♂ E4.0 man running: medium-light skin tone -1F3C3 1F3FD 200D 2642 FE0F ; fully-qualified # 🏃🏽‍♂️ E4.0 man running: medium skin tone -1F3C3 1F3FD 200D 2642 ; minimally-qualified # 🏃🏽‍♂ E4.0 man running: medium skin tone -1F3C3 1F3FE 200D 2642 FE0F ; fully-qualified # 🏃🏾‍♂️ E4.0 man running: medium-dark skin tone -1F3C3 1F3FE 200D 2642 ; minimally-qualified # 🏃🏾‍♂ E4.0 man running: medium-dark skin tone -1F3C3 1F3FF 200D 2642 FE0F ; fully-qualified # 🏃🏿‍♂️ E4.0 man running: dark skin tone -1F3C3 1F3FF 200D 2642 ; minimally-qualified # 🏃🏿‍♂ E4.0 man running: dark skin tone -1F3C3 200D 2640 FE0F ; fully-qualified # 🏃‍♀️ E4.0 woman running -1F3C3 200D 2640 ; minimally-qualified # 🏃‍♀ E4.0 woman running -1F3C3 1F3FB 200D 2640 FE0F ; fully-qualified # 🏃🏻‍♀️ E4.0 woman running: light skin tone -1F3C3 1F3FB 200D 2640 ; minimally-qualified # 🏃🏻‍♀ E4.0 woman running: light skin tone -1F3C3 1F3FC 200D 2640 FE0F ; fully-qualified # 🏃🏼‍♀️ E4.0 woman running: medium-light skin tone -1F3C3 1F3FC 200D 2640 ; minimally-qualified # 🏃🏼‍♀ E4.0 woman running: medium-light skin tone -1F3C3 1F3FD 200D 2640 FE0F ; fully-qualified # 🏃🏽‍♀️ E4.0 woman running: medium skin tone -1F3C3 1F3FD 200D 2640 ; minimally-qualified # 🏃🏽‍♀ E4.0 woman running: medium skin tone -1F3C3 1F3FE 200D 2640 FE0F ; fully-qualified # 🏃🏾‍♀️ E4.0 woman running: medium-dark skin tone -1F3C3 1F3FE 200D 2640 ; minimally-qualified # 🏃🏾‍♀ E4.0 woman running: medium-dark skin tone -1F3C3 1F3FF 200D 2640 FE0F ; fully-qualified # 🏃🏿‍♀️ E4.0 woman running: dark skin tone -1F3C3 1F3FF 200D 2640 ; minimally-qualified # 🏃🏿‍♀ E4.0 woman running: dark skin tone -1F483 ; fully-qualified # 💃 E0.6 woman dancing -1F483 1F3FB ; fully-qualified # 💃🏻 E1.0 woman dancing: light skin tone -1F483 1F3FC ; fully-qualified # 💃🏼 E1.0 woman dancing: medium-light skin tone -1F483 1F3FD ; fully-qualified # 💃🏽 E1.0 woman dancing: medium skin tone -1F483 1F3FE ; fully-qualified # 💃🏾 E1.0 woman dancing: medium-dark skin tone -1F483 1F3FF ; fully-qualified # 💃🏿 E1.0 woman dancing: dark skin tone -1F57A ; fully-qualified # 🕺 E3.0 man dancing -1F57A 1F3FB ; fully-qualified # 🕺🏻 E3.0 man dancing: light skin tone -1F57A 1F3FC ; fully-qualified # 🕺🏼 E3.0 man dancing: medium-light skin tone -1F57A 1F3FD ; fully-qualified # 🕺🏽 E3.0 man dancing: medium skin tone -1F57A 1F3FE ; fully-qualified # 🕺🏾 E3.0 man dancing: medium-dark skin tone -1F57A 1F3FF ; fully-qualified # 🕺🏿 E3.0 man dancing: dark skin tone -1F574 FE0F ; fully-qualified # 🕴️ E0.7 person in suit levitating -1F574 ; unqualified # 🕴 E0.7 person in suit levitating -1F574 1F3FB ; fully-qualified # 🕴🏻 E4.0 person in suit levitating: light skin tone -1F574 1F3FC ; fully-qualified # 🕴🏼 E4.0 person in suit levitating: medium-light skin tone -1F574 1F3FD ; fully-qualified # 🕴🏽 E4.0 person in suit levitating: medium skin tone -1F574 1F3FE ; fully-qualified # 🕴🏾 E4.0 person in suit levitating: medium-dark skin tone -1F574 1F3FF ; fully-qualified # 🕴🏿 E4.0 person in suit levitating: dark skin tone -1F46F ; fully-qualified # 👯 E0.6 people with bunny ears -1F46F 200D 2642 FE0F ; fully-qualified # 👯‍♂️ E4.0 men with bunny ears -1F46F 200D 2642 ; minimally-qualified # 👯‍♂ E4.0 men with bunny ears -1F46F 200D 2640 FE0F ; fully-qualified # 👯‍♀️ E4.0 women with bunny ears -1F46F 200D 2640 ; minimally-qualified # 👯‍♀ E4.0 women with bunny ears -1F9D6 ; fully-qualified # 🧖 E5.0 person in steamy room -1F9D6 1F3FB ; fully-qualified # 🧖🏻 E5.0 person in steamy room: light skin tone -1F9D6 1F3FC ; fully-qualified # 🧖🏼 E5.0 person in steamy room: medium-light skin tone -1F9D6 1F3FD ; fully-qualified # 🧖🏽 E5.0 person in steamy room: medium skin tone -1F9D6 1F3FE ; fully-qualified # 🧖🏾 E5.0 person in steamy room: medium-dark skin tone -1F9D6 1F3FF ; fully-qualified # 🧖🏿 E5.0 person in steamy room: dark skin tone -1F9D6 200D 2642 FE0F ; fully-qualified # 🧖‍♂️ E5.0 man in steamy room -1F9D6 200D 2642 ; minimally-qualified # 🧖‍♂ E5.0 man in steamy room -1F9D6 1F3FB 200D 2642 FE0F ; fully-qualified # 🧖🏻‍♂️ E5.0 man in steamy room: light skin tone -1F9D6 1F3FB 200D 2642 ; minimally-qualified # 🧖🏻‍♂ E5.0 man in steamy room: light skin tone -1F9D6 1F3FC 200D 2642 FE0F ; fully-qualified # 🧖🏼‍♂️ E5.0 man in steamy room: medium-light skin tone -1F9D6 1F3FC 200D 2642 ; minimally-qualified # 🧖🏼‍♂ E5.0 man in steamy room: medium-light skin tone -1F9D6 1F3FD 200D 2642 FE0F ; fully-qualified # 🧖🏽‍♂️ E5.0 man in steamy room: medium skin tone -1F9D6 1F3FD 200D 2642 ; minimally-qualified # 🧖🏽‍♂ E5.0 man in steamy room: medium skin tone -1F9D6 1F3FE 200D 2642 FE0F ; fully-qualified # 🧖🏾‍♂️ E5.0 man in steamy room: medium-dark skin tone -1F9D6 1F3FE 200D 2642 ; minimally-qualified # 🧖🏾‍♂ E5.0 man in steamy room: medium-dark skin tone -1F9D6 1F3FF 200D 2642 FE0F ; fully-qualified # 🧖🏿‍♂️ E5.0 man in steamy room: dark skin tone -1F9D6 1F3FF 200D 2642 ; minimally-qualified # 🧖🏿‍♂ E5.0 man in steamy room: dark skin tone -1F9D6 200D 2640 FE0F ; fully-qualified # 🧖‍♀️ E5.0 woman in steamy room -1F9D6 200D 2640 ; minimally-qualified # 🧖‍♀ E5.0 woman in steamy room -1F9D6 1F3FB 200D 2640 FE0F ; fully-qualified # 🧖🏻‍♀️ E5.0 woman in steamy room: light skin tone -1F9D6 1F3FB 200D 2640 ; minimally-qualified # 🧖🏻‍♀ E5.0 woman in steamy room: light skin tone -1F9D6 1F3FC 200D 2640 FE0F ; fully-qualified # 🧖🏼‍♀️ E5.0 woman in steamy room: medium-light skin tone -1F9D6 1F3FC 200D 2640 ; minimally-qualified # 🧖🏼‍♀ E5.0 woman in steamy room: medium-light skin tone -1F9D6 1F3FD 200D 2640 FE0F ; fully-qualified # 🧖🏽‍♀️ E5.0 woman in steamy room: medium skin tone -1F9D6 1F3FD 200D 2640 ; minimally-qualified # 🧖🏽‍♀ E5.0 woman in steamy room: medium skin tone -1F9D6 1F3FE 200D 2640 FE0F ; fully-qualified # 🧖🏾‍♀️ E5.0 woman in steamy room: medium-dark skin tone -1F9D6 1F3FE 200D 2640 ; minimally-qualified # 🧖🏾‍♀ E5.0 woman in steamy room: medium-dark skin tone -1F9D6 1F3FF 200D 2640 FE0F ; fully-qualified # 🧖🏿‍♀️ E5.0 woman in steamy room: dark skin tone -1F9D6 1F3FF 200D 2640 ; minimally-qualified # 🧖🏿‍♀ E5.0 woman in steamy room: dark skin tone -1F9D7 ; fully-qualified # 🧗 E5.0 person climbing -1F9D7 1F3FB ; fully-qualified # 🧗🏻 E5.0 person climbing: light skin tone -1F9D7 1F3FC ; fully-qualified # 🧗🏼 E5.0 person climbing: medium-light skin tone -1F9D7 1F3FD ; fully-qualified # 🧗🏽 E5.0 person climbing: medium skin tone -1F9D7 1F3FE ; fully-qualified # 🧗🏾 E5.0 person climbing: medium-dark skin tone -1F9D7 1F3FF ; fully-qualified # 🧗🏿 E5.0 person climbing: dark skin tone -1F9D7 200D 2642 FE0F ; fully-qualified # 🧗‍♂️ E5.0 man climbing -1F9D7 200D 2642 ; minimally-qualified # 🧗‍♂ E5.0 man climbing -1F9D7 1F3FB 200D 2642 FE0F ; fully-qualified # 🧗🏻‍♂️ E5.0 man climbing: light skin tone -1F9D7 1F3FB 200D 2642 ; minimally-qualified # 🧗🏻‍♂ E5.0 man climbing: light skin tone -1F9D7 1F3FC 200D 2642 FE0F ; fully-qualified # 🧗🏼‍♂️ E5.0 man climbing: medium-light skin tone -1F9D7 1F3FC 200D 2642 ; minimally-qualified # 🧗🏼‍♂ E5.0 man climbing: medium-light skin tone -1F9D7 1F3FD 200D 2642 FE0F ; fully-qualified # 🧗🏽‍♂️ E5.0 man climbing: medium skin tone -1F9D7 1F3FD 200D 2642 ; minimally-qualified # 🧗🏽‍♂ E5.0 man climbing: medium skin tone -1F9D7 1F3FE 200D 2642 FE0F ; fully-qualified # 🧗🏾‍♂️ E5.0 man climbing: medium-dark skin tone -1F9D7 1F3FE 200D 2642 ; minimally-qualified # 🧗🏾‍♂ E5.0 man climbing: medium-dark skin tone -1F9D7 1F3FF 200D 2642 FE0F ; fully-qualified # 🧗🏿‍♂️ E5.0 man climbing: dark skin tone -1F9D7 1F3FF 200D 2642 ; minimally-qualified # 🧗🏿‍♂ E5.0 man climbing: dark skin tone -1F9D7 200D 2640 FE0F ; fully-qualified # 🧗‍♀️ E5.0 woman climbing -1F9D7 200D 2640 ; minimally-qualified # 🧗‍♀ E5.0 woman climbing -1F9D7 1F3FB 200D 2640 FE0F ; fully-qualified # 🧗🏻‍♀️ E5.0 woman climbing: light skin tone -1F9D7 1F3FB 200D 2640 ; minimally-qualified # 🧗🏻‍♀ E5.0 woman climbing: light skin tone -1F9D7 1F3FC 200D 2640 FE0F ; fully-qualified # 🧗🏼‍♀️ E5.0 woman climbing: medium-light skin tone -1F9D7 1F3FC 200D 2640 ; minimally-qualified # 🧗🏼‍♀ E5.0 woman climbing: medium-light skin tone -1F9D7 1F3FD 200D 2640 FE0F ; fully-qualified # 🧗🏽‍♀️ E5.0 woman climbing: medium skin tone -1F9D7 1F3FD 200D 2640 ; minimally-qualified # 🧗🏽‍♀ E5.0 woman climbing: medium skin tone -1F9D7 1F3FE 200D 2640 FE0F ; fully-qualified # 🧗🏾‍♀️ E5.0 woman climbing: medium-dark skin tone -1F9D7 1F3FE 200D 2640 ; minimally-qualified # 🧗🏾‍♀ E5.0 woman climbing: medium-dark skin tone -1F9D7 1F3FF 200D 2640 FE0F ; fully-qualified # 🧗🏿‍♀️ E5.0 woman climbing: dark skin tone -1F9D7 1F3FF 200D 2640 ; minimally-qualified # 🧗🏿‍♀ E5.0 woman climbing: dark skin tone - -# subgroup: person-sport -1F93A ; fully-qualified # 🤺 E3.0 person fencing -1F3C7 ; fully-qualified # 🏇 E1.0 horse racing -1F3C7 1F3FB ; fully-qualified # 🏇🏻 E1.0 horse racing: light skin tone -1F3C7 1F3FC ; fully-qualified # 🏇🏼 E1.0 horse racing: medium-light skin tone -1F3C7 1F3FD ; fully-qualified # 🏇🏽 E1.0 horse racing: medium skin tone -1F3C7 1F3FE ; fully-qualified # 🏇🏾 E1.0 horse racing: medium-dark skin tone -1F3C7 1F3FF ; fully-qualified # 🏇🏿 E1.0 horse racing: dark skin tone -26F7 FE0F ; fully-qualified # ⛷️ E0.7 skier -26F7 ; unqualified # ⛷ E0.7 skier -1F3C2 ; fully-qualified # 🏂 E0.6 snowboarder -1F3C2 1F3FB ; fully-qualified # 🏂🏻 E1.0 snowboarder: light skin tone -1F3C2 1F3FC ; fully-qualified # 🏂🏼 E1.0 snowboarder: medium-light skin tone -1F3C2 1F3FD ; fully-qualified # 🏂🏽 E1.0 snowboarder: medium skin tone -1F3C2 1F3FE ; fully-qualified # 🏂🏾 E1.0 snowboarder: medium-dark skin tone -1F3C2 1F3FF ; fully-qualified # 🏂🏿 E1.0 snowboarder: dark skin tone -1F3CC FE0F ; fully-qualified # 🏌️ E0.7 person golfing -1F3CC ; unqualified # 🏌 E0.7 person golfing -1F3CC 1F3FB ; fully-qualified # 🏌🏻 E4.0 person golfing: light skin tone -1F3CC 1F3FC ; fully-qualified # 🏌🏼 E4.0 person golfing: medium-light skin tone -1F3CC 1F3FD ; fully-qualified # 🏌🏽 E4.0 person golfing: medium skin tone -1F3CC 1F3FE ; fully-qualified # 🏌🏾 E4.0 person golfing: medium-dark skin tone -1F3CC 1F3FF ; fully-qualified # 🏌🏿 E4.0 person golfing: dark skin tone -1F3CC FE0F 200D 2642 FE0F ; fully-qualified # 🏌️‍♂️ E4.0 man golfing -1F3CC 200D 2642 FE0F ; unqualified # 🏌‍♂️ E4.0 man golfing -1F3CC FE0F 200D 2642 ; minimally-qualified # 🏌️‍♂ E4.0 man golfing -1F3CC 200D 2642 ; unqualified # 🏌‍♂ E4.0 man golfing -1F3CC 1F3FB 200D 2642 FE0F ; fully-qualified # 🏌🏻‍♂️ E4.0 man golfing: light skin tone -1F3CC 1F3FB 200D 2642 ; minimally-qualified # 🏌🏻‍♂ E4.0 man golfing: light skin tone -1F3CC 1F3FC 200D 2642 FE0F ; fully-qualified # 🏌🏼‍♂️ E4.0 man golfing: medium-light skin tone -1F3CC 1F3FC 200D 2642 ; minimally-qualified # 🏌🏼‍♂ E4.0 man golfing: medium-light skin tone -1F3CC 1F3FD 200D 2642 FE0F ; fully-qualified # 🏌🏽‍♂️ E4.0 man golfing: medium skin tone -1F3CC 1F3FD 200D 2642 ; minimally-qualified # 🏌🏽‍♂ E4.0 man golfing: medium skin tone -1F3CC 1F3FE 200D 2642 FE0F ; fully-qualified # 🏌🏾‍♂️ E4.0 man golfing: medium-dark skin tone -1F3CC 1F3FE 200D 2642 ; minimally-qualified # 🏌🏾‍♂ E4.0 man golfing: medium-dark skin tone -1F3CC 1F3FF 200D 2642 FE0F ; fully-qualified # 🏌🏿‍♂️ E4.0 man golfing: dark skin tone -1F3CC 1F3FF 200D 2642 ; minimally-qualified # 🏌🏿‍♂ E4.0 man golfing: dark skin tone -1F3CC FE0F 200D 2640 FE0F ; fully-qualified # 🏌️‍♀️ E4.0 woman golfing -1F3CC 200D 2640 FE0F ; unqualified # 🏌‍♀️ E4.0 woman golfing -1F3CC FE0F 200D 2640 ; minimally-qualified # 🏌️‍♀ E4.0 woman golfing -1F3CC 200D 2640 ; unqualified # 🏌‍♀ E4.0 woman golfing -1F3CC 1F3FB 200D 2640 FE0F ; fully-qualified # 🏌🏻‍♀️ E4.0 woman golfing: light skin tone -1F3CC 1F3FB 200D 2640 ; minimally-qualified # 🏌🏻‍♀ E4.0 woman golfing: light skin tone -1F3CC 1F3FC 200D 2640 FE0F ; fully-qualified # 🏌🏼‍♀️ E4.0 woman golfing: medium-light skin tone -1F3CC 1F3FC 200D 2640 ; minimally-qualified # 🏌🏼‍♀ E4.0 woman golfing: medium-light skin tone -1F3CC 1F3FD 200D 2640 FE0F ; fully-qualified # 🏌🏽‍♀️ E4.0 woman golfing: medium skin tone -1F3CC 1F3FD 200D 2640 ; minimally-qualified # 🏌🏽‍♀ E4.0 woman golfing: medium skin tone -1F3CC 1F3FE 200D 2640 FE0F ; fully-qualified # 🏌🏾‍♀️ E4.0 woman golfing: medium-dark skin tone -1F3CC 1F3FE 200D 2640 ; minimally-qualified # 🏌🏾‍♀ E4.0 woman golfing: medium-dark skin tone -1F3CC 1F3FF 200D 2640 FE0F ; fully-qualified # 🏌🏿‍♀️ E4.0 woman golfing: dark skin tone -1F3CC 1F3FF 200D 2640 ; minimally-qualified # 🏌🏿‍♀ E4.0 woman golfing: dark skin tone -1F3C4 ; fully-qualified # 🏄 E0.6 person surfing -1F3C4 1F3FB ; fully-qualified # 🏄🏻 E1.0 person surfing: light skin tone -1F3C4 1F3FC ; fully-qualified # 🏄🏼 E1.0 person surfing: medium-light skin tone -1F3C4 1F3FD ; fully-qualified # 🏄🏽 E1.0 person surfing: medium skin tone -1F3C4 1F3FE ; fully-qualified # 🏄🏾 E1.0 person surfing: medium-dark skin tone -1F3C4 1F3FF ; fully-qualified # 🏄🏿 E1.0 person surfing: dark skin tone -1F3C4 200D 2642 FE0F ; fully-qualified # 🏄‍♂️ E4.0 man surfing -1F3C4 200D 2642 ; minimally-qualified # 🏄‍♂ E4.0 man surfing -1F3C4 1F3FB 200D 2642 FE0F ; fully-qualified # 🏄🏻‍♂️ E4.0 man surfing: light skin tone -1F3C4 1F3FB 200D 2642 ; minimally-qualified # 🏄🏻‍♂ E4.0 man surfing: light skin tone -1F3C4 1F3FC 200D 2642 FE0F ; fully-qualified # 🏄🏼‍♂️ E4.0 man surfing: medium-light skin tone -1F3C4 1F3FC 200D 2642 ; minimally-qualified # 🏄🏼‍♂ E4.0 man surfing: medium-light skin tone -1F3C4 1F3FD 200D 2642 FE0F ; fully-qualified # 🏄🏽‍♂️ E4.0 man surfing: medium skin tone -1F3C4 1F3FD 200D 2642 ; minimally-qualified # 🏄🏽‍♂ E4.0 man surfing: medium skin tone -1F3C4 1F3FE 200D 2642 FE0F ; fully-qualified # 🏄🏾‍♂️ E4.0 man surfing: medium-dark skin tone -1F3C4 1F3FE 200D 2642 ; minimally-qualified # 🏄🏾‍♂ E4.0 man surfing: medium-dark skin tone -1F3C4 1F3FF 200D 2642 FE0F ; fully-qualified # 🏄🏿‍♂️ E4.0 man surfing: dark skin tone -1F3C4 1F3FF 200D 2642 ; minimally-qualified # 🏄🏿‍♂ E4.0 man surfing: dark skin tone -1F3C4 200D 2640 FE0F ; fully-qualified # 🏄‍♀️ E4.0 woman surfing -1F3C4 200D 2640 ; minimally-qualified # 🏄‍♀ E4.0 woman surfing -1F3C4 1F3FB 200D 2640 FE0F ; fully-qualified # 🏄🏻‍♀️ E4.0 woman surfing: light skin tone -1F3C4 1F3FB 200D 2640 ; minimally-qualified # 🏄🏻‍♀ E4.0 woman surfing: light skin tone -1F3C4 1F3FC 200D 2640 FE0F ; fully-qualified # 🏄🏼‍♀️ E4.0 woman surfing: medium-light skin tone -1F3C4 1F3FC 200D 2640 ; minimally-qualified # 🏄🏼‍♀ E4.0 woman surfing: medium-light skin tone -1F3C4 1F3FD 200D 2640 FE0F ; fully-qualified # 🏄🏽‍♀️ E4.0 woman surfing: medium skin tone -1F3C4 1F3FD 200D 2640 ; minimally-qualified # 🏄🏽‍♀ E4.0 woman surfing: medium skin tone -1F3C4 1F3FE 200D 2640 FE0F ; fully-qualified # 🏄🏾‍♀️ E4.0 woman surfing: medium-dark skin tone -1F3C4 1F3FE 200D 2640 ; minimally-qualified # 🏄🏾‍♀ E4.0 woman surfing: medium-dark skin tone -1F3C4 1F3FF 200D 2640 FE0F ; fully-qualified # 🏄🏿‍♀️ E4.0 woman surfing: dark skin tone -1F3C4 1F3FF 200D 2640 ; minimally-qualified # 🏄🏿‍♀ E4.0 woman surfing: dark skin tone -1F6A3 ; fully-qualified # 🚣 E1.0 person rowing boat -1F6A3 1F3FB ; fully-qualified # 🚣🏻 E1.0 person rowing boat: light skin tone -1F6A3 1F3FC ; fully-qualified # 🚣🏼 E1.0 person rowing boat: medium-light skin tone -1F6A3 1F3FD ; fully-qualified # 🚣🏽 E1.0 person rowing boat: medium skin tone -1F6A3 1F3FE ; fully-qualified # 🚣🏾 E1.0 person rowing boat: medium-dark skin tone -1F6A3 1F3FF ; fully-qualified # 🚣🏿 E1.0 person rowing boat: dark skin tone -1F6A3 200D 2642 FE0F ; fully-qualified # 🚣‍♂️ E4.0 man rowing boat -1F6A3 200D 2642 ; minimally-qualified # 🚣‍♂ E4.0 man rowing boat -1F6A3 1F3FB 200D 2642 FE0F ; fully-qualified # 🚣🏻‍♂️ E4.0 man rowing boat: light skin tone -1F6A3 1F3FB 200D 2642 ; minimally-qualified # 🚣🏻‍♂ E4.0 man rowing boat: light skin tone -1F6A3 1F3FC 200D 2642 FE0F ; fully-qualified # 🚣🏼‍♂️ E4.0 man rowing boat: medium-light skin tone -1F6A3 1F3FC 200D 2642 ; minimally-qualified # 🚣🏼‍♂ E4.0 man rowing boat: medium-light skin tone -1F6A3 1F3FD 200D 2642 FE0F ; fully-qualified # 🚣🏽‍♂️ E4.0 man rowing boat: medium skin tone -1F6A3 1F3FD 200D 2642 ; minimally-qualified # 🚣🏽‍♂ E4.0 man rowing boat: medium skin tone -1F6A3 1F3FE 200D 2642 FE0F ; fully-qualified # 🚣🏾‍♂️ E4.0 man rowing boat: medium-dark skin tone -1F6A3 1F3FE 200D 2642 ; minimally-qualified # 🚣🏾‍♂ E4.0 man rowing boat: medium-dark skin tone -1F6A3 1F3FF 200D 2642 FE0F ; fully-qualified # 🚣🏿‍♂️ E4.0 man rowing boat: dark skin tone -1F6A3 1F3FF 200D 2642 ; minimally-qualified # 🚣🏿‍♂ E4.0 man rowing boat: dark skin tone -1F6A3 200D 2640 FE0F ; fully-qualified # 🚣‍♀️ E4.0 woman rowing boat -1F6A3 200D 2640 ; minimally-qualified # 🚣‍♀ E4.0 woman rowing boat -1F6A3 1F3FB 200D 2640 FE0F ; fully-qualified # 🚣🏻‍♀️ E4.0 woman rowing boat: light skin tone -1F6A3 1F3FB 200D 2640 ; minimally-qualified # 🚣🏻‍♀ E4.0 woman rowing boat: light skin tone -1F6A3 1F3FC 200D 2640 FE0F ; fully-qualified # 🚣🏼‍♀️ E4.0 woman rowing boat: medium-light skin tone -1F6A3 1F3FC 200D 2640 ; minimally-qualified # 🚣🏼‍♀ E4.0 woman rowing boat: medium-light skin tone -1F6A3 1F3FD 200D 2640 FE0F ; fully-qualified # 🚣🏽‍♀️ E4.0 woman rowing boat: medium skin tone -1F6A3 1F3FD 200D 2640 ; minimally-qualified # 🚣🏽‍♀ E4.0 woman rowing boat: medium skin tone -1F6A3 1F3FE 200D 2640 FE0F ; fully-qualified # 🚣🏾‍♀️ E4.0 woman rowing boat: medium-dark skin tone -1F6A3 1F3FE 200D 2640 ; minimally-qualified # 🚣🏾‍♀ E4.0 woman rowing boat: medium-dark skin tone -1F6A3 1F3FF 200D 2640 FE0F ; fully-qualified # 🚣🏿‍♀️ E4.0 woman rowing boat: dark skin tone -1F6A3 1F3FF 200D 2640 ; minimally-qualified # 🚣🏿‍♀ E4.0 woman rowing boat: dark skin tone -1F3CA ; fully-qualified # 🏊 E0.6 person swimming -1F3CA 1F3FB ; fully-qualified # 🏊🏻 E1.0 person swimming: light skin tone -1F3CA 1F3FC ; fully-qualified # 🏊🏼 E1.0 person swimming: medium-light skin tone -1F3CA 1F3FD ; fully-qualified # 🏊🏽 E1.0 person swimming: medium skin tone -1F3CA 1F3FE ; fully-qualified # 🏊🏾 E1.0 person swimming: medium-dark skin tone -1F3CA 1F3FF ; fully-qualified # 🏊🏿 E1.0 person swimming: dark skin tone -1F3CA 200D 2642 FE0F ; fully-qualified # 🏊‍♂️ E4.0 man swimming -1F3CA 200D 2642 ; minimally-qualified # 🏊‍♂ E4.0 man swimming -1F3CA 1F3FB 200D 2642 FE0F ; fully-qualified # 🏊🏻‍♂️ E4.0 man swimming: light skin tone -1F3CA 1F3FB 200D 2642 ; minimally-qualified # 🏊🏻‍♂ E4.0 man swimming: light skin tone -1F3CA 1F3FC 200D 2642 FE0F ; fully-qualified # 🏊🏼‍♂️ E4.0 man swimming: medium-light skin tone -1F3CA 1F3FC 200D 2642 ; minimally-qualified # 🏊🏼‍♂ E4.0 man swimming: medium-light skin tone -1F3CA 1F3FD 200D 2642 FE0F ; fully-qualified # 🏊🏽‍♂️ E4.0 man swimming: medium skin tone -1F3CA 1F3FD 200D 2642 ; minimally-qualified # 🏊🏽‍♂ E4.0 man swimming: medium skin tone -1F3CA 1F3FE 200D 2642 FE0F ; fully-qualified # 🏊🏾‍♂️ E4.0 man swimming: medium-dark skin tone -1F3CA 1F3FE 200D 2642 ; minimally-qualified # 🏊🏾‍♂ E4.0 man swimming: medium-dark skin tone -1F3CA 1F3FF 200D 2642 FE0F ; fully-qualified # 🏊🏿‍♂️ E4.0 man swimming: dark skin tone -1F3CA 1F3FF 200D 2642 ; minimally-qualified # 🏊🏿‍♂ E4.0 man swimming: dark skin tone -1F3CA 200D 2640 FE0F ; fully-qualified # 🏊‍♀️ E4.0 woman swimming -1F3CA 200D 2640 ; minimally-qualified # 🏊‍♀ E4.0 woman swimming -1F3CA 1F3FB 200D 2640 FE0F ; fully-qualified # 🏊🏻‍♀️ E4.0 woman swimming: light skin tone -1F3CA 1F3FB 200D 2640 ; minimally-qualified # 🏊🏻‍♀ E4.0 woman swimming: light skin tone -1F3CA 1F3FC 200D 2640 FE0F ; fully-qualified # 🏊🏼‍♀️ E4.0 woman swimming: medium-light skin tone -1F3CA 1F3FC 200D 2640 ; minimally-qualified # 🏊🏼‍♀ E4.0 woman swimming: medium-light skin tone -1F3CA 1F3FD 200D 2640 FE0F ; fully-qualified # 🏊🏽‍♀️ E4.0 woman swimming: medium skin tone -1F3CA 1F3FD 200D 2640 ; minimally-qualified # 🏊🏽‍♀ E4.0 woman swimming: medium skin tone -1F3CA 1F3FE 200D 2640 FE0F ; fully-qualified # 🏊🏾‍♀️ E4.0 woman swimming: medium-dark skin tone -1F3CA 1F3FE 200D 2640 ; minimally-qualified # 🏊🏾‍♀ E4.0 woman swimming: medium-dark skin tone -1F3CA 1F3FF 200D 2640 FE0F ; fully-qualified # 🏊🏿‍♀️ E4.0 woman swimming: dark skin tone -1F3CA 1F3FF 200D 2640 ; minimally-qualified # 🏊🏿‍♀ E4.0 woman swimming: dark skin tone -26F9 FE0F ; fully-qualified # ⛹️ E0.7 person bouncing ball -26F9 ; unqualified # ⛹ E0.7 person bouncing ball -26F9 1F3FB ; fully-qualified # ⛹🏻 E2.0 person bouncing ball: light skin tone -26F9 1F3FC ; fully-qualified # ⛹🏼 E2.0 person bouncing ball: medium-light skin tone -26F9 1F3FD ; fully-qualified # ⛹🏽 E2.0 person bouncing ball: medium skin tone -26F9 1F3FE ; fully-qualified # ⛹🏾 E2.0 person bouncing ball: medium-dark skin tone -26F9 1F3FF ; fully-qualified # ⛹🏿 E2.0 person bouncing ball: dark skin tone -26F9 FE0F 200D 2642 FE0F ; fully-qualified # ⛹️‍♂️ E4.0 man bouncing ball -26F9 200D 2642 FE0F ; unqualified # ⛹‍♂️ E4.0 man bouncing ball -26F9 FE0F 200D 2642 ; minimally-qualified # ⛹️‍♂ E4.0 man bouncing ball -26F9 200D 2642 ; unqualified # ⛹‍♂ E4.0 man bouncing ball -26F9 1F3FB 200D 2642 FE0F ; fully-qualified # ⛹🏻‍♂️ E4.0 man bouncing ball: light skin tone -26F9 1F3FB 200D 2642 ; minimally-qualified # ⛹🏻‍♂ E4.0 man bouncing ball: light skin tone -26F9 1F3FC 200D 2642 FE0F ; fully-qualified # ⛹🏼‍♂️ E4.0 man bouncing ball: medium-light skin tone -26F9 1F3FC 200D 2642 ; minimally-qualified # ⛹🏼‍♂ E4.0 man bouncing ball: medium-light skin tone -26F9 1F3FD 200D 2642 FE0F ; fully-qualified # ⛹🏽‍♂️ E4.0 man bouncing ball: medium skin tone -26F9 1F3FD 200D 2642 ; minimally-qualified # ⛹🏽‍♂ E4.0 man bouncing ball: medium skin tone -26F9 1F3FE 200D 2642 FE0F ; fully-qualified # ⛹🏾‍♂️ E4.0 man bouncing ball: medium-dark skin tone -26F9 1F3FE 200D 2642 ; minimally-qualified # ⛹🏾‍♂ E4.0 man bouncing ball: medium-dark skin tone -26F9 1F3FF 200D 2642 FE0F ; fully-qualified # ⛹🏿‍♂️ E4.0 man bouncing ball: dark skin tone -26F9 1F3FF 200D 2642 ; minimally-qualified # ⛹🏿‍♂ E4.0 man bouncing ball: dark skin tone -26F9 FE0F 200D 2640 FE0F ; fully-qualified # ⛹️‍♀️ E4.0 woman bouncing ball -26F9 200D 2640 FE0F ; unqualified # ⛹‍♀️ E4.0 woman bouncing ball -26F9 FE0F 200D 2640 ; minimally-qualified # ⛹️‍♀ E4.0 woman bouncing ball -26F9 200D 2640 ; unqualified # ⛹‍♀ E4.0 woman bouncing ball -26F9 1F3FB 200D 2640 FE0F ; fully-qualified # ⛹🏻‍♀️ E4.0 woman bouncing ball: light skin tone -26F9 1F3FB 200D 2640 ; minimally-qualified # ⛹🏻‍♀ E4.0 woman bouncing ball: light skin tone -26F9 1F3FC 200D 2640 FE0F ; fully-qualified # ⛹🏼‍♀️ E4.0 woman bouncing ball: medium-light skin tone -26F9 1F3FC 200D 2640 ; minimally-qualified # ⛹🏼‍♀ E4.0 woman bouncing ball: medium-light skin tone -26F9 1F3FD 200D 2640 FE0F ; fully-qualified # ⛹🏽‍♀️ E4.0 woman bouncing ball: medium skin tone -26F9 1F3FD 200D 2640 ; minimally-qualified # ⛹🏽‍♀ E4.0 woman bouncing ball: medium skin tone -26F9 1F3FE 200D 2640 FE0F ; fully-qualified # ⛹🏾‍♀️ E4.0 woman bouncing ball: medium-dark skin tone -26F9 1F3FE 200D 2640 ; minimally-qualified # ⛹🏾‍♀ E4.0 woman bouncing ball: medium-dark skin tone -26F9 1F3FF 200D 2640 FE0F ; fully-qualified # ⛹🏿‍♀️ E4.0 woman bouncing ball: dark skin tone -26F9 1F3FF 200D 2640 ; minimally-qualified # ⛹🏿‍♀ E4.0 woman bouncing ball: dark skin tone -1F3CB FE0F ; fully-qualified # 🏋️ E0.7 person lifting weights -1F3CB ; unqualified # 🏋 E0.7 person lifting weights -1F3CB 1F3FB ; fully-qualified # 🏋🏻 E2.0 person lifting weights: light skin tone -1F3CB 1F3FC ; fully-qualified # 🏋🏼 E2.0 person lifting weights: medium-light skin tone -1F3CB 1F3FD ; fully-qualified # 🏋🏽 E2.0 person lifting weights: medium skin tone -1F3CB 1F3FE ; fully-qualified # 🏋🏾 E2.0 person lifting weights: medium-dark skin tone -1F3CB 1F3FF ; fully-qualified # 🏋🏿 E2.0 person lifting weights: dark skin tone -1F3CB FE0F 200D 2642 FE0F ; fully-qualified # 🏋️‍♂️ E4.0 man lifting weights -1F3CB 200D 2642 FE0F ; unqualified # 🏋‍♂️ E4.0 man lifting weights -1F3CB FE0F 200D 2642 ; minimally-qualified # 🏋️‍♂ E4.0 man lifting weights -1F3CB 200D 2642 ; unqualified # 🏋‍♂ E4.0 man lifting weights -1F3CB 1F3FB 200D 2642 FE0F ; fully-qualified # 🏋🏻‍♂️ E4.0 man lifting weights: light skin tone -1F3CB 1F3FB 200D 2642 ; minimally-qualified # 🏋🏻‍♂ E4.0 man lifting weights: light skin tone -1F3CB 1F3FC 200D 2642 FE0F ; fully-qualified # 🏋🏼‍♂️ E4.0 man lifting weights: medium-light skin tone -1F3CB 1F3FC 200D 2642 ; minimally-qualified # 🏋🏼‍♂ E4.0 man lifting weights: medium-light skin tone -1F3CB 1F3FD 200D 2642 FE0F ; fully-qualified # 🏋🏽‍♂️ E4.0 man lifting weights: medium skin tone -1F3CB 1F3FD 200D 2642 ; minimally-qualified # 🏋🏽‍♂ E4.0 man lifting weights: medium skin tone -1F3CB 1F3FE 200D 2642 FE0F ; fully-qualified # 🏋🏾‍♂️ E4.0 man lifting weights: medium-dark skin tone -1F3CB 1F3FE 200D 2642 ; minimally-qualified # 🏋🏾‍♂ E4.0 man lifting weights: medium-dark skin tone -1F3CB 1F3FF 200D 2642 FE0F ; fully-qualified # 🏋🏿‍♂️ E4.0 man lifting weights: dark skin tone -1F3CB 1F3FF 200D 2642 ; minimally-qualified # 🏋🏿‍♂ E4.0 man lifting weights: dark skin tone -1F3CB FE0F 200D 2640 FE0F ; fully-qualified # 🏋️‍♀️ E4.0 woman lifting weights -1F3CB 200D 2640 FE0F ; unqualified # 🏋‍♀️ E4.0 woman lifting weights -1F3CB FE0F 200D 2640 ; minimally-qualified # 🏋️‍♀ E4.0 woman lifting weights -1F3CB 200D 2640 ; unqualified # 🏋‍♀ E4.0 woman lifting weights -1F3CB 1F3FB 200D 2640 FE0F ; fully-qualified # 🏋🏻‍♀️ E4.0 woman lifting weights: light skin tone -1F3CB 1F3FB 200D 2640 ; minimally-qualified # 🏋🏻‍♀ E4.0 woman lifting weights: light skin tone -1F3CB 1F3FC 200D 2640 FE0F ; fully-qualified # 🏋🏼‍♀️ E4.0 woman lifting weights: medium-light skin tone -1F3CB 1F3FC 200D 2640 ; minimally-qualified # 🏋🏼‍♀ E4.0 woman lifting weights: medium-light skin tone -1F3CB 1F3FD 200D 2640 FE0F ; fully-qualified # 🏋🏽‍♀️ E4.0 woman lifting weights: medium skin tone -1F3CB 1F3FD 200D 2640 ; minimally-qualified # 🏋🏽‍♀ E4.0 woman lifting weights: medium skin tone -1F3CB 1F3FE 200D 2640 FE0F ; fully-qualified # 🏋🏾‍♀️ E4.0 woman lifting weights: medium-dark skin tone -1F3CB 1F3FE 200D 2640 ; minimally-qualified # 🏋🏾‍♀ E4.0 woman lifting weights: medium-dark skin tone -1F3CB 1F3FF 200D 2640 FE0F ; fully-qualified # 🏋🏿‍♀️ E4.0 woman lifting weights: dark skin tone -1F3CB 1F3FF 200D 2640 ; minimally-qualified # 🏋🏿‍♀ E4.0 woman lifting weights: dark skin tone -1F6B4 ; fully-qualified # 🚴 E1.0 person biking -1F6B4 1F3FB ; fully-qualified # 🚴🏻 E1.0 person biking: light skin tone -1F6B4 1F3FC ; fully-qualified # 🚴🏼 E1.0 person biking: medium-light skin tone -1F6B4 1F3FD ; fully-qualified # 🚴🏽 E1.0 person biking: medium skin tone -1F6B4 1F3FE ; fully-qualified # 🚴🏾 E1.0 person biking: medium-dark skin tone -1F6B4 1F3FF ; fully-qualified # 🚴🏿 E1.0 person biking: dark skin tone -1F6B4 200D 2642 FE0F ; fully-qualified # 🚴‍♂️ E4.0 man biking -1F6B4 200D 2642 ; minimally-qualified # 🚴‍♂ E4.0 man biking -1F6B4 1F3FB 200D 2642 FE0F ; fully-qualified # 🚴🏻‍♂️ E4.0 man biking: light skin tone -1F6B4 1F3FB 200D 2642 ; minimally-qualified # 🚴🏻‍♂ E4.0 man biking: light skin tone -1F6B4 1F3FC 200D 2642 FE0F ; fully-qualified # 🚴🏼‍♂️ E4.0 man biking: medium-light skin tone -1F6B4 1F3FC 200D 2642 ; minimally-qualified # 🚴🏼‍♂ E4.0 man biking: medium-light skin tone -1F6B4 1F3FD 200D 2642 FE0F ; fully-qualified # 🚴🏽‍♂️ E4.0 man biking: medium skin tone -1F6B4 1F3FD 200D 2642 ; minimally-qualified # 🚴🏽‍♂ E4.0 man biking: medium skin tone -1F6B4 1F3FE 200D 2642 FE0F ; fully-qualified # 🚴🏾‍♂️ E4.0 man biking: medium-dark skin tone -1F6B4 1F3FE 200D 2642 ; minimally-qualified # 🚴🏾‍♂ E4.0 man biking: medium-dark skin tone -1F6B4 1F3FF 200D 2642 FE0F ; fully-qualified # 🚴🏿‍♂️ E4.0 man biking: dark skin tone -1F6B4 1F3FF 200D 2642 ; minimally-qualified # 🚴🏿‍♂ E4.0 man biking: dark skin tone -1F6B4 200D 2640 FE0F ; fully-qualified # 🚴‍♀️ E4.0 woman biking -1F6B4 200D 2640 ; minimally-qualified # 🚴‍♀ E4.0 woman biking -1F6B4 1F3FB 200D 2640 FE0F ; fully-qualified # 🚴🏻‍♀️ E4.0 woman biking: light skin tone -1F6B4 1F3FB 200D 2640 ; minimally-qualified # 🚴🏻‍♀ E4.0 woman biking: light skin tone -1F6B4 1F3FC 200D 2640 FE0F ; fully-qualified # 🚴🏼‍♀️ E4.0 woman biking: medium-light skin tone -1F6B4 1F3FC 200D 2640 ; minimally-qualified # 🚴🏼‍♀ E4.0 woman biking: medium-light skin tone -1F6B4 1F3FD 200D 2640 FE0F ; fully-qualified # 🚴🏽‍♀️ E4.0 woman biking: medium skin tone -1F6B4 1F3FD 200D 2640 ; minimally-qualified # 🚴🏽‍♀ E4.0 woman biking: medium skin tone -1F6B4 1F3FE 200D 2640 FE0F ; fully-qualified # 🚴🏾‍♀️ E4.0 woman biking: medium-dark skin tone -1F6B4 1F3FE 200D 2640 ; minimally-qualified # 🚴🏾‍♀ E4.0 woman biking: medium-dark skin tone -1F6B4 1F3FF 200D 2640 FE0F ; fully-qualified # 🚴🏿‍♀️ E4.0 woman biking: dark skin tone -1F6B4 1F3FF 200D 2640 ; minimally-qualified # 🚴🏿‍♀ E4.0 woman biking: dark skin tone -1F6B5 ; fully-qualified # 🚵 E1.0 person mountain biking -1F6B5 1F3FB ; fully-qualified # 🚵🏻 E1.0 person mountain biking: light skin tone -1F6B5 1F3FC ; fully-qualified # 🚵🏼 E1.0 person mountain biking: medium-light skin tone -1F6B5 1F3FD ; fully-qualified # 🚵🏽 E1.0 person mountain biking: medium skin tone -1F6B5 1F3FE ; fully-qualified # 🚵🏾 E1.0 person mountain biking: medium-dark skin tone -1F6B5 1F3FF ; fully-qualified # 🚵🏿 E1.0 person mountain biking: dark skin tone -1F6B5 200D 2642 FE0F ; fully-qualified # 🚵‍♂️ E4.0 man mountain biking -1F6B5 200D 2642 ; minimally-qualified # 🚵‍♂ E4.0 man mountain biking -1F6B5 1F3FB 200D 2642 FE0F ; fully-qualified # 🚵🏻‍♂️ E4.0 man mountain biking: light skin tone -1F6B5 1F3FB 200D 2642 ; minimally-qualified # 🚵🏻‍♂ E4.0 man mountain biking: light skin tone -1F6B5 1F3FC 200D 2642 FE0F ; fully-qualified # 🚵🏼‍♂️ E4.0 man mountain biking: medium-light skin tone -1F6B5 1F3FC 200D 2642 ; minimally-qualified # 🚵🏼‍♂ E4.0 man mountain biking: medium-light skin tone -1F6B5 1F3FD 200D 2642 FE0F ; fully-qualified # 🚵🏽‍♂️ E4.0 man mountain biking: medium skin tone -1F6B5 1F3FD 200D 2642 ; minimally-qualified # 🚵🏽‍♂ E4.0 man mountain biking: medium skin tone -1F6B5 1F3FE 200D 2642 FE0F ; fully-qualified # 🚵🏾‍♂️ E4.0 man mountain biking: medium-dark skin tone -1F6B5 1F3FE 200D 2642 ; minimally-qualified # 🚵🏾‍♂ E4.0 man mountain biking: medium-dark skin tone -1F6B5 1F3FF 200D 2642 FE0F ; fully-qualified # 🚵🏿‍♂️ E4.0 man mountain biking: dark skin tone -1F6B5 1F3FF 200D 2642 ; minimally-qualified # 🚵🏿‍♂ E4.0 man mountain biking: dark skin tone -1F6B5 200D 2640 FE0F ; fully-qualified # 🚵‍♀️ E4.0 woman mountain biking -1F6B5 200D 2640 ; minimally-qualified # 🚵‍♀ E4.0 woman mountain biking -1F6B5 1F3FB 200D 2640 FE0F ; fully-qualified # 🚵🏻‍♀️ E4.0 woman mountain biking: light skin tone -1F6B5 1F3FB 200D 2640 ; minimally-qualified # 🚵🏻‍♀ E4.0 woman mountain biking: light skin tone -1F6B5 1F3FC 200D 2640 FE0F ; fully-qualified # 🚵🏼‍♀️ E4.0 woman mountain biking: medium-light skin tone -1F6B5 1F3FC 200D 2640 ; minimally-qualified # 🚵🏼‍♀ E4.0 woman mountain biking: medium-light skin tone -1F6B5 1F3FD 200D 2640 FE0F ; fully-qualified # 🚵🏽‍♀️ E4.0 woman mountain biking: medium skin tone -1F6B5 1F3FD 200D 2640 ; minimally-qualified # 🚵🏽‍♀ E4.0 woman mountain biking: medium skin tone -1F6B5 1F3FE 200D 2640 FE0F ; fully-qualified # 🚵🏾‍♀️ E4.0 woman mountain biking: medium-dark skin tone -1F6B5 1F3FE 200D 2640 ; minimally-qualified # 🚵🏾‍♀ E4.0 woman mountain biking: medium-dark skin tone -1F6B5 1F3FF 200D 2640 FE0F ; fully-qualified # 🚵🏿‍♀️ E4.0 woman mountain biking: dark skin tone -1F6B5 1F3FF 200D 2640 ; minimally-qualified # 🚵🏿‍♀ E4.0 woman mountain biking: dark skin tone -1F938 ; fully-qualified # 🤸 E3.0 person cartwheeling -1F938 1F3FB ; fully-qualified # 🤸🏻 E3.0 person cartwheeling: light skin tone -1F938 1F3FC ; fully-qualified # 🤸🏼 E3.0 person cartwheeling: medium-light skin tone -1F938 1F3FD ; fully-qualified # 🤸🏽 E3.0 person cartwheeling: medium skin tone -1F938 1F3FE ; fully-qualified # 🤸🏾 E3.0 person cartwheeling: medium-dark skin tone -1F938 1F3FF ; fully-qualified # 🤸🏿 E3.0 person cartwheeling: dark skin tone -1F938 200D 2642 FE0F ; fully-qualified # 🤸‍♂️ E4.0 man cartwheeling -1F938 200D 2642 ; minimally-qualified # 🤸‍♂ E4.0 man cartwheeling -1F938 1F3FB 200D 2642 FE0F ; fully-qualified # 🤸🏻‍♂️ E4.0 man cartwheeling: light skin tone -1F938 1F3FB 200D 2642 ; minimally-qualified # 🤸🏻‍♂ E4.0 man cartwheeling: light skin tone -1F938 1F3FC 200D 2642 FE0F ; fully-qualified # 🤸🏼‍♂️ E4.0 man cartwheeling: medium-light skin tone -1F938 1F3FC 200D 2642 ; minimally-qualified # 🤸🏼‍♂ E4.0 man cartwheeling: medium-light skin tone -1F938 1F3FD 200D 2642 FE0F ; fully-qualified # 🤸🏽‍♂️ E4.0 man cartwheeling: medium skin tone -1F938 1F3FD 200D 2642 ; minimally-qualified # 🤸🏽‍♂ E4.0 man cartwheeling: medium skin tone -1F938 1F3FE 200D 2642 FE0F ; fully-qualified # 🤸🏾‍♂️ E4.0 man cartwheeling: medium-dark skin tone -1F938 1F3FE 200D 2642 ; minimally-qualified # 🤸🏾‍♂ E4.0 man cartwheeling: medium-dark skin tone -1F938 1F3FF 200D 2642 FE0F ; fully-qualified # 🤸🏿‍♂️ E4.0 man cartwheeling: dark skin tone -1F938 1F3FF 200D 2642 ; minimally-qualified # 🤸🏿‍♂ E4.0 man cartwheeling: dark skin tone -1F938 200D 2640 FE0F ; fully-qualified # 🤸‍♀️ E4.0 woman cartwheeling -1F938 200D 2640 ; minimally-qualified # 🤸‍♀ E4.0 woman cartwheeling -1F938 1F3FB 200D 2640 FE0F ; fully-qualified # 🤸🏻‍♀️ E4.0 woman cartwheeling: light skin tone -1F938 1F3FB 200D 2640 ; minimally-qualified # 🤸🏻‍♀ E4.0 woman cartwheeling: light skin tone -1F938 1F3FC 200D 2640 FE0F ; fully-qualified # 🤸🏼‍♀️ E4.0 woman cartwheeling: medium-light skin tone -1F938 1F3FC 200D 2640 ; minimally-qualified # 🤸🏼‍♀ E4.0 woman cartwheeling: medium-light skin tone -1F938 1F3FD 200D 2640 FE0F ; fully-qualified # 🤸🏽‍♀️ E4.0 woman cartwheeling: medium skin tone -1F938 1F3FD 200D 2640 ; minimally-qualified # 🤸🏽‍♀ E4.0 woman cartwheeling: medium skin tone -1F938 1F3FE 200D 2640 FE0F ; fully-qualified # 🤸🏾‍♀️ E4.0 woman cartwheeling: medium-dark skin tone -1F938 1F3FE 200D 2640 ; minimally-qualified # 🤸🏾‍♀ E4.0 woman cartwheeling: medium-dark skin tone -1F938 1F3FF 200D 2640 FE0F ; fully-qualified # 🤸🏿‍♀️ E4.0 woman cartwheeling: dark skin tone -1F938 1F3FF 200D 2640 ; minimally-qualified # 🤸🏿‍♀ E4.0 woman cartwheeling: dark skin tone -1F93C ; fully-qualified # 🤼 E3.0 people wrestling -1F93C 200D 2642 FE0F ; fully-qualified # 🤼‍♂️ E4.0 men wrestling -1F93C 200D 2642 ; minimally-qualified # 🤼‍♂ E4.0 men wrestling -1F93C 200D 2640 FE0F ; fully-qualified # 🤼‍♀️ E4.0 women wrestling -1F93C 200D 2640 ; minimally-qualified # 🤼‍♀ E4.0 women wrestling -1F93D ; fully-qualified # 🤽 E3.0 person playing water polo -1F93D 1F3FB ; fully-qualified # 🤽🏻 E3.0 person playing water polo: light skin tone -1F93D 1F3FC ; fully-qualified # 🤽🏼 E3.0 person playing water polo: medium-light skin tone -1F93D 1F3FD ; fully-qualified # 🤽🏽 E3.0 person playing water polo: medium skin tone -1F93D 1F3FE ; fully-qualified # 🤽🏾 E3.0 person playing water polo: medium-dark skin tone -1F93D 1F3FF ; fully-qualified # 🤽🏿 E3.0 person playing water polo: dark skin tone -1F93D 200D 2642 FE0F ; fully-qualified # 🤽‍♂️ E4.0 man playing water polo -1F93D 200D 2642 ; minimally-qualified # 🤽‍♂ E4.0 man playing water polo -1F93D 1F3FB 200D 2642 FE0F ; fully-qualified # 🤽🏻‍♂️ E4.0 man playing water polo: light skin tone -1F93D 1F3FB 200D 2642 ; minimally-qualified # 🤽🏻‍♂ E4.0 man playing water polo: light skin tone -1F93D 1F3FC 200D 2642 FE0F ; fully-qualified # 🤽🏼‍♂️ E4.0 man playing water polo: medium-light skin tone -1F93D 1F3FC 200D 2642 ; minimally-qualified # 🤽🏼‍♂ E4.0 man playing water polo: medium-light skin tone -1F93D 1F3FD 200D 2642 FE0F ; fully-qualified # 🤽🏽‍♂️ E4.0 man playing water polo: medium skin tone -1F93D 1F3FD 200D 2642 ; minimally-qualified # 🤽🏽‍♂ E4.0 man playing water polo: medium skin tone -1F93D 1F3FE 200D 2642 FE0F ; fully-qualified # 🤽🏾‍♂️ E4.0 man playing water polo: medium-dark skin tone -1F93D 1F3FE 200D 2642 ; minimally-qualified # 🤽🏾‍♂ E4.0 man playing water polo: medium-dark skin tone -1F93D 1F3FF 200D 2642 FE0F ; fully-qualified # 🤽🏿‍♂️ E4.0 man playing water polo: dark skin tone -1F93D 1F3FF 200D 2642 ; minimally-qualified # 🤽🏿‍♂ E4.0 man playing water polo: dark skin tone -1F93D 200D 2640 FE0F ; fully-qualified # 🤽‍♀️ E4.0 woman playing water polo -1F93D 200D 2640 ; minimally-qualified # 🤽‍♀ E4.0 woman playing water polo -1F93D 1F3FB 200D 2640 FE0F ; fully-qualified # 🤽🏻‍♀️ E4.0 woman playing water polo: light skin tone -1F93D 1F3FB 200D 2640 ; minimally-qualified # 🤽🏻‍♀ E4.0 woman playing water polo: light skin tone -1F93D 1F3FC 200D 2640 FE0F ; fully-qualified # 🤽🏼‍♀️ E4.0 woman playing water polo: medium-light skin tone -1F93D 1F3FC 200D 2640 ; minimally-qualified # 🤽🏼‍♀ E4.0 woman playing water polo: medium-light skin tone -1F93D 1F3FD 200D 2640 FE0F ; fully-qualified # 🤽🏽‍♀️ E4.0 woman playing water polo: medium skin tone -1F93D 1F3FD 200D 2640 ; minimally-qualified # 🤽🏽‍♀ E4.0 woman playing water polo: medium skin tone -1F93D 1F3FE 200D 2640 FE0F ; fully-qualified # 🤽🏾‍♀️ E4.0 woman playing water polo: medium-dark skin tone -1F93D 1F3FE 200D 2640 ; minimally-qualified # 🤽🏾‍♀ E4.0 woman playing water polo: medium-dark skin tone -1F93D 1F3FF 200D 2640 FE0F ; fully-qualified # 🤽🏿‍♀️ E4.0 woman playing water polo: dark skin tone -1F93D 1F3FF 200D 2640 ; minimally-qualified # 🤽🏿‍♀ E4.0 woman playing water polo: dark skin tone -1F93E ; fully-qualified # 🤾 E3.0 person playing handball -1F93E 1F3FB ; fully-qualified # 🤾🏻 E3.0 person playing handball: light skin tone -1F93E 1F3FC ; fully-qualified # 🤾🏼 E3.0 person playing handball: medium-light skin tone -1F93E 1F3FD ; fully-qualified # 🤾🏽 E3.0 person playing handball: medium skin tone -1F93E 1F3FE ; fully-qualified # 🤾🏾 E3.0 person playing handball: medium-dark skin tone -1F93E 1F3FF ; fully-qualified # 🤾🏿 E3.0 person playing handball: dark skin tone -1F93E 200D 2642 FE0F ; fully-qualified # 🤾‍♂️ E4.0 man playing handball -1F93E 200D 2642 ; minimally-qualified # 🤾‍♂ E4.0 man playing handball -1F93E 1F3FB 200D 2642 FE0F ; fully-qualified # 🤾🏻‍♂️ E4.0 man playing handball: light skin tone -1F93E 1F3FB 200D 2642 ; minimally-qualified # 🤾🏻‍♂ E4.0 man playing handball: light skin tone -1F93E 1F3FC 200D 2642 FE0F ; fully-qualified # 🤾🏼‍♂️ E4.0 man playing handball: medium-light skin tone -1F93E 1F3FC 200D 2642 ; minimally-qualified # 🤾🏼‍♂ E4.0 man playing handball: medium-light skin tone -1F93E 1F3FD 200D 2642 FE0F ; fully-qualified # 🤾🏽‍♂️ E4.0 man playing handball: medium skin tone -1F93E 1F3FD 200D 2642 ; minimally-qualified # 🤾🏽‍♂ E4.0 man playing handball: medium skin tone -1F93E 1F3FE 200D 2642 FE0F ; fully-qualified # 🤾🏾‍♂️ E4.0 man playing handball: medium-dark skin tone -1F93E 1F3FE 200D 2642 ; minimally-qualified # 🤾🏾‍♂ E4.0 man playing handball: medium-dark skin tone -1F93E 1F3FF 200D 2642 FE0F ; fully-qualified # 🤾🏿‍♂️ E4.0 man playing handball: dark skin tone -1F93E 1F3FF 200D 2642 ; minimally-qualified # 🤾🏿‍♂ E4.0 man playing handball: dark skin tone -1F93E 200D 2640 FE0F ; fully-qualified # 🤾‍♀️ E4.0 woman playing handball -1F93E 200D 2640 ; minimally-qualified # 🤾‍♀ E4.0 woman playing handball -1F93E 1F3FB 200D 2640 FE0F ; fully-qualified # 🤾🏻‍♀️ E4.0 woman playing handball: light skin tone -1F93E 1F3FB 200D 2640 ; minimally-qualified # 🤾🏻‍♀ E4.0 woman playing handball: light skin tone -1F93E 1F3FC 200D 2640 FE0F ; fully-qualified # 🤾🏼‍♀️ E4.0 woman playing handball: medium-light skin tone -1F93E 1F3FC 200D 2640 ; minimally-qualified # 🤾🏼‍♀ E4.0 woman playing handball: medium-light skin tone -1F93E 1F3FD 200D 2640 FE0F ; fully-qualified # 🤾🏽‍♀️ E4.0 woman playing handball: medium skin tone -1F93E 1F3FD 200D 2640 ; minimally-qualified # 🤾🏽‍♀ E4.0 woman playing handball: medium skin tone -1F93E 1F3FE 200D 2640 FE0F ; fully-qualified # 🤾🏾‍♀️ E4.0 woman playing handball: medium-dark skin tone -1F93E 1F3FE 200D 2640 ; minimally-qualified # 🤾🏾‍♀ E4.0 woman playing handball: medium-dark skin tone -1F93E 1F3FF 200D 2640 FE0F ; fully-qualified # 🤾🏿‍♀️ E4.0 woman playing handball: dark skin tone -1F93E 1F3FF 200D 2640 ; minimally-qualified # 🤾🏿‍♀ E4.0 woman playing handball: dark skin tone -1F939 ; fully-qualified # 🤹 E3.0 person juggling -1F939 1F3FB ; fully-qualified # 🤹🏻 E3.0 person juggling: light skin tone -1F939 1F3FC ; fully-qualified # 🤹🏼 E3.0 person juggling: medium-light skin tone -1F939 1F3FD ; fully-qualified # 🤹🏽 E3.0 person juggling: medium skin tone -1F939 1F3FE ; fully-qualified # 🤹🏾 E3.0 person juggling: medium-dark skin tone -1F939 1F3FF ; fully-qualified # 🤹🏿 E3.0 person juggling: dark skin tone -1F939 200D 2642 FE0F ; fully-qualified # 🤹‍♂️ E4.0 man juggling -1F939 200D 2642 ; minimally-qualified # 🤹‍♂ E4.0 man juggling -1F939 1F3FB 200D 2642 FE0F ; fully-qualified # 🤹🏻‍♂️ E4.0 man juggling: light skin tone -1F939 1F3FB 200D 2642 ; minimally-qualified # 🤹🏻‍♂ E4.0 man juggling: light skin tone -1F939 1F3FC 200D 2642 FE0F ; fully-qualified # 🤹🏼‍♂️ E4.0 man juggling: medium-light skin tone -1F939 1F3FC 200D 2642 ; minimally-qualified # 🤹🏼‍♂ E4.0 man juggling: medium-light skin tone -1F939 1F3FD 200D 2642 FE0F ; fully-qualified # 🤹🏽‍♂️ E4.0 man juggling: medium skin tone -1F939 1F3FD 200D 2642 ; minimally-qualified # 🤹🏽‍♂ E4.0 man juggling: medium skin tone -1F939 1F3FE 200D 2642 FE0F ; fully-qualified # 🤹🏾‍♂️ E4.0 man juggling: medium-dark skin tone -1F939 1F3FE 200D 2642 ; minimally-qualified # 🤹🏾‍♂ E4.0 man juggling: medium-dark skin tone -1F939 1F3FF 200D 2642 FE0F ; fully-qualified # 🤹🏿‍♂️ E4.0 man juggling: dark skin tone -1F939 1F3FF 200D 2642 ; minimally-qualified # 🤹🏿‍♂ E4.0 man juggling: dark skin tone -1F939 200D 2640 FE0F ; fully-qualified # 🤹‍♀️ E4.0 woman juggling -1F939 200D 2640 ; minimally-qualified # 🤹‍♀ E4.0 woman juggling -1F939 1F3FB 200D 2640 FE0F ; fully-qualified # 🤹🏻‍♀️ E4.0 woman juggling: light skin tone -1F939 1F3FB 200D 2640 ; minimally-qualified # 🤹🏻‍♀ E4.0 woman juggling: light skin tone -1F939 1F3FC 200D 2640 FE0F ; fully-qualified # 🤹🏼‍♀️ E4.0 woman juggling: medium-light skin tone -1F939 1F3FC 200D 2640 ; minimally-qualified # 🤹🏼‍♀ E4.0 woman juggling: medium-light skin tone -1F939 1F3FD 200D 2640 FE0F ; fully-qualified # 🤹🏽‍♀️ E4.0 woman juggling: medium skin tone -1F939 1F3FD 200D 2640 ; minimally-qualified # 🤹🏽‍♀ E4.0 woman juggling: medium skin tone -1F939 1F3FE 200D 2640 FE0F ; fully-qualified # 🤹🏾‍♀️ E4.0 woman juggling: medium-dark skin tone -1F939 1F3FE 200D 2640 ; minimally-qualified # 🤹🏾‍♀ E4.0 woman juggling: medium-dark skin tone -1F939 1F3FF 200D 2640 FE0F ; fully-qualified # 🤹🏿‍♀️ E4.0 woman juggling: dark skin tone -1F939 1F3FF 200D 2640 ; minimally-qualified # 🤹🏿‍♀ E4.0 woman juggling: dark skin tone - -# subgroup: person-resting -1F9D8 ; fully-qualified # 🧘 E5.0 person in lotus position -1F9D8 1F3FB ; fully-qualified # 🧘🏻 E5.0 person in lotus position: light skin tone -1F9D8 1F3FC ; fully-qualified # 🧘🏼 E5.0 person in lotus position: medium-light skin tone -1F9D8 1F3FD ; fully-qualified # 🧘🏽 E5.0 person in lotus position: medium skin tone -1F9D8 1F3FE ; fully-qualified # 🧘🏾 E5.0 person in lotus position: medium-dark skin tone -1F9D8 1F3FF ; fully-qualified # 🧘🏿 E5.0 person in lotus position: dark skin tone -1F9D8 200D 2642 FE0F ; fully-qualified # 🧘‍♂️ E5.0 man in lotus position -1F9D8 200D 2642 ; minimally-qualified # 🧘‍♂ E5.0 man in lotus position -1F9D8 1F3FB 200D 2642 FE0F ; fully-qualified # 🧘🏻‍♂️ E5.0 man in lotus position: light skin tone -1F9D8 1F3FB 200D 2642 ; minimally-qualified # 🧘🏻‍♂ E5.0 man in lotus position: light skin tone -1F9D8 1F3FC 200D 2642 FE0F ; fully-qualified # 🧘🏼‍♂️ E5.0 man in lotus position: medium-light skin tone -1F9D8 1F3FC 200D 2642 ; minimally-qualified # 🧘🏼‍♂ E5.0 man in lotus position: medium-light skin tone -1F9D8 1F3FD 200D 2642 FE0F ; fully-qualified # 🧘🏽‍♂️ E5.0 man in lotus position: medium skin tone -1F9D8 1F3FD 200D 2642 ; minimally-qualified # 🧘🏽‍♂ E5.0 man in lotus position: medium skin tone -1F9D8 1F3FE 200D 2642 FE0F ; fully-qualified # 🧘🏾‍♂️ E5.0 man in lotus position: medium-dark skin tone -1F9D8 1F3FE 200D 2642 ; minimally-qualified # 🧘🏾‍♂ E5.0 man in lotus position: medium-dark skin tone -1F9D8 1F3FF 200D 2642 FE0F ; fully-qualified # 🧘🏿‍♂️ E5.0 man in lotus position: dark skin tone -1F9D8 1F3FF 200D 2642 ; minimally-qualified # 🧘🏿‍♂ E5.0 man in lotus position: dark skin tone -1F9D8 200D 2640 FE0F ; fully-qualified # 🧘‍♀️ E5.0 woman in lotus position -1F9D8 200D 2640 ; minimally-qualified # 🧘‍♀ E5.0 woman in lotus position -1F9D8 1F3FB 200D 2640 FE0F ; fully-qualified # 🧘🏻‍♀️ E5.0 woman in lotus position: light skin tone -1F9D8 1F3FB 200D 2640 ; minimally-qualified # 🧘🏻‍♀ E5.0 woman in lotus position: light skin tone -1F9D8 1F3FC 200D 2640 FE0F ; fully-qualified # 🧘🏼‍♀️ E5.0 woman in lotus position: medium-light skin tone -1F9D8 1F3FC 200D 2640 ; minimally-qualified # 🧘🏼‍♀ E5.0 woman in lotus position: medium-light skin tone -1F9D8 1F3FD 200D 2640 FE0F ; fully-qualified # 🧘🏽‍♀️ E5.0 woman in lotus position: medium skin tone -1F9D8 1F3FD 200D 2640 ; minimally-qualified # 🧘🏽‍♀ E5.0 woman in lotus position: medium skin tone -1F9D8 1F3FE 200D 2640 FE0F ; fully-qualified # 🧘🏾‍♀️ E5.0 woman in lotus position: medium-dark skin tone -1F9D8 1F3FE 200D 2640 ; minimally-qualified # 🧘🏾‍♀ E5.0 woman in lotus position: medium-dark skin tone -1F9D8 1F3FF 200D 2640 FE0F ; fully-qualified # 🧘🏿‍♀️ E5.0 woman in lotus position: dark skin tone -1F9D8 1F3FF 200D 2640 ; minimally-qualified # 🧘🏿‍♀ E5.0 woman in lotus position: dark skin tone -1F6C0 ; fully-qualified # 🛀 E0.6 person taking bath -1F6C0 1F3FB ; fully-qualified # 🛀🏻 E1.0 person taking bath: light skin tone -1F6C0 1F3FC ; fully-qualified # 🛀🏼 E1.0 person taking bath: medium-light skin tone -1F6C0 1F3FD ; fully-qualified # 🛀🏽 E1.0 person taking bath: medium skin tone -1F6C0 1F3FE ; fully-qualified # 🛀🏾 E1.0 person taking bath: medium-dark skin tone -1F6C0 1F3FF ; fully-qualified # 🛀🏿 E1.0 person taking bath: dark skin tone -1F6CC ; fully-qualified # 🛌 E1.0 person in bed -1F6CC 1F3FB ; fully-qualified # 🛌🏻 E4.0 person in bed: light skin tone -1F6CC 1F3FC ; fully-qualified # 🛌🏼 E4.0 person in bed: medium-light skin tone -1F6CC 1F3FD ; fully-qualified # 🛌🏽 E4.0 person in bed: medium skin tone -1F6CC 1F3FE ; fully-qualified # 🛌🏾 E4.0 person in bed: medium-dark skin tone -1F6CC 1F3FF ; fully-qualified # 🛌🏿 E4.0 person in bed: dark skin tone - -# subgroup: family -1F9D1 200D 1F91D 200D 1F9D1 ; fully-qualified # 🧑‍🤝‍🧑 E12.0 people holding hands -1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏻‍🤝‍🧑🏻 E12.0 people holding hands: light skin tone -1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏻‍🤝‍🧑🏼 E12.1 people holding hands: light skin tone, medium-light skin tone -1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏻‍🤝‍🧑🏽 E12.1 people holding hands: light skin tone, medium skin tone -1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏻‍🤝‍🧑🏾 E12.1 people holding hands: light skin tone, medium-dark skin tone -1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏻‍🤝‍🧑🏿 E12.1 people holding hands: light skin tone, dark skin tone -1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏼‍🤝‍🧑🏻 E12.0 people holding hands: medium-light skin tone, light skin tone -1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏼‍🤝‍🧑🏼 E12.0 people holding hands: medium-light skin tone -1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏼‍🤝‍🧑🏽 E12.1 people holding hands: medium-light skin tone, medium skin tone -1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏼‍🤝‍🧑🏾 E12.1 people holding hands: medium-light skin tone, medium-dark skin tone -1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏼‍🤝‍🧑🏿 E12.1 people holding hands: medium-light skin tone, dark skin tone -1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏽‍🤝‍🧑🏻 E12.0 people holding hands: medium skin tone, light skin tone -1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏽‍🤝‍🧑🏼 E12.0 people holding hands: medium skin tone, medium-light skin tone -1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏽‍🤝‍🧑🏽 E12.0 people holding hands: medium skin tone -1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏽‍🤝‍🧑🏾 E12.1 people holding hands: medium skin tone, medium-dark skin tone -1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏽‍🤝‍🧑🏿 E12.1 people holding hands: medium skin tone, dark skin tone -1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏾‍🤝‍🧑🏻 E12.0 people holding hands: medium-dark skin tone, light skin tone -1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏾‍🤝‍🧑🏼 E12.0 people holding hands: medium-dark skin tone, medium-light skin tone -1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏾‍🤝‍🧑🏽 E12.0 people holding hands: medium-dark skin tone, medium skin tone -1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏾‍🤝‍🧑🏾 E12.0 people holding hands: medium-dark skin tone -1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏾‍🤝‍🧑🏿 E12.1 people holding hands: medium-dark skin tone, dark skin tone -1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏿‍🤝‍🧑🏻 E12.0 people holding hands: dark skin tone, light skin tone -1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏿‍🤝‍🧑🏼 E12.0 people holding hands: dark skin tone, medium-light skin tone -1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏿‍🤝‍🧑🏽 E12.0 people holding hands: dark skin tone, medium skin tone -1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏿‍🤝‍🧑🏾 E12.0 people holding hands: dark skin tone, medium-dark skin tone -1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏿‍🤝‍🧑🏿 E12.0 people holding hands: dark skin tone -1F46D ; fully-qualified # 👭 E1.0 women holding hands -1F46D 1F3FB ; fully-qualified # 👭🏻 E12.0 women holding hands: light skin tone -1F469 1F3FB 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏻‍🤝‍👩🏼 E12.1 women holding hands: light skin tone, medium-light skin tone -1F469 1F3FB 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏻‍🤝‍👩🏽 E12.1 women holding hands: light skin tone, medium skin tone -1F469 1F3FB 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏻‍🤝‍👩🏾 E12.1 women holding hands: light skin tone, medium-dark skin tone -1F469 1F3FB 200D 1F91D 200D 1F469 1F3FF ; fully-qualified # 👩🏻‍🤝‍👩🏿 E12.1 women holding hands: light skin tone, dark skin tone -1F469 1F3FC 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏼‍🤝‍👩🏻 E12.0 women holding hands: medium-light skin tone, light skin tone -1F46D 1F3FC ; fully-qualified # 👭🏼 E12.0 women holding hands: medium-light skin tone -1F469 1F3FC 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏼‍🤝‍👩🏽 E12.1 women holding hands: medium-light skin tone, medium skin tone -1F469 1F3FC 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏼‍🤝‍👩🏾 E12.1 women holding hands: medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 1F91D 200D 1F469 1F3FF ; fully-qualified # 👩🏼‍🤝‍👩🏿 E12.1 women holding hands: medium-light skin tone, dark skin tone -1F469 1F3FD 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏽‍🤝‍👩🏻 E12.0 women holding hands: medium skin tone, light skin tone -1F469 1F3FD 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏽‍🤝‍👩🏼 E12.0 women holding hands: medium skin tone, medium-light skin tone -1F46D 1F3FD ; fully-qualified # 👭🏽 E12.0 women holding hands: medium skin tone -1F469 1F3FD 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏽‍🤝‍👩🏾 E12.1 women holding hands: medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 1F91D 200D 1F469 1F3FF ; fully-qualified # 👩🏽‍🤝‍👩🏿 E12.1 women holding hands: medium skin tone, dark skin tone -1F469 1F3FE 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏾‍🤝‍👩🏻 E12.0 women holding hands: medium-dark skin tone, light skin tone -1F469 1F3FE 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏾‍🤝‍👩🏼 E12.0 women holding hands: medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏾‍🤝‍👩🏽 E12.0 women holding hands: medium-dark skin tone, medium skin tone -1F46D 1F3FE ; fully-qualified # 👭🏾 E12.0 women holding hands: medium-dark skin tone -1F469 1F3FE 200D 1F91D 200D 1F469 1F3FF ; fully-qualified # 👩🏾‍🤝‍👩🏿 E12.1 women holding hands: medium-dark skin tone, dark skin tone -1F469 1F3FF 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏿‍🤝‍👩🏻 E12.0 women holding hands: dark skin tone, light skin tone -1F469 1F3FF 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏿‍🤝‍👩🏼 E12.0 women holding hands: dark skin tone, medium-light skin tone -1F469 1F3FF 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏿‍🤝‍👩🏽 E12.0 women holding hands: dark skin tone, medium skin tone -1F469 1F3FF 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏿‍🤝‍👩🏾 E12.0 women holding hands: dark skin tone, medium-dark skin tone -1F46D 1F3FF ; fully-qualified # 👭🏿 E12.0 women holding hands: dark skin tone -1F46B ; fully-qualified # 👫 E0.6 woman and man holding hands -1F46B 1F3FB ; fully-qualified # 👫🏻 E12.0 woman and man holding hands: light skin tone -1F469 1F3FB 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏻‍🤝‍👨🏼 E12.0 woman and man holding hands: light skin tone, medium-light skin tone -1F469 1F3FB 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏻‍🤝‍👨🏽 E12.0 woman and man holding hands: light skin tone, medium skin tone -1F469 1F3FB 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏻‍🤝‍👨🏾 E12.0 woman and man holding hands: light skin tone, medium-dark skin tone -1F469 1F3FB 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏻‍🤝‍👨🏿 E12.0 woman and man holding hands: light skin tone, dark skin tone -1F469 1F3FC 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏼‍🤝‍👨🏻 E12.0 woman and man holding hands: medium-light skin tone, light skin tone -1F46B 1F3FC ; fully-qualified # 👫🏼 E12.0 woman and man holding hands: medium-light skin tone -1F469 1F3FC 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏼‍🤝‍👨🏽 E12.0 woman and man holding hands: medium-light skin tone, medium skin tone -1F469 1F3FC 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏼‍🤝‍👨🏾 E12.0 woman and man holding hands: medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏼‍🤝‍👨🏿 E12.0 woman and man holding hands: medium-light skin tone, dark skin tone -1F469 1F3FD 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏽‍🤝‍👨🏻 E12.0 woman and man holding hands: medium skin tone, light skin tone -1F469 1F3FD 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏽‍🤝‍👨🏼 E12.0 woman and man holding hands: medium skin tone, medium-light skin tone -1F46B 1F3FD ; fully-qualified # 👫🏽 E12.0 woman and man holding hands: medium skin tone -1F469 1F3FD 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏽‍🤝‍👨🏾 E12.0 woman and man holding hands: medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏽‍🤝‍👨🏿 E12.0 woman and man holding hands: medium skin tone, dark skin tone -1F469 1F3FE 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏾‍🤝‍👨🏻 E12.0 woman and man holding hands: medium-dark skin tone, light skin tone -1F469 1F3FE 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏾‍🤝‍👨🏼 E12.0 woman and man holding hands: medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏾‍🤝‍👨🏽 E12.0 woman and man holding hands: medium-dark skin tone, medium skin tone -1F46B 1F3FE ; fully-qualified # 👫🏾 E12.0 woman and man holding hands: medium-dark skin tone -1F469 1F3FE 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏾‍🤝‍👨🏿 E12.0 woman and man holding hands: medium-dark skin tone, dark skin tone -1F469 1F3FF 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏿‍🤝‍👨🏻 E12.0 woman and man holding hands: dark skin tone, light skin tone -1F469 1F3FF 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏿‍🤝‍👨🏼 E12.0 woman and man holding hands: dark skin tone, medium-light skin tone -1F469 1F3FF 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏿‍🤝‍👨🏽 E12.0 woman and man holding hands: dark skin tone, medium skin tone -1F469 1F3FF 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏿‍🤝‍👨🏾 E12.0 woman and man holding hands: dark skin tone, medium-dark skin tone -1F46B 1F3FF ; fully-qualified # 👫🏿 E12.0 woman and man holding hands: dark skin tone -1F46C ; fully-qualified # 👬 E1.0 men holding hands -1F46C 1F3FB ; fully-qualified # 👬🏻 E12.0 men holding hands: light skin tone -1F468 1F3FB 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏻‍🤝‍👨🏼 E12.1 men holding hands: light skin tone, medium-light skin tone -1F468 1F3FB 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏻‍🤝‍👨🏽 E12.1 men holding hands: light skin tone, medium skin tone -1F468 1F3FB 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏻‍🤝‍👨🏾 E12.1 men holding hands: light skin tone, medium-dark skin tone -1F468 1F3FB 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👨🏻‍🤝‍👨🏿 E12.1 men holding hands: light skin tone, dark skin tone -1F468 1F3FC 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏼‍🤝‍👨🏻 E12.0 men holding hands: medium-light skin tone, light skin tone -1F46C 1F3FC ; fully-qualified # 👬🏼 E12.0 men holding hands: medium-light skin tone -1F468 1F3FC 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏼‍🤝‍👨🏽 E12.1 men holding hands: medium-light skin tone, medium skin tone -1F468 1F3FC 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏼‍🤝‍👨🏾 E12.1 men holding hands: medium-light skin tone, medium-dark skin tone -1F468 1F3FC 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👨🏼‍🤝‍👨🏿 E12.1 men holding hands: medium-light skin tone, dark skin tone -1F468 1F3FD 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏽‍🤝‍👨🏻 E12.0 men holding hands: medium skin tone, light skin tone -1F468 1F3FD 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏽‍🤝‍👨🏼 E12.0 men holding hands: medium skin tone, medium-light skin tone -1F46C 1F3FD ; fully-qualified # 👬🏽 E12.0 men holding hands: medium skin tone -1F468 1F3FD 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏽‍🤝‍👨🏾 E12.1 men holding hands: medium skin tone, medium-dark skin tone -1F468 1F3FD 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👨🏽‍🤝‍👨🏿 E12.1 men holding hands: medium skin tone, dark skin tone -1F468 1F3FE 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏾‍🤝‍👨🏻 E12.0 men holding hands: medium-dark skin tone, light skin tone -1F468 1F3FE 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏾‍🤝‍👨🏼 E12.0 men holding hands: medium-dark skin tone, medium-light skin tone -1F468 1F3FE 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏾‍🤝‍👨🏽 E12.0 men holding hands: medium-dark skin tone, medium skin tone -1F46C 1F3FE ; fully-qualified # 👬🏾 E12.0 men holding hands: medium-dark skin tone -1F468 1F3FE 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👨🏾‍🤝‍👨🏿 E12.1 men holding hands: medium-dark skin tone, dark skin tone -1F468 1F3FF 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏿‍🤝‍👨🏻 E12.0 men holding hands: dark skin tone, light skin tone -1F468 1F3FF 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏿‍🤝‍👨🏼 E12.0 men holding hands: dark skin tone, medium-light skin tone -1F468 1F3FF 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏿‍🤝‍👨🏽 E12.0 men holding hands: dark skin tone, medium skin tone -1F468 1F3FF 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏿‍🤝‍👨🏾 E12.0 men holding hands: dark skin tone, medium-dark skin tone -1F46C 1F3FF ; fully-qualified # 👬🏿 E12.0 men holding hands: dark skin tone -1F48F ; fully-qualified # 💏 E0.6 kiss -1F48F 1F3FB ; fully-qualified # 💏🏻 E13.1 kiss: light skin tone -1F48F 1F3FC ; fully-qualified # 💏🏼 E13.1 kiss: medium-light skin tone -1F48F 1F3FD ; fully-qualified # 💏🏽 E13.1 kiss: medium skin tone -1F48F 1F3FE ; fully-qualified # 💏🏾 E13.1 kiss: medium-dark skin tone -1F48F 1F3FF ; fully-qualified # 💏🏿 E13.1 kiss: dark skin tone -1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏻‍❤️‍💋‍🧑🏼 E13.1 kiss: person, person, light skin tone, medium-light skin tone -1F9D1 1F3FB 200D 2764 200D 1F48B 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏻‍❤‍💋‍🧑🏼 E13.1 kiss: person, person, light skin tone, medium-light skin tone -1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏻‍❤️‍💋‍🧑🏽 E13.1 kiss: person, person, light skin tone, medium skin tone -1F9D1 1F3FB 200D 2764 200D 1F48B 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏻‍❤‍💋‍🧑🏽 E13.1 kiss: person, person, light skin tone, medium skin tone -1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏻‍❤️‍💋‍🧑🏾 E13.1 kiss: person, person, light skin tone, medium-dark skin tone -1F9D1 1F3FB 200D 2764 200D 1F48B 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏻‍❤‍💋‍🧑🏾 E13.1 kiss: person, person, light skin tone, medium-dark skin tone -1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏻‍❤️‍💋‍🧑🏿 E13.1 kiss: person, person, light skin tone, dark skin tone -1F9D1 1F3FB 200D 2764 200D 1F48B 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏻‍❤‍💋‍🧑🏿 E13.1 kiss: person, person, light skin tone, dark skin tone -1F9D1 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏼‍❤️‍💋‍🧑🏻 E13.1 kiss: person, person, medium-light skin tone, light skin tone -1F9D1 1F3FC 200D 2764 200D 1F48B 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏼‍❤‍💋‍🧑🏻 E13.1 kiss: person, person, medium-light skin tone, light skin tone -1F9D1 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏼‍❤️‍💋‍🧑🏽 E13.1 kiss: person, person, medium-light skin tone, medium skin tone -1F9D1 1F3FC 200D 2764 200D 1F48B 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏼‍❤‍💋‍🧑🏽 E13.1 kiss: person, person, medium-light skin tone, medium skin tone -1F9D1 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏼‍❤️‍💋‍🧑🏾 E13.1 kiss: person, person, medium-light skin tone, medium-dark skin tone -1F9D1 1F3FC 200D 2764 200D 1F48B 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏼‍❤‍💋‍🧑🏾 E13.1 kiss: person, person, medium-light skin tone, medium-dark skin tone -1F9D1 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏼‍❤️‍💋‍🧑🏿 E13.1 kiss: person, person, medium-light skin tone, dark skin tone -1F9D1 1F3FC 200D 2764 200D 1F48B 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏼‍❤‍💋‍🧑🏿 E13.1 kiss: person, person, medium-light skin tone, dark skin tone -1F9D1 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏽‍❤️‍💋‍🧑🏻 E13.1 kiss: person, person, medium skin tone, light skin tone -1F9D1 1F3FD 200D 2764 200D 1F48B 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏽‍❤‍💋‍🧑🏻 E13.1 kiss: person, person, medium skin tone, light skin tone -1F9D1 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏽‍❤️‍💋‍🧑🏼 E13.1 kiss: person, person, medium skin tone, medium-light skin tone -1F9D1 1F3FD 200D 2764 200D 1F48B 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏽‍❤‍💋‍🧑🏼 E13.1 kiss: person, person, medium skin tone, medium-light skin tone -1F9D1 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏽‍❤️‍💋‍🧑🏾 E13.1 kiss: person, person, medium skin tone, medium-dark skin tone -1F9D1 1F3FD 200D 2764 200D 1F48B 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏽‍❤‍💋‍🧑🏾 E13.1 kiss: person, person, medium skin tone, medium-dark skin tone -1F9D1 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏽‍❤️‍💋‍🧑🏿 E13.1 kiss: person, person, medium skin tone, dark skin tone -1F9D1 1F3FD 200D 2764 200D 1F48B 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏽‍❤‍💋‍🧑🏿 E13.1 kiss: person, person, medium skin tone, dark skin tone -1F9D1 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏾‍❤️‍💋‍🧑🏻 E13.1 kiss: person, person, medium-dark skin tone, light skin tone -1F9D1 1F3FE 200D 2764 200D 1F48B 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏾‍❤‍💋‍🧑🏻 E13.1 kiss: person, person, medium-dark skin tone, light skin tone -1F9D1 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏾‍❤️‍💋‍🧑🏼 E13.1 kiss: person, person, medium-dark skin tone, medium-light skin tone -1F9D1 1F3FE 200D 2764 200D 1F48B 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏾‍❤‍💋‍🧑🏼 E13.1 kiss: person, person, medium-dark skin tone, medium-light skin tone -1F9D1 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏾‍❤️‍💋‍🧑🏽 E13.1 kiss: person, person, medium-dark skin tone, medium skin tone -1F9D1 1F3FE 200D 2764 200D 1F48B 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏾‍❤‍💋‍🧑🏽 E13.1 kiss: person, person, medium-dark skin tone, medium skin tone -1F9D1 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏾‍❤️‍💋‍🧑🏿 E13.1 kiss: person, person, medium-dark skin tone, dark skin tone -1F9D1 1F3FE 200D 2764 200D 1F48B 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏾‍❤‍💋‍🧑🏿 E13.1 kiss: person, person, medium-dark skin tone, dark skin tone -1F9D1 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏿‍❤️‍💋‍🧑🏻 E13.1 kiss: person, person, dark skin tone, light skin tone -1F9D1 1F3FF 200D 2764 200D 1F48B 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏿‍❤‍💋‍🧑🏻 E13.1 kiss: person, person, dark skin tone, light skin tone -1F9D1 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏿‍❤️‍💋‍🧑🏼 E13.1 kiss: person, person, dark skin tone, medium-light skin tone -1F9D1 1F3FF 200D 2764 200D 1F48B 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏿‍❤‍💋‍🧑🏼 E13.1 kiss: person, person, dark skin tone, medium-light skin tone -1F9D1 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏿‍❤️‍💋‍🧑🏽 E13.1 kiss: person, person, dark skin tone, medium skin tone -1F9D1 1F3FF 200D 2764 200D 1F48B 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏿‍❤‍💋‍🧑🏽 E13.1 kiss: person, person, dark skin tone, medium skin tone -1F9D1 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏿‍❤️‍💋‍🧑🏾 E13.1 kiss: person, person, dark skin tone, medium-dark skin tone -1F9D1 1F3FF 200D 2764 200D 1F48B 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏿‍❤‍💋‍🧑🏾 E13.1 kiss: person, person, dark skin tone, medium-dark skin tone -1F469 200D 2764 FE0F 200D 1F48B 200D 1F468 ; fully-qualified # 👩‍❤️‍💋‍👨 E2.0 kiss: woman, man -1F469 200D 2764 200D 1F48B 200D 1F468 ; minimally-qualified # 👩‍❤‍💋‍👨 E2.0 kiss: woman, man -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, light skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, light skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, light skin tone, medium-light skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, light skin tone, medium-light skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, light skin tone, medium skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, light skin tone, medium skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, light skin tone, medium-dark skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, light skin tone, medium-dark skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏻‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, light skin tone, dark skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏻‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, light skin tone, dark skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, medium-light skin tone, light skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, medium-light skin tone, light skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, medium-light skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, medium-light skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, medium-light skin tone, medium skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, medium-light skin tone, medium skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏼‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, medium-light skin tone, dark skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏼‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, medium-light skin tone, dark skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, medium skin tone, light skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, medium skin tone, light skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, medium skin tone, medium-light skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, medium skin tone, medium-light skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, medium skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, medium skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏽‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, medium skin tone, dark skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏽‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, medium skin tone, dark skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, medium-dark skin tone, light skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, medium-dark skin tone, light skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, medium-dark skin tone, medium skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, medium-dark skin tone, medium skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, medium-dark skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, medium-dark skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏾‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, medium-dark skin tone, dark skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏾‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, medium-dark skin tone, dark skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏻 E13.1 kiss: woman, man, dark skin tone, light skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏻 E13.1 kiss: woman, man, dark skin tone, light skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏼 E13.1 kiss: woman, man, dark skin tone, medium-light skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏼 E13.1 kiss: woman, man, dark skin tone, medium-light skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏽 E13.1 kiss: woman, man, dark skin tone, medium skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏽 E13.1 kiss: woman, man, dark skin tone, medium skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏾 E13.1 kiss: woman, man, dark skin tone, medium-dark skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏾 E13.1 kiss: woman, man, dark skin tone, medium-dark skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👩🏿‍❤️‍💋‍👨🏿 E13.1 kiss: woman, man, dark skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👩🏿‍❤‍💋‍👨🏿 E13.1 kiss: woman, man, dark skin tone -1F468 200D 2764 FE0F 200D 1F48B 200D 1F468 ; fully-qualified # 👨‍❤️‍💋‍👨 E2.0 kiss: man, man -1F468 200D 2764 200D 1F48B 200D 1F468 ; minimally-qualified # 👨‍❤‍💋‍👨 E2.0 kiss: man, man -1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, light skin tone -1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏻 E13.1 kiss: man, man, light skin tone -1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, light skin tone, medium-light skin tone -1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏼 E13.1 kiss: man, man, light skin tone, medium-light skin tone -1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, light skin tone, medium skin tone -1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏽 E13.1 kiss: man, man, light skin tone, medium skin tone -1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, light skin tone, medium-dark skin tone -1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏾 E13.1 kiss: man, man, light skin tone, medium-dark skin tone -1F468 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏻‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, light skin tone, dark skin tone -1F468 1F3FB 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏻‍❤‍💋‍👨🏿 E13.1 kiss: man, man, light skin tone, dark skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, medium-light skin tone, light skin tone -1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏻 E13.1 kiss: man, man, medium-light skin tone, light skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, medium-light skin tone -1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏼 E13.1 kiss: man, man, medium-light skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, medium-light skin tone, medium skin tone -1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏽 E13.1 kiss: man, man, medium-light skin tone, medium skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, medium-light skin tone, medium-dark skin tone -1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏾 E13.1 kiss: man, man, medium-light skin tone, medium-dark skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏼‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, medium-light skin tone, dark skin tone -1F468 1F3FC 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏼‍❤‍💋‍👨🏿 E13.1 kiss: man, man, medium-light skin tone, dark skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, medium skin tone, light skin tone -1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏻 E13.1 kiss: man, man, medium skin tone, light skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, medium skin tone, medium-light skin tone -1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏼 E13.1 kiss: man, man, medium skin tone, medium-light skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, medium skin tone -1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏽 E13.1 kiss: man, man, medium skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, medium skin tone, medium-dark skin tone -1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏾 E13.1 kiss: man, man, medium skin tone, medium-dark skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏽‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, medium skin tone, dark skin tone -1F468 1F3FD 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏽‍❤‍💋‍👨🏿 E13.1 kiss: man, man, medium skin tone, dark skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, medium-dark skin tone, light skin tone -1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏻 E13.1 kiss: man, man, medium-dark skin tone, light skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, medium-dark skin tone, medium-light skin tone -1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏼 E13.1 kiss: man, man, medium-dark skin tone, medium-light skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, medium-dark skin tone, medium skin tone -1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏽 E13.1 kiss: man, man, medium-dark skin tone, medium skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, medium-dark skin tone -1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏾 E13.1 kiss: man, man, medium-dark skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏾‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, medium-dark skin tone, dark skin tone -1F468 1F3FE 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏾‍❤‍💋‍👨🏿 E13.1 kiss: man, man, medium-dark skin tone, dark skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FB ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏻 E13.1 kiss: man, man, dark skin tone, light skin tone -1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FB ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏻 E13.1 kiss: man, man, dark skin tone, light skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FC ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏼 E13.1 kiss: man, man, dark skin tone, medium-light skin tone -1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FC ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏼 E13.1 kiss: man, man, dark skin tone, medium-light skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FD ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏽 E13.1 kiss: man, man, dark skin tone, medium skin tone -1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FD ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏽 E13.1 kiss: man, man, dark skin tone, medium skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FE ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏾 E13.1 kiss: man, man, dark skin tone, medium-dark skin tone -1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FE ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏾 E13.1 kiss: man, man, dark skin tone, medium-dark skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F468 1F3FF ; fully-qualified # 👨🏿‍❤️‍💋‍👨🏿 E13.1 kiss: man, man, dark skin tone -1F468 1F3FF 200D 2764 200D 1F48B 200D 1F468 1F3FF ; minimally-qualified # 👨🏿‍❤‍💋‍👨🏿 E13.1 kiss: man, man, dark skin tone -1F469 200D 2764 FE0F 200D 1F48B 200D 1F469 ; fully-qualified # 👩‍❤️‍💋‍👩 E2.0 kiss: woman, woman -1F469 200D 2764 200D 1F48B 200D 1F469 ; minimally-qualified # 👩‍❤‍💋‍👩 E2.0 kiss: woman, woman -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, light skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, light skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, light skin tone, medium-light skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, light skin tone, medium-light skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, light skin tone, medium skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, light skin tone, medium skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, light skin tone, medium-dark skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, light skin tone, medium-dark skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏻‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, light skin tone, dark skin tone -1F469 1F3FB 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏻‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, light skin tone, dark skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, medium-light skin tone, light skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, medium-light skin tone, light skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, medium-light skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, medium-light skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, medium-light skin tone, medium skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, medium-light skin tone, medium skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏼‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, medium-light skin tone, dark skin tone -1F469 1F3FC 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏼‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, medium-light skin tone, dark skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, medium skin tone, light skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, medium skin tone, light skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, medium skin tone, medium-light skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, medium skin tone, medium-light skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, medium skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, medium skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏽‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, medium skin tone, dark skin tone -1F469 1F3FD 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏽‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, medium skin tone, dark skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, medium-dark skin tone, light skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, medium-dark skin tone, light skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, medium-dark skin tone, medium skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, medium-dark skin tone, medium skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, medium-dark skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, medium-dark skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏾‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, medium-dark skin tone, dark skin tone -1F469 1F3FE 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏾‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, medium-dark skin tone, dark skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FB ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏻 E13.1 kiss: woman, woman, dark skin tone, light skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FB ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏻 E13.1 kiss: woman, woman, dark skin tone, light skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FC ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏼 E13.1 kiss: woman, woman, dark skin tone, medium-light skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FC ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏼 E13.1 kiss: woman, woman, dark skin tone, medium-light skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FD ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏽 E13.1 kiss: woman, woman, dark skin tone, medium skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FD ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏽 E13.1 kiss: woman, woman, dark skin tone, medium skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FE ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏾 E13.1 kiss: woman, woman, dark skin tone, medium-dark skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FE ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏾 E13.1 kiss: woman, woman, dark skin tone, medium-dark skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F48B 200D 1F469 1F3FF ; fully-qualified # 👩🏿‍❤️‍💋‍👩🏿 E13.1 kiss: woman, woman, dark skin tone -1F469 1F3FF 200D 2764 200D 1F48B 200D 1F469 1F3FF ; minimally-qualified # 👩🏿‍❤‍💋‍👩🏿 E13.1 kiss: woman, woman, dark skin tone -1F491 ; fully-qualified # 💑 E0.6 couple with heart -1F491 1F3FB ; fully-qualified # 💑🏻 E13.1 couple with heart: light skin tone -1F491 1F3FC ; fully-qualified # 💑🏼 E13.1 couple with heart: medium-light skin tone -1F491 1F3FD ; fully-qualified # 💑🏽 E13.1 couple with heart: medium skin tone -1F491 1F3FE ; fully-qualified # 💑🏾 E13.1 couple with heart: medium-dark skin tone -1F491 1F3FF ; fully-qualified # 💑🏿 E13.1 couple with heart: dark skin tone -1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏻‍❤️‍🧑🏼 E13.1 couple with heart: person, person, light skin tone, medium-light skin tone -1F9D1 1F3FB 200D 2764 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏻‍❤‍🧑🏼 E13.1 couple with heart: person, person, light skin tone, medium-light skin tone -1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏻‍❤️‍🧑🏽 E13.1 couple with heart: person, person, light skin tone, medium skin tone -1F9D1 1F3FB 200D 2764 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏻‍❤‍🧑🏽 E13.1 couple with heart: person, person, light skin tone, medium skin tone -1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏻‍❤️‍🧑🏾 E13.1 couple with heart: person, person, light skin tone, medium-dark skin tone -1F9D1 1F3FB 200D 2764 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏻‍❤‍🧑🏾 E13.1 couple with heart: person, person, light skin tone, medium-dark skin tone -1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏻‍❤️‍🧑🏿 E13.1 couple with heart: person, person, light skin tone, dark skin tone -1F9D1 1F3FB 200D 2764 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏻‍❤‍🧑🏿 E13.1 couple with heart: person, person, light skin tone, dark skin tone -1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏼‍❤️‍🧑🏻 E13.1 couple with heart: person, person, medium-light skin tone, light skin tone -1F9D1 1F3FC 200D 2764 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏼‍❤‍🧑🏻 E13.1 couple with heart: person, person, medium-light skin tone, light skin tone -1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏼‍❤️‍🧑🏽 E13.1 couple with heart: person, person, medium-light skin tone, medium skin tone -1F9D1 1F3FC 200D 2764 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏼‍❤‍🧑🏽 E13.1 couple with heart: person, person, medium-light skin tone, medium skin tone -1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏼‍❤️‍🧑🏾 E13.1 couple with heart: person, person, medium-light skin tone, medium-dark skin tone -1F9D1 1F3FC 200D 2764 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏼‍❤‍🧑🏾 E13.1 couple with heart: person, person, medium-light skin tone, medium-dark skin tone -1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏼‍❤️‍🧑🏿 E13.1 couple with heart: person, person, medium-light skin tone, dark skin tone -1F9D1 1F3FC 200D 2764 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏼‍❤‍🧑🏿 E13.1 couple with heart: person, person, medium-light skin tone, dark skin tone -1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏽‍❤️‍🧑🏻 E13.1 couple with heart: person, person, medium skin tone, light skin tone -1F9D1 1F3FD 200D 2764 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏽‍❤‍🧑🏻 E13.1 couple with heart: person, person, medium skin tone, light skin tone -1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏽‍❤️‍🧑🏼 E13.1 couple with heart: person, person, medium skin tone, medium-light skin tone -1F9D1 1F3FD 200D 2764 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏽‍❤‍🧑🏼 E13.1 couple with heart: person, person, medium skin tone, medium-light skin tone -1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏽‍❤️‍🧑🏾 E13.1 couple with heart: person, person, medium skin tone, medium-dark skin tone -1F9D1 1F3FD 200D 2764 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏽‍❤‍🧑🏾 E13.1 couple with heart: person, person, medium skin tone, medium-dark skin tone -1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏽‍❤️‍🧑🏿 E13.1 couple with heart: person, person, medium skin tone, dark skin tone -1F9D1 1F3FD 200D 2764 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏽‍❤‍🧑🏿 E13.1 couple with heart: person, person, medium skin tone, dark skin tone -1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏾‍❤️‍🧑🏻 E13.1 couple with heart: person, person, medium-dark skin tone, light skin tone -1F9D1 1F3FE 200D 2764 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏾‍❤‍🧑🏻 E13.1 couple with heart: person, person, medium-dark skin tone, light skin tone -1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏾‍❤️‍🧑🏼 E13.1 couple with heart: person, person, medium-dark skin tone, medium-light skin tone -1F9D1 1F3FE 200D 2764 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏾‍❤‍🧑🏼 E13.1 couple with heart: person, person, medium-dark skin tone, medium-light skin tone -1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏾‍❤️‍🧑🏽 E13.1 couple with heart: person, person, medium-dark skin tone, medium skin tone -1F9D1 1F3FE 200D 2764 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏾‍❤‍🧑🏽 E13.1 couple with heart: person, person, medium-dark skin tone, medium skin tone -1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏾‍❤️‍🧑🏿 E13.1 couple with heart: person, person, medium-dark skin tone, dark skin tone -1F9D1 1F3FE 200D 2764 200D 1F9D1 1F3FF ; minimally-qualified # 🧑🏾‍❤‍🧑🏿 E13.1 couple with heart: person, person, medium-dark skin tone, dark skin tone -1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏿‍❤️‍🧑🏻 E13.1 couple with heart: person, person, dark skin tone, light skin tone -1F9D1 1F3FF 200D 2764 200D 1F9D1 1F3FB ; minimally-qualified # 🧑🏿‍❤‍🧑🏻 E13.1 couple with heart: person, person, dark skin tone, light skin tone -1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏿‍❤️‍🧑🏼 E13.1 couple with heart: person, person, dark skin tone, medium-light skin tone -1F9D1 1F3FF 200D 2764 200D 1F9D1 1F3FC ; minimally-qualified # 🧑🏿‍❤‍🧑🏼 E13.1 couple with heart: person, person, dark skin tone, medium-light skin tone -1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏿‍❤️‍🧑🏽 E13.1 couple with heart: person, person, dark skin tone, medium skin tone -1F9D1 1F3FF 200D 2764 200D 1F9D1 1F3FD ; minimally-qualified # 🧑🏿‍❤‍🧑🏽 E13.1 couple with heart: person, person, dark skin tone, medium skin tone -1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏿‍❤️‍🧑🏾 E13.1 couple with heart: person, person, dark skin tone, medium-dark skin tone -1F9D1 1F3FF 200D 2764 200D 1F9D1 1F3FE ; minimally-qualified # 🧑🏿‍❤‍🧑🏾 E13.1 couple with heart: person, person, dark skin tone, medium-dark skin tone -1F469 200D 2764 FE0F 200D 1F468 ; fully-qualified # 👩‍❤️‍👨 E2.0 couple with heart: woman, man -1F469 200D 2764 200D 1F468 ; minimally-qualified # 👩‍❤‍👨 E2.0 couple with heart: woman, man -1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏻‍❤️‍👨🏻 E13.1 couple with heart: woman, man, light skin tone -1F469 1F3FB 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏻‍❤‍👨🏻 E13.1 couple with heart: woman, man, light skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏻‍❤️‍👨🏼 E13.1 couple with heart: woman, man, light skin tone, medium-light skin tone -1F469 1F3FB 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏻‍❤‍👨🏼 E13.1 couple with heart: woman, man, light skin tone, medium-light skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏻‍❤️‍👨🏽 E13.1 couple with heart: woman, man, light skin tone, medium skin tone -1F469 1F3FB 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏻‍❤‍👨🏽 E13.1 couple with heart: woman, man, light skin tone, medium skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏻‍❤️‍👨🏾 E13.1 couple with heart: woman, man, light skin tone, medium-dark skin tone -1F469 1F3FB 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏻‍❤‍👨🏾 E13.1 couple with heart: woman, man, light skin tone, medium-dark skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏻‍❤️‍👨🏿 E13.1 couple with heart: woman, man, light skin tone, dark skin tone -1F469 1F3FB 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏻‍❤‍👨🏿 E13.1 couple with heart: woman, man, light skin tone, dark skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏼‍❤️‍👨🏻 E13.1 couple with heart: woman, man, medium-light skin tone, light skin tone -1F469 1F3FC 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏼‍❤‍👨🏻 E13.1 couple with heart: woman, man, medium-light skin tone, light skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏼‍❤️‍👨🏼 E13.1 couple with heart: woman, man, medium-light skin tone -1F469 1F3FC 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏼‍❤‍👨🏼 E13.1 couple with heart: woman, man, medium-light skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏼‍❤️‍👨🏽 E13.1 couple with heart: woman, man, medium-light skin tone, medium skin tone -1F469 1F3FC 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏼‍❤‍👨🏽 E13.1 couple with heart: woman, man, medium-light skin tone, medium skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏼‍❤️‍👨🏾 E13.1 couple with heart: woman, man, medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏼‍❤‍👨🏾 E13.1 couple with heart: woman, man, medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏼‍❤️‍👨🏿 E13.1 couple with heart: woman, man, medium-light skin tone, dark skin tone -1F469 1F3FC 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏼‍❤‍👨🏿 E13.1 couple with heart: woman, man, medium-light skin tone, dark skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏽‍❤️‍👨🏻 E13.1 couple with heart: woman, man, medium skin tone, light skin tone -1F469 1F3FD 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏽‍❤‍👨🏻 E13.1 couple with heart: woman, man, medium skin tone, light skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏽‍❤️‍👨🏼 E13.1 couple with heart: woman, man, medium skin tone, medium-light skin tone -1F469 1F3FD 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏽‍❤‍👨🏼 E13.1 couple with heart: woman, man, medium skin tone, medium-light skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏽‍❤️‍👨🏽 E13.1 couple with heart: woman, man, medium skin tone -1F469 1F3FD 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏽‍❤‍👨🏽 E13.1 couple with heart: woman, man, medium skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏽‍❤️‍👨🏾 E13.1 couple with heart: woman, man, medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏽‍❤‍👨🏾 E13.1 couple with heart: woman, man, medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏽‍❤️‍👨🏿 E13.1 couple with heart: woman, man, medium skin tone, dark skin tone -1F469 1F3FD 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏽‍❤‍👨🏿 E13.1 couple with heart: woman, man, medium skin tone, dark skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏾‍❤️‍👨🏻 E13.1 couple with heart: woman, man, medium-dark skin tone, light skin tone -1F469 1F3FE 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏾‍❤‍👨🏻 E13.1 couple with heart: woman, man, medium-dark skin tone, light skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏾‍❤️‍👨🏼 E13.1 couple with heart: woman, man, medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏾‍❤‍👨🏼 E13.1 couple with heart: woman, man, medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏾‍❤️‍👨🏽 E13.1 couple with heart: woman, man, medium-dark skin tone, medium skin tone -1F469 1F3FE 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏾‍❤‍👨🏽 E13.1 couple with heart: woman, man, medium-dark skin tone, medium skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏾‍❤️‍👨🏾 E13.1 couple with heart: woman, man, medium-dark skin tone -1F469 1F3FE 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏾‍❤‍👨🏾 E13.1 couple with heart: woman, man, medium-dark skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏾‍❤️‍👨🏿 E13.1 couple with heart: woman, man, medium-dark skin tone, dark skin tone -1F469 1F3FE 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏾‍❤‍👨🏿 E13.1 couple with heart: woman, man, medium-dark skin tone, dark skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👩🏿‍❤️‍👨🏻 E13.1 couple with heart: woman, man, dark skin tone, light skin tone -1F469 1F3FF 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👩🏿‍❤‍👨🏻 E13.1 couple with heart: woman, man, dark skin tone, light skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👩🏿‍❤️‍👨🏼 E13.1 couple with heart: woman, man, dark skin tone, medium-light skin tone -1F469 1F3FF 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👩🏿‍❤‍👨🏼 E13.1 couple with heart: woman, man, dark skin tone, medium-light skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👩🏿‍❤️‍👨🏽 E13.1 couple with heart: woman, man, dark skin tone, medium skin tone -1F469 1F3FF 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👩🏿‍❤‍👨🏽 E13.1 couple with heart: woman, man, dark skin tone, medium skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👩🏿‍❤️‍👨🏾 E13.1 couple with heart: woman, man, dark skin tone, medium-dark skin tone -1F469 1F3FF 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👩🏿‍❤‍👨🏾 E13.1 couple with heart: woman, man, dark skin tone, medium-dark skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👩🏿‍❤️‍👨🏿 E13.1 couple with heart: woman, man, dark skin tone -1F469 1F3FF 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👩🏿‍❤‍👨🏿 E13.1 couple with heart: woman, man, dark skin tone -1F468 200D 2764 FE0F 200D 1F468 ; fully-qualified # 👨‍❤️‍👨 E2.0 couple with heart: man, man -1F468 200D 2764 200D 1F468 ; minimally-qualified # 👨‍❤‍👨 E2.0 couple with heart: man, man -1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏻‍❤️‍👨🏻 E13.1 couple with heart: man, man, light skin tone -1F468 1F3FB 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏻‍❤‍👨🏻 E13.1 couple with heart: man, man, light skin tone -1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏻‍❤️‍👨🏼 E13.1 couple with heart: man, man, light skin tone, medium-light skin tone -1F468 1F3FB 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏻‍❤‍👨🏼 E13.1 couple with heart: man, man, light skin tone, medium-light skin tone -1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏻‍❤️‍👨🏽 E13.1 couple with heart: man, man, light skin tone, medium skin tone -1F468 1F3FB 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏻‍❤‍👨🏽 E13.1 couple with heart: man, man, light skin tone, medium skin tone -1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏻‍❤️‍👨🏾 E13.1 couple with heart: man, man, light skin tone, medium-dark skin tone -1F468 1F3FB 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏻‍❤‍👨🏾 E13.1 couple with heart: man, man, light skin tone, medium-dark skin tone -1F468 1F3FB 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏻‍❤️‍👨🏿 E13.1 couple with heart: man, man, light skin tone, dark skin tone -1F468 1F3FB 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏻‍❤‍👨🏿 E13.1 couple with heart: man, man, light skin tone, dark skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏼‍❤️‍👨🏻 E13.1 couple with heart: man, man, medium-light skin tone, light skin tone -1F468 1F3FC 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏼‍❤‍👨🏻 E13.1 couple with heart: man, man, medium-light skin tone, light skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏼‍❤️‍👨🏼 E13.1 couple with heart: man, man, medium-light skin tone -1F468 1F3FC 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏼‍❤‍👨🏼 E13.1 couple with heart: man, man, medium-light skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏼‍❤️‍👨🏽 E13.1 couple with heart: man, man, medium-light skin tone, medium skin tone -1F468 1F3FC 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏼‍❤‍👨🏽 E13.1 couple with heart: man, man, medium-light skin tone, medium skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏼‍❤️‍👨🏾 E13.1 couple with heart: man, man, medium-light skin tone, medium-dark skin tone -1F468 1F3FC 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏼‍❤‍👨🏾 E13.1 couple with heart: man, man, medium-light skin tone, medium-dark skin tone -1F468 1F3FC 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏼‍❤️‍👨🏿 E13.1 couple with heart: man, man, medium-light skin tone, dark skin tone -1F468 1F3FC 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏼‍❤‍👨🏿 E13.1 couple with heart: man, man, medium-light skin tone, dark skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏽‍❤️‍👨🏻 E13.1 couple with heart: man, man, medium skin tone, light skin tone -1F468 1F3FD 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏽‍❤‍👨🏻 E13.1 couple with heart: man, man, medium skin tone, light skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏽‍❤️‍👨🏼 E13.1 couple with heart: man, man, medium skin tone, medium-light skin tone -1F468 1F3FD 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏽‍❤‍👨🏼 E13.1 couple with heart: man, man, medium skin tone, medium-light skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏽‍❤️‍👨🏽 E13.1 couple with heart: man, man, medium skin tone -1F468 1F3FD 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏽‍❤‍👨🏽 E13.1 couple with heart: man, man, medium skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏽‍❤️‍👨🏾 E13.1 couple with heart: man, man, medium skin tone, medium-dark skin tone -1F468 1F3FD 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏽‍❤‍👨🏾 E13.1 couple with heart: man, man, medium skin tone, medium-dark skin tone -1F468 1F3FD 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏽‍❤️‍👨🏿 E13.1 couple with heart: man, man, medium skin tone, dark skin tone -1F468 1F3FD 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏽‍❤‍👨🏿 E13.1 couple with heart: man, man, medium skin tone, dark skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏾‍❤️‍👨🏻 E13.1 couple with heart: man, man, medium-dark skin tone, light skin tone -1F468 1F3FE 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏾‍❤‍👨🏻 E13.1 couple with heart: man, man, medium-dark skin tone, light skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏾‍❤️‍👨🏼 E13.1 couple with heart: man, man, medium-dark skin tone, medium-light skin tone -1F468 1F3FE 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏾‍❤‍👨🏼 E13.1 couple with heart: man, man, medium-dark skin tone, medium-light skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏾‍❤️‍👨🏽 E13.1 couple with heart: man, man, medium-dark skin tone, medium skin tone -1F468 1F3FE 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏾‍❤‍👨🏽 E13.1 couple with heart: man, man, medium-dark skin tone, medium skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏾‍❤️‍👨🏾 E13.1 couple with heart: man, man, medium-dark skin tone -1F468 1F3FE 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏾‍❤‍👨🏾 E13.1 couple with heart: man, man, medium-dark skin tone -1F468 1F3FE 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏾‍❤️‍👨🏿 E13.1 couple with heart: man, man, medium-dark skin tone, dark skin tone -1F468 1F3FE 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏾‍❤‍👨🏿 E13.1 couple with heart: man, man, medium-dark skin tone, dark skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FB ; fully-qualified # 👨🏿‍❤️‍👨🏻 E13.1 couple with heart: man, man, dark skin tone, light skin tone -1F468 1F3FF 200D 2764 200D 1F468 1F3FB ; minimally-qualified # 👨🏿‍❤‍👨🏻 E13.1 couple with heart: man, man, dark skin tone, light skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FC ; fully-qualified # 👨🏿‍❤️‍👨🏼 E13.1 couple with heart: man, man, dark skin tone, medium-light skin tone -1F468 1F3FF 200D 2764 200D 1F468 1F3FC ; minimally-qualified # 👨🏿‍❤‍👨🏼 E13.1 couple with heart: man, man, dark skin tone, medium-light skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FD ; fully-qualified # 👨🏿‍❤️‍👨🏽 E13.1 couple with heart: man, man, dark skin tone, medium skin tone -1F468 1F3FF 200D 2764 200D 1F468 1F3FD ; minimally-qualified # 👨🏿‍❤‍👨🏽 E13.1 couple with heart: man, man, dark skin tone, medium skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FE ; fully-qualified # 👨🏿‍❤️‍👨🏾 E13.1 couple with heart: man, man, dark skin tone, medium-dark skin tone -1F468 1F3FF 200D 2764 200D 1F468 1F3FE ; minimally-qualified # 👨🏿‍❤‍👨🏾 E13.1 couple with heart: man, man, dark skin tone, medium-dark skin tone -1F468 1F3FF 200D 2764 FE0F 200D 1F468 1F3FF ; fully-qualified # 👨🏿‍❤️‍👨🏿 E13.1 couple with heart: man, man, dark skin tone -1F468 1F3FF 200D 2764 200D 1F468 1F3FF ; minimally-qualified # 👨🏿‍❤‍👨🏿 E13.1 couple with heart: man, man, dark skin tone -1F469 200D 2764 FE0F 200D 1F469 ; fully-qualified # 👩‍❤️‍👩 E2.0 couple with heart: woman, woman -1F469 200D 2764 200D 1F469 ; minimally-qualified # 👩‍❤‍👩 E2.0 couple with heart: woman, woman -1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏻‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, light skin tone -1F469 1F3FB 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏻‍❤‍👩🏻 E13.1 couple with heart: woman, woman, light skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏻‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, light skin tone, medium-light skin tone -1F469 1F3FB 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏻‍❤‍👩🏼 E13.1 couple with heart: woman, woman, light skin tone, medium-light skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏻‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, light skin tone, medium skin tone -1F469 1F3FB 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏻‍❤‍👩🏽 E13.1 couple with heart: woman, woman, light skin tone, medium skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏻‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, light skin tone, medium-dark skin tone -1F469 1F3FB 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏻‍❤‍👩🏾 E13.1 couple with heart: woman, woman, light skin tone, medium-dark skin tone -1F469 1F3FB 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏻‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, light skin tone, dark skin tone -1F469 1F3FB 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏻‍❤‍👩🏿 E13.1 couple with heart: woman, woman, light skin tone, dark skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏼‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, medium-light skin tone, light skin tone -1F469 1F3FC 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏼‍❤‍👩🏻 E13.1 couple with heart: woman, woman, medium-light skin tone, light skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏼‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, medium-light skin tone -1F469 1F3FC 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏼‍❤‍👩🏼 E13.1 couple with heart: woman, woman, medium-light skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏼‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, medium-light skin tone, medium skin tone -1F469 1F3FC 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏼‍❤‍👩🏽 E13.1 couple with heart: woman, woman, medium-light skin tone, medium skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏼‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏼‍❤‍👩🏾 E13.1 couple with heart: woman, woman, medium-light skin tone, medium-dark skin tone -1F469 1F3FC 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏼‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, medium-light skin tone, dark skin tone -1F469 1F3FC 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏼‍❤‍👩🏿 E13.1 couple with heart: woman, woman, medium-light skin tone, dark skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏽‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, medium skin tone, light skin tone -1F469 1F3FD 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏽‍❤‍👩🏻 E13.1 couple with heart: woman, woman, medium skin tone, light skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏽‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, medium skin tone, medium-light skin tone -1F469 1F3FD 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏽‍❤‍👩🏼 E13.1 couple with heart: woman, woman, medium skin tone, medium-light skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏽‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, medium skin tone -1F469 1F3FD 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏽‍❤‍👩🏽 E13.1 couple with heart: woman, woman, medium skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏽‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏽‍❤‍👩🏾 E13.1 couple with heart: woman, woman, medium skin tone, medium-dark skin tone -1F469 1F3FD 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏽‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, medium skin tone, dark skin tone -1F469 1F3FD 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏽‍❤‍👩🏿 E13.1 couple with heart: woman, woman, medium skin tone, dark skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏾‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, medium-dark skin tone, light skin tone -1F469 1F3FE 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏾‍❤‍👩🏻 E13.1 couple with heart: woman, woman, medium-dark skin tone, light skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏾‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏾‍❤‍👩🏼 E13.1 couple with heart: woman, woman, medium-dark skin tone, medium-light skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏾‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, medium-dark skin tone, medium skin tone -1F469 1F3FE 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏾‍❤‍👩🏽 E13.1 couple with heart: woman, woman, medium-dark skin tone, medium skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏾‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, medium-dark skin tone -1F469 1F3FE 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏾‍❤‍👩🏾 E13.1 couple with heart: woman, woman, medium-dark skin tone -1F469 1F3FE 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏾‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, medium-dark skin tone, dark skin tone -1F469 1F3FE 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏾‍❤‍👩🏿 E13.1 couple with heart: woman, woman, medium-dark skin tone, dark skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FB ; fully-qualified # 👩🏿‍❤️‍👩🏻 E13.1 couple with heart: woman, woman, dark skin tone, light skin tone -1F469 1F3FF 200D 2764 200D 1F469 1F3FB ; minimally-qualified # 👩🏿‍❤‍👩🏻 E13.1 couple with heart: woman, woman, dark skin tone, light skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FC ; fully-qualified # 👩🏿‍❤️‍👩🏼 E13.1 couple with heart: woman, woman, dark skin tone, medium-light skin tone -1F469 1F3FF 200D 2764 200D 1F469 1F3FC ; minimally-qualified # 👩🏿‍❤‍👩🏼 E13.1 couple with heart: woman, woman, dark skin tone, medium-light skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FD ; fully-qualified # 👩🏿‍❤️‍👩🏽 E13.1 couple with heart: woman, woman, dark skin tone, medium skin tone -1F469 1F3FF 200D 2764 200D 1F469 1F3FD ; minimally-qualified # 👩🏿‍❤‍👩🏽 E13.1 couple with heart: woman, woman, dark skin tone, medium skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FE ; fully-qualified # 👩🏿‍❤️‍👩🏾 E13.1 couple with heart: woman, woman, dark skin tone, medium-dark skin tone -1F469 1F3FF 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏿‍❤‍👩🏾 E13.1 couple with heart: woman, woman, dark skin tone, medium-dark skin tone -1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏿‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, dark skin tone -1F469 1F3FF 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏿‍❤‍👩🏿 E13.1 couple with heart: woman, woman, dark skin tone -1F46A ; fully-qualified # 👪 E0.6 family -1F468 200D 1F469 200D 1F466 ; fully-qualified # 👨‍👩‍👦 E2.0 family: man, woman, boy -1F468 200D 1F469 200D 1F467 ; fully-qualified # 👨‍👩‍👧 E2.0 family: man, woman, girl -1F468 200D 1F469 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👩‍👧‍👦 E2.0 family: man, woman, girl, boy -1F468 200D 1F469 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👩‍👦‍👦 E2.0 family: man, woman, boy, boy -1F468 200D 1F469 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👩‍👧‍👧 E2.0 family: man, woman, girl, girl -1F468 200D 1F468 200D 1F466 ; fully-qualified # 👨‍👨‍👦 E2.0 family: man, man, boy -1F468 200D 1F468 200D 1F467 ; fully-qualified # 👨‍👨‍👧 E2.0 family: man, man, girl -1F468 200D 1F468 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👨‍👧‍👦 E2.0 family: man, man, girl, boy -1F468 200D 1F468 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👨‍👦‍👦 E2.0 family: man, man, boy, boy -1F468 200D 1F468 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👨‍👧‍👧 E2.0 family: man, man, girl, girl -1F469 200D 1F469 200D 1F466 ; fully-qualified # 👩‍👩‍👦 E2.0 family: woman, woman, boy -1F469 200D 1F469 200D 1F467 ; fully-qualified # 👩‍👩‍👧 E2.0 family: woman, woman, girl -1F469 200D 1F469 200D 1F467 200D 1F466 ; fully-qualified # 👩‍👩‍👧‍👦 E2.0 family: woman, woman, girl, boy -1F469 200D 1F469 200D 1F466 200D 1F466 ; fully-qualified # 👩‍👩‍👦‍👦 E2.0 family: woman, woman, boy, boy -1F469 200D 1F469 200D 1F467 200D 1F467 ; fully-qualified # 👩‍👩‍👧‍👧 E2.0 family: woman, woman, girl, girl -1F468 200D 1F466 ; fully-qualified # 👨‍👦 E4.0 family: man, boy -1F468 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👦‍👦 E4.0 family: man, boy, boy -1F468 200D 1F467 ; fully-qualified # 👨‍👧 E4.0 family: man, girl -1F468 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👧‍👦 E4.0 family: man, girl, boy -1F468 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👧‍👧 E4.0 family: man, girl, girl -1F469 200D 1F466 ; fully-qualified # 👩‍👦 E4.0 family: woman, boy -1F469 200D 1F466 200D 1F466 ; fully-qualified # 👩‍👦‍👦 E4.0 family: woman, boy, boy -1F469 200D 1F467 ; fully-qualified # 👩‍👧 E4.0 family: woman, girl -1F469 200D 1F467 200D 1F466 ; fully-qualified # 👩‍👧‍👦 E4.0 family: woman, girl, boy -1F469 200D 1F467 200D 1F467 ; fully-qualified # 👩‍👧‍👧 E4.0 family: woman, girl, girl - -# subgroup: person-symbol -1F5E3 FE0F ; fully-qualified # 🗣️ E0.7 speaking head -1F5E3 ; unqualified # 🗣 E0.7 speaking head -1F464 ; fully-qualified # 👤 E0.6 bust in silhouette -1F465 ; fully-qualified # 👥 E1.0 busts in silhouette -1FAC2 ; fully-qualified # 🫂 E13.0 people hugging -1F463 ; fully-qualified # 👣 E0.6 footprints - -# People & Body subtotal: 2998 -# People & Body subtotal: 508 w/o modifiers - -# group: Component - -# subgroup: skin-tone -1F3FB ; component # 🏻 E1.0 light skin tone -1F3FC ; component # 🏼 E1.0 medium-light skin tone -1F3FD ; component # 🏽 E1.0 medium skin tone -1F3FE ; component # 🏾 E1.0 medium-dark skin tone -1F3FF ; component # 🏿 E1.0 dark skin tone - -# subgroup: hair-style -1F9B0 ; component # 🦰 E11.0 red hair -1F9B1 ; component # 🦱 E11.0 curly hair -1F9B3 ; component # 🦳 E11.0 white hair -1F9B2 ; component # 🦲 E11.0 bald - -# Component subtotal: 9 -# Component subtotal: 4 w/o modifiers - -# group: Animals & Nature - -# subgroup: animal-mammal -1F435 ; fully-qualified # 🐵 E0.6 monkey face -1F412 ; fully-qualified # 🐒 E0.6 monkey -1F98D ; fully-qualified # 🦍 E3.0 gorilla -1F9A7 ; fully-qualified # 🦧 E12.0 orangutan -1F436 ; fully-qualified # 🐶 E0.6 dog face -1F415 ; fully-qualified # 🐕 E0.7 dog -1F9AE ; fully-qualified # 🦮 E12.0 guide dog -1F415 200D 1F9BA ; fully-qualified # 🐕‍🦺 E12.0 service dog -1F429 ; fully-qualified # 🐩 E0.6 poodle -1F43A ; fully-qualified # 🐺 E0.6 wolf -1F98A ; fully-qualified # 🦊 E3.0 fox -1F99D ; fully-qualified # 🦝 E11.0 raccoon -1F431 ; fully-qualified # 🐱 E0.6 cat face -1F408 ; fully-qualified # 🐈 E0.7 cat -1F408 200D 2B1B ; fully-qualified # 🐈‍⬛ E13.0 black cat -1F981 ; fully-qualified # 🦁 E1.0 lion -1F42F ; fully-qualified # 🐯 E0.6 tiger face -1F405 ; fully-qualified # 🐅 E1.0 tiger -1F406 ; fully-qualified # 🐆 E1.0 leopard -1F434 ; fully-qualified # 🐴 E0.6 horse face -1FACE ; fully-qualified # 🫎 E15.0 moose -1FACF ; fully-qualified # 🫏 E15.0 donkey -1F40E ; fully-qualified # 🐎 E0.6 horse -1F984 ; fully-qualified # 🦄 E1.0 unicorn -1F993 ; fully-qualified # 🦓 E5.0 zebra -1F98C ; fully-qualified # 🦌 E3.0 deer -1F9AC ; fully-qualified # 🦬 E13.0 bison -1F42E ; fully-qualified # 🐮 E0.6 cow face -1F402 ; fully-qualified # 🐂 E1.0 ox -1F403 ; fully-qualified # 🐃 E1.0 water buffalo -1F404 ; fully-qualified # 🐄 E1.0 cow -1F437 ; fully-qualified # 🐷 E0.6 pig face -1F416 ; fully-qualified # 🐖 E1.0 pig -1F417 ; fully-qualified # 🐗 E0.6 boar -1F43D ; fully-qualified # 🐽 E0.6 pig nose -1F40F ; fully-qualified # 🐏 E1.0 ram -1F411 ; fully-qualified # 🐑 E0.6 ewe -1F410 ; fully-qualified # 🐐 E1.0 goat -1F42A ; fully-qualified # 🐪 E1.0 camel -1F42B ; fully-qualified # 🐫 E0.6 two-hump camel -1F999 ; fully-qualified # 🦙 E11.0 llama -1F992 ; fully-qualified # 🦒 E5.0 giraffe -1F418 ; fully-qualified # 🐘 E0.6 elephant -1F9A3 ; fully-qualified # 🦣 E13.0 mammoth -1F98F ; fully-qualified # 🦏 E3.0 rhinoceros -1F99B ; fully-qualified # 🦛 E11.0 hippopotamus -1F42D ; fully-qualified # 🐭 E0.6 mouse face -1F401 ; fully-qualified # 🐁 E1.0 mouse -1F400 ; fully-qualified # 🐀 E1.0 rat -1F439 ; fully-qualified # 🐹 E0.6 hamster -1F430 ; fully-qualified # 🐰 E0.6 rabbit face -1F407 ; fully-qualified # 🐇 E1.0 rabbit -1F43F FE0F ; fully-qualified # 🐿️ E0.7 chipmunk -1F43F ; unqualified # 🐿 E0.7 chipmunk -1F9AB ; fully-qualified # 🦫 E13.0 beaver -1F994 ; fully-qualified # 🦔 E5.0 hedgehog -1F987 ; fully-qualified # 🦇 E3.0 bat -1F43B ; fully-qualified # 🐻 E0.6 bear -1F43B 200D 2744 FE0F ; fully-qualified # 🐻‍❄️ E13.0 polar bear -1F43B 200D 2744 ; minimally-qualified # 🐻‍❄ E13.0 polar bear -1F428 ; fully-qualified # 🐨 E0.6 koala -1F43C ; fully-qualified # 🐼 E0.6 panda -1F9A5 ; fully-qualified # 🦥 E12.0 sloth -1F9A6 ; fully-qualified # 🦦 E12.0 otter -1F9A8 ; fully-qualified # 🦨 E12.0 skunk -1F998 ; fully-qualified # 🦘 E11.0 kangaroo -1F9A1 ; fully-qualified # 🦡 E11.0 badger -1F43E ; fully-qualified # 🐾 E0.6 paw prints - -# subgroup: animal-bird -1F983 ; fully-qualified # 🦃 E1.0 turkey -1F414 ; fully-qualified # 🐔 E0.6 chicken -1F413 ; fully-qualified # 🐓 E1.0 rooster -1F423 ; fully-qualified # 🐣 E0.6 hatching chick -1F424 ; fully-qualified # 🐤 E0.6 baby chick -1F425 ; fully-qualified # 🐥 E0.6 front-facing baby chick -1F426 ; fully-qualified # 🐦 E0.6 bird -1F427 ; fully-qualified # 🐧 E0.6 penguin -1F54A FE0F ; fully-qualified # 🕊️ E0.7 dove -1F54A ; unqualified # 🕊 E0.7 dove -1F985 ; fully-qualified # 🦅 E3.0 eagle -1F986 ; fully-qualified # 🦆 E3.0 duck -1F9A2 ; fully-qualified # 🦢 E11.0 swan -1F989 ; fully-qualified # 🦉 E3.0 owl -1F9A4 ; fully-qualified # 🦤 E13.0 dodo -1FAB6 ; fully-qualified # 🪶 E13.0 feather -1F9A9 ; fully-qualified # 🦩 E12.0 flamingo -1F99A ; fully-qualified # 🦚 E11.0 peacock -1F99C ; fully-qualified # 🦜 E11.0 parrot -1FABD ; fully-qualified # 🪽 E15.0 wing -1F426 200D 2B1B ; fully-qualified # 🐦‍⬛ E15.0 black bird -1FABF ; fully-qualified # 🪿 E15.0 goose - -# subgroup: animal-amphibian -1F438 ; fully-qualified # 🐸 E0.6 frog - -# subgroup: animal-reptile -1F40A ; fully-qualified # 🐊 E1.0 crocodile -1F422 ; fully-qualified # 🐢 E0.6 turtle -1F98E ; fully-qualified # 🦎 E3.0 lizard -1F40D ; fully-qualified # 🐍 E0.6 snake -1F432 ; fully-qualified # 🐲 E0.6 dragon face -1F409 ; fully-qualified # 🐉 E1.0 dragon -1F995 ; fully-qualified # 🦕 E5.0 sauropod -1F996 ; fully-qualified # 🦖 E5.0 T-Rex - -# subgroup: animal-marine -1F433 ; fully-qualified # 🐳 E0.6 spouting whale -1F40B ; fully-qualified # 🐋 E1.0 whale -1F42C ; fully-qualified # 🐬 E0.6 dolphin -1F9AD ; fully-qualified # 🦭 E13.0 seal -1F41F ; fully-qualified # 🐟 E0.6 fish -1F420 ; fully-qualified # 🐠 E0.6 tropical fish -1F421 ; fully-qualified # 🐡 E0.6 blowfish -1F988 ; fully-qualified # 🦈 E3.0 shark -1F419 ; fully-qualified # 🐙 E0.6 octopus -1F41A ; fully-qualified # 🐚 E0.6 spiral shell -1FAB8 ; fully-qualified # 🪸 E14.0 coral -1FABC ; fully-qualified # 🪼 E15.0 jellyfish - -# subgroup: animal-bug -1F40C ; fully-qualified # 🐌 E0.6 snail -1F98B ; fully-qualified # 🦋 E3.0 butterfly -1F41B ; fully-qualified # 🐛 E0.6 bug -1F41C ; fully-qualified # 🐜 E0.6 ant -1F41D ; fully-qualified # 🐝 E0.6 honeybee -1FAB2 ; fully-qualified # 🪲 E13.0 beetle -1F41E ; fully-qualified # 🐞 E0.6 lady beetle -1F997 ; fully-qualified # 🦗 E5.0 cricket -1FAB3 ; fully-qualified # 🪳 E13.0 cockroach -1F577 FE0F ; fully-qualified # 🕷️ E0.7 spider -1F577 ; unqualified # 🕷 E0.7 spider -1F578 FE0F ; fully-qualified # 🕸️ E0.7 spider web -1F578 ; unqualified # 🕸 E0.7 spider web -1F982 ; fully-qualified # 🦂 E1.0 scorpion -1F99F ; fully-qualified # 🦟 E11.0 mosquito -1FAB0 ; fully-qualified # 🪰 E13.0 fly -1FAB1 ; fully-qualified # 🪱 E13.0 worm -1F9A0 ; fully-qualified # 🦠 E11.0 microbe - -# subgroup: plant-flower -1F490 ; fully-qualified # 💐 E0.6 bouquet -1F338 ; fully-qualified # 🌸 E0.6 cherry blossom -1F4AE ; fully-qualified # 💮 E0.6 white flower -1FAB7 ; fully-qualified # 🪷 E14.0 lotus -1F3F5 FE0F ; fully-qualified # 🏵️ E0.7 rosette -1F3F5 ; unqualified # 🏵 E0.7 rosette -1F339 ; fully-qualified # 🌹 E0.6 rose -1F940 ; fully-qualified # 🥀 E3.0 wilted flower -1F33A ; fully-qualified # 🌺 E0.6 hibiscus -1F33B ; fully-qualified # 🌻 E0.6 sunflower -1F33C ; fully-qualified # 🌼 E0.6 blossom -1F337 ; fully-qualified # 🌷 E0.6 tulip -1FABB ; fully-qualified # 🪻 E15.0 hyacinth - -# subgroup: plant-other -1F331 ; fully-qualified # 🌱 E0.6 seedling -1FAB4 ; fully-qualified # 🪴 E13.0 potted plant -1F332 ; fully-qualified # 🌲 E1.0 evergreen tree -1F333 ; fully-qualified # 🌳 E1.0 deciduous tree -1F334 ; fully-qualified # 🌴 E0.6 palm tree -1F335 ; fully-qualified # 🌵 E0.6 cactus -1F33E ; fully-qualified # 🌾 E0.6 sheaf of rice -1F33F ; fully-qualified # 🌿 E0.6 herb -2618 FE0F ; fully-qualified # ☘️ E1.0 shamrock -2618 ; unqualified # ☘ E1.0 shamrock -1F340 ; fully-qualified # 🍀 E0.6 four leaf clover -1F341 ; fully-qualified # 🍁 E0.6 maple leaf -1F342 ; fully-qualified # 🍂 E0.6 fallen leaf -1F343 ; fully-qualified # 🍃 E0.6 leaf fluttering in wind -1FAB9 ; fully-qualified # 🪹 E14.0 empty nest -1FABA ; fully-qualified # 🪺 E14.0 nest with eggs -1F344 ; fully-qualified # 🍄 E0.6 mushroom - -# Animals & Nature subtotal: 159 -# Animals & Nature subtotal: 159 w/o modifiers - -# group: Food & Drink - -# subgroup: food-fruit -1F347 ; fully-qualified # 🍇 E0.6 grapes -1F348 ; fully-qualified # 🍈 E0.6 melon -1F349 ; fully-qualified # 🍉 E0.6 watermelon -1F34A ; fully-qualified # 🍊 E0.6 tangerine -1F34B ; fully-qualified # 🍋 E1.0 lemon -1F34C ; fully-qualified # 🍌 E0.6 banana -1F34D ; fully-qualified # 🍍 E0.6 pineapple -1F96D ; fully-qualified # 🥭 E11.0 mango -1F34E ; fully-qualified # 🍎 E0.6 red apple -1F34F ; fully-qualified # 🍏 E0.6 green apple -1F350 ; fully-qualified # 🍐 E1.0 pear -1F351 ; fully-qualified # 🍑 E0.6 peach -1F352 ; fully-qualified # 🍒 E0.6 cherries -1F353 ; fully-qualified # 🍓 E0.6 strawberry -1FAD0 ; fully-qualified # 🫐 E13.0 blueberries -1F95D ; fully-qualified # 🥝 E3.0 kiwi fruit -1F345 ; fully-qualified # 🍅 E0.6 tomato -1FAD2 ; fully-qualified # 🫒 E13.0 olive -1F965 ; fully-qualified # 🥥 E5.0 coconut - -# subgroup: food-vegetable -1F951 ; fully-qualified # 🥑 E3.0 avocado -1F346 ; fully-qualified # 🍆 E0.6 eggplant -1F954 ; fully-qualified # 🥔 E3.0 potato -1F955 ; fully-qualified # 🥕 E3.0 carrot -1F33D ; fully-qualified # 🌽 E0.6 ear of corn -1F336 FE0F ; fully-qualified # 🌶️ E0.7 hot pepper -1F336 ; unqualified # 🌶 E0.7 hot pepper -1FAD1 ; fully-qualified # 🫑 E13.0 bell pepper -1F952 ; fully-qualified # 🥒 E3.0 cucumber -1F96C ; fully-qualified # 🥬 E11.0 leafy green -1F966 ; fully-qualified # 🥦 E5.0 broccoli -1F9C4 ; fully-qualified # 🧄 E12.0 garlic -1F9C5 ; fully-qualified # 🧅 E12.0 onion -1F95C ; fully-qualified # 🥜 E3.0 peanuts -1FAD8 ; fully-qualified # 🫘 E14.0 beans -1F330 ; fully-qualified # 🌰 E0.6 chestnut -1FADA ; fully-qualified # 🫚 E15.0 ginger root -1FADB ; fully-qualified # 🫛 E15.0 pea pod - -# subgroup: food-prepared -1F35E ; fully-qualified # 🍞 E0.6 bread -1F950 ; fully-qualified # 🥐 E3.0 croissant -1F956 ; fully-qualified # 🥖 E3.0 baguette bread -1FAD3 ; fully-qualified # 🫓 E13.0 flatbread -1F968 ; fully-qualified # 🥨 E5.0 pretzel -1F96F ; fully-qualified # 🥯 E11.0 bagel -1F95E ; fully-qualified # 🥞 E3.0 pancakes -1F9C7 ; fully-qualified # 🧇 E12.0 waffle -1F9C0 ; fully-qualified # 🧀 E1.0 cheese wedge -1F356 ; fully-qualified # 🍖 E0.6 meat on bone -1F357 ; fully-qualified # 🍗 E0.6 poultry leg -1F969 ; fully-qualified # 🥩 E5.0 cut of meat -1F953 ; fully-qualified # 🥓 E3.0 bacon -1F354 ; fully-qualified # 🍔 E0.6 hamburger -1F35F ; fully-qualified # 🍟 E0.6 french fries -1F355 ; fully-qualified # 🍕 E0.6 pizza -1F32D ; fully-qualified # 🌭 E1.0 hot dog -1F96A ; fully-qualified # 🥪 E5.0 sandwich -1F32E ; fully-qualified # 🌮 E1.0 taco -1F32F ; fully-qualified # 🌯 E1.0 burrito -1FAD4 ; fully-qualified # 🫔 E13.0 tamale -1F959 ; fully-qualified # 🥙 E3.0 stuffed flatbread -1F9C6 ; fully-qualified # 🧆 E12.0 falafel -1F95A ; fully-qualified # 🥚 E3.0 egg -1F373 ; fully-qualified # 🍳 E0.6 cooking -1F958 ; fully-qualified # 🥘 E3.0 shallow pan of food -1F372 ; fully-qualified # 🍲 E0.6 pot of food -1FAD5 ; fully-qualified # 🫕 E13.0 fondue -1F963 ; fully-qualified # 🥣 E5.0 bowl with spoon -1F957 ; fully-qualified # 🥗 E3.0 green salad -1F37F ; fully-qualified # 🍿 E1.0 popcorn -1F9C8 ; fully-qualified # 🧈 E12.0 butter -1F9C2 ; fully-qualified # 🧂 E11.0 salt -1F96B ; fully-qualified # 🥫 E5.0 canned food - -# subgroup: food-asian -1F371 ; fully-qualified # 🍱 E0.6 bento box -1F358 ; fully-qualified # 🍘 E0.6 rice cracker -1F359 ; fully-qualified # 🍙 E0.6 rice ball -1F35A ; fully-qualified # 🍚 E0.6 cooked rice -1F35B ; fully-qualified # 🍛 E0.6 curry rice -1F35C ; fully-qualified # 🍜 E0.6 steaming bowl -1F35D ; fully-qualified # 🍝 E0.6 spaghetti -1F360 ; fully-qualified # 🍠 E0.6 roasted sweet potato -1F362 ; fully-qualified # 🍢 E0.6 oden -1F363 ; fully-qualified # 🍣 E0.6 sushi -1F364 ; fully-qualified # 🍤 E0.6 fried shrimp -1F365 ; fully-qualified # 🍥 E0.6 fish cake with swirl -1F96E ; fully-qualified # 🥮 E11.0 moon cake -1F361 ; fully-qualified # 🍡 E0.6 dango -1F95F ; fully-qualified # 🥟 E5.0 dumpling -1F960 ; fully-qualified # 🥠 E5.0 fortune cookie -1F961 ; fully-qualified # 🥡 E5.0 takeout box - -# subgroup: food-marine -1F980 ; fully-qualified # 🦀 E1.0 crab -1F99E ; fully-qualified # 🦞 E11.0 lobster -1F990 ; fully-qualified # 🦐 E3.0 shrimp -1F991 ; fully-qualified # 🦑 E3.0 squid -1F9AA ; fully-qualified # 🦪 E12.0 oyster - -# subgroup: food-sweet -1F366 ; fully-qualified # 🍦 E0.6 soft ice cream -1F367 ; fully-qualified # 🍧 E0.6 shaved ice -1F368 ; fully-qualified # 🍨 E0.6 ice cream -1F369 ; fully-qualified # 🍩 E0.6 doughnut -1F36A ; fully-qualified # 🍪 E0.6 cookie -1F382 ; fully-qualified # 🎂 E0.6 birthday cake -1F370 ; fully-qualified # 🍰 E0.6 shortcake -1F9C1 ; fully-qualified # 🧁 E11.0 cupcake -1F967 ; fully-qualified # 🥧 E5.0 pie -1F36B ; fully-qualified # 🍫 E0.6 chocolate bar -1F36C ; fully-qualified # 🍬 E0.6 candy -1F36D ; fully-qualified # 🍭 E0.6 lollipop -1F36E ; fully-qualified # 🍮 E0.6 custard -1F36F ; fully-qualified # 🍯 E0.6 honey pot - -# subgroup: drink -1F37C ; fully-qualified # 🍼 E1.0 baby bottle -1F95B ; fully-qualified # 🥛 E3.0 glass of milk -2615 ; fully-qualified # ☕ E0.6 hot beverage -1FAD6 ; fully-qualified # 🫖 E13.0 teapot -1F375 ; fully-qualified # 🍵 E0.6 teacup without handle -1F376 ; fully-qualified # 🍶 E0.6 sake -1F37E ; fully-qualified # 🍾 E1.0 bottle with popping cork -1F377 ; fully-qualified # 🍷 E0.6 wine glass -1F378 ; fully-qualified # 🍸 E0.6 cocktail glass -1F379 ; fully-qualified # 🍹 E0.6 tropical drink -1F37A ; fully-qualified # 🍺 E0.6 beer mug -1F37B ; fully-qualified # 🍻 E0.6 clinking beer mugs -1F942 ; fully-qualified # 🥂 E3.0 clinking glasses -1F943 ; fully-qualified # 🥃 E3.0 tumbler glass -1FAD7 ; fully-qualified # 🫗 E14.0 pouring liquid -1F964 ; fully-qualified # 🥤 E5.0 cup with straw -1F9CB ; fully-qualified # 🧋 E13.0 bubble tea -1F9C3 ; fully-qualified # 🧃 E12.0 beverage box -1F9C9 ; fully-qualified # 🧉 E12.0 mate -1F9CA ; fully-qualified # 🧊 E12.0 ice - -# subgroup: dishware -1F962 ; fully-qualified # 🥢 E5.0 chopsticks -1F37D FE0F ; fully-qualified # 🍽️ E0.7 fork and knife with plate -1F37D ; unqualified # 🍽 E0.7 fork and knife with plate -1F374 ; fully-qualified # 🍴 E0.6 fork and knife -1F944 ; fully-qualified # 🥄 E3.0 spoon -1F52A ; fully-qualified # 🔪 E0.6 kitchen knife -1FAD9 ; fully-qualified # 🫙 E14.0 jar -1F3FA ; fully-qualified # 🏺 E1.0 amphora - -# Food & Drink subtotal: 135 -# Food & Drink subtotal: 135 w/o modifiers - -# group: Travel & Places - -# subgroup: place-map -1F30D ; fully-qualified # 🌍 E0.7 globe showing Europe-Africa -1F30E ; fully-qualified # 🌎 E0.7 globe showing Americas -1F30F ; fully-qualified # 🌏 E0.6 globe showing Asia-Australia -1F310 ; fully-qualified # 🌐 E1.0 globe with meridians -1F5FA FE0F ; fully-qualified # 🗺️ E0.7 world map -1F5FA ; unqualified # 🗺 E0.7 world map -1F5FE ; fully-qualified # 🗾 E0.6 map of Japan -1F9ED ; fully-qualified # 🧭 E11.0 compass - -# subgroup: place-geographic -1F3D4 FE0F ; fully-qualified # 🏔️ E0.7 snow-capped mountain -1F3D4 ; unqualified # 🏔 E0.7 snow-capped mountain -26F0 FE0F ; fully-qualified # ⛰️ E0.7 mountain -26F0 ; unqualified # ⛰ E0.7 mountain -1F30B ; fully-qualified # 🌋 E0.6 volcano -1F5FB ; fully-qualified # 🗻 E0.6 mount fuji -1F3D5 FE0F ; fully-qualified # 🏕️ E0.7 camping -1F3D5 ; unqualified # 🏕 E0.7 camping -1F3D6 FE0F ; fully-qualified # 🏖️ E0.7 beach with umbrella -1F3D6 ; unqualified # 🏖 E0.7 beach with umbrella -1F3DC FE0F ; fully-qualified # 🏜️ E0.7 desert -1F3DC ; unqualified # 🏜 E0.7 desert -1F3DD FE0F ; fully-qualified # 🏝️ E0.7 desert island -1F3DD ; unqualified # 🏝 E0.7 desert island -1F3DE FE0F ; fully-qualified # 🏞️ E0.7 national park -1F3DE ; unqualified # 🏞 E0.7 national park - -# subgroup: place-building -1F3DF FE0F ; fully-qualified # 🏟️ E0.7 stadium -1F3DF ; unqualified # 🏟 E0.7 stadium -1F3DB FE0F ; fully-qualified # 🏛️ E0.7 classical building -1F3DB ; unqualified # 🏛 E0.7 classical building -1F3D7 FE0F ; fully-qualified # 🏗️ E0.7 building construction -1F3D7 ; unqualified # 🏗 E0.7 building construction -1F9F1 ; fully-qualified # 🧱 E11.0 brick -1FAA8 ; fully-qualified # 🪨 E13.0 rock -1FAB5 ; fully-qualified # 🪵 E13.0 wood -1F6D6 ; fully-qualified # 🛖 E13.0 hut -1F3D8 FE0F ; fully-qualified # 🏘️ E0.7 houses -1F3D8 ; unqualified # 🏘 E0.7 houses -1F3DA FE0F ; fully-qualified # 🏚️ E0.7 derelict house -1F3DA ; unqualified # 🏚 E0.7 derelict house -1F3E0 ; fully-qualified # 🏠 E0.6 house -1F3E1 ; fully-qualified # 🏡 E0.6 house with garden -1F3E2 ; fully-qualified # 🏢 E0.6 office building -1F3E3 ; fully-qualified # 🏣 E0.6 Japanese post office -1F3E4 ; fully-qualified # 🏤 E1.0 post office -1F3E5 ; fully-qualified # 🏥 E0.6 hospital -1F3E6 ; fully-qualified # 🏦 E0.6 bank -1F3E8 ; fully-qualified # 🏨 E0.6 hotel -1F3E9 ; fully-qualified # 🏩 E0.6 love hotel -1F3EA ; fully-qualified # 🏪 E0.6 convenience store -1F3EB ; fully-qualified # 🏫 E0.6 school -1F3EC ; fully-qualified # 🏬 E0.6 department store -1F3ED ; fully-qualified # 🏭 E0.6 factory -1F3EF ; fully-qualified # 🏯 E0.6 Japanese castle -1F3F0 ; fully-qualified # 🏰 E0.6 castle -1F492 ; fully-qualified # 💒 E0.6 wedding -1F5FC ; fully-qualified # 🗼 E0.6 Tokyo tower -1F5FD ; fully-qualified # 🗽 E0.6 Statue of Liberty - -# subgroup: place-religious -26EA ; fully-qualified # ⛪ E0.6 church -1F54C ; fully-qualified # 🕌 E1.0 mosque -1F6D5 ; fully-qualified # 🛕 E12.0 hindu temple -1F54D ; fully-qualified # 🕍 E1.0 synagogue -26E9 FE0F ; fully-qualified # ⛩️ E0.7 shinto shrine -26E9 ; unqualified # ⛩ E0.7 shinto shrine -1F54B ; fully-qualified # 🕋 E1.0 kaaba - -# subgroup: place-other -26F2 ; fully-qualified # ⛲ E0.6 fountain -26FA ; fully-qualified # ⛺ E0.6 tent -1F301 ; fully-qualified # 🌁 E0.6 foggy -1F303 ; fully-qualified # 🌃 E0.6 night with stars -1F3D9 FE0F ; fully-qualified # 🏙️ E0.7 cityscape -1F3D9 ; unqualified # 🏙 E0.7 cityscape -1F304 ; fully-qualified # 🌄 E0.6 sunrise over mountains -1F305 ; fully-qualified # 🌅 E0.6 sunrise -1F306 ; fully-qualified # 🌆 E0.6 cityscape at dusk -1F307 ; fully-qualified # 🌇 E0.6 sunset -1F309 ; fully-qualified # 🌉 E0.6 bridge at night -2668 FE0F ; fully-qualified # ♨️ E0.6 hot springs -2668 ; unqualified # ♨ E0.6 hot springs -1F3A0 ; fully-qualified # 🎠 E0.6 carousel horse -1F6DD ; fully-qualified # 🛝 E14.0 playground slide -1F3A1 ; fully-qualified # 🎡 E0.6 ferris wheel -1F3A2 ; fully-qualified # 🎢 E0.6 roller coaster -1F488 ; fully-qualified # 💈 E0.6 barber pole -1F3AA ; fully-qualified # 🎪 E0.6 circus tent - -# subgroup: transport-ground -1F682 ; fully-qualified # 🚂 E1.0 locomotive -1F683 ; fully-qualified # 🚃 E0.6 railway car -1F684 ; fully-qualified # 🚄 E0.6 high-speed train -1F685 ; fully-qualified # 🚅 E0.6 bullet train -1F686 ; fully-qualified # 🚆 E1.0 train -1F687 ; fully-qualified # 🚇 E0.6 metro -1F688 ; fully-qualified # 🚈 E1.0 light rail -1F689 ; fully-qualified # 🚉 E0.6 station -1F68A ; fully-qualified # 🚊 E1.0 tram -1F69D ; fully-qualified # 🚝 E1.0 monorail -1F69E ; fully-qualified # 🚞 E1.0 mountain railway -1F68B ; fully-qualified # 🚋 E1.0 tram car -1F68C ; fully-qualified # 🚌 E0.6 bus -1F68D ; fully-qualified # 🚍 E0.7 oncoming bus -1F68E ; fully-qualified # 🚎 E1.0 trolleybus -1F690 ; fully-qualified # 🚐 E1.0 minibus -1F691 ; fully-qualified # 🚑 E0.6 ambulance -1F692 ; fully-qualified # 🚒 E0.6 fire engine -1F693 ; fully-qualified # 🚓 E0.6 police car -1F694 ; fully-qualified # 🚔 E0.7 oncoming police car -1F695 ; fully-qualified # 🚕 E0.6 taxi -1F696 ; fully-qualified # 🚖 E1.0 oncoming taxi -1F697 ; fully-qualified # 🚗 E0.6 automobile -1F698 ; fully-qualified # 🚘 E0.7 oncoming automobile -1F699 ; fully-qualified # 🚙 E0.6 sport utility vehicle -1F6FB ; fully-qualified # 🛻 E13.0 pickup truck -1F69A ; fully-qualified # 🚚 E0.6 delivery truck -1F69B ; fully-qualified # 🚛 E1.0 articulated lorry -1F69C ; fully-qualified # 🚜 E1.0 tractor -1F3CE FE0F ; fully-qualified # 🏎️ E0.7 racing car -1F3CE ; unqualified # 🏎 E0.7 racing car -1F3CD FE0F ; fully-qualified # 🏍️ E0.7 motorcycle -1F3CD ; unqualified # 🏍 E0.7 motorcycle -1F6F5 ; fully-qualified # 🛵 E3.0 motor scooter -1F9BD ; fully-qualified # 🦽 E12.0 manual wheelchair -1F9BC ; fully-qualified # 🦼 E12.0 motorized wheelchair -1F6FA ; fully-qualified # 🛺 E12.0 auto rickshaw -1F6B2 ; fully-qualified # 🚲 E0.6 bicycle -1F6F4 ; fully-qualified # 🛴 E3.0 kick scooter -1F6F9 ; fully-qualified # 🛹 E11.0 skateboard -1F6FC ; fully-qualified # 🛼 E13.0 roller skate -1F68F ; fully-qualified # 🚏 E0.6 bus stop -1F6E3 FE0F ; fully-qualified # 🛣️ E0.7 motorway -1F6E3 ; unqualified # 🛣 E0.7 motorway -1F6E4 FE0F ; fully-qualified # 🛤️ E0.7 railway track -1F6E4 ; unqualified # 🛤 E0.7 railway track -1F6E2 FE0F ; fully-qualified # 🛢️ E0.7 oil drum -1F6E2 ; unqualified # 🛢 E0.7 oil drum -26FD ; fully-qualified # ⛽ E0.6 fuel pump -1F6DE ; fully-qualified # 🛞 E14.0 wheel -1F6A8 ; fully-qualified # 🚨 E0.6 police car light -1F6A5 ; fully-qualified # 🚥 E0.6 horizontal traffic light -1F6A6 ; fully-qualified # 🚦 E1.0 vertical traffic light -1F6D1 ; fully-qualified # 🛑 E3.0 stop sign -1F6A7 ; fully-qualified # 🚧 E0.6 construction - -# subgroup: transport-water -2693 ; fully-qualified # ⚓ E0.6 anchor -1F6DF ; fully-qualified # 🛟 E14.0 ring buoy -26F5 ; fully-qualified # ⛵ E0.6 sailboat -1F6F6 ; fully-qualified # 🛶 E3.0 canoe -1F6A4 ; fully-qualified # 🚤 E0.6 speedboat -1F6F3 FE0F ; fully-qualified # 🛳️ E0.7 passenger ship -1F6F3 ; unqualified # 🛳 E0.7 passenger ship -26F4 FE0F ; fully-qualified # ⛴️ E0.7 ferry -26F4 ; unqualified # ⛴ E0.7 ferry -1F6E5 FE0F ; fully-qualified # 🛥️ E0.7 motor boat -1F6E5 ; unqualified # 🛥 E0.7 motor boat -1F6A2 ; fully-qualified # 🚢 E0.6 ship - -# subgroup: transport-air -2708 FE0F ; fully-qualified # ✈️ E0.6 airplane -2708 ; unqualified # ✈ E0.6 airplane -1F6E9 FE0F ; fully-qualified # 🛩️ E0.7 small airplane -1F6E9 ; unqualified # 🛩 E0.7 small airplane -1F6EB ; fully-qualified # 🛫 E1.0 airplane departure -1F6EC ; fully-qualified # 🛬 E1.0 airplane arrival -1FA82 ; fully-qualified # 🪂 E12.0 parachute -1F4BA ; fully-qualified # 💺 E0.6 seat -1F681 ; fully-qualified # 🚁 E1.0 helicopter -1F69F ; fully-qualified # 🚟 E1.0 suspension railway -1F6A0 ; fully-qualified # 🚠 E1.0 mountain cableway -1F6A1 ; fully-qualified # 🚡 E1.0 aerial tramway -1F6F0 FE0F ; fully-qualified # 🛰️ E0.7 satellite -1F6F0 ; unqualified # 🛰 E0.7 satellite -1F680 ; fully-qualified # 🚀 E0.6 rocket -1F6F8 ; fully-qualified # 🛸 E5.0 flying saucer - -# subgroup: hotel -1F6CE FE0F ; fully-qualified # 🛎️ E0.7 bellhop bell -1F6CE ; unqualified # 🛎 E0.7 bellhop bell -1F9F3 ; fully-qualified # 🧳 E11.0 luggage - -# subgroup: time -231B ; fully-qualified # ⌛ E0.6 hourglass done -23F3 ; fully-qualified # ⏳ E0.6 hourglass not done -231A ; fully-qualified # ⌚ E0.6 watch -23F0 ; fully-qualified # ⏰ E0.6 alarm clock -23F1 FE0F ; fully-qualified # ⏱️ E1.0 stopwatch -23F1 ; unqualified # ⏱ E1.0 stopwatch -23F2 FE0F ; fully-qualified # ⏲️ E1.0 timer clock -23F2 ; unqualified # ⏲ E1.0 timer clock -1F570 FE0F ; fully-qualified # 🕰️ E0.7 mantelpiece clock -1F570 ; unqualified # 🕰 E0.7 mantelpiece clock -1F55B ; fully-qualified # 🕛 E0.6 twelve o’clock -1F567 ; fully-qualified # 🕧 E0.7 twelve-thirty -1F550 ; fully-qualified # 🕐 E0.6 one o’clock -1F55C ; fully-qualified # 🕜 E0.7 one-thirty -1F551 ; fully-qualified # 🕑 E0.6 two o’clock -1F55D ; fully-qualified # 🕝 E0.7 two-thirty -1F552 ; fully-qualified # 🕒 E0.6 three o’clock -1F55E ; fully-qualified # 🕞 E0.7 three-thirty -1F553 ; fully-qualified # 🕓 E0.6 four o’clock -1F55F ; fully-qualified # 🕟 E0.7 four-thirty -1F554 ; fully-qualified # 🕔 E0.6 five o’clock -1F560 ; fully-qualified # 🕠 E0.7 five-thirty -1F555 ; fully-qualified # 🕕 E0.6 six o’clock -1F561 ; fully-qualified # 🕡 E0.7 six-thirty -1F556 ; fully-qualified # 🕖 E0.6 seven o’clock -1F562 ; fully-qualified # 🕢 E0.7 seven-thirty -1F557 ; fully-qualified # 🕗 E0.6 eight o’clock -1F563 ; fully-qualified # 🕣 E0.7 eight-thirty -1F558 ; fully-qualified # 🕘 E0.6 nine o’clock -1F564 ; fully-qualified # 🕤 E0.7 nine-thirty -1F559 ; fully-qualified # 🕙 E0.6 ten o’clock -1F565 ; fully-qualified # 🕥 E0.7 ten-thirty -1F55A ; fully-qualified # 🕚 E0.6 eleven o’clock -1F566 ; fully-qualified # 🕦 E0.7 eleven-thirty - -# subgroup: sky & weather -1F311 ; fully-qualified # 🌑 E0.6 new moon -1F312 ; fully-qualified # 🌒 E1.0 waxing crescent moon -1F313 ; fully-qualified # 🌓 E0.6 first quarter moon -1F314 ; fully-qualified # 🌔 E0.6 waxing gibbous moon -1F315 ; fully-qualified # 🌕 E0.6 full moon -1F316 ; fully-qualified # 🌖 E1.0 waning gibbous moon -1F317 ; fully-qualified # 🌗 E1.0 last quarter moon -1F318 ; fully-qualified # 🌘 E1.0 waning crescent moon -1F319 ; fully-qualified # 🌙 E0.6 crescent moon -1F31A ; fully-qualified # 🌚 E1.0 new moon face -1F31B ; fully-qualified # 🌛 E0.6 first quarter moon face -1F31C ; fully-qualified # 🌜 E0.7 last quarter moon face -1F321 FE0F ; fully-qualified # 🌡️ E0.7 thermometer -1F321 ; unqualified # 🌡 E0.7 thermometer -2600 FE0F ; fully-qualified # ☀️ E0.6 sun -2600 ; unqualified # ☀ E0.6 sun -1F31D ; fully-qualified # 🌝 E1.0 full moon face -1F31E ; fully-qualified # 🌞 E1.0 sun with face -1FA90 ; fully-qualified # 🪐 E12.0 ringed planet -2B50 ; fully-qualified # ⭐ E0.6 star -1F31F ; fully-qualified # 🌟 E0.6 glowing star -1F320 ; fully-qualified # 🌠 E0.6 shooting star -1F30C ; fully-qualified # 🌌 E0.6 milky way -2601 FE0F ; fully-qualified # ☁️ E0.6 cloud -2601 ; unqualified # ☁ E0.6 cloud -26C5 ; fully-qualified # ⛅ E0.6 sun behind cloud -26C8 FE0F ; fully-qualified # ⛈️ E0.7 cloud with lightning and rain -26C8 ; unqualified # ⛈ E0.7 cloud with lightning and rain -1F324 FE0F ; fully-qualified # 🌤️ E0.7 sun behind small cloud -1F324 ; unqualified # 🌤 E0.7 sun behind small cloud -1F325 FE0F ; fully-qualified # 🌥️ E0.7 sun behind large cloud -1F325 ; unqualified # 🌥 E0.7 sun behind large cloud -1F326 FE0F ; fully-qualified # 🌦️ E0.7 sun behind rain cloud -1F326 ; unqualified # 🌦 E0.7 sun behind rain cloud -1F327 FE0F ; fully-qualified # 🌧️ E0.7 cloud with rain -1F327 ; unqualified # 🌧 E0.7 cloud with rain -1F328 FE0F ; fully-qualified # 🌨️ E0.7 cloud with snow -1F328 ; unqualified # 🌨 E0.7 cloud with snow -1F329 FE0F ; fully-qualified # 🌩️ E0.7 cloud with lightning -1F329 ; unqualified # 🌩 E0.7 cloud with lightning -1F32A FE0F ; fully-qualified # 🌪️ E0.7 tornado -1F32A ; unqualified # 🌪 E0.7 tornado -1F32B FE0F ; fully-qualified # 🌫️ E0.7 fog -1F32B ; unqualified # 🌫 E0.7 fog -1F32C FE0F ; fully-qualified # 🌬️ E0.7 wind face -1F32C ; unqualified # 🌬 E0.7 wind face -1F300 ; fully-qualified # 🌀 E0.6 cyclone -1F308 ; fully-qualified # 🌈 E0.6 rainbow -1F302 ; fully-qualified # 🌂 E0.6 closed umbrella -2602 FE0F ; fully-qualified # ☂️ E0.7 umbrella -2602 ; unqualified # ☂ E0.7 umbrella -2614 ; fully-qualified # ☔ E0.6 umbrella with rain drops -26F1 FE0F ; fully-qualified # ⛱️ E0.7 umbrella on ground -26F1 ; unqualified # ⛱ E0.7 umbrella on ground -26A1 ; fully-qualified # ⚡ E0.6 high voltage -2744 FE0F ; fully-qualified # ❄️ E0.6 snowflake -2744 ; unqualified # ❄ E0.6 snowflake -2603 FE0F ; fully-qualified # ☃️ E0.7 snowman -2603 ; unqualified # ☃ E0.7 snowman -26C4 ; fully-qualified # ⛄ E0.6 snowman without snow -2604 FE0F ; fully-qualified # ☄️ E1.0 comet -2604 ; unqualified # ☄ E1.0 comet -1F525 ; fully-qualified # 🔥 E0.6 fire -1F4A7 ; fully-qualified # 💧 E0.6 droplet -1F30A ; fully-qualified # 🌊 E0.6 water wave - -# Travel & Places subtotal: 267 -# Travel & Places subtotal: 267 w/o modifiers - -# group: Activities - -# subgroup: event -1F383 ; fully-qualified # 🎃 E0.6 jack-o-lantern -1F384 ; fully-qualified # 🎄 E0.6 Christmas tree -1F386 ; fully-qualified # 🎆 E0.6 fireworks -1F387 ; fully-qualified # 🎇 E0.6 sparkler -1F9E8 ; fully-qualified # 🧨 E11.0 firecracker -2728 ; fully-qualified # ✨ E0.6 sparkles -1F388 ; fully-qualified # 🎈 E0.6 balloon -1F389 ; fully-qualified # 🎉 E0.6 party popper -1F38A ; fully-qualified # 🎊 E0.6 confetti ball -1F38B ; fully-qualified # 🎋 E0.6 tanabata tree -1F38D ; fully-qualified # 🎍 E0.6 pine decoration -1F38E ; fully-qualified # 🎎 E0.6 Japanese dolls -1F38F ; fully-qualified # 🎏 E0.6 carp streamer -1F390 ; fully-qualified # 🎐 E0.6 wind chime -1F391 ; fully-qualified # 🎑 E0.6 moon viewing ceremony -1F9E7 ; fully-qualified # 🧧 E11.0 red envelope -1F380 ; fully-qualified # 🎀 E0.6 ribbon -1F381 ; fully-qualified # 🎁 E0.6 wrapped gift -1F397 FE0F ; fully-qualified # 🎗️ E0.7 reminder ribbon -1F397 ; unqualified # 🎗 E0.7 reminder ribbon -1F39F FE0F ; fully-qualified # 🎟️ E0.7 admission tickets -1F39F ; unqualified # 🎟 E0.7 admission tickets -1F3AB ; fully-qualified # 🎫 E0.6 ticket - -# subgroup: award-medal -1F396 FE0F ; fully-qualified # 🎖️ E0.7 military medal -1F396 ; unqualified # 🎖 E0.7 military medal -1F3C6 ; fully-qualified # 🏆 E0.6 trophy -1F3C5 ; fully-qualified # 🏅 E1.0 sports medal -1F947 ; fully-qualified # 🥇 E3.0 1st place medal -1F948 ; fully-qualified # 🥈 E3.0 2nd place medal -1F949 ; fully-qualified # 🥉 E3.0 3rd place medal - -# subgroup: sport -26BD ; fully-qualified # ⚽ E0.6 soccer ball -26BE ; fully-qualified # ⚾ E0.6 baseball -1F94E ; fully-qualified # 🥎 E11.0 softball -1F3C0 ; fully-qualified # 🏀 E0.6 basketball -1F3D0 ; fully-qualified # 🏐 E1.0 volleyball -1F3C8 ; fully-qualified # 🏈 E0.6 american football -1F3C9 ; fully-qualified # 🏉 E1.0 rugby football -1F3BE ; fully-qualified # 🎾 E0.6 tennis -1F94F ; fully-qualified # 🥏 E11.0 flying disc -1F3B3 ; fully-qualified # 🎳 E0.6 bowling -1F3CF ; fully-qualified # 🏏 E1.0 cricket game -1F3D1 ; fully-qualified # 🏑 E1.0 field hockey -1F3D2 ; fully-qualified # 🏒 E1.0 ice hockey -1F94D ; fully-qualified # 🥍 E11.0 lacrosse -1F3D3 ; fully-qualified # 🏓 E1.0 ping pong -1F3F8 ; fully-qualified # 🏸 E1.0 badminton -1F94A ; fully-qualified # 🥊 E3.0 boxing glove -1F94B ; fully-qualified # 🥋 E3.0 martial arts uniform -1F945 ; fully-qualified # 🥅 E3.0 goal net -26F3 ; fully-qualified # ⛳ E0.6 flag in hole -26F8 FE0F ; fully-qualified # ⛸️ E0.7 ice skate -26F8 ; unqualified # ⛸ E0.7 ice skate -1F3A3 ; fully-qualified # 🎣 E0.6 fishing pole -1F93F ; fully-qualified # 🤿 E12.0 diving mask -1F3BD ; fully-qualified # 🎽 E0.6 running shirt -1F3BF ; fully-qualified # 🎿 E0.6 skis -1F6F7 ; fully-qualified # 🛷 E5.0 sled -1F94C ; fully-qualified # 🥌 E5.0 curling stone - -# subgroup: game -1F3AF ; fully-qualified # 🎯 E0.6 bullseye -1FA80 ; fully-qualified # 🪀 E12.0 yo-yo -1FA81 ; fully-qualified # 🪁 E12.0 kite -1F52B ; fully-qualified # 🔫 E0.6 water pistol -1F3B1 ; fully-qualified # 🎱 E0.6 pool 8 ball -1F52E ; fully-qualified # 🔮 E0.6 crystal ball -1FA84 ; fully-qualified # 🪄 E13.0 magic wand -1F3AE ; fully-qualified # 🎮 E0.6 video game -1F579 FE0F ; fully-qualified # 🕹️ E0.7 joystick -1F579 ; unqualified # 🕹 E0.7 joystick -1F3B0 ; fully-qualified # 🎰 E0.6 slot machine -1F3B2 ; fully-qualified # 🎲 E0.6 game die -1F9E9 ; fully-qualified # 🧩 E11.0 puzzle piece -1F9F8 ; fully-qualified # 🧸 E11.0 teddy bear -1FA85 ; fully-qualified # 🪅 E13.0 piñata -1FAA9 ; fully-qualified # 🪩 E14.0 mirror ball -1FA86 ; fully-qualified # 🪆 E13.0 nesting dolls -2660 FE0F ; fully-qualified # ♠️ E0.6 spade suit -2660 ; unqualified # ♠ E0.6 spade suit -2665 FE0F ; fully-qualified # ♥️ E0.6 heart suit -2665 ; unqualified # ♥ E0.6 heart suit -2666 FE0F ; fully-qualified # ♦️ E0.6 diamond suit -2666 ; unqualified # ♦ E0.6 diamond suit -2663 FE0F ; fully-qualified # ♣️ E0.6 club suit -2663 ; unqualified # ♣ E0.6 club suit -265F FE0F ; fully-qualified # ♟️ E11.0 chess pawn -265F ; unqualified # ♟ E11.0 chess pawn -1F0CF ; fully-qualified # 🃏 E0.6 joker -1F004 ; fully-qualified # 🀄 E0.6 mahjong red dragon -1F3B4 ; fully-qualified # 🎴 E0.6 flower playing cards - -# subgroup: arts & crafts -1F3AD ; fully-qualified # 🎭 E0.6 performing arts -1F5BC FE0F ; fully-qualified # 🖼️ E0.7 framed picture -1F5BC ; unqualified # 🖼 E0.7 framed picture -1F3A8 ; fully-qualified # 🎨 E0.6 artist palette -1F9F5 ; fully-qualified # 🧵 E11.0 thread -1FAA1 ; fully-qualified # 🪡 E13.0 sewing needle -1F9F6 ; fully-qualified # 🧶 E11.0 yarn -1FAA2 ; fully-qualified # 🪢 E13.0 knot - -# Activities subtotal: 96 -# Activities subtotal: 96 w/o modifiers - -# group: Objects - -# subgroup: clothing -1F453 ; fully-qualified # 👓 E0.6 glasses -1F576 FE0F ; fully-qualified # 🕶️ E0.7 sunglasses -1F576 ; unqualified # 🕶 E0.7 sunglasses -1F97D ; fully-qualified # 🥽 E11.0 goggles -1F97C ; fully-qualified # 🥼 E11.0 lab coat -1F9BA ; fully-qualified # 🦺 E12.0 safety vest -1F454 ; fully-qualified # 👔 E0.6 necktie -1F455 ; fully-qualified # 👕 E0.6 t-shirt -1F456 ; fully-qualified # 👖 E0.6 jeans -1F9E3 ; fully-qualified # 🧣 E5.0 scarf -1F9E4 ; fully-qualified # 🧤 E5.0 gloves -1F9E5 ; fully-qualified # 🧥 E5.0 coat -1F9E6 ; fully-qualified # 🧦 E5.0 socks -1F457 ; fully-qualified # 👗 E0.6 dress -1F458 ; fully-qualified # 👘 E0.6 kimono -1F97B ; fully-qualified # 🥻 E12.0 sari -1FA71 ; fully-qualified # 🩱 E12.0 one-piece swimsuit -1FA72 ; fully-qualified # 🩲 E12.0 briefs -1FA73 ; fully-qualified # 🩳 E12.0 shorts -1F459 ; fully-qualified # 👙 E0.6 bikini -1F45A ; fully-qualified # 👚 E0.6 woman’s clothes -1FAAD ; fully-qualified # 🪭 E15.0 folding hand fan -1F45B ; fully-qualified # 👛 E0.6 purse -1F45C ; fully-qualified # 👜 E0.6 handbag -1F45D ; fully-qualified # 👝 E0.6 clutch bag -1F6CD FE0F ; fully-qualified # 🛍️ E0.7 shopping bags -1F6CD ; unqualified # 🛍 E0.7 shopping bags -1F392 ; fully-qualified # 🎒 E0.6 backpack -1FA74 ; fully-qualified # 🩴 E13.0 thong sandal -1F45E ; fully-qualified # 👞 E0.6 man’s shoe -1F45F ; fully-qualified # 👟 E0.6 running shoe -1F97E ; fully-qualified # 🥾 E11.0 hiking boot -1F97F ; fully-qualified # 🥿 E11.0 flat shoe -1F460 ; fully-qualified # 👠 E0.6 high-heeled shoe -1F461 ; fully-qualified # 👡 E0.6 woman’s sandal -1FA70 ; fully-qualified # 🩰 E12.0 ballet shoes -1F462 ; fully-qualified # 👢 E0.6 woman’s boot -1FAAE ; fully-qualified # 🪮 E15.0 hair pick -1F451 ; fully-qualified # 👑 E0.6 crown -1F452 ; fully-qualified # 👒 E0.6 woman’s hat -1F3A9 ; fully-qualified # 🎩 E0.6 top hat -1F393 ; fully-qualified # 🎓 E0.6 graduation cap -1F9E2 ; fully-qualified # 🧢 E5.0 billed cap -1FA96 ; fully-qualified # 🪖 E13.0 military helmet -26D1 FE0F ; fully-qualified # ⛑️ E0.7 rescue worker’s helmet -26D1 ; unqualified # ⛑ E0.7 rescue worker’s helmet -1F4FF ; fully-qualified # 📿 E1.0 prayer beads -1F484 ; fully-qualified # 💄 E0.6 lipstick -1F48D ; fully-qualified # 💍 E0.6 ring -1F48E ; fully-qualified # 💎 E0.6 gem stone - -# subgroup: sound -1F507 ; fully-qualified # 🔇 E1.0 muted speaker -1F508 ; fully-qualified # 🔈 E0.7 speaker low volume -1F509 ; fully-qualified # 🔉 E1.0 speaker medium volume -1F50A ; fully-qualified # 🔊 E0.6 speaker high volume -1F4E2 ; fully-qualified # 📢 E0.6 loudspeaker -1F4E3 ; fully-qualified # 📣 E0.6 megaphone -1F4EF ; fully-qualified # 📯 E1.0 postal horn -1F514 ; fully-qualified # 🔔 E0.6 bell -1F515 ; fully-qualified # 🔕 E1.0 bell with slash - -# subgroup: music -1F3BC ; fully-qualified # 🎼 E0.6 musical score -1F3B5 ; fully-qualified # 🎵 E0.6 musical note -1F3B6 ; fully-qualified # 🎶 E0.6 musical notes -1F399 FE0F ; fully-qualified # 🎙️ E0.7 studio microphone -1F399 ; unqualified # 🎙 E0.7 studio microphone -1F39A FE0F ; fully-qualified # 🎚️ E0.7 level slider -1F39A ; unqualified # 🎚 E0.7 level slider -1F39B FE0F ; fully-qualified # 🎛️ E0.7 control knobs -1F39B ; unqualified # 🎛 E0.7 control knobs -1F3A4 ; fully-qualified # 🎤 E0.6 microphone -1F3A7 ; fully-qualified # 🎧 E0.6 headphone -1F4FB ; fully-qualified # 📻 E0.6 radio - -# subgroup: musical-instrument -1F3B7 ; fully-qualified # 🎷 E0.6 saxophone -1FA97 ; fully-qualified # 🪗 E13.0 accordion -1F3B8 ; fully-qualified # 🎸 E0.6 guitar -1F3B9 ; fully-qualified # 🎹 E0.6 musical keyboard -1F3BA ; fully-qualified # 🎺 E0.6 trumpet -1F3BB ; fully-qualified # 🎻 E0.6 violin -1FA95 ; fully-qualified # 🪕 E12.0 banjo -1F941 ; fully-qualified # 🥁 E3.0 drum -1FA98 ; fully-qualified # 🪘 E13.0 long drum -1FA87 ; fully-qualified # 🪇 E15.0 maracas -1FA88 ; fully-qualified # 🪈 E15.0 flute - -# subgroup: phone -1F4F1 ; fully-qualified # 📱 E0.6 mobile phone -1F4F2 ; fully-qualified # 📲 E0.6 mobile phone with arrow -260E FE0F ; fully-qualified # ☎️ E0.6 telephone -260E ; unqualified # ☎ E0.6 telephone -1F4DE ; fully-qualified # 📞 E0.6 telephone receiver -1F4DF ; fully-qualified # 📟 E0.6 pager -1F4E0 ; fully-qualified # 📠 E0.6 fax machine - -# subgroup: computer -1F50B ; fully-qualified # 🔋 E0.6 battery -1FAAB ; fully-qualified # 🪫 E14.0 low battery -1F50C ; fully-qualified # 🔌 E0.6 electric plug -1F4BB ; fully-qualified # 💻 E0.6 laptop -1F5A5 FE0F ; fully-qualified # 🖥️ E0.7 desktop computer -1F5A5 ; unqualified # 🖥 E0.7 desktop computer -1F5A8 FE0F ; fully-qualified # 🖨️ E0.7 printer -1F5A8 ; unqualified # 🖨 E0.7 printer -2328 FE0F ; fully-qualified # ⌨️ E1.0 keyboard -2328 ; unqualified # ⌨ E1.0 keyboard -1F5B1 FE0F ; fully-qualified # 🖱️ E0.7 computer mouse -1F5B1 ; unqualified # 🖱 E0.7 computer mouse -1F5B2 FE0F ; fully-qualified # 🖲️ E0.7 trackball -1F5B2 ; unqualified # 🖲 E0.7 trackball -1F4BD ; fully-qualified # 💽 E0.6 computer disk -1F4BE ; fully-qualified # 💾 E0.6 floppy disk -1F4BF ; fully-qualified # 💿 E0.6 optical disk -1F4C0 ; fully-qualified # 📀 E0.6 dvd -1F9EE ; fully-qualified # 🧮 E11.0 abacus - -# subgroup: light & video -1F3A5 ; fully-qualified # 🎥 E0.6 movie camera -1F39E FE0F ; fully-qualified # 🎞️ E0.7 film frames -1F39E ; unqualified # 🎞 E0.7 film frames -1F4FD FE0F ; fully-qualified # 📽️ E0.7 film projector -1F4FD ; unqualified # 📽 E0.7 film projector -1F3AC ; fully-qualified # 🎬 E0.6 clapper board -1F4FA ; fully-qualified # 📺 E0.6 television -1F4F7 ; fully-qualified # 📷 E0.6 camera -1F4F8 ; fully-qualified # 📸 E1.0 camera with flash -1F4F9 ; fully-qualified # 📹 E0.6 video camera -1F4FC ; fully-qualified # 📼 E0.6 videocassette -1F50D ; fully-qualified # 🔍 E0.6 magnifying glass tilted left -1F50E ; fully-qualified # 🔎 E0.6 magnifying glass tilted right -1F56F FE0F ; fully-qualified # 🕯️ E0.7 candle -1F56F ; unqualified # 🕯 E0.7 candle -1F4A1 ; fully-qualified # 💡 E0.6 light bulb -1F526 ; fully-qualified # 🔦 E0.6 flashlight -1F3EE ; fully-qualified # 🏮 E0.6 red paper lantern -1FA94 ; fully-qualified # 🪔 E12.0 diya lamp - -# subgroup: book-paper -1F4D4 ; fully-qualified # 📔 E0.6 notebook with decorative cover -1F4D5 ; fully-qualified # 📕 E0.6 closed book -1F4D6 ; fully-qualified # 📖 E0.6 open book -1F4D7 ; fully-qualified # 📗 E0.6 green book -1F4D8 ; fully-qualified # 📘 E0.6 blue book -1F4D9 ; fully-qualified # 📙 E0.6 orange book -1F4DA ; fully-qualified # 📚 E0.6 books -1F4D3 ; fully-qualified # 📓 E0.6 notebook -1F4D2 ; fully-qualified # 📒 E0.6 ledger -1F4C3 ; fully-qualified # 📃 E0.6 page with curl -1F4DC ; fully-qualified # 📜 E0.6 scroll -1F4C4 ; fully-qualified # 📄 E0.6 page facing up -1F4F0 ; fully-qualified # 📰 E0.6 newspaper -1F5DE FE0F ; fully-qualified # 🗞️ E0.7 rolled-up newspaper -1F5DE ; unqualified # 🗞 E0.7 rolled-up newspaper -1F4D1 ; fully-qualified # 📑 E0.6 bookmark tabs -1F516 ; fully-qualified # 🔖 E0.6 bookmark -1F3F7 FE0F ; fully-qualified # 🏷️ E0.7 label -1F3F7 ; unqualified # 🏷 E0.7 label - -# subgroup: money -1F4B0 ; fully-qualified # 💰 E0.6 money bag -1FA99 ; fully-qualified # 🪙 E13.0 coin -1F4B4 ; fully-qualified # 💴 E0.6 yen banknote -1F4B5 ; fully-qualified # 💵 E0.6 dollar banknote -1F4B6 ; fully-qualified # 💶 E1.0 euro banknote -1F4B7 ; fully-qualified # 💷 E1.0 pound banknote -1F4B8 ; fully-qualified # 💸 E0.6 money with wings -1F4B3 ; fully-qualified # 💳 E0.6 credit card -1F9FE ; fully-qualified # 🧾 E11.0 receipt -1F4B9 ; fully-qualified # 💹 E0.6 chart increasing with yen - -# subgroup: mail -2709 FE0F ; fully-qualified # ✉️ E0.6 envelope -2709 ; unqualified # ✉ E0.6 envelope -1F4E7 ; fully-qualified # 📧 E0.6 e-mail -1F4E8 ; fully-qualified # 📨 E0.6 incoming envelope -1F4E9 ; fully-qualified # 📩 E0.6 envelope with arrow -1F4E4 ; fully-qualified # 📤 E0.6 outbox tray -1F4E5 ; fully-qualified # 📥 E0.6 inbox tray -1F4E6 ; fully-qualified # 📦 E0.6 package -1F4EB ; fully-qualified # 📫 E0.6 closed mailbox with raised flag -1F4EA ; fully-qualified # 📪 E0.6 closed mailbox with lowered flag -1F4EC ; fully-qualified # 📬 E0.7 open mailbox with raised flag -1F4ED ; fully-qualified # 📭 E0.7 open mailbox with lowered flag -1F4EE ; fully-qualified # 📮 E0.6 postbox -1F5F3 FE0F ; fully-qualified # 🗳️ E0.7 ballot box with ballot -1F5F3 ; unqualified # 🗳 E0.7 ballot box with ballot - -# subgroup: writing -270F FE0F ; fully-qualified # ✏️ E0.6 pencil -270F ; unqualified # ✏ E0.6 pencil -2712 FE0F ; fully-qualified # ✒️ E0.6 black nib -2712 ; unqualified # ✒ E0.6 black nib -1F58B FE0F ; fully-qualified # 🖋️ E0.7 fountain pen -1F58B ; unqualified # 🖋 E0.7 fountain pen -1F58A FE0F ; fully-qualified # 🖊️ E0.7 pen -1F58A ; unqualified # 🖊 E0.7 pen -1F58C FE0F ; fully-qualified # 🖌️ E0.7 paintbrush -1F58C ; unqualified # 🖌 E0.7 paintbrush -1F58D FE0F ; fully-qualified # 🖍️ E0.7 crayon -1F58D ; unqualified # 🖍 E0.7 crayon -1F4DD ; fully-qualified # 📝 E0.6 memo - -# subgroup: office -1F4BC ; fully-qualified # 💼 E0.6 briefcase -1F4C1 ; fully-qualified # 📁 E0.6 file folder -1F4C2 ; fully-qualified # 📂 E0.6 open file folder -1F5C2 FE0F ; fully-qualified # 🗂️ E0.7 card index dividers -1F5C2 ; unqualified # 🗂 E0.7 card index dividers -1F4C5 ; fully-qualified # 📅 E0.6 calendar -1F4C6 ; fully-qualified # 📆 E0.6 tear-off calendar -1F5D2 FE0F ; fully-qualified # 🗒️ E0.7 spiral notepad -1F5D2 ; unqualified # 🗒 E0.7 spiral notepad -1F5D3 FE0F ; fully-qualified # 🗓️ E0.7 spiral calendar -1F5D3 ; unqualified # 🗓 E0.7 spiral calendar -1F4C7 ; fully-qualified # 📇 E0.6 card index -1F4C8 ; fully-qualified # 📈 E0.6 chart increasing -1F4C9 ; fully-qualified # 📉 E0.6 chart decreasing -1F4CA ; fully-qualified # 📊 E0.6 bar chart -1F4CB ; fully-qualified # 📋 E0.6 clipboard -1F4CC ; fully-qualified # 📌 E0.6 pushpin -1F4CD ; fully-qualified # 📍 E0.6 round pushpin -1F4CE ; fully-qualified # 📎 E0.6 paperclip -1F587 FE0F ; fully-qualified # 🖇️ E0.7 linked paperclips -1F587 ; unqualified # 🖇 E0.7 linked paperclips -1F4CF ; fully-qualified # 📏 E0.6 straight ruler -1F4D0 ; fully-qualified # 📐 E0.6 triangular ruler -2702 FE0F ; fully-qualified # ✂️ E0.6 scissors -2702 ; unqualified # ✂ E0.6 scissors -1F5C3 FE0F ; fully-qualified # 🗃️ E0.7 card file box -1F5C3 ; unqualified # 🗃 E0.7 card file box -1F5C4 FE0F ; fully-qualified # 🗄️ E0.7 file cabinet -1F5C4 ; unqualified # 🗄 E0.7 file cabinet -1F5D1 FE0F ; fully-qualified # 🗑️ E0.7 wastebasket -1F5D1 ; unqualified # 🗑 E0.7 wastebasket - -# subgroup: lock -1F512 ; fully-qualified # 🔒 E0.6 locked -1F513 ; fully-qualified # 🔓 E0.6 unlocked -1F50F ; fully-qualified # 🔏 E0.6 locked with pen -1F510 ; fully-qualified # 🔐 E0.6 locked with key -1F511 ; fully-qualified # 🔑 E0.6 key -1F5DD FE0F ; fully-qualified # 🗝️ E0.7 old key -1F5DD ; unqualified # 🗝 E0.7 old key - -# subgroup: tool -1F528 ; fully-qualified # 🔨 E0.6 hammer -1FA93 ; fully-qualified # 🪓 E12.0 axe -26CF FE0F ; fully-qualified # ⛏️ E0.7 pick -26CF ; unqualified # ⛏ E0.7 pick -2692 FE0F ; fully-qualified # ⚒️ E1.0 hammer and pick -2692 ; unqualified # ⚒ E1.0 hammer and pick -1F6E0 FE0F ; fully-qualified # 🛠️ E0.7 hammer and wrench -1F6E0 ; unqualified # 🛠 E0.7 hammer and wrench -1F5E1 FE0F ; fully-qualified # 🗡️ E0.7 dagger -1F5E1 ; unqualified # 🗡 E0.7 dagger -2694 FE0F ; fully-qualified # ⚔️ E1.0 crossed swords -2694 ; unqualified # ⚔ E1.0 crossed swords -1F4A3 ; fully-qualified # 💣 E0.6 bomb -1FA83 ; fully-qualified # 🪃 E13.0 boomerang -1F3F9 ; fully-qualified # 🏹 E1.0 bow and arrow -1F6E1 FE0F ; fully-qualified # 🛡️ E0.7 shield -1F6E1 ; unqualified # 🛡 E0.7 shield -1FA9A ; fully-qualified # 🪚 E13.0 carpentry saw -1F527 ; fully-qualified # 🔧 E0.6 wrench -1FA9B ; fully-qualified # 🪛 E13.0 screwdriver -1F529 ; fully-qualified # 🔩 E0.6 nut and bolt -2699 FE0F ; fully-qualified # ⚙️ E1.0 gear -2699 ; unqualified # ⚙ E1.0 gear -1F5DC FE0F ; fully-qualified # 🗜️ E0.7 clamp -1F5DC ; unqualified # 🗜 E0.7 clamp -2696 FE0F ; fully-qualified # ⚖️ E1.0 balance scale -2696 ; unqualified # ⚖ E1.0 balance scale -1F9AF ; fully-qualified # 🦯 E12.0 white cane -1F517 ; fully-qualified # 🔗 E0.6 link -26D3 FE0F ; fully-qualified # ⛓️ E0.7 chains -26D3 ; unqualified # ⛓ E0.7 chains -1FA9D ; fully-qualified # 🪝 E13.0 hook -1F9F0 ; fully-qualified # 🧰 E11.0 toolbox -1F9F2 ; fully-qualified # 🧲 E11.0 magnet -1FA9C ; fully-qualified # 🪜 E13.0 ladder - -# subgroup: science -2697 FE0F ; fully-qualified # ⚗️ E1.0 alembic -2697 ; unqualified # ⚗ E1.0 alembic -1F9EA ; fully-qualified # 🧪 E11.0 test tube -1F9EB ; fully-qualified # 🧫 E11.0 petri dish -1F9EC ; fully-qualified # 🧬 E11.0 dna -1F52C ; fully-qualified # 🔬 E1.0 microscope -1F52D ; fully-qualified # 🔭 E1.0 telescope -1F4E1 ; fully-qualified # 📡 E0.6 satellite antenna - -# subgroup: medical -1F489 ; fully-qualified # 💉 E0.6 syringe -1FA78 ; fully-qualified # 🩸 E12.0 drop of blood -1F48A ; fully-qualified # 💊 E0.6 pill -1FA79 ; fully-qualified # 🩹 E12.0 adhesive bandage -1FA7C ; fully-qualified # 🩼 E14.0 crutch -1FA7A ; fully-qualified # 🩺 E12.0 stethoscope -1FA7B ; fully-qualified # 🩻 E14.0 x-ray - -# subgroup: household -1F6AA ; fully-qualified # 🚪 E0.6 door -1F6D7 ; fully-qualified # 🛗 E13.0 elevator -1FA9E ; fully-qualified # 🪞 E13.0 mirror -1FA9F ; fully-qualified # 🪟 E13.0 window -1F6CF FE0F ; fully-qualified # 🛏️ E0.7 bed -1F6CF ; unqualified # 🛏 E0.7 bed -1F6CB FE0F ; fully-qualified # 🛋️ E0.7 couch and lamp -1F6CB ; unqualified # 🛋 E0.7 couch and lamp -1FA91 ; fully-qualified # 🪑 E12.0 chair -1F6BD ; fully-qualified # 🚽 E0.6 toilet -1FAA0 ; fully-qualified # 🪠 E13.0 plunger -1F6BF ; fully-qualified # 🚿 E1.0 shower -1F6C1 ; fully-qualified # 🛁 E1.0 bathtub -1FAA4 ; fully-qualified # 🪤 E13.0 mouse trap -1FA92 ; fully-qualified # 🪒 E12.0 razor -1F9F4 ; fully-qualified # 🧴 E11.0 lotion bottle -1F9F7 ; fully-qualified # 🧷 E11.0 safety pin -1F9F9 ; fully-qualified # 🧹 E11.0 broom -1F9FA ; fully-qualified # 🧺 E11.0 basket -1F9FB ; fully-qualified # 🧻 E11.0 roll of paper -1FAA3 ; fully-qualified # 🪣 E13.0 bucket -1F9FC ; fully-qualified # 🧼 E11.0 soap -1FAE7 ; fully-qualified # 🫧 E14.0 bubbles -1FAA5 ; fully-qualified # 🪥 E13.0 toothbrush -1F9FD ; fully-qualified # 🧽 E11.0 sponge -1F9EF ; fully-qualified # 🧯 E11.0 fire extinguisher -1F6D2 ; fully-qualified # 🛒 E3.0 shopping cart - -# subgroup: other-object -1F6AC ; fully-qualified # 🚬 E0.6 cigarette -26B0 FE0F ; fully-qualified # ⚰️ E1.0 coffin -26B0 ; unqualified # ⚰ E1.0 coffin -1FAA6 ; fully-qualified # 🪦 E13.0 headstone -26B1 FE0F ; fully-qualified # ⚱️ E1.0 funeral urn -26B1 ; unqualified # ⚱ E1.0 funeral urn -1F9FF ; fully-qualified # 🧿 E11.0 nazar amulet -1FAAC ; fully-qualified # 🪬 E14.0 hamsa -1F5FF ; fully-qualified # 🗿 E0.6 moai -1FAA7 ; fully-qualified # 🪧 E13.0 placard -1FAAA ; fully-qualified # 🪪 E14.0 identification card - -# Objects subtotal: 310 -# Objects subtotal: 310 w/o modifiers - -# group: Symbols - -# subgroup: transport-sign -1F3E7 ; fully-qualified # 🏧 E0.6 ATM sign -1F6AE ; fully-qualified # 🚮 E1.0 litter in bin sign -1F6B0 ; fully-qualified # 🚰 E1.0 potable water -267F ; fully-qualified # ♿ E0.6 wheelchair symbol -1F6B9 ; fully-qualified # 🚹 E0.6 men’s room -1F6BA ; fully-qualified # 🚺 E0.6 women’s room -1F6BB ; fully-qualified # 🚻 E0.6 restroom -1F6BC ; fully-qualified # 🚼 E0.6 baby symbol -1F6BE ; fully-qualified # 🚾 E0.6 water closet -1F6C2 ; fully-qualified # 🛂 E1.0 passport control -1F6C3 ; fully-qualified # 🛃 E1.0 customs -1F6C4 ; fully-qualified # 🛄 E1.0 baggage claim -1F6C5 ; fully-qualified # 🛅 E1.0 left luggage - -# subgroup: warning -26A0 FE0F ; fully-qualified # ⚠️ E0.6 warning -26A0 ; unqualified # ⚠ E0.6 warning -1F6B8 ; fully-qualified # 🚸 E1.0 children crossing -26D4 ; fully-qualified # ⛔ E0.6 no entry -1F6AB ; fully-qualified # 🚫 E0.6 prohibited -1F6B3 ; fully-qualified # 🚳 E1.0 no bicycles -1F6AD ; fully-qualified # 🚭 E0.6 no smoking -1F6AF ; fully-qualified # 🚯 E1.0 no littering -1F6B1 ; fully-qualified # 🚱 E1.0 non-potable water -1F6B7 ; fully-qualified # 🚷 E1.0 no pedestrians -1F4F5 ; fully-qualified # 📵 E1.0 no mobile phones -1F51E ; fully-qualified # 🔞 E0.6 no one under eighteen -2622 FE0F ; fully-qualified # ☢️ E1.0 radioactive -2622 ; unqualified # ☢ E1.0 radioactive -2623 FE0F ; fully-qualified # ☣️ E1.0 biohazard -2623 ; unqualified # ☣ E1.0 biohazard - -# subgroup: arrow -2B06 FE0F ; fully-qualified # ⬆️ E0.6 up arrow -2B06 ; unqualified # ⬆ E0.6 up arrow -2197 FE0F ; fully-qualified # ↗️ E0.6 up-right arrow -2197 ; unqualified # ↗ E0.6 up-right arrow -27A1 FE0F ; fully-qualified # ➡️ E0.6 right arrow -27A1 ; unqualified # ➡ E0.6 right arrow -2198 FE0F ; fully-qualified # ↘️ E0.6 down-right arrow -2198 ; unqualified # ↘ E0.6 down-right arrow -2B07 FE0F ; fully-qualified # ⬇️ E0.6 down arrow -2B07 ; unqualified # ⬇ E0.6 down arrow -2199 FE0F ; fully-qualified # ↙️ E0.6 down-left arrow -2199 ; unqualified # ↙ E0.6 down-left arrow -2B05 FE0F ; fully-qualified # ⬅️ E0.6 left arrow -2B05 ; unqualified # ⬅ E0.6 left arrow -2196 FE0F ; fully-qualified # ↖️ E0.6 up-left arrow -2196 ; unqualified # ↖ E0.6 up-left arrow -2195 FE0F ; fully-qualified # ↕️ E0.6 up-down arrow -2195 ; unqualified # ↕ E0.6 up-down arrow -2194 FE0F ; fully-qualified # ↔️ E0.6 left-right arrow -2194 ; unqualified # ↔ E0.6 left-right arrow -21A9 FE0F ; fully-qualified # ↩️ E0.6 right arrow curving left -21A9 ; unqualified # ↩ E0.6 right arrow curving left -21AA FE0F ; fully-qualified # ↪️ E0.6 left arrow curving right -21AA ; unqualified # ↪ E0.6 left arrow curving right -2934 FE0F ; fully-qualified # ⤴️ E0.6 right arrow curving up -2934 ; unqualified # ⤴ E0.6 right arrow curving up -2935 FE0F ; fully-qualified # ⤵️ E0.6 right arrow curving down -2935 ; unqualified # ⤵ E0.6 right arrow curving down -1F503 ; fully-qualified # 🔃 E0.6 clockwise vertical arrows -1F504 ; fully-qualified # 🔄 E1.0 counterclockwise arrows button -1F519 ; fully-qualified # 🔙 E0.6 BACK arrow -1F51A ; fully-qualified # 🔚 E0.6 END arrow -1F51B ; fully-qualified # 🔛 E0.6 ON! arrow -1F51C ; fully-qualified # 🔜 E0.6 SOON arrow -1F51D ; fully-qualified # 🔝 E0.6 TOP arrow - -# subgroup: religion -1F6D0 ; fully-qualified # 🛐 E1.0 place of worship -269B FE0F ; fully-qualified # ⚛️ E1.0 atom symbol -269B ; unqualified # ⚛ E1.0 atom symbol -1F549 FE0F ; fully-qualified # 🕉️ E0.7 om -1F549 ; unqualified # 🕉 E0.7 om -2721 FE0F ; fully-qualified # ✡️ E0.7 star of David -2721 ; unqualified # ✡ E0.7 star of David -2638 FE0F ; fully-qualified # ☸️ E0.7 wheel of dharma -2638 ; unqualified # ☸ E0.7 wheel of dharma -262F FE0F ; fully-qualified # ☯️ E0.7 yin yang -262F ; unqualified # ☯ E0.7 yin yang -271D FE0F ; fully-qualified # ✝️ E0.7 latin cross -271D ; unqualified # ✝ E0.7 latin cross -2626 FE0F ; fully-qualified # ☦️ E1.0 orthodox cross -2626 ; unqualified # ☦ E1.0 orthodox cross -262A FE0F ; fully-qualified # ☪️ E0.7 star and crescent -262A ; unqualified # ☪ E0.7 star and crescent -262E FE0F ; fully-qualified # ☮️ E1.0 peace symbol -262E ; unqualified # ☮ E1.0 peace symbol -1F54E ; fully-qualified # 🕎 E1.0 menorah -1F52F ; fully-qualified # 🔯 E0.6 dotted six-pointed star -1FAAF ; fully-qualified # 🪯 E15.0 khanda - -# subgroup: zodiac -2648 ; fully-qualified # ♈ E0.6 Aries -2649 ; fully-qualified # ♉ E0.6 Taurus -264A ; fully-qualified # ♊ E0.6 Gemini -264B ; fully-qualified # ♋ E0.6 Cancer -264C ; fully-qualified # ♌ E0.6 Leo -264D ; fully-qualified # ♍ E0.6 Virgo -264E ; fully-qualified # ♎ E0.6 Libra -264F ; fully-qualified # ♏ E0.6 Scorpio -2650 ; fully-qualified # ♐ E0.6 Sagittarius -2651 ; fully-qualified # ♑ E0.6 Capricorn -2652 ; fully-qualified # ♒ E0.6 Aquarius -2653 ; fully-qualified # ♓ E0.6 Pisces -26CE ; fully-qualified # ⛎ E0.6 Ophiuchus - -# subgroup: av-symbol -1F500 ; fully-qualified # 🔀 E1.0 shuffle tracks button -1F501 ; fully-qualified # 🔁 E1.0 repeat button -1F502 ; fully-qualified # 🔂 E1.0 repeat single button -25B6 FE0F ; fully-qualified # ▶️ E0.6 play button -25B6 ; unqualified # ▶ E0.6 play button -23E9 ; fully-qualified # ⏩ E0.6 fast-forward button -23ED FE0F ; fully-qualified # ⏭️ E0.7 next track button -23ED ; unqualified # ⏭ E0.7 next track button -23EF FE0F ; fully-qualified # ⏯️ E1.0 play or pause button -23EF ; unqualified # ⏯ E1.0 play or pause button -25C0 FE0F ; fully-qualified # ◀️ E0.6 reverse button -25C0 ; unqualified # ◀ E0.6 reverse button -23EA ; fully-qualified # ⏪ E0.6 fast reverse button -23EE FE0F ; fully-qualified # ⏮️ E0.7 last track button -23EE ; unqualified # ⏮ E0.7 last track button -1F53C ; fully-qualified # 🔼 E0.6 upwards button -23EB ; fully-qualified # ⏫ E0.6 fast up button -1F53D ; fully-qualified # 🔽 E0.6 downwards button -23EC ; fully-qualified # ⏬ E0.6 fast down button -23F8 FE0F ; fully-qualified # ⏸️ E0.7 pause button -23F8 ; unqualified # ⏸ E0.7 pause button -23F9 FE0F ; fully-qualified # ⏹️ E0.7 stop button -23F9 ; unqualified # ⏹ E0.7 stop button -23FA FE0F ; fully-qualified # ⏺️ E0.7 record button -23FA ; unqualified # ⏺ E0.7 record button -23CF FE0F ; fully-qualified # ⏏️ E1.0 eject button -23CF ; unqualified # ⏏ E1.0 eject button -1F3A6 ; fully-qualified # 🎦 E0.6 cinema -1F505 ; fully-qualified # 🔅 E1.0 dim button -1F506 ; fully-qualified # 🔆 E1.0 bright button -1F4F6 ; fully-qualified # 📶 E0.6 antenna bars -1F6DC ; fully-qualified # 🛜 E15.0 wireless -1F4F3 ; fully-qualified # 📳 E0.6 vibration mode -1F4F4 ; fully-qualified # 📴 E0.6 mobile phone off - -# subgroup: gender -2640 FE0F ; fully-qualified # ♀️ E4.0 female sign -2640 ; unqualified # ♀ E4.0 female sign -2642 FE0F ; fully-qualified # ♂️ E4.0 male sign -2642 ; unqualified # ♂ E4.0 male sign -26A7 FE0F ; fully-qualified # ⚧️ E13.0 transgender symbol -26A7 ; unqualified # ⚧ E13.0 transgender symbol - -# subgroup: math -2716 FE0F ; fully-qualified # ✖️ E0.6 multiply -2716 ; unqualified # ✖ E0.6 multiply -2795 ; fully-qualified # ➕ E0.6 plus -2796 ; fully-qualified # ➖ E0.6 minus -2797 ; fully-qualified # ➗ E0.6 divide -1F7F0 ; fully-qualified # 🟰 E14.0 heavy equals sign -267E FE0F ; fully-qualified # ♾️ E11.0 infinity -267E ; unqualified # ♾ E11.0 infinity - -# subgroup: punctuation -203C FE0F ; fully-qualified # ‼️ E0.6 double exclamation mark -203C ; unqualified # ‼ E0.6 double exclamation mark -2049 FE0F ; fully-qualified # ⁉️ E0.6 exclamation question mark -2049 ; unqualified # ⁉ E0.6 exclamation question mark -2753 ; fully-qualified # ❓ E0.6 red question mark -2754 ; fully-qualified # ❔ E0.6 white question mark -2755 ; fully-qualified # ❕ E0.6 white exclamation mark -2757 ; fully-qualified # ❗ E0.6 red exclamation mark -3030 FE0F ; fully-qualified # 〰️ E0.6 wavy dash -3030 ; unqualified # 〰 E0.6 wavy dash - -# subgroup: currency -1F4B1 ; fully-qualified # 💱 E0.6 currency exchange -1F4B2 ; fully-qualified # 💲 E0.6 heavy dollar sign - -# subgroup: other-symbol -2695 FE0F ; fully-qualified # ⚕️ E4.0 medical symbol -2695 ; unqualified # ⚕ E4.0 medical symbol -267B FE0F ; fully-qualified # ♻️ E0.6 recycling symbol -267B ; unqualified # ♻ E0.6 recycling symbol -269C FE0F ; fully-qualified # ⚜️ E1.0 fleur-de-lis -269C ; unqualified # ⚜ E1.0 fleur-de-lis -1F531 ; fully-qualified # 🔱 E0.6 trident emblem -1F4DB ; fully-qualified # 📛 E0.6 name badge -1F530 ; fully-qualified # 🔰 E0.6 Japanese symbol for beginner -2B55 ; fully-qualified # ⭕ E0.6 hollow red circle -2705 ; fully-qualified # ✅ E0.6 check mark button -2611 FE0F ; fully-qualified # ☑️ E0.6 check box with check -2611 ; unqualified # ☑ E0.6 check box with check -2714 FE0F ; fully-qualified # ✔️ E0.6 check mark -2714 ; unqualified # ✔ E0.6 check mark -274C ; fully-qualified # ❌ E0.6 cross mark -274E ; fully-qualified # ❎ E0.6 cross mark button -27B0 ; fully-qualified # ➰ E0.6 curly loop -27BF ; fully-qualified # ➿ E1.0 double curly loop -303D FE0F ; fully-qualified # 〽️ E0.6 part alternation mark -303D ; unqualified # 〽 E0.6 part alternation mark -2733 FE0F ; fully-qualified # ✳️ E0.6 eight-spoked asterisk -2733 ; unqualified # ✳ E0.6 eight-spoked asterisk -2734 FE0F ; fully-qualified # ✴️ E0.6 eight-pointed star -2734 ; unqualified # ✴ E0.6 eight-pointed star -2747 FE0F ; fully-qualified # ❇️ E0.6 sparkle -2747 ; unqualified # ❇ E0.6 sparkle -00A9 FE0F ; fully-qualified # ©️ E0.6 copyright -00A9 ; unqualified # © E0.6 copyright -00AE FE0F ; fully-qualified # ®️ E0.6 registered -00AE ; unqualified # ® E0.6 registered -2122 FE0F ; fully-qualified # ™️ E0.6 trade mark -2122 ; unqualified # ™ E0.6 trade mark - -# subgroup: keycap -0023 FE0F 20E3 ; fully-qualified # #️⃣ E0.6 keycap: # -0023 20E3 ; unqualified # #⃣ E0.6 keycap: # -002A FE0F 20E3 ; fully-qualified # *️⃣ E2.0 keycap: * -002A 20E3 ; unqualified # *⃣ E2.0 keycap: * -0030 FE0F 20E3 ; fully-qualified # 0️⃣ E0.6 keycap: 0 -0030 20E3 ; unqualified # 0⃣ E0.6 keycap: 0 -0031 FE0F 20E3 ; fully-qualified # 1️⃣ E0.6 keycap: 1 -0031 20E3 ; unqualified # 1⃣ E0.6 keycap: 1 -0032 FE0F 20E3 ; fully-qualified # 2️⃣ E0.6 keycap: 2 -0032 20E3 ; unqualified # 2⃣ E0.6 keycap: 2 -0033 FE0F 20E3 ; fully-qualified # 3️⃣ E0.6 keycap: 3 -0033 20E3 ; unqualified # 3⃣ E0.6 keycap: 3 -0034 FE0F 20E3 ; fully-qualified # 4️⃣ E0.6 keycap: 4 -0034 20E3 ; unqualified # 4⃣ E0.6 keycap: 4 -0035 FE0F 20E3 ; fully-qualified # 5️⃣ E0.6 keycap: 5 -0035 20E3 ; unqualified # 5⃣ E0.6 keycap: 5 -0036 FE0F 20E3 ; fully-qualified # 6️⃣ E0.6 keycap: 6 -0036 20E3 ; unqualified # 6⃣ E0.6 keycap: 6 -0037 FE0F 20E3 ; fully-qualified # 7️⃣ E0.6 keycap: 7 -0037 20E3 ; unqualified # 7⃣ E0.6 keycap: 7 -0038 FE0F 20E3 ; fully-qualified # 8️⃣ E0.6 keycap: 8 -0038 20E3 ; unqualified # 8⃣ E0.6 keycap: 8 -0039 FE0F 20E3 ; fully-qualified # 9️⃣ E0.6 keycap: 9 -0039 20E3 ; unqualified # 9⃣ E0.6 keycap: 9 -1F51F ; fully-qualified # 🔟 E0.6 keycap: 10 - -# subgroup: alphanum -1F520 ; fully-qualified # 🔠 E0.6 input latin uppercase -1F521 ; fully-qualified # 🔡 E0.6 input latin lowercase -1F522 ; fully-qualified # 🔢 E0.6 input numbers -1F523 ; fully-qualified # 🔣 E0.6 input symbols -1F524 ; fully-qualified # 🔤 E0.6 input latin letters -1F170 FE0F ; fully-qualified # 🅰️ E0.6 A button (blood type) -1F170 ; unqualified # 🅰 E0.6 A button (blood type) -1F18E ; fully-qualified # 🆎 E0.6 AB button (blood type) -1F171 FE0F ; fully-qualified # 🅱️ E0.6 B button (blood type) -1F171 ; unqualified # 🅱 E0.6 B button (blood type) -1F191 ; fully-qualified # 🆑 E0.6 CL button -1F192 ; fully-qualified # 🆒 E0.6 COOL button -1F193 ; fully-qualified # 🆓 E0.6 FREE button -2139 FE0F ; fully-qualified # ℹ️ E0.6 information -2139 ; unqualified # ℹ E0.6 information -1F194 ; fully-qualified # 🆔 E0.6 ID button -24C2 FE0F ; fully-qualified # Ⓜ️ E0.6 circled M -24C2 ; unqualified # Ⓜ E0.6 circled M -1F195 ; fully-qualified # 🆕 E0.6 NEW button -1F196 ; fully-qualified # 🆖 E0.6 NG button -1F17E FE0F ; fully-qualified # 🅾️ E0.6 O button (blood type) -1F17E ; unqualified # 🅾 E0.6 O button (blood type) -1F197 ; fully-qualified # 🆗 E0.6 OK button -1F17F FE0F ; fully-qualified # 🅿️ E0.6 P button -1F17F ; unqualified # 🅿 E0.6 P button -1F198 ; fully-qualified # 🆘 E0.6 SOS button -1F199 ; fully-qualified # 🆙 E0.6 UP! button -1F19A ; fully-qualified # 🆚 E0.6 VS button -1F201 ; fully-qualified # 🈁 E0.6 Japanese “here” button -1F202 FE0F ; fully-qualified # 🈂️ E0.6 Japanese “service charge” button -1F202 ; unqualified # 🈂 E0.6 Japanese “service charge” button -1F237 FE0F ; fully-qualified # 🈷️ E0.6 Japanese “monthly amount” button -1F237 ; unqualified # 🈷 E0.6 Japanese “monthly amount” button -1F236 ; fully-qualified # 🈶 E0.6 Japanese “not free of charge” button -1F22F ; fully-qualified # 🈯 E0.6 Japanese “reserved” button -1F250 ; fully-qualified # 🉐 E0.6 Japanese “bargain” button -1F239 ; fully-qualified # 🈹 E0.6 Japanese “discount” button -1F21A ; fully-qualified # 🈚 E0.6 Japanese “free of charge” button -1F232 ; fully-qualified # 🈲 E0.6 Japanese “prohibited” button -1F251 ; fully-qualified # 🉑 E0.6 Japanese “acceptable” button -1F238 ; fully-qualified # 🈸 E0.6 Japanese “application” button -1F234 ; fully-qualified # 🈴 E0.6 Japanese “passing grade” button -1F233 ; fully-qualified # 🈳 E0.6 Japanese “vacancy” button -3297 FE0F ; fully-qualified # ㊗️ E0.6 Japanese “congratulations” button -3297 ; unqualified # ㊗ E0.6 Japanese “congratulations” button -3299 FE0F ; fully-qualified # ㊙️ E0.6 Japanese “secret” button -3299 ; unqualified # ㊙ E0.6 Japanese “secret” button -1F23A ; fully-qualified # 🈺 E0.6 Japanese “open for business” button -1F235 ; fully-qualified # 🈵 E0.6 Japanese “no vacancy” button - -# subgroup: geometric -1F534 ; fully-qualified # 🔴 E0.6 red circle -1F7E0 ; fully-qualified # 🟠 E12.0 orange circle -1F7E1 ; fully-qualified # 🟡 E12.0 yellow circle -1F7E2 ; fully-qualified # 🟢 E12.0 green circle -1F535 ; fully-qualified # 🔵 E0.6 blue circle -1F7E3 ; fully-qualified # 🟣 E12.0 purple circle -1F7E4 ; fully-qualified # 🟤 E12.0 brown circle -26AB ; fully-qualified # ⚫ E0.6 black circle -26AA ; fully-qualified # ⚪ E0.6 white circle -1F7E5 ; fully-qualified # 🟥 E12.0 red square -1F7E7 ; fully-qualified # 🟧 E12.0 orange square -1F7E8 ; fully-qualified # 🟨 E12.0 yellow square -1F7E9 ; fully-qualified # 🟩 E12.0 green square -1F7E6 ; fully-qualified # 🟦 E12.0 blue square -1F7EA ; fully-qualified # 🟪 E12.0 purple square -1F7EB ; fully-qualified # 🟫 E12.0 brown square -2B1B ; fully-qualified # ⬛ E0.6 black large square -2B1C ; fully-qualified # ⬜ E0.6 white large square -25FC FE0F ; fully-qualified # ◼️ E0.6 black medium square -25FC ; unqualified # ◼ E0.6 black medium square -25FB FE0F ; fully-qualified # ◻️ E0.6 white medium square -25FB ; unqualified # ◻ E0.6 white medium square -25FE ; fully-qualified # ◾ E0.6 black medium-small square -25FD ; fully-qualified # ◽ E0.6 white medium-small square -25AA FE0F ; fully-qualified # ▪️ E0.6 black small square -25AA ; unqualified # ▪ E0.6 black small square -25AB FE0F ; fully-qualified # ▫️ E0.6 white small square -25AB ; unqualified # ▫ E0.6 white small square -1F536 ; fully-qualified # 🔶 E0.6 large orange diamond -1F537 ; fully-qualified # 🔷 E0.6 large blue diamond -1F538 ; fully-qualified # 🔸 E0.6 small orange diamond -1F539 ; fully-qualified # 🔹 E0.6 small blue diamond -1F53A ; fully-qualified # 🔺 E0.6 red triangle pointed up -1F53B ; fully-qualified # 🔻 E0.6 red triangle pointed down -1F4A0 ; fully-qualified # 💠 E0.6 diamond with a dot -1F518 ; fully-qualified # 🔘 E0.6 radio button -1F533 ; fully-qualified # 🔳 E0.6 white square button -1F532 ; fully-qualified # 🔲 E0.6 black square button - -# Symbols subtotal: 304 -# Symbols subtotal: 304 w/o modifiers - -# group: Flags - -# subgroup: flag -1F3C1 ; fully-qualified # 🏁 E0.6 chequered flag -1F6A9 ; fully-qualified # 🚩 E0.6 triangular flag -1F38C ; fully-qualified # 🎌 E0.6 crossed flags -1F3F4 ; fully-qualified # 🏴 E1.0 black flag -1F3F3 FE0F ; fully-qualified # 🏳️ E0.7 white flag -1F3F3 ; unqualified # 🏳 E0.7 white flag -1F3F3 FE0F 200D 1F308 ; fully-qualified # 🏳️‍🌈 E4.0 rainbow flag -1F3F3 200D 1F308 ; unqualified # 🏳‍🌈 E4.0 rainbow flag -1F3F3 FE0F 200D 26A7 FE0F ; fully-qualified # 🏳️‍⚧️ E13.0 transgender flag -1F3F3 200D 26A7 FE0F ; unqualified # 🏳‍⚧️ E13.0 transgender flag -1F3F3 FE0F 200D 26A7 ; minimally-qualified # 🏳️‍⚧ E13.0 transgender flag -1F3F3 200D 26A7 ; unqualified # 🏳‍⚧ E13.0 transgender flag -1F3F4 200D 2620 FE0F ; fully-qualified # 🏴‍☠️ E11.0 pirate flag -1F3F4 200D 2620 ; minimally-qualified # 🏴‍☠ E11.0 pirate flag - -# subgroup: country-flag -1F1E6 1F1E8 ; fully-qualified # 🇦🇨 E2.0 flag: Ascension Island -1F1E6 1F1E9 ; fully-qualified # 🇦🇩 E2.0 flag: Andorra -1F1E6 1F1EA ; fully-qualified # 🇦🇪 E2.0 flag: United Arab Emirates -1F1E6 1F1EB ; fully-qualified # 🇦🇫 E2.0 flag: Afghanistan -1F1E6 1F1EC ; fully-qualified # 🇦🇬 E2.0 flag: Antigua & Barbuda -1F1E6 1F1EE ; fully-qualified # 🇦🇮 E2.0 flag: Anguilla -1F1E6 1F1F1 ; fully-qualified # 🇦🇱 E2.0 flag: Albania -1F1E6 1F1F2 ; fully-qualified # 🇦🇲 E2.0 flag: Armenia -1F1E6 1F1F4 ; fully-qualified # 🇦🇴 E2.0 flag: Angola -1F1E6 1F1F6 ; fully-qualified # 🇦🇶 E2.0 flag: Antarctica -1F1E6 1F1F7 ; fully-qualified # 🇦🇷 E2.0 flag: Argentina -1F1E6 1F1F8 ; fully-qualified # 🇦🇸 E2.0 flag: American Samoa -1F1E6 1F1F9 ; fully-qualified # 🇦🇹 E2.0 flag: Austria -1F1E6 1F1FA ; fully-qualified # 🇦🇺 E2.0 flag: Australia -1F1E6 1F1FC ; fully-qualified # 🇦🇼 E2.0 flag: Aruba -1F1E6 1F1FD ; fully-qualified # 🇦🇽 E2.0 flag: Åland Islands -1F1E6 1F1FF ; fully-qualified # 🇦🇿 E2.0 flag: Azerbaijan -1F1E7 1F1E6 ; fully-qualified # 🇧🇦 E2.0 flag: Bosnia & Herzegovina -1F1E7 1F1E7 ; fully-qualified # 🇧🇧 E2.0 flag: Barbados -1F1E7 1F1E9 ; fully-qualified # 🇧🇩 E2.0 flag: Bangladesh -1F1E7 1F1EA ; fully-qualified # 🇧🇪 E2.0 flag: Belgium -1F1E7 1F1EB ; fully-qualified # 🇧🇫 E2.0 flag: Burkina Faso -1F1E7 1F1EC ; fully-qualified # 🇧🇬 E2.0 flag: Bulgaria -1F1E7 1F1ED ; fully-qualified # 🇧🇭 E2.0 flag: Bahrain -1F1E7 1F1EE ; fully-qualified # 🇧🇮 E2.0 flag: Burundi -1F1E7 1F1EF ; fully-qualified # 🇧🇯 E2.0 flag: Benin -1F1E7 1F1F1 ; fully-qualified # 🇧🇱 E2.0 flag: St. Barthélemy -1F1E7 1F1F2 ; fully-qualified # 🇧🇲 E2.0 flag: Bermuda -1F1E7 1F1F3 ; fully-qualified # 🇧🇳 E2.0 flag: Brunei -1F1E7 1F1F4 ; fully-qualified # 🇧🇴 E2.0 flag: Bolivia -1F1E7 1F1F6 ; fully-qualified # 🇧🇶 E2.0 flag: Caribbean Netherlands -1F1E7 1F1F7 ; fully-qualified # 🇧🇷 E2.0 flag: Brazil -1F1E7 1F1F8 ; fully-qualified # 🇧🇸 E2.0 flag: Bahamas -1F1E7 1F1F9 ; fully-qualified # 🇧🇹 E2.0 flag: Bhutan -1F1E7 1F1FB ; fully-qualified # 🇧🇻 E2.0 flag: Bouvet Island -1F1E7 1F1FC ; fully-qualified # 🇧🇼 E2.0 flag: Botswana -1F1E7 1F1FE ; fully-qualified # 🇧🇾 E2.0 flag: Belarus -1F1E7 1F1FF ; fully-qualified # 🇧🇿 E2.0 flag: Belize -1F1E8 1F1E6 ; fully-qualified # 🇨🇦 E2.0 flag: Canada -1F1E8 1F1E8 ; fully-qualified # 🇨🇨 E2.0 flag: Cocos (Keeling) Islands -1F1E8 1F1E9 ; fully-qualified # 🇨🇩 E2.0 flag: Congo - Kinshasa -1F1E8 1F1EB ; fully-qualified # 🇨🇫 E2.0 flag: Central African Republic -1F1E8 1F1EC ; fully-qualified # 🇨🇬 E2.0 flag: Congo - Brazzaville -1F1E8 1F1ED ; fully-qualified # 🇨🇭 E2.0 flag: Switzerland -1F1E8 1F1EE ; fully-qualified # 🇨🇮 E2.0 flag: Côte d’Ivoire -1F1E8 1F1F0 ; fully-qualified # 🇨🇰 E2.0 flag: Cook Islands -1F1E8 1F1F1 ; fully-qualified # 🇨🇱 E2.0 flag: Chile -1F1E8 1F1F2 ; fully-qualified # 🇨🇲 E2.0 flag: Cameroon -1F1E8 1F1F3 ; fully-qualified # 🇨🇳 E0.6 flag: China -1F1E8 1F1F4 ; fully-qualified # 🇨🇴 E2.0 flag: Colombia -1F1E8 1F1F5 ; fully-qualified # 🇨🇵 E2.0 flag: Clipperton Island -1F1E8 1F1F7 ; fully-qualified # 🇨🇷 E2.0 flag: Costa Rica -1F1E8 1F1FA ; fully-qualified # 🇨🇺 E2.0 flag: Cuba -1F1E8 1F1FB ; fully-qualified # 🇨🇻 E2.0 flag: Cape Verde -1F1E8 1F1FC ; fully-qualified # 🇨🇼 E2.0 flag: Curaçao -1F1E8 1F1FD ; fully-qualified # 🇨🇽 E2.0 flag: Christmas Island -1F1E8 1F1FE ; fully-qualified # 🇨🇾 E2.0 flag: Cyprus -1F1E8 1F1FF ; fully-qualified # 🇨🇿 E2.0 flag: Czechia -1F1E9 1F1EA ; fully-qualified # 🇩🇪 E0.6 flag: Germany -1F1E9 1F1EC ; fully-qualified # 🇩🇬 E2.0 flag: Diego Garcia -1F1E9 1F1EF ; fully-qualified # 🇩🇯 E2.0 flag: Djibouti -1F1E9 1F1F0 ; fully-qualified # 🇩🇰 E2.0 flag: Denmark -1F1E9 1F1F2 ; fully-qualified # 🇩🇲 E2.0 flag: Dominica -1F1E9 1F1F4 ; fully-qualified # 🇩🇴 E2.0 flag: Dominican Republic -1F1E9 1F1FF ; fully-qualified # 🇩🇿 E2.0 flag: Algeria -1F1EA 1F1E6 ; fully-qualified # 🇪🇦 E2.0 flag: Ceuta & Melilla -1F1EA 1F1E8 ; fully-qualified # 🇪🇨 E2.0 flag: Ecuador -1F1EA 1F1EA ; fully-qualified # 🇪🇪 E2.0 flag: Estonia -1F1EA 1F1EC ; fully-qualified # 🇪🇬 E2.0 flag: Egypt -1F1EA 1F1ED ; fully-qualified # 🇪🇭 E2.0 flag: Western Sahara -1F1EA 1F1F7 ; fully-qualified # 🇪🇷 E2.0 flag: Eritrea -1F1EA 1F1F8 ; fully-qualified # 🇪🇸 E0.6 flag: Spain -1F1EA 1F1F9 ; fully-qualified # 🇪🇹 E2.0 flag: Ethiopia -1F1EA 1F1FA ; fully-qualified # 🇪🇺 E2.0 flag: European Union -1F1EB 1F1EE ; fully-qualified # 🇫🇮 E2.0 flag: Finland -1F1EB 1F1EF ; fully-qualified # 🇫🇯 E2.0 flag: Fiji -1F1EB 1F1F0 ; fully-qualified # 🇫🇰 E2.0 flag: Falkland Islands -1F1EB 1F1F2 ; fully-qualified # 🇫🇲 E2.0 flag: Micronesia -1F1EB 1F1F4 ; fully-qualified # 🇫🇴 E2.0 flag: Faroe Islands -1F1EB 1F1F7 ; fully-qualified # 🇫🇷 E0.6 flag: France -1F1EC 1F1E6 ; fully-qualified # 🇬🇦 E2.0 flag: Gabon -1F1EC 1F1E7 ; fully-qualified # 🇬🇧 E0.6 flag: United Kingdom -1F1EC 1F1E9 ; fully-qualified # 🇬🇩 E2.0 flag: Grenada -1F1EC 1F1EA ; fully-qualified # 🇬🇪 E2.0 flag: Georgia -1F1EC 1F1EB ; fully-qualified # 🇬🇫 E2.0 flag: French Guiana -1F1EC 1F1EC ; fully-qualified # 🇬🇬 E2.0 flag: Guernsey -1F1EC 1F1ED ; fully-qualified # 🇬🇭 E2.0 flag: Ghana -1F1EC 1F1EE ; fully-qualified # 🇬🇮 E2.0 flag: Gibraltar -1F1EC 1F1F1 ; fully-qualified # 🇬🇱 E2.0 flag: Greenland -1F1EC 1F1F2 ; fully-qualified # 🇬🇲 E2.0 flag: Gambia -1F1EC 1F1F3 ; fully-qualified # 🇬🇳 E2.0 flag: Guinea -1F1EC 1F1F5 ; fully-qualified # 🇬🇵 E2.0 flag: Guadeloupe -1F1EC 1F1F6 ; fully-qualified # 🇬🇶 E2.0 flag: Equatorial Guinea -1F1EC 1F1F7 ; fully-qualified # 🇬🇷 E2.0 flag: Greece -1F1EC 1F1F8 ; fully-qualified # 🇬🇸 E2.0 flag: South Georgia & South Sandwich Islands -1F1EC 1F1F9 ; fully-qualified # 🇬🇹 E2.0 flag: Guatemala -1F1EC 1F1FA ; fully-qualified # 🇬🇺 E2.0 flag: Guam -1F1EC 1F1FC ; fully-qualified # 🇬🇼 E2.0 flag: Guinea-Bissau -1F1EC 1F1FE ; fully-qualified # 🇬🇾 E2.0 flag: Guyana -1F1ED 1F1F0 ; fully-qualified # 🇭🇰 E2.0 flag: Hong Kong SAR China -1F1ED 1F1F2 ; fully-qualified # 🇭🇲 E2.0 flag: Heard & McDonald Islands -1F1ED 1F1F3 ; fully-qualified # 🇭🇳 E2.0 flag: Honduras -1F1ED 1F1F7 ; fully-qualified # 🇭🇷 E2.0 flag: Croatia -1F1ED 1F1F9 ; fully-qualified # 🇭🇹 E2.0 flag: Haiti -1F1ED 1F1FA ; fully-qualified # 🇭🇺 E2.0 flag: Hungary -1F1EE 1F1E8 ; fully-qualified # 🇮🇨 E2.0 flag: Canary Islands -1F1EE 1F1E9 ; fully-qualified # 🇮🇩 E2.0 flag: Indonesia -1F1EE 1F1EA ; fully-qualified # 🇮🇪 E2.0 flag: Ireland -1F1EE 1F1F1 ; fully-qualified # 🇮🇱 E2.0 flag: Israel -1F1EE 1F1F2 ; fully-qualified # 🇮🇲 E2.0 flag: Isle of Man -1F1EE 1F1F3 ; fully-qualified # 🇮🇳 E2.0 flag: India -1F1EE 1F1F4 ; fully-qualified # 🇮🇴 E2.0 flag: British Indian Ocean Territory -1F1EE 1F1F6 ; fully-qualified # 🇮🇶 E2.0 flag: Iraq -1F1EE 1F1F7 ; fully-qualified # 🇮🇷 E2.0 flag: Iran -1F1EE 1F1F8 ; fully-qualified # 🇮🇸 E2.0 flag: Iceland -1F1EE 1F1F9 ; fully-qualified # 🇮🇹 E0.6 flag: Italy -1F1EF 1F1EA ; fully-qualified # 🇯🇪 E2.0 flag: Jersey -1F1EF 1F1F2 ; fully-qualified # 🇯🇲 E2.0 flag: Jamaica -1F1EF 1F1F4 ; fully-qualified # 🇯🇴 E2.0 flag: Jordan -1F1EF 1F1F5 ; fully-qualified # 🇯🇵 E0.6 flag: Japan -1F1F0 1F1EA ; fully-qualified # 🇰🇪 E2.0 flag: Kenya -1F1F0 1F1EC ; fully-qualified # 🇰🇬 E2.0 flag: Kyrgyzstan -1F1F0 1F1ED ; fully-qualified # 🇰🇭 E2.0 flag: Cambodia -1F1F0 1F1EE ; fully-qualified # 🇰🇮 E2.0 flag: Kiribati -1F1F0 1F1F2 ; fully-qualified # 🇰🇲 E2.0 flag: Comoros -1F1F0 1F1F3 ; fully-qualified # 🇰🇳 E2.0 flag: St. Kitts & Nevis -1F1F0 1F1F5 ; fully-qualified # 🇰🇵 E2.0 flag: North Korea -1F1F0 1F1F7 ; fully-qualified # 🇰🇷 E0.6 flag: South Korea -1F1F0 1F1FC ; fully-qualified # 🇰🇼 E2.0 flag: Kuwait -1F1F0 1F1FE ; fully-qualified # 🇰🇾 E2.0 flag: Cayman Islands -1F1F0 1F1FF ; fully-qualified # 🇰🇿 E2.0 flag: Kazakhstan -1F1F1 1F1E6 ; fully-qualified # 🇱🇦 E2.0 flag: Laos -1F1F1 1F1E7 ; fully-qualified # 🇱🇧 E2.0 flag: Lebanon -1F1F1 1F1E8 ; fully-qualified # 🇱🇨 E2.0 flag: St. Lucia -1F1F1 1F1EE ; fully-qualified # 🇱🇮 E2.0 flag: Liechtenstein -1F1F1 1F1F0 ; fully-qualified # 🇱🇰 E2.0 flag: Sri Lanka -1F1F1 1F1F7 ; fully-qualified # 🇱🇷 E2.0 flag: Liberia -1F1F1 1F1F8 ; fully-qualified # 🇱🇸 E2.0 flag: Lesotho -1F1F1 1F1F9 ; fully-qualified # 🇱🇹 E2.0 flag: Lithuania -1F1F1 1F1FA ; fully-qualified # 🇱🇺 E2.0 flag: Luxembourg -1F1F1 1F1FB ; fully-qualified # 🇱🇻 E2.0 flag: Latvia -1F1F1 1F1FE ; fully-qualified # 🇱🇾 E2.0 flag: Libya -1F1F2 1F1E6 ; fully-qualified # 🇲🇦 E2.0 flag: Morocco -1F1F2 1F1E8 ; fully-qualified # 🇲🇨 E2.0 flag: Monaco -1F1F2 1F1E9 ; fully-qualified # 🇲🇩 E2.0 flag: Moldova -1F1F2 1F1EA ; fully-qualified # 🇲🇪 E2.0 flag: Montenegro -1F1F2 1F1EB ; fully-qualified # 🇲🇫 E2.0 flag: St. Martin -1F1F2 1F1EC ; fully-qualified # 🇲🇬 E2.0 flag: Madagascar -1F1F2 1F1ED ; fully-qualified # 🇲🇭 E2.0 flag: Marshall Islands -1F1F2 1F1F0 ; fully-qualified # 🇲🇰 E2.0 flag: North Macedonia -1F1F2 1F1F1 ; fully-qualified # 🇲🇱 E2.0 flag: Mali -1F1F2 1F1F2 ; fully-qualified # 🇲🇲 E2.0 flag: Myanmar (Burma) -1F1F2 1F1F3 ; fully-qualified # 🇲🇳 E2.0 flag: Mongolia -1F1F2 1F1F4 ; fully-qualified # 🇲🇴 E2.0 flag: Macao SAR China -1F1F2 1F1F5 ; fully-qualified # 🇲🇵 E2.0 flag: Northern Mariana Islands -1F1F2 1F1F6 ; fully-qualified # 🇲🇶 E2.0 flag: Martinique -1F1F2 1F1F7 ; fully-qualified # 🇲🇷 E2.0 flag: Mauritania -1F1F2 1F1F8 ; fully-qualified # 🇲🇸 E2.0 flag: Montserrat -1F1F2 1F1F9 ; fully-qualified # 🇲🇹 E2.0 flag: Malta -1F1F2 1F1FA ; fully-qualified # 🇲🇺 E2.0 flag: Mauritius -1F1F2 1F1FB ; fully-qualified # 🇲🇻 E2.0 flag: Maldives -1F1F2 1F1FC ; fully-qualified # 🇲🇼 E2.0 flag: Malawi -1F1F2 1F1FD ; fully-qualified # 🇲🇽 E2.0 flag: Mexico -1F1F2 1F1FE ; fully-qualified # 🇲🇾 E2.0 flag: Malaysia -1F1F2 1F1FF ; fully-qualified # 🇲🇿 E2.0 flag: Mozambique -1F1F3 1F1E6 ; fully-qualified # 🇳🇦 E2.0 flag: Namibia -1F1F3 1F1E8 ; fully-qualified # 🇳🇨 E2.0 flag: New Caledonia -1F1F3 1F1EA ; fully-qualified # 🇳🇪 E2.0 flag: Niger -1F1F3 1F1EB ; fully-qualified # 🇳🇫 E2.0 flag: Norfolk Island -1F1F3 1F1EC ; fully-qualified # 🇳🇬 E2.0 flag: Nigeria -1F1F3 1F1EE ; fully-qualified # 🇳🇮 E2.0 flag: Nicaragua -1F1F3 1F1F1 ; fully-qualified # 🇳🇱 E2.0 flag: Netherlands -1F1F3 1F1F4 ; fully-qualified # 🇳🇴 E2.0 flag: Norway -1F1F3 1F1F5 ; fully-qualified # 🇳🇵 E2.0 flag: Nepal -1F1F3 1F1F7 ; fully-qualified # 🇳🇷 E2.0 flag: Nauru -1F1F3 1F1FA ; fully-qualified # 🇳🇺 E2.0 flag: Niue -1F1F3 1F1FF ; fully-qualified # 🇳🇿 E2.0 flag: New Zealand -1F1F4 1F1F2 ; fully-qualified # 🇴🇲 E2.0 flag: Oman -1F1F5 1F1E6 ; fully-qualified # 🇵🇦 E2.0 flag: Panama -1F1F5 1F1EA ; fully-qualified # 🇵🇪 E2.0 flag: Peru -1F1F5 1F1EB ; fully-qualified # 🇵🇫 E2.0 flag: French Polynesia -1F1F5 1F1EC ; fully-qualified # 🇵🇬 E2.0 flag: Papua New Guinea -1F1F5 1F1ED ; fully-qualified # 🇵🇭 E2.0 flag: Philippines -1F1F5 1F1F0 ; fully-qualified # 🇵🇰 E2.0 flag: Pakistan -1F1F5 1F1F1 ; fully-qualified # 🇵🇱 E2.0 flag: Poland -1F1F5 1F1F2 ; fully-qualified # 🇵🇲 E2.0 flag: St. Pierre & Miquelon -1F1F5 1F1F3 ; fully-qualified # 🇵🇳 E2.0 flag: Pitcairn Islands -1F1F5 1F1F7 ; fully-qualified # 🇵🇷 E2.0 flag: Puerto Rico -1F1F5 1F1F8 ; fully-qualified # 🇵🇸 E2.0 flag: Palestinian Territories -1F1F5 1F1F9 ; fully-qualified # 🇵🇹 E2.0 flag: Portugal -1F1F5 1F1FC ; fully-qualified # 🇵🇼 E2.0 flag: Palau -1F1F5 1F1FE ; fully-qualified # 🇵🇾 E2.0 flag: Paraguay -1F1F6 1F1E6 ; fully-qualified # 🇶🇦 E2.0 flag: Qatar -1F1F7 1F1EA ; fully-qualified # 🇷🇪 E2.0 flag: Réunion -1F1F7 1F1F4 ; fully-qualified # 🇷🇴 E2.0 flag: Romania -1F1F7 1F1F8 ; fully-qualified # 🇷🇸 E2.0 flag: Serbia -1F1F7 1F1FA ; fully-qualified # 🇷🇺 E0.6 flag: Russia -1F1F7 1F1FC ; fully-qualified # 🇷🇼 E2.0 flag: Rwanda -1F1F8 1F1E6 ; fully-qualified # 🇸🇦 E2.0 flag: Saudi Arabia -1F1F8 1F1E7 ; fully-qualified # 🇸🇧 E2.0 flag: Solomon Islands -1F1F8 1F1E8 ; fully-qualified # 🇸🇨 E2.0 flag: Seychelles -1F1F8 1F1E9 ; fully-qualified # 🇸🇩 E2.0 flag: Sudan -1F1F8 1F1EA ; fully-qualified # 🇸🇪 E2.0 flag: Sweden -1F1F8 1F1EC ; fully-qualified # 🇸🇬 E2.0 flag: Singapore -1F1F8 1F1ED ; fully-qualified # 🇸🇭 E2.0 flag: St. Helena -1F1F8 1F1EE ; fully-qualified # 🇸🇮 E2.0 flag: Slovenia -1F1F8 1F1EF ; fully-qualified # 🇸🇯 E2.0 flag: Svalbard & Jan Mayen -1F1F8 1F1F0 ; fully-qualified # 🇸🇰 E2.0 flag: Slovakia -1F1F8 1F1F1 ; fully-qualified # 🇸🇱 E2.0 flag: Sierra Leone -1F1F8 1F1F2 ; fully-qualified # 🇸🇲 E2.0 flag: San Marino -1F1F8 1F1F3 ; fully-qualified # 🇸🇳 E2.0 flag: Senegal -1F1F8 1F1F4 ; fully-qualified # 🇸🇴 E2.0 flag: Somalia -1F1F8 1F1F7 ; fully-qualified # 🇸🇷 E2.0 flag: Suriname -1F1F8 1F1F8 ; fully-qualified # 🇸🇸 E2.0 flag: South Sudan -1F1F8 1F1F9 ; fully-qualified # 🇸🇹 E2.0 flag: São Tomé & Príncipe -1F1F8 1F1FB ; fully-qualified # 🇸🇻 E2.0 flag: El Salvador -1F1F8 1F1FD ; fully-qualified # 🇸🇽 E2.0 flag: Sint Maarten -1F1F8 1F1FE ; fully-qualified # 🇸🇾 E2.0 flag: Syria -1F1F8 1F1FF ; fully-qualified # 🇸🇿 E2.0 flag: Eswatini -1F1F9 1F1E6 ; fully-qualified # 🇹🇦 E2.0 flag: Tristan da Cunha -1F1F9 1F1E8 ; fully-qualified # 🇹🇨 E2.0 flag: Turks & Caicos Islands -1F1F9 1F1E9 ; fully-qualified # 🇹🇩 E2.0 flag: Chad -1F1F9 1F1EB ; fully-qualified # 🇹🇫 E2.0 flag: French Southern Territories -1F1F9 1F1EC ; fully-qualified # 🇹🇬 E2.0 flag: Togo -1F1F9 1F1ED ; fully-qualified # 🇹🇭 E2.0 flag: Thailand -1F1F9 1F1EF ; fully-qualified # 🇹🇯 E2.0 flag: Tajikistan -1F1F9 1F1F0 ; fully-qualified # 🇹🇰 E2.0 flag: Tokelau -1F1F9 1F1F1 ; fully-qualified # 🇹🇱 E2.0 flag: Timor-Leste -1F1F9 1F1F2 ; fully-qualified # 🇹🇲 E2.0 flag: Turkmenistan -1F1F9 1F1F3 ; fully-qualified # 🇹🇳 E2.0 flag: Tunisia -1F1F9 1F1F4 ; fully-qualified # 🇹🇴 E2.0 flag: Tonga -1F1F9 1F1F7 ; fully-qualified # 🇹🇷 E2.0 flag: Turkey -1F1F9 1F1F9 ; fully-qualified # 🇹🇹 E2.0 flag: Trinidad & Tobago -1F1F9 1F1FB ; fully-qualified # 🇹🇻 E2.0 flag: Tuvalu -1F1F9 1F1FC ; fully-qualified # 🇹🇼 E2.0 flag: Taiwan -1F1F9 1F1FF ; fully-qualified # 🇹🇿 E2.0 flag: Tanzania -1F1FA 1F1E6 ; fully-qualified # 🇺🇦 E2.0 flag: Ukraine -1F1FA 1F1EC ; fully-qualified # 🇺🇬 E2.0 flag: Uganda -1F1FA 1F1F2 ; fully-qualified # 🇺🇲 E2.0 flag: U.S. Outlying Islands -1F1FA 1F1F3 ; fully-qualified # 🇺🇳 E4.0 flag: United Nations -1F1FA 1F1F8 ; fully-qualified # 🇺🇸 E0.6 flag: United States -1F1FA 1F1FE ; fully-qualified # 🇺🇾 E2.0 flag: Uruguay -1F1FA 1F1FF ; fully-qualified # 🇺🇿 E2.0 flag: Uzbekistan -1F1FB 1F1E6 ; fully-qualified # 🇻🇦 E2.0 flag: Vatican City -1F1FB 1F1E8 ; fully-qualified # 🇻🇨 E2.0 flag: St. Vincent & Grenadines -1F1FB 1F1EA ; fully-qualified # 🇻🇪 E2.0 flag: Venezuela -1F1FB 1F1EC ; fully-qualified # 🇻🇬 E2.0 flag: British Virgin Islands -1F1FB 1F1EE ; fully-qualified # 🇻🇮 E2.0 flag: U.S. Virgin Islands -1F1FB 1F1F3 ; fully-qualified # 🇻🇳 E2.0 flag: Vietnam -1F1FB 1F1FA ; fully-qualified # 🇻🇺 E2.0 flag: Vanuatu -1F1FC 1F1EB ; fully-qualified # 🇼🇫 E2.0 flag: Wallis & Futuna -1F1FC 1F1F8 ; fully-qualified # 🇼🇸 E2.0 flag: Samoa -1F1FD 1F1F0 ; fully-qualified # 🇽🇰 E2.0 flag: Kosovo -1F1FE 1F1EA ; fully-qualified # 🇾🇪 E2.0 flag: Yemen -1F1FE 1F1F9 ; fully-qualified # 🇾🇹 E2.0 flag: Mayotte -1F1FF 1F1E6 ; fully-qualified # 🇿🇦 E2.0 flag: South Africa -1F1FF 1F1F2 ; fully-qualified # 🇿🇲 E2.0 flag: Zambia -1F1FF 1F1FC ; fully-qualified # 🇿🇼 E2.0 flag: Zimbabwe - -# subgroup: subdivision-flag -1F3F4 E0067 E0062 E0065 E006E E0067 E007F ; fully-qualified # 🏴󠁧󠁢󠁥󠁮󠁧󠁿 E5.0 flag: England -1F3F4 E0067 E0062 E0073 E0063 E0074 E007F ; fully-qualified # 🏴󠁧󠁢󠁳󠁣󠁴󠁿 E5.0 flag: Scotland -1F3F4 E0067 E0062 E0077 E006C E0073 E007F ; fully-qualified # 🏴󠁧󠁢󠁷󠁬󠁳󠁿 E5.0 flag: Wales - -# Flags subtotal: 275 -# Flags subtotal: 275 w/o modifiers - -# Status Counts -# fully-qualified : 3655 -# minimally-qualified : 827 -# unqualified : 242 -# component : 9 - -#EOF diff --git a/emoji/scrape_aliases b/emoji/scrape_aliases deleted file mode 100755 index 3290d80b..00000000 --- a/emoji/scrape_aliases +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -import asyncio -import json -import re - -from requests_html import AsyncHTMLSession -from rich.progress import track - -LINE_RE = re.compile( - r""" - ^ - (?P .*\S) - \s*;\s* - (?P \S+) - \s*\#\s* - (?P \S+) - \s* - (?P E\d+.\d+) - \s* - (?P .+) - $ -""", - re.VERBOSE, -) - - -async def get_aliases(session, name): - emojipedia_name = name.replace(" ", "-") - url = f"https://emojipedia.org/{emojipedia_name}/" - r = await session.get(url) - if r.status_code != 200: - return (name, []) - - aliases = r.html.find(".aliases li") - res = [] - for alias in aliases: - alias = alias.text.split(maxsplit=1)[1] - alias = alias.replace("\N{NO-BREAK SPACE}", " ") # Replace nbsp - res.append(alias) - return (name, res) - - -async def main(): - session = AsyncHTMLSession() - aliases = {} - - aws = [] - with open("emoji-test.txt") as f: - for l in f: - if m := LINE_RE.match(l): - d = m.groupdict() - if d["status"] != "fully-qualified": - continue - - aws.append(get_aliases(session, d["name"])) - - for aw in track(asyncio.as_completed(aws), total=len(aws)): - name, res = await aw - if res: - aliases[name] = res - - print(name, res) - - with open("aliases.json", "w") as f: - json.dump(aliases, f) - - -asyncio.run(main()) From e7d3d186a32eb85299ce15c02d2154642b015d9f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:56:37 +0200 Subject: [PATCH 154/355] [goldendict] Interface v2.0 --- goldendict/__init__.py | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/goldendict/__init__.py b/goldendict/__init__.py index c1bbd3db..6b1aba14 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -1,32 +1,25 @@ from albert import Action, Item, TriggerQuery, TriggerQueryHandler, runDetachedProcess # pylint: disable=import-error -md_iid = '1.0' -md_version = '1.2' +md_iid = '2.0' +md_version = '1.3' md_name = 'GoldenDict' md_description = 'Searches in GoldenDict' md_url = 'https://github.com/albertlauncher/python/' md_maintainers = '@stevenxxiu' md_bin_dependencies = ['goldendict'] -TRIGGER = 'gd' -ICON_PATH = '/usr/share/pixmaps/goldendict.png' +class Plugin(PluginInstance, TriggerQueryHandler): -class Plugin(TriggerQueryHandler): - def id(self) -> str: - return __name__ - - def name(self) -> str: - return md_name - - def description(self) -> str: - return md_description - - def defaultTrigger(self) -> str: - return f'{TRIGGER} ' - - def synopsis(self) -> str: - return 'query' + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='query', + defaultTrigger='gd ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = ["xdg:goldendict"] def handleTriggerQuery(self, query: TriggerQuery) -> None: query_str = query.string.strip() @@ -34,11 +27,11 @@ def handleTriggerQuery(self, query: TriggerQuery) -> None: return query.add( - Item( + StandardItem( id=md_name, text=md_name, subtext=f'Look up {query_str} using GoldenDict', - icon=[ICON_PATH], + iconUrls=self.iconUrls, actions=[Action(md_name, md_name, lambda: runDetachedProcess(['goldendict', query_str]))], ) ) From e11d5c47af7860b76c21c70f87a23bcfc93a7004 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:57:00 +0200 Subject: [PATCH 155/355] [googletrans] Interface v2.0 --- googletrans/__init__.py | 48 ++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/googletrans/__init__.py b/googletrans/__init__.py index 65e3873d..a97d4a81 100644 --- a/googletrans/__init__.py +++ b/googletrans/__init__.py @@ -4,14 +4,15 @@ Translator using py-googletrans """ -from albert import * -from googletrans import Translator, LANGUAGES from locale import getdefaultlocale +from pathlib import Path from time import sleep -import os -md_iid = '1.0' -md_version = "1.1" +from albert import * +from googletrans import Translator, LANGUAGES + +md_iid = '2.0' +md_version = "1.2" md_name = "Google Translate" md_description = "Translate sentences using googletrans" md_license = "BSD-3" @@ -19,32 +20,25 @@ md_lib_dependencies = "googletrans==3.1.0a0" md_maintainers = "@manuelschneid3r" -class Plugin(TriggerQueryHandler): - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return "tr " - - def synopsis(self): - return "[[src] dest] text" +class Plugin(TriggerQueryHandler): - def initialize(self): - self.icon = [os.path.dirname(__file__)+"/google_translate.png"] + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis="[[src] dest] text", + defaultTrigger='tr ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = [f"file:{Path(__file__).parent}/google_translate.png"] self.translator = Translator() self.lang = getdefaultlocale()[0][0:2] def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: - for number in range(50): + for _ in range(50): sleep(0.01) if not query.isValid: return @@ -64,11 +58,11 @@ def handleTriggerQuery(self, query): else: translation = self.translator.translate(text, dest=dest) - query.add(Item( + query.add(StandardItem( id=md_id, text=translation.text, subtext=f'From {LANGUAGES[translation.src]} to {LANGUAGES[translation.dest]}', - icon=self.icon, - actions = [Action("copy", "Copy result to clipboard", - lambda t=translation.text: setClipboardText(t))] + iconUrls=self.iconUrls, + actions=[Action("copy", "Copy result to clipboard", + lambda t=translation.text: setClipboardText(t))] )) From bce5ce82df98e06777390c258c758eca8bfcc39c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:57:27 +0200 Subject: [PATCH 156/355] [jetbrains] Interface v2.0 --- jetbrains_projects/__init__.py | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 10bb9aa4..9a5258c3 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -15,8 +15,8 @@ from xml.etree import ElementTree from albert import * -md_iid = '1.0' -md_version = "1.4" +md_iid = '2.0' +md_version = "1.5" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "GPL-3" @@ -82,22 +82,19 @@ def _parse_recent_projects(self, recent_projects_file: Path) -> list[Project]: return [] -class Plugin(TriggerQueryHandler): - executables = [] - - def id(self): - return md_id +class Plugin(PluginInstance, TriggerQueryHandler): - def name(self): - return md_name - - def description(self): - return md_description + executables = [] - def defaultTrigger(self): - return "jb " + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='project name', + defaultTrigger='jb ') + PluginInstance.__init__(self, extensions=[self]) - def initialize(self): plugin_dir = Path(__file__).parent editors = [ Editor( @@ -175,12 +172,12 @@ def handleTriggerQuery(self, query: TriggerQuery): query.add([self._make_item(editor, project, query) for editor, project in editor_project_pairs]) def _make_item(self, editor: Editor, project: Project, query: TriggerQuery) -> Item: - return Item( + return StandardItem( id="%s-%s-%s" % (editor.binary, project.path, project.last_opened), text=project.name, subtext=project.path, - completion=query.trigger + project.name, - icon=[str(editor.icon)], + inputActionText=query.trigger + project.name, + iconUrls=["file:" + str(editor.icon)], actions=[ Action( "Open", From 6c9c962d16f299adde2456f1bfb6f8c093a1fdab Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 01:57:43 +0200 Subject: [PATCH 157/355] [kill] Interface v2.0 --- kill/__init__.py | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/kill/__init__.py b/kill/__init__.py index 7aec13c8..0b259a23 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = '1.0' -md_version = "1.2" +md_iid = '2.0' +md_version = "1.3" md_name = "Kill Process" md_description = "Kill processes" md_license = "BSD-3" @@ -15,23 +15,14 @@ md_credits = "Original idea by Benedict Dudel & Manuel Schneider" -class Plugin(TriggerQueryHandler): - icon_path = "xdg:process-stop" - - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def initialize(self): - pass - - def defaultTrigger(self): - return "kill " +class Plugin(PluginInstance, TriggerQueryHandler): + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='kill ') + PluginInstance.__init__(self, extensions=[self]) def handleTriggerQuery(self, query): if not query.isValid: @@ -53,9 +44,9 @@ def handleTriggerQuery(self, query): .replace("\0", " ") ) results.append( - Item( + StandardItem( id="kill", - icon=[self.icon_path], + iconUrls=["xdg:process-stop"], text=proc_command, subtext=proc_cmdline, actions=[ From fb6cde26e1f02f6c7708dc090fa543fc7dcb4f05 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:02:16 +0200 Subject: [PATCH 158/355] [locate] Interface v2.0 --- locate/__init__.py | 48 +++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/locate/__init__.py b/locate/__init__.py index 40fef9bb..461de92b 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -7,14 +7,14 @@ """ -from albert import * -import os -import pathlib import shlex import subprocess +from pathlib import Path + +from albert import * -md_iid = '1.0' -md_version = "1.8" +md_iid = '2.0' +md_version = "1.9" md_name = "Locate" md_description = "Find and open files using locate" md_license = "BSD-3" @@ -24,28 +24,21 @@ class Plugin(TriggerQueryHandler): - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return "'" - - def synopsis(self): - return "" + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='', + defaultTrigger="'") + PluginInstance.__init__(self, extensions=[self]) - def initialize(self): - self.icons = [ + self.iconUrls = [ "xdg:preferences-system-search", "xdg:system-search", "xdg:search", "xdg:text-x-generic", - str(pathlib.Path(__file__).parent / "locate.svg") + f"file:{Path(__file__).parent}/locate.svg" ] def handleTriggerQuery(self, query): @@ -64,13 +57,12 @@ def handleTriggerQuery(self, query): return for path in lines: - basename = os.path.basename(path) query.add( - Item( + StandardItem( id=path, - text=basename, + text=Path(path).name, subtext=path, - icon=self.icons, + iconUrls=self.iconUrls, actions=[ Action("open", "Open", lambda p=path: openUrl("file://%s" % p)) ] @@ -78,11 +70,11 @@ def handleTriggerQuery(self, query): ) else: query.add( - Item( + StandardItem( id="updatedb", text="Update locate database", subtext="Type at least three chars for a search", - icon=self.icons, + iconUrls=self.iconUrls, actions=[ Action("update", "Update", lambda: runTerminal("sudo updatedb")) ] From 6afc16efe6368a7a6cb390a6199c964c9ecf7bc5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:02:33 +0200 Subject: [PATCH 159/355] [mathematica_eval] Interface v2.0 --- mathematica_eval/__init__.py | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/mathematica_eval/__init__.py b/mathematica_eval/__init__.py index e988fc67..6bb38c4d 100644 --- a/mathematica_eval/__init__.py +++ b/mathematica_eval/__init__.py @@ -7,8 +7,8 @@ from albert import (Action, Item, TriggerQuery, TriggerQueryHandler, setClipboardText) -md_iid = "1.0" -md_version = "1.0" +md_iid = "2.0" +md_version = "1.1" md_name = "Mathematica Eval" md_description = "Evaluate Mathemtica code" md_license = "GPL-3.0" @@ -17,21 +17,16 @@ md_bin_dependencies = ["wolframscript"] -class Plugin(TriggerQueryHandler): - def id(self) -> str: - return md_id +class Plugin(PluginInstance, TriggerQueryHandler): - def name(self) -> str: - return md_name - - def description(self) -> str: - return md_description - - def defaultTrigger(self) -> str: - return "mma " - - def synopsis(self) -> str: - return "" + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='', + defaultTrigger='mma ') + PluginInstance.__init__(self, extensions=[self]) def handleTriggerQuery(self, query: TriggerQuery) -> None: stripped = query.string.strip() @@ -61,11 +56,11 @@ def handleTriggerQuery(self, query: TriggerQuery) -> None: result_str = output.strip() query.add( - Item( + StandardItem( id=md_id, text=result_str, - completion=query.trigger + result_str, - icon=["xdg:wolfram-mathematica"], + inputActionText=query.trigger + result_str, + iconUrls=["xdg:wolfram-mathematica"], actions=[ Action( "copy", From aa454efb825a57c96220f17390998e4c0bf77aa4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:04:01 +0200 Subject: [PATCH 160/355] [pacman] Interface v2.0 --- pacman/__init__.py | 50 +++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/pacman/__init__.py b/pacman/__init__.py index 0b2ee192..11e9a841 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -11,8 +11,8 @@ from albert import Action, Item, TriggerQueryHandler, runTerminal, openUrl -md_iid = '1.0' -md_version = "1.7" +md_iid = '2.0' +md_version = "1.8" md_name = "PacMan" md_description = "Search, install and remove packages" md_license = "BSD-3" @@ -20,30 +20,22 @@ md_bin_dependencies = ["pacman", "expac"] -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): pkgs_url = "https://www.archlinux.org/packages/" - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def synopsis(self): - return "" - - def defaultTrigger(self): - return "pac " - - def initialize(self): - self.icons = [ + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='', + defaultTrigger='pac ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = [ "xdg:archlinux-logo", "xdg:system-software-install", - str(pathlib.Path(__file__).parent / "arch.svg") + f"file:{pathlib.Path(__file__).parent}/arch.svg" ] def handleTriggerQuery(self, query): @@ -51,11 +43,11 @@ def handleTriggerQuery(self, query): # Update item on empty queries if not stripped: - query.add(Item( + query.add(StandardItem( id="%s-update" % md_id, text="Pacman package manager", subtext="Enter the package you are looking for or hit enter to update.", - icon=self.icons, + iconUrls=self.iconUrls, actions=[ Action("up-nc", "Update packages (no confirm)", lambda: runTerminal("sudo pacman -Syu --noconfirm")), @@ -82,7 +74,7 @@ def handleTriggerQuery(self, query): remote_pkgs = [tuple(line.split('\t')) for line in proc_s.stdout.read().split('\n')[:-1]] # newline at end for pkg_name, pkg_vers, pkg_repo, pkg_desc, pkg_purl, pkg_deps in remote_pkgs: - if stripped not in pkg_name : + if stripped not in pkg_name: continue pkg_installed = True if pkg_name in local_pkgs else False @@ -100,12 +92,12 @@ def handleTriggerQuery(self, query): if pkg_purl: actions.append(Action("proj_url", "Show project website", lambda u=pkg_purl: openUrl(u))) - item = Item( + item = StandardItem( id="%s_%s_%s" % (md_id, pkg_repo, pkg_name), - icon=self.icons, + iconUrls=self.iconUrls, text="%s %s [%s]" % (pkg_name, pkg_vers, pkg_repo), subtext=f"{pkg_desc} [Installed]" if pkg_installed else f"{pkg_desc}", - completion="%s%s" % (query.trigger, pkg_name), + inputActionText="%s%s" % (query.trigger, pkg_name), actions=actions ) items.append(item) @@ -113,10 +105,10 @@ def handleTriggerQuery(self, query): if items: query.add(items) else: - query.add(Item( + query.add(StandardItem( id="%s-empty" % md_id, text="Search on archlinux.org", subtext="No results found in the local database", - icon=self.icons, + iconUrls=self.iconUrls, actions=[Action("search", "Search on archlinux.org", lambda: openUrl(f"{self.pkgs_url}?q={stripped}"))] )) From c409e3feab2708740f03c0ba6dd6abbf4a691b74 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:05:07 +0200 Subject: [PATCH 161/355] [pass] Interface v2.0 --- pass/__init__.py | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/pass/__init__.py b/pass/__init__.py index 0a76a51f..97feb71e 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -4,8 +4,8 @@ import os from albert import * -md_iid = '1.0' -md_version = "1.3" +md_iid = '2.0' +md_version = "1.4" md_name = "Pass" md_description = "Manage passwords in pass" md_bin_dependencies = ["pass"] @@ -14,24 +14,19 @@ HOME_DIR = os.environ["HOME"] PASS_DIR = os.environ.get("PASSWORD_STORE_DIR", os.path.join(HOME_DIR, ".password-store/")) -ICON = ["xdg:dialog-password"] -class Plugin(TriggerQueryHandler): - def id(self): - return md_id +class Plugin(PluginInstance, TriggerQueryHandler): - def name(self): - return md_name - - def description(self): - return md_description - - def synopsis(self): - return "" - - def defaultTrigger(self): - return "pass " + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='', + defaultTrigger='pass ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = ["xdg:dialog-password"] def handleTriggerQuery(self, query): if query.string.strip().startswith("generate"): @@ -42,19 +37,18 @@ def handleTriggerQuery(self, query): def generatePassword(self, query): location = query.string.strip()[9:] - query.add(Item( + query.add(StandardItem( id="generate_password", - icon=ICON, + iconUrls=self.iconUrls, text="Generate a new password", subtext="The new password will be located at %s" % location, - completion="pass %s" % query.string, + inputActionText="pass %s" % query.string, actions=[ Action("generate", "Generate", lambda: runDetachedProcess(["pass", "generate", "--clip", location, "20"])) ] )) def showPasswords(self, query): - passwords = [] if query.string.strip(): passwords = self.getPasswordsFromSearch(query) else: @@ -64,12 +58,12 @@ def showPasswords(self, query): for password in passwords: name = password.split("/")[-1] results.append( - Item( + StandardItem( id=password, - icon=ICON, text=name, subtext=password, - completion="pass %s" % password, + iconUrls=self.iconUrls, + inputActionText="pass %s" % password, actions=[ Action("copy", "Copy", lambda pwd=password: runDetachedProcess(["pass", "--clip", pwd])), Action("edit", "Edit", lambda pwd=password: runDetachedProcess(["pass", "edit", pwd])), From 33d6ad9eff545699e217f05d6bc178c503e79ea7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:07:04 +0200 Subject: [PATCH 162/355] [pomodoro] Interface v2.0 --- pomodoro/__init__.py | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 53faba9b..a18b4455 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -5,14 +5,15 @@ https://en.wikipedia.org/wiki/Pomodoro_Technique """ -from albert import * import subprocess import threading import time -import os +from pathlib import Path + +from albert import * -md_iid = '1.0' -md_version = "1.2" +md_iid = '2.0' +md_version = "1.3" md_name = "Pomodoro" md_description = "Set up a Pomodoro timer" md_license = "BSD-3" @@ -66,36 +67,28 @@ def isActive(self): return self.timer is not None -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): - icon = [os.path.dirname(__file__) + "/pomodoro.svg"] default_pomodoro_duration = 25 default_break_duration = 5 default_longbreak_duration = 15 default_pomodoro_count = 4 - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return "pomo " - - def initialize(self): + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='[duration [break duration [long break duration [count]]]]', + defaultTrigger='pomo ') + PluginInstance.__init__(self, extensions=[self]) self.pomodoro = PomodoroTimer() - - def synopsis(self): - return "[duration [break duration [long break duration [count]]]]" + self.iconUrls = [f"file:{Path(__file__).parent}/pomodoro.svg"] def handleTriggerQuery(self, query): - item = Item( + item = StandardItem( id=md_id, - icon=self.icon, + iconUrls=self.iconUrls, text=md_name ) From b13835e4cd8f238e0e460346588bc7cb60d79a5e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:08:13 +0200 Subject: [PATCH 163/355] [python_eval] Interface v2.0 --- python_eval/__init__.py | 45 +++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/python_eval/__init__.py b/python_eval/__init__.py index 71a480ff..86f86d16 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -1,39 +1,30 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2022-2023 Manuel Schneider -from albert import * from builtins import pow from math import * -import os +from pathlib import Path + +from albert import * -md_iid = '1.0' -md_version = "1.4" +md_iid = '2.0' +md_version = "1.5" md_name = "Python Eval" md_description = "Evaluate Python code" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/python_eval" -md_maintainers = "@manuelschneid3r" - - -class Plugin(TriggerQueryHandler): - - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - def defaultTrigger(self): - return "py " - def synopsis(self): - return "" +class Plugin(PluginInstance, TriggerQueryHandler): - def initialize(self): - self.iconPath = os.path.dirname(__file__)+"/python.svg" + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='', + defaultTrigger='py ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = [f"file:{Path(__file__).parent}/python.svg"] def handleTriggerQuery(self, query): stripped = query.string.strip() @@ -45,12 +36,12 @@ def handleTriggerQuery(self, query): result_str = str(result) - query.add(Item( + query.add(StandardItem( id=md_id, text=result_str, subtext=type(result).__name__, - completion=query.trigger + result_str, - icon=[self.iconPath], + inputActionText=query.trigger + result_str, + iconUrls=self.iconUrls, actions = [ Action("copy", "Copy result to clipboard", lambda r=result_str: setClipboardText(r)), Action("exec", "Execute python code", lambda r=result_str: exec(stripped)), From 94f5fe4ac49746348a77a0ce9694130aba625f0c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:09:28 +0200 Subject: [PATCH 164/355] [tex_to_unicode] Interface v2.0 --- tex_to_unicode/__init__.py | 39 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/tex_to_unicode/__init__.py b/tex_to_unicode/__init__.py index 6393ed43..f28fabdd 100644 --- a/tex_to_unicode/__init__.py +++ b/tex_to_unicode/__init__.py @@ -2,15 +2,15 @@ # Copyright (c) 2022 Manuel Schneider -import os import re import unicodedata +from pathlib import Path +from pylatexenc.latex2text import LatexNodes2Text from albert import * -from pylatexenc.latex2text import LatexNodes2Text -md_iid = '1.0' -md_version = "1.1" +md_iid = '2.0' +md_version = "1.2" md_name = "TeX to Unicode" md_description = "Convert TeX mathmode commands to unicode characters" md_license = "GPL-3.0" @@ -19,25 +19,18 @@ md_maintainers = "@DenverCoder1" -class Plugin(TriggerQueryHandler): - def id(self) -> str: - return md_id - - def name(self) -> str: - return md_name - - def description(self) -> str: - return md_description - - def defaultTrigger(self) -> str: - return "tex " - - def synopsis(self) -> str: - return "" +class Plugin(PluginInstance, TriggerQueryHandler): - def initialize(self) -> None: + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='', + defaultTrigger='tex ') + PluginInstance.__init__(self, extensions=[self]) self.COMBINING_LONG_SOLIDUS_OVERLAY = "\u0338" - self.icon = [os.path.dirname(__file__) + "/tex.png"] + self.iconUrls = [f"file:{Path(__file__).parent}/tex.png"] def _create_item(self, text: str, subtext: str, can_copy: bool) -> Item: actions = [] @@ -49,11 +42,11 @@ def _create_item(self, text: str, subtext: str, can_copy: bool) -> Item: lambda t=text: setClipboardText(t), ) ) - return Item( + return StandardItem( id=md_id, - icon=self.icon, text=text, subtext=subtext, + iconUrls=self.iconUrls, actions=actions, ) From 32d1701664dfd37194631239fba6870a5c210deb Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:10:28 +0200 Subject: [PATCH 165/355] [timer] Interface v2.0 --- timer/__init__.py | 59 +++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/timer/__init__.py b/timer/__init__.py index 5fc96bbb..a85e6ee1 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -10,16 +10,17 @@ - `120:` starts a 2 hours timer """ -from albert import * -from time import strftime, time, localtime -from datetime import timedelta +import subprocess import threading +from datetime import timedelta +from pathlib import Path from sys import platform -import os -import subprocess +from time import strftime, time, localtime -md_iid = '1.0' -md_version = "1.5" +from albert import * + +md_iid = '2.0' +md_version = "1.6" md_name = "Timer" md_description = "Set up timers" md_license = "BSD-2" @@ -37,11 +38,18 @@ def __init__(self, interval, name, callback): self.start() -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): - def initialize(self): - self.icons = [os.path.dirname(__file__)+"/time.svg"] - self.soundPath = os.path.dirname(__file__)+"/bing.wav" + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='[[hrs:]mins:]secs [name]', + defaultTrigger='timer ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = [f"file:{Path(__file__).parent}/time.svg"] + self.soundPath = Path(__file__).parent / "bing.wav" self.timers = [] def finalize(self): @@ -68,21 +76,6 @@ def onTimerTimeout(self, timer): self.deleteTimer(timer) - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - - def defaultTrigger(self): - return 'timer ' - - def synopsis(self): - return '[[hrs:]mins:]secs [name]' - def handleTriggerQuery(self, query): if not query.isValid: return @@ -92,11 +85,11 @@ def handleTriggerQuery(self, query): fields = args[0].split(":") name = args[1] if 1 < len(args) else '' if not all(field.isdigit() or field == '' for field in fields): - return Item( + return StandardItem( id=self.name(), text="Invalid input", subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % self.defaultTrigger(), - icon=self.icons + iconUrls=self.iconUrls, ) seconds = 0 @@ -104,11 +97,11 @@ def handleTriggerQuery(self, query): for i in range(len(fields)): seconds += int(fields[i] if fields[i] else 0)*(60**i) - query.add(Item( + query.add(StandardItem( id=self.name(), text=str(timedelta(seconds=seconds)), subtext='Set a timer with name "%s"' % name if name else 'Set a timer', - icon=self.icons, + iconUrls=self.iconUrls, actions=[Action("set-timer", "Set timer", lambda sec=seconds: self.startTimer(sec, name))] )) return @@ -121,13 +114,13 @@ def handleTriggerQuery(self, query): identifier = "%d:%02d:%02d" % (h, m, s) timer_name_with_quotes = '"%s"' % timer.name if timer.name else '' - items.append(Item( + items.append(StandardItem( id=self.name(), text='Delete timer %s [%s]' % (timer_name_with_quotes, identifier), subtext="Times out %s" % strftime("%X", localtime(timer.end)), - icon=self.icons, + iconUrls=self.iconUrls, actions=[Action("delete-timer", "Delete timer", lambda timer=timer: self.deleteTimer(timer))] )) if items: - query.add(items) \ No newline at end of file + query.add(items) From 52b30f7ef78716f4cacdfa6c0c027babf989c33f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:11:04 +0200 Subject: [PATCH 166/355] [unit_converter] Interface v2.0 --- unit_converter/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/unit_converter/__init__.py b/unit_converter/__init__.py index d25f547f..462dad4f 100644 --- a/unit_converter/__init__.py +++ b/unit_converter/__init__.py @@ -29,8 +29,8 @@ import pint -md_iid = '1.0' -md_version = "1.3" +md_iid = '2.0' +md_version = "1.4" md_name = "Unit Converter" md_description = "Convert between units" md_license = "MIT" @@ -356,7 +356,7 @@ def initialize(self): self.currency_converter = CurrencyConverter() def id(self) -> str: - return __name__ + return md_id def name(self) -> str: return md_name @@ -405,9 +405,9 @@ def _create_item(self, text: str, subtext: str, icon: str = "") -> albert.Item: if not icon or not icon_path.exists(): albert.warning(f"Icon {icon} does not exist") icon_path = Path(__file__).parent / "icons" / "unit_converter.svg" - return albert.Item( + return albert.StandardItem( id=str(icon_path), - icon=[str(icon_path)], + iconUrls=["file:" + str(icon_path)], text=text, subtext=subtext, actions=[ From 4bebd79cc38878c31f4b5d61aafba477c96f3b38 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:13:28 +0200 Subject: [PATCH 167/355] [vbox] Interface v2.0 --- virtualbox/__init__.py | 51 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py index f084bcfe..94b21015 100644 --- a/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = '1.0' -md_version = "1.4" +md_iid = '2.0' +md_version = "1.5" md_name = "VirtualBox" md_description = "Manage your VirtualBox machines" md_license = "BSD-3" @@ -23,47 +23,48 @@ def startVm(vm): except Exception as e: warning(str(e)) + def acpiPowerVm(vm): with vm.create_session(LockType.shared) as session: session.console.power_button() + def stopVm(vm): with vm.create_session(LockType.shared) as session: session.console.power_down() + def saveVm(vm): with vm.create_session(LockType.shared) as session: session.machine.save_state() + def discardSavedVm(vm): with vm.create_session(LockType.shared) as session: - session.machine.discard_save_state(True); + session.machine.discard_save_state(True) + def resumeVm(vm): with vm.create_session(LockType.shared) as session: session.console.resume() + def pauseVm(vm): with vm.create_session(LockType.shared) as session: session.console.pause() -class Plugin(TriggerQueryHandler): - iconUrls = ["xdg:virtualbox", ":unknown"] - - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description - def synopsis(self): - return "" +class Plugin(PluginInstance, TriggerQueryHandler): - def defaultTrigger(self): - return "vbox " + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='', + defaultTrigger='vbox ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = ["xdg:virtualbox", ":unknown"] def handleTriggerQuery(self, query): items = [] @@ -71,26 +72,26 @@ def handleTriggerQuery(self, query): try: for vm in filter(lambda vm: pattern in vm.name.lower(), virtualbox.VirtualBox().machines): actions = [] - if vm.state == MachineState.powered_off or vm.state == MachineState.aborted: #1 #4 + if vm.state == MachineState.powered_off or vm.state == MachineState.aborted: # 1 # 4 actions.append(Action("startvm", "Start virtual machine", lambda vm=vm: startVm(vm))) - if vm.state == MachineState.saved: #2 + if vm.state == MachineState.saved: # 2 actions.append(Action("restorevm", "Start saved virtual machine", lambda vm=vm: startVm(vm))) actions.append(Action("discardvm", "Discard saved state", lambda vm=vm: discardSavedVm(vm))) - if vm.state == MachineState.running: #5 + if vm.state == MachineState.running: # 5 actions.append(Action("savevm", "Save virtual machine", lambda vm=vm: saveVm(vm))) actions.append(Action("poweroffvm", "Power off via ACPI event (Power button)", lambda vm=vm: acpiPowerVm(vm))) actions.append(Action("stopvm", "Turn off virtual machine", lambda vm=vm: stopVm(vm))) actions.append(Action("pausevm", "Pause virtual machine", lambda vm=vm: pauseVm(vm))) - if vm.state == MachineState.paused: #6 + if vm.state == MachineState.paused: # 6 actions.append(Action("resumevm", "Resume virtual machine", lambda vm=vm: resumeVm(vm))) items.append( - Item( + StandardItem( id=vm.__uuid__, text=vm.name, subtext="{vm.state}".format(vm=vm), - completion=vm.name, - icon=self.iconUrls, + inputActionText=vm.name, + iconUrls=self.iconUrls, actions=actions ) ) From c8725d89951a0a805198d320e735cab30f46105e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:15:56 +0200 Subject: [PATCH 168/355] [vpn] Interface v2.0 --- vpn/__init__.py | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/vpn/__init__.py b/vpn/__init__.py index 3d6fae20..7c7bc02d 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -1,9 +1,10 @@ -from albert import * -from collections import namedtuple import subprocess +from collections import namedtuple + +from albert import * -md_iid = '1.0' -md_version = "1.3" +md_iid = '2.0' +md_version = "1.4" md_id = "vpn" md_name = "VPN" md_description = "Manage NetworkManager VPN connections" @@ -14,20 +15,17 @@ md_bin_dependencies = ["nmcli"] -class Plugin(TriggerQueryHandler): - - iconPath = ['xdg:network-wired'] +class Plugin(PluginInstance, TriggerQueryHandler): VPNConnection = namedtuple('VPNConnection', ['name', 'connected']) - def id(self): - return md_id - - def name(self): - return md_name - - def description(self): - return md_description + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='vpn ') + PluginInstance.__init__(self, extensions=[self]) def getVPNConnections(self): consStr = subprocess.check_output( @@ -40,25 +38,24 @@ def getVPNConnections(self): if con[2] in ['vpn', 'wireguard']: yield self.VPNConnection(name=con[0], connected=con[3] != '') - - def buildItem(self,con): + @staticmethod + def buildItem(con): name = con.name command = 'down' if con.connected else 'up' text = f'Connect to {name}' if command == 'up' else f'Disconnect from {name}' commandline = ['nmcli', 'connection', command, 'id', name] - return Item( + return StandardItem( id=f'vpn-{command}-{name}', text=name, subtext=text, - icon=self.iconPath, - completion=name, - actions=[ Action("run",text=text, callable=lambda: runDetachedProcess(commandline)) ] + iconUrls=['xdg:network-wired'], + inputActionText=name, + actions=[Action("run", text=text, callable=lambda: runDetachedProcess(commandline))] ) - - def handleTriggerQuery(self,query): + def handleTriggerQuery(self, query): if query.isValid: connections = self.getVPNConnections() if query.string: - connections = [ con for con in connections if query.string.lower() in con.name.lower() ] - query.add([ self.buildItem(con) for con in connections ]) + connections = [con for con in connections if query.string.lower() in con.name.lower()] + query.add([self.buildItem(con) for con in connections]) From 8b1d7480afd76458cc96f3d57f68980bc39e09c4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:25:31 +0200 Subject: [PATCH 169/355] [youtube] Interface v2.0 --- youtube/__init__.py | 54 +++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/youtube/__init__.py b/youtube/__init__.py index 17f5bc9e..ee6fb6a7 100644 --- a/youtube/__init__.py +++ b/youtube/__init__.py @@ -8,17 +8,16 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen -from albert import Action, Item, TriggerQuery, TriggerQueryHandler, critical, info, openUrl # pylint: disable=import-error +from albert import Action, StandardItem, TriggerQuery, PluginInstance, TriggerQueryHandler, critical, info, openUrl # pylint: disable=import-error -md_iid = '1.0' -md_version = '1.4' +md_iid = '2.0' +md_version = '1.5' md_name = 'YouTube' md_description = 'Query and open YouTube videos and channels' md_url = 'https://github.com/albertlauncher/python/' md_maintainers = '@stevenxxiu' -ICON_PATH = str(Path(__file__).parent / 'youtube.svg') DATA_REGEX = re.compile(r'\b(var\s|window\[")ytInitialData("\])?\s*=\s*(.*)\s*;', re.MULTILINE) HEADERS = { @@ -52,17 +51,17 @@ def text_from(val: dict[str, Any]) -> str: return text.strip() -def download_item_icon(item: Item, temp_dir: Path) -> None: +def download_item_icon(item: StandardItem, temp_dir: Path) -> None: url = item.icon[0] video_id = url.split('/')[-2] path = temp_dir / f'{video_id}.png' with urlopen_with_headers(url) as response, path.open('wb') as sr: sr.write(response.read()) - item.icon = [str(path)] + item.icon = ["file:" + str(path)] -def entry_to_item(type_, data) -> Item | None: - icon = ICON_PATH +def entry_to_item(type_, data) -> StandardItem | None: + icon = Plugin.iconUrls[0] match type_: case 'videoRenderer': subtext = ['Video'] @@ -87,16 +86,16 @@ def entry_to_item(type_, data) -> Item | None: case _: return None - return Item( + return StandardItem( id=f'{md_name}/{url_path}', text=text_from(data['title']), subtext=' | '.join(subtext), - icon=[icon], + iconUrls=[icon], actions=[Action(f'{md_name}/{url_path}', action, lambda: openUrl(f'https://www.youtube.com/{url_path}'))], ) -def results_to_items(results: dict) -> list[Item]: +def results_to_items(results: dict) -> list[StandardItem]: items: list[Item] = [] for result in results: for type_, data in result.items(): @@ -111,19 +110,18 @@ def results_to_items(results: dict) -> list[Item]: return items -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): temp_dir = None - - def id(self) -> str: - return __name__ - - def name(self) -> str: - return md_name - - def description(self) -> str: - return md_description - - def initialize(self) -> None: + iconUrls = [f"file:{Path(__file__).parent}/youtube.svg"] + + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis='query', + defaultTrigger='yt ') + PluginInstance.__init__(self, extensions=[self]) self.temp_dir = Path(tempfile.mkdtemp(prefix='albert_yt_')) def finalize(self) -> None: @@ -131,12 +129,6 @@ def finalize(self) -> None: child.unlink() self.temp_dir.rmdir() - def defaultTrigger(self) -> str: - return 'yt ' - - def synopsis(self) -> str: - return 'query' - def handleTriggerQuery(self, query: TriggerQuery) -> None: query_str = query.string.strip() if not query_str: @@ -182,10 +174,10 @@ def handleTriggerQuery(self, query: TriggerQuery) -> None: query.add(item) # Add a link to the *YouTube* page, in case there's more results, including results we didn't include - item = Item( + item = StandardItem( id=f'{md_name}/show_more', text='Show more in browser', - icon=[ICON_PATH], + iconUrls=self.iconUrls, actions=[ Action( f'{md_name}/show_more', From 8efaf89e354a4dd99e04291992b240b47b4ce486 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:26:09 +0200 Subject: [PATCH 170/355] [color] Add extension --- color/__init__.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 color/__init__.py diff --git a/color/__init__.py b/color/__init__.py new file mode 100644 index 00000000..10bfa2f9 --- /dev/null +++ b/color/__init__.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- + +""" +Displays a color parsed from name, which may be in one of these formats: + +* #RGB (each of R, G, and B is a single hex digit) +* #RRGGBB +* #AARRGGBB +* #RRRGGGBBB +* #RRRRGGGGBBBB +* A name from the list of colors defined in the list of SVG color keyword +names provided by the World Wide Web Consortium; for example, "steelblue" +or "gainsboro". + +Note: This extension started as a prototype to test the internal color pixmap +generator. However it may serve as a starting point for people having a real +need for color workflows. PR's welcome. +""" + +from albert import * +from urllib.parse import quote_plus +from string import hexdigits + +md_iid = '2.0' +md_version = '1.0' +md_name = 'Color' +md_description = 'Display color for color codes' +md_license = 'MIT' +md_url = 'https://github.com/albertlauncher/python/color' + + +class Plugin(PluginInstance, GlobalQueryHandler): + + def __init__(self): + GlobalQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='#') + PluginInstance.__init__(self, extensions=[self]) + + def handleGlobalQuery(self, query): + rank_items = [] + s = query.string.strip() + if s: + if s.startswith('#'): # remove hash + s = s[1:] + + # check length and hex + if any([len(s) == l for l in [3, 6, 8, 9, 12]]) and all(c in hexdigits for c in s): + rank_items.append( + RankItem( + StandardItem( + id=md_id, + text=s, + subtext="The color for this code.", + iconUrls=[f"gen:?background=%23{s}"], + ), + 1 + ) + ) + + return rank_items From 09ad279054ba0ddb4f0913fced09e523b6160684 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 02:26:27 +0200 Subject: [PATCH 171/355] [duckduckgo] Add extension --- duckduckgo/__init__.py | 52 +++++++++++++++++ duckduckgo/duckduckgo.svg | 118 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 duckduckgo/__init__.py create mode 100644 duckduckgo/duckduckgo.svg diff --git a/duckduckgo/__init__.py b/duckduckgo/__init__.py new file mode 100644 index 00000000..2f9174e9 --- /dev/null +++ b/duckduckgo/__init__.py @@ -0,0 +1,52 @@ +""" +Inline DuckDuckGo web search using the 'duckduckgo-search' library. +""" + +from albert import * +from pathlib import Path +from duckduckgo_search import DDGS +from itertools import islice +from time import sleep + +md_iid = '2.0' +md_version = '1.0' +md_name = 'DuckDuckGo' +md_description = 'Inline DuckDuckGo web search' +md_url = 'https://github.com/albertlauncher/python/duckduckgo' +md_lib_dependencies = "duckduckgo-search" + + +class Plugin(PluginInstance, TriggerQueryHandler): + + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis="", + defaultTrigger='ddg ') + PluginInstance.__init__(self, extensions=[self]) + self.ddg = DDGS() + self.iconUrls = [f"file:{Path(__file__).parent}/duckduckgo.svg"] + + def handleTriggerQuery(self, query): + + stripped = query.string.strip() + if stripped: + + # dont flood + for number in range(25): + sleep(0.01) + if not query.isValid: + return + + for r in islice(self.ddg.text(stripped, safesearch='off'), 10): + query.add( + StandardItem( + id=md_id, + text=r['title'], + subtext=r['body'], + iconUrls=self.iconUrls, + actions=[Action("open", "Open link", lambda u=r['href']: openUrl(u))] + ) + ) diff --git a/duckduckgo/duckduckgo.svg b/duckduckgo/duckduckgo.svg new file mode 100644 index 00000000..87f27951 --- /dev/null +++ b/duckduckgo/duckduckgo.svg @@ -0,0 +1,118 @@ + + From 2cf4cc1917c2b8907d044fe69265bffe71c6dff1 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 3 Aug 2023 20:48:14 +0200 Subject: [PATCH 172/355] [wiki] Don't fail on lacking language code. Use en. --- wikipedia/__init__.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index b44aac5c..24809292 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -11,7 +11,7 @@ from pathlib import Path md_iid = '2.0' -md_version = "1.9" +md_version = "1.10" md_name = "Wikipedia" md_description = "Search Wikipedia articles" md_license = "BSD-3" @@ -47,7 +47,6 @@ def __init__(self): self.wiki_fb = WikiFallbackHandler() PluginInstance.__init__(self, extensions=[self, self.wiki_fb]) - params = { 'action': 'query', 'meta': 'siteinfo', @@ -56,7 +55,12 @@ def __init__(self): 'format': 'json' } - Plugin.local_lang_code = getdefaultlocale()[0][0:2] + Plugin.local_lang_code = getdefaultlocale()[0] + if Plugin.local_lang_code: + Plugin.local_lang_code = Plugin.local_lang_code[0:2] + else: + Plugin.local_lang_code = 'en' + warning("Failed getting language code. Using 'en'.") get_url = "%s?%s" % (self.baseurl, parse.urlencode(params)) req = request.Request(get_url, headers={'User-Agent': self.user_agent}) @@ -67,15 +71,15 @@ def __init__(self): if self.local_lang_code in languages: self.baseurl = self.baseurl.replace("en", self.local_lang_code) except timeout: - critical('Error getting languages - socket timed out. Defaulting to EN.') + warning('Error getting languages - socket timed out. Defaulting to EN.') except Exception as error: - critical('Error getting languages (%s). Defaulting to EN.' % error) + warning('Error getting languages (%s). Defaulting to EN.' % error) def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: # avoid rate limiting - for number in range(50): + for _ in range(50): sleep(0.01) if not query.isValid: return @@ -99,17 +103,22 @@ def handleTriggerQuery(self, query): title = data[1][i] summary = data[2][i] url = data[3][i] + results.append( + StandardItem( + id=md_id, + text=title, + subtext=summary if summary else url, + iconUrls=self.iconUrls, + actions=[ + Action("open", "Open article on Wikipedia", lambda u=url: openUrl(u)), + Action("copy", "Copy URL to clipboard", lambda u=url: setClipboardText(u)) + ] + ) + ) - results.append(StandardItem(id=md_id, - text=title, - subtext=summary if summary else url, - iconUrls=self.iconUrls, - actions=[ - Action("open", "Open article on Wikipedia", lambda u=url: openUrl(u)), - Action("copy", "Copy URL to clipboard", lambda u=url: setClipboardText(u)) - ])) if not results: results.append(Plugin.createFallbackItem(stripped)) + query.add(results) else: query.add( From 970f98b3f44a3838510526f5c94dbda1ee8b242e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 5 Aug 2023 10:02:11 +0200 Subject: [PATCH 173/355] [emoji] New generic and platform agnostic emoji implementation --- emoji/__init__.py | 182 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 emoji/__init__.py diff --git a/emoji/__init__.py b/emoji/__init__.py new file mode 100644 index 00000000..df6965ec --- /dev/null +++ b/emoji/__init__.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- + +import json +import re +import threading +import urllib.request +from itertools import product +from locale import getdefaultlocale +from pathlib import Path + +from albert import * + +md_iid = '2.0' +md_version = "2.0" +md_name = "Emoji" +md_description = "Find and copy emojis by name" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/master/emoji" + + +class Plugin(PluginInstance, IndexQueryHandler): + + def __init__(self): + IndexQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger=':', + synopsis='') + PluginInstance.__init__(self, extensions=[self]) + self.thread = None + + def finalize(self): + if self.thread.is_alive(): + self.thread.join() + + def updateIndexItems(self): + if self.thread and self.thread.is_alive(): + self.thread.join() + self.thread = threading.Thread(target=self.update_index_items_task) + self.thread.start() + + def update_index_items_task(self): + + def download_file(url: str, path: str) -> bool: + debug(f"Downloading {url}.") + headers = {'User-Agent': 'Mozilla/5.0'} # otherwise github returns html + request = urllib.request.Request(url, headers=headers) + with urllib.request.urlopen(request, timeout=3) as response: + if response.getcode() == 200: + debug(f"Success. Storing to {path}.") + with open(path, 'wb') as file: + file.write(response.read()) + else: + raise RuntimeError(f"Failed to download {url}. Status code: {response.getcode()}") + + def get_fully_qualified_emojis(cache_path: str) -> list: + """Returns fully qualified emoji strings""" + + def convert_to_unicode_char(hex_code: str): + return chr(int(hex_code, 16)) + + def convert_to_unicode_str(hex_codes: str): + hex_list = hex_codes.split() + return ''.join([convert_to_unicode_char(hex_code) for hex_code in hex_list]) + + path = cache_path / 'emoji_list.txt' + if not path.is_file(): + info("Fetching emoji list.") + url = 'https://unicode.org/Public/emoji/latest/emoji-test.txt' + download_file(url, path) + + # components = set() + fully_qualified = [] + + with path.open("r") as f: + + emoji_list_re_str = r""" + ^ + (?P .*\S) + \s*;\s* + (?P \S+) + \s*\#\s* + (?P \S+) + \s* + (?P E\d+.\d+) + \s* + (?P [^:]+) + (?: : \s* (?P .+))? + \n + $ + """ + + line_re = re.compile(emoji_list_re_str, re.VERBOSE) + for line in f: + if match := line_re.match(line): + if match.group("status") == "fully-qualified": + fully_qualified.append(convert_to_unicode_str(match.group("codepoints"))) + + return fully_qualified + + def get_annotations(cache_path: str) -> dict: + + # determine locale + + if lang := getdefaultlocale()[0]: + lang = lang[0:2] + else: + warning("Failed getting locale. There will be no localized emoji aliases.") + lang = 'en' + + # fetch localized cldr annotations 'full' + + path_full = cache_path / 'emoji_annotations_full.json' + if not path_full.is_file(): + url = 'https://raw.githubusercontent.com/unicode-org/cldr-json/main/cldr-json/' \ + 'cldr-annotations-full/annotations/%s/annotations.json' % lang + download_file(url, path_full) + + # fetch localized cldr annotations 'derived' + + path_derived = cache_path / 'emoji_annotations_derived.json' + if not path_derived.is_file(): + url = 'https://raw.githubusercontent.com/unicode-org/cldr-json/main/cldr-json/' \ + 'cldr-annotations-derived-full/annotationsDerived/%s/annotations.json' % lang + download_file(url, path_derived) + + # open, read, parse, merge, return + + with path_full.open("r", encoding='utf-8') as file_full, \ + path_derived.open("r", encoding='utf-8') as file_derived: + json_full = json.load(file_full)['annotations']['annotations'] + json_derived = json.load(file_derived)['annotationsDerived']['annotations'] + return json_full | json_derived + emojis = get_fully_qualified_emojis(self.cacheLocation) + annotations = get_annotations(self.cacheLocation) + + def remove_redundancy(sentences): + sets_of_words = [set(sentence.lower().split()) for sentence in sentences] + unique = [] + for sow, sentence in zip(sets_of_words, sentences): + for other_sow in sets_of_words: + if sow != other_sow: + if all([any([oword.startswith(word) for oword in other_sow]) for word in sow]): + break + else: + unique.append(sentence) + return unique + + index_items = [] + for emoji in emojis: + try: + ann = annotations[emoji] + except KeyError: + try: + non_rgi_emoji = emoji.replace('\uFE0F', '') + ann = annotations[non_rgi_emoji] + except KeyError as e: + debug(f"Found no translation for {e}. Emoji will not be available.") + continue + + title = ann['tts'][0] + aliases = remove_redundancy([title.replace(':', '').replace(',', ''), *ann['default']]) + + item = StandardItem( + id=emoji, + text=title.capitalize(), + subtext=", ".join([a.capitalize() for a in aliases]), + iconUrls=[f"gen:?text={emoji}"], + actions=[ + Action( + "copy", + "Copy to clipboard", + lambda emj=emoji: setClipboardText(emj), + ), + ] + ) + + for alias in aliases: + index_items.append(IndexItem(item=item, string=alias)) + + self.setIndexItems(index_items) From f49f2172da0eb95df70b2975f9ecdb33b85252d4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 5 Aug 2023 16:36:19 +0200 Subject: [PATCH 174/355] [stub] v2.0 Albert.setClipboardTextAndPaste --- albert.pyi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/albert.pyi b/albert.pyi index f9b824bf..969a40aa 100644 --- a/albert.pyi +++ b/albert.pyi @@ -317,6 +317,14 @@ def setClipboardText(text: str=''): """ +def setClipboardTextAndPaste(text: str=''): + """ + Set the system clipboard text and paste to the front-most window + Args: + text: The text used to set the clipboard + """ + + def openUrl(url: str = ''): """ Open an URL using QDesktopServices::openUrl. From 6a561e016e47abf6884edbb69fa869cee49a2084 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 5 Aug 2023 16:38:19 +0200 Subject: [PATCH 175/355] [emoji] Use paste action --- emoji/__init__.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index df6965ec..c8190ea9 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -169,9 +169,12 @@ def remove_redundancy(sentences): iconUrls=[f"gen:?text={emoji}"], actions=[ Action( - "copy", - "Copy to clipboard", - lambda emj=emoji: setClipboardText(emj), + "paste", "Copy and paste to front-most window", + lambda emj=emoji: setClipboardTextAndPaste(emj) + ), + Action( + "copy", "Copy to clipboard", + lambda emj=emoji: setClipboardText(emj) ), ] ) From 30e6d6c3e37cdb1962e9169e7e94f3a5e001440a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20K=C3=A4stner?= Date: Sat, 5 Aug 2023 19:16:05 +0200 Subject: [PATCH 176/355] [pass]: follow symlinks --- pass/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pass/__init__.py b/pass/__init__.py index 97feb71e..9a868c3a 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -76,7 +76,7 @@ def showPasswords(self, query): def getPasswords(self): passwords = [] - for root, dirnames, filenames in os.walk(PASS_DIR): + for root, dirnames, filenames in os.walk(PASS_DIR, followlinks=True): for filename in fnmatch.filter(filenames, "*.gpg"): passwords.append( os.path.join(root, filename.replace(".gpg", "")).replace(PASS_DIR, "") From 75e69801f2d69398f920a71e1f7ec74880e27647 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 8 Aug 2023 16:54:24 +0200 Subject: [PATCH 177/355] [stub] Add missing GQH ctor --- albert.pyi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/albert.pyi b/albert.pyi index 969a40aa..bff1dadb 100644 --- a/albert.pyi +++ b/albert.pyi @@ -268,6 +268,16 @@ class GlobalQuery(ABC): class GlobalQueryHandler(TriggerQueryHandler): """https://albertlauncher.github.io/reference/classalbert_1_1_global_query_handler.html""" + def __init__(self, + id: str, + name: str, + description: str, + synopsis: str = '', + defaultTrigger: str = f'{id} ', + allowTriggerRemap: str = true, + supportsFuzzyMatching: bool = False): + ... + @abstractmethod def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: ... From 99d4d5130a29d00d1565996ff72deda3829a7176 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 8 Aug 2023 16:54:55 +0200 Subject: [PATCH 178/355] [stub] 0.2 add notification --- albert.pyi | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/albert.pyi b/albert.pyi index bff1dadb..ec5130b9 100644 --- a/albert.pyi +++ b/albert.pyi @@ -313,6 +313,12 @@ class IndexQueryHandler(GlobalQueryHandler): ... +class Notification: + + def __init__(self, title: str, subtitle: str = '', text: str = ''): + ... + + def debug(arg: Any):... def info(arg: Any):... def warning(arg: Any):... @@ -361,13 +367,3 @@ def runTerminal(script: str = '', workdir: str = '', close_on_exit: bool = False close_on_exit: Close the terminal on exit. Otherwise exec $SHELL. """ - -def sendTrayNotification(title: str = '', msg: str = '', ms: int = 10000): - """ - Send a tray notification. - Args: - title: The notification title - msg: The notification body - ms: The display time (if supported by the system) - """ - From 675cdec8f9d6e57874808de9510df8b66d1489f6 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 8 Aug 2023 16:58:29 +0200 Subject: [PATCH 179/355] [timer:1.7] use notification, fixes --- timer/__init__.py | 27 +++++++++++---------------- timer/bing.wav | Bin 254670 -> 0 bytes 2 files changed, 11 insertions(+), 16 deletions(-) delete mode 100644 timer/bing.wav diff --git a/timer/__init__.py b/timer/__init__.py index a85e6ee1..02760cd1 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -10,23 +10,22 @@ - `120:` starts a 2 hours timer """ -import subprocess import threading from datetime import timedelta from pathlib import Path -from sys import platform from time import strftime, time, localtime from albert import * md_iid = '2.0' -md_version = "1.6" +md_version = "1.7" md_name = "Timer" md_description = "Set up timers" md_license = "BSD-2" md_url = "https://github.com/albertlauncher/python/tree/master/timer" md_maintainers = ["@manuelschneid3r", "@googol42", "@uztnus"] + class Timer(threading.Timer): def __init__(self, interval, name, callback): @@ -51,6 +50,7 @@ def __init__(self): self.iconUrls = [f"file:{Path(__file__).parent}/time.svg"] self.soundPath = Path(__file__).parent / "bing.wav" self.timers = [] + self.notification = None def finalize(self): for timer in self.timers: @@ -65,15 +65,10 @@ def deleteTimer(self, timer): timer.cancel() def onTimerTimeout(self, timer): - title = 'Timer "%s"' % timer.name if timer.name else 'Timer' - text = "Timed out at %s" % strftime("%X", localtime(timer.end)) - sendTrayNotification(title, text) - - if platform == "linux": - subprocess.Popen(["aplay", self.soundPath]) - elif platform == "darwin": - subprocess.Popen(["afplay", self.soundPath]) - + self.notification = Notification( + title=f"Timer '{timer.name if timer.name else 'Timer'}'", + subtitle=f"Timed out at {strftime('%X', localtime(timer.end))}" + ) self.deleteTimer(timer) def handleTriggerQuery(self, query): @@ -86,7 +81,7 @@ def handleTriggerQuery(self, query): name = args[1] if 1 < len(args) else '' if not all(field.isdigit() or field == '' for field in fields): return StandardItem( - id=self.name(), + id=self.name, text="Invalid input", subtext="Enter a query in the form of '%s[[hours:]minutes:]seconds [name]'" % self.defaultTrigger(), iconUrls=self.iconUrls, @@ -98,7 +93,7 @@ def handleTriggerQuery(self, query): seconds += int(fields[i] if fields[i] else 0)*(60**i) query.add(StandardItem( - id=self.name(), + id=self.name, text=str(timedelta(seconds=seconds)), subtext='Set a timer with name "%s"' % name if name else 'Set a timer', iconUrls=self.iconUrls, @@ -115,11 +110,11 @@ def handleTriggerQuery(self, query): timer_name_with_quotes = '"%s"' % timer.name if timer.name else '' items.append(StandardItem( - id=self.name(), + id=self.name, text='Delete timer %s [%s]' % (timer_name_with_quotes, identifier), subtext="Times out %s" % strftime("%X", localtime(timer.end)), iconUrls=self.iconUrls, - actions=[Action("delete-timer", "Delete timer", lambda timer=timer: self.deleteTimer(timer))] + actions=[Action("delete-timer", "Delete timer", lambda t=timer: self.deleteTimer(t))] )) if items: diff --git a/timer/bing.wav b/timer/bing.wav deleted file mode 100644 index 1e9ef1037d7c1e4fa83e1cc326e41eb71cd916cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 254670 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%0A7n7-QP%*c(q` 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 t=c{?lm+APnvg{PslX$OY$M1jYn696{n;k!XA9 Date: Wed, 9 Aug 2023 07:17:35 +0200 Subject: [PATCH 180/355] [docker] Catch errors. Fail graciously --- docker/__init__.py | 91 +++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/docker/__init__.py b/docker/__init__.py index 547762f2..f925e913 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -8,7 +8,7 @@ from albert import * md_iid = "2.0" -md_version = "1.5" +md_version = "1.6" md_name = "Docker" md_description = "Manage docker images and containers" md_license = "BSD-3" @@ -27,60 +27,61 @@ def __init__(self): defaultTrigger='d ', synopsis='') PluginInstance.__init__(self, extensions=[self]) - self.icon_urls_running = [f"file:{Path(__file__).parent}/running.png"] self.icon_urls_stopped = [f"file:{Path(__file__).parent}/stopped.png"] - self.client = docker.from_env() - if not self.client: - self.client = docker.DockerClient(base_url='unix://var/run/docker.sock') - if not self.client: - raise "Failed to initialize client." + self.client = None def handleGlobalQuery(self, query): rank_items = [] + try: + if not self.client: + self.client = docker.from_env() - for container in self.client.containers.list(all=True): - if query.string in container.name: - # Create dynamic actions - if container.status == 'running': - actions = [Action("stop", "Stop container", lambda c=container: c.stop()), - Action("restart", "Restart container", lambda c=container: c.restart())] - else: - actions = [Action("start", "Start container", lambda c=container: c.start())] - actions.extend([ - Action("logs", "Logs", - lambda c=container.id: runTerminal("docker logs -f %s" % c, close_on_exit=False)), - Action("remove", "Remove (forced, with volumes)", - lambda c=container: c.remove(v=True, force=True)), - Action("copy-id", "Copy id to clipboard", - lambda id=container.id: setClipboardText(id)) - ]) - - rank_items.append(RankItem( - item=StandardItem( - id=container.id, - text="%s (%s)" % (container.name, ", ".join(container.image.tags)), - subtext="Container: %s" % container.id, - iconUrls=self.icon_urls_running if container.status == 'running' else self.icon_urls_stopped, - actions=actions - ), - score=len(query.string)/len(container.name) - )) + for container in self.client.containers.list(all=True): + if query.string in container.name: + # Create dynamic actions + if container.status == 'running': + actions = [Action("stop", "Stop container", lambda c=container: c.stop()), + Action("restart", "Restart container", lambda c=container: c.restart())] + else: + actions = [Action("start", "Start container", lambda c=container: c.start())] + actions.extend([ + Action("logs", "Logs", + lambda c=container.id: runTerminal("docker logs -f %s" % c, close_on_exit=False)), + Action("remove", "Remove (forced, with volumes)", + lambda c=container: c.remove(v=True, force=True)), + Action("copy-id", "Copy id to clipboard", + lambda id=container.id: setClipboardText(id)) + ]) - for image in reversed(self.client.images.list()): - for tag in sorted(image.tags, key=len): # order by resulting score - if query.string in tag: rank_items.append(RankItem( item=StandardItem( - id=image.short_id, - text=", ".join(image.tags), - subtext="Image: %s" % image.id, - iconUrls=self.icon_urls_stopped, - actions=[Action("run", "Run with command: %s" % query.string, - lambda i=image, s=query.string: client.containers.run(i, s)), - Action("rmi", "Remove image", lambda i=image: i.remove())] + id=container.id, + text="%s (%s)" % (container.name, ", ".join(container.image.tags)), + subtext="Container: %s" % container.id, + iconUrls=self.icon_urls_running if container.status == 'running' else self.icon_urls_stopped, + actions=actions ), - score=len(query.string)/len(tag) + score=len(query.string)/len(container.name) )) + for image in reversed(self.client.images.list()): + for tag in sorted(image.tags, key=len): # order by resulting score + if query.string in tag: + rank_items.append(RankItem( + item=StandardItem( + id=image.short_id, + text=", ".join(image.tags), + subtext="Image: %s" % image.id, + iconUrls=self.icon_urls_stopped, + actions=[Action("run", "Run with command: %s" % query.string, + lambda i=image, s=query.string: client.containers.run(i, s)), + Action("rmi", "Remove image", lambda i=image: i.remove())] + ), + score=len(query.string)/len(tag) + )) + except Exception as e: + warning(e) + self.client = None + return rank_items From 2c14265ad1423ae97b1ce1faa55fcc39db77bcc8 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 10 Aug 2023 11:15:27 +0200 Subject: [PATCH 181/355] [stub] Add a note on the attached attributes --- albert.pyi | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/albert.pyi b/albert.pyi index ec5130b9..bb910509 100644 --- a/albert.pyi +++ b/albert.pyi @@ -319,10 +319,20 @@ class Notification: ... -def debug(arg: Any):... -def info(arg: Any):... -def warning(arg: Any):... -def critical(arg: Any):... +def debug(arg: Any): + """Module attached attribute""" + + +def info(arg: Any): + """Module attached attribute""" + + +def warning(arg: Any): + """Module attached attribute""" + + +def critical(arg: Any): + """Module attached attribute""" def setClipboardText(text: str=''): From a97b8ac4f8e7451499756bf947e70a87b62d952e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 10 Aug 2023 11:15:48 +0200 Subject: [PATCH 182/355] [yt] Adopt to the attached logging attributes --- youtube/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube/__init__.py b/youtube/__init__.py index ee6fb6a7..f1b58ec0 100644 --- a/youtube/__init__.py +++ b/youtube/__init__.py @@ -8,7 +8,7 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen -from albert import Action, StandardItem, TriggerQuery, PluginInstance, TriggerQueryHandler, critical, info, openUrl # pylint: disable=import-error +from albert import Action, StandardItem, TriggerQuery, PluginInstance, TriggerQueryHandler, openUrl # pylint: disable=import-error md_iid = '2.0' From 6e785f31bea17aaf450172667060515571e28180 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 12 Aug 2023 20:04:17 +0200 Subject: [PATCH 183/355] [pacman] fix imports --- pacman/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pacman/__init__.py b/pacman/__init__.py index 11e9a841..51cb829d 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -9,7 +9,7 @@ from time import sleep import pathlib -from albert import Action, Item, TriggerQueryHandler, runTerminal, openUrl +from albert import Action, StandardItem, PluginInstance, TriggerQueryHandler, runTerminal, openUrl md_iid = '2.0' md_version = "1.8" From c3b4b33344f71f39cede92eee9a886701ddc2abb Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 12 Aug 2023 21:06:34 +0200 Subject: [PATCH 184/355] [coingecko] Fix crash on initial fetch --- coingecko/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index 328f5e6b..602d0684 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -104,8 +104,7 @@ def finalize(self): self.thread.join() def updateIndexItems(self): - mtime = self.coinCacheFilePath.lstat().st_mtime - if self.coinCacheFilePath.is_file() and mtime > self.mtime: + if self.coinCacheFilePath.is_file() and (mtime := self.coinCacheFilePath.lstat().st_mtime) > self.mtime: self.mtime = mtime with open(self.coinCacheFilePath) as f: self.items.clear() From 1309b21c92ee55a2353bb330842b8b3262b30cbc Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 14 Aug 2023 13:12:33 +0200 Subject: [PATCH 185/355] [timer] Adopt notification api changes --- timer/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/timer/__init__.py b/timer/__init__.py index 02760cd1..ab49cb5c 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -67,7 +67,7 @@ def deleteTimer(self, timer): def onTimerTimeout(self, timer): self.notification = Notification( title=f"Timer '{timer.name if timer.name else 'Timer'}'", - subtitle=f"Timed out at {strftime('%X', localtime(timer.end))}" + body=f"Timed out at {strftime('%X', localtime(timer.end))}" ) self.deleteTimer(timer) From 61a4a678d8f1c32404e6ae0c2d6096ee383a5908 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 14 Aug 2023 14:42:59 +0200 Subject: [PATCH 186/355] [pint,yt] Require maintenance --- {unit_converter => .archive/unit_converter}/__init__.py | 0 {unit_converter => .archive/unit_converter}/icons/currency.svg | 0 {unit_converter => .archive/unit_converter}/icons/current.svg | 0 {unit_converter => .archive/unit_converter}/icons/length.svg | 0 {unit_converter => .archive/unit_converter}/icons/lengthtime.svg | 0 {unit_converter => .archive/unit_converter}/icons/luminosity.svg | 0 {unit_converter => .archive/unit_converter}/icons/mass.svg | 0 .../unit_converter}/icons/printing_unit.svg | 0 {unit_converter => .archive/unit_converter}/icons/substance.svg | 0 {unit_converter => .archive/unit_converter}/icons/temperature.svg | 0 {unit_converter => .archive/unit_converter}/icons/time.svg | 0 .../unit_converter}/icons/unit_converter.svg | 0 {youtube => .archive/youtube}/__init__.py | 0 {youtube => .archive/youtube}/youtube.svg | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename {unit_converter => .archive/unit_converter}/__init__.py (100%) rename {unit_converter => .archive/unit_converter}/icons/currency.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/current.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/length.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/lengthtime.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/luminosity.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/mass.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/printing_unit.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/substance.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/temperature.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/time.svg (100%) rename {unit_converter => .archive/unit_converter}/icons/unit_converter.svg (100%) rename {youtube => .archive/youtube}/__init__.py (100%) rename {youtube => .archive/youtube}/youtube.svg (100%) diff --git a/unit_converter/__init__.py b/.archive/unit_converter/__init__.py similarity index 100% rename from unit_converter/__init__.py rename to .archive/unit_converter/__init__.py diff --git a/unit_converter/icons/currency.svg b/.archive/unit_converter/icons/currency.svg similarity index 100% rename from unit_converter/icons/currency.svg rename to .archive/unit_converter/icons/currency.svg diff --git a/unit_converter/icons/current.svg b/.archive/unit_converter/icons/current.svg similarity index 100% rename from unit_converter/icons/current.svg rename to .archive/unit_converter/icons/current.svg diff --git a/unit_converter/icons/length.svg b/.archive/unit_converter/icons/length.svg similarity index 100% rename from unit_converter/icons/length.svg rename to .archive/unit_converter/icons/length.svg diff --git a/unit_converter/icons/lengthtime.svg b/.archive/unit_converter/icons/lengthtime.svg similarity index 100% rename from unit_converter/icons/lengthtime.svg rename to .archive/unit_converter/icons/lengthtime.svg diff --git a/unit_converter/icons/luminosity.svg b/.archive/unit_converter/icons/luminosity.svg similarity index 100% rename from unit_converter/icons/luminosity.svg rename to .archive/unit_converter/icons/luminosity.svg diff --git a/unit_converter/icons/mass.svg b/.archive/unit_converter/icons/mass.svg similarity index 100% rename from unit_converter/icons/mass.svg rename to .archive/unit_converter/icons/mass.svg diff --git a/unit_converter/icons/printing_unit.svg b/.archive/unit_converter/icons/printing_unit.svg similarity index 100% rename from unit_converter/icons/printing_unit.svg rename to .archive/unit_converter/icons/printing_unit.svg diff --git a/unit_converter/icons/substance.svg b/.archive/unit_converter/icons/substance.svg similarity index 100% rename from unit_converter/icons/substance.svg rename to .archive/unit_converter/icons/substance.svg diff --git a/unit_converter/icons/temperature.svg b/.archive/unit_converter/icons/temperature.svg similarity index 100% rename from unit_converter/icons/temperature.svg rename to .archive/unit_converter/icons/temperature.svg diff --git a/unit_converter/icons/time.svg b/.archive/unit_converter/icons/time.svg similarity index 100% rename from unit_converter/icons/time.svg rename to .archive/unit_converter/icons/time.svg diff --git a/unit_converter/icons/unit_converter.svg b/.archive/unit_converter/icons/unit_converter.svg similarity index 100% rename from unit_converter/icons/unit_converter.svg rename to .archive/unit_converter/icons/unit_converter.svg diff --git a/youtube/__init__.py b/.archive/youtube/__init__.py similarity index 100% rename from youtube/__init__.py rename to .archive/youtube/__init__.py diff --git a/youtube/youtube.svg b/.archive/youtube/youtube.svg similarity index 100% rename from youtube/youtube.svg rename to .archive/youtube/youtube.svg From 4c07be6b386ca95a63e6375004d8628dec343fce Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 18 Aug 2023 12:25:49 +0200 Subject: [PATCH 187/355] [dice_roll] Archived. Maintenance required. --- {dice_roll => .archive/dice_roll}/README.md | 0 {dice_roll => .archive/dice_roll}/__init__.py | 0 {dice_roll => .archive/dice_roll}/icons/d10.svg | 0 {dice_roll => .archive/dice_roll}/icons/d100.svg | 0 {dice_roll => .archive/dice_roll}/icons/d12.svg | 0 {dice_roll => .archive/dice_roll}/icons/d2.svg | 0 {dice_roll => .archive/dice_roll}/icons/d20.svg | 0 {dice_roll => .archive/dice_roll}/icons/d4.svg | 0 {dice_roll => .archive/dice_roll}/icons/d6.svg | 0 {dice_roll => .archive/dice_roll}/icons/d8.svg | 0 {dice_roll => .archive/dice_roll}/icons/dice.svg | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename {dice_roll => .archive/dice_roll}/README.md (100%) rename {dice_roll => .archive/dice_roll}/__init__.py (100%) rename {dice_roll => .archive/dice_roll}/icons/d10.svg (100%) rename {dice_roll => .archive/dice_roll}/icons/d100.svg (100%) rename {dice_roll => .archive/dice_roll}/icons/d12.svg (100%) rename {dice_roll => .archive/dice_roll}/icons/d2.svg (100%) rename {dice_roll => .archive/dice_roll}/icons/d20.svg (100%) rename {dice_roll => .archive/dice_roll}/icons/d4.svg (100%) rename {dice_roll => .archive/dice_roll}/icons/d6.svg (100%) rename {dice_roll => .archive/dice_roll}/icons/d8.svg (100%) rename {dice_roll => .archive/dice_roll}/icons/dice.svg (100%) diff --git a/dice_roll/README.md b/.archive/dice_roll/README.md similarity index 100% rename from dice_roll/README.md rename to .archive/dice_roll/README.md diff --git a/dice_roll/__init__.py b/.archive/dice_roll/__init__.py similarity index 100% rename from dice_roll/__init__.py rename to .archive/dice_roll/__init__.py diff --git a/dice_roll/icons/d10.svg b/.archive/dice_roll/icons/d10.svg similarity index 100% rename from dice_roll/icons/d10.svg rename to .archive/dice_roll/icons/d10.svg diff --git a/dice_roll/icons/d100.svg b/.archive/dice_roll/icons/d100.svg similarity index 100% rename from dice_roll/icons/d100.svg rename to .archive/dice_roll/icons/d100.svg diff --git a/dice_roll/icons/d12.svg b/.archive/dice_roll/icons/d12.svg similarity index 100% rename from dice_roll/icons/d12.svg rename to .archive/dice_roll/icons/d12.svg diff --git a/dice_roll/icons/d2.svg b/.archive/dice_roll/icons/d2.svg similarity index 100% rename from dice_roll/icons/d2.svg rename to .archive/dice_roll/icons/d2.svg diff --git a/dice_roll/icons/d20.svg b/.archive/dice_roll/icons/d20.svg similarity index 100% rename from dice_roll/icons/d20.svg rename to .archive/dice_roll/icons/d20.svg diff --git a/dice_roll/icons/d4.svg b/.archive/dice_roll/icons/d4.svg similarity index 100% rename from dice_roll/icons/d4.svg rename to .archive/dice_roll/icons/d4.svg diff --git a/dice_roll/icons/d6.svg b/.archive/dice_roll/icons/d6.svg similarity index 100% rename from dice_roll/icons/d6.svg rename to .archive/dice_roll/icons/d6.svg diff --git a/dice_roll/icons/d8.svg b/.archive/dice_roll/icons/d8.svg similarity index 100% rename from dice_roll/icons/d8.svg rename to .archive/dice_roll/icons/d8.svg diff --git a/dice_roll/icons/dice.svg b/.archive/dice_roll/icons/dice.svg similarity index 100% rename from dice_roll/icons/dice.svg rename to .archive/dice_roll/icons/dice.svg From 134d26c5a5151f0116542e117fd7cd7c25f015ce Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Fri, 18 Aug 2023 16:17:50 +0300 Subject: [PATCH 188/355] [dice_roll] iid 2.0 --- {.archive/dice_roll => dice_roll}/README.md | 0 {.archive/dice_roll => dice_roll}/__init__.py | 41 +++++++++---------- .../dice_roll => dice_roll}/icons/d10.svg | 0 .../dice_roll => dice_roll}/icons/d100.svg | 0 .../dice_roll => dice_roll}/icons/d12.svg | 0 .../dice_roll => dice_roll}/icons/d2.svg | 0 .../dice_roll => dice_roll}/icons/d20.svg | 0 .../dice_roll => dice_roll}/icons/d4.svg | 0 .../dice_roll => dice_roll}/icons/d6.svg | 0 .../dice_roll => dice_roll}/icons/d8.svg | 0 .../dice_roll => dice_roll}/icons/dice.svg | 0 11 files changed, 20 insertions(+), 21 deletions(-) rename {.archive/dice_roll => dice_roll}/README.md (100%) rename {.archive/dice_roll => dice_roll}/__init__.py (84%) rename {.archive/dice_roll => dice_roll}/icons/d10.svg (100%) rename {.archive/dice_roll => dice_roll}/icons/d100.svg (100%) rename {.archive/dice_roll => dice_roll}/icons/d12.svg (100%) rename {.archive/dice_roll => dice_roll}/icons/d2.svg (100%) rename {.archive/dice_roll => dice_roll}/icons/d20.svg (100%) rename {.archive/dice_roll => dice_roll}/icons/d4.svg (100%) rename {.archive/dice_roll => dice_roll}/icons/d6.svg (100%) rename {.archive/dice_roll => dice_roll}/icons/d8.svg (100%) rename {.archive/dice_roll => dice_roll}/icons/dice.svg (100%) diff --git a/.archive/dice_roll/README.md b/dice_roll/README.md similarity index 100% rename from .archive/dice_roll/README.md rename to dice_roll/README.md diff --git a/.archive/dice_roll/__init__.py b/dice_roll/__init__.py similarity index 84% rename from .archive/dice_roll/__init__.py rename to dice_roll/__init__.py index 5a338b75..95f95031 100644 --- a/.archive/dice_roll/__init__.py +++ b/dice_roll/__init__.py @@ -15,7 +15,7 @@ """ md_iid = '2.0' -md_version = "1.2" +md_version = "1.3" md_name = "Dice Roll" md_description = "Roll any number of dice" md_license = "MIT" @@ -39,7 +39,7 @@ def get_icon_path(num_sides: int | None) -> str: if num_sides is None: icon = "dice" # return the path to the icon - return str("file:" + icons_path / f"{icon}.svg") + return str(f"file:{icons_path / f'{icon}.svg'}") def roll_dice(num_dice: int, num_sides: int) -> tuple[int, list[int]]: @@ -127,29 +127,28 @@ def get_items(query_string: str) -> list[albert.Item]: return results -class Plugin(albert.TriggerQueryHandler): +class Plugin(albert.PluginInstance, albert.TriggerQueryHandler): """A plugin to roll dice""" - def id(self) -> str: - return md_id - - def name(self) -> str: - return md_name - - def description(self) -> str: - return md_description - - def synopsis(self) -> str: - return "d [d ...]" - - def defaultTrigger(self) -> str: - return "roll " - - def handleTriggerQuery(self, query: albert.TriggerQuery) -> None: + def __init__(self): + albert.TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis="d [d ...]", + defaultTrigger="roll ", + ) + albert.PluginInstance.__init__(self, extensions=[self]) + + def handleTriggerQuery(self, query: albert.Query) -> None: query_string = query.string.strip() try: items = get_items(query_string) query.add(items) except Exception as e: - albert.warning(e) - albert.info("Something went wrong. Make sure you're using the correct format.") + query.add([albert.StandardItem( + id="error", + iconUrls=[get_icon_path(None)], + text="Something went wrong.", + subtext="Make sure you're using the correct format.", + )]) diff --git a/.archive/dice_roll/icons/d10.svg b/dice_roll/icons/d10.svg similarity index 100% rename from .archive/dice_roll/icons/d10.svg rename to dice_roll/icons/d10.svg diff --git a/.archive/dice_roll/icons/d100.svg b/dice_roll/icons/d100.svg similarity index 100% rename from .archive/dice_roll/icons/d100.svg rename to dice_roll/icons/d100.svg diff --git a/.archive/dice_roll/icons/d12.svg b/dice_roll/icons/d12.svg similarity index 100% rename from .archive/dice_roll/icons/d12.svg rename to dice_roll/icons/d12.svg diff --git a/.archive/dice_roll/icons/d2.svg b/dice_roll/icons/d2.svg similarity index 100% rename from .archive/dice_roll/icons/d2.svg rename to dice_roll/icons/d2.svg diff --git a/.archive/dice_roll/icons/d20.svg b/dice_roll/icons/d20.svg similarity index 100% rename from .archive/dice_roll/icons/d20.svg rename to dice_roll/icons/d20.svg diff --git a/.archive/dice_roll/icons/d4.svg b/dice_roll/icons/d4.svg similarity index 100% rename from .archive/dice_roll/icons/d4.svg rename to dice_roll/icons/d4.svg diff --git a/.archive/dice_roll/icons/d6.svg b/dice_roll/icons/d6.svg similarity index 100% rename from .archive/dice_roll/icons/d6.svg rename to dice_roll/icons/d6.svg diff --git a/.archive/dice_roll/icons/d8.svg b/dice_roll/icons/d8.svg similarity index 100% rename from .archive/dice_roll/icons/d8.svg rename to dice_roll/icons/d8.svg diff --git a/.archive/dice_roll/icons/dice.svg b/dice_roll/icons/dice.svg similarity index 100% rename from .archive/dice_roll/icons/dice.svg rename to dice_roll/icons/dice.svg From a7cda531d3dc74bb3a3de11ff729421565a54987 Mon Sep 17 00:00:00 2001 From: Peter Oettig Date: Wed, 23 Aug 2023 09:25:16 +0200 Subject: [PATCH 189/355] [jetbrains_projects] Catch FileNotFoundError --- jetbrains_projects/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 9a5258c3..d8dc59f6 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -78,7 +78,7 @@ def _parse_recent_projects(self, recent_projects_file: Path) -> list[Project]: Project(name=Path(project_path).name, path=project_path, last_opened=int(last_opened)) ) return projects - except ElementTree.ParseError: + except (ElementTree.ParseError, FileNotFoundError): return [] From b4563c204e456b3f4f30410f3af60b27a3f8fec3 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 26 Aug 2023 13:29:21 +0200 Subject: [PATCH 190/355] [goldendict] Fix import error Related https://github.com/albertlauncher/plugins/issues/119 --- goldendict/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/goldendict/__init__.py b/goldendict/__init__.py index 6b1aba14..92ef6d95 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -1,4 +1,4 @@ -from albert import Action, Item, TriggerQuery, TriggerQueryHandler, runDetachedProcess # pylint: disable=import-error +from albert import Action, Item, TriggerQuery, PluginInstance, TriggerQueryHandler, runDetachedProcess # pylint: disable=import-error md_iid = '2.0' md_version = '1.3' From 2e57e703faf51de4148366fb65c12f32f930fe3c Mon Sep 17 00:00:00 2001 From: ismail soudi <30784313+ismasou@users.noreply.github.com> Date: Tue, 29 Aug 2023 04:20:42 -0400 Subject: [PATCH 191/355] [mathematica_eval] Fixed missing import --- mathematica_eval/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mathematica_eval/__init__.py b/mathematica_eval/__init__.py index 6bb38c4d..31de13cc 100644 --- a/mathematica_eval/__init__.py +++ b/mathematica_eval/__init__.py @@ -4,8 +4,7 @@ from tempfile import NamedTemporaryFile from threading import Lock -from albert import (Action, Item, TriggerQuery, TriggerQueryHandler, - setClipboardText) +from albert import * md_iid = "2.0" md_version = "1.1" From c9ebe8935725c3c434f460759086921a9f1a46e9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 29 Aug 2023 21:06:03 +0200 Subject: [PATCH 192/355] [stub] Config prototype --- albert.pyi | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/albert.pyi b/albert.pyi index bb910509..b659c7d8 100644 --- a/albert.pyi +++ b/albert.pyi @@ -1,6 +1,6 @@ """ -# Albert Python interface v2.0 +# Albert Python interface v2.1 The Python interface is a subset of the internal C++ interface exposed to Python with some minor adjustments. A Python @@ -90,6 +90,27 @@ class PluginInstance(ABC): def finalize(self): ... + def readConfig(self, key: str, type: type[str|int|float|bool]) -> str|int|float|bool|None: + ... + + def writeConfig(self, key: str, value: str|int|float|bool): + ... + + def configWidget(self): + """ + [ + { + 'type': 'lineedit'|'checkbox'|'spinbox'|'doublespinbox', + 'property_name': '…', + 'display_name': '…', + 'widget_properties': { + 'widget_property': bool|int|float|string, + … + } + }, + … + ] + """ class Action: """https://albertlauncher.github.io/reference/classalbert_1_1_action.html""" From 7bd0931f550ddec795d1c3a3e8a8b2e2faa53981 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 29 Aug 2023 21:09:05 +0200 Subject: [PATCH 193/355] [emoji] Add "Use derived emojis" option --- emoji/__init__.py | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index c8190ea9..fe918e6d 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -10,8 +10,8 @@ from albert import * -md_iid = '2.0' -md_version = "2.0" +md_iid = '2.1' +md_version = "2.1" md_name = "Emoji" md_description = "Find and copy emojis by name" md_license = "MIT" @@ -30,10 +30,33 @@ def __init__(self): PluginInstance.__init__(self, extensions=[self]) self.thread = None + self._use_derived = self.readConfig('use_derived', bool) + if self._use_derived is None: + self._use_derived = False + def finalize(self): if self.thread.is_alive(): self.thread.join() + @property + def use_derived(self): + return self._use_derived + + @use_derived.setter + def use_derived(self, value): + self._use_derived = value + self.writeConfig('use_derived', value) + self.updateIndexItems() + + def configWidget(self): + return [ + { + 'type': 'checkbox', + 'property': 'use_derived', + 'label': 'Use derived emojis' + } + ] + def updateIndexItems(self): if self.thread and self.thread.is_alive(): self.thread.join() @@ -99,7 +122,7 @@ def convert_to_unicode_str(hex_codes: str): return fully_qualified - def get_annotations(cache_path: str) -> dict: + def get_annotations(cache_path: str, use_derived: bool) -> dict: # determine locale @@ -117,6 +140,12 @@ def get_annotations(cache_path: str) -> dict: 'cldr-annotations-full/annotations/%s/annotations.json' % lang download_file(url, path_full) + with path_full.open("r", encoding='utf-8') as file_full: + json_full = json.load(file_full)['annotations']['annotations'] + + if not use_derived: + return json_full + # fetch localized cldr annotations 'derived' path_derived = cache_path / 'emoji_annotations_derived.json' @@ -127,13 +156,12 @@ def get_annotations(cache_path: str) -> dict: # open, read, parse, merge, return - with path_full.open("r", encoding='utf-8') as file_full, \ - path_derived.open("r", encoding='utf-8') as file_derived: - json_full = json.load(file_full)['annotations']['annotations'] + with path_derived.open("r", encoding='utf-8') as file_derived: json_derived = json.load(file_derived)['annotationsDerived']['annotations'] return json_full | json_derived + emojis = get_fully_qualified_emojis(self.cacheLocation) - annotations = get_annotations(self.cacheLocation) + annotations = get_annotations(self.cacheLocation, self.use_derived) def remove_redundancy(sentences): sets_of_words = [set(sentence.lower().split()) for sentence in sentences] @@ -156,7 +184,7 @@ def remove_redundancy(sentences): non_rgi_emoji = emoji.replace('\uFE0F', '') ann = annotations[non_rgi_emoji] except KeyError as e: - debug(f"Found no translation for {e}. Emoji will not be available.") + # debug(f"Found no translation for {e}. Emoji will not be available.") continue title = ann['tts'][0] From 9229b0cce7f92bdbd8bc652bc55b55415d550540 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 30 Aug 2023 08:53:48 +0200 Subject: [PATCH 194/355] [translators] Add "translators" plugin --- translators/__init__.py | 120 +++++++++++++++++++++++++++++++ translators/google_translate.png | Bin 0 -> 51950 bytes 2 files changed, 120 insertions(+) create mode 100644 translators/__init__.py create mode 100644 translators/google_translate.png diff --git a/translators/__init__.py b/translators/__init__.py new file mode 100644 index 00000000..4bc994d8 --- /dev/null +++ b/translators/__init__.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- + +""" +Translates text using the python package translators. See https://pypi.org/project/translators/ +""" + +from locale import getdefaultlocale +from pathlib import Path +from time import sleep + +from albert import * +import translators as ts + +md_iid = '2.0' +md_version = "1.3" +md_name = "Translator" +md_description = "Translate sentences using 'translators' package" +md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/translators" +md_lib_dependencies = "translators" + + +class Plugin(PluginInstance, TriggerQueryHandler): + + def __init__(self): + TriggerQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + synopsis="[[from] to] text", + defaultTrigger='tr ') + PluginInstance.__init__(self, extensions=[self]) + self.iconUrls = [f"file:{Path(__file__).parent}/google_translate.png"] + + self._translator = self.readConfig('translator', str) + if self._translator is None: + self._translator = 'google' + + self._lang = self.readConfig('lang', str) + if self._lang is None: + self._lang = getdefaultlocale()[0][0:2] + + try: + languages = ts.get_languages(self.translator) + self.src_languages = set(languages.keys()) + self.dst_languages = set(languages[self.lang]) + except Exception as e: + warning(str(e)) + + @property + def translator(self): + return self._translator + + @translator.setter + def translator(self, value): + self._translator = value + self.writeConfig('translator', value) + languages = ts.get_languages(self.translator) + self.src_languages = set(languages.keys()) + self.dst_languages = set(languages[self.lang]) + + @property + def lang(self): + return self._lang + + @lang.setter + def lang(self, value): + self._lang = value + self.writeConfig('lang', value) + + def configWidget(self): + return [ + { + 'type': 'combobox', + 'property': 'translator', + 'label': 'Translator', + 'items': ts.translators_pool + }, + { + 'type': 'lineedit', + 'property': 'lang', + 'label': 'Default language', + } + ] + + def handleTriggerQuery(self, query): + stripped = query.string.strip() + if stripped: + for _ in range(50): + sleep(0.01) + if not query.isValid: + return + + if len(splits := stripped.split(maxsplit=2)) == 3 \ + and splits[0] in self.src_languages and splits[1] in self.dst_languages: + src, dst, text = splits + elif len(splits := stripped.split(maxsplit=1)) == 2 and splits[0] in self.src_languages: + src, dst, text = splits[0], self.lang, splits[1] + else: + src, dst, text = 'auto', self.lang, stripped + + translation = ts.translate_text(query_text=text, + translator=self.translator, + from_language=src, + to_language=dst) + + query.add(StandardItem( + id=md_id, + text=translation, + subtext=f"{src.upper()} > {dst.upper()}", + iconUrls=self.iconUrls, + actions=[ + Action( + "paste", "Copy to clipboard and paste to front-most window", + lambda t=translation: setClipboardTextAndPaste(t) + ), + Action("copy", "Copy to clipboard", + lambda t=translation: setClipboardText(t)) + ] + )) diff --git a/translators/google_translate.png b/translators/google_translate.png new file mode 100644 index 0000000000000000000000000000000000000000..63617cf578c9f2b502ea30349dd61b0a7604d8a1 GIT binary patch literal 51950 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
- -``` -Output of `albert -d` when run in a terminal -``` - -
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index bf083087..00000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,14 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Start a discussion - url: https://github.com/orgs/albertlauncher/discussions/new/choose - about: Post the link to the discussion in the chats to get more attention. - - name: Chat on Discord - url: https://discord.gg/t8G2EkvRZh - about: Bridged community chat. - - name: Chat on Telegram - url: https://telegram.me/albert_launcher_community - about: Bridged community chat. - - name: Chat on on IRC (libera#albertlauncher) - url: https://web.libera.chat/#albertlauncher - about: Bridged community chat. From 841bb4afb731500d8e8202896412664edc3ef6f0 Mon Sep 17 00:00:00 2001 From: DavidDeadly Date: Thu, 19 Oct 2023 20:39:43 -0500 Subject: [PATCH 206/355] [bitwarden] 2.0 * add copy-username action * segregate actions callbacks This helps readability and performance. Before password and code subprocesses were running for each filtered_password. Now they only run when the user requests it. * enhance filter_items readability * remove 'Unlock' item in favor of 'Sync' 'Unlock' item is unncesary because rbw binary by default asks for the master password on any action, like listing (__get_items). The only reason maybe to use it before might probably be to sync with the cloud items, and that can be done via 'rbw sync'. * rename actions methods --- bitwarden/__init__.py | 175 +++++++++++++++++++++++++----------------- 1 file changed, 103 insertions(+), 72 deletions(-) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 78d39f51..23b8bcdc 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = '2.0' -md_version = "1.3" +md_iid = '2.1' +md_version = "2.0" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" md_license = "BSD-3" @@ -27,79 +27,28 @@ def __init__(self): PluginInstance.__init__(self, extensions=[self]) self.iconUrls = [f"file:{Path(__file__).parent}/bw.svg"] - def _get_passwords(self): - field_names = ["id", "name", "user", "folder"] - p = run( - ["rbw", "list", "--fields", ",".join(field_names)], - capture_output=True, - encoding="utf-8", - check=True, - ) - passwords = [] - for l in p.stdout.splitlines(): - fields = l.split("\t") - d = dict(zip(field_names, fields)) - if d["folder"]: - d["path"] = d["folder"] + "/" + d["name"] - else: - d["path"] = d["name"] - passwords.append(d) - - return passwords - def handleTriggerQuery(self, query): - if query.string.strip().lower() == "unlock": + if query.string.strip().lower() == "sync": query.add( StandardItem( - id="unlock", - text="Unlock Bitwarden Vault", + id="sync", + text="Sync Bitwarden Vault", iconUrls=self.iconUrls, actions=[ Action( - id="unlock", - text="Unlocking Bitwarden Vault", - callable=lambda: runTerminal( - script="rbw stop-agent && rbw unlock", - close_on_exit=True + id="sync", + text="Syncing Bitwarden Vault", + callable=lambda: run( + ["rbw", "sync"], ) ) ] ) ) - passwords = self._get_passwords() - filtered_passwords = [] - search_fields = ["path", "user"] - words = query.string.strip().lower().split() - for p in passwords: - all_matches = True - for w in words: - for k in search_fields: - if w in p[k].lower(): - break - else: - all_matches = False - break - - if all_matches: - filtered_passwords.append(p) + filtered_items = self._filter_items(query) - for p in filtered_passwords: - pw = run( - ["rbw", "get", p["id"]], - capture_output=True, - encoding="utf-8", - check=True - ) - try: - code = run( - ["rbw", "code", p["id"]], - capture_output=True, - encoding="utf-8", - check=True - ) - except CalledProcessError as err: - code = run (["echo"], capture_output=True,encoding="utf-8", check=True) + for p in filtered_items: query.add( StandardItem( id=p["id"], @@ -110,24 +59,106 @@ def handleTriggerQuery(self, query): Action( id="copy", text="Copy password to clipboard", - callable=lambda password=pw.stdout.strip(): setClipboardText( - text=password) + callable=lambda item=p: self._password_to_clipboard(item) ), Action( id="copy-auth", text="Copy auth code to clipboard", - callable=lambda code=code.stdout.strip(): setClipboardText( - text=code) + callable=lambda item=p: self._code_to_clipboard(item) + ), + Action( + id="copy-username", + text="Copy username to clipboard", + callable=lambda username=p["user"]: + setClipboardText(text=username) ), Action( id="edit", text="Edit entry in terminal", - callable=lambda pid=p['id']: runTerminal( - script=f"rbw edit {pid}", - workdir="~", - close_on_exit=False - ) + callable=lambda item=p: self._edit_entry(item) ) ] ) - ) \ No newline at end of file + ) + + def _get_items(self): + field_names = ["id", "name", "user", "folder"] + raw_items = run( + ["rbw", "list", "--fields", ",".join(field_names)], + capture_output=True, + encoding="utf-8", + check=True, + ) + + items = [] + + for line in raw_items.stdout.splitlines(): + fields = line.split("\t") + item = dict(zip(field_names, fields)) + + if item["folder"]: + item["path"] = item["folder"] + "/" + item["name"] + else: + item["path"] = item["name"] + items.append(item) + + return items + + def _filter_items(self, query): + passwords = self._get_items() + search_fields = ["path", "user"] + # Use a set for faster membership tests + words = set(query.string.strip().lower().split()) + + filtered_passwords = [] + + for p in passwords: + match_all_words_with_any_field = all( + any(word in p[field].lower() for field in search_fields) + for word in words + ) + + if match_all_words_with_any_field: + filtered_passwords.append(p) + + return filtered_passwords + + def _password_to_clipboard(self, item): + id = item["id"] + + password = run( + ["rbw", "get", id], + capture_output=True, + encoding="utf-8", + check=True + ).stdout.strip() + + setClipboardText(text=password) + + def _code_to_clipboard(self, item): + id = item["id"] + + try: + code = run( + ["rbw", "code", id], + capture_output=True, + encoding="utf-8", + check=True + ).stdout.strip() + except CalledProcessError as err: + code = run( + ["echo", err.__str__()], + capture_output=True, + encoding="utf-8", + check=True + ).stdout.strip() + + setClipboardText(text=code) + + def _edit_entry(self, item): + id = item["id"] + + runTerminal( + script=f"rbw edit {id}", + close_on_exit=True + ) From 9310a97eeafd87e582a69ad24afc836a62325372 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 25 Nov 2023 20:23:16 +0100 Subject: [PATCH 207/355] [awiki:1.5] Fix search fallback --- arch_wiki/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index cc70f54e..a1b243be 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -8,7 +8,7 @@ from albert import * md_iid = '2.0' -md_version = "1.4" +md_version = "1.5" md_name = "ArchLinux Wiki" md_description = "Search ArchLinux Wiki articles" md_license = "BSD-3" @@ -75,7 +75,8 @@ def handleTriggerQuery(self, query): text="Search '%s'" % query.string, subtext="No results. Start online search on Arch Wiki", iconUrls=self.iconUrls, - actions=[Action("search", "Open search", lambda s=query.string: self.search_url % s)])) + actions=[Action("search", "Open search", + lambda s=query.string: openUrl(self.search_url % s))])) else: query.add(StandardItem(id=md_id, From 2067bbb3d8fa5cfa5df2be9cada29a7e6715f07a Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 26 Nov 2023 02:17:06 +0100 Subject: [PATCH 208/355] [translator:1.4] Add timeout --- translators/__init__.py | 53 +++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/translators/__init__.py b/translators/__init__.py index 3f1f9b3d..dbcac7b5 100644 --- a/translators/__init__.py +++ b/translators/__init__.py @@ -12,7 +12,7 @@ import translators as ts md_iid = '2.0' -md_version = "1.3" +md_version = "1.4" md_name = "Translator" md_description = "Translate sentences using 'translators' package" md_license = "BSD-3" @@ -99,22 +99,35 @@ def handleTriggerQuery(self, query): else: src, dst, text = 'auto', self.lang, stripped - translation = ts.translate_text(query_text=text, - translator=self.translator, - from_language=src, - to_language=dst) - - query.add(StandardItem( - id=md_id, - text=translation, - subtext=f"{src.upper()} > {dst.upper()}", - iconUrls=self.iconUrls, - actions=[ - Action( - "paste", "Copy to clipboard and paste to front-most window", - lambda t=translation: setClipboardTextAndPaste(t) - ), - Action("copy", "Copy to clipboard", - lambda t=translation: setClipboardText(t)) - ] - )) + try: + translation = ts.translate_text(query_text=text, + translator=self.translator, + from_language=src, + to_language=dst, + timeout=5) + + query.add(StandardItem( + id=md_id, + text=translation, + subtext=f"{src.upper()} > {dst.upper()}", + iconUrls=self.iconUrls, + actions=[ + Action( + "paste", "Copy to clipboard and paste to front-most window", + lambda t=translation: setClipboardTextAndPaste(t) + ), + Action("copy", "Copy to clipboard", + lambda t=translation: setClipboardText(t)) + ] + )) + + except Exception as e: + + query.add(StandardItem( + id=md_id, + text="Error", + subtext=str(e), + iconUrls=self.iconUrls + )) + + warning(str(e)) \ No newline at end of file From 7f3bb83644a3a211405a3c62b3edf1f26e930318 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 28 Dec 2023 15:16:01 +0100 Subject: [PATCH 209/355] [pacman:1.9] Fix pgk site url --- pacman/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pacman/__init__.py b/pacman/__init__.py index 51cb829d..856b7c77 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -12,7 +12,7 @@ from albert import Action, StandardItem, PluginInstance, TriggerQueryHandler, runTerminal, openUrl md_iid = '2.0' -md_version = "1.8" +md_version = "1.9" md_name = "PacMan" md_description = "Search, install and remove packages" md_license = "BSD-3" @@ -87,8 +87,9 @@ def handleTriggerQuery(self, query): ]) else: actions.append(Action("inst", "Install", lambda n=pkg_name: runTerminal("sudo pacman -S %s" % n))) + actions.append(Action("pkg_url", "Show on packages.archlinux.org", - lambda r=pkg_repo, n=pkg_name: openUrl(f"{r}/x86_64/{n}/"))) + lambda r=pkg_repo, n=pkg_name: openUrl(f"{self.pkgs_url}{r}/x86_64/{n}/"))) if pkg_purl: actions.append(Action("proj_url", "Show project website", lambda u=pkg_purl: openUrl(u))) From f12ef96656be340283a20b00d36a212eb57d754b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 28 Dec 2023 22:46:17 +0100 Subject: [PATCH 210/355] =?UTF-8?q?[inhibit=5Fsleep:1.0]=20Similar=20to=20?= =?UTF-8?q?caffeine,=20theine,=20amphetamine=20etc=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inhibit_sleep/__init__.py | 63 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 inhibit_sleep/__init__.py diff --git a/inhibit_sleep/__init__.py b/inhibit_sleep/__init__.py new file mode 100644 index 00000000..c5f56427 --- /dev/null +++ b/inhibit_sleep/__init__.py @@ -0,0 +1,63 @@ +""" +Provides an item 'Inhibit sleep' which can be used to temporarily disable system suspension. + +This is a prototype using `systemd-inhibit`. A sophisticated implementation would probably use the systemd D-Bus +interface documented [here](https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html). +""" + +from albert import * +from subprocess import Popen, TimeoutExpired + +md_iid = '2.0' +md_version = '1.0' +md_name = 'Inhibit sleep' +md_description = 'Inhibit system sleep mode.' +md_url = 'https://github.com/albertlauncher/python/inhibit_sleep' +md_bin_dependencies = ['systemd-inhibit', "sleep"] + + +class Plugin(PluginInstance, GlobalQueryHandler): + + def __init__(self): + GlobalQueryHandler.__init__(self, + id=md_id, + name=md_name, + description=md_description, + defaultTrigger='is ') + PluginInstance.__init__(self, extensions=[self]) + self.proc = None + + def finalize(self): + if self.proc: + self.toggle() + + def toggle(self): + if self.proc: + self.proc.terminate() + try: + self.proc.wait(timeout=1) + except TimeoutExpired: + self.proc.kill() + self.proc = None + else: + self.proc = Popen(["systemd-inhibit", + "--what=idle:sleep", "--who=Albert", "--why=User", + "sleep", "infinity"]) + info(str(self.proc)) + + def handleGlobalQuery(self, query: GlobalQuery): + stripped = query.string.strip().lower() + if stripped in "inhibit sleep": + return [ + RankItem( + StandardItem( + id=md_name, + text=md_name, + subtext=f"{'Enable' if self.proc else 'Disable'} sleep mode", + iconUrls=[f"gen:?text=💤"], + actions=[Action("inhibit", "Toggle", self.toggle)] + ), + len(stripped)/len(md_name)) + + ] + return [] From 3a22cb4e684fdb7506363be73c93573224719a4b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 29 Dec 2023 13:53:47 +0100 Subject: [PATCH 211/355] Update albert.pyi --- albert.pyi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/albert.pyi b/albert.pyi index a105ec78..787ec318 100644 --- a/albert.pyi +++ b/albert.pyi @@ -19,7 +19,8 @@ md_description: str | A brief, imperative description. (Like "Launch apps" or "O ## Optional metadata variables: -md_id | Identifier overwrite. [a-zA-Z0-9_]. Defaults to module name. +md_id | Identifier overwrite. [a-zA-Z0-9_]. Note: This variable is attached at runtime + | if it is unset and defaults to the module name. __doc__ | The docstring of the module is used as long description/readme of the extension. md_license: str | Short form e.g. BSD-2-Clause or GPL-3.0 md_url: str | Browsable source, issues etc @@ -35,8 +36,7 @@ The plugin class is the entry point for a Python plugin. It is instantiated on p PluginInstance. Implement extensions by subclassing _one_ extension class (TriggerQueryHandler etc…) provided by the built-in `albert` module and pass the list of your extensions to the PluginInstance init function. Due to the differences in type systems multiple inheritance of extensions is not supported. (Python does not support virtual -inheritance, which is used in the C++ space to inherit from 'Extension'). For more details see - +inheritance, which is used in the C++ space to inherit from 'Extension'). """ From f59426454c683904b61c9bd379c00930319dbf86 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 29 Dec 2023 14:51:47 +0100 Subject: [PATCH 212/355] Update README.md --- README.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 81e3ce5b..d6802f24 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,23 @@ -### This is the official repository for python plugins. +## Official Albert Python plugin repository -This repository is shipped with albert. If you want to have bleeding edge plugins or share your work clone the repository. Check the [docs on Python plugins](https://github.com/albertlauncher/plugins/blob/master/python/README.md). To install the plugins in user space type the following in your terminal: - -```shell -git clone https://github.com/albertlauncher/python.git ~/.local/share/albert/python/plugins -``` - -Credits go to our contributors +This repository is shipped with Albert. Credits go to our contributors 👍 + +### Contribution + +* Fork this repository. +* Clone it into the Python user plugin location. + ```shell + # on linux + git clone https://github.com//python.git ~/.local/share/albert/python/plugins + + # on macos + git clone https://github.com//python.git ~/Library/Application\ Support/albert/python/plugins + ``` +* Open the directory in your favorite IDE (PyCharmCE is a good choice). +* Write your plugin (Make sure it is upstream-polished-enough though). + This repository ships a [python stub file](https://github.com/albertlauncher/python/blob/master/albert.pyi) which gives you coding assistance. +* Commit, push, send a PR. From f7114926c9a5ccee0e48b9387061fd10652a1370 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 13 Jan 2024 12:21:38 +0100 Subject: [PATCH 213/355] Licensing has to be clearified --- {arch_wiki => licensing/arch_wiki}/__init__.py | 0 {arch_wiki => licensing/arch_wiki}/arch.svg | 4 ---- {aur => licensing/aur}/__init__.py | 0 {aur => licensing/aur}/arch.svg | 4 ---- {bitwarden => licensing/bitwarden}/__init__.py | 0 {bitwarden => licensing/bitwarden}/bw.svg | 0 {coingecko => licensing/coingecko}/__init__.py | 0 {coingecko => licensing/coingecko}/coingecko.png | Bin {color => licensing/color}/__init__.py | 0 {copyq => licensing/copyq}/__init__.py | 0 {dice_roll => licensing/dice_roll}/README.md | 0 {dice_roll => licensing/dice_roll}/__init__.py | 0 {dice_roll => licensing/dice_roll}/icons/d10.svg | 0 {dice_roll => licensing/dice_roll}/icons/d100.svg | 0 {dice_roll => licensing/dice_roll}/icons/d12.svg | 0 {dice_roll => licensing/dice_roll}/icons/d2.svg | 0 {dice_roll => licensing/dice_roll}/icons/d20.svg | 0 {dice_roll => licensing/dice_roll}/icons/d4.svg | 0 {dice_roll => licensing/dice_roll}/icons/d6.svg | 0 {dice_roll => licensing/dice_roll}/icons/d8.svg | 0 {dice_roll => licensing/dice_roll}/icons/dice.svg | 0 {docker => licensing/docker}/__init__.py | 0 {docker => licensing/docker}/running.png | Bin {docker => licensing/docker}/stopped.png | Bin {duckduckgo => licensing/duckduckgo}/__init__.py | 0 {duckduckgo => licensing/duckduckgo}/duckduckgo.svg | 0 {emoji => licensing/emoji}/__init__.py | 0 {goldendict => licensing/goldendict}/__init__.py | 0 .../jetbrains_projects}/LICENSE | 0 .../jetbrains_projects}/README.md | 0 .../jetbrains_projects}/__init__.py | 1 + .../jetbrains_projects}/androidstudio.svg | 0 .../jetbrains_projects}/clion.svg | 0 .../jetbrains_projects}/datagrip.svg | 0 .../jetbrains_projects}/dataspell.svg | 0 .../jetbrains_projects}/goland.svg | 0 .../jetbrains_projects}/idea.svg | 0 .../jetbrains_projects}/phpstorm.svg | 0 .../jetbrains_projects}/pycharm.svg | 0 .../jetbrains_projects}/rider.svg | 0 .../jetbrains_projects}/rubymine.svg | 0 .../jetbrains_projects}/rustrover.svg | 0 .../jetbrains_projects}/webstorm.svg | 0 {kill => licensing/kill}/__init__.py | 0 {locate => licensing/locate}/__init__.py | 0 {locate => licensing/locate}/locate.svg | 0 .../mathematica_eval}/__init__.py | 0 {pacman => licensing/pacman}/__init__.py | 0 {pacman => licensing/pacman}/arch.svg | 4 ---- {pass => licensing/pass}/__init__.py | 0 {pomodoro => licensing/pomodoro}/__init__.py | 0 {pomodoro => licensing/pomodoro}/pomodoro.svg | 4 ---- {python_eval => licensing/python_eval}/__init__.py | 0 {python_eval => licensing/python_eval}/python.svg | 0 .../tex_to_unicode}/__init__.py | 0 .../tex_to_unicode}/tex.png | Bin {timer => licensing/timer}/__init__.py | 0 {timer => licensing/timer}/time.svg | 4 ---- {translators => licensing/translators}/__init__.py | 0 .../translators}/google_translate.png | Bin {virtualbox => licensing/virtualbox}/__init__.py | 0 {vpn => licensing/vpn}/__init__.py | 0 {wikipedia => licensing/wikipedia}/__init__.py | 0 {wikipedia => licensing/wikipedia}/wikipedia.png | Bin {zeal => licensing/zeal}/__init__.py | 0 65 files changed, 1 insertion(+), 20 deletions(-) rename {arch_wiki => licensing/arch_wiki}/__init__.py (100%) rename {arch_wiki => licensing/arch_wiki}/arch.svg (97%) rename {aur => licensing/aur}/__init__.py (100%) rename {aur => licensing/aur}/arch.svg (97%) rename {bitwarden => licensing/bitwarden}/__init__.py (100%) rename {bitwarden => licensing/bitwarden}/bw.svg (100%) rename {coingecko => licensing/coingecko}/__init__.py (100%) rename {coingecko => licensing/coingecko}/coingecko.png (100%) rename {color => licensing/color}/__init__.py (100%) rename {copyq => licensing/copyq}/__init__.py (100%) rename {dice_roll => licensing/dice_roll}/README.md (100%) rename {dice_roll => licensing/dice_roll}/__init__.py (100%) rename {dice_roll => licensing/dice_roll}/icons/d10.svg (100%) rename {dice_roll => licensing/dice_roll}/icons/d100.svg (100%) rename {dice_roll => licensing/dice_roll}/icons/d12.svg (100%) rename {dice_roll => licensing/dice_roll}/icons/d2.svg (100%) rename {dice_roll => licensing/dice_roll}/icons/d20.svg (100%) rename {dice_roll => licensing/dice_roll}/icons/d4.svg (100%) rename {dice_roll => licensing/dice_roll}/icons/d6.svg (100%) rename {dice_roll => licensing/dice_roll}/icons/d8.svg (100%) rename {dice_roll => licensing/dice_roll}/icons/dice.svg (100%) rename {docker => licensing/docker}/__init__.py (100%) rename {docker => licensing/docker}/running.png (100%) rename {docker => licensing/docker}/stopped.png (100%) rename {duckduckgo => licensing/duckduckgo}/__init__.py (100%) rename {duckduckgo => licensing/duckduckgo}/duckduckgo.svg (100%) rename {emoji => licensing/emoji}/__init__.py (100%) rename {goldendict => licensing/goldendict}/__init__.py (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/LICENSE (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/README.md (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/__init__.py (99%) rename {jetbrains_projects => licensing/jetbrains_projects}/androidstudio.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/clion.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/datagrip.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/dataspell.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/goland.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/idea.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/phpstorm.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/pycharm.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/rider.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/rubymine.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/rustrover.svg (100%) rename {jetbrains_projects => licensing/jetbrains_projects}/webstorm.svg (100%) rename {kill => licensing/kill}/__init__.py (100%) rename {locate => licensing/locate}/__init__.py (100%) rename {locate => licensing/locate}/locate.svg (100%) rename {mathematica_eval => licensing/mathematica_eval}/__init__.py (100%) rename {pacman => licensing/pacman}/__init__.py (100%) rename {pacman => licensing/pacman}/arch.svg (97%) rename {pass => licensing/pass}/__init__.py (100%) rename {pomodoro => licensing/pomodoro}/__init__.py (100%) rename {pomodoro => licensing/pomodoro}/pomodoro.svg (97%) rename {python_eval => licensing/python_eval}/__init__.py (100%) rename {python_eval => licensing/python_eval}/python.svg (100%) rename {tex_to_unicode => licensing/tex_to_unicode}/__init__.py (100%) rename {tex_to_unicode => licensing/tex_to_unicode}/tex.png (100%) rename {timer => licensing/timer}/__init__.py (100%) rename {timer => licensing/timer}/time.svg (99%) rename {translators => licensing/translators}/__init__.py (100%) rename {translators => licensing/translators}/google_translate.png (100%) rename {virtualbox => licensing/virtualbox}/__init__.py (100%) rename {vpn => licensing/vpn}/__init__.py (100%) rename {wikipedia => licensing/wikipedia}/__init__.py (100%) rename {wikipedia => licensing/wikipedia}/wikipedia.png (100%) rename {zeal => licensing/zeal}/__init__.py (100%) diff --git a/arch_wiki/__init__.py b/licensing/arch_wiki/__init__.py similarity index 100% rename from arch_wiki/__init__.py rename to licensing/arch_wiki/__init__.py diff --git a/arch_wiki/arch.svg b/licensing/arch_wiki/arch.svg similarity index 97% rename from arch_wiki/arch.svg rename to licensing/arch_wiki/arch.svg index 61f55ed9..b95bef86 100644 --- a/arch_wiki/arch.svg +++ b/licensing/arch_wiki/arch.svg @@ -1,5 +1 @@ - - \ No newline at end of file diff --git a/aur/__init__.py b/licensing/aur/__init__.py similarity index 100% rename from aur/__init__.py rename to licensing/aur/__init__.py diff --git a/aur/arch.svg b/licensing/aur/arch.svg similarity index 97% rename from aur/arch.svg rename to licensing/aur/arch.svg index 61f55ed9..b95bef86 100644 --- a/aur/arch.svg +++ b/licensing/aur/arch.svg @@ -1,5 +1 @@ - - \ No newline at end of file diff --git a/bitwarden/__init__.py b/licensing/bitwarden/__init__.py similarity index 100% rename from bitwarden/__init__.py rename to licensing/bitwarden/__init__.py diff --git a/bitwarden/bw.svg b/licensing/bitwarden/bw.svg similarity index 100% rename from bitwarden/bw.svg rename to licensing/bitwarden/bw.svg diff --git a/coingecko/__init__.py b/licensing/coingecko/__init__.py similarity index 100% rename from coingecko/__init__.py rename to licensing/coingecko/__init__.py diff --git a/coingecko/coingecko.png b/licensing/coingecko/coingecko.png similarity index 100% rename from coingecko/coingecko.png rename to licensing/coingecko/coingecko.png diff --git a/color/__init__.py b/licensing/color/__init__.py similarity index 100% rename from color/__init__.py rename to licensing/color/__init__.py diff --git a/copyq/__init__.py b/licensing/copyq/__init__.py similarity index 100% rename from copyq/__init__.py rename to licensing/copyq/__init__.py diff --git a/dice_roll/README.md b/licensing/dice_roll/README.md similarity index 100% rename from dice_roll/README.md rename to licensing/dice_roll/README.md diff --git a/dice_roll/__init__.py b/licensing/dice_roll/__init__.py similarity index 100% rename from dice_roll/__init__.py rename to licensing/dice_roll/__init__.py diff --git a/dice_roll/icons/d10.svg b/licensing/dice_roll/icons/d10.svg similarity index 100% rename from dice_roll/icons/d10.svg rename to licensing/dice_roll/icons/d10.svg diff --git a/dice_roll/icons/d100.svg b/licensing/dice_roll/icons/d100.svg similarity index 100% rename from dice_roll/icons/d100.svg rename to licensing/dice_roll/icons/d100.svg diff --git a/dice_roll/icons/d12.svg b/licensing/dice_roll/icons/d12.svg similarity index 100% rename from dice_roll/icons/d12.svg rename to licensing/dice_roll/icons/d12.svg diff --git a/dice_roll/icons/d2.svg b/licensing/dice_roll/icons/d2.svg similarity index 100% rename from dice_roll/icons/d2.svg rename to licensing/dice_roll/icons/d2.svg diff --git a/dice_roll/icons/d20.svg b/licensing/dice_roll/icons/d20.svg similarity index 100% rename from dice_roll/icons/d20.svg rename to licensing/dice_roll/icons/d20.svg diff --git a/dice_roll/icons/d4.svg b/licensing/dice_roll/icons/d4.svg similarity index 100% rename from dice_roll/icons/d4.svg rename to licensing/dice_roll/icons/d4.svg diff --git a/dice_roll/icons/d6.svg b/licensing/dice_roll/icons/d6.svg similarity index 100% rename from dice_roll/icons/d6.svg rename to licensing/dice_roll/icons/d6.svg diff --git a/dice_roll/icons/d8.svg b/licensing/dice_roll/icons/d8.svg similarity index 100% rename from dice_roll/icons/d8.svg rename to licensing/dice_roll/icons/d8.svg diff --git a/dice_roll/icons/dice.svg b/licensing/dice_roll/icons/dice.svg similarity index 100% rename from dice_roll/icons/dice.svg rename to licensing/dice_roll/icons/dice.svg diff --git a/docker/__init__.py b/licensing/docker/__init__.py similarity index 100% rename from docker/__init__.py rename to licensing/docker/__init__.py diff --git a/docker/running.png b/licensing/docker/running.png similarity index 100% rename from docker/running.png rename to licensing/docker/running.png diff --git a/docker/stopped.png b/licensing/docker/stopped.png similarity index 100% rename from docker/stopped.png rename to licensing/docker/stopped.png diff --git a/duckduckgo/__init__.py b/licensing/duckduckgo/__init__.py similarity index 100% rename from duckduckgo/__init__.py rename to licensing/duckduckgo/__init__.py diff --git a/duckduckgo/duckduckgo.svg b/licensing/duckduckgo/duckduckgo.svg similarity index 100% rename from duckduckgo/duckduckgo.svg rename to licensing/duckduckgo/duckduckgo.svg diff --git a/emoji/__init__.py b/licensing/emoji/__init__.py similarity index 100% rename from emoji/__init__.py rename to licensing/emoji/__init__.py diff --git a/goldendict/__init__.py b/licensing/goldendict/__init__.py similarity index 100% rename from goldendict/__init__.py rename to licensing/goldendict/__init__.py diff --git a/jetbrains_projects/LICENSE b/licensing/jetbrains_projects/LICENSE similarity index 100% rename from jetbrains_projects/LICENSE rename to licensing/jetbrains_projects/LICENSE diff --git a/jetbrains_projects/README.md b/licensing/jetbrains_projects/README.md similarity index 100% rename from jetbrains_projects/README.md rename to licensing/jetbrains_projects/README.md diff --git a/jetbrains_projects/__init__.py b/licensing/jetbrains_projects/__init__.py similarity index 99% rename from jetbrains_projects/__init__.py rename to licensing/jetbrains_projects/__init__.py index e461c7e6..8c66640e 100644 --- a/jetbrains_projects/__init__.py +++ b/licensing/jetbrains_projects/__init__.py @@ -22,6 +22,7 @@ md_license = "GPL-3" md_url = "https://github.com/albertlauncher/python/" md_maintainers = ["@mqus", "@tomsquest"] +md_authors = ["@mqus", "@tomsquest"] @dataclass diff --git a/jetbrains_projects/androidstudio.svg b/licensing/jetbrains_projects/androidstudio.svg similarity index 100% rename from jetbrains_projects/androidstudio.svg rename to licensing/jetbrains_projects/androidstudio.svg diff --git a/jetbrains_projects/clion.svg b/licensing/jetbrains_projects/clion.svg similarity index 100% rename from jetbrains_projects/clion.svg rename to licensing/jetbrains_projects/clion.svg diff --git a/jetbrains_projects/datagrip.svg b/licensing/jetbrains_projects/datagrip.svg similarity index 100% rename from jetbrains_projects/datagrip.svg rename to licensing/jetbrains_projects/datagrip.svg diff --git a/jetbrains_projects/dataspell.svg b/licensing/jetbrains_projects/dataspell.svg similarity index 100% rename from jetbrains_projects/dataspell.svg rename to licensing/jetbrains_projects/dataspell.svg diff --git a/jetbrains_projects/goland.svg b/licensing/jetbrains_projects/goland.svg similarity index 100% rename from jetbrains_projects/goland.svg rename to licensing/jetbrains_projects/goland.svg diff --git a/jetbrains_projects/idea.svg b/licensing/jetbrains_projects/idea.svg similarity index 100% rename from jetbrains_projects/idea.svg rename to licensing/jetbrains_projects/idea.svg diff --git a/jetbrains_projects/phpstorm.svg b/licensing/jetbrains_projects/phpstorm.svg similarity index 100% rename from jetbrains_projects/phpstorm.svg rename to licensing/jetbrains_projects/phpstorm.svg diff --git a/jetbrains_projects/pycharm.svg b/licensing/jetbrains_projects/pycharm.svg similarity index 100% rename from jetbrains_projects/pycharm.svg rename to licensing/jetbrains_projects/pycharm.svg diff --git a/jetbrains_projects/rider.svg b/licensing/jetbrains_projects/rider.svg similarity index 100% rename from jetbrains_projects/rider.svg rename to licensing/jetbrains_projects/rider.svg diff --git a/jetbrains_projects/rubymine.svg b/licensing/jetbrains_projects/rubymine.svg similarity index 100% rename from jetbrains_projects/rubymine.svg rename to licensing/jetbrains_projects/rubymine.svg diff --git a/jetbrains_projects/rustrover.svg b/licensing/jetbrains_projects/rustrover.svg similarity index 100% rename from jetbrains_projects/rustrover.svg rename to licensing/jetbrains_projects/rustrover.svg diff --git a/jetbrains_projects/webstorm.svg b/licensing/jetbrains_projects/webstorm.svg similarity index 100% rename from jetbrains_projects/webstorm.svg rename to licensing/jetbrains_projects/webstorm.svg diff --git a/kill/__init__.py b/licensing/kill/__init__.py similarity index 100% rename from kill/__init__.py rename to licensing/kill/__init__.py diff --git a/locate/__init__.py b/licensing/locate/__init__.py similarity index 100% rename from locate/__init__.py rename to licensing/locate/__init__.py diff --git a/locate/locate.svg b/licensing/locate/locate.svg similarity index 100% rename from locate/locate.svg rename to licensing/locate/locate.svg diff --git a/mathematica_eval/__init__.py b/licensing/mathematica_eval/__init__.py similarity index 100% rename from mathematica_eval/__init__.py rename to licensing/mathematica_eval/__init__.py diff --git a/pacman/__init__.py b/licensing/pacman/__init__.py similarity index 100% rename from pacman/__init__.py rename to licensing/pacman/__init__.py diff --git a/pacman/arch.svg b/licensing/pacman/arch.svg similarity index 97% rename from pacman/arch.svg rename to licensing/pacman/arch.svg index 61f55ed9..b95bef86 100644 --- a/pacman/arch.svg +++ b/licensing/pacman/arch.svg @@ -1,5 +1 @@ - - \ No newline at end of file diff --git a/pass/__init__.py b/licensing/pass/__init__.py similarity index 100% rename from pass/__init__.py rename to licensing/pass/__init__.py diff --git a/pomodoro/__init__.py b/licensing/pomodoro/__init__.py similarity index 100% rename from pomodoro/__init__.py rename to licensing/pomodoro/__init__.py diff --git a/pomodoro/pomodoro.svg b/licensing/pomodoro/pomodoro.svg similarity index 97% rename from pomodoro/pomodoro.svg rename to licensing/pomodoro/pomodoro.svg index 29cc53cf..fea164ad 100644 --- a/pomodoro/pomodoro.svg +++ b/licensing/pomodoro/pomodoro.svg @@ -1,5 +1 @@ - - \ No newline at end of file diff --git a/python_eval/__init__.py b/licensing/python_eval/__init__.py similarity index 100% rename from python_eval/__init__.py rename to licensing/python_eval/__init__.py diff --git a/python_eval/python.svg b/licensing/python_eval/python.svg similarity index 100% rename from python_eval/python.svg rename to licensing/python_eval/python.svg diff --git a/tex_to_unicode/__init__.py b/licensing/tex_to_unicode/__init__.py similarity index 100% rename from tex_to_unicode/__init__.py rename to licensing/tex_to_unicode/__init__.py diff --git a/tex_to_unicode/tex.png b/licensing/tex_to_unicode/tex.png similarity index 100% rename from tex_to_unicode/tex.png rename to licensing/tex_to_unicode/tex.png diff --git a/timer/__init__.py b/licensing/timer/__init__.py similarity index 100% rename from timer/__init__.py rename to licensing/timer/__init__.py diff --git a/timer/time.svg b/licensing/timer/time.svg similarity index 99% rename from timer/time.svg rename to licensing/timer/time.svg index 0f675ad2..f6cc4d0b 100644 --- a/timer/time.svg +++ b/licensing/timer/time.svg @@ -1,5 +1 @@ - - \ No newline at end of file diff --git a/translators/__init__.py b/licensing/translators/__init__.py similarity index 100% rename from translators/__init__.py rename to licensing/translators/__init__.py diff --git a/translators/google_translate.png b/licensing/translators/google_translate.png similarity index 100% rename from translators/google_translate.png rename to licensing/translators/google_translate.png diff --git a/virtualbox/__init__.py b/licensing/virtualbox/__init__.py similarity index 100% rename from virtualbox/__init__.py rename to licensing/virtualbox/__init__.py diff --git a/vpn/__init__.py b/licensing/vpn/__init__.py similarity index 100% rename from vpn/__init__.py rename to licensing/vpn/__init__.py diff --git a/wikipedia/__init__.py b/licensing/wikipedia/__init__.py similarity index 100% rename from wikipedia/__init__.py rename to licensing/wikipedia/__init__.py diff --git a/wikipedia/wikipedia.png b/licensing/wikipedia/wikipedia.png similarity index 100% rename from wikipedia/wikipedia.png rename to licensing/wikipedia/wikipedia.png diff --git a/zeal/__init__.py b/licensing/zeal/__init__.py similarity index 100% rename from zeal/__init__.py rename to licensing/zeal/__init__.py From d31cdd3edf2c92d45a91308debbdacab48d84733 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:20:47 +0100 Subject: [PATCH 214/355] [archwiki] Reinstate proper licensing --- {licensing/arch_wiki => arch_wiki}/__init__.py | 10 ++++++---- {licensing/arch_wiki => arch_wiki}/arch.svg | 0 2 files changed, 6 insertions(+), 4 deletions(-) rename {licensing/arch_wiki => arch_wiki}/__init__.py (94%) rename {licensing/arch_wiki => arch_wiki}/arch.svg (100%) diff --git a/licensing/arch_wiki/__init__.py b/arch_wiki/__init__.py similarity index 94% rename from licensing/arch_wiki/__init__.py rename to arch_wiki/__init__.py index a1b243be..2dbf9456 100644 --- a/licensing/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider import json from pathlib import Path @@ -9,10 +10,11 @@ md_iid = '2.0' md_version = "1.5" -md_name = "ArchLinux Wiki" -md_description = "Search ArchLinux Wiki articles" -md_license = "BSD-3" -md_url = "https://github.com/albertlauncher/python/tree/master/awiki" +md_name = "Arch Linux Wiki" +md_description = "Search Arch Linux Wiki articles" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/master/arch_wiki" +md_authors = "@manuelschneid3r" class Plugin(PluginInstance, TriggerQueryHandler): diff --git a/licensing/arch_wiki/arch.svg b/arch_wiki/arch.svg similarity index 100% rename from licensing/arch_wiki/arch.svg rename to arch_wiki/arch.svg From 0ecdab89e4b6eb43b12e45d4217a2ecdd50469f2 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:21:34 +0100 Subject: [PATCH 215/355] [coingecko] Reinstate proper licensing --- {licensing/coingecko => coingecko}/__init__.py | 6 +++--- {licensing/coingecko => coingecko}/coingecko.png | Bin 2 files changed, 3 insertions(+), 3 deletions(-) rename {licensing/coingecko => coingecko}/__init__.py (98%) rename {licensing/coingecko => coingecko}/coingecko.png (100%) diff --git a/licensing/coingecko/__init__.py b/coingecko/__init__.py similarity index 98% rename from licensing/coingecko/__init__.py rename to coingecko/__init__.py index 602d0684..bf05ae9f 100644 --- a/licensing/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- - -"""Show and access crypto currencies on CoinGecko.com.""" +# Copyright (c) 2024 Manuel Schneider from albert import * from time import time @@ -13,8 +12,9 @@ md_version = "1.1" md_name = "CoinGecko" md_description = "Access CoinGecko" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/coingecko" +md_authors = "@manuelschneid3r" class CoinFetcherThread(Thread): diff --git a/licensing/coingecko/coingecko.png b/coingecko/coingecko.png similarity index 100% rename from licensing/coingecko/coingecko.png rename to coingecko/coingecko.png From fb26263dbf70ba5d5391c1f3de21eac8d69d43ff Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:22:17 +0100 Subject: [PATCH 216/355] [color] Reinstate proper licensing --- {licensing/color => color}/__init__.py | 2 ++ 1 file changed, 2 insertions(+) rename {licensing/color => color}/__init__.py (96%) diff --git a/licensing/color/__init__.py b/color/__init__.py similarity index 96% rename from licensing/color/__init__.py rename to color/__init__.py index 10bfa2f9..6287ac3a 100644 --- a/licensing/color/__init__.py +++ b/color/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider """ Displays a color parsed from name, which may be in one of these formats: @@ -27,6 +28,7 @@ md_description = 'Display color for color codes' md_license = 'MIT' md_url = 'https://github.com/albertlauncher/python/color' +md_authors = "@manuelschneid3r" class Plugin(PluginInstance, GlobalQueryHandler): From a47648a1508b9ac158110462e814940fc5029c0a Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:26:06 +0100 Subject: [PATCH 217/355] [color:1.1] Adopt iid:3.0 --- color/__init__.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/color/__init__.py b/color/__init__.py index 6287ac3a..6a840120 100644 --- a/color/__init__.py +++ b/color/__init__.py @@ -2,20 +2,16 @@ # Copyright (c) 2024 Manuel Schneider """ -Displays a color parsed from name, which may be in one of these formats: +Displays a color parsed from a code, which may be in one of these formats: * #RGB (each of R, G, and B is a single hex digit) * #RRGGBB * #AARRGGBB * #RRRGGGBBB * #RRRRGGGGBBBB -* A name from the list of colors defined in the list of SVG color keyword -names provided by the World Wide Web Consortium; for example, "steelblue" -or "gainsboro". -Note: This extension started as a prototype to test the internal color pixmap -generator. However it may serve as a starting point for people having a real -need for color workflows. PR's welcome. +Note: This extension started as a prototype to test the internal color pixmap generator. However it may serve as a \ +starting point for people having a real need for color workflows. PR's welcome. """ from albert import * @@ -23,7 +19,7 @@ from string import hexdigits md_iid = '2.0' -md_version = '1.0' +md_version = '1.1' md_name = 'Color' md_description = 'Display color for color codes' md_license = 'MIT' @@ -63,3 +59,11 @@ def handleGlobalQuery(self, query): ) return rank_items + + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip() + } + ] \ No newline at end of file From d1f25fa0cdfe084fc09203766813b3201c9886a9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:28:51 +0100 Subject: [PATCH 218/355] [duckduckgo] Reinstate proper licensing --- {licensing/duckduckgo => duckduckgo}/__init__.py | 7 ++++++- {licensing/duckduckgo => duckduckgo}/duckduckgo.svg | 0 2 files changed, 6 insertions(+), 1 deletion(-) rename {licensing/duckduckgo => duckduckgo}/__init__.py (91%) rename {licensing/duckduckgo => duckduckgo}/duckduckgo.svg (100%) diff --git a/licensing/duckduckgo/__init__.py b/duckduckgo/__init__.py similarity index 91% rename from licensing/duckduckgo/__init__.py rename to duckduckgo/__init__.py index 2f9174e9..f8865961 100644 --- a/licensing/duckduckgo/__init__.py +++ b/duckduckgo/__init__.py @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider + """ Inline DuckDuckGo web search using the 'duckduckgo-search' library. """ @@ -12,8 +15,10 @@ md_version = '1.0' md_name = 'DuckDuckGo' md_description = 'Inline DuckDuckGo web search' +md_license = "MIT" md_url = 'https://github.com/albertlauncher/python/duckduckgo' md_lib_dependencies = "duckduckgo-search" +md_authors = "@manuelschneid3r" class Plugin(PluginInstance, TriggerQueryHandler): @@ -35,7 +40,7 @@ def handleTriggerQuery(self, query): if stripped: # dont flood - for number in range(25): + for _ in range(25): sleep(0.01) if not query.isValid: return diff --git a/licensing/duckduckgo/duckduckgo.svg b/duckduckgo/duckduckgo.svg similarity index 100% rename from licensing/duckduckgo/duckduckgo.svg rename to duckduckgo/duckduckgo.svg From 22db77c51107950927d4713d70aca97f9fb99e6f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:29:43 +0100 Subject: [PATCH 219/355] [inhibit_sleep] Reinstate proper licensing --- inhibit_sleep/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/inhibit_sleep/__init__.py b/inhibit_sleep/__init__.py index c5f56427..b27c65df 100644 --- a/inhibit_sleep/__init__.py +++ b/inhibit_sleep/__init__.py @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider + """ Provides an item 'Inhibit sleep' which can be used to temporarily disable system suspension. @@ -12,7 +15,9 @@ md_version = '1.0' md_name = 'Inhibit sleep' md_description = 'Inhibit system sleep mode.' +md_license = "MIT" md_url = 'https://github.com/albertlauncher/python/inhibit_sleep' +md_authors = "@manuelschneid3r" md_bin_dependencies = ['systemd-inhibit', "sleep"] From 74ab65c0737e91ca0eed5fc2c7e1365cb25efc83 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:45:37 +0100 Subject: [PATCH 220/355] [killd] Reinstate proper licensing --- {licensing/kill => kill}/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) rename {licensing/kill => kill}/__init__.py (92%) diff --git a/licensing/kill/__init__.py b/kill/__init__.py similarity index 92% rename from licensing/kill/__init__.py rename to kill/__init__.py index 0b259a23..73e3ca41 100644 --- a/licensing/kill/__init__.py +++ b/kill/__init__.py @@ -1,4 +1,8 @@ -"""Unix 'kill' wrapper extension.""" +# -*- coding: utf-8 -*- +# Copyright (c) 2022 Manuel Schneider +# Copyright (c) 2022 Benedict Dudel +# Copyright (c) 2022 Pete Hamlin + import os from signal import SIGKILL, SIGTERM @@ -9,10 +13,9 @@ md_version = "1.3" md_name = "Kill Process" md_description = "Kill processes" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/kill" -md_maintainers = "@Pete-Hamlin" -md_credits = "Original idea by Benedict Dudel & Manuel Schneider" +md_authors = ["@Pete-Hamlin", "@BenedictDwudel", "@ManuelSchneid3r"] class Plugin(PluginInstance, TriggerQueryHandler): From e28c3afd320d5431512c615859cbf90dfa92dbcf Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:51:22 +0100 Subject: [PATCH 221/355] [pacman] Reinstate proper licensing --- {licensing/pacman => pacman}/__init__.py | 11 ++++------- {licensing/pacman => pacman}/arch.svg | 0 2 files changed, 4 insertions(+), 7 deletions(-) rename {licensing/pacman => pacman}/__init__.py (96%) rename {licensing/pacman => pacman}/arch.svg (100%) diff --git a/licensing/pacman/__init__.py b/pacman/__init__.py similarity index 96% rename from licensing/pacman/__init__.py rename to pacman/__init__.py index 856b7c77..a47f39fd 100644 --- a/licensing/pacman/__init__.py +++ b/pacman/__init__.py @@ -1,9 +1,5 @@ # -*- coding: utf-8 -*- - -""" -This plugin is a `pacman` (Arch Linux Package Manager) wrapper. You can update, search, install and remove \ -packages. -""" +# Copyright (c) 2024 Manuel Schneider import subprocess from time import sleep @@ -15,8 +11,9 @@ md_version = "1.9" md_name = "PacMan" md_description = "Search, install and remove packages" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/pacman" +md_authors = "@ManuelSchneid3r" md_bin_dependencies = ["pacman", "expac"] @@ -58,7 +55,7 @@ def handleTriggerQuery(self, query): return # avoid rate limiting - for number in range(50): + for _ in range(50): sleep(0.01) if not query.isValid: return diff --git a/licensing/pacman/arch.svg b/pacman/arch.svg similarity index 100% rename from licensing/pacman/arch.svg rename to pacman/arch.svg From 0f5a14116ae46624ba2878e692f6f3e9e0154a80 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:53:24 +0100 Subject: [PATCH 222/355] [pomodoro] Reinstate proper licensing --- {licensing/pomodoro => pomodoro}/__init__.py | 6 +++--- {licensing/pomodoro => pomodoro}/pomodoro.svg | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename {licensing/pomodoro => pomodoro}/__init__.py (97%) rename {licensing/pomodoro => pomodoro}/pomodoro.svg (100%) diff --git a/licensing/pomodoro/__init__.py b/pomodoro/__init__.py similarity index 97% rename from licensing/pomodoro/__init__.py rename to pomodoro/__init__.py index a18b4455..55ac7180 100644 --- a/licensing/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2022 Manuel Schneider +# Copyright (c) 2024 Manuel Schneider """ https://en.wikipedia.org/wiki/Pomodoro_Technique @@ -16,9 +16,9 @@ md_version = "1.3" md_name = "Pomodoro" md_description = "Set up a Pomodoro timer" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/pomodoro" -md_maintainers = "@manuelschneid3r" +md_author = "@manuelschneid3r" class PomodoroTimer: diff --git a/licensing/pomodoro/pomodoro.svg b/pomodoro/pomodoro.svg similarity index 100% rename from licensing/pomodoro/pomodoro.svg rename to pomodoro/pomodoro.svg From 9f384037ce67074750932f6491ae5a1f2c63f593 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:54:51 +0100 Subject: [PATCH 223/355] [translators] Reinstate proper licensing --- {licensing/translators => translators}/__init__.py | 4 +++- .../google_translate.png | Bin 2 files changed, 3 insertions(+), 1 deletion(-) rename {licensing/translators => translators}/__init__.py (98%) rename {licensing/translators => translators}/google_translate.png (100%) diff --git a/licensing/translators/__init__.py b/translators/__init__.py similarity index 98% rename from licensing/translators/__init__.py rename to translators/__init__.py index dbcac7b5..7ed4fc59 100644 --- a/licensing/translators/__init__.py +++ b/translators/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider """ Translates text using the python package translators. See https://pypi.org/project/translators/ @@ -15,8 +16,9 @@ md_version = "1.4" md_name = "Translator" md_description = "Translate sentences using 'translators' package" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/translators" +md_authors = "@manuelschneid3r" md_lib_dependencies = "translators" diff --git a/licensing/translators/google_translate.png b/translators/google_translate.png similarity index 100% rename from licensing/translators/google_translate.png rename to translators/google_translate.png From 5e43239b7e3b824ba9539acc3548e7e83d4fd279 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:55:09 +0100 Subject: [PATCH 224/355] [virtualbox] Reinstate proper licensing --- {licensing/virtualbox => virtualbox}/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename {licensing/virtualbox => virtualbox}/__init__.py (97%) diff --git a/licensing/virtualbox/__init__.py b/virtualbox/__init__.py similarity index 97% rename from licensing/virtualbox/__init__.py rename to virtualbox/__init__.py index 94b21015..4b628a27 100644 --- a/licensing/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider import virtualbox from virtualbox.library import LockType, MachineState @@ -9,9 +10,9 @@ md_version = "1.5" md_name = "VirtualBox" md_description = "Manage your VirtualBox machines" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/virtualbox" -md_maintainers = "@manuelschneid3r" +md_authors = "@manuelschneid3r" md_lib_dependencies = ['virtualbox'] From 62c27ea56e3223d95df9342ced8782c463a942c9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:56:34 +0100 Subject: [PATCH 225/355] [wikipedia] Reinstate proper licensing --- {licensing/wikipedia => wikipedia}/__init__.py | 5 +++-- {licensing/wikipedia => wikipedia}/wikipedia.png | Bin 2 files changed, 3 insertions(+), 2 deletions(-) rename {licensing/wikipedia => wikipedia}/__init__.py (98%) rename {licensing/wikipedia => wikipedia}/wikipedia.png (100%) diff --git a/licensing/wikipedia/__init__.py b/wikipedia/__init__.py similarity index 98% rename from licensing/wikipedia/__init__.py rename to wikipedia/__init__.py index 24809292..433f85c2 100644 --- a/licensing/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider -# Copyright (c) 2022-2023 Manuel Schneider from albert import * from locale import getdefaultlocale @@ -14,8 +14,9 @@ md_version = "1.10" md_name = "Wikipedia" md_description = "Search Wikipedia articles" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/wikipedia" +md_authors = "@manuelschneid3r" class WikiFallbackHandler(FallbackHandler): diff --git a/licensing/wikipedia/wikipedia.png b/wikipedia/wikipedia.png similarity index 100% rename from licensing/wikipedia/wikipedia.png rename to wikipedia/wikipedia.png From 3955f7aafb981632ba6c552343379e12e0afd70f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 00:56:55 +0100 Subject: [PATCH 226/355] [zeal] Reinstate proper licensing --- {licensing/zeal => zeal}/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) rename {licensing/zeal => zeal}/__init__.py (90%) diff --git a/licensing/zeal/__init__.py b/zeal/__init__.py similarity index 90% rename from licensing/zeal/__init__.py rename to zeal/__init__.py index 843eee45..7ebae3c2 100644 --- a/licensing/zeal/__init__.py +++ b/zeal/__init__.py @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider + """Search in Zeal offline docs.""" from albert import * @@ -6,7 +9,9 @@ md_version = '1.2' md_name = 'Zeal' md_description = 'Search in Zeal docs' +md_license = "MIT" md_url = 'https://github.com/albertlauncher/python/zeal' +md_authors = "@manuelschneid3r" md_bin_dependencies = ['zeal'] From b29b96d7cf24bb896154990661ab389df1e18678 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 01:09:39 +0100 Subject: [PATCH 227/355] [aur] Reinstate proper licensing There were two minor additions not worth a copyright - 43f3b93 Gaganpreet [aur:1.6] Fix install action - fce8b8b Manuel Parati [aur] added paru AUR helper (#128) --- {licensing/aur => aur}/__init__.py | 5 +++-- {licensing/aur => aur}/arch.svg | 0 2 files changed, 3 insertions(+), 2 deletions(-) rename {licensing/aur => aur}/__init__.py (98%) rename {licensing/aur => aur}/arch.svg (100%) diff --git a/licensing/aur/__init__.py b/aur/__init__.py similarity index 98% rename from licensing/aur/__init__.py rename to aur/__init__.py index a2bcb1e2..3989eb95 100644 --- a/licensing/aur/__init__.py +++ b/aur/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2022-2023 Manuel Schneider +# Copyright (c) 2024 Manuel Schneider """ Search for packages and open their URLs. This extension is also intended to be used to \ @@ -19,9 +19,10 @@ md_version = "1.8" md_name = "AUR" md_description = "Query and install AUR packages" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/aur" # md_platforms = ["Linux"] +md_authors = "@manuelschneid3r" class Plugin(PluginInstance, TriggerQueryHandler): diff --git a/licensing/aur/arch.svg b/aur/arch.svg similarity index 100% rename from licensing/aur/arch.svg rename to aur/arch.svg From f28d799e44fff247739485a05c4d31d2e488e833 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 01:12:34 +0100 Subject: [PATCH 228/355] Add contribution guide --- CONTRIBUTING.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..4742ff5a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,16 @@ +## How to contribute to this repository + +### Do you have an issue? + +* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/albertlauncher/albert/issues). +* Create a new issue using the templates provided. +* Ping the authors of the related plugin. + +### Do you want to contribute code? + +* Add a copyright notice, otherwise the code is in public domain. +* You agree to publish your contribution under the MIT license. +* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. +* Changes that do not add anything substantial to the stability, functionality, or testability will generally not be accepted. + +Thanks! :heart: From aad5a83789df99cfff7cecbbc4ca9c708b808c38 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 01:14:19 +0100 Subject: [PATCH 229/355] [pyi] v2.2 --- albert.pyi | 103 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 26 deletions(-) diff --git a/albert.pyi b/albert.pyi index 787ec318..43eebdf8 100644 --- a/albert.pyi +++ b/albert.pyi @@ -1,6 +1,5 @@ """ - -# Albert Python interface v2.1 +# Albert Python interface v2.2 The Python interface is a subset of the internal C++ interface exposed to Python with some minor adjustments. A Python @@ -21,10 +20,9 @@ md_description: str | A brief, imperative description. (Like "Launch apps" or "O md_id | Identifier overwrite. [a-zA-Z0-9_]. Note: This variable is attached at runtime | if it is unset and defaults to the module name. -__doc__ | The docstring of the module is used as long description/readme of the extension. -md_license: str | Short form e.g. BSD-2-Clause or GPL-3.0 +md_license: str | Short form e.g. MIT or BSD-2 md_url: str | Browsable source, issues etc -md_maintainers: [str|List(str)] | Active maintainer(s). Preferrably using mentionable Github usernames. +md_authors: [str|List(str)] | The authors. Preferably using mentionable Github usernames. md_bin_dependencies: [str|List(str)] | Required executable(s). Have to match the name of the executable in $PATH. md_lib_dependencies: [str|List(str)] | Required Python package(s). Have to match the PyPI package name. md_credits: [str|List(str)] | Third party credit(s) and license notes @@ -37,8 +35,20 @@ PluginInstance. Implement extensions by subclassing _one_ extension class (Trigg built-in `albert` module and pass the list of your extensions to the PluginInstance init function. Due to the differences in type systems multiple inheritance of extensions is not supported. (Python does not support virtual inheritance, which is used in the C++ space to inherit from 'Extension'). -""" +Changes in 2.1 + + - Add PluginInstance.readConfig + - Add PluginInstance.writeConfig + - Add PluginInstance.configWidget + +Changes in 2.2: + + - PluginInstance.configWidget supports 'label' + - __doc__ is not used anymore, since 0.23 drops long_description metadata + - md_maintainers not used anymore + - md_authors new optional field +""" from abc import abstractmethod, ABC from enum import Enum @@ -105,26 +115,67 @@ class PluginInstance(ABC): def configWidget(self) -> List[dict]: """ - Descriptive config widget factory. - - Define a static config widget using a list of dicts, each defining a row in the resulting form layout. - Supported keys are: - - - 'property' The name of the property that will be set upon editing the forms. - - 'label' The text displayed in front of the the editor widget. - - 'type' The type of editor widget used. See the supported types below. - - 'items' The list of strings used for 'type': 'combobox'. - - 'widget_properties' Dict setting the widget properties of the editor widget. - See the links along the editor types below (but also the base classes) to find available properties. - Note that due to the restricted type conversion only properties of type str|int|float|bool are settable. - - The supported editor widget types are: - - * 'checkbox' for boolean properties (See https://doc.qt.io/qt-6/qcheckbox.html) - * 'spinbox' for integer properties. (See https://doc.qt.io/qt-6/qspinbox.html) - * 'doublespinbox' for float properties. (See https://doc.qt.io/qt-6/qdoublespinbox.html) - * 'lineedit' if you want the user to input any string. (See https://doc.qt.io/qt-6/qlineedit.html) - * 'combobox' if you want the user to choose a string. (See https://doc.qt.io/qt-6/qcombobox.html) + **Descriptive config widget factory.** + + Define a static config widget using a list of dicts, each defining a row in the resulting form layout. Each dict + must contain key 'type' having one of the supported types specified below. Each type may define further + keys. + + **A note on 'widget_properties'** + + This is a dict setting the widget properties of a QWidget or one of its derived classes. See Qt documentation + for a particular class. Note that due to the restricted type conversion only properties of type + str|int|float|bool are settable. + + **Supported row 'type's** + + * 'label' (since 2.2) + + Display text spanning both columns. Additional keys: + + - 'text': The text to display + - 'widget_properties': https://doc.qt.io/qt-6/qlabel.html. + + * 'checkbox' + + A form layout item to edit boolean properties. Additional keys: + + - 'label': The text displayed in front of the the editor widget. + - 'property': The name of the property that will be set on changes. + - 'widget_properties': https://doc.qt.io/qt-6/qcheckbox.html + + * 'lineedit' + + A form layout item to edit string properties. Additional keys: + + - 'label': The text displayed in front of the the editor widget. + - 'property': The name of the property that will be set on changes. + - 'widget_properties': https://doc.qt.io/qt-6/qlineedit.html + + * 'combobox' + + A form layout item to set string properties using a list of options. Additional keys: + + - 'label': The text displayed in front of the the editor widget. + - 'property': The name of the property that will be set on changes. + - 'items': The list of strings used to populate the combobox. + - 'widget_properties': https://doc.qt.io/qt-6/qcombobox.html + + * 'spinbox' + + A form layout item to edit integer properties. Additional keys: + + - 'label': The text displayed in front of the the editor widget. + - 'property': The name of the property that will be set on changes. + - 'widget_properties': https://doc.qt.io/qt-6/qspinbox.html + + * 'doublespinbox' + + A form layout item to edit float properties. Additional keys: + + - 'label': The text displayed in front of the the editor widget. + - 'property': The name of the property that will be set on changes. + - 'widget_properties': https://doc.qt.io/qt-6/qdoublespinbox.html Returns: A list of dicts, describing a form layout as defined above. From e73f30e5c57e5e062785723967f79c475a9bdc3b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 01:21:44 +0100 Subject: [PATCH 230/355] [aur] Reinstate proper licensing There was one minor additions not worth a copyright - 45b6de3 Lorenz Henk [docker] Fix typo (#121) --- {licensing/docker => docker}/__init__.py | 10 ++++------ {licensing/docker => docker}/running.png | Bin {licensing/docker => docker}/stopped.png | Bin 3 files changed, 4 insertions(+), 6 deletions(-) rename {licensing/docker => docker}/__init__.py (97%) rename {licensing/docker => docker}/running.png (100%) rename {licensing/docker => docker}/stopped.png (100%) diff --git a/licensing/docker/__init__.py b/docker/__init__.py similarity index 97% rename from licensing/docker/__init__.py rename to docker/__init__.py index f925e913..f47905f0 100644 --- a/licensing/docker/__init__.py +++ b/docker/__init__.py @@ -1,8 +1,5 @@ -""" -Docker wrapper (prototype) -""" - -from pathlib import Path +# -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider import docker from albert import * @@ -11,8 +8,9 @@ md_version = "1.6" md_name = "Docker" md_description = "Manage docker images and containers" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/docker" +md_authors = "@manuelschneid3r" md_bin_dependencies = "docker" md_lib_dependencies = "docker" diff --git a/licensing/docker/running.png b/docker/running.png similarity index 100% rename from licensing/docker/running.png rename to docker/running.png diff --git a/licensing/docker/stopped.png b/docker/stopped.png similarity index 100% rename from licensing/docker/stopped.png rename to docker/stopped.png From 7c12ad41c9a7b714b9bb14cd398e20cee484b367 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 01:27:58 +0100 Subject: [PATCH 231/355] [dice_roll] Reinstate proper licensing --- {licensing/dice_roll => dice_roll}/__init__.py | 3 ++- {licensing/dice_roll => dice_roll}/icons/d10.svg | 0 {licensing/dice_roll => dice_roll}/icons/d100.svg | 0 {licensing/dice_roll => dice_roll}/icons/d12.svg | 0 {licensing/dice_roll => dice_roll}/icons/d2.svg | 0 {licensing/dice_roll => dice_roll}/icons/d20.svg | 0 {licensing/dice_roll => dice_roll}/icons/d4.svg | 0 {licensing/dice_roll => dice_roll}/icons/d6.svg | 0 {licensing/dice_roll => dice_roll}/icons/d8.svg | 0 {licensing/dice_roll => dice_roll}/icons/dice.svg | 0 licensing/dice_roll/README.md | 13 ------------- 11 files changed, 2 insertions(+), 14 deletions(-) rename {licensing/dice_roll => dice_roll}/__init__.py (98%) rename {licensing/dice_roll => dice_roll}/icons/d10.svg (100%) rename {licensing/dice_roll => dice_roll}/icons/d100.svg (100%) rename {licensing/dice_roll => dice_roll}/icons/d12.svg (100%) rename {licensing/dice_roll => dice_roll}/icons/d2.svg (100%) rename {licensing/dice_roll => dice_roll}/icons/d20.svg (100%) rename {licensing/dice_roll => dice_roll}/icons/d4.svg (100%) rename {licensing/dice_roll => dice_roll}/icons/d6.svg (100%) rename {licensing/dice_roll => dice_roll}/icons/d8.svg (100%) rename {licensing/dice_roll => dice_roll}/icons/dice.svg (100%) delete mode 100644 licensing/dice_roll/README.md diff --git a/licensing/dice_roll/__init__.py b/dice_roll/__init__.py similarity index 98% rename from licensing/dice_roll/__init__.py rename to dice_roll/__init__.py index 95f95031..dc2e3c88 100644 --- a/licensing/dice_roll/__init__.py +++ b/dice_roll/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2024 Jonah Lawrence from __future__ import annotations @@ -20,7 +21,7 @@ md_description = "Roll any number of dice" md_license = "MIT" md_url = "https://github.com/albertlauncher/python" -md_maintainers = "@DenverCoder1" +md_authors = "@DenverCoder1" def get_icon_path(num_sides: int | None) -> str: diff --git a/licensing/dice_roll/icons/d10.svg b/dice_roll/icons/d10.svg similarity index 100% rename from licensing/dice_roll/icons/d10.svg rename to dice_roll/icons/d10.svg diff --git a/licensing/dice_roll/icons/d100.svg b/dice_roll/icons/d100.svg similarity index 100% rename from licensing/dice_roll/icons/d100.svg rename to dice_roll/icons/d100.svg diff --git a/licensing/dice_roll/icons/d12.svg b/dice_roll/icons/d12.svg similarity index 100% rename from licensing/dice_roll/icons/d12.svg rename to dice_roll/icons/d12.svg diff --git a/licensing/dice_roll/icons/d2.svg b/dice_roll/icons/d2.svg similarity index 100% rename from licensing/dice_roll/icons/d2.svg rename to dice_roll/icons/d2.svg diff --git a/licensing/dice_roll/icons/d20.svg b/dice_roll/icons/d20.svg similarity index 100% rename from licensing/dice_roll/icons/d20.svg rename to dice_roll/icons/d20.svg diff --git a/licensing/dice_roll/icons/d4.svg b/dice_roll/icons/d4.svg similarity index 100% rename from licensing/dice_roll/icons/d4.svg rename to dice_roll/icons/d4.svg diff --git a/licensing/dice_roll/icons/d6.svg b/dice_roll/icons/d6.svg similarity index 100% rename from licensing/dice_roll/icons/d6.svg rename to dice_roll/icons/d6.svg diff --git a/licensing/dice_roll/icons/d8.svg b/dice_roll/icons/d8.svg similarity index 100% rename from licensing/dice_roll/icons/d8.svg rename to dice_roll/icons/d8.svg diff --git a/licensing/dice_roll/icons/dice.svg b/dice_roll/icons/dice.svg similarity index 100% rename from licensing/dice_roll/icons/dice.svg rename to dice_roll/icons/dice.svg diff --git a/licensing/dice_roll/README.md b/licensing/dice_roll/README.md deleted file mode 100644 index 955d6c3c..00000000 --- a/licensing/dice_roll/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Dice Roll - -Extension for rolling dice - -![image](https://user-images.githubusercontent.com/20955511/211666706-eae9c9f2-849f-4b9c-9a59-39d71940b83d.png) - -## Usage - -Roll any number of dice using the format `_d_`. - -Synopsis: ` d [d ...]` - -Example: `"roll 2d6 3d8 1d20"` From ea91d50c11b1a0933496f3e0180183a7dba57913 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 01:40:15 +0100 Subject: [PATCH 232/355] [copyq] Reinstate proper licensing --- {licensing/copyq => copyq}/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename {licensing/copyq => copyq}/__init__.py (94%) diff --git a/licensing/copyq/__init__.py b/copyq/__init__.py similarity index 94% rename from licensing/copyq/__init__.py rename to copyq/__init__.py index ae418eb5..18a77185 100644 --- a/licensing/copyq/__init__.py +++ b/copyq/__init__.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2017-2024 Manuel Schneider +# Copyright (c) 2023 Oskar Haarklou Veileborg (@BarrensZeppelin) import json import subprocess @@ -11,8 +13,8 @@ md_description = "Access CopyQ clipboard" md_license = "BSD-2-Clause" md_url = "https://github.com/albertlauncher/python" +md_authors = ["@ManuelSchneid3r", "@BarrensZeppelin"] md_bin_dependencies = ["copyq"] -md_maintainers = "@BarrensZeppelin" copyq_script_getAll = r""" From 286114c24561660cdccaa24ad24968bd33d2b6e2 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 01:44:02 +0100 Subject: [PATCH 233/355] [emoji] Reinstate proper licensing Has been entirely rewritten in 970f98b --- {licensing/emoji => emoji}/__init__.py | 2 ++ 1 file changed, 2 insertions(+) rename {licensing/emoji => emoji}/__init__.py (99%) diff --git a/licensing/emoji/__init__.py b/emoji/__init__.py similarity index 99% rename from licensing/emoji/__init__.py rename to emoji/__init__.py index fe918e6d..bdf6db4e 100644 --- a/licensing/emoji/__init__.py +++ b/emoji/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider import json import re @@ -16,6 +17,7 @@ md_description = "Find and copy emojis by name" md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/emoji" +md_authors = "@manuelschneid3r" class Plugin(PluginInstance, IndexQueryHandler): From 9ee2599be5e35533293a42b1fd7424fdff2e8c6e Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 01:50:33 +0100 Subject: [PATCH 234/355] [locate] Reinstate proper licensing - 68e11eb is just a minor fix --- {licensing/locate => locate}/__init__.py | 5 +++-- {licensing/locate => locate}/locate.svg | 0 2 files changed, 3 insertions(+), 2 deletions(-) rename {licensing/locate => locate}/__init__.py (96%) rename {licensing/locate => locate}/locate.svg (100%) diff --git a/licensing/locate/__init__.py b/locate/__init__.py similarity index 96% rename from licensing/locate/__init__.py rename to locate/__init__.py index 29ed4c4c..494e20ac 100644 --- a/licensing/locate/__init__.py +++ b/locate/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2022 Manuel Schneider +# Copyright (c) 2022-2024 Manuel Schneider """ `locate` wrapper. Note that it is up to you to ensure that the locate database is \ @@ -17,9 +17,10 @@ md_version = "1.9" md_name = "Locate" md_description = "Find and open files using locate" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/locate" md_bin_dependencies = "locate" +md_authors = "@manuelschneid3r" class Plugin(PluginInstance, TriggerQueryHandler): diff --git a/licensing/locate/locate.svg b/locate/locate.svg similarity index 100% rename from licensing/locate/locate.svg rename to locate/locate.svg From 57f8a6bf190e628a400b880e3600423712de133d Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 02:15:31 +0100 Subject: [PATCH 235/355] [goldendict] Reinstate proper licensing - f33d955 is superseded just a minor fix https://github.com/albertlauncher/python/commits/91845ed824ef7d61e572890c41f75c65c8d0a477/goldendict.py --- {licensing/goldendict => goldendict}/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) rename {licensing/goldendict => goldendict}/__init__.py (87%) diff --git a/licensing/goldendict/__init__.py b/goldendict/__init__.py similarity index 87% rename from licensing/goldendict/__init__.py rename to goldendict/__init__.py index 80126cf6..aebbc447 100644 --- a/licensing/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -1,11 +1,15 @@ -from albert import Action, StandardItem, TriggerQuery, PluginInstance, TriggerQueryHandler, runDetachedProcess # pylint: disable=import-error +# -*- coding: utf-8 -*- +# Copyright (c) 2017-2024 Manuel Schneider + +from albert import * md_iid = '2.0' md_version = '1.3' md_name = 'GoldenDict' md_description = 'Searches in GoldenDict' +md_license = 'MIT' md_url = 'https://github.com/albertlauncher/python/' -md_maintainers = '@stevenxxiu' +md_authors = '@manuelschneid3r' md_bin_dependencies = ['goldendict'] From 7823707c7fa646586eb9c4483d4470f206c3bddd Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 02:28:00 +0100 Subject: [PATCH 236/355] [pass] Reinstate proper licensing ignoring 30e6d6c, 1c868b2 due to loe LOC https://github.com/albertlauncher/python/commits/master/pass/ https://github.com/albertlauncher/python/commits/91845ed824ef7d61e572890c41f75c65c8d0a477/pass.py https://github.com/albertlauncher/python/commits/6ec2774966a524568112b27d285a4df6cb76ec2b/Pass.py?browsing_rename_history=true&new_path=pass.py&original_branch=91845ed824ef7d61e572890c41f75c65c8d0a477 --- {licensing/pass => pass}/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) rename {licensing/pass => pass}/__init__.py (97%) diff --git a/licensing/pass/__init__.py b/pass/__init__.py similarity index 97% rename from licensing/pass/__init__.py rename to pass/__init__.py index 5da2d5fc..9288c2af 100644 --- a/licensing/pass/__init__.py +++ b/pass/__init__.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2017 Benedict Dudel +# Copyright (c) 2023 Max +# Copyright (c) 2023 Pete-Hamlin import fnmatch import os @@ -8,9 +11,9 @@ md_version = "1.5" md_name = "Pass" md_description = "Manage passwords in pass" -md_bin_dependencies = ["pass"] -md_maintainers = ["@Pete-Hamlin"] md_license = "BSD-3" +md_authors = ["@benedictdudel", "@maxmil", "@Pete-Hamlin"] +md_bin_dependencies = ["pass"] HOME_DIR = os.environ["HOME"] PASS_DIR = os.environ.get("PASSWORD_STORE_DIR", os.path.join(HOME_DIR, ".password-store/")) From 3cbfda5a7c8456cae5d21c426da5b8ecedb063c5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 02:32:27 +0100 Subject: [PATCH 237/355] [python_eval] Reinstate proper licensing ignoring 962a832 due to low LOC https://github.com/albertlauncher/python/commits/master/python_eval/ https://github.com/albertlauncher/python/commits/10a5010aa3fb7ac93550b50772d7b6d07464389d/Python --- {licensing/python_eval => python_eval}/__init__.py | 2 ++ {licensing/python_eval => python_eval}/python.svg | 0 2 files changed, 2 insertions(+) rename {licensing/python_eval => python_eval}/__init__.py (95%) rename {licensing/python_eval => python_eval}/python.svg (100%) diff --git a/licensing/python_eval/__init__.py b/python_eval/__init__.py similarity index 95% rename from licensing/python_eval/__init__.py rename to python_eval/__init__.py index 86f86d16..9f3813a5 100644 --- a/licensing/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2017-2014 Manuel Schneider from builtins import pow from math import * @@ -12,6 +13,7 @@ md_description = "Evaluate Python code" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/tree/master/python_eval" +md_authors = "@manuelschneid3r" class Plugin(PluginInstance, TriggerQueryHandler): diff --git a/licensing/python_eval/python.svg b/python_eval/python.svg similarity index 100% rename from licensing/python_eval/python.svg rename to python_eval/python.svg From a0dc01acd9fea9d361f2bceffd5637a545af1ec6 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 02:38:11 +0100 Subject: [PATCH 238/355] [timer] Reinstate proper licensing https://github.com/albertlauncher/python/commits/master/timer/ https://github.com/albertlauncher/python/commits/10a5010aa3fb7ac93550b50772d7b6d07464389d/Timer --- {licensing/timer => timer}/__init__.py | 6 ++++-- {licensing/timer => timer}/time.svg | 0 2 files changed, 4 insertions(+), 2 deletions(-) rename {licensing/timer => timer}/__init__.py (96%) rename {licensing/timer => timer}/time.svg (100%) diff --git a/licensing/timer/__init__.py b/timer/__init__.py similarity index 96% rename from licensing/timer/__init__.py rename to timer/__init__.py index ab49cb5c..fc3020d7 100644 --- a/licensing/timer/__init__.py +++ b/timer/__init__.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +# # Copyright (c) 2018-2024 Manuel Schneider +# # Copyright (c) 2020 Andreas Dominik Preikschat """ Takes arguments in the form of '`[[hrs:]mins:]secs [name]`'. Empty fields resolve to `0`. \ @@ -21,9 +23,9 @@ md_version = "1.7" md_name = "Timer" md_description = "Set up timers" -md_license = "BSD-2" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/timer" -md_maintainers = ["@manuelschneid3r", "@googol42", "@uztnus"] +md_authors = ["@manuelschneid3r", "@googol42"] class Timer(threading.Timer): diff --git a/licensing/timer/time.svg b/timer/time.svg similarity index 100% rename from licensing/timer/time.svg rename to timer/time.svg From a7b62710f632bee907dbfaf737c1b875ff153df4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 02:48:55 +0100 Subject: [PATCH 239/355] [vpn] Reinstate proper licensing Ignoring 7dc1514 for low LOC https://github.com/albertlauncher/python/commits/f7114926c9a5ccee0e48b9387061fd10652a1370/vpn/__init__.py?browsing_rename_history=true&new_path=licensing/vpn/__init__.py&original_branch=master https://github.com/albertlauncher/python/commits/73762b03adf98a80f19cb0039f52a8bd66d24c0e/vpn/__init_.py?browsing_rename_history=true&new_path=licensing/vpn/__init__.py&original_branch=master --- {licensing/vpn => vpn}/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) rename {licensing/vpn => vpn}/__init__.py (91%) diff --git a/licensing/vpn/__init__.py b/vpn/__init__.py similarity index 91% rename from licensing/vpn/__init__.py rename to vpn/__init__.py index 7c7bc02d..82177092 100644 --- a/licensing/vpn/__init__.py +++ b/vpn/__init__.py @@ -1,3 +1,8 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020 janeklb +# Copyright (c) 2023 Bierchermuesli +# Copyright (c) 2020-2024 Manuel Schneider + import subprocess from collections import namedtuple @@ -10,8 +15,7 @@ md_description = "Manage NetworkManager VPN connections" md_license = "MIT" md_url = "https://github.com/albertlauncher/python" -md_maintainers = ["@Bierchermuesli"] -md_credits = ["@janeklb"] +md_authors = ["@janeklb", "@Bierchermuesli", "@manuelschneid3r"] md_bin_dependencies = ["nmcli"] From 5770fb9347cc1b85f5541ad2311c58064a4e0597 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 03:11:12 +0100 Subject: [PATCH 240/355] mv mathematica_eval/ jetbrains_projects tex_to_unicode bitwarden .archive until licensing is clear --- {licensing => .archive}/bitwarden/__init__.py | 6 +++--- {licensing => .archive}/bitwarden/bw.svg | 0 {licensing => .archive}/jetbrains_projects/LICENSE | 0 .../jetbrains_projects/README.md | 0 .../jetbrains_projects/__init__.py | 8 ++++++-- .../jetbrains_projects/androidstudio.svg | 0 .../jetbrains_projects/clion.svg | 0 .../jetbrains_projects/datagrip.svg | 0 .../jetbrains_projects/dataspell.svg | 0 .../jetbrains_projects/goland.svg | 0 {licensing => .archive}/jetbrains_projects/idea.svg | 0 .../jetbrains_projects/phpstorm.svg | 0 .../jetbrains_projects/pycharm.svg | 0 .../jetbrains_projects/rider.svg | 0 .../jetbrains_projects/rubymine.svg | 0 .../jetbrains_projects/rustrover.svg | 0 .../jetbrains_projects/webstorm.svg | 0 .../mathematica_eval/__init__.py | 0 {licensing => .archive}/tex_to_unicode/__init__.py | 0 {licensing => .archive}/tex_to_unicode/tex.png | Bin 20 files changed, 9 insertions(+), 5 deletions(-) rename {licensing => .archive}/bitwarden/__init__.py (98%) rename {licensing => .archive}/bitwarden/bw.svg (100%) rename {licensing => .archive}/jetbrains_projects/LICENSE (100%) rename {licensing => .archive}/jetbrains_projects/README.md (100%) rename {licensing => .archive}/jetbrains_projects/__init__.py (97%) rename {licensing => .archive}/jetbrains_projects/androidstudio.svg (100%) rename {licensing => .archive}/jetbrains_projects/clion.svg (100%) rename {licensing => .archive}/jetbrains_projects/datagrip.svg (100%) rename {licensing => .archive}/jetbrains_projects/dataspell.svg (100%) rename {licensing => .archive}/jetbrains_projects/goland.svg (100%) rename {licensing => .archive}/jetbrains_projects/idea.svg (100%) rename {licensing => .archive}/jetbrains_projects/phpstorm.svg (100%) rename {licensing => .archive}/jetbrains_projects/pycharm.svg (100%) rename {licensing => .archive}/jetbrains_projects/rider.svg (100%) rename {licensing => .archive}/jetbrains_projects/rubymine.svg (100%) rename {licensing => .archive}/jetbrains_projects/rustrover.svg (100%) rename {licensing => .archive}/jetbrains_projects/webstorm.svg (100%) rename {licensing => .archive}/mathematica_eval/__init__.py (100%) rename {licensing => .archive}/tex_to_unicode/__init__.py (100%) rename {licensing => .archive}/tex_to_unicode/tex.png (100%) diff --git a/licensing/bitwarden/__init__.py b/.archive/bitwarden/__init__.py similarity index 98% rename from licensing/bitwarden/__init__.py rename to .archive/bitwarden/__init__.py index 23b8bcdc..87e7b4b9 100644 --- a/licensing/bitwarden/__init__.py +++ b/.archive/bitwarden/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider from pathlib import Path from subprocess import run, CalledProcessError @@ -9,10 +10,9 @@ md_version = "2.0" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" -md_license = "BSD-3" +md_license = "MIT" md_url = "https://github.com/albertlauncher/python" -md_maintainers = "@ovitor" -md_credits = "Original author: @tylio" +md_authors = ["@ovitor", "@tylio", ] md_bin_dependencies = ["rbw"] diff --git a/licensing/bitwarden/bw.svg b/.archive/bitwarden/bw.svg similarity index 100% rename from licensing/bitwarden/bw.svg rename to .archive/bitwarden/bw.svg diff --git a/licensing/jetbrains_projects/LICENSE b/.archive/jetbrains_projects/LICENSE similarity index 100% rename from licensing/jetbrains_projects/LICENSE rename to .archive/jetbrains_projects/LICENSE diff --git a/licensing/jetbrains_projects/README.md b/.archive/jetbrains_projects/README.md similarity index 100% rename from licensing/jetbrains_projects/README.md rename to .archive/jetbrains_projects/README.md diff --git a/licensing/jetbrains_projects/__init__.py b/.archive/jetbrains_projects/__init__.py similarity index 97% rename from licensing/jetbrains_projects/__init__.py rename to .archive/jetbrains_projects/__init__.py index 8c66640e..82c766ad 100644 --- a/licensing/jetbrains_projects/__init__.py +++ b/.archive/jetbrains_projects/__init__.py @@ -1,3 +1,8 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018-2020 Markus Richter +# Copyright (c) 2018-2023 Thomas Queste +# Copyright (c) 2023 Valentin Maerten + """ Supported IDEs: @@ -21,8 +26,7 @@ md_description = "Open your JetBrains projects" md_license = "GPL-3" md_url = "https://github.com/albertlauncher/python/" -md_maintainers = ["@mqus", "@tomsquest"] -md_authors = ["@mqus", "@tomsquest"] +md_authors = ["@mqus", "@tomsquest", "@vmaerten"] @dataclass diff --git a/licensing/jetbrains_projects/androidstudio.svg b/.archive/jetbrains_projects/androidstudio.svg similarity index 100% rename from licensing/jetbrains_projects/androidstudio.svg rename to .archive/jetbrains_projects/androidstudio.svg diff --git a/licensing/jetbrains_projects/clion.svg b/.archive/jetbrains_projects/clion.svg similarity index 100% rename from licensing/jetbrains_projects/clion.svg rename to .archive/jetbrains_projects/clion.svg diff --git a/licensing/jetbrains_projects/datagrip.svg b/.archive/jetbrains_projects/datagrip.svg similarity index 100% rename from licensing/jetbrains_projects/datagrip.svg rename to .archive/jetbrains_projects/datagrip.svg diff --git a/licensing/jetbrains_projects/dataspell.svg b/.archive/jetbrains_projects/dataspell.svg similarity index 100% rename from licensing/jetbrains_projects/dataspell.svg rename to .archive/jetbrains_projects/dataspell.svg diff --git a/licensing/jetbrains_projects/goland.svg b/.archive/jetbrains_projects/goland.svg similarity index 100% rename from licensing/jetbrains_projects/goland.svg rename to .archive/jetbrains_projects/goland.svg diff --git a/licensing/jetbrains_projects/idea.svg b/.archive/jetbrains_projects/idea.svg similarity index 100% rename from licensing/jetbrains_projects/idea.svg rename to .archive/jetbrains_projects/idea.svg diff --git a/licensing/jetbrains_projects/phpstorm.svg b/.archive/jetbrains_projects/phpstorm.svg similarity index 100% rename from licensing/jetbrains_projects/phpstorm.svg rename to .archive/jetbrains_projects/phpstorm.svg diff --git a/licensing/jetbrains_projects/pycharm.svg b/.archive/jetbrains_projects/pycharm.svg similarity index 100% rename from licensing/jetbrains_projects/pycharm.svg rename to .archive/jetbrains_projects/pycharm.svg diff --git a/licensing/jetbrains_projects/rider.svg b/.archive/jetbrains_projects/rider.svg similarity index 100% rename from licensing/jetbrains_projects/rider.svg rename to .archive/jetbrains_projects/rider.svg diff --git a/licensing/jetbrains_projects/rubymine.svg b/.archive/jetbrains_projects/rubymine.svg similarity index 100% rename from licensing/jetbrains_projects/rubymine.svg rename to .archive/jetbrains_projects/rubymine.svg diff --git a/licensing/jetbrains_projects/rustrover.svg b/.archive/jetbrains_projects/rustrover.svg similarity index 100% rename from licensing/jetbrains_projects/rustrover.svg rename to .archive/jetbrains_projects/rustrover.svg diff --git a/licensing/jetbrains_projects/webstorm.svg b/.archive/jetbrains_projects/webstorm.svg similarity index 100% rename from licensing/jetbrains_projects/webstorm.svg rename to .archive/jetbrains_projects/webstorm.svg diff --git a/licensing/mathematica_eval/__init__.py b/.archive/mathematica_eval/__init__.py similarity index 100% rename from licensing/mathematica_eval/__init__.py rename to .archive/mathematica_eval/__init__.py diff --git a/licensing/tex_to_unicode/__init__.py b/.archive/tex_to_unicode/__init__.py similarity index 100% rename from licensing/tex_to_unicode/__init__.py rename to .archive/tex_to_unicode/__init__.py diff --git a/licensing/tex_to_unicode/tex.png b/.archive/tex_to_unicode/tex.png similarity index 100% rename from licensing/tex_to_unicode/tex.png rename to .archive/tex_to_unicode/tex.png From 98b135ff262cf8986981cd9cc9687169f25191d9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 11:35:50 +0100 Subject: [PATCH 241/355] [jetbrains_projects] Reinstate proper licensing Closing https://github.com/albertlauncher/albert/issues/1351 Ignoring 860d190, 746456a, f5f5c50, 700b3be, 328dcf5, a7cda53 https://github.com/albertlauncher/python/commits/master/jetbrains_projects/ https://github.com/albertlauncher/python/commits/6ec2774966a524568112b27d285a4df6cb76ec2b/JetbrainsProjects/__init__.py?browsing_rename_history=true&new_path=jetbrains_projects/__init__.py&original_branch=6ec2774966a524568112b27d285a4df6cb76ec2b https://github.com/albertlauncher/python/commits/db49d114191feedf6fae0b268986074ef41373be/jetbrains-projects.py --- .archive/jetbrains_projects/LICENSE | 674 ------------------ .archive/jetbrains_projects/README.md | 24 - .../__init__.py | 42 +- .../androidstudio.svg | 0 .../clion.svg | 0 .../datagrip.svg | 0 .../dataspell.svg | 0 .../goland.svg | 0 .../idea.svg | 0 .../phpstorm.svg | 0 .../pycharm.svg | 0 .../rider.svg | 0 .../rubymine.svg | 0 .../rustrover.svg | 0 .../webstorm.svg | 0 15 files changed, 32 insertions(+), 708 deletions(-) delete mode 100644 .archive/jetbrains_projects/LICENSE delete mode 100644 .archive/jetbrains_projects/README.md rename {.archive/jetbrains_projects => jetbrains_projects}/__init__.py (89%) rename {.archive/jetbrains_projects => jetbrains_projects}/androidstudio.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/clion.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/datagrip.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/dataspell.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/goland.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/idea.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/phpstorm.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/pycharm.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/rider.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/rubymine.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/rustrover.svg (100%) rename {.archive/jetbrains_projects => jetbrains_projects}/webstorm.svg (100%) diff --git a/.archive/jetbrains_projects/LICENSE b/.archive/jetbrains_projects/LICENSE deleted file mode 100644 index f288702d..00000000 --- a/.archive/jetbrains_projects/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/.archive/jetbrains_projects/README.md b/.archive/jetbrains_projects/README.md deleted file mode 100644 index 08f9b880..00000000 --- a/.archive/jetbrains_projects/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Jetbrains-albert-plugin - -DISCLAIMER: This plugin has no affiliation with JetBrains s.r.o.. The icons are used under the terms specified [here](https://www.jetbrains.com/company/brand/#brand-guidelines). - -The plugin itself (the python file(s)) is licensed under the GPLv3 license. - -## How to use: - -Type `jb ` in the prompt, followed by your search term. Albert should show you a list of matching projects, scraped from your "recently edited" list of your Jetbrains IDEs. It tries to match the path of your project directory (not e.g. any files or contents). - -## Creating the project launcher: - -For this plugin to find the editors, you need to create a command line launcher for them. This is done by opening the IDE (for example PyCharm) and then going to `Tools -> Create Command-line Launcher...`. This will create a launcher (for example, `charm`) that this plugin will be able to find. - -## Authors: - -- Thomas Queste (@tomsquest) -- @mqus - -## Contributors: - -- @iyzana -- @Sharsie -- @dsager diff --git a/.archive/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py similarity index 89% rename from .archive/jetbrains_projects/__init__.py rename to jetbrains_projects/__init__.py index 82c766ad..dc598c5f 100644 --- a/.archive/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -1,15 +1,26 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2018-2020 Markus Richter # Copyright (c) 2018-2023 Thomas Queste # Copyright (c) 2023 Valentin Maerten """ -Supported IDEs: - -Android Studio, CLion, DataGrip, DataSpell, GoLand, IntelliJ IDEA, PhpStorm, PyCharm, Rider, RubyMine, WebStorm. - -Note: To open projects the command-line launcher is required. If your IDE has no \ -command-line launcher in $PATH, use `Tools` > `Create Command-line Launcher`. +This plugin allows you to quickly open projects of the Jetbrains IDEs + +* Android Studio +* CLion +* DataGrip +* DataSpell +* GoLand +* IntelliJ IDEA +* PhpStorm +* PyCharm +* Rider +* RubyMine +* WebStorm. + +Note that for this plugin to find the IDEs, a commandline launcher in $PATH is required. +Open the IDE and click Tools -> Create Command-line Launcher to add one. + +Disclaimer: This plugin has no affiliation with JetBrains s.r.o.. The icons are used under the terms specified here. """ from dataclasses import dataclass @@ -24,9 +35,9 @@ md_version = "1.6" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" -md_license = "GPL-3" -md_url = "https://github.com/albertlauncher/python/" -md_authors = ["@mqus", "@tomsquest", "@vmaerten"] +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/master/jetbrains_projects" +md_authors = ["@tomsquest", "@vmaerten", "@manuelschneid3r"] @dataclass @@ -198,3 +209,14 @@ def _make_item(self, editor: Editor, project: Project, query: TriggerQuery) -> I ) ], ) + + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip(), + 'widget_properties': { + 'textFormat': 'Qt::MarkdownText' + } + } + ] diff --git a/.archive/jetbrains_projects/androidstudio.svg b/jetbrains_projects/androidstudio.svg similarity index 100% rename from .archive/jetbrains_projects/androidstudio.svg rename to jetbrains_projects/androidstudio.svg diff --git a/.archive/jetbrains_projects/clion.svg b/jetbrains_projects/clion.svg similarity index 100% rename from .archive/jetbrains_projects/clion.svg rename to jetbrains_projects/clion.svg diff --git a/.archive/jetbrains_projects/datagrip.svg b/jetbrains_projects/datagrip.svg similarity index 100% rename from .archive/jetbrains_projects/datagrip.svg rename to jetbrains_projects/datagrip.svg diff --git a/.archive/jetbrains_projects/dataspell.svg b/jetbrains_projects/dataspell.svg similarity index 100% rename from .archive/jetbrains_projects/dataspell.svg rename to jetbrains_projects/dataspell.svg diff --git a/.archive/jetbrains_projects/goland.svg b/jetbrains_projects/goland.svg similarity index 100% rename from .archive/jetbrains_projects/goland.svg rename to jetbrains_projects/goland.svg diff --git a/.archive/jetbrains_projects/idea.svg b/jetbrains_projects/idea.svg similarity index 100% rename from .archive/jetbrains_projects/idea.svg rename to jetbrains_projects/idea.svg diff --git a/.archive/jetbrains_projects/phpstorm.svg b/jetbrains_projects/phpstorm.svg similarity index 100% rename from .archive/jetbrains_projects/phpstorm.svg rename to jetbrains_projects/phpstorm.svg diff --git a/.archive/jetbrains_projects/pycharm.svg b/jetbrains_projects/pycharm.svg similarity index 100% rename from .archive/jetbrains_projects/pycharm.svg rename to jetbrains_projects/pycharm.svg diff --git a/.archive/jetbrains_projects/rider.svg b/jetbrains_projects/rider.svg similarity index 100% rename from .archive/jetbrains_projects/rider.svg rename to jetbrains_projects/rider.svg diff --git a/.archive/jetbrains_projects/rubymine.svg b/jetbrains_projects/rubymine.svg similarity index 100% rename from .archive/jetbrains_projects/rubymine.svg rename to jetbrains_projects/rubymine.svg diff --git a/.archive/jetbrains_projects/rustrover.svg b/jetbrains_projects/rustrover.svg similarity index 100% rename from .archive/jetbrains_projects/rustrover.svg rename to jetbrains_projects/rustrover.svg diff --git a/.archive/jetbrains_projects/webstorm.svg b/jetbrains_projects/webstorm.svg similarity index 100% rename from .archive/jetbrains_projects/webstorm.svg rename to jetbrains_projects/webstorm.svg From e667d005dbd86cf36efab53b11d07ff974d48970 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:15:37 +0100 Subject: [PATCH 242/355] [aur:1.9] Show docstring in config widget --- aur/__init__.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/aur/__init__.py b/aur/__init__.py index 3989eb95..7dfb0c97 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -15,13 +15,12 @@ from albert import * -md_iid = '2.0' -md_version = "1.8" +md_iid = '2.2' +md_version = "1.9" md_name = "AUR" md_description = "Query and install AUR packages" md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/aur" -# md_platforms = ["Linux"] md_authors = "@manuelschneid3r" @@ -52,6 +51,14 @@ def __init__(self): info("No supported AUR helper found.") self.install_cmdline = None + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip() + } + ] + def handleTriggerQuery(self, query): for _ in range(50): sleep(0.01) From ea06843bb796093f2618430be807db6eee4bddef Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:15:57 +0100 Subject: [PATCH 243/355] [color:1.2] Show docstring in config widget --- color/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/color/__init__.py b/color/__init__.py index 6a840120..beda8f9b 100644 --- a/color/__init__.py +++ b/color/__init__.py @@ -18,8 +18,8 @@ from urllib.parse import quote_plus from string import hexdigits -md_iid = '2.0' -md_version = '1.1' +md_iid = '2.2' +md_version = '1.2' md_name = 'Color' md_description = 'Display color for color codes' md_license = 'MIT' @@ -66,4 +66,5 @@ def configWidget(self): 'type': 'label', 'text': __doc__.strip() } - ] \ No newline at end of file + ] + \ No newline at end of file From 88abbdc1c0e3458b2c0d0317c9e60cdd296df0bf Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:17:37 +0100 Subject: [PATCH 244/355] [dice_roll:1.4] Show docstring in config widget --- dice_roll/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dice_roll/__init__.py b/dice_roll/__init__.py index dc2e3c88..b65aa82b 100644 --- a/dice_roll/__init__.py +++ b/dice_roll/__init__.py @@ -15,8 +15,8 @@ Example: "roll 2d6 3d8 1d20" """ -md_iid = '2.0' -md_version = "1.3" +md_iid = '2.2' +md_version = "1.4" md_name = "Dice Roll" md_description = "Roll any number of dice" md_license = "MIT" @@ -141,6 +141,14 @@ def __init__(self): ) albert.PluginInstance.__init__(self, extensions=[self]) + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip(), + } + ] + def handleTriggerQuery(self, query: albert.Query) -> None: query_string = query.string.strip() try: From b3b38e8528c0f522d77a9f3f4655b1c4206d01c9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:19:09 +0100 Subject: [PATCH 245/355] [inhibit_sleep] Show docstring in config widget --- inhibit_sleep/__init__.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/inhibit_sleep/__init__.py b/inhibit_sleep/__init__.py index b27c65df..968cab1d 100644 --- a/inhibit_sleep/__init__.py +++ b/inhibit_sleep/__init__.py @@ -4,14 +4,14 @@ """ Provides an item 'Inhibit sleep' which can be used to temporarily disable system suspension. -This is a prototype using `systemd-inhibit`. A sophisticated implementation would probably use the systemd D-Bus +This is a prototype using `systemd-inhibit`. A sophisticated implementation would probably use the systemd D-Bus \ interface documented [here](https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html). """ from albert import * from subprocess import Popen, TimeoutExpired -md_iid = '2.0' +md_iid = '2.2' md_version = '1.0' md_name = 'Inhibit sleep' md_description = 'Inhibit system sleep mode.' @@ -50,6 +50,17 @@ def toggle(self): "sleep", "infinity"]) info(str(self.proc)) + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip(), + 'widget_properties': { + 'textFormat': 'Qt::MarkdownText' + } + } + ] + def handleGlobalQuery(self, query: GlobalQuery): stripped = query.string.strip().lower() if stripped in "inhibit sleep": From 704fbd641b9ea990d2aa1a6a1cea72dc86be3f8c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:24:30 +0100 Subject: [PATCH 246/355] [jetbrains_projects:1.7] Move icons in a dir, correct iid --- jetbrains_projects/__init__.py | 28 +++++++++---------- .../{ => icons}/androidstudio.svg | 0 jetbrains_projects/{ => icons}/clion.svg | 0 jetbrains_projects/{ => icons}/datagrip.svg | 0 jetbrains_projects/{ => icons}/dataspell.svg | 0 jetbrains_projects/{ => icons}/goland.svg | 0 jetbrains_projects/{ => icons}/idea.svg | 0 jetbrains_projects/{ => icons}/phpstorm.svg | 0 jetbrains_projects/{ => icons}/pycharm.svg | 0 jetbrains_projects/{ => icons}/rider.svg | 0 jetbrains_projects/{ => icons}/rubymine.svg | 0 jetbrains_projects/{ => icons}/rustrover.svg | 0 jetbrains_projects/{ => icons}/webstorm.svg | 0 13 files changed, 14 insertions(+), 14 deletions(-) rename jetbrains_projects/{ => icons}/androidstudio.svg (100%) rename jetbrains_projects/{ => icons}/clion.svg (100%) rename jetbrains_projects/{ => icons}/datagrip.svg (100%) rename jetbrains_projects/{ => icons}/dataspell.svg (100%) rename jetbrains_projects/{ => icons}/goland.svg (100%) rename jetbrains_projects/{ => icons}/idea.svg (100%) rename jetbrains_projects/{ => icons}/phpstorm.svg (100%) rename jetbrains_projects/{ => icons}/pycharm.svg (100%) rename jetbrains_projects/{ => icons}/rider.svg (100%) rename jetbrains_projects/{ => icons}/rubymine.svg (100%) rename jetbrains_projects/{ => icons}/rustrover.svg (100%) rename jetbrains_projects/{ => icons}/webstorm.svg (100%) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index dc598c5f..7409e8b0 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -31,8 +31,8 @@ from xml.etree import ElementTree from albert import * -md_iid = '2.0' -md_version = "1.6" +md_iid = '2.2' +md_version = "1.7" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" @@ -115,65 +115,65 @@ def __init__(self): editors = [ Editor( name="Android Studio", - icon=plugin_dir / "androidstudio.svg", + icon=plugin_dir / "icons" / "androidstudio.svg", config_dir_prefix="Google/AndroidStudio", binaries=["studio", "androidstudio", "android-studio", "android-studio-canary", "jdk-android-studio", "android-studio-system-jdk"]), Editor( name="CLion", - icon=plugin_dir / "clion.svg", + icon=plugin_dir / "icons" / "clion.svg", config_dir_prefix="JetBrains/CLion", binaries=["clion", "clion-eap"]), Editor( name="DataGrip", - icon=plugin_dir / "datagrip.svg", + icon=plugin_dir / "icons" / "datagrip.svg", config_dir_prefix="JetBrains/DataGrip", binaries=["datagrip", "datagrip-eap"]), Editor( name="DataSpell", - icon=plugin_dir / "dataspell.svg", + icon=plugin_dir / "icons" / "dataspell.svg", config_dir_prefix="JetBrains/DataSpell", binaries=["dataspell", "dataspell-eap"]), Editor( name="GoLand", - icon=plugin_dir / "goland.svg", + icon=plugin_dir / "icons" / "goland.svg", config_dir_prefix="JetBrains/GoLand", binaries=["goland", "goland-eap"]), Editor( name="IntelliJ IDEA", - icon=plugin_dir / "idea.svg", + icon=plugin_dir / "icons" / "idea.svg", config_dir_prefix="JetBrains/IntelliJIdea", binaries=["idea", "idea.sh", "idea-ultimate", "idea-ce-eap", "idea-ue-eap", "intellij-idea-ce", "intellij-idea-ce-eap", "intellij-idea-ue-bundled-jre", "intellij-idea-ultimate-edition", "intellij-idea-community-edition-jre", "intellij-idea-community-edition-no-jre"]), Editor( name="PhpStorm", - icon=plugin_dir / "phpstorm.svg", + icon=plugin_dir / "icons" / "phpstorm.svg", config_dir_prefix="JetBrains/PhpStorm", binaries=["phpstorm", "phpstorm-eap"]), Editor( name="PyCharm", - icon=plugin_dir / "pycharm.svg", + icon=plugin_dir / "icons" / "pycharm.svg", config_dir_prefix="JetBrains/PyCharm", binaries=["charm", "pycharm", "pycharm-eap"]), Editor( name="Rider", - icon=plugin_dir / "rider.svg", + icon=plugin_dir / "icons" / "rider.svg", config_dir_prefix="JetBrains/Rider", binaries=["rider", "rider-eap"]), Editor( name="RubyMine", - icon=plugin_dir / "rubymine.svg", + icon=plugin_dir / "icons" / "rubymine.svg", config_dir_prefix="JetBrains/RubyMine", binaries=["rubymine", "rubymine-eap", "jetbrains-rubymine", "jetbrains-rubymine-eap"]), Editor( name="WebStorm", - icon=plugin_dir / "webstorm.svg", + icon=plugin_dir / "icons" / "webstorm.svg", config_dir_prefix="JetBrains/WebStorm", binaries=["webstorm", "webstorm-eap"]), Editor( name="RustRover", - icon=plugin_dir / "rustrover.svg", + icon=plugin_dir / "icons" / "rustrover.svg", config_dir_prefix="JetBrains/RustRover", binaries=["rustrover", "rustrover-eap"]), ] diff --git a/jetbrains_projects/androidstudio.svg b/jetbrains_projects/icons/androidstudio.svg similarity index 100% rename from jetbrains_projects/androidstudio.svg rename to jetbrains_projects/icons/androidstudio.svg diff --git a/jetbrains_projects/clion.svg b/jetbrains_projects/icons/clion.svg similarity index 100% rename from jetbrains_projects/clion.svg rename to jetbrains_projects/icons/clion.svg diff --git a/jetbrains_projects/datagrip.svg b/jetbrains_projects/icons/datagrip.svg similarity index 100% rename from jetbrains_projects/datagrip.svg rename to jetbrains_projects/icons/datagrip.svg diff --git a/jetbrains_projects/dataspell.svg b/jetbrains_projects/icons/dataspell.svg similarity index 100% rename from jetbrains_projects/dataspell.svg rename to jetbrains_projects/icons/dataspell.svg diff --git a/jetbrains_projects/goland.svg b/jetbrains_projects/icons/goland.svg similarity index 100% rename from jetbrains_projects/goland.svg rename to jetbrains_projects/icons/goland.svg diff --git a/jetbrains_projects/idea.svg b/jetbrains_projects/icons/idea.svg similarity index 100% rename from jetbrains_projects/idea.svg rename to jetbrains_projects/icons/idea.svg diff --git a/jetbrains_projects/phpstorm.svg b/jetbrains_projects/icons/phpstorm.svg similarity index 100% rename from jetbrains_projects/phpstorm.svg rename to jetbrains_projects/icons/phpstorm.svg diff --git a/jetbrains_projects/pycharm.svg b/jetbrains_projects/icons/pycharm.svg similarity index 100% rename from jetbrains_projects/pycharm.svg rename to jetbrains_projects/icons/pycharm.svg diff --git a/jetbrains_projects/rider.svg b/jetbrains_projects/icons/rider.svg similarity index 100% rename from jetbrains_projects/rider.svg rename to jetbrains_projects/icons/rider.svg diff --git a/jetbrains_projects/rubymine.svg b/jetbrains_projects/icons/rubymine.svg similarity index 100% rename from jetbrains_projects/rubymine.svg rename to jetbrains_projects/icons/rubymine.svg diff --git a/jetbrains_projects/rustrover.svg b/jetbrains_projects/icons/rustrover.svg similarity index 100% rename from jetbrains_projects/rustrover.svg rename to jetbrains_projects/icons/rustrover.svg diff --git a/jetbrains_projects/webstorm.svg b/jetbrains_projects/icons/webstorm.svg similarity index 100% rename from jetbrains_projects/webstorm.svg rename to jetbrains_projects/icons/webstorm.svg From 3299f14f316c6bac80029a12fcb14ab4956155ec Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:25:28 +0100 Subject: [PATCH 247/355] [pomodora:1.4] Show docstring in config widget --- pomodoro/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 55ac7180..3e75decb 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -12,8 +12,8 @@ from albert import * -md_iid = '2.0' -md_version = "1.3" +md_iid = '2.2' +md_version = "1.4" md_name = "Pomodoro" md_description = "Set up a Pomodoro timer" md_license = "MIT" @@ -85,6 +85,14 @@ def __init__(self): self.pomodoro = PomodoroTimer() self.iconUrls = [f"file:{Path(__file__).parent}/pomodoro.svg"] + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip(), + } + ] + def handleTriggerQuery(self, query): item = StandardItem( id=md_id, From 685734155c9dc08152684857174bb11300621be7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:25:50 +0100 Subject: [PATCH 248/355] [timer:1.8] Show docstring in config widget --- timer/__init__.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/timer/__init__.py b/timer/__init__.py index fc3020d7..0a577485 100644 --- a/timer/__init__.py +++ b/timer/__init__.py @@ -19,8 +19,8 @@ from albert import * -md_iid = '2.0' -md_version = "1.7" +md_iid = '2.2' +md_version = "1.8" md_name = "Timer" md_description = "Set up timers" md_license = "MIT" @@ -73,6 +73,15 @@ def onTimerTimeout(self, timer): ) self.deleteTimer(timer) + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip(), + 'widget_properties': { 'textFormat': 'Qt::MarkdownText' } + } + ] + def handleTriggerQuery(self, query): if not query.isValid: return From 5a34d94a8939ce4ad4edf9a842826f9138c4fbf5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:26:03 +0100 Subject: [PATCH 249/355] [translators:1.5] Show docstring in config widget --- translators/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/translators/__init__.py b/translators/__init__.py index 7ed4fc59..36b563eb 100644 --- a/translators/__init__.py +++ b/translators/__init__.py @@ -12,8 +12,8 @@ from albert import * import translators as ts -md_iid = '2.0' -md_version = "1.4" +md_iid = '2.2' +md_version = "1.5" md_name = "Translator" md_description = "Translate sentences using 'translators' package" md_license = "MIT" @@ -72,6 +72,10 @@ def lang(self, value): def configWidget(self): return [ + { + 'type': 'label', + 'text': __doc__.strip(), + }, { 'type': 'combobox', 'property': 'translator', From c00750406987cff65e1df23ea408332c81bbd53c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 14 Jan 2024 18:26:28 +0100 Subject: [PATCH 250/355] [zeal] Remove unused docstring --- zeal/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/zeal/__init__.py b/zeal/__init__.py index 7ebae3c2..1201d130 100644 --- a/zeal/__init__.py +++ b/zeal/__init__.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2024 Manuel Schneider -"""Search in Zeal offline docs.""" - from albert import * md_iid = '2.0' From 8c96cd374f16d267e6952a218c45c9d8017999e4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 19 Jan 2024 00:33:32 +0100 Subject: [PATCH 251/355] [pomodoro:1.5] Fix * notifications * property synopsis * Ux. Dislpay action --- pomodoro/__init__.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 3e75decb..2849131d 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -2,7 +2,7 @@ # Copyright (c) 2024 Manuel Schneider """ -https://en.wikipedia.org/wiki/Pomodoro_Technique +Wiki: [Pomodoro_Technique](https://en.wikipedia.org/wiki/Pomodoro_Technique). """ import subprocess @@ -13,7 +13,7 @@ from albert import * md_iid = '2.2' -md_version = "1.4" +md_version = "1.5" md_name = "Pomodoro" md_description = "Set up a Pomodoro timer" md_license = "MIT" @@ -26,22 +26,23 @@ class PomodoroTimer: def __init__(self): self.isBreak = True self.timer = None + self.notification = None def timeout(self): if self.isBreak: duration = self.pomodoroDuration * 60 self.timer = threading.Timer(duration, self.timeout) self.endTime = time.time() + duration - sendTrayNotification("PomodoroTimer", "Let's go to work!") + self.notification = Notification("PomodoroTimer", "Let's go to work!") self.timer.start() else: self.remainingTillLongBreak -= 1 if self.remainingTillLongBreak == 0: self.remainingTillLongBreak = self.count - sendTrayNotification("PomodoroTimer", "Take a long break (%s min)" % self.longBreakDuration) + self.notification = Notification("PomodoroTimer", "Take a long break (%s min)" % self.longBreakDuration) duration = self.longBreakDuration * 60 else: - sendTrayNotification("PomodoroTimer", "Take a short break (%s min)" % self.breakDuration) + self.notification = Notification("PomodoroTimer", "Take a short break (%s min)" % self.breakDuration) duration = self.breakDuration * 60 self.endTime = time.time() + duration self.timer = threading.Timer(duration, self.timeout) @@ -90,6 +91,7 @@ def configWidget(self): { 'type': 'label', 'text': __doc__.strip(), + 'widget_properties': {'textFormat': 'Qt::MarkdownText'} } ] @@ -97,30 +99,32 @@ def handleTriggerQuery(self, query): item = StandardItem( id=md_id, iconUrls=self.iconUrls, - text=md_name ) if self.pomodoro.isActive(): + item.text = "Stop Pomodoro" item.actions = [Action("stop", "Stop", lambda p=self.pomodoro: p.stop())] if self.pomodoro.isBreak: whatsNext = "Pomodoro" else: whatsNext = "Long break" if self.pomodoro.remainingTillLongBreak == 1 else "Short break" - item.subtext = "Stop pomodoro (Next: %s at %s)" \ - % (whatsNext, time.strftime("%X", time.localtime(self.pomodoro.endTime))) + item.subtext = "%s at %s" % (whatsNext, time.strftime("%X", time.localtime(self.pomodoro.endTime))) query.add(item) else: tokens = query.string.split() if len(tokens) > 4 or not all([t.isdigit() for t in tokens]): - item.subtext = "Invalid parameters. Use %s" % self.synopsis() + item.text = "Invalid parameters" + item.subtext = "Use %s" % self.synopsis query.add(item) else: p = int(tokens[0]) if len(tokens) > 0 else self.default_pomodoro_duration b = int(tokens[1]) if len(tokens) > 1 else self.default_break_duration lb = int(tokens[2]) if len(tokens) > 2 else self.default_longbreak_duration c = int(tokens[3]) if len(tokens) > 3 else self.default_pomodoro_count - item.subtext = "Start new pomodoro timer (%s min, break %s min, long break %s min, count %s)"\ - % (p, b, lb, c) - item.actions = [Action("start", "Start", lambda p=p, b=b, lb=lb, c=c: self.pomodoro.start(p, b, lb, c))] + + item.text = "Start Pomodoro" + item.subtext = f"{p} min, break {b} min, long break {lb} min, count {c}" + item.actions = [Action("start", "Start", + lambda p=p, b=b, lb=lb, c=c: self.pomodoro.start(p, b, lb, c))] query.add(item) From 581bff3e5b7218513f0394fe03b846a3e62a2238 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 26 Jan 2024 13:33:39 +0100 Subject: [PATCH 252/355] [bitwarden:2.1] Proper licensing See https://github.com/albertlauncher/albert/issues/1350 --- {.archive/bitwarden => bitwarden}/__init__.py | 5 ++--- {.archive/bitwarden => bitwarden}/bw.svg | 0 2 files changed, 2 insertions(+), 3 deletions(-) rename {.archive/bitwarden => bitwarden}/__init__.py (98%) rename {.archive/bitwarden => bitwarden}/bw.svg (100%) diff --git a/.archive/bitwarden/__init__.py b/bitwarden/__init__.py similarity index 98% rename from .archive/bitwarden/__init__.py rename to bitwarden/__init__.py index 87e7b4b9..72421d52 100644 --- a/.archive/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2024 Manuel Schneider from pathlib import Path from subprocess import run, CalledProcessError @@ -7,12 +6,12 @@ from albert import * md_iid = '2.1' -md_version = "2.0" +md_version = "2.1" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" md_license = "MIT" md_url = "https://github.com/albertlauncher/python" -md_authors = ["@ovitor", "@tylio", ] +md_authors = ["@ovitor", "@daviddeadly", "@manuelschneid3r"] md_bin_dependencies = ["rbw"] diff --git a/.archive/bitwarden/bw.svg b/bitwarden/bw.svg similarity index 100% rename from .archive/bitwarden/bw.svg rename to bitwarden/bw.svg From 14848376d5e7c345c80094dd2f098561bbb4334f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 6 Feb 2024 22:10:57 +0100 Subject: [PATCH 253/355] [docker:2.0] * Show error on conn failure. * Fix pathlib import --- docker/__init__.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/docker/__init__.py b/docker/__init__.py index f47905f0..3a2c8a21 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -1,11 +1,13 @@ # -*- coding: utf-8 -*- # Copyright (c) 2024 Manuel Schneider +from pathlib import Path + import docker from albert import * md_iid = "2.0" -md_version = "1.6" +md_version = "2.0" md_name = "Docker" md_description = "Manage docker images and containers" md_license = "MIT" @@ -31,10 +33,23 @@ def __init__(self): def handleGlobalQuery(self, query): rank_items = [] - try: - if not self.client: + + if not self.client: + try: self.client = docker.from_env() + except Exception as e: + rank_items.append(RankItem( + item=StandardItem( + id='except', + text="Failed starting docker client", + subtext=str(e), + iconUrls=self.icon_urls_running, + ), + score=1.0 + )) + return rank_items + try: for container in self.client.containers.list(all=True): if query.string in container.name: # Create dynamic actions @@ -79,7 +94,7 @@ def handleGlobalQuery(self, query): score=len(query.string)/len(tag) )) except Exception as e: - warning(e) + warning(str(e)) self.client = None return rank_items From f0831a4a2f0b3fcfe9ed06265131a587496cd892 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 10 Feb 2024 23:29:26 +0100 Subject: [PATCH 254/355] [jetbrains:1.8] * Bullets in config --- jetbrains_projects/__init__.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 7409e8b0..cde5006b 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -5,17 +5,17 @@ """ This plugin allows you to quickly open projects of the Jetbrains IDEs -* Android Studio -* CLion -* DataGrip -* DataSpell -* GoLand -* IntelliJ IDEA -* PhpStorm -* PyCharm -* Rider -* RubyMine -* WebStorm. +- Android Studio +- CLion +- DataGrip +- DataSpell +- GoLand +- IntelliJ IDEA +- PhpStorm +- PyCharm +- Rider +- RubyMine +- WebStorm. Note that for this plugin to find the IDEs, a commandline launcher in $PATH is required. Open the IDE and click Tools -> Create Command-line Launcher to add one. @@ -32,7 +32,7 @@ from albert import * md_iid = '2.2' -md_version = "1.7" +md_version = "1.8" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" From 72a8863accb81f484f5d348e11c91e706eede9e9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 27 Feb 2024 20:51:16 +0100 Subject: [PATCH 255/355] [pomodoro:1.6] * Fix authors metadata field --- pomodoro/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 2849131d..7e8ab084 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -13,12 +13,12 @@ from albert import * md_iid = '2.2' -md_version = "1.5" +md_version = "1.6" md_name = "Pomodoro" md_description = "Set up a Pomodoro timer" md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/master/pomodoro" -md_author = "@manuelschneid3r" +md_authors = "@manuelschneid3r" class PomodoroTimer: From cd790246d42fdf6ee8fe5cddc2c8adc13f101d5c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 27 Feb 2024 20:51:36 +0100 Subject: [PATCH 256/355] [pass:1.6] * Add url metadata --- pass/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pass/__init__.py b/pass/__init__.py index 9288c2af..d0c378f7 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -8,10 +8,11 @@ from albert import * md_iid = "2.1" -md_version = "1.5" +md_version = "1.6" md_name = "Pass" md_description = "Manage passwords in pass" md_license = "BSD-3" +md_url = "https://github.com/albertlauncher/python/tree/master/pass" md_authors = ["@benedictdudel", "@maxmil", "@Pete-Hamlin"] md_bin_dependencies = ["pass"] From faeddafbb1cb6781549ac789adf338c97491dc6c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 1 Mar 2024 11:47:24 +0100 Subject: [PATCH 257/355] [virtualbox:1.6] Add info on vboxapi requirement --- virtualbox/__init__.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py index 4b628a27..3b908840 100644 --- a/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -1,13 +1,18 @@ # -*- coding: utf-8 -*- # Copyright (c) 2024 Manuel Schneider +""" +This plugin is based on [virtualbox-python](https://pypi.org/project/virtualbox/) and needs the 'vboxapi' module which +is part of the VirtualBox SDK. Some distributions package the SDK, e.g. Arch has +[virtualbox-sdk](https://archlinux.org/packages/extra/x86_64/virtualbox-sdk/). +""" import virtualbox from virtualbox.library import LockType, MachineState from albert import * -md_iid = '2.0' -md_version = "1.5" +md_iid = '2.2' +md_version = "1.6" md_name = "VirtualBox" md_description = "Manage your VirtualBox machines" md_license = "MIT" @@ -67,6 +72,17 @@ def __init__(self): PluginInstance.__init__(self, extensions=[self]) self.iconUrls = ["xdg:virtualbox", ":unknown"] + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip(), + 'widget_properties': { + 'textFormat': 'Qt::MarkdownText' + } + } + ] + def handleTriggerQuery(self, query): items = [] pattern = query.string.strip().lower() From 96dc437e4dcbcc2fb7d8729fbe27ddca631c73ba Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 12:34:29 +0200 Subject: [PATCH 258/355] Remove albert.pyi Ship, install and update with plugin. Add python stubfile to ignore files --- .gitignore | 3 +- albert.pyi | 469 ----------------------------------------------------- 2 files changed, 2 insertions(+), 470 deletions(-) delete mode 100644 albert.pyi diff --git a/.gitignore b/.gitignore index 1d4436e8..bef49833 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ __pycache__ /.idea /.vscode -/.venv \ No newline at end of file +/.venv +albert.pyi \ No newline at end of file diff --git a/albert.pyi b/albert.pyi deleted file mode 100644 index 43eebdf8..00000000 --- a/albert.pyi +++ /dev/null @@ -1,469 +0,0 @@ -""" -# Albert Python interface v2.2 - - -The Python interface is a subset of the internal C++ interface exposed to Python with some minor adjustments. A Python -plugin is required to contain the mandatory metadata and a plugin class, both described below. To get started read the -top level classes and function names in this file. Most of them are self explanatory. In case of questions see the C++ -documentation at https://albertlauncher.github.io/reference/namespacealbert.html - - -## Mandatory metadata variables - -md_iid: str | Interface version (.) -md_version: str | Plugin version (.) -md_name: str | Human readable name -md_description: str | A brief, imperative description. (Like "Launch apps" or "Open files") - - -## Optional metadata variables: - -md_id | Identifier overwrite. [a-zA-Z0-9_]. Note: This variable is attached at runtime - | if it is unset and defaults to the module name. -md_license: str | Short form e.g. MIT or BSD-2 -md_url: str | Browsable source, issues etc -md_authors: [str|List(str)] | The authors. Preferably using mentionable Github usernames. -md_bin_dependencies: [str|List(str)] | Required executable(s). Have to match the name of the executable in $PATH. -md_lib_dependencies: [str|List(str)] | Required Python package(s). Have to match the PyPI package name. -md_credits: [str|List(str)] | Third party credit(s) and license notes - - -## The Plugin class - -The plugin class is the entry point for a Python plugin. It is instantiated on plugin initialization and has to subclass -PluginInstance. Implement extensions by subclassing _one_ extension class (TriggerQueryHandler etc…) provided by the -built-in `albert` module and pass the list of your extensions to the PluginInstance init function. Due to the -differences in type systems multiple inheritance of extensions is not supported. (Python does not support virtual -inheritance, which is used in the C++ space to inherit from 'Extension'). - -Changes in 2.1 - - - Add PluginInstance.readConfig - - Add PluginInstance.writeConfig - - Add PluginInstance.configWidget - -Changes in 2.2: - - - PluginInstance.configWidget supports 'label' - - __doc__ is not used anymore, since 0.23 drops long_description metadata - - md_maintainers not used anymore - - md_authors new optional field -""" - -from abc import abstractmethod, ABC -from enum import Enum -from typing import Any -from typing import Callable -from typing import List -from typing import Optional -from typing import Union -from typing import overload - - -class PluginInstance(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1PluginInstance.html""" - - def __init__(self, extensions: List[Extension] = []): - ... - - @property - def id(self) -> str: - ... - - @property - def name(self) -> str: - ... - - @property - def description(self) -> str: - ... - - @property - def cacheLocation(self) -> pathlib.Path: - ... - - @property - def configLocation(self) -> pathlib.Path: - ... - - @property - def dataLocation(self) -> pathlib.Path: - ... - - @property - def extensions(self) -> List[Extension]: - ... - - def initialize(self): - ... - - def finalize(self): - ... - - def readConfig(self, key: str, type: type[str|int|float|bool]) -> str|int|float|bool|None: - """ - Read a config value from the Albert settings. - Note: Due to limitations of QSettings on some platforms the type may be lost, therefore the type expected has to - be passed. - - Returns: - The requested value or None if the value does not exist or errors occurred. - """ - - def writeConfig(self, key: str, value: str|int|float|bool): - """Write a config value to the Albert settings.""" - - def configWidget(self) -> List[dict]: - """ - **Descriptive config widget factory.** - - Define a static config widget using a list of dicts, each defining a row in the resulting form layout. Each dict - must contain key 'type' having one of the supported types specified below. Each type may define further - keys. - - **A note on 'widget_properties'** - - This is a dict setting the widget properties of a QWidget or one of its derived classes. See Qt documentation - for a particular class. Note that due to the restricted type conversion only properties of type - str|int|float|bool are settable. - - **Supported row 'type's** - - * 'label' (since 2.2) - - Display text spanning both columns. Additional keys: - - - 'text': The text to display - - 'widget_properties': https://doc.qt.io/qt-6/qlabel.html. - - * 'checkbox' - - A form layout item to edit boolean properties. Additional keys: - - - 'label': The text displayed in front of the the editor widget. - - 'property': The name of the property that will be set on changes. - - 'widget_properties': https://doc.qt.io/qt-6/qcheckbox.html - - * 'lineedit' - - A form layout item to edit string properties. Additional keys: - - - 'label': The text displayed in front of the the editor widget. - - 'property': The name of the property that will be set on changes. - - 'widget_properties': https://doc.qt.io/qt-6/qlineedit.html - - * 'combobox' - - A form layout item to set string properties using a list of options. Additional keys: - - - 'label': The text displayed in front of the the editor widget. - - 'property': The name of the property that will be set on changes. - - 'items': The list of strings used to populate the combobox. - - 'widget_properties': https://doc.qt.io/qt-6/qcombobox.html - - * 'spinbox' - - A form layout item to edit integer properties. Additional keys: - - - 'label': The text displayed in front of the the editor widget. - - 'property': The name of the property that will be set on changes. - - 'widget_properties': https://doc.qt.io/qt-6/qspinbox.html - - * 'doublespinbox' - - A form layout item to edit float properties. Additional keys: - - - 'label': The text displayed in front of the the editor widget. - - 'property': The name of the property that will be set on changes. - - 'widget_properties': https://doc.qt.io/qt-6/qdoublespinbox.html - - Returns: - A list of dicts, describing a form layout as defined above. - """ - -class Action: - """https://albertlauncher.github.io/reference/classalbert_1_1Action.html""" - - def __init__(self, - id: str, - text: str, - callable: Callable): - ... - - -class Item(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1Item.html""" - - @abstractmethod - def id(self) -> str: - ... - - @abstractmethod - def text(self) -> str: - ... - - @abstractmethod - def subtext(self) -> str: - ... - - @abstractmethod - def inputActionText(self) -> str: - ... - - @abstractmethod - def iconUrls(self) -> List[str]: - """See https://albertlauncher.github.io/reference/classalbert_1_1IconProvider.html""" - - @abstractmethod - def actions(self) -> List[Action]: - ... - - -class StandardItem(Item): - """https://albertlauncher.github.io/reference/structalbert_1_1StandardItem.html""" - - def __init__(self, - id: str = '', - text: str = '', - subtext: str = '', - iconUrls: List[str] = [], - actions: List[Action] = [], - inputActionText: Optional[str] = ''): - ... - - id: str - text: str - subtext: str - iconUrls: List[str] - actions: List[Action] - inputActionText: str - - -class Extension(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1Extension.html""" - - @property - def id(self) -> str: - ... - - @property - def name(self) -> str: - ... - - @property - def description(self) -> str: - ... - - -class FallbackHandler(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1FallbackHandler.html""" - - @abstractmethod - def fallbacks(self, query: str ) ->List[Item]: - ... - - -class TriggerQuery(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1TriggerQueryHandler_1_1TriggerQuery.html""" - - @property - def trigger(self) -> str: - ... - - @property - def string(self) -> str: - ... - - @property - def isValid(self) -> bool: - ... - - @overload - def add(self, item: Item): - ... - - @overload - def add(self, item: List[Item]): - ... - - -class TriggerQueryHandler(Extension): - """https://albertlauncher.github.io/reference/classalbert_1_1TriggerQueryHandler.html""" - - def __init__(self, - id: str, - name: str, - description: str, - synopsis: str = '', - defaultTrigger: str = f'{id} ', - allowTriggerRemap: str = true, - supportsFuzzyMatching: bool = False): - ... - - @property - def synopsis(self) -> str: - ... - - @property - def trigger(self) -> str: - ... - - @property - def defaultTrigger(self) -> str: - ... - - @property - def allowTriggerRemap(self) -> bool: - ... - - @property - def supportsFuzzyMatching(self) -> bool: - ... - - @property - def fuzzyMatching(self) -> bool: - ... - - @fuzzyMatching.setter - def setFuzzyMatching(self, enabled: bool): - ... - - @abstractmethod - def handleTriggerQuery(self, query: TriggerQuery): - ... - - -class RankItem: - """https://albertlauncher.github.io/reference/classalbert_1_1RankItem.html""" - - def __init__(self, item: Item, score: float): - ... - - item: Item - score: float - - -class GlobalQuery(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1GlobalQueryHandler_1_1GlobalQuery.html""" - - @property - def string(self) -> str: - ... - - @property - def isValid(self) -> bool: - ... - - -class GlobalQueryHandler(TriggerQueryHandler): - """https://albertlauncher.github.io/reference/classalbert_1_1GlobalQueryHandler.html""" - - def __init__(self, - id: str, - name: str, - description: str, - synopsis: str = '', - defaultTrigger: str = f'{id} ', - allowTriggerRemap: str = true, - supportsFuzzyMatching: bool = False): - ... - - @abstractmethod - def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: - ... - - def applyUsageScore(self, rank_items: List[RankItem]): - ... - - def handleTriggerQuery(self, query: TriggerQuery): - ... - - -class IndexItem: - """https://albertlauncher.github.io/reference/classalbert_1_1IndexItem.html""" - - def __init__(self, item: AbstractItem, string: str): - ... - - item: AbstractItem - string: str - - -class IndexQueryHandler(GlobalQueryHandler): - """https://albertlauncher.github.io/reference/classalbert_1_1IndexQueryHandler.html""" - - @abstractmethod - def updateIndexItems(self): - ... - - def setIndexItems(self, indexItems: List[RankItem]): - ... - - def handleGlobalQuery(self, query: GlobalQuery) -> List[RankItem]: - ... - - -class Notification: - - def __init__(self, title: str, subtitle: str = '', text: str = ''): - ... - - -def debug(arg: Any): - """Module attached attribute""" - - -def info(arg: Any): - """Module attached attribute""" - - -def warning(arg: Any): - """Module attached attribute""" - - -def critical(arg: Any): - """Module attached attribute""" - - -def setClipboardText(text: str=''): - """ - Set the system clipboard text. - Args: - text: The text used to set the clipboard - """ - - -def setClipboardTextAndPaste(text: str=''): - """ - Set the system clipboard text and paste to the front-most window - Args: - text: The text used to set the clipboard - """ - - -def openUrl(url: str = ''): - """ - Open an URL using QDesktopServices::openUrl. - Args: - url: The URL to open - """ - - -def runDetachedProcess(cmdln: List[str] = [], workdir: str = ''): - """ - Run a detached process. - Args: - cmdln: The commandline to run in the terminal (argv) - workdir: The working directory used to run the terminal - """ - - -def runTerminal(script: str = '', workdir: str = '', close_on_exit: bool = False): - """ - Run a script in the users shell and terminal. - Args: - script: The script to be executed. - workdir: The working directory used to run the process - close_on_exit: Close the terminal on exit. Otherwise exec $SHELL. - """ - From a7bb92d061f9ad041e01825929b1adef72bb72b1 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 12:23:29 +0200 Subject: [PATCH 259/355] [arch_wiki:1.6] - Min api 2.3 --- arch_wiki/__init__.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index 2dbf9456..2b8eb1db 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -8,12 +8,12 @@ from albert import * -md_iid = '2.0' -md_version = "1.5" -md_name = "Arch Linux Wiki" -md_description = "Search Arch Linux Wiki articles" -md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/arch_wiki" +md_iid = '2.3' +md_version = '1.6' +md_name = 'Arch Linux Wiki' +md_description = 'Search Arch Linux Wiki articles' +md_license = 'MIT' +md_url = 'https://github.com/albertlauncher/python/tree/main/arch_wiki' md_authors = "@manuelschneid3r" @@ -24,12 +24,8 @@ class Plugin(PluginInstance, TriggerQueryHandler): user_agent = "org.albert.extension.python.archwiki" def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='awiki ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__(self, self.id, self.name, self.description, defaultTrigger='awiki ') self.iconUrls = [f"file:{Path(__file__).parent}/arch.svg"] def handleTriggerQuery(self, query): @@ -62,7 +58,7 @@ def handleTriggerQuery(self, query): summary = data[2][i] url = data[3][i] - results.append(StandardItem(id=md_id, + results.append(StandardItem(id=self.id, text=title, subtext=summary if summary else url, iconUrls=self.iconUrls, @@ -73,7 +69,7 @@ def handleTriggerQuery(self, query): if results: query.add(results) else: - query.add(StandardItem(id=md_id, + query.add(StandardItem(id=self.id, text="Search '%s'" % query.string, subtext="No results. Start online search on Arch Wiki", iconUrls=self.iconUrls, @@ -81,7 +77,7 @@ def handleTriggerQuery(self, query): lambda s=query.string: openUrl(self.search_url % s))])) else: - query.add(StandardItem(id=md_id, + query.add(StandardItem(id=self.id, text=md_name, iconUrls=self.iconUrls, subtext="Enter a query to search on the Arch Wiki")) From f8c63dbdb6cee7cff761fd3a6b43e10662610c7b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 12:21:02 +0200 Subject: [PATCH 260/355] [aur:1.10] - Min api 2.3 --- aur/__init__.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/aur/__init__.py b/aur/__init__.py index 7dfb0c97..7fa763a1 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -15,12 +15,12 @@ from albert import * -md_iid = '2.2' -md_version = "1.9" +md_iid = '2.3' +md_version = "1.10" md_name = "AUR" md_description = "Query and install AUR packages" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/aur" +md_url = "https://github.com/albertlauncher/python/tree/main/aur" md_authors = "@manuelschneid3r" @@ -30,13 +30,11 @@ class Plugin(PluginInstance, TriggerQueryHandler): baseurl = 'https://aur.archlinux.org/rpc/' def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='aur ') - PluginInstance.__init__(self, extensions=[self]) - + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='aur ' + ) self.iconUrls = [f"file:{Path(__file__).parent}/arch.svg"] if which("yaourt"): @@ -80,7 +78,7 @@ def handleTriggerQuery(self, query): data = json.loads(response.read().decode()) if data['type'] == "error": query.add(StandardItem( - id=md_id, + id=self.id, text="Error", subtext=data['error'], iconUrls=self.iconUrls @@ -94,7 +92,7 @@ def handleTriggerQuery(self, query): for entry in results_json: name = entry['Name'] item = StandardItem( - id=md_id, + id=self.id, iconUrls=self.iconUrls, text=f"{entry['Name']} {entry['Version']}" ) @@ -141,7 +139,7 @@ def handleTriggerQuery(self, query): query.add(results) else: query.add(StandardItem( - id=md_id, + id=self.id, text=md_name, subtext="Enter a query to search the AUR", iconUrls=self.iconUrls, From 2bc81d40a9d072e038c0723af6d932d739801f0c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:57:24 +0200 Subject: [PATCH 261/355] [bitwarden:2.3] - Min api 2.3 --- bitwarden/__init__.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 72421d52..7cc1aec2 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -5,12 +5,12 @@ from albert import * -md_iid = '2.1' -md_version = "2.1" +md_iid = '2.3' +md_version = "2.3" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python" +md_url = "https://github.com/albertlauncher/python/tree/main/bitwarden" md_authors = ["@ovitor", "@daviddeadly", "@manuelschneid3r"] md_bin_dependencies = ["rbw"] @@ -18,12 +18,11 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='bw ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='bw ' + ) self.iconUrls = [f"file:{Path(__file__).parent}/bw.svg"] def handleTriggerQuery(self, query): From bb4e4a7fc92b9eab1d86c0fd86c162962d9af4ae Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:56:30 +0200 Subject: [PATCH 262/355] [coingecko:1.2] - Min api 2.3 --- coingecko/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index bf05ae9f..d4c9de14 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -8,12 +8,12 @@ from pathlib import Path from threading import Thread, Event -md_iid = "2.0" -md_version = "1.1" +md_iid = '2.3' +md_version = "1.2" md_name = "CoinGecko" md_description = "Access CoinGecko" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/coingecko" +md_url = "https://github.com/albertlauncher/python/tree/main/coingecko" md_authors = "@manuelschneid3r" @@ -86,12 +86,12 @@ class Plugin(PluginInstance, IndexQueryHandler): iconUrls = [f"file:{Path(__file__).parent}/coingecko.png"] def __init__(self): + PluginInstance.__init__(self) IndexQueryHandler.__init__( - self, md_id, md_name, md_description, + self, self.id, self.name, self.description, defaultTrigger='cg ', synopsis='< symbol | name >' ) - PluginInstance.__init__(self, extensions=[self]) self.items = [] self.mtime = 0 @@ -99,7 +99,7 @@ def __init__(self): self.thread = CoinFetcherThread(self.updateIndexItems, self.coinCacheFilePath) self.thread.start() - def finalize(self): + def __del__(self): self.thread.stop() self.thread.join() From ced8305ebaf79f660386cfa60bb64db6cd9e6bf5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:55:44 +0200 Subject: [PATCH 263/355] [color:1.3] - Min api 2.3 --- color/__init__.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/color/__init__.py b/color/__init__.py index beda8f9b..4ec468ae 100644 --- a/color/__init__.py +++ b/color/__init__.py @@ -18,8 +18,8 @@ from urllib.parse import quote_plus from string import hexdigits -md_iid = '2.2' -md_version = '1.2' +md_iid = '2.3' +md_version = '1.3' md_name = 'Color' md_description = 'Display color for color codes' md_license = 'MIT' @@ -30,12 +30,11 @@ class Plugin(PluginInstance, GlobalQueryHandler): def __init__(self): - GlobalQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='#') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + GlobalQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='#' + ) def handleGlobalQuery(self, query): rank_items = [] @@ -49,7 +48,7 @@ def handleGlobalQuery(self, query): rank_items.append( RankItem( StandardItem( - id=md_id, + id=self.id, text=s, subtext="The color for this code.", iconUrls=[f"gen:?background=%23{s}"], @@ -61,10 +60,5 @@ def handleGlobalQuery(self, query): return rank_items def configWidget(self): - return [ - { - 'type': 'label', - 'text': __doc__.strip() - } - ] + return [{ 'type': 'label', 'text': __doc__.strip() }] \ No newline at end of file From 5cecc32b7c6fa05a643339e49443ea5f7510b976 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:55:21 +0200 Subject: [PATCH 264/355] [copyq:1.5] - Min api 2.3 --- copyq/__init__.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/copyq/__init__.py b/copyq/__init__.py index 18a77185..6ff3d234 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -7,8 +7,8 @@ from albert import * -md_iid = '2.0' -md_version = "1.4" +md_iid = '2.3' +md_version = "1.5" md_name = "CopyQ" md_description = "Access CopyQ clipboard" md_license = "BSD-2-Clause" @@ -50,13 +50,11 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis="", - defaultTrigger='cq ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='cp ' + ) def handleTriggerQuery(self, query): items = [] @@ -79,7 +77,7 @@ def handleTriggerQuery(self, query): ) items.append( StandardItem( - id=md_id, + id=self.id, iconUrls=["xdg:copyq"], text=text, subtext="%s: %s" % (row, ", ".join(json_obj["mimetypes"])), From 5efb549073d995081af286f8cd483fda7ddc2754 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:54:51 +0200 Subject: [PATCH 265/355] [dice_roll:1.5] - Min api 2.3 --- dice_roll/__init__.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/dice_roll/__init__.py b/dice_roll/__init__.py index b65aa82b..ae12f472 100644 --- a/dice_roll/__init__.py +++ b/dice_roll/__init__.py @@ -15,8 +15,8 @@ Example: "roll 2d6 3d8 1d20" """ -md_iid = '2.2' -md_version = "1.4" +md_iid = '2.3' +md_version = "1.5" md_name = "Dice Roll" md_description = "Roll any number of dice" md_license = "MIT" @@ -132,22 +132,15 @@ class Plugin(albert.PluginInstance, albert.TriggerQueryHandler): """A plugin to roll dice""" def __init__(self): - albert.TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, + albert.PluginInstance.__init__(self) + albert.TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, synopsis="d [d ...]", - defaultTrigger="roll ", + defaultTrigger='roll ' ) - albert.PluginInstance.__init__(self, extensions=[self]) def configWidget(self): - return [ - { - 'type': 'label', - 'text': __doc__.strip(), - } - ] + return [{ 'type': 'label', 'text': __doc__.strip() }] def handleTriggerQuery(self, query: albert.Query) -> None: query_string = query.string.strip() From 60f19a772c7e65f32ffb10f2696fbec79e381f54 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:54:16 +0200 Subject: [PATCH 266/355] [docker:2.1] - Min api 2.3 --- docker/__init__.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/docker/__init__.py b/docker/__init__.py index 3a2c8a21..1e6fc8bf 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -6,12 +6,12 @@ import docker from albert import * -md_iid = "2.0" -md_version = "2.0" +md_iid = '2.3' +md_version = "2.1" md_name = "Docker" md_description = "Manage docker images and containers" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/docker" +md_url = "https://github.com/albertlauncher/python/tree/main/docker" md_authors = "@manuelschneid3r" md_bin_dependencies = "docker" md_lib_dependencies = "docker" @@ -20,13 +20,12 @@ class Plugin(PluginInstance, GlobalQueryHandler): def __init__(self): - GlobalQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='d ', - synopsis='') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + GlobalQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='d ', + synopsis='' + ) self.icon_urls_running = [f"file:{Path(__file__).parent}/running.png"] self.icon_urls_stopped = [f"file:{Path(__file__).parent}/stopped.png"] self.client = None From 30b8e249fd3ef2a35e59b68f393ea4d08717fde9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:53:49 +0200 Subject: [PATCH 267/355] [duckduckgo:1.1] - Min api 2.3 --- duckduckgo/__init__.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/duckduckgo/__init__.py b/duckduckgo/__init__.py index f8865961..f04f08ea 100644 --- a/duckduckgo/__init__.py +++ b/duckduckgo/__init__.py @@ -11,8 +11,8 @@ from itertools import islice from time import sleep -md_iid = '2.0' -md_version = '1.0' +md_iid = '2.3' +md_version = '1.1' md_name = 'DuckDuckGo' md_description = 'Inline DuckDuckGo web search' md_license = "MIT" @@ -24,13 +24,11 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis="", - defaultTrigger='ddg ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='ddg ' + ) self.ddg = DDGS() self.iconUrls = [f"file:{Path(__file__).parent}/duckduckgo.svg"] @@ -48,7 +46,7 @@ def handleTriggerQuery(self, query): for r in islice(self.ddg.text(stripped, safesearch='off'), 10): query.add( StandardItem( - id=md_id, + id=self.id, text=r['title'], subtext=r['body'], iconUrls=self.iconUrls, From c4300ae9e09490095df422d02b25f6d6ab3ad91b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 22 Apr 2024 14:39:52 +0200 Subject: [PATCH 268/355] [emoji:2.2] - Check paste support - Min api 2.3 --- emoji/__init__.py | 56 ++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index bdf6db4e..120f1516 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -11,33 +11,28 @@ from albert import * -md_iid = '2.1' -md_version = "2.1" +md_iid = '2.3' +md_version = "2.2" md_name = "Emoji" md_description = "Find and copy emojis by name" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/emoji" +md_url = "https://github.com/albertlauncher/python/tree/main/emoji" md_authors = "@manuelschneid3r" class Plugin(PluginInstance, IndexQueryHandler): def __init__(self): - IndexQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger=':', - synopsis='') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + IndexQueryHandler.__init__(self, self.id, self.name, self.description, defaultTrigger=':') self.thread = None self._use_derived = self.readConfig('use_derived', bool) if self._use_derived is None: self._use_derived = False - def finalize(self): - if self.thread.is_alive(): + def __del__(self): + if self.thread and self.thread.is_alive(): self.thread.join() @property @@ -67,7 +62,7 @@ def updateIndexItems(self): def update_index_items_task(self): - def download_file(url: str, path: str) -> bool: + def download_file(url: str, path: Path): debug(f"Downloading {url}.") headers = {'User-Agent': 'Mozilla/5.0'} # otherwise github returns html request = urllib.request.Request(url, headers=headers) @@ -79,7 +74,7 @@ def download_file(url: str, path: str) -> bool: else: raise RuntimeError(f"Failed to download {url}. Status code: {response.getcode()}") - def get_fully_qualified_emojis(cache_path: str) -> list: + def get_fully_qualified_emojis(cache_path: Path) -> list: """Returns fully qualified emoji strings""" def convert_to_unicode_char(hex_code: str): @@ -124,7 +119,7 @@ def convert_to_unicode_str(hex_codes: str): return fully_qualified - def get_annotations(cache_path: str, use_derived: bool) -> dict: + def get_annotations(cache_path: Path, use_derived: bool) -> dict: # determine locale @@ -136,7 +131,7 @@ def get_annotations(cache_path: str, use_derived: bool) -> dict: # fetch localized cldr annotations 'full' - path_full = cache_path / 'emoji_annotations_full.json' + path_full = cache_path / f'emoji_annotations_full_{lang}.json' if not path_full.is_file(): url = 'https://raw.githubusercontent.com/unicode-org/cldr-json/main/cldr-json/' \ 'cldr-annotations-full/annotations/%s/annotations.json' % lang @@ -150,7 +145,7 @@ def get_annotations(cache_path: str, use_derived: bool) -> dict: # fetch localized cldr annotations 'derived' - path_derived = cache_path / 'emoji_annotations_derived.json' + path_derived = cache_path / f'emoji_annotations_derived_{lang}.json' if not path_derived.is_file(): url = 'https://raw.githubusercontent.com/unicode-org/cldr-json/main/cldr-json/' \ 'cldr-annotations-derived-full/annotationsDerived/%s/annotations.json' % lang @@ -192,21 +187,28 @@ def remove_redundancy(sentences): title = ann['tts'][0] aliases = remove_redundancy([title.replace(':', '').replace(',', ''), *ann['default']]) + actions = [] + if havePasteSupport(): + actions.append( + Action( + "paste", "Copy and paste to front-most window", + lambda emj=emoji: setClipboardTextAndPaste(emj) + ) + ) + + actions.append( + Action( + "copy", "Copy to clipboard", + lambda emj=emoji: setClipboardText(emj) + ) + ) + item = StandardItem( id=emoji, text=title.capitalize(), subtext=", ".join([a.capitalize() for a in aliases]), iconUrls=[f"gen:?text={emoji}"], - actions=[ - Action( - "paste", "Copy and paste to front-most window", - lambda emj=emoji: setClipboardTextAndPaste(emj) - ), - Action( - "copy", "Copy to clipboard", - lambda emj=emoji: setClipboardText(emj) - ), - ] + actions=actions ) for alias in aliases: From 9985c076576077d4fadd1d4db2074dc6513e792b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 15 May 2024 15:30:36 +0200 Subject: [PATCH 269/355] [goldendict:1.4] - Support flatpaks and goldendict-ng - Min api 2.3 --- goldendict/__init__.py | 55 +++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/goldendict/__init__.py b/goldendict/__init__.py index aebbc447..51eadcd6 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -1,41 +1,56 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017-2024 Manuel Schneider +import os +import shutil + from albert import * -md_iid = '2.0' -md_version = '1.3' +md_iid = '2.3' +md_version = '1.4' md_name = 'GoldenDict' -md_description = 'Searches in GoldenDict' +md_description = 'Quick access to GoldenDict' md_license = 'MIT' -md_url = 'https://github.com/albertlauncher/python/' +md_url = 'https://github.com/albertlauncher/python/tree/main/goldendict' md_authors = '@manuelschneid3r' -md_bin_dependencies = ['goldendict'] class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis='query', - defaultTrigger='gd ') - PluginInstance.__init__(self, extensions=[self]) - self.iconUrls = ["xdg:goldendict"] - - def handleTriggerQuery(self, query: TriggerQuery) -> None: - query_str = query.string.strip() - if not query_str: - return + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='gd ' + ) + + commands = [ + '/var/lib/flatpak/exports/bin/org.goldendict.GoldenDict', # flatpak + '/var/lib/flatpak/exports/bin/io.github.xiaoyifang.goldendict_ng', # flatpak ng + 'goldendict', # native + 'goldendict-ng', # native ng + ] + + executables = [e for e in [shutil.which(c) for c in commands] if e] + + if not executables: + raise RuntimeError(f'None of the GoldenDict distributions found.') + + self.executable = executables[0] + self.iconUrls = [f'xdg:{os.path.basename(self.executable)}'] + + if len(executables) > 1: + warning(f"Multiple GoldenDict commands found: {', '.join(executables)}") + warning(f"Using {self.executable}") + def handleTriggerQuery(self, query: TriggerQuery): + q = query.string.strip() query.add( StandardItem( id=md_name, text=md_name, - subtext=f'Look up {query_str} using GoldenDict', + subtext=f"Look up '{q}' in GoldenDict", iconUrls=self.iconUrls, - actions=[Action(md_name, md_name, lambda: runDetachedProcess(['goldendict', query_str]))], + actions=[Action(md_name, md_name, lambda e=self.executable: runDetachedProcess([e, q]))], ) ) From e3ce3bebd7a9115082e53c54df03968867237b56 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 22 Apr 2024 21:50:53 +0200 Subject: [PATCH 270/355] [inhibit_sleep:1.1] - Fix type hint - Min api 2.3 --- inhibit_sleep/__init__.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/inhibit_sleep/__init__.py b/inhibit_sleep/__init__.py index 968cab1d..3d620ebb 100644 --- a/inhibit_sleep/__init__.py +++ b/inhibit_sleep/__init__.py @@ -11,8 +11,8 @@ from albert import * from subprocess import Popen, TimeoutExpired -md_iid = '2.2' -md_version = '1.0' +md_iid = '2.3' +md_version = '1.1' md_name = 'Inhibit sleep' md_description = 'Inhibit system sleep mode.' md_license = "MIT" @@ -24,12 +24,11 @@ class Plugin(PluginInstance, GlobalQueryHandler): def __init__(self): - GlobalQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='is ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + GlobalQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='is ' + ) self.proc = None def finalize(self): @@ -61,7 +60,7 @@ def configWidget(self): } ] - def handleGlobalQuery(self, query: GlobalQuery): + def handleGlobalQuery(self, query): stripped = query.string.strip().lower() if stripped in "inhibit sleep": return [ From 5514fcc65c169b3b3f5821624f25ba4a953fd69f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 22 Apr 2024 14:40:40 +0200 Subject: [PATCH 271/355] [jb:1.9] Fix type hints --- jetbrains_projects/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index cde5006b..0b62b244 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -32,7 +32,7 @@ from albert import * md_iid = '2.2' -md_version = "1.8" +md_version = "1.9" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" @@ -179,7 +179,7 @@ def __init__(self): ] self.editors = [e for e in editors if e.binary is not None] - def handleTriggerQuery(self, query: TriggerQuery): + def handleTriggerQuery(self, query: Query): editor_project_pairs = [] for editor in self.editors: projects = editor.list_projects() @@ -192,7 +192,7 @@ def handleTriggerQuery(self, query: TriggerQuery): query.add([self._make_item(editor, project, query) for editor, project in editor_project_pairs]) - def _make_item(self, editor: Editor, project: Project, query: TriggerQuery) -> Item: + def _make_item(self, editor: Editor, project: Project, query: Query) -> Item: return StandardItem( id="%s-%s-%s" % (editor.binary, project.path, project.last_opened), text=project.name, From f12b90edf31ccdaa1221637a2df42d3e1375948b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:47:54 +0200 Subject: [PATCH 272/355] [jetbrains:1.10] - Min api 2.3 --- jetbrains_projects/__init__.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 0b62b244..623f8eb1 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -31,12 +31,12 @@ from xml.etree import ElementTree from albert import * -md_iid = '2.2' -md_version = "1.9" +md_iid = '2.3' +md_version = "1.10" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/jetbrains_projects" +md_url = "https://github.com/albertlauncher/python/tree/main/jetbrains_projects" md_authors = ["@tomsquest", "@vmaerten", "@manuelschneid3r"] @@ -103,13 +103,11 @@ class Plugin(PluginInstance, TriggerQueryHandler): executables = [] def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis='project name', - defaultTrigger='jb ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='jb ' + ) plugin_dir = Path(__file__).parent editors = [ From 8a99bd52911176c2e38d8d5b27ba7b2fd8b2e5db Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:46:48 +0200 Subject: [PATCH 273/355] [kill:1.4] - Min api 2.3 --- kill/__init__.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/kill/__init__.py b/kill/__init__.py index 73e3ca41..c443d2b1 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -9,23 +9,22 @@ from albert import * -md_iid = '2.0' -md_version = "1.3" +md_iid = '2.3' +md_version = "1.4" md_name = "Kill Process" md_description = "Kill processes" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/kill" +md_url = "https://github.com/albertlauncher/python/tree/main/kill" md_authors = ["@Pete-Hamlin", "@BenedictDwudel", "@ManuelSchneid3r"] class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='kill ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='kill ' + ) def handleTriggerQuery(self, query): if not query.isValid: From 54e59966e8ebc12e4ac9100a0f54bcf5a2beb5c1 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:45:01 +0200 Subject: [PATCH 274/355] [locate:1.10] - Min api 2.3 --- locate/__init__.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/locate/__init__.py b/locate/__init__.py index 494e20ac..8da7db90 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -13,12 +13,12 @@ from albert import * -md_iid = '2.0' -md_version = "1.9" +md_iid = '2.3' +md_version = "1.10" md_name = "Locate" md_description = "Find and open files using locate" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/locate" +md_url = "https://github.com/albertlauncher/python/tree/main/locate" md_bin_dependencies = "locate" md_authors = "@manuelschneid3r" @@ -26,13 +26,12 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis='', - defaultTrigger="'") - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + synopsis='', + defaultTrigger="'" + ) self.iconUrls = [ "xdg:preferences-system-search", From 37588a1a86875cfd68ea6f39ee3a491bb7c5facf Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:44:30 +0200 Subject: [PATCH 275/355] [pacman:1.10] - Min api 2.3 --- pacman/__init__.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/pacman/__init__.py b/pacman/__init__.py index a47f39fd..a522c73a 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -7,12 +7,12 @@ from albert import Action, StandardItem, PluginInstance, TriggerQueryHandler, runTerminal, openUrl -md_iid = '2.0' -md_version = "1.9" +md_iid = '2.3' +md_version = "1.10" md_name = "PacMan" md_description = "Search, install and remove packages" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/pacman" +md_url = "https://github.com/albertlauncher/python/tree/main/pacman" md_authors = "@ManuelSchneid3r" md_bin_dependencies = ["pacman", "expac"] @@ -22,13 +22,12 @@ class Plugin(PluginInstance, TriggerQueryHandler): pkgs_url = "https://www.archlinux.org/packages/" def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis='', - defaultTrigger='pac ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + synopsis='', + defaultTrigger='pac ' + ) self.iconUrls = [ "xdg:archlinux-logo", "xdg:system-software-install", @@ -41,7 +40,7 @@ def handleTriggerQuery(self, query): # Update item on empty queries if not stripped: query.add(StandardItem( - id="%s-update" % md_id, + id="%s-update" % self.id, text="Pacman package manager", subtext="Enter the package you are looking for or hit enter to update.", iconUrls=self.iconUrls, @@ -91,7 +90,7 @@ def handleTriggerQuery(self, query): actions.append(Action("proj_url", "Show project website", lambda u=pkg_purl: openUrl(u))) item = StandardItem( - id="%s_%s_%s" % (md_id, pkg_repo, pkg_name), + id="%s_%s_%s" % (self.id, pkg_repo, pkg_name), iconUrls=self.iconUrls, text="%s %s [%s]" % (pkg_name, pkg_vers, pkg_repo), subtext=f"{pkg_desc} [Installed]" if pkg_installed else f"{pkg_desc}", @@ -104,7 +103,7 @@ def handleTriggerQuery(self, query): query.add(items) else: query.add(StandardItem( - id="%s-empty" % md_id, + id="%s-empty" % self.id, text="Search on archlinux.org", subtext="No results found in the local database", iconUrls=self.iconUrls, From caede59a94f580081da5abd2aa16dd6a9ef15108 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:44:04 +0200 Subject: [PATCH 276/355] [pass:1.7] - Min api 2.3 --- pass/__init__.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/pass/__init__.py b/pass/__init__.py index d0c378f7..567d1650 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -7,12 +7,12 @@ import os from albert import * -md_iid = "2.1" -md_version = "1.6" +md_iid = '2.3' +md_version = "1.7" md_name = "Pass" md_description = "Manage passwords in pass" md_license = "BSD-3" -md_url = "https://github.com/albertlauncher/python/tree/master/pass" +md_url = "https://github.com/albertlauncher/python/tree/main/pass" md_authors = ["@benedictdudel", "@maxmil", "@Pete-Hamlin"] md_bin_dependencies = ["pass"] @@ -22,15 +22,12 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): + PluginInstance.__init__(self) TriggerQueryHandler.__init__( - self, - id=md_id, - name=md_name, - description=md_description, - synopsis="", - defaultTrigger="pass ", + self, self.id, self.name, self.description, + synopsis='', + defaultTrigger='pass ' ) - PluginInstance.__init__(self, extensions=[self]) self.iconUrls = ["xdg:dialog-password"] self._use_otp = self.readConfig("use_otp", bool) or False self._otp_glob = self.readConfig("otp_glob", str) or "*-otp.gpg" From 412f53ed943822309899aa363d6d89118aeaaeda Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:43:28 +0200 Subject: [PATCH 277/355] [pomodoro:1.7] - Min api 2.3 --- pomodoro/__init__.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 7e8ab084..4a38a8d4 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -12,12 +12,12 @@ from albert import * -md_iid = '2.2' -md_version = "1.6" +md_iid = '2.3' +md_version = "1.7" md_name = "Pomodoro" md_description = "Set up a Pomodoro timer" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/pomodoro" +md_url = "https://github.com/albertlauncher/python/tree/main/pomodoro" md_authors = "@manuelschneid3r" @@ -76,13 +76,12 @@ class Plugin(PluginInstance, TriggerQueryHandler): default_pomodoro_count = 4 def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis='[duration [break duration [long break duration [count]]]]', - defaultTrigger='pomo ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + synopsis='[duration [break duration [long break duration [count]]]]', + defaultTrigger='pomo ' + ) self.pomodoro = PomodoroTimer() self.iconUrls = [f"file:{Path(__file__).parent}/pomodoro.svg"] @@ -97,7 +96,7 @@ def configWidget(self): def handleTriggerQuery(self, query): item = StandardItem( - id=md_id, + id=self.id, iconUrls=self.iconUrls, ) From b6faf30e471c15fe3728c0afe52b1925662ae1de Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:42:46 +0200 Subject: [PATCH 278/355] [python_eval:1.6] - Min api 2.3 --- python_eval/__init__.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/python_eval/__init__.py b/python_eval/__init__.py index 9f3813a5..c054025d 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -7,25 +7,24 @@ from albert import * -md_iid = '2.0' -md_version = "1.5" +md_iid = '2.3' +md_version = "1.6" md_name = "Python Eval" md_description = "Evaluate Python code" md_license = "BSD-3" -md_url = "https://github.com/albertlauncher/python/tree/master/python_eval" +md_url = "https://github.com/albertlauncher/python/tree/main/python_eval" md_authors = "@manuelschneid3r" class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis='', - defaultTrigger='py ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + synopsis='', + defaultTrigger='py ' + ) self.iconUrls = [f"file:{Path(__file__).parent}/python.svg"] def handleTriggerQuery(self, query): @@ -39,7 +38,7 @@ def handleTriggerQuery(self, query): result_str = str(result) query.add(StandardItem( - id=md_id, + id=self.id, text=result_str, subtext=type(result).__name__, inputActionText=query.trigger + result_str, From 2b7bb22422cb96d13dd5e32cbccdd615f66b4f69 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 21 Mar 2024 18:39:57 +0100 Subject: [PATCH 279/355] [syncthing:1.0] Initial prototype --- syncthing/__init__.py | 143 ++++++++++++++++++++++++++++++++++++++++ syncthing/syncthing.svg | 26 ++++++++ 2 files changed, 169 insertions(+) create mode 100644 syncthing/__init__.py create mode 100644 syncthing/syncthing.svg diff --git a/syncthing/__init__.py b/syncthing/__init__.py new file mode 100644 index 00000000..c43fa9e2 --- /dev/null +++ b/syncthing/__init__.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2024 Manuel Schneider + +""" +Quickly pause/resume/open/scan shares and devices. +""" + +from pathlib import Path + +from albert import * +from syncthing import Syncthing + +md_iid = '2.3' +md_version = "1.0" +md_name = "Syncthing" +md_description = "Trigger basic syncthing actions." +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/main/syncthing" +md_authors = "@manuelschneid3r" +md_lib_dependencies = "syncthing" + + +class Plugin(PluginInstance, GlobalQueryHandler): + + config_key = 'syncthing_api_key' + + def __init__(self): + PluginInstance.__init__(self) + GlobalQueryHandler.__init__(self, self.id, self.name, self.description, defaultTrigger='st ') + self.iconUrls = ["xdg:syncthing", f"file:{Path(__file__).parent}/syncthing.svg"] + self._api_key = self.readConfig(self.config_key, str) + if self._api_key: + self.st = Syncthing(self._api_key) + + @property + def api_key(self) -> str: + return self._api_key + + @api_key.setter + def api_key(self, value: str): + if self._api_key != value: + self._api_key = value + self.writeConfig(self.config_key, value) + self.st = Syncthing(self._api_key) + + + def configWidget(self): + return [ + { + 'type': 'label', + 'text': __doc__.strip(), + }, + { + 'type': 'lineedit', + 'property': 'api_key', + 'label': 'API key', + 'widget_properties': {'tooltip': 'You can find the API key using the web frontend.'} + } + ] + + def handleGlobalQuery(self, query): + + results = [] + + if self.st: + + config = self.st.system.config() + + devices = dict() + for d in config['devices']: + if not d['name']: + d['name'] = d['deviceID'] + d['_shared_folders'] = {} + devices[d['deviceID']] = d + + folders = dict() + for f in config['folders']: + if not f['label']: + f['label'] = f['id'] + for d in f['devices']: + devices[d['deviceID']]['_shared_folders'][f['id']] = f + folders[f['id']] = f + + matcher = Matcher(query.string) + + # create device items + for id, d in devices.items(): + device_name = d['name'] + + if match := matcher.match(device_name): + device_folders = ", ".join([f['label'] for f in d['_shared_folders'].values()]) + + actions = [] + if d['paused']: + actions.append( + Action("resume", "Resume synchronization", + lambda did=id: self.st.system.resume(did)) + ) + else: + actions.append( + Action("pause", "Pause synchronization", + lambda did=id: self.st.system.pause(did)) + ) + + results.append( + RankItem( + StandardItem( + id=id, + text=f"{device_name}", + subtext=f"{'Paused ' if d['paused'] else ''}Syncthing device. " + f"Shared: {device_folders if device_folders else 'Nothing'}.", + iconUrls=self.iconUrls, + actions=actions + ), + match.score + ) + ) + + # create folder items + for id, f in folders.items(): + folder_name = f['label'] + if match := matcher.match(folder_name): + folders_devices = ", ".join([devices[d['deviceID']]['name'] for d in f['devices']]) + results.append( + RankItem( + StandardItem( + id=id, + text=folder_name, + subtext=f"Syncthing folder {f['path']}. " + f"Shared with {folders_devices if folders_devices else 'nobody'}.", + iconUrls=self.iconUrls, + actions=[ + Action("scan", "Scan the folder", + lambda fid=id: self.st.database.scan(fid)), + Action("open", "Open this folder in file browser", + lambda p=f['path']: openUrl(f'file://{p}')) + ] + ), + match.score + ) + ) + + return results diff --git a/syncthing/syncthing.svg b/syncthing/syncthing.svg new file mode 100644 index 00000000..ce92210f --- /dev/null +++ b/syncthing/syncthing.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + From 8df7f609cbbb0ed1c7658f22588967660b005933 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 4 Jun 2024 12:16:08 +0200 Subject: [PATCH 280/355] [timer] Move to archive --- {timer => .archive/timer}/__init__.py | 6 +++--- timer/time.svg | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) rename {timer => .archive/timer}/__init__.py (96%) delete mode 100644 timer/time.svg diff --git a/timer/__init__.py b/.archive/timer/__init__.py similarity index 96% rename from timer/__init__.py rename to .archive/timer/__init__.py index 0a577485..5a22e160 100644 --- a/timer/__init__.py +++ b/.archive/timer/__init__.py @@ -19,12 +19,12 @@ from albert import * -md_iid = '2.2' +md_iid = '2.3' md_version = "1.8" md_name = "Timer" md_description = "Set up timers" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/timer" +md_url = "https://github.com/albertlauncher/python/tree/main/timer" md_authors = ["@manuelschneid3r", "@googol42"] @@ -48,7 +48,7 @@ def __init__(self): description=md_description, synopsis='[[hrs:]mins:]secs [name]', defaultTrigger='timer ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) self.iconUrls = [f"file:{Path(__file__).parent}/time.svg"] self.soundPath = Path(__file__).parent / "bing.wav" self.timers = [] diff --git a/timer/time.svg b/timer/time.svg deleted file mode 100644 index f6cc4d0b..00000000 --- a/timer/time.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 41f575bc672cadca75cd9c3183199500898de03d Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 22 Apr 2024 14:41:09 +0200 Subject: [PATCH 281/355] [tr:1.6] Check paste support --- translators/__init__.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/translators/__init__.py b/translators/__init__.py index 36b563eb..5ab65cc8 100644 --- a/translators/__init__.py +++ b/translators/__init__.py @@ -13,7 +13,7 @@ import translators as ts md_iid = '2.2' -md_version = "1.5" +md_version = "1.6" md_name = "Translator" md_description = "Translate sentences using 'translators' package" md_license = "MIT" @@ -112,19 +112,26 @@ def handleTriggerQuery(self, query): to_language=dst, timeout=5) + actions = [] + if havePasteSupport(): + actions.append( + Action( + "paste", "Copy to clipboard and paste to front-most window", + lambda t=translation: setClipboardTextAndPaste(t) + ) + ) + + actions.append( + Action("copy", "Copy to clipboard", + lambda t=translation: setClipboardText(t)) + ) + query.add(StandardItem( id=md_id, text=translation, subtext=f"{src.upper()} > {dst.upper()}", iconUrls=self.iconUrls, - actions=[ - Action( - "paste", "Copy to clipboard and paste to front-most window", - lambda t=translation: setClipboardTextAndPaste(t) - ), - Action("copy", "Copy to clipboard", - lambda t=translation: setClipboardText(t)) - ] + actions=actions )) except Exception as e: From 190f5cf6cfec5970c8bdcbab73ba8e3d956d0e45 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:29:17 +0200 Subject: [PATCH 282/355] [translators:1.7] - Min api 2.3 --- translators/__init__.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/translators/__init__.py b/translators/__init__.py index 5ab65cc8..6fb04efc 100644 --- a/translators/__init__.py +++ b/translators/__init__.py @@ -12,8 +12,8 @@ from albert import * import translators as ts -md_iid = '2.2' -md_version = "1.6" +md_iid = '2.3' +md_version = "1.7" md_name = "Translator" md_description = "Translate sentences using 'translators' package" md_license = "MIT" @@ -25,13 +25,12 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis="[[from] to] text", - defaultTrigger='tr ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + synopsis="[[from] to] text", + defaultTrigger='tr ' + ) self.iconUrls = [f"file:{Path(__file__).parent}/google_translate.png"] self._translator = self.readConfig('translator', str) @@ -127,7 +126,7 @@ def handleTriggerQuery(self, query): ) query.add(StandardItem( - id=md_id, + id=self.id, text=translation, subtext=f"{src.upper()} > {dst.upper()}", iconUrls=self.iconUrls, @@ -137,7 +136,7 @@ def handleTriggerQuery(self, query): except Exception as e: query.add(StandardItem( - id=md_id, + id=self.id, text="Error", subtext=str(e), iconUrls=self.iconUrls From 6ba92ba4837b67f3a1a908179948c1324381edc6 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:26:19 +0200 Subject: [PATCH 283/355] [virtualbox:1.7] - Min api 2.3 --- virtualbox/__init__.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py index 3b908840..8ba78272 100644 --- a/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -11,12 +11,12 @@ from albert import * -md_iid = '2.2' -md_version = "1.6" +md_iid = '2.3' +md_version = "1.7" md_name = "VirtualBox" md_description = "Manage your VirtualBox machines" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/virtualbox" +md_url = "https://github.com/albertlauncher/python/tree/main/virtualbox" md_authors = "@manuelschneid3r" md_lib_dependencies = ['virtualbox'] @@ -63,13 +63,12 @@ def pauseVm(vm): class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis='', - defaultTrigger='vbox ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + synopsis='', + defaultTrigger='vbox ' + ) self.iconUrls = ["xdg:virtualbox", ":unknown"] def configWidget(self): From 1c98aec4c5fad2bb213198a08dca5049756bff46 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:24:04 +0200 Subject: [PATCH 284/355] [vpn:1.5] - Min api 2.3 --- vpn/__init__.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/vpn/__init__.py b/vpn/__init__.py index 82177092..ef82febd 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -8,9 +8,8 @@ from albert import * -md_iid = '2.0' -md_version = "1.4" -md_id = "vpn" +md_iid = '2.3' +md_version = "1.5" md_name = "VPN" md_description = "Manage NetworkManager VPN connections" md_license = "MIT" @@ -24,12 +23,11 @@ class Plugin(PluginInstance, TriggerQueryHandler): VPNConnection = namedtuple('VPNConnection', ['name', 'connected']) def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='vpn ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='vpn ' + ) def getVPNConnections(self): consStr = subprocess.check_output( From 27c69f2d2d18aebde477da7edb2f7eac49ec072f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:10:23 +0200 Subject: [PATCH 285/355] [wikipedia:2.0] - Min api 2.3 - Add fuzzy search support --- wikipedia/__init__.py | 92 +++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 433f85c2..2305117a 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -10,27 +10,15 @@ import json from pathlib import Path -md_iid = '2.0' -md_version = "1.10" +md_iid = '2.3' +md_version = "2.0" md_name = "Wikipedia" md_description = "Search Wikipedia articles" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/tree/master/wikipedia" +md_url = "https://github.com/albertlauncher/python/tree/main/wikipedia" md_authors = "@manuelschneid3r" -class WikiFallbackHandler(FallbackHandler): - def __init__(self): - FallbackHandler.__init__(self, - id=f"{md_id}_fb", - name=f"{md_name} fallback", - description="Wikipedia fallback search") - - def fallbacks(self, query_string): - stripped = query_string.strip() - return [Plugin.createFallbackItem(query_string)] if stripped else [] - - class Plugin(PluginInstance, TriggerQueryHandler): baseurl = 'https://en.wikipedia.org/w/api.php' @@ -40,13 +28,22 @@ class Plugin(PluginInstance, TriggerQueryHandler): iconUrls = [f"file:{Path(__file__).parent}/wikipedia.png"] def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='wiki ') - self.wiki_fb = WikiFallbackHandler() - PluginInstance.__init__(self, extensions=[self, self.wiki_fb]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='wiki ', supportsFuzzyMatching=True + ) + self.fuzzy = False + + self.local_lang_code = getdefaultlocale()[0] + if self.local_lang_code: + self.local_lang_code = self.local_lang_code[0:2] + else: + self.local_lang_code = 'en' + warning("Failed getting language code. Using 'en'.") + + self.fbh = FBH(self) + self.registerExtension(self.fbh) params = { 'action': 'query', @@ -56,13 +53,6 @@ def __init__(self): 'format': 'json' } - Plugin.local_lang_code = getdefaultlocale()[0] - if Plugin.local_lang_code: - Plugin.local_lang_code = Plugin.local_lang_code[0:2] - else: - Plugin.local_lang_code = 'en' - warning("Failed getting language code. Using 'en'.") - get_url = "%s?%s" % (self.baseurl, parse.urlencode(params)) req = request.Request(get_url, headers={'User-Agent': self.user_agent}) try: @@ -76,9 +66,15 @@ def __init__(self): except Exception as error: warning('Error getting languages (%s). Defaulting to EN.' % error) + def __del__(self): + self.deregisterExtension(self.fbh) + + def setFuzzyMatching(self, enabled: bool): + self.fuzzy = enabled + def handleTriggerQuery(self, query): - stripped = query.string.strip() - if stripped: + if stripped := query.string.strip(): + # avoid rate limiting for _ in range(50): sleep(0.01) @@ -92,7 +88,8 @@ def handleTriggerQuery(self, query): 'search': stripped, 'limit': self.limit, 'utf8': 1, - 'format': 'json' + 'format': 'json', + 'profile': 'fuzzy' if self.fuzzy else 'normal' } get_url = "%s?%s" % (self.baseurl, parse.urlencode(params)) req = request.Request(get_url, headers={'User-Agent': self.user_agent}) @@ -106,7 +103,7 @@ def handleTriggerQuery(self, query): url = data[3][i] results.append( StandardItem( - id=md_id, + id=self.id, text=title, subtext=summary if summary else url, iconUrls=self.iconUrls, @@ -118,28 +115,37 @@ def handleTriggerQuery(self, query): ) if not results: - results.append(Plugin.createFallbackItem(stripped)) + results.append(self.createFallbackItem(stripped)) query.add(results) else: query.add( StandardItem( - id=md_id, - text=md_name, + id=self.id, + text=self.name, subtext="Enter a query to search on Wikipedia", iconUrls=self.iconUrls ) ) - @staticmethod - def createFallbackItem(query_string): + def createFallbackItem(self, q: str) -> Item: return StandardItem( - id=md_id, - text=md_name, - subtext="Search '%s' on Wiki" % query_string, - iconUrls=Plugin.iconUrls, + id=self.id, + text=self.name, + subtext="Search '%s' on Wikipedia" % q, + iconUrls=self.iconUrls, actions=[ Action("wiki_search", "Search on Wikipedia", - lambda url=Plugin.searchUrl % (Plugin.local_lang_code, query_string): openUrl(url)) + lambda url=self.searchUrl % (self.local_lang_code, q): openUrl(url)) ] ) + + +class FBH(FallbackHandler): + + def __init__(self, p: Plugin): + FallbackHandler.__init__(self, p.id + 'fb', p.name, p.description) + self.plugin = p + + def fallbacks(self, q :str): + return [self.plugin.createFallbackItem(q)] From 1b7fa593946f0b9c6ef02b8255323a60550a2e96 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sat, 22 Jun 2024 01:16:17 +0200 Subject: [PATCH 286/355] [zeal:2.0] - Min api 2.3 - Add fallback extension --- zeal/__init__.py | 58 +++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/zeal/__init__.py b/zeal/__init__.py index 1201d130..89e6bd63 100644 --- a/zeal/__init__.py +++ b/zeal/__init__.py @@ -3,34 +3,52 @@ from albert import * -md_iid = '2.0' -md_version = '1.2' +md_iid = '2.3' +md_version = '2.0' md_name = 'Zeal' md_description = 'Search in Zeal docs' md_license = "MIT" -md_url = 'https://github.com/albertlauncher/python/zeal' +md_url = 'https://github.com/albertlauncher/python/tree/main/zeal' md_authors = "@manuelschneid3r" md_bin_dependencies = ['zeal'] +class FBH(FallbackHandler): + def fallbacks(self, s): + return [Plugin.createItem(s)] if s else [] + + class Plugin(PluginInstance, TriggerQueryHandler): + def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - defaultTrigger='z ') - PluginInstance.__init__(self, extensions=[self]) + PluginInstance.__init__(self) + TriggerQueryHandler.__init__( + self, self.id, self.name, self.description, + defaultTrigger='z ' + ) + self.fbh = FBH( + id=self.id + 'fb', + name=self.name, + description=self.description + ) + + self.registerExtension(self.fbh) + + def __del__(self): + self.deregisterExtension(self.fbh) def handleTriggerQuery(self, query): - stripped = query.string.strip() - if stripped: - query.add( - StandardItem( - id=md_name, - text=md_name, - subtext=f"Search '{stripped}' in Zeal", - iconUrls=["xdg:zeal"], - actions=[Action("zeal", "Search in Zeal", lambda s=stripped: runDetachedProcess(['zeal', s]))] - ) - ) + if stripped := query.string.strip(): + query.add(self.createItem(stripped)) + + @staticmethod + def createItem(query: str) -> Item: + return StandardItem( + id=md_name, + text=md_name, + subtext=f"Search '{query}' in Zeal", + iconUrls=["xdg:zeal"], + actions=[Action("zeal", "Search in Zeal", + lambda q=query: runDetachedProcess(['zeal', q]))] + ) + From 7a724d7620827e7a71d1b78892eee21b33da1a99 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 1 Jul 2024 21:54:29 +0200 Subject: [PATCH 287/355] [GoldenDict:1.5] Remove breaking type hints --- goldendict/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/goldendict/__init__.py b/goldendict/__init__.py index 51eadcd6..d60298eb 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -7,7 +7,7 @@ from albert import * md_iid = '2.3' -md_version = '1.4' +md_version = '1.5' md_name = 'GoldenDict' md_description = 'Quick access to GoldenDict' md_license = 'MIT' @@ -43,7 +43,7 @@ def __init__(self): warning(f"Multiple GoldenDict commands found: {', '.join(executables)}") warning(f"Using {self.executable}") - def handleTriggerQuery(self, query: TriggerQuery): + def handleTriggerQuery(self, query): q = query.string.strip() query.add( StandardItem( From beb090365e4de1e51bf225ab9cdd6f4e3ec892cc Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 17 Jul 2024 15:28:20 +0200 Subject: [PATCH 288/355] [CoinGecko:1.3] Use Matcher --- coingecko/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index d4c9de14..58fdab66 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -9,7 +9,7 @@ from threading import Thread, Event md_iid = '2.3' -md_version = "1.2" +md_version = "1.3" md_name = "CoinGecko" md_description = "Access CoinGecko" md_license = "MIT" @@ -128,7 +128,7 @@ def updateIndexItems(self): # override default trigger handling to sort by rank def handleTriggerQuery(self, query): - qs = query.string.strip().lower() + m = Matcher(query.string) for item in self.items: - if qs in item.name.lower() or qs in item.symbol.lower(): + if m.match(item.symbol) or m.match(item.name): query.add(item) From 54c5eebe8a37bcb6f204b7c2d34cec3736c1f1ad Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 7 Aug 2024 14:04:52 +0200 Subject: [PATCH 289/355] [tex_to_unicode:1.3] Port to v2.3 Author is okay with license change. See https://github.com/orgs/albertlauncher/discussions/1391#discussioncomment-10263863 --- .archive/tex_to_unicode/tex.png | Bin 9268 -> 0 bytes .../__init__.py | 31 ++++++++---------- tex_to_unicode/tex.svg | 4 +++ 3 files changed, 17 insertions(+), 18 deletions(-) delete mode 100644 .archive/tex_to_unicode/tex.png rename {.archive/tex_to_unicode => tex_to_unicode}/__init__.py (71%) create mode 100644 tex_to_unicode/tex.svg diff --git a/.archive/tex_to_unicode/tex.png b/.archive/tex_to_unicode/tex.png deleted file mode 100644 index 49379b81f05387b988f68864e06b4dfe3d55f841..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9268 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 W3tuFJQegG~0000 Item: + def _create_item(self, text: str, subtext: str, can_copy: bool): actions = [] if can_copy: actions.append( @@ -43,14 +38,14 @@ def _create_item(self, text: str, subtext: str, can_copy: bool) -> Item: ) ) return StandardItem( - id=md_id, + id=self.id, text=text, subtext=subtext, iconUrls=self.iconUrls, actions=actions, ) - def handleTriggerQuery(self, query: TriggerQuery) -> None: + def handleTriggerQuery(self, query): stripped = query.string.strip() if not stripped: diff --git a/tex_to_unicode/tex.svg b/tex_to_unicode/tex.svg new file mode 100644 index 00000000..86ddf19b --- /dev/null +++ b/tex_to_unicode/tex.svg @@ -0,0 +1,4 @@ + + + + From bb60bbe59920a01d0ddc7627a6c1021d4f3a18db Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 12 Aug 2024 02:02:10 +0200 Subject: [PATCH 290/355] [bitwarden:2.4] Drop deprecated parameters --- bitwarden/__init__.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 7cc1aec2..c40057c9 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = '2.3' -md_version = "2.3" +md_iid = "2.3" +md_version = "2.4" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" md_license = "MIT" @@ -156,7 +156,4 @@ def _code_to_clipboard(self, item): def _edit_entry(self, item): id = item["id"] - runTerminal( - script=f"rbw edit {id}", - close_on_exit=True - ) + runTerminal(script=f"rbw edit {id}") From 2d2c9eb42d89f1b81f045d31f16097b409a636e4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 12 Aug 2024 02:13:28 +0200 Subject: [PATCH 291/355] [docker:2.2] Drop deprecated parameters --- docker/__init__.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docker/__init__.py b/docker/__init__.py index 1e6fc8bf..99c60200 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -6,8 +6,8 @@ import docker from albert import * -md_iid = '2.3' -md_version = "2.1" +md_iid = "2.3" +md_version = "2.2" md_name = "Docker" md_description = "Manage docker images and containers" md_license = "MIT" @@ -59,7 +59,7 @@ def handleGlobalQuery(self, query): actions = [Action("start", "Start container", lambda c=container: c.start())] actions.extend([ Action("logs", "Logs", - lambda c=container.id: runTerminal("docker logs -f %s" % c, close_on_exit=False)), + lambda c=container.id: runTerminal("docker logs -f %s ; exec $SHELL" % c)), Action("remove", "Remove (forced, with volumes)", lambda c=container: c.remove(v=True, force=True)), Action("copy-id", "Copy id to clipboard", @@ -86,9 +86,11 @@ def handleGlobalQuery(self, query): text=", ".join(image.tags), subtext="Image: %s" % image.id, iconUrls=self.icon_urls_stopped, - actions=[Action("run", "Run with command: %s" % query.string, - lambda i=image, s=query.string: client.containers.run(i, s)), - Action("rmi", "Remove image", lambda i=image: i.remove())] + actions=[ + # Action("run", "Run with command: %s" % query.string, + # lambda i=image, s=query.string: client.containers.run(i, s)), + Action("rmi", "Remove image", lambda i=image: i.remove()) + ] ), score=len(query.string)/len(tag) )) From 2e300d120e48003125061c78b9b17dba403373a2 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 12 Aug 2024 02:17:15 +0200 Subject: [PATCH 292/355] [aur:1.11] Drop deprecated parameters --- aur/__init__.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/aur/__init__.py b/aur/__init__.py index 7fa763a1..69ad787c 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -15,8 +15,8 @@ from albert import * -md_iid = '2.3' -md_version = "1.10" +md_iid = "2.3" +md_version = "1.11" md_name = "AUR" md_description = "Query and install AUR packages" md_license = "MIT" @@ -113,16 +113,14 @@ def handleTriggerQuery(self, query): id="inst", text="Install using %s" % pacman, callable=lambda n=name: runTerminal( - script=self.install_cmdline % n, - close_on_exit=False + script=self.install_cmdline % n + " ; exec $SHELL" ) )) actions.append(Action( id="instnc", text="Install using %s (noconfirm)" % pacman, callable=lambda n=name: runTerminal( - script=self.install_cmdline % n + " --noconfirm", - close_on_exit=False + script=self.install_cmdline % n + " --noconfirm ; exec $SHELL" ) )) From bdaf3ccb133b88f1929da73926a88392e0214845 Mon Sep 17 00:00:00 2001 From: dev2a Date: Wed, 14 Aug 2024 22:37:54 +0200 Subject: [PATCH 293/355] [jetbrains:2.0] - Add Aqua and Writerside - Look for project name to search in projects - Use albert.Matcher Co-authored-by: @manuelschneid3r --- jetbrains_projects/__init__.py | 35 ++++- jetbrains_projects/icons/aqua.svg | 171 ++++++++++++++++++++++++ jetbrains_projects/icons/writerside.svg | 9 ++ 3 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 jetbrains_projects/icons/aqua.svg create mode 100644 jetbrains_projects/icons/writerside.svg diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 623f8eb1..39d69f0c 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -5,6 +5,7 @@ """ This plugin allows you to quickly open projects of the Jetbrains IDEs +- Aqua - Android Studio - CLion - DataGrip @@ -15,7 +16,8 @@ - PyCharm - Rider - RubyMine -- WebStorm. +- WebStorm +- Writerside. Note that for this plugin to find the IDEs, a commandline launcher in $PATH is required. Open the IDE and click Tools -> Create Command-line Launcher to add one. @@ -32,12 +34,12 @@ from albert import * md_iid = '2.3' -md_version = "1.10" +md_version = "2.0" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/main/jetbrains_projects" -md_authors = ["@tomsquest", "@vmaerten", "@manuelschneid3r"] +md_authors = ["@tomsquest", "@vmaerten", "@manuelschneid3r", "@d3v2a"] @dataclass @@ -84,15 +86,22 @@ def _parse_recent_projects(self, recent_projects_file: Path) -> list[Project]: projects = [] for entry in entries: - project_path = entry.attrib["key"].replace("$USER_HOME$", str(Path.home())) - + project_path = entry.attrib["key"] + project_path = project_path.replace("$USER_HOME$", str(Path.home())) + project_name = Path(project_path).name + files = Path(project_path + "/.idea").glob("*.iml") tag_opened = entry.find(".//option[@name='projectOpenTimestamp']") last_opened = tag_opened.attrib["value"] if tag_opened is not None and "value" in tag_opened.attrib else None if project_path and last_opened: projects.append( - Project(name=Path(project_path).name, path=project_path, last_opened=int(last_opened)) + Project(name=project_name, path=project_path, last_opened=int(last_opened)) ) + for file in files: + name = file.name.replace(".iml", "") + if name != project_name: + projects.append(Project(name=name, path=project_path, last_opened=int(last_opened))) + return projects except (ElementTree.ParseError, FileNotFoundError): return [] @@ -117,6 +126,11 @@ def __init__(self): config_dir_prefix="Google/AndroidStudio", binaries=["studio", "androidstudio", "android-studio", "android-studio-canary", "jdk-android-studio", "android-studio-system-jdk"]), + Editor( + name="Aqua", + icon=plugin_dir / "icons" / "aqua.svg", + config_dir_prefix="JetBrains/Aqua", + binaries=["aqua", "aqua-eap"]), Editor( name="CLion", icon=plugin_dir / "icons" / "clion.svg", @@ -174,15 +188,22 @@ def __init__(self): icon=plugin_dir / "icons" / "rustrover.svg", config_dir_prefix="JetBrains/RustRover", binaries=["rustrover", "rustrover-eap"]), + Editor( + name="Writerside", + icon=plugin_dir / "icons" / "writerside.svg", + config_dir_prefix="JetBrains/Writerside", + binaries=["writerside", "writerside-eap"]), ] self.editors = [e for e in editors if e.binary is not None] def handleTriggerQuery(self, query: Query): editor_project_pairs = [] + + m = Matcher(query.string) for editor in self.editors: projects = editor.list_projects() projects = [p for p in projects if Path(p.path).exists()] - projects = [p for p in projects if query.string.lower() in p.name.lower()] + projects = [p for p in projects if m.match(p.name) or m.match(p.path)] editor_project_pairs.extend([(editor, p) for p in projects]) # sort by last opened diff --git a/jetbrains_projects/icons/aqua.svg b/jetbrains_projects/icons/aqua.svg new file mode 100644 index 00000000..a2d7e161 --- /dev/null +++ b/jetbrains_projects/icons/aqua.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jetbrains_projects/icons/writerside.svg b/jetbrains_projects/icons/writerside.svg new file mode 100644 index 00000000..087eed26 --- /dev/null +++ b/jetbrains_projects/icons/writerside.svg @@ -0,0 +1,9 @@ + + + + + + + + + From 109a5cb34a31e47828223b987ac13ab1a8d3c216 Mon Sep 17 00:00:00 2001 From: Pete Hamlin Date: Wed, 14 Aug 2024 21:00:04 +0000 Subject: [PATCH 294/355] [unit_converter:1.6] Port to API v2 --- .../__init__.py | 103 +++++++++--------- .../icons/currency.svg | 0 .../icons/current.svg | 0 .../icons/length.svg | 0 .../icons/lengthtime.svg | 0 .../icons/luminosity.svg | 0 .../icons/mass.svg | 0 .../icons/printing_unit.svg | 0 .../icons/substance.svg | 0 .../icons/temperature.svg | 0 .../icons/time.svg | 0 .../icons/unit_converter.svg | 0 12 files changed, 49 insertions(+), 54 deletions(-) rename {.archive/unit_converter => unit_converter}/__init__.py (86%) rename {.archive/unit_converter => unit_converter}/icons/currency.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/current.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/length.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/lengthtime.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/luminosity.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/mass.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/printing_unit.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/substance.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/temperature.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/time.svg (100%) rename {.archive/unit_converter => unit_converter}/icons/unit_converter.svg (100%) diff --git a/.archive/unit_converter/__init__.py b/unit_converter/__init__.py similarity index 86% rename from .archive/unit_converter/__init__.py rename to unit_converter/__init__.py index 462dad4f..66b1c05a 100644 --- a/.archive/unit_converter/__init__.py +++ b/unit_converter/__init__.py @@ -24,19 +24,18 @@ from urllib.error import URLError from urllib.request import urlopen -import albert import inflect import pint +from albert import * - -md_iid = '2.0' -md_version = "1.4" +md_iid = "2.3" +md_version = "1.6" md_name = "Unit Converter" md_description = "Convert between units" md_license = "MIT" md_url = "https://github.com/albertlauncher/python" md_lib_dependencies = ["pint", "inflect"] -md_maintainers = "@DenverCoder1" +md_authors = ["@DenverCoder1", "@Pete-Hamlin"] class ConversionResult: @@ -250,12 +249,12 @@ def _get_currencies(self) -> dict[str, float]: with urlopen(self.API_URL) as response: data = json.loads(response.read().decode("utf-8")) if not data or "rates" not in data: - albert.info("No currencies found") + info("No currencies found") return {} - albert.info(f'Currencies updated') + info(f"Currencies updated") return data["rates"] except URLError as error: - albert.warning(f"Error getting currencies: {error}") + warning(f"Error getting currencies: {error}") return {} def get_currency(self, currency: str) -> str | None: @@ -309,14 +308,9 @@ def convert(self, amount: float, from_unit: str, to_unit: str) -> ConversionResu ) -class Plugin(albert.TriggerQueryHandler): +class Plugin(PluginInstance, GlobalQueryHandler): """The plugin class""" - unit_convert_regex = re.compile( - r"(?P-?\d+\.?\d*)\s?(?P.*)\s(?:to|in)\s(?P.*)", - re.I, - ) - config: dict[str, Any] = { # Maximum number of decimal places for precision "precision": 12, @@ -351,47 +345,50 @@ class Plugin(albert.TriggerQueryHandler): }, } - def initialize(self): + def __init__(self): + PluginInstance.__init__(self) + GlobalQueryHandler.__init__( + self, + id=self.id, + name=self.name, + description=self.description, + synopsis=" to ", + defaultTrigger="convert ", + ) + + self.unit_convert_regex = re.compile( + r"(?P-?\d+\.?\d*)\s?(?P.*)\s(?:to|in)\s(?P.*)", + re.I, + ) self.unit_converter = StandardUnitConverter() self.currency_converter = CurrencyConverter() - def id(self) -> str: - return md_id + def handleTriggerQuery(self, query: Query) -> None: + if query_string := query.string.strip(): + items = self.match_query(query_string) + query.add(items) - def name(self) -> str: - return md_name + def handleGlobalQuery(self, query): + return [RankItem(item=item, score=1) for item in self.match_query(query.string.strip())] - def description(self) -> str: - return md_description - - def synopsis(self) -> str: - return " to " - - def defaultTrigger(self) -> str: - return "convert " - - def handleTriggerQuery(self, query: albert.TriggerQuery) -> None: - query_string = query.string.strip() + def match_query(self, query_string: str): match = self.unit_convert_regex.fullmatch(query_string) if match: - albert.info(f"Matched {query_string}") try: - items = self._get_items( + return self._get_items( float(match.group("from_amount")), match.group("from_unit").strip(), match.group("to_unit").strip(), ) - query.add(items) except Exception as error: - albert.warning(f"Error: {error}") - tb = "".join( - traceback.format_exception(error.__class__, error, error.__traceback__) - ) - albert.warning(tb) - albert.info("Something went wrong. Make sure you're using the correct format.") + warning(f"Error: {error}") + tb = "".join(traceback.format_exception(error.__class__, error, error.__traceback__)) + warning(tb) + info("Something went wrong. Make sure you're using the correct format.") + return [] - def _create_item(self, text: str, subtext: str, icon: str = "") -> albert.Item: - """Create an albert.Item from a text and subtext + def _create_item(self, text: str, subtext: str, icon: str = "") -> Item: + """Create an Item from a text and subtext Args: text (str): The text to display @@ -399,22 +396,22 @@ def _create_item(self, text: str, subtext: str, icon: str = "") -> albert.Item: icon (Optional[str]): The icon to display. If not specified, the default icon will be used Returns: - albert.Item: The item to be added to the list of results + Item: The item to be added to the list of results """ icon_path = Path(__file__).parent / "icons" / icon if not icon or not icon_path.exists(): - albert.warning(f"Icon {icon} does not exist") + warning(f"Icon {icon} does not exist") icon_path = Path(__file__).parent / "icons" / "unit_converter.svg" - return albert.StandardItem( + return StandardItem( id=str(icon_path), iconUrls=["file:" + str(icon_path)], text=text, subtext=subtext, actions=[ - albert.Action( + Action( id="copy", text="Copy result to clipboard", - callable=lambda: albert.setClipboardText(text=text), + callable=lambda: setClipboardText(text=text), ) ], ) @@ -436,7 +433,7 @@ def _get_converter(self, from_unit: str, to_unit: str) -> UnitConverter: return self.currency_converter return self.unit_converter - def _get_items(self, amount: float, from_unit: str, to_unit: str) -> list[albert.Item]: + def _get_items(self, amount: float, from_unit: str, to_unit: str) -> list[Item]: """Generate the Albert items to display for the query Args: @@ -445,7 +442,7 @@ def _get_items(self, amount: float, from_unit: str, to_unit: str) -> list[albert to_unit (str): The unit to convert to Returns: - List[albert.Item]: The list of items to display + List[Item]: The list of items to display """ try: converter = self._get_converter(from_unit, to_unit) @@ -459,13 +456,11 @@ def _get_items(self, amount: float, from_unit: str, to_unit: str) -> list[albert ) ] except pint.errors.DimensionalityError as e: - albert.warning(f"DimensionalityError: {e}") - return [ - self._create_item(f"Unable to convert {amount} {from_unit} to {to_unit}", str(e)) - ] + warning(f"DimensionalityError: {e}") + return [self._create_item(f"Unable to convert {amount} {from_unit} to {to_unit}", str(e))] except pint.errors.UndefinedUnitError as e: - albert.warning(f"UndefinedUnitError: {e}") + warning(f"UndefinedUnitError: {e}") return [] except UnknownCurrencyError as e: - albert.warning(f"UnknownCurrencyError: {e}") + warning(f"UnknownCurrencyError: {e}") return [] diff --git a/.archive/unit_converter/icons/currency.svg b/unit_converter/icons/currency.svg similarity index 100% rename from .archive/unit_converter/icons/currency.svg rename to unit_converter/icons/currency.svg diff --git a/.archive/unit_converter/icons/current.svg b/unit_converter/icons/current.svg similarity index 100% rename from .archive/unit_converter/icons/current.svg rename to unit_converter/icons/current.svg diff --git a/.archive/unit_converter/icons/length.svg b/unit_converter/icons/length.svg similarity index 100% rename from .archive/unit_converter/icons/length.svg rename to unit_converter/icons/length.svg diff --git a/.archive/unit_converter/icons/lengthtime.svg b/unit_converter/icons/lengthtime.svg similarity index 100% rename from .archive/unit_converter/icons/lengthtime.svg rename to unit_converter/icons/lengthtime.svg diff --git a/.archive/unit_converter/icons/luminosity.svg b/unit_converter/icons/luminosity.svg similarity index 100% rename from .archive/unit_converter/icons/luminosity.svg rename to unit_converter/icons/luminosity.svg diff --git a/.archive/unit_converter/icons/mass.svg b/unit_converter/icons/mass.svg similarity index 100% rename from .archive/unit_converter/icons/mass.svg rename to unit_converter/icons/mass.svg diff --git a/.archive/unit_converter/icons/printing_unit.svg b/unit_converter/icons/printing_unit.svg similarity index 100% rename from .archive/unit_converter/icons/printing_unit.svg rename to unit_converter/icons/printing_unit.svg diff --git a/.archive/unit_converter/icons/substance.svg b/unit_converter/icons/substance.svg similarity index 100% rename from .archive/unit_converter/icons/substance.svg rename to unit_converter/icons/substance.svg diff --git a/.archive/unit_converter/icons/temperature.svg b/unit_converter/icons/temperature.svg similarity index 100% rename from .archive/unit_converter/icons/temperature.svg rename to unit_converter/icons/temperature.svg diff --git a/.archive/unit_converter/icons/time.svg b/unit_converter/icons/time.svg similarity index 100% rename from .archive/unit_converter/icons/time.svg rename to unit_converter/icons/time.svg diff --git a/.archive/unit_converter/icons/unit_converter.svg b/unit_converter/icons/unit_converter.svg similarity index 100% rename from .archive/unit_converter/icons/unit_converter.svg rename to unit_converter/icons/unit_converter.svg From 3d68043a559515e1fe84e15952cc98e2b41d25dd Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 08:42:22 +0200 Subject: [PATCH 295/355] [docker:3.0] Revert to trigger query handling Global query handler not applicable, queries take seconds sometimes --- docker/__init__.py | 66 ++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/docker/__init__.py b/docker/__init__.py index 99c60200..9835e46f 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -7,7 +7,7 @@ from albert import * md_iid = "2.3" -md_version = "2.2" +md_version = "3.0" md_name = "Docker" md_description = "Manage docker images and containers" md_license = "MIT" @@ -17,11 +17,12 @@ md_lib_dependencies = "docker" -class Plugin(PluginInstance, GlobalQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): + # Global query handler not applicable, queries take seconds sometimes def __init__(self): PluginInstance.__init__(self) - GlobalQueryHandler.__init__( + TriggerQueryHandler.__init__( self, self.id, self.name, self.description, defaultTrigger='d ', synopsis='' @@ -30,23 +31,20 @@ def __init__(self): self.icon_urls_stopped = [f"file:{Path(__file__).parent}/stopped.png"] self.client = None - def handleGlobalQuery(self, query): - rank_items = [] + def handleTriggerQuery(self, query): + items = [] if not self.client: try: self.client = docker.from_env() except Exception as e: - rank_items.append(RankItem( - item=StandardItem( - id='except', - text="Failed starting docker client", - subtext=str(e), - iconUrls=self.icon_urls_running, - ), - score=1.0 + items.append(StandardItem( + id='except', + text="Failed starting docker client", + subtext=str(e), + iconUrls=self.icon_urls_running, )) - return rank_items + return items try: for container in self.client.containers.list(all=True): @@ -66,36 +64,30 @@ def handleGlobalQuery(self, query): lambda id=container.id: setClipboardText(id)) ]) - rank_items.append(RankItem( - item=StandardItem( - id=container.id, - text="%s (%s)" % (container.name, ", ".join(container.image.tags)), - subtext="Container: %s" % container.id, - iconUrls=self.icon_urls_running if container.status == 'running' else self.icon_urls_stopped, - actions=actions - ), - score=len(query.string)/len(container.name) + items.append(StandardItem( + id=container.id, + text="%s (%s)" % (container.name, ", ".join(container.image.tags)), + subtext="Container: %s" % container.id, + iconUrls=self.icon_urls_running if container.status == 'running' else self.icon_urls_stopped, + actions=actions )) for image in reversed(self.client.images.list()): for tag in sorted(image.tags, key=len): # order by resulting score if query.string in tag: - rank_items.append(RankItem( - item=StandardItem( - id=image.short_id, - text=", ".join(image.tags), - subtext="Image: %s" % image.id, - iconUrls=self.icon_urls_stopped, - actions=[ - # Action("run", "Run with command: %s" % query.string, - # lambda i=image, s=query.string: client.containers.run(i, s)), - Action("rmi", "Remove image", lambda i=image: i.remove()) - ] - ), - score=len(query.string)/len(tag) + items.append(StandardItem( + id=image.short_id, + text=", ".join(image.tags), + subtext="Image: %s" % image.id, + iconUrls=self.icon_urls_stopped, + actions=[ + # Action("run", "Run with command: %s" % query.string, + # lambda i=image, s=query.string: client.containers.run(i, s)), + Action("rmi", "Remove image", lambda i=image: i.remove()) + ] )) except Exception as e: warning(str(e)) self.client = None - return rank_items + query.add(items) From a93035d1dbb93e4ae28dd6f72ca51e69c4b541c6 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 23:43:36 +0200 Subject: [PATCH 296/355] [color:1.4] Fix upstream url --- color/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/color/__init__.py b/color/__init__.py index 4ec468ae..ab5d8f41 100644 --- a/color/__init__.py +++ b/color/__init__.py @@ -19,11 +19,11 @@ from string import hexdigits md_iid = '2.3' -md_version = '1.3' +md_version = '1.4' md_name = 'Color' md_description = 'Display color for color codes' md_license = 'MIT' -md_url = 'https://github.com/albertlauncher/python/color' +md_url = 'https://github.com/albertlauncher/python/tree/main/color' md_authors = "@manuelschneid3r" From 89a380bc4286be3e96175744efc91957b427cbed Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 23:43:56 +0200 Subject: [PATCH 297/355] [copyq:1.6] Fix upstream url --- copyq/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/copyq/__init__.py b/copyq/__init__.py index 6ff3d234..bcf3ea72 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -8,11 +8,11 @@ from albert import * md_iid = '2.3' -md_version = "1.5" +md_version = "1.6" md_name = "CopyQ" md_description = "Access CopyQ clipboard" md_license = "BSD-2-Clause" -md_url = "https://github.com/albertlauncher/python" +md_url = "https://github.com/albertlauncher/python/tree/main/copyq" md_authors = ["@ManuelSchneid3r", "@BarrensZeppelin"] md_bin_dependencies = ["copyq"] From dc8e2d97a1fd2d709cbfbd13d0f883439b2d3b25 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 23:44:11 +0200 Subject: [PATCH 298/355] [dice_roll:1.6] Fix upstream url --- dice_roll/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dice_roll/__init__.py b/dice_roll/__init__.py index ae12f472..10101814 100644 --- a/dice_roll/__init__.py +++ b/dice_roll/__init__.py @@ -16,11 +16,11 @@ """ md_iid = '2.3' -md_version = "1.5" +md_version = "1.6" md_name = "Dice Roll" md_description = "Roll any number of dice" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python" +md_url = "https://github.com/albertlauncher/python/tree/main/dice_roll" md_authors = "@DenverCoder1" From 9729f80b24008199ad98eea2e6f4baaa723af4b5 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 23:44:26 +0200 Subject: [PATCH 299/355] [duckduckgo:1.2] Fix upstream url --- duckduckgo/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/duckduckgo/__init__.py b/duckduckgo/__init__.py index f04f08ea..e5b5a92b 100644 --- a/duckduckgo/__init__.py +++ b/duckduckgo/__init__.py @@ -12,11 +12,11 @@ from time import sleep md_iid = '2.3' -md_version = '1.1' +md_version = '1.2' md_name = 'DuckDuckGo' md_description = 'Inline DuckDuckGo web search' md_license = "MIT" -md_url = 'https://github.com/albertlauncher/python/duckduckgo' +md_url = 'https://github.com/albertlauncher/python/tree/main/duckduckgo' md_lib_dependencies = "duckduckgo-search" md_authors = "@manuelschneid3r" From e00e0accc7ea067203736f62af6dffd824fe7b0b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 23:44:43 +0200 Subject: [PATCH 300/355] [inhibit_sleep:1.2] Fix upstream url --- inhibit_sleep/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inhibit_sleep/__init__.py b/inhibit_sleep/__init__.py index 3d620ebb..76829305 100644 --- a/inhibit_sleep/__init__.py +++ b/inhibit_sleep/__init__.py @@ -12,11 +12,11 @@ from subprocess import Popen, TimeoutExpired md_iid = '2.3' -md_version = '1.1' +md_version = '1.2' md_name = 'Inhibit sleep' md_description = 'Inhibit system sleep mode.' md_license = "MIT" -md_url = 'https://github.com/albertlauncher/python/inhibit_sleep' +md_url = 'https://github.com/albertlauncher/python/tree/main/inhibit_sleep' md_authors = "@manuelschneid3r" md_bin_dependencies = ['systemd-inhibit', "sleep"] From 3f2d4d93f378371177db2843d8ebef0d6cbd3799 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 23:45:03 +0200 Subject: [PATCH 301/355] [translators:1.8] Fix upstream url --- translators/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translators/__init__.py b/translators/__init__.py index 6fb04efc..85f7b098 100644 --- a/translators/__init__.py +++ b/translators/__init__.py @@ -13,11 +13,11 @@ import translators as ts md_iid = '2.3' -md_version = "1.7" +md_version = "1.8" md_name = "Translator" md_description = "Translate sentences using 'translators' package" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python/translators" +md_url = "https://github.com/albertlauncher/python/tree/main/translators" md_authors = "@manuelschneid3r" md_lib_dependencies = "translators" From 82b15e5dddd9e715409034f7546769ed0888a512 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 23:45:18 +0200 Subject: [PATCH 302/355] [unit_converter:1.7] Fix upstream url --- unit_converter/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unit_converter/__init__.py b/unit_converter/__init__.py index 66b1c05a..927629b2 100644 --- a/unit_converter/__init__.py +++ b/unit_converter/__init__.py @@ -29,11 +29,11 @@ from albert import * md_iid = "2.3" -md_version = "1.6" +md_version = "1.7" md_name = "Unit Converter" md_description = "Convert between units" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python" +md_url = "https://github.com/albertlauncher/python/tree/main/unit_converter" md_lib_dependencies = ["pint", "inflect"] md_authors = ["@DenverCoder1", "@Pete-Hamlin"] From b1183a63a645abd644be0a5a163b3acd5878dd98 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 15 Aug 2024 23:45:30 +0200 Subject: [PATCH 303/355] [vpn:1.6] Fix upstream url --- vpn/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vpn/__init__.py b/vpn/__init__.py index ef82febd..db122112 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -9,11 +9,11 @@ from albert import * md_iid = '2.3' -md_version = "1.5" +md_version = "1.6" md_name = "VPN" md_description = "Manage NetworkManager VPN connections" md_license = "MIT" -md_url = "https://github.com/albertlauncher/python" +md_url = "https://github.com/albertlauncher/python/tree/main/vpn" md_authors = ["@janeklb", "@Bierchermuesli", "@manuelschneid3r"] md_bin_dependencies = ["nmcli"] From 522196fc33acda8df8d12ca5db56e2293dffbc4d Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 16 Aug 2024 18:42:57 +0200 Subject: [PATCH 304/355] [inhibit_sleep] Archive Moved to system plugin --- {inhibit_sleep => .archive/inhibit_sleep}/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {inhibit_sleep => .archive/inhibit_sleep}/__init__.py (100%) diff --git a/inhibit_sleep/__init__.py b/.archive/inhibit_sleep/__init__.py similarity index 100% rename from inhibit_sleep/__init__.py rename to .archive/inhibit_sleep/__init__.py From d39c04c04204784bf7e8a671131da876806090fb Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 21 Aug 2024 16:38:34 +0200 Subject: [PATCH 305/355] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d6802f24..9a5cd63a 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,6 @@ This repository is shipped with Albert. Credits go to our contributors 👍 git clone https://github.com//python.git ~/Library/Application\ Support/albert/python/plugins ``` * Open the directory in your favorite IDE (PyCharmCE is a good choice). -* Write your plugin (Make sure it is upstream-polished-enough though). - This repository ships a [python stub file](https://github.com/albertlauncher/python/blob/master/albert.pyi) which gives you coding assistance. +* The Python plugins plugin installs a python stub file in your user plugin directory. This file serves as API documentation and gives you coding assistance if you are using a decent IDE. +* Write your plugin. Make sure it is polished (No bugs, few to no linting warnings, efficient, readable, maintainable, …). * Commit, push, send a PR. From cda9f21426daa10e8e75fcdc3c86f38f0d73007c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 10 Sep 2024 12:55:38 +0200 Subject: [PATCH 306/355] [unit_converter] Remove future typehints --- unit_converter/__init__.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/unit_converter/__init__.py b/unit_converter/__init__.py index 927629b2..6fcf779f 100644 --- a/unit_converter/__init__.py +++ b/unit_converter/__init__.py @@ -12,15 +12,12 @@ - `convert 100 USD to EUR` """ - -from __future__ import annotations - import json import re import traceback from datetime import datetime from pathlib import Path -from typing import Any +from typing import Any, Optional from urllib.error import URLError from urllib.request import urlopen @@ -29,7 +26,7 @@ from albert import * md_iid = "2.3" -md_version = "1.7" +md_version = "1.8" md_name = "Unit Converter" md_description = "Convert between units" md_license = "MIT" @@ -96,7 +93,8 @@ def __display_unit_name(self, amount: float, unit: str) -> str: unit = self.__pluralize_unit(unit) if amount != 1 else unit return self.display_names.get(unit, unit) - def __format_float(self, num: float) -> str: + @staticmethod + def __format_float(num: float) -> str: """Format a float to remove trailing zeros and avoid scientific notation Args: @@ -257,7 +255,7 @@ def _get_currencies(self) -> dict[str, float]: warning(f"Error getting currencies: {error}") return {} - def get_currency(self, currency: str) -> str | None: + def get_currency(self, currency: str) -> Optional[str]: """Get the currency name normalized using aliases and capitalization Args: @@ -387,7 +385,8 @@ def match_query(self, query_string: str): info("Something went wrong. Make sure you're using the correct format.") return [] - def _create_item(self, text: str, subtext: str, icon: str = "") -> Item: + @staticmethod + def _create_item(text: str, subtext: str, icon: str = "") -> Item: """Create an Item from a text and subtext Args: From e4af117f9adeee0a935c663f2be082debd7e9399 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 12 Sep 2024 22:12:42 +0200 Subject: [PATCH 307/355] [syncthing] Use syncthing2 Syncthing is dead --- syncthing/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/syncthing/__init__.py b/syncthing/__init__.py index c43fa9e2..1ddb423c 100644 --- a/syncthing/__init__.py +++ b/syncthing/__init__.py @@ -11,13 +11,13 @@ from syncthing import Syncthing md_iid = '2.3' -md_version = "1.0" +md_version = "1.1" md_name = "Syncthing" md_description = "Trigger basic syncthing actions." md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/main/syncthing" md_authors = "@manuelschneid3r" -md_lib_dependencies = "syncthing" +md_lib_dependencies = "syncthing2" class Plugin(PluginInstance, GlobalQueryHandler): From 2d07e54a3cada14cfa42226c053c8ac5306d92f3 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 18 Nov 2024 12:44:15 +0100 Subject: [PATCH 308/355] [coingecko] Use variadic matcher --- coingecko/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index 58fdab66..a1d3f2b5 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -8,8 +8,8 @@ from pathlib import Path from threading import Thread, Event -md_iid = '2.3' -md_version = "1.3" +md_iid = '2.5' +md_version = "1.4" md_name = "CoinGecko" md_description = "Access CoinGecko" md_license = "MIT" @@ -130,5 +130,5 @@ def updateIndexItems(self): def handleTriggerQuery(self, query): m = Matcher(query.string) for item in self.items: - if m.match(item.symbol) or m.match(item.name): + if m.match(item.symbol, item.name): query.add(item) From 50a2d4e0252b392f78fcd44b03dbcb7f9722cf2f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 18 Nov 2024 12:44:24 +0100 Subject: [PATCH 309/355] [jetbrains] Use variadic matcher --- jetbrains_projects/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 39d69f0c..36f7625e 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -33,8 +33,8 @@ from xml.etree import ElementTree from albert import * -md_iid = '2.3' -md_version = "2.0" +md_iid = '2.5' +md_version = "2.1" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" @@ -203,7 +203,7 @@ def handleTriggerQuery(self, query: Query): for editor in self.editors: projects = editor.list_projects() projects = [p for p in projects if Path(p.path).exists()] - projects = [p for p in projects if m.match(p.name) or m.match(p.path)] + projects = [p for p in projects if m.match(p.name, p.path)] editor_project_pairs.extend([(editor, p) for p in projects]) # sort by last opened From dcdbb0521fc7be25a03898ac5a5025ca82b728ae Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 310/355] [arch_wiki] v3 --- arch_wiki/__init__.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/arch_wiki/__init__.py b/arch_wiki/__init__.py index 2b8eb1db..c24c2476 100644 --- a/arch_wiki/__init__.py +++ b/arch_wiki/__init__.py @@ -8,12 +8,12 @@ from albert import * -md_iid = '2.3' -md_version = '1.6' -md_name = 'Arch Linux Wiki' -md_description = 'Search Arch Linux Wiki articles' -md_license = 'MIT' -md_url = 'https://github.com/albertlauncher/python/tree/main/arch_wiki' +md_iid = "3.0" +md_version = '2.0' +md_name = "Arch Linux Wiki" +md_description = "Search Arch Linux Wiki articles" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/main/arch_wiki" md_authors = "@manuelschneid3r" @@ -22,11 +22,14 @@ class Plugin(PluginInstance, TriggerQueryHandler): baseurl = 'https://wiki.archlinux.org/api.php' search_url = "https://wiki.archlinux.org/index.php?search=%s" user_agent = "org.albert.extension.python.archwiki" + iconUrls = [f"file:{Path(__file__).parent}/arch.svg"] def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__(self, self.id, self.name, self.description, defaultTrigger='awiki ') - self.iconUrls = [f"file:{Path(__file__).parent}/arch.svg"] + TriggerQueryHandler.__init__(self) + + def defaultTrigger(self): + return 'awiki ' def handleTriggerQuery(self, query): stripped = query.string.strip() @@ -58,7 +61,7 @@ def handleTriggerQuery(self, query): summary = data[2][i] url = data[3][i] - results.append(StandardItem(id=self.id, + results.append(StandardItem(id=self.id(), text=title, subtext=summary if summary else url, iconUrls=self.iconUrls, @@ -69,7 +72,7 @@ def handleTriggerQuery(self, query): if results: query.add(results) else: - query.add(StandardItem(id=self.id, + query.add(StandardItem(id=self.id(), text="Search '%s'" % query.string, subtext="No results. Start online search on Arch Wiki", iconUrls=self.iconUrls, @@ -77,7 +80,7 @@ def handleTriggerQuery(self, query): lambda s=query.string: openUrl(self.search_url % s))])) else: - query.add(StandardItem(id=self.id, + query.add(StandardItem(id=self.id(), text=md_name, iconUrls=self.iconUrls, subtext="Enter a query to search on the Arch Wiki")) From d9b1d092342cd4fe98824228b94325413746866a Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 311/355] [aur] v3 --- aur/__init__.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/aur/__init__.py b/aur/__init__.py index 69ad787c..0ca8917a 100644 --- a/aur/__init__.py +++ b/aur/__init__.py @@ -15,8 +15,8 @@ from albert import * -md_iid = "2.3" -md_version = "1.11" +md_iid = "3.0" +md_version = "2.0" md_name = "AUR" md_description = "Query and install AUR packages" md_license = "MIT" @@ -28,14 +28,11 @@ class Plugin(PluginInstance, TriggerQueryHandler): aur_url = "https://aur.archlinux.org/packages/" baseurl = 'https://aur.archlinux.org/rpc/' + iconUrls = [f"file:{Path(__file__).parent}/arch.svg"] def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='aur ' - ) - self.iconUrls = [f"file:{Path(__file__).parent}/arch.svg"] + TriggerQueryHandler.__init__(self) if which("yaourt"): self.install_cmdline = "yaourt -S aur/%s" @@ -49,6 +46,9 @@ def __init__(self): info("No supported AUR helper found.") self.install_cmdline = None + def defaultTrigger(self): + return 'aur ' + def configWidget(self): return [ { @@ -78,7 +78,7 @@ def handleTriggerQuery(self, query): data = json.loads(response.read().decode()) if data['type'] == "error": query.add(StandardItem( - id=self.id, + id=self.id(), text="Error", subtext=data['error'], iconUrls=self.iconUrls @@ -92,7 +92,7 @@ def handleTriggerQuery(self, query): for entry in results_json: name = entry['Name'] item = StandardItem( - id=self.id, + id=self.id(), iconUrls=self.iconUrls, text=f"{entry['Name']} {entry['Version']}" ) @@ -137,7 +137,7 @@ def handleTriggerQuery(self, query): query.add(results) else: query.add(StandardItem( - id=self.id, + id=self.id(), text=md_name, subtext="Enter a query to search the AUR", iconUrls=self.iconUrls, From 3a6f4159bba37fb1e72f757f9633067286d8afe9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 312/355] [bitwarden] v3 --- bitwarden/__init__.py | 45 +++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index c40057c9..6e9e8031 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -5,8 +5,8 @@ from albert import * -md_iid = "2.3" -md_version = "2.4" +md_iid = "3.0" +md_version = "3.0" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" md_license = "MIT" @@ -17,13 +17,14 @@ class Plugin(PluginInstance, TriggerQueryHandler): + iconUrls = [f"file:{Path(__file__).parent}/bw.svg"] + def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='bw ' - ) - self.iconUrls = [f"file:{Path(__file__).parent}/bw.svg"] + TriggerQueryHandler.__init__(self) + + def defaultTrigger(self): + return 'bw ' def handleTriggerQuery(self, query): if query.string.strip().lower() == "sync": @@ -44,9 +45,7 @@ def handleTriggerQuery(self, query): ) ) - filtered_items = self._filter_items(query) - - for p in filtered_items: + for p in self._filter_items(query): query.add( StandardItem( id=p["id"], @@ -68,7 +67,7 @@ def handleTriggerQuery(self, query): id="copy-username", text="Copy username to clipboard", callable=lambda username=p["user"]: - setClipboardText(text=username) + setClipboardText(text=username) ), Action( id="edit", @@ -79,7 +78,8 @@ def handleTriggerQuery(self, query): ) ) - def _get_items(self): + @staticmethod + def _get_items(): field_names = ["id", "name", "user", "folder"] raw_items = run( ["rbw", "list", "--fields", ",".join(field_names)], @@ -121,11 +121,12 @@ def _filter_items(self, query): return filtered_passwords - def _password_to_clipboard(self, item): - id = item["id"] + @staticmethod + def _password_to_clipboard(item): + rbw_id = item["id"] password = run( - ["rbw", "get", id], + ["rbw", "get", rbw_id], capture_output=True, encoding="utf-8", check=True @@ -133,12 +134,13 @@ def _password_to_clipboard(self, item): setClipboardText(text=password) - def _code_to_clipboard(self, item): - id = item["id"] + @staticmethod + def _code_to_clipboard(item): + rbw_id = item["id"] try: code = run( - ["rbw", "code", id], + ["rbw", "code", rbw_id], capture_output=True, encoding="utf-8", check=True @@ -153,7 +155,8 @@ def _code_to_clipboard(self, item): setClipboardText(text=code) - def _edit_entry(self, item): - id = item["id"] + @staticmethod + def _edit_entry(item): + rbw_id = item["id"] - runTerminal(script=f"rbw edit {id}") + runTerminal(script=f"rbw edit {rbw_id}") From 86c33d2d0b303ae68c4072b4120b28b57ec3cdba Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 313/355] [coingecko] v3 --- coingecko/__init__.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index a1d3f2b5..76f9f089 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -8,8 +8,8 @@ from pathlib import Path from threading import Thread, Event -md_iid = '2.5' -md_version = "1.4" +md_iid = "3.0" +md_version = "2.0" md_name = "CoinGecko" md_description = "Access CoinGecko" md_license = "MIT" @@ -71,9 +71,9 @@ def __init__(self, iconUrls=Plugin.iconUrls, actions=[ Action("show", f"Show {name} on CoinGecko", - lambda id=identifier: openUrl(Plugin.coinsUrl + id)), + lambda coin_id=identifier: openUrl(Plugin.coinsUrl + coin_id)), Action("url", "Copy URL to clipboard", - lambda id=identifier: setClipboardText(Plugin.coinsUrl + id)) + lambda coin_id=identifier: setClipboardText(Plugin.coinsUrl + coin_id)) ] ) self.name = name @@ -87,15 +87,11 @@ class Plugin(PluginInstance, IndexQueryHandler): def __init__(self): PluginInstance.__init__(self) - IndexQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='cg ', - synopsis='< symbol | name >' - ) + IndexQueryHandler.__init__(self) self.items = [] self.mtime = 0 - self.coinCacheFilePath = self.cacheLocation / "coins.json" + self.coinCacheFilePath = self.cacheLocation() / "coins.json" self.thread = CoinFetcherThread(self.updateIndexItems, self.coinCacheFilePath) self.thread.start() @@ -103,6 +99,12 @@ def __del__(self): self.thread.stop() self.thread.join() + def defaultTrigger(self): + return 'cg ' + + def synopsis(self, query): + return "< symbol | name >" + def updateIndexItems(self): if self.coinCacheFilePath.is_file() and (mtime := self.coinCacheFilePath.lstat().st_mtime) > self.mtime: self.mtime = mtime From 220b112605816ff4a61d89716bf9753ea0f44c55 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 314/355] [color] v3 --- color/__init__.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/color/__init__.py b/color/__init__.py index ab5d8f41..482f709f 100644 --- a/color/__init__.py +++ b/color/__init__.py @@ -15,15 +15,14 @@ """ from albert import * -from urllib.parse import quote_plus from string import hexdigits -md_iid = '2.3' -md_version = '1.4' -md_name = 'Color' -md_description = 'Display color for color codes' -md_license = 'MIT' -md_url = 'https://github.com/albertlauncher/python/tree/main/color' +md_iid = "3.0" +md_version = "2.0" +md_name = "Color" +md_description = "Display color for color codes" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/main/color" md_authors = "@manuelschneid3r" @@ -31,10 +30,10 @@ class Plugin(PluginInstance, GlobalQueryHandler): def __init__(self): PluginInstance.__init__(self) - GlobalQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='#' - ) + GlobalQueryHandler.__init__(self) + + def defaultTrigger(self): + return '#' def handleGlobalQuery(self, query): rank_items = [] @@ -48,7 +47,7 @@ def handleGlobalQuery(self, query): rank_items.append( RankItem( StandardItem( - id=self.id, + id=self.id(), text=s, subtext="The color for this code.", iconUrls=[f"gen:?background=%23{s}"], From eb52b10775c1b05b3e3e7559a41e805b7be1f511 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 315/355] [copyq] v3 --- copyq/__init__.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/copyq/__init__.py b/copyq/__init__.py index bcf3ea72..cd21adb7 100644 --- a/copyq/__init__.py +++ b/copyq/__init__.py @@ -7,8 +7,8 @@ from albert import * -md_iid = '2.3' -md_version = "1.6" +md_iid = "3.0" +md_version = "2.0" md_name = "CopyQ" md_description = "Access CopyQ clipboard" md_license = "BSD-2-Clause" @@ -51,16 +51,14 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='cp ' - ) + TriggerQueryHandler.__init__(self) + + def defaultTrigger(self): + return "cp " def handleTriggerQuery(self, query): items = [] - q_string = query.string - - script = copyq_script_getMatches % q_string if q_string else copyq_script_getAll + script = copyq_script_getMatches % query.string if query.string else copyq_script_getAll proc = subprocess.run(["copyq", "-"], input=script.encode(), stdout=subprocess.PIPE) json_arr = json.loads(proc.stdout.decode()) @@ -72,12 +70,12 @@ def handleTriggerQuery(self, query): else: text = " ".join(filter(None, text.replace("\n", " ").split(" "))) - act = lambda script, row=row: ( - lambda: runDetachedProcess(["copyq", script % row]) + act = lambda s=script, r=row: ( + lambda: runDetachedProcess(["copyq", s % r]) ) items.append( StandardItem( - id=self.id, + id=self.id(), iconUrls=["xdg:copyq"], text=text, subtext="%s: %s" % (row, ", ".join(json_obj["mimetypes"])), From ba086e893c1ce1ffc2db5c230b5cc8fd76268646 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 316/355] [dice_roll] v3 --- dice_roll/__init__.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/dice_roll/__init__.py b/dice_roll/__init__.py index 10101814..deb9bc2c 100644 --- a/dice_roll/__init__.py +++ b/dice_roll/__init__.py @@ -15,8 +15,8 @@ Example: "roll 2d6 3d8 1d20" """ -md_iid = '2.3' -md_version = "1.6" +md_iid = "3.0" +md_version = "2.0" md_name = "Dice Roll" md_description = "Roll any number of dice" md_license = "MIT" @@ -133,11 +133,13 @@ class Plugin(albert.PluginInstance, albert.TriggerQueryHandler): def __init__(self): albert.PluginInstance.__init__(self) - albert.TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - synopsis="d [d ...]", - defaultTrigger='roll ' - ) + albert.TriggerQueryHandler.__init__(self) + + def synopsis(self, query): + return "d [d ...]" + + def defaultTrigger(self): + return "roll " def configWidget(self): return [{ 'type': 'label', 'text': __doc__.strip() }] @@ -147,7 +149,7 @@ def handleTriggerQuery(self, query: albert.Query) -> None: try: items = get_items(query_string) query.add(items) - except Exception as e: + except Exception: query.add([albert.StandardItem( id="error", iconUrls=[get_icon_path(None)], From 5104a11fbdd43634f3063a9e57f16a0ed29f553c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 317/355] [docker] v3 --- docker/__init__.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docker/__init__.py b/docker/__init__.py index 9835e46f..f6639c03 100644 --- a/docker/__init__.py +++ b/docker/__init__.py @@ -6,8 +6,8 @@ import docker from albert import * -md_iid = "2.3" -md_version = "3.0" +md_iid = "3.0" +md_version = "4.0" md_name = "Docker" md_description = "Manage docker images and containers" md_license = "MIT" @@ -22,15 +22,17 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='d ', - synopsis='' - ) + TriggerQueryHandler.__init__(self) self.icon_urls_running = [f"file:{Path(__file__).parent}/running.png"] self.icon_urls_stopped = [f"file:{Path(__file__).parent}/stopped.png"] self.client = None + def synopsis(self, query): + return "" + + def defaultTrigger(self): + return "d " + def handleTriggerQuery(self, query): items = [] @@ -61,7 +63,7 @@ def handleTriggerQuery(self, query): Action("remove", "Remove (forced, with volumes)", lambda c=container: c.remove(v=True, force=True)), Action("copy-id", "Copy id to clipboard", - lambda id=container.id: setClipboardText(id)) + lambda cid=container.id: setClipboardText(cid)) ]) items.append(StandardItem( From 28d94a0d027dac3be79d6aae986ccc058b9240e8 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:11:59 +0100 Subject: [PATCH 318/355] [duckduckgo] v3 --- duckduckgo/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/duckduckgo/__init__.py b/duckduckgo/__init__.py index e5b5a92b..3666115e 100644 --- a/duckduckgo/__init__.py +++ b/duckduckgo/__init__.py @@ -11,8 +11,8 @@ from itertools import islice from time import sleep -md_iid = '2.3' -md_version = '1.2' +md_iid = "3.0" +md_version = "2.0" md_name = 'DuckDuckGo' md_description = 'Inline DuckDuckGo web search' md_license = "MIT" @@ -25,13 +25,13 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='ddg ' - ) + TriggerQueryHandler.__init__(self) self.ddg = DDGS() self.iconUrls = [f"file:{Path(__file__).parent}/duckduckgo.svg"] + def defaultTrigger(self): + return "ddg " + def handleTriggerQuery(self, query): stripped = query.string.strip() @@ -46,7 +46,7 @@ def handleTriggerQuery(self, query): for r in islice(self.ddg.text(stripped, safesearch='off'), 10): query.add( StandardItem( - id=self.id, + id=self.id(), text=r['title'], subtext=r['body'], iconUrls=self.iconUrls, From 1a09f389ace86e62380d13a3caf1f972c86648eb Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 319/355] [emoji] v3 --- emoji/__init__.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index 120f1516..361198f0 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -5,14 +5,14 @@ import re import threading import urllib.request -from itertools import product +import builtins from locale import getdefaultlocale from pathlib import Path from albert import * -md_iid = '2.3' -md_version = "2.2" +md_iid = "3.0" +md_version = "3.0" md_name = "Emoji" md_description = "Find and copy emojis by name" md_license = "MIT" @@ -24,7 +24,7 @@ class Plugin(PluginInstance, IndexQueryHandler): def __init__(self): PluginInstance.__init__(self) - IndexQueryHandler.__init__(self, self.id, self.name, self.description, defaultTrigger=':') + IndexQueryHandler.__init__(self) self.thread = None self._use_derived = self.readConfig('use_derived', bool) @@ -35,6 +35,9 @@ def __del__(self): if self.thread and self.thread.is_alive(): self.thread.join() + def defaultTrigger(self): + return ':' + @property def use_derived(self): return self._use_derived @@ -69,7 +72,7 @@ def download_file(url: str, path: Path): with urllib.request.urlopen(request, timeout=3) as response: if response.getcode() == 200: debug(f"Success. Storing to {path}.") - with open(path, 'wb') as file: + with builtins.open(path, 'wb') as file: file.write(response.read()) else: raise RuntimeError(f"Failed to download {url}. Status code: {response.getcode()}") @@ -157,8 +160,8 @@ def get_annotations(cache_path: Path, use_derived: bool) -> dict: json_derived = json.load(file_derived)['annotationsDerived']['annotations'] return json_full | json_derived - emojis = get_fully_qualified_emojis(self.cacheLocation) - annotations = get_annotations(self.cacheLocation, self.use_derived) + emojis = get_fully_qualified_emojis(self.cacheLocation()) + annotations = get_annotations(self.cacheLocation(), self.use_derived) def remove_redundancy(sentences): sets_of_words = [set(sentence.lower().split()) for sentence in sentences] @@ -181,7 +184,7 @@ def remove_redundancy(sentences): non_rgi_emoji = emoji.replace('\uFE0F', '') ann = annotations[non_rgi_emoji] except KeyError as e: - # debug(f"Found no translation for {e}. Emoji will not be available.") + debug(f"Found no translation for {e}. Emoji will not be available.") continue title = ann['tts'][0] From 8e3635bec1c8aaec2a130a82c64d7d7b511b6770 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 320/355] [goldendict] v3 --- goldendict/__init__.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/goldendict/__init__.py b/goldendict/__init__.py index d60298eb..c25c72bb 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -6,23 +6,20 @@ from albert import * -md_iid = '2.3' -md_version = '1.5' -md_name = 'GoldenDict' -md_description = 'Quick access to GoldenDict' -md_license = 'MIT' -md_url = 'https://github.com/albertlauncher/python/tree/main/goldendict' -md_authors = '@manuelschneid3r' +md_iid = "3.0" +md_version = "2.0" +md_name = "GoldenDict" +md_description = "Quick access to GoldenDict" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/main/goldendict" +md_authors = "@manuelschneid3r" class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='gd ' - ) + TriggerQueryHandler.__init__(self) commands = [ '/var/lib/flatpak/exports/bin/org.goldendict.GoldenDict', # flatpak @@ -43,6 +40,9 @@ def __init__(self): warning(f"Multiple GoldenDict commands found: {', '.join(executables)}") warning(f"Using {self.executable}") + def defaultTrigger(self): + return "gd " + def handleTriggerQuery(self, query): q = query.string.strip() query.add( From 4aac6ca4a18c1a0e7e6bb14fda58c1fca97e9064 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 321/355] [jetbrains_projects] v3 --- jetbrains_projects/__init__.py | 43 +++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 36f7625e..3dbfcf2b 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -27,14 +27,14 @@ from dataclasses import dataclass from pathlib import Path -from typing import Union +from typing import Union, List from shutil import which from sys import platform from xml.etree import ElementTree from albert import * -md_iid = '2.5' -md_version = "2.1" +md_iid = "3.0" +md_version = "3.0" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" @@ -62,13 +62,14 @@ def __init__(self, name: str, icon: Path, config_dir_prefix: str, binaries: list self.config_dir_prefix = config_dir_prefix self.binary = self._find_binary(binaries) - def _find_binary(self, binaries: list[str]) -> Union[str, None]: + @staticmethod + def _find_binary(binaries: list[str]) -> Union[str, None]: for binary in binaries: if which(binary): return binary return None - def list_projects(self) -> list[Project]: + def list_projects(self) -> List[Project]: config_dir = Path.home() / ".config" if platform == "darwin": config_dir = Path.home() / "Library" / "Application Support" @@ -79,7 +80,8 @@ def list_projects(self) -> list[Project]: latest = sorted(dirs)[-1] return self._parse_recent_projects(Path(latest) / "options" / "recentProjects.xml") - def _parse_recent_projects(self, recent_projects_file: Path) -> list[Project]: + @staticmethod + def _parse_recent_projects(recent_projects_file: Path) -> list[Project]: try: root = ElementTree.parse(recent_projects_file).getroot() entries = root.findall(".//component[@name='RecentProjectsManager']//entry[@key]") @@ -113,10 +115,9 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='jb ' - ) + TriggerQueryHandler.__init__(self) + + self.fuzzy = False plugin_dir = Path(__file__).parent editors = [ @@ -196,22 +197,32 @@ def __init__(self): ] self.editors = [e for e in editors if e.binary is not None] + def supportsFuzzyMatching(self): + return True + + def setFuzzyMatching(self, enabled): + self.fuzzy = enabled + + def defaultTrigger(self): + return "jb " + def handleTriggerQuery(self, query: Query): editor_project_pairs = [] - m = Matcher(query.string) + m = Matcher(query.string, MatchConfig(fuzzy=self.fuzzy)) + for editor in self.editors: - projects = editor.list_projects() - projects = [p for p in projects if Path(p.path).exists()] - projects = [p for p in projects if m.match(p.name, p.path)] - editor_project_pairs.extend([(editor, p) for p in projects]) + for project in editor.list_projects(): + if Path(project.path).exists() and m.match(project.name, project.path): + editor_project_pairs.append((editor, project)) # sort by last opened editor_project_pairs.sort(key=lambda pair: pair[1].last_opened, reverse=True) query.add([self._make_item(editor, project, query) for editor, project in editor_project_pairs]) - def _make_item(self, editor: Editor, project: Project, query: Query) -> Item: + @staticmethod + def _make_item(editor: Editor, project: Project, query: Query) -> Item: return StandardItem( id="%s-%s-%s" % (editor.binary, project.path, project.last_opened), text=project.name, From a3225989dee2a2a2deebd0938bdf151918097aba Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 322/355] [kill] v3 --- kill/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kill/__init__.py b/kill/__init__.py index c443d2b1..c9c69231 100644 --- a/kill/__init__.py +++ b/kill/__init__.py @@ -9,8 +9,8 @@ from albert import * -md_iid = '2.3' -md_version = "1.4" +md_iid = "3.0" +md_version = "2.0" md_name = "Kill Process" md_description = "Kill processes" md_license = "MIT" @@ -21,10 +21,10 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='kill ' - ) + TriggerQueryHandler.__init__(self) + + def defaultTrigger(self): + return "kill " def handleTriggerQuery(self, query): if not query.isValid: From 2a503e63b4048a28e15e5d4b33bab4bd9ff93748 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 323/355] [locate] v3 --- locate/__init__.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/locate/__init__.py b/locate/__init__.py index 8da7db90..55015ba8 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -13,8 +13,8 @@ from albert import * -md_iid = '2.3' -md_version = "1.10" +md_iid = "3.0" +md_version = "2.0" md_name = "Locate" md_description = "Find and open files using locate" md_license = "MIT" @@ -27,11 +27,7 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - synopsis='', - defaultTrigger="'" - ) + TriggerQueryHandler.__init__(self) self.iconUrls = [ "xdg:preferences-system-search", @@ -41,6 +37,12 @@ def __init__(self): f"file:{Path(__file__).parent}/locate.svg" ] + def synopsis(self, query): + return "" + + def defaultTrigger(self): + return "'" + def handleTriggerQuery(self, query): if len(query.string) > 2: From a12c9b03c4659a6bf90caf6659daaced58ba6b2b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 324/355] [pacman] v3 --- pacman/__init__.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pacman/__init__.py b/pacman/__init__.py index a522c73a..eb0e3e14 100644 --- a/pacman/__init__.py +++ b/pacman/__init__.py @@ -7,8 +7,8 @@ from albert import Action, StandardItem, PluginInstance, TriggerQueryHandler, runTerminal, openUrl -md_iid = '2.3' -md_version = "1.10" +md_iid = "3.0" +md_version = "2.0" md_name = "PacMan" md_description = "Search, install and remove packages" md_license = "MIT" @@ -23,17 +23,19 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - synopsis='', - defaultTrigger='pac ' - ) + TriggerQueryHandler.__init__(self) self.iconUrls = [ "xdg:archlinux-logo", "xdg:system-software-install", f"file:{pathlib.Path(__file__).parent}/arch.svg" ] + def synopsis(self, query): + return "" + + def defaultTrigger(self): + return "pac " + def handleTriggerQuery(self, query): stripped = query.string.strip() From 5808276dc70f85d543216504c5d54a1327010f69 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 325/355] [pass] v3 --- pass/__init__.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pass/__init__.py b/pass/__init__.py index 567d1650..2a0ce20a 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -7,8 +7,8 @@ import os from albert import * -md_iid = '2.3' -md_version = "1.7" +md_iid = "3.0" +md_version = "2.0" md_name = "Pass" md_description = "Manage passwords in pass" md_license = "BSD-3" @@ -23,11 +23,7 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - synopsis='', - defaultTrigger='pass ' - ) + TriggerQueryHandler.__init__(self) self.iconUrls = ["xdg:dialog-password"] self._use_otp = self.readConfig("use_otp", bool) or False self._otp_glob = self.readConfig("otp_glob", str) or "*-otp.gpg" @@ -52,6 +48,12 @@ def otp_glob(self, value): self._otp_glob = value self.writeConfig("otp_glob", value) + def defaultTrigger(self): + return "pass " + + def synopsis(self, query): + return "" + def configWidget(self): return [ {"type": "checkbox", "property": "use_otp", "label": "Enable pass OTP extension"}, From b7cd108cfdd12e46b62b1a52d762cd949f11d777 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 326/355] [pomodoro] v3 --- pomodoro/__init__.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/pomodoro/__init__.py b/pomodoro/__init__.py index 4a38a8d4..39dc9b35 100644 --- a/pomodoro/__init__.py +++ b/pomodoro/__init__.py @@ -5,15 +5,14 @@ Wiki: [Pomodoro_Technique](https://en.wikipedia.org/wiki/Pomodoro_Technique). """ -import subprocess import threading import time from pathlib import Path from albert import * -md_iid = '2.3' -md_version = "1.7" +md_iid = "3.0" +md_version = "2.0" md_name = "Pomodoro" md_description = "Set up a Pomodoro timer" md_license = "MIT" @@ -27,6 +26,12 @@ def __init__(self): self.isBreak = True self.timer = None self.notification = None + self.remainingTillLongBreak = 0 + self.endTime = 0 + self.pomodoroDuration = 0 + self.breakDuration = 0 + self.longBreakDuration = 0 + self.count = 0 def timeout(self): if self.isBreak: @@ -77,14 +82,16 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - synopsis='[duration [break duration [long break duration [count]]]]', - defaultTrigger='pomo ' - ) + TriggerQueryHandler.__init__(self) self.pomodoro = PomodoroTimer() self.iconUrls = [f"file:{Path(__file__).parent}/pomodoro.svg"] + def defaultTrigger(self): + return 'pomo ' + + def synopsis(self, query): + return '[duration [break duration [long break duration [count]]]]' + def configWidget(self): return [ { @@ -96,13 +103,13 @@ def configWidget(self): def handleTriggerQuery(self, query): item = StandardItem( - id=self.id, + id=self.id(), iconUrls=self.iconUrls, ) if self.pomodoro.isActive(): item.text = "Stop Pomodoro" - item.actions = [Action("stop", "Stop", lambda p=self.pomodoro: p.stop())] + item.actions = [Action("stop", "Stop", lambda pomo=self.pomodoro: pomo.stop())] if self.pomodoro.isBreak: whatsNext = "Pomodoro" else: @@ -125,5 +132,5 @@ def handleTriggerQuery(self, query): item.text = "Start Pomodoro" item.subtext = f"{p} min, break {b} min, long break {lb} min, count {c}" item.actions = [Action("start", "Start", - lambda p=p, b=b, lb=lb, c=c: self.pomodoro.start(p, b, lb, c))] + lambda _p=p, _b=b, _lb=lb, _c=c: self.pomodoro.start(_p, _b, _lb, _c))] query.add(item) From 2aca84dfd488ea54610286fd3db9e186afd7e455 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 327/355] [python_eval] v3 --- python_eval/__init__.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/python_eval/__init__.py b/python_eval/__init__.py index c054025d..1acce6c4 100644 --- a/python_eval/__init__.py +++ b/python_eval/__init__.py @@ -1,14 +1,12 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017-2014 Manuel Schneider -from builtins import pow -from math import * from pathlib import Path from albert import * -md_iid = '2.3' -md_version = "1.6" +md_iid = "3.0" +md_version = "2.0" md_name = "Python Eval" md_description = "Evaluate Python code" md_license = "BSD-3" @@ -20,13 +18,15 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - synopsis='', - defaultTrigger='py ' - ) + TriggerQueryHandler.__init__(self) self.iconUrls = [f"file:{Path(__file__).parent}/python.svg"] + def synopsis(self, query): + return "" + + def defaultTrigger(self): + return "py " + def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: @@ -38,7 +38,7 @@ def handleTriggerQuery(self, query): result_str = str(result) query.add(StandardItem( - id=self.id, + id=self.id(), text=result_str, subtext=type(result).__name__, inputActionText=query.trigger + result_str, From 6267a9177bc4ac3efd0b8185e5564ffbf6560579 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 328/355] [syncthing] v3 --- syncthing/__init__.py | 69 +++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/syncthing/__init__.py b/syncthing/__init__.py index 1ddb423c..ce4cb3e7 100644 --- a/syncthing/__init__.py +++ b/syncthing/__init__.py @@ -10,8 +10,8 @@ from albert import * from syncthing import Syncthing -md_iid = '2.3' -md_version = "1.1" +md_iid = "3.0" +md_version = "2.0" md_name = "Syncthing" md_description = "Trigger basic syncthing actions." md_license = "MIT" @@ -26,12 +26,16 @@ class Plugin(PluginInstance, GlobalQueryHandler): def __init__(self): PluginInstance.__init__(self) - GlobalQueryHandler.__init__(self, self.id, self.name, self.description, defaultTrigger='st ') + GlobalQueryHandler.__init__(self) + self.iconUrls = ["xdg:syncthing", f"file:{Path(__file__).parent}/syncthing.svg"] self._api_key = self.readConfig(self.config_key, str) if self._api_key: self.st = Syncthing(self._api_key) + def defaultTrigger(self): + return 'st ' + @property def api_key(self) -> str: return self._api_key @@ -84,7 +88,7 @@ def handleGlobalQuery(self, query): matcher = Matcher(query.string) # create device items - for id, d in devices.items(): + for device_id, d in devices.items(): device_name = d['name'] if match := matcher.match(device_name): @@ -94,50 +98,43 @@ def handleGlobalQuery(self, query): if d['paused']: actions.append( Action("resume", "Resume synchronization", - lambda did=id: self.st.system.resume(did)) + lambda did=device_id: self.st.system.resume(did)) ) else: actions.append( Action("pause", "Pause synchronization", - lambda did=id: self.st.system.pause(did)) + lambda did=device_id: self.st.system.pause(did)) ) - results.append( - RankItem( - StandardItem( - id=id, - text=f"{device_name}", - subtext=f"{'Paused ' if d['paused'] else ''}Syncthing device. " - f"Shared: {device_folders if device_folders else 'Nothing'}.", - iconUrls=self.iconUrls, - actions=actions - ), - match.score - ) + item = StandardItem( + id=device_id, + text=f"{device_name}", + subtext=f"{'Paused ' if d['paused'] else ''}Syncthing device. " + f"Shared: {device_folders if device_folders else 'Nothing'}.", + iconUrls=self.iconUrls, + actions=actions ) + results.append(RankItem(item, match)) + # create folder items - for id, f in folders.items(): + for folder_id, f in folders.items(): folder_name = f['label'] if match := matcher.match(folder_name): folders_devices = ", ".join([devices[d['deviceID']]['name'] for d in f['devices']]) - results.append( - RankItem( - StandardItem( - id=id, - text=folder_name, - subtext=f"Syncthing folder {f['path']}. " - f"Shared with {folders_devices if folders_devices else 'nobody'}.", - iconUrls=self.iconUrls, - actions=[ - Action("scan", "Scan the folder", - lambda fid=id: self.st.database.scan(fid)), - Action("open", "Open this folder in file browser", - lambda p=f['path']: openUrl(f'file://{p}')) - ] - ), - match.score - ) + item = StandardItem( + id=folder_id, + text=folder_name, + subtext=f"Syncthing folder {f['path']}. " + f"Shared with {folders_devices if folders_devices else 'nobody'}.", + iconUrls=self.iconUrls, + actions=[ + Action("scan", "Scan the folder", + lambda fid=folder_id: self.st.database.scan(fid)), + Action("open", "Open this folder in file browser", + lambda p=f['path']: openFile(p)) + ] ) + results.append(RankItem(item, match)) return results From 958eff2e66bacf8970caff4cd707ecbe89e8fca9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 329/355] [tex_to_unicode] v3 --- tex_to_unicode/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tex_to_unicode/__init__.py b/tex_to_unicode/__init__.py index baf5905d..629e4584 100644 --- a/tex_to_unicode/__init__.py +++ b/tex_to_unicode/__init__.py @@ -9,8 +9,8 @@ from albert import * -md_iid = '2.3' -md_version = "1.3" +md_iid = "3.0" +md_version = "2.0" md_name = "TeX to Unicode" md_description = "Convert TeX mathmode commands to unicode characters" md_license = "MIT" @@ -23,7 +23,7 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__(self, self.id, self.name, self.description, defaultTrigger='tex ') + TriggerQueryHandler.__init__(self) self.COMBINING_LONG_SOLIDUS_OVERLAY = "\u0338" self.iconUrls = [f"file:{Path(__file__).parent}/tex.svg"] @@ -38,13 +38,16 @@ def _create_item(self, text: str, subtext: str, can_copy: bool): ) ) return StandardItem( - id=self.id, + id=self.id(), text=text, subtext=subtext, iconUrls=self.iconUrls, actions=actions, ) + def defaultTrigger(self): + return "tex " + def handleTriggerQuery(self, query): stripped = query.string.strip() From cc0b3b72c9059e4471292d0b0ed7416690335e8f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 330/355] [translators] v3 --- translators/__init__.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/translators/__init__.py b/translators/__init__.py index 85f7b098..862f427f 100644 --- a/translators/__init__.py +++ b/translators/__init__.py @@ -12,8 +12,8 @@ from albert import * import translators as ts -md_iid = '2.3' -md_version = "1.8" +md_iid = "3.0" +md_version = "2.0" md_name = "Translator" md_description = "Translate sentences using 'translators' package" md_license = "MIT" @@ -26,11 +26,8 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - synopsis="[[from] to] text", - defaultTrigger='tr ' - ) + TriggerQueryHandler.__init__(self) + self.iconUrls = [f"file:{Path(__file__).parent}/google_translate.png"] self._translator = self.readConfig('translator', str) @@ -69,6 +66,9 @@ def lang(self, value): self._lang = value self.writeConfig('lang', value) + def defaultTrigger(self): + return 'tr ' + def configWidget(self): return [ { @@ -88,6 +88,9 @@ def configWidget(self): } ] + def synopsis(self, s): + return "[[from] to] text" + def handleTriggerQuery(self, query): stripped = query.string.strip() if stripped: @@ -126,7 +129,7 @@ def handleTriggerQuery(self, query): ) query.add(StandardItem( - id=self.id, + id=self.id(), text=translation, subtext=f"{src.upper()} > {dst.upper()}", iconUrls=self.iconUrls, @@ -136,7 +139,7 @@ def handleTriggerQuery(self, query): except Exception as e: query.add(StandardItem( - id=self.id, + id=self.id(), text="Error", subtext=str(e), iconUrls=self.iconUrls From 20a33badfa61bcd0d7678a87358285fb535d2855 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 331/355] [unit_converter] v3 --- unit_converter/__init__.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/unit_converter/__init__.py b/unit_converter/__init__.py index 6fcf779f..cd26cf22 100644 --- a/unit_converter/__init__.py +++ b/unit_converter/__init__.py @@ -25,7 +25,7 @@ import pint from albert import * -md_iid = "2.3" +md_iid = "3.0" md_version = "1.8" md_name = "Unit Converter" md_description = "Convert between units" @@ -126,7 +126,7 @@ def formatted_from(self) -> str: def icon(self) -> str: """Return the icon for the result's dimensionality""" # strip characters from the dimensionality if not alphanumeric or underscore - dimensionality = re.sub(r"[^\w]", "", self.dimensionality) + dimensionality = re.sub(r"\W", "", self.dimensionality) return f"{dimensionality}.svg" def __repr__(self): @@ -345,14 +345,7 @@ class Plugin(PluginInstance, GlobalQueryHandler): def __init__(self): PluginInstance.__init__(self) - GlobalQueryHandler.__init__( - self, - id=self.id, - name=self.name, - description=self.description, - synopsis=" to ", - defaultTrigger="convert ", - ) + GlobalQueryHandler.__init__(self) self.unit_convert_regex = re.compile( r"(?P-?\d+\.?\d*)\s?(?P.*)\s(?:to|in)\s(?P.*)", @@ -361,6 +354,12 @@ def __init__(self): self.unit_converter = StandardUnitConverter() self.currency_converter = CurrencyConverter() + def defaultTrigger(self): + return "convert " + + def synopsis(self, query): + return " to " + def handleTriggerQuery(self, query: Query) -> None: if query_string := query.string.strip(): items = self.match_query(query_string) From 920b617ea142f9e0627a3c35653915a088db0ede Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 332/355] [virtualbox] v3 --- virtualbox/__init__.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/virtualbox/__init__.py b/virtualbox/__init__.py index 8ba78272..ad39ebbf 100644 --- a/virtualbox/__init__.py +++ b/virtualbox/__init__.py @@ -11,8 +11,8 @@ from albert import * -md_iid = '2.3' -md_version = "1.7" +md_iid = "3.0" +md_version = "2.0" md_name = "VirtualBox" md_description = "Manage your VirtualBox machines" md_license = "MIT" @@ -64,13 +64,15 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - synopsis='', - defaultTrigger='vbox ' - ) + TriggerQueryHandler.__init__(self) self.iconUrls = ["xdg:virtualbox", ":unknown"] + def defaultTrigger(self): + return 'vbox ' + + def synopsis(self, query): + return "" + def configWidget(self): return [ { @@ -89,17 +91,17 @@ def handleTriggerQuery(self, query): for vm in filter(lambda vm: pattern in vm.name.lower(), virtualbox.VirtualBox().machines): actions = [] if vm.state == MachineState.powered_off or vm.state == MachineState.aborted: # 1 # 4 - actions.append(Action("startvm", "Start virtual machine", lambda vm=vm: startVm(vm))) + actions.append(Action("startvm", "Start virtual machine", lambda m=vm: startVm(m))) if vm.state == MachineState.saved: # 2 - actions.append(Action("restorevm", "Start saved virtual machine", lambda vm=vm: startVm(vm))) - actions.append(Action("discardvm", "Discard saved state", lambda vm=vm: discardSavedVm(vm))) + actions.append(Action("restorevm", "Start saved virtual machine", lambda m=vm: startVm(m))) + actions.append(Action("discardvm", "Discard saved state", lambda m=vm: discardSavedVm(m))) if vm.state == MachineState.running: # 5 - actions.append(Action("savevm", "Save virtual machine", lambda vm=vm: saveVm(vm))) - actions.append(Action("poweroffvm", "Power off via ACPI event (Power button)", lambda vm=vm: acpiPowerVm(vm))) - actions.append(Action("stopvm", "Turn off virtual machine", lambda vm=vm: stopVm(vm))) - actions.append(Action("pausevm", "Pause virtual machine", lambda vm=vm: pauseVm(vm))) + actions.append(Action("savevm", "Save virtual machine", lambda m=vm: saveVm(m))) + actions.append(Action("poweroffvm", "Power off via ACPI event (Power button)", lambda m=vm: acpiPowerVm(m))) + actions.append(Action("stopvm", "Turn off virtual machine", lambda m=vm: stopVm(m))) + actions.append(Action("pausevm", "Pause virtual machine", lambda m=vm: pauseVm(m))) if vm.state == MachineState.paused: # 6 - actions.append(Action("resumevm", "Resume virtual machine", lambda vm=vm: resumeVm(vm))) + actions.append(Action("resumevm", "Resume virtual machine", lambda m=vm: resumeVm(m))) items.append( StandardItem( From ff8ac96f6929591ec845198f237ecde6edcf6e51 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 00:12:00 +0100 Subject: [PATCH 333/355] [vpn] v3 --- vpn/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vpn/__init__.py b/vpn/__init__.py index db122112..f529bc93 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -8,8 +8,8 @@ from albert import * -md_iid = '2.3' -md_version = "1.6" +md_iid = "3.0" +md_version = "2.0" md_name = "VPN" md_description = "Manage NetworkManager VPN connections" md_license = "MIT" @@ -24,10 +24,10 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='vpn ' - ) + TriggerQueryHandler.__init__(self) + + def defaultTrigger(self): + return "vpn " def getVPNConnections(self): consStr = subprocess.check_output( From 69d51583cdb0cb2d5040e7535ae88332cc14e9f7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 14:05:11 +0100 Subject: [PATCH 334/355] [wikipedia] v3.0 --- wikipedia/__init__.py | 46 ++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/wikipedia/__init__.py b/wikipedia/__init__.py index 2305117a..af92e2f6 100644 --- a/wikipedia/__init__.py +++ b/wikipedia/__init__.py @@ -10,15 +10,14 @@ import json from pathlib import Path -md_iid = '2.3' -md_version = "2.0" +md_iid = "3.0" +md_version = "3.0" md_name = "Wikipedia" md_description = "Search Wikipedia articles" md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/main/wikipedia" md_authors = "@manuelschneid3r" - class Plugin(PluginInstance, TriggerQueryHandler): baseurl = 'https://en.wikipedia.org/w/api.php' @@ -29,10 +28,9 @@ class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='wiki ', supportsFuzzyMatching=True - ) + TriggerQueryHandler.__init__(self) + + self.fbh = FBH(self) self.fuzzy = False self.local_lang_code = getdefaultlocale()[0] @@ -42,9 +40,6 @@ def __init__(self): self.local_lang_code = 'en' warning("Failed getting language code. Using 'en'.") - self.fbh = FBH(self) - self.registerExtension(self.fbh) - params = { 'action': 'query', 'meta': 'siteinfo', @@ -66,8 +61,14 @@ def __init__(self): except Exception as error: warning('Error getting languages (%s). Defaulting to EN.' % error) - def __del__(self): - self.deregisterExtension(self.fbh) + def extensions(self): + return [self, self.fbh] + + def defaultTrigger(self): + return "wiki " + + def supportsFuzzyMatching(self): + return True def setFuzzyMatching(self, enabled: bool): self.fuzzy = enabled @@ -103,7 +104,7 @@ def handleTriggerQuery(self, query): url = data[3][i] results.append( StandardItem( - id=self.id, + id=self.id(), text=title, subtext=summary if summary else url, iconUrls=self.iconUrls, @@ -121,8 +122,8 @@ def handleTriggerQuery(self, query): else: query.add( StandardItem( - id=self.id, - text=self.name, + id=self.id(), + text=self.name(), subtext="Enter a query to search on Wikipedia", iconUrls=self.iconUrls ) @@ -130,8 +131,8 @@ def handleTriggerQuery(self, query): def createFallbackItem(self, q: str) -> Item: return StandardItem( - id=self.id, - text=self.name, + id=self.id(), + text=self.name(), subtext="Search '%s' on Wikipedia" % q, iconUrls=self.iconUrls, actions=[ @@ -144,8 +145,17 @@ def createFallbackItem(self, q: str) -> Item: class FBH(FallbackHandler): def __init__(self, p: Plugin): - FallbackHandler.__init__(self, p.id + 'fb', p.name, p.description) + FallbackHandler.__init__(self) self.plugin = p + def id(self): + return "wikipedia.fallbacks" + + def name(self): + return md_name + + def description(self): + return md_description + def fallbacks(self, q :str): return [self.plugin.createFallbackItem(q)] From 0958ea7e770730da6884c170d30190012e050782 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Feb 2025 14:06:11 +0100 Subject: [PATCH 335/355] [zeal] v3.0 --- zeal/__init__.py | 75 ++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/zeal/__init__.py b/zeal/__init__.py index 89e6bd63..1339a7d9 100644 --- a/zeal/__init__.py +++ b/zeal/__init__.py @@ -1,54 +1,55 @@ # -*- coding: utf-8 -*- # Copyright (c) 2024 Manuel Schneider -from albert import * +import albert -md_iid = '2.3' -md_version = '2.0' -md_name = 'Zeal' -md_description = 'Search in Zeal docs' +md_iid = "3.0" +md_version = "3.0" +md_name = "Zeal" +md_description = "Search in Zeal docs" md_license = "MIT" -md_url = 'https://github.com/albertlauncher/python/tree/main/zeal' +md_url = "https://github.com/albertlauncher/python/tree/main/zeal" md_authors = "@manuelschneid3r" md_bin_dependencies = ['zeal'] +def createItem(query: str): + return albert.StandardItem( + id=md_name, + text=md_name, + subtext=f"Search '{query}' in Zeal", + iconUrls=["xdg:zeal"], + actions=[albert.Action("zeal", "Search in Zeal", + lambda q=query: albert.runDetachedProcess(['zeal', q]))] + ) + +class FBH(albert.FallbackHandler): + + def id(self): + return "zeal_fbh" + + def name(self): + return md_name + + def description(self): + return md_description -class FBH(FallbackHandler): def fallbacks(self, s): - return [Plugin.createItem(s)] if s else [] + return [createItem(s)] if s else [] -class Plugin(PluginInstance, TriggerQueryHandler): +class Plugin(albert.PluginInstance, albert.TriggerQueryHandler): def __init__(self): - PluginInstance.__init__(self) - TriggerQueryHandler.__init__( - self, self.id, self.name, self.description, - defaultTrigger='z ' - ) - self.fbh = FBH( - id=self.id + 'fb', - name=self.name, - description=self.description - ) - - self.registerExtension(self.fbh) - - def __del__(self): - self.deregisterExtension(self.fbh) + albert.PluginInstance.__init__(self) + albert.TriggerQueryHandler.__init__(self) + self.fbh = FBH() + + def defaultTrigger(self): + return "z " + + def extensions(self): + return [self, self.fbh] def handleTriggerQuery(self, query): if stripped := query.string.strip(): - query.add(self.createItem(stripped)) - - @staticmethod - def createItem(query: str) -> Item: - return StandardItem( - id=md_name, - text=md_name, - subtext=f"Search '{query}' in Zeal", - iconUrls=["xdg:zeal"], - actions=[Action("zeal", "Search in Zeal", - lambda q=query: runDetachedProcess(['zeal', q]))] - ) - + query.add(createItem(stripped)) From 806da15b4ec4f0738cdd4730aa6a337a9abbd9ff Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 5 Mar 2025 11:52:16 +0100 Subject: [PATCH 336/355] [vpn] Archive The native VPN plugin now covers NetworkManager --- {vpn => .archive/vpn}/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {vpn => .archive/vpn}/__init__.py (100%) diff --git a/vpn/__init__.py b/.archive/vpn/__init__.py similarity index 100% rename from vpn/__init__.py rename to .archive/vpn/__init__.py From dd2d795aa068429cc6c75812d71928eb664bddbe Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 5 Mar 2025 13:57:30 +0100 Subject: [PATCH 337/355] Update readme --- README.md | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 9a5cd63a..b95c05b6 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,11 @@ ## Official Albert Python plugin repository -This repository is shipped with Albert. Credits go to our contributors 👍 +These plugins are shipped with the app. + +Visit the website to learn [how to write plugins](https://albertlauncher.github.io/gettingstarted/extension/). + +Credits go to our contributors: - -### Contribution - -* Fork this repository. -* Clone it into the Python user plugin location. - ```shell - # on linux - git clone https://github.com//python.git ~/.local/share/albert/python/plugins - - # on macos - git clone https://github.com//python.git ~/Library/Application\ Support/albert/python/plugins - ``` -* Open the directory in your favorite IDE (PyCharmCE is a good choice). -* The Python plugins plugin installs a python stub file in your user plugin directory. This file serves as API documentation and gives you coding assistance if you are using a decent IDE. -* Write your plugin. Make sure it is polished (No bugs, few to no linting warnings, efficient, readable, maintainable, …). -* Commit, push, send a PR. From fc25d02f9f8b009691f369d9190677c54bd62800 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 6 Mar 2025 21:41:55 +0100 Subject: [PATCH 338/355] [emoji] Make sure cache location exists Close https://github.com/albertlauncher/albert/issues/1521 --- emoji/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/emoji/__init__.py b/emoji/__init__.py index 361198f0..49bfa0a3 100644 --- a/emoji/__init__.py +++ b/emoji/__init__.py @@ -12,7 +12,7 @@ from albert import * md_iid = "3.0" -md_version = "3.0" +md_version = "3.1" md_name = "Emoji" md_description = "Find and copy emojis by name" md_license = "MIT" @@ -160,8 +160,10 @@ def get_annotations(cache_path: Path, use_derived: bool) -> dict: json_derived = json.load(file_derived)['annotationsDerived']['annotations'] return json_full | json_derived - emojis = get_fully_qualified_emojis(self.cacheLocation()) - annotations = get_annotations(self.cacheLocation(), self.use_derived) + cache_location = self.cacheLocation() + cache_location.mkdir(parents=True, exist_ok=True) + emojis = get_fully_qualified_emojis(cache_location) + annotations = get_annotations(cache_location, self.use_derived) def remove_redundancy(sentences): sets_of_words = [set(sentence.lower().split()) for sentence in sentences] From 41f93b9506dacb6414ed7bad2826d13c97020bed Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 6 Mar 2025 21:50:11 +0100 Subject: [PATCH 339/355] [coingecko] Make sure cache location exists --- coingecko/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index 76f9f089..328a3189 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -91,7 +91,9 @@ def __init__(self): self.items = [] self.mtime = 0 - self.coinCacheFilePath = self.cacheLocation() / "coins.json" + cache_location = self.cacheLocation() + cache_location.mkdir(parents=True, exist_ok=True) + self.coinCacheFilePath = cache_location / "coins.json" self.thread = CoinFetcherThread(self.updateIndexItems, self.coinCacheFilePath) self.thread.start() From a8507e5920ad3e68d13c9d0a821c29f5b5c06cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Rag=C3=A1ny-N=C3=A9meth?= Date: Sat, 8 Mar 2025 19:41:08 +0100 Subject: [PATCH 340/355] [jetbrains_projects] Fix Rider config --- jetbrains_projects/__init__.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 3dbfcf2b..c25c13ef 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -56,11 +56,21 @@ class Editor: config_dir_prefix: str binary: str - def __init__(self, name: str, icon: Path, config_dir_prefix: str, binaries: list[str]): + # Rider calls recentProjects.xml -> recentSolutions.xml and in it RecentProjectsManager -> RiderRecentProjectsManager + is_rider: bool + + def __init__( + self, + name: str, + icon: Path, + config_dir_prefix: str, + binaries: list[str], + is_rider = False): self.name = name self.icon = icon self.config_dir_prefix = config_dir_prefix self.binary = self._find_binary(binaries) + self.is_rider = is_rider @staticmethod def _find_binary(binaries: list[str]) -> Union[str, None]: @@ -78,13 +88,20 @@ def list_projects(self) -> List[Project]: if not dirs: return [] latest = sorted(dirs)[-1] - return self._parse_recent_projects(Path(latest) / "options" / "recentProjects.xml") + if not self.is_rider: + recent_projects_xml = "recentProjects.xml" + else: + recent_projects_xml = "recentSolutions.xml" + return self._parse_recent_projects(Path(latest) / "options" / recent_projects_xml) @staticmethod def _parse_recent_projects(recent_projects_file: Path) -> list[Project]: try: root = ElementTree.parse(recent_projects_file).getroot() - entries = root.findall(".//component[@name='RecentProjectsManager']//entry[@key]") + if not self.is_rider: + entries = root.findall(".//component[@name='RecentProjectsManager']//entry[@key]") + else: + entries = root.findall(".//component[@name='RiderRecentProjectsManager']//entry[@key]") projects = [] for entry in entries: @@ -173,7 +190,8 @@ def __init__(self): name="Rider", icon=plugin_dir / "icons" / "rider.svg", config_dir_prefix="JetBrains/Rider", - binaries=["rider", "rider-eap"]), + binaries=["rider", "rider-eap"], + is_rider=True), Editor( name="RubyMine", icon=plugin_dir / "icons" / "rubymine.svg", From 145b5e97461505f2a6479e29d1c254e8c425030d Mon Sep 17 00:00:00 2001 From: Jose David Rueda Date: Wed, 26 Mar 2025 04:49:48 -0500 Subject: [PATCH 341/355] [bitwarden] v3.1 - cache `rbw list` response - add cache_timeout config prop --- bitwarden/__init__.py | 100 ++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 23 deletions(-) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 6e9e8031..3c8bf20e 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -1,12 +1,15 @@ # -*- coding: utf-8 -*- +import time +from dataclasses import dataclass +from enum import Enum from pathlib import Path -from subprocess import run, CalledProcessError +from subprocess import CalledProcessError, run from albert import * md_iid = "3.0" -md_version = "3.0" +md_version = "3.1" md_name = "Bitwarden" md_description = "'rbw' wrapper extension" md_license = "MIT" @@ -14,8 +17,18 @@ md_authors = ["@ovitor", "@daviddeadly", "@manuelschneid3r"] md_bin_dependencies = ["rbw"] +MAX_MINUTES_CACHE_TIMEOUT = 60 +DEFAULT_MINUTE_CACHE_TIMEOUT = 5 + + +@dataclass(frozen=True) +class ConfigKeys: + CACHE_TIMEOUT = "cache_timeout" + class Plugin(PluginInstance, TriggerQueryHandler): + _cached_items = None + _last_fetch_time = 0 iconUrls = [f"file:{Path(__file__).parent}/bw.svg"] @@ -23,8 +36,36 @@ def __init__(self): PluginInstance.__init__(self) TriggerQueryHandler.__init__(self) + self.cache_timeout = ( + self.readConfig(ConfigKeys.CACHE_TIMEOUT, int) + or DEFAULT_MINUTE_CACHE_TIMEOUT + ) + def defaultTrigger(self): - return 'bw ' + return "bw " + + @property + def cache_timeout(self): + return int(self._cache_timeout / 60) + + @cache_timeout.setter + def cache_timeout(self, value): + self._cache_timeout = int(value * 60) + self.writeConfig(ConfigKeys.CACHE_TIMEOUT, value) + + def configWidget(self): + return [ + { + "type": "label", + "text": "Cache (result of `rbw list`) duration", + }, + { + "type": "spinbox", + "property": ConfigKeys.CACHE_TIMEOUT, + "label": f"Minutes: (max: {MAX_MINUTES_CACHE_TIMEOUT}, disable: 0)", + "widget_properties": {"maximum": MAX_MINUTES_CACHE_TIMEOUT}, + }, + ] def handleTriggerQuery(self, query): if query.string.strip().lower() == "sync": @@ -37,11 +78,9 @@ def handleTriggerQuery(self, query): Action( id="sync", text="Syncing Bitwarden Vault", - callable=lambda: run( - ["rbw", "sync"], - ) + callable=lambda: self._sync_vault(), ) - ] + ], ) ) @@ -56,30 +95,38 @@ def handleTriggerQuery(self, query): Action( id="copy", text="Copy password to clipboard", - callable=lambda item=p: self._password_to_clipboard(item) + callable=lambda item=p: self._password_to_clipboard(item), ), Action( id="copy-auth", text="Copy auth code to clipboard", - callable=lambda item=p: self._code_to_clipboard(item) + callable=lambda item=p: self._code_to_clipboard(item), ), Action( id="copy-username", text="Copy username to clipboard", - callable=lambda username=p["user"]: - setClipboardText(text=username) + callable=lambda username=p["user"]: setClipboardText( + text=username + ), ), Action( id="edit", text="Edit entry in terminal", - callable=lambda item=p: self._edit_entry(item) - ) - ] + callable=lambda item=p: self._edit_entry(item), + ), + ], ) ) - @staticmethod - def _get_items(): + def _get_items(self): + not_first_time = self._cached_items is not None + + time_passed = time.time() - self._last_fetch_time + is_chache_fresh = time_passed < self._cache_timeout + + if not_first_time and is_chache_fresh: + return self._cached_items + field_names = ["id", "name", "user", "folder"] raw_items = run( ["rbw", "list", "--fields", ",".join(field_names)], @@ -98,12 +145,16 @@ def _get_items(): item["path"] = item["folder"] + "/" + item["name"] else: item["path"] = item["name"] + items.append(item) + self._cached_items = items + self._last_fetch_time = time.time() + return items def _filter_items(self, query): - passwords = self._get_items() + passwords = self._get_items() or [] search_fields = ["path", "user"] # Use a set for faster membership tests words = set(query.string.strip().lower().split()) @@ -121,15 +172,18 @@ def _filter_items(self, query): return filtered_passwords + def _sync_vault(self): + run(["rbw", "sync"], check=True) + + self._cached_items = None + self._last_fetch_time = 0 + @staticmethod def _password_to_clipboard(item): rbw_id = item["id"] password = run( - ["rbw", "get", rbw_id], - capture_output=True, - encoding="utf-8", - check=True + ["rbw", "get", rbw_id], capture_output=True, encoding="utf-8", check=True ).stdout.strip() setClipboardText(text=password) @@ -143,14 +197,14 @@ def _code_to_clipboard(item): ["rbw", "code", rbw_id], capture_output=True, encoding="utf-8", - check=True + check=True, ).stdout.strip() except CalledProcessError as err: code = run( ["echo", err.__str__()], capture_output=True, encoding="utf-8", - check=True + check=True, ).stdout.strip() setClipboardText(text=code) From abd1c4490c7aab0da80e0b66870b7246a73956fb Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Mar 2025 10:38:59 +0100 Subject: [PATCH 342/355] [coingecko] Use batch add to avoid flicker --- coingecko/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/coingecko/__init__.py b/coingecko/__init__.py index 328a3189..df23f20d 100644 --- a/coingecko/__init__.py +++ b/coingecko/__init__.py @@ -9,7 +9,7 @@ from threading import Thread, Event md_iid = "3.0" -md_version = "2.0" +md_version = "2.1" md_name = "CoinGecko" md_description = "Access CoinGecko" md_license = "MIT" @@ -133,6 +133,4 @@ def updateIndexItems(self): # override default trigger handling to sort by rank def handleTriggerQuery(self, query): m = Matcher(query.string) - for item in self.items: - if m.match(item.symbol, item.name): - query.add(item) + query.add([item for item in self.items if m.match(item.symbol, item.name)]) From a6cc30136e23bc622804c54fb63db82aa74603e7 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Mar 2025 12:00:48 +0100 Subject: [PATCH 343/355] [jetbrains_projects] Fix automerge issues --- jetbrains_projects/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index c25c13ef..a286ad38 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -94,8 +94,7 @@ def list_projects(self) -> List[Project]: recent_projects_xml = "recentSolutions.xml" return self._parse_recent_projects(Path(latest) / "options" / recent_projects_xml) - @staticmethod - def _parse_recent_projects(recent_projects_file: Path) -> list[Project]: + def _parse_recent_projects(self, recent_projects_file: Path) -> list[Project]: try: root = ElementTree.parse(recent_projects_file).getroot() if not self.is_rider: From cb2318242cec1691647f6486d2943cfb6ae9498f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Mar 2025 12:01:42 +0100 Subject: [PATCH 344/355] [jetbrains_projects] Adopt to core trigger behavior --- jetbrains_projects/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index a286ad38..c3cdd029 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -236,15 +236,15 @@ def handleTriggerQuery(self, query: Query): # sort by last opened editor_project_pairs.sort(key=lambda pair: pair[1].last_opened, reverse=True) - query.add([self._make_item(editor, project, query) for editor, project in editor_project_pairs]) + query.add([self._make_item(editor, project) for editor, project in editor_project_pairs]) @staticmethod - def _make_item(editor: Editor, project: Project, query: Query) -> Item: + def _make_item(editor: Editor, project: Project) -> Item: return StandardItem( id="%s-%s-%s" % (editor.binary, project.path, project.last_opened), text=project.name, subtext=project.path, - inputActionText=query.trigger + project.name, + inputActionText=project.name, iconUrls=["file:" + str(editor.icon)], actions=[ Action( From 3aa6a1396291c8055a16c28a12ab09c9dd40962b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Mar 2025 12:02:15 +0100 Subject: [PATCH 345/355] [jetbrains_projects] Add match path option Related: https://github.com/albertlauncher/python/pull/202 --- jetbrains_projects/__init__.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index c3cdd029..5e50e509 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -135,6 +135,10 @@ def __init__(self): self.fuzzy = False + self._match_path = self.readConfig('match_path', bool) + if self._match_path is None: + self._match_path = False + plugin_dir = Path(__file__).parent editors = [ Editor( @@ -214,6 +218,15 @@ def __init__(self): ] self.editors = [e for e in editors if e.binary is not None] + @property + def match_path(self): + return self._match_path + + @match_path.setter + def match_path(self, value): + self._match_path = value + self.writeConfig('match_path', value) + def supportsFuzzyMatching(self): return True @@ -230,8 +243,13 @@ def handleTriggerQuery(self, query: Query): for editor in self.editors: for project in editor.list_projects(): - if Path(project.path).exists() and m.match(project.name, project.path): - editor_project_pairs.append((editor, project)) + if Path(project.path).exists(): + if self._match_path: + if m.match(project.name, project.path): + editor_project_pairs.append((editor, project)) + else: + if m.match(project.name): + editor_project_pairs.append((editor, project)) # sort by last opened editor_project_pairs.sort(key=lambda pair: pair[1].last_opened, reverse=True) @@ -259,6 +277,11 @@ def _make_item(editor: Editor, project: Project) -> Item: def configWidget(self): return [ + { + 'type': 'checkbox', + 'property': 'match_path', + 'label': 'Match path' + }, { 'type': 'label', 'text': __doc__.strip(), From 8df351d6cfb232e0df5569d60c436e41bc3e4896 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 26 Mar 2025 12:10:04 +0100 Subject: [PATCH 346/355] [jetbrains_projects] 4.0 --- jetbrains_projects/__init__.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index 5e50e509..fc4ae84d 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -5,8 +5,8 @@ """ This plugin allows you to quickly open projects of the Jetbrains IDEs -- Aqua - Android Studio +- Aqua - CLion - DataGrip - DataSpell @@ -16,13 +16,12 @@ - PyCharm - Rider - RubyMine +- RustRover - WebStorm - Writerside. Note that for this plugin to find the IDEs, a commandline launcher in $PATH is required. Open the IDE and click Tools -> Create Command-line Launcher to add one. - -Disclaimer: This plugin has no affiliation with JetBrains s.r.o.. The icons are used under the terms specified here. """ from dataclasses import dataclass @@ -34,7 +33,7 @@ from albert import * md_iid = "3.0" -md_version = "3.0" +md_version = "4.0" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" @@ -200,16 +199,16 @@ def __init__(self): icon=plugin_dir / "icons" / "rubymine.svg", config_dir_prefix="JetBrains/RubyMine", binaries=["rubymine", "rubymine-eap", "jetbrains-rubymine", "jetbrains-rubymine-eap"]), - Editor( - name="WebStorm", - icon=plugin_dir / "icons" / "webstorm.svg", - config_dir_prefix="JetBrains/WebStorm", - binaries=["webstorm", "webstorm-eap"]), Editor( name="RustRover", icon=plugin_dir / "icons" / "rustrover.svg", config_dir_prefix="JetBrains/RustRover", binaries=["rustrover", "rustrover-eap"]), + Editor( + name="WebStorm", + icon=plugin_dir / "icons" / "webstorm.svg", + config_dir_prefix="JetBrains/WebStorm", + binaries=["webstorm", "webstorm-eap"]), Editor( name="Writerside", icon=plugin_dir / "icons" / "writerside.svg", From 9b696d4ec77e5bc71a4ea86b7fcd392753eee605 Mon Sep 17 00:00:00 2001 From: M Naufal Shidqi Date: Fri, 28 Mar 2025 20:38:59 +0700 Subject: [PATCH 347/355] [x_window_switcher] 0.6.0 --- x_window_switcher/__init__.py | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 x_window_switcher/__init__.py diff --git a/x_window_switcher/__init__.py b/x_window_switcher/__init__.py new file mode 100644 index 00000000..00c180b9 --- /dev/null +++ b/x_window_switcher/__init__.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- + +import subprocess +from collections import namedtuple +from albert import * + +md_iid = "3.0" +md_version = "0.6.0" +md_name = "X Window Switcher" +md_description = "Switch X11 Windows" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/main/x_window_switcher" +md_bin_dependencies = "wmctrl" +md_authors = ["Ed Perez", "Manuel S.", "dshoreman", "nopsqi"] + +Window = namedtuple("Window", ["wid", "desktop", "wm_class", "host", "wm_name"]) + + +class Plugin(PluginInstance, TriggerQueryHandler): + def __init__(self): + PluginInstance.__init__(self) + TriggerQueryHandler.__init__(self) + + # Check for X session and wmctrl availability + try: + subprocess.check_call(["wmctrl", "-m"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except FileNotFoundError: + raise Exception("wmctrl not found. Please install wmctrl.") + except subprocess.CalledProcessError: + raise Exception("Unable to communicate with X11 window manager. This plugin requires a running X session.") + + def defaultTrigger(self): + return 'w ' + + def handleTriggerQuery(self, query): + try: + for line in subprocess.check_output(['wmctrl', '-l', '-x']).splitlines(): + win = Window(*parseWindow(line)) + + if win.desktop == "-1": + continue + + win_instance, win_class = win.wm_class.replace(' ', '-').split('.', 1) + + m = Matcher(query.string) + if not query.string or m.match(win_instance + ' ' + win_class + ' ' + win.wm_name): + query.add(StandardItem( + id="%s%s" % (md_name, win.wm_class), + iconUrls=["xdg:%s" % win_instance], + text="%s - Desktop %s" % (win_class.replace('-', ' '), win.desktop), + subtext=win.wm_name, + actions=[Action("switch", + "Switch Window", + lambda w=win: runDetachedProcess(["wmctrl", '-i', '-a', w.wid])), + Action("move", + "Move window to this desktop", + lambda w=win: runDetachedProcess(["wmctrl", '-i', '-R', w.wid])), + Action("close", + "Close the window gracefully.", + lambda w=win: runDetachedProcess(["wmctrl", '-c', w.wid]))] + )) + except subprocess.CalledProcessError as e: + warning(f"Error executing wmctrl: {str(e)}") + + +def parseWindow(line): + win_id, desktop, rest = line.decode().split(None, 2) + win_class, rest = rest.split(' ', 1) + host, title = rest.strip().split(None, 1) + + return [win_id, desktop, win_class, host, title] From 53c4bdda1c4edcef226159deef4279739414fda0 Mon Sep 17 00:00:00 2001 From: mqus <8398165+mqus@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:40:19 +0100 Subject: [PATCH 348/355] [jetbrains_projects] Add pycharm-professional to binary list --- jetbrains_projects/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index fc4ae84d..06229396 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -33,7 +33,7 @@ from albert import * md_iid = "3.0" -md_version = "4.0" +md_version = "4.1" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "MIT" @@ -187,7 +187,7 @@ def __init__(self): name="PyCharm", icon=plugin_dir / "icons" / "pycharm.svg", config_dir_prefix="JetBrains/PyCharm", - binaries=["charm", "pycharm", "pycharm-eap"]), + binaries=["charm", "pycharm", "pycharm-eap", "pycharm-professional"]), Editor( name="Rider", icon=plugin_dir / "icons" / "rider.svg", From 79969a6087322a4944be266c4e738e81d725a1e3 Mon Sep 17 00:00:00 2001 From: MagneFire Date: Sat, 21 Jun 2025 23:11:56 +0200 Subject: [PATCH 349/355] [bitwarden] Fix freeze when triggering bitwarden (#221) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A freeze can be observed when triggering the bitwarden plugin. This seems to occur the second time `query.add` is called. To fix this issue the same logic as the `kill` plugin is used: Add all items to a local array before finally adding this using `query.add` This fixes https://github.com/albertlauncher/python/issues/215 Signed-off-by: Darrel Griët --- bitwarden/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bitwarden/__init__.py b/bitwarden/__init__.py index 3c8bf20e..87afe63a 100644 --- a/bitwarden/__init__.py +++ b/bitwarden/__init__.py @@ -68,8 +68,9 @@ def configWidget(self): ] def handleTriggerQuery(self, query): + results = [] if query.string.strip().lower() == "sync": - query.add( + results.append( StandardItem( id="sync", text="Sync Bitwarden Vault", @@ -85,7 +86,7 @@ def handleTriggerQuery(self, query): ) for p in self._filter_items(query): - query.add( + results.append( StandardItem( id=p["id"], text=p["path"], @@ -118,6 +119,8 @@ def handleTriggerQuery(self, query): ) ) + query.add(results) + def _get_items(self): not_first_time = self._cached_items is not None From a57b6e6ec6c585c3c41e866c1e634b68a104bf58 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 30 Jun 2025 15:27:52 +0200 Subject: [PATCH 350/355] [translators] Improve description --- translators/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translators/__init__.py b/translators/__init__.py index 862f427f..45541e8b 100644 --- a/translators/__init__.py +++ b/translators/__init__.py @@ -13,9 +13,9 @@ import translators as ts md_iid = "3.0" -md_version = "2.0" +md_version = "2.1" md_name = "Translator" -md_description = "Translate sentences using 'translators' package" +md_description = "Translate text using online translators" md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/main/translators" md_authors = "@manuelschneid3r" From cb6326caa62b092634e6cc686276bfd7dd62c850 Mon Sep 17 00:00:00 2001 From: Sharsie Date: Mon, 30 Jun 2025 15:56:44 +0200 Subject: [PATCH 351/355] [vscode_projects] Add plugin Provide a search of VSCode recent files and its Project Manager extension * [vscode_projects:1.1] Upgrade the interface version to 2.2 * [vscode_projects:1.2] Always add action to open workdir through VSCode If terminal command is specified, it becomes the default action while allowing the user to still open the workdir using default VSCode action without running through terminal * [vscode_projects:1.3] Use new Matcher introduced in interface version 2.3 * [vscode_projects:1.3] Remove unnecessary slashes in the icons url * [vscode_projects:1.3] Use cached iconUrls when building the standard item result * [vscode_projects:1.4] Normalize paths. Resolve symlinks to make sure only unique results are returned * [vscode_projects:1.5] Update to interface version 2.4 * [vscode_projects:1.6] Provide project tags in the subtext * [vscode_projects:1.6] Update plugin to interface version 3 * [vscode_projects:1.7] Fix caching and action text * [vscode_projects:1.8] Drop string normalization in favor of native Matcher * [vscode_projects:1.9] Optimize adding items to query --- vscode_projects/__init__.py | 550 ++++++++++++++++++++++++++++++++++++ vscode_projects/icon.svg | 41 +++ 2 files changed, 591 insertions(+) create mode 100644 vscode_projects/__init__.py create mode 100644 vscode_projects/icon.svg diff --git a/vscode_projects/__init__.py b/vscode_projects/__init__.py new file mode 100644 index 00000000..9f8690b6 --- /dev/null +++ b/vscode_projects/__init__.py @@ -0,0 +1,550 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2024 Sharsie + +import os +import json +from pathlib import Path +from dataclasses import dataclass +from albert import * + +md_iid = "3.0" +md_version = "1.9" +md_name = "VSCode projects" +md_description = "Open VSCode projects" +md_url = "https://github.com/albertlauncher/python/tree/master/vscode_projects" +md_license = "MIT" +md_bin_dependencies = ["code"] +md_authors = ["@Sharsie"] + +@dataclass +class Project: + displayName: str + name: str + path: str + tags: list[str] + + +@dataclass +class SearchResult: + project: Project + # priority is used to sort returned results + priority: int + # sortIndex is a decision maker when two search results have same priority + sortIndex: int + + +@dataclass +class CachedConfig: + projects: list[Project] + mTime: float + + +class Plugin(PluginInstance, TriggerQueryHandler): + # Possible locations for Code configuration + _configStoragePaths = [ + os.path.join(os.environ["HOME"], ".config/Code/storage.json"), + os.path.join(os.environ["HOME"], + ".config/Code/User/globalStorage/storage.json"), + ] + + # Possible locations for Project Manager extension configuration + _configProjectManagerPaths = [ + os.path.join( + os.environ["HOME"], ".config/Code/User/globalStorage/alefragnani.project-manager/projects.json") + ] + + # Indicates whether results from the Recent list in VSCode should be searched + _recentEnabled = True + + # Indicates whether projects from Project Manager extension should be searched + _projectManagerEnabled = False + + # Defines sorting priorities for results + _sortPriority = { + "PMName": 1, + "PMPath": 5, + "PMTag": 10, + "Recent": 15 + } + + # Holds cached data from the json configurations + _configCache: dict[str, CachedConfig] = {} + + # Overrides the command to open projects + _terminalCommand = "" + + # Setting indicating whether results from the Recent list in VSCode should be searched + @property + def recentEnabled(self): + return self._recentEnabled + + @recentEnabled.setter + def recentEnabled(self, value): + self._recentEnabled = value + self.writeConfig("recentEnabled", value) + + # Setting indicating whether projects in Project Manager extension should be searched + @property + def projectManagerEnabled(self): + return self._projectManagerEnabled + + @projectManagerEnabled.setter + def projectManagerEnabled(self, value): + self._projectManagerEnabled = value + self.writeConfig("projectManagerEnabled", value) + + found = False + for p in self._configProjectManagerPaths: + if os.path.exists(p): + found = True + break + + if found == False: + warning( + "Project Manager search was enabled, but configuration file was not found") + notif = Notification( + title=f"{self.name}", + text=f"Configuration file was not found for the Project Manager extension. Please make sure the extension is installed." + ) + notif.send() + + # Priority settings for project manager results using name search + @property + def priorityPMName(self): + return self._sortPriority["PMName"] + + @priorityPMName.setter + def priorityPMName(self, value): + self._sortPriority["PMName"] = value + self.writeConfig("priorityPMName", value) + + # Priority settings for project manager results using path search + @property + def priorityPMPath(self): + return self._sortPriority["PMPath"] + + @priorityPMPath.setter + def priorityPMPath(self, value): + self._sortPriority["PMPath"] = value + self.writeConfig("priorityPMPath", value) + + # Priority settings for project manager results using tag search + @property + def priorityPMTag(self): + return self._sortPriority["PMTag"] + + @priorityPMTag.setter + def priorityPMTag(self, value): + self._sortPriority["PMTag"] = value + self.writeConfig("priorityPMTag", value) + + # Priority settings for recently opened files + @property + def priorityRecent(self): + return self._sortPriority["Recent"] + + @priorityRecent.setter + def priorityRecent(self, value): + self._sortPriority["Recent"] = value + self.writeConfig("priorityRecent", value) + + # Setting for custom command when opening resulted items + @property + def terminalCommand(self): + return self._terminalCommand + + @terminalCommand.setter + def terminalCommand(self, value): + self._terminalCommand = value + self.writeConfig("terminalCommand", value) + + def defaultTrigger(self): + return "code " + + def synopsis(self, query): + return "project name or path" + + def __init__(self): + self.iconUrls = [f"file:{Path(__file__).parent}/icon.svg"] + + PluginInstance.__init__(self) + + TriggerQueryHandler.__init__(self) + + configFound = False + + for p in self._configStoragePaths: + if os.path.exists(p): + configFound = True + break + + if not configFound: + warning("Could not find any VSCode configuration directory") + + self._initConfiguration() + + def configWidget(self): + return [ + { + "type": "label", + "text": """Recent files are sorted in order found in the VSCode configuration. +Sort order with Project Manager can be adjusted, lower number = higher priority = displays first. +With all priorities equal, PM results will take precedence over recents.""" + }, + { + "type": "label", + "text": """ +PM extension: https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager +""" + }, + + { + "type": "checkbox", + "property": "recentEnabled", + "label": "Search in Recent files" + }, + { + "type": "checkbox", + "property": "projectManagerEnabled", + "label": "Search in Project Manager extension" + }, + { + "type": "spinbox", + "property": "priorityPMName", + "label": "Priority: Project Manager entries matched by name", + "widget_properties": { + "minimum": 1, + "maximum": 99, + }, + }, + { + "type": "spinbox", + "property": "priorityPMPath", + "label": "Priority: Project Manager entries matched by path", + "widget_properties": { + "minimum": 1, + "maximum": 99, + }, + }, + { + "type": "spinbox", + "property": "priorityPMTag", + "label": "Priority: Project Manager entries matched by tag", + "widget_properties": { + "minimum": 1, + "maximum": 99, + }, + }, + { + "type": "spinbox", + "property": "priorityRecent", + "label": "Priority: Recent entries", + "widget_properties": { + "minimum": 1, + "maximum": 99, + }, + }, + { + "type": "label", + "text": """ +The way VSCode is opened can be overriden through terminal command. +Terminal will enter the working directory of the project upon selection, execute the command and then close itself. + +Usecase with direnv - To load direnv environment before opening VSCode, enter the following custom command: direnv exec . code . + +Usecase with single VSCode instance - To reuse the VSCode window instead of opening a new one, enter the following custom command: code -r .""" + }, + { + "type": "lineedit", + "property": "terminalCommand", + "label": "Run custom command in the workdir of selected item" + }, + ] + + def _initConfiguration(self): + # Recent search + recentEnabled = self.readConfig('recentEnabled', bool) + if recentEnabled is None: + self._recentEnabled = True + self.writeConfig("recentEnabled", True) + else: + self._recentEnabled = recentEnabled + + # Project Manager search + foundPM = False + for p in self._configProjectManagerPaths: + if os.path.exists(p): + foundPM = True + break + + projectManagerEnabled = self.readConfig('projectManagerEnabled', bool) + if projectManagerEnabled is None: + # If not configured, check if the project manager configuration file exists and if so, enable PM search + if foundPM: + self._projectManagerEnabled = True + self.writeConfig("projectManagerEnabled", True) + else: + self._projectManagerEnabled = False + else: + self._projectManagerEnabled = projectManagerEnabled + + # Priority settings + for p in self._sortPriority: + prio = self.readConfig(f"priority{p}", int) + if prio is None: + self.writeConfig(f"priority{p}", self._sortPriority[p]) + else: + self._sortPriority[p] = prio + + # Terminal command setting + terminalCommand = self.readConfig('terminalCommand', str) + if terminalCommand is not None: + self._terminalCommand = terminalCommand + + def handleTriggerQuery(self, query): + if not query.isValid: + return + + if query.string == "": + return + + matcher = Matcher(query.string) + + results: dict[str, SearchResult] = {} + + if self.recentEnabled: + results = self._searchInRecentFiles(matcher, results) + + if self.projectManagerEnabled: + results = self._searchInProjectManager(matcher, results) + + sortedItems = sorted(results.values(), key=lambda item: "%s_%s_%s" % ( + '{:03d}'.format(item.priority), '{:03d}'.format(item.sortIndex), item.project.name), reverse=False) + + items: list[StandardItem] = [] + for i in sortedItems: + items.append(self._createItem(i.project, query)) + + query.add(items) + + # Creates an item for the query based on the project and plugin settings + def _createItem(self, project: Project, query: Query) -> StandardItem: + actions: list[Action] = [] + + if self.terminalCommand != "": + actions.append( + Action( + id="open-terminal", + text=f"Run terminal command in project's workdir: {self.terminalCommand}", + callable=lambda: runTerminal(f"cd {project.path} && {self.terminalCommand}") + ) + ) + + actions.append( + Action( + id="open-code", + text="Open with VSCode", + callable=lambda: runDetachedProcess( + ["code", project.path]), + ) + ) + + subtext = "" + + if len(project.tags) > 0: + subtext = "<" + ",".join(project.tags) + "> " + + return StandardItem( + id=project.path, + text=project.displayName, + subtext=f"{subtext}{project.path}", + iconUrls=self.iconUrls, + inputActionText=f"{query.trigger}{project.displayName}", + actions=actions, + ) + + def _searchInRecentFiles(self, matcher: Matcher, results: dict[str, SearchResult]) -> dict[str, SearchResult]: + sortIndex = 1 + + for path in self._configStoragePaths: + c = self._getStorageConfig(path) + for proj in c.projects: + # Resolve sym links to get unique results + resolvedPath = str(Path(proj.path).resolve()) + if matcher.match(proj.name) or matcher.match(proj.path) or matcher.match(resolvedPath): + results[resolvedPath] = self._getHigherPriorityResult( + SearchResult( + project=proj, + priority=self.priorityRecent, + sortIndex=sortIndex + ), + results.get(resolvedPath), + ) + + if results.get(resolvedPath) is not None: + sortIndex += 1 + + return results + + def _searchInProjectManager(self, matcher: Matcher, results: dict[str, SearchResult]) -> dict[str, SearchResult]: + for path in self._configProjectManagerPaths: + c = self._getProjectManagerConfig(path) + for proj in c.projects: + # Resolve sym links to get unique results + resolvedPath = str(Path(proj.path).resolve()) + if matcher.match(proj.name): + results[resolvedPath] = self._getHigherPriorityResult( + SearchResult( + project=proj, + priority=self.priorityPMName, + sortIndex=0 if matcher.match(proj.name).isExactMatch() else 1 + ), + results.get(resolvedPath), + ) + + if matcher.match(proj.path) or matcher.match(resolvedPath): + results[resolvedPath] = self._getHigherPriorityResult( + SearchResult( + project=proj, + priority=self.priorityPMPath, + sortIndex=1 + ), + results.get(resolvedPath), + ) + + for tag in proj.tags: + if matcher.match(tag): + results[resolvedPath] = self._getHigherPriorityResult( + SearchResult( + project=proj, + priority=self.priorityPMTag, + sortIndex=1 + ), + results.get(resolvedPath), + ) + break + + return results + + # Compares the search results to return the one with higher priority + # For nitpickers: higher priorty = lower number + def _getHigherPriorityResult(self, current: SearchResult, prev: SearchResult | None) -> SearchResult: + if prev is None or current.priority < prev.priority or (current.priority == prev.priority and current.sortIndex < prev.sortIndex): + return current + + return prev + + def _getStorageConfig(self, path: str) -> CachedConfig: + c: CachedConfig = self._configCache.get(path, CachedConfig([], 0)) + + if not os.path.exists(path): + return c + + mTime = os.stat(path).st_mtime + + if mTime == c.mTime: + return c + + c.mTime = mTime + + with open(path) as configFile: + # Load the storage json + storageConfig = json.loads(configFile.read()) + + if ( + "lastKnownMenubarData" in storageConfig + and "menus" in storageConfig["lastKnownMenubarData"] + and "File" in storageConfig["lastKnownMenubarData"]["menus"] + and "items" in storageConfig["lastKnownMenubarData"]["menus"]["File"] + ): + # These are all the menu items in File dropdown + for menuItem in storageConfig["lastKnownMenubarData"]["menus"]["File"]["items"]: + # Cannot safely detect proper menu item, as menu item IDs change over time + # Instead we will search all submenus and check for IDs inside the submenu items + if ( + not "id" in menuItem + or not "submenu" in menuItem + or not "items" in menuItem["submenu"] + ): + continue + + for submenuItem in menuItem["submenu"]["items"]: + # Check of submenu item with id "openRecentFolder" and make sure it contains necessarry keys + if ( + not "id" in submenuItem + or submenuItem['id'] != "openRecentFolder" + or not "enabled" in submenuItem + or submenuItem["enabled"] != True + or not "label" in submenuItem + or not "uri" in submenuItem + or not "path" in submenuItem["uri"] + ): + continue + + # Get the full path to the project + recentPath = submenuItem["uri"]["path"] + if not os.path.exists(recentPath): + continue + + displayName = recentPath.split("/")[-1] + + # Inject the project + c.projects.append(Project( + displayName=displayName, + name=displayName, + path=recentPath, + tags=[], + )) + + self._configCache[path] = c + + return c + + def _getProjectManagerConfig(self, path: str) -> CachedConfig: + c = self._configCache.get(path, CachedConfig([], 0)) + + if not os.path.exists(path): + return c + + mTime = os.stat(path).st_mtime + + if mTime == c.mTime: + return c + + c.mTime = mTime + + with open(path) as configFile: + configuredProjects = json.loads(configFile.read()) + + for p in configuredProjects: + # Make sure we have necessarry keys + if ( + not "rootPath" in p + or not "name" in p + or not "enabled" in p + or p["enabled"] != True + ): + continue + + # Grab the path to the project + rootPath = p["rootPath"] + if os.path.exists(rootPath) == False: + continue + + project = Project( + displayName=p["name"], + name=p["name"], + path=rootPath, + tags=[], + ) + + # Search against the query string + if "tags" in p: + for tag in p["tags"]: + project.tags.append(tag) + + c.projects.append(project) + + self._configCache[path] = c + + return c diff --git a/vscode_projects/icon.svg b/vscode_projects/icon.svg new file mode 100644 index 00000000..c453e633 --- /dev/null +++ b/vscode_projects/icon.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ab649e7159285baa307802ee0dba53812502f807 Mon Sep 17 00:00:00 2001 From: Sharsie Date: Mon, 7 Jul 2025 23:15:47 +0200 Subject: [PATCH 352/355] [vscode_projects:1.10] Fixes duplicated trigger in query auto completion (#224) --- vscode_projects/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vscode_projects/__init__.py b/vscode_projects/__init__.py index 9f8690b6..7ed263c9 100644 --- a/vscode_projects/__init__.py +++ b/vscode_projects/__init__.py @@ -8,7 +8,7 @@ from albert import * md_iid = "3.0" -md_version = "1.9" +md_version = "1.10" md_name = "VSCode projects" md_description = "Open VSCode projects" md_url = "https://github.com/albertlauncher/python/tree/master/vscode_projects" @@ -103,7 +103,7 @@ def projectManagerEnabled(self, value): warning( "Project Manager search was enabled, but configuration file was not found") notif = Notification( - title=f"{self.name}", + title=self.name, text=f"Configuration file was not found for the Project Manager extension. Please make sure the extension is installed." ) notif.send() @@ -359,7 +359,7 @@ def _createItem(self, project: Project, query: Query) -> StandardItem: text=project.displayName, subtext=f"{subtext}{project.path}", iconUrls=self.iconUrls, - inputActionText=f"{query.trigger}{project.displayName}", + inputActionText=project.displayName, actions=actions, ) From 7b0c53260efb6c881736c1c33268bc630102ef39 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 17 Jul 2025 12:33:43 +0200 Subject: [PATCH 353/355] [syncthing] v3 - Drop PyPi dependendencies `syncthing` is broken for years. `syncthing2` simply fixes the silly dependency issue but is still heavily outdated. - Add pause/resume folder action (was not available in the PyPi pkgs) - Show exceptions as item in trigger query handler - Visualize paused devices/folders with desaturated icons --- syncthing/__init__.py | 228 ++++++++++++++++++------------- syncthing/syncthing.svg | 26 ---- syncthing/syncthing_active.svg | 1 + syncthing/syncthing_inactive.svg | 1 + 4 files changed, 137 insertions(+), 119 deletions(-) delete mode 100644 syncthing/syncthing.svg create mode 100644 syncthing/syncthing_active.svg create mode 100644 syncthing/syncthing_inactive.svg diff --git a/syncthing/__init__.py b/syncthing/__init__.py index ce4cb3e7..6fde0df1 100644 --- a/syncthing/__init__.py +++ b/syncthing/__init__.py @@ -1,59 +1,100 @@ # -*- coding: utf-8 -*- # Copyright (c) 2024 Manuel Schneider -""" -Quickly pause/resume/open/scan shares and devices. -""" - +import json +import urllib.error +import urllib.request from pathlib import Path from albert import * -from syncthing import Syncthing md_iid = "3.0" -md_version = "2.0" +md_version = "3.0" md_name = "Syncthing" -md_description = "Trigger basic syncthing actions." +md_description = "Control the local Syncthing instance." md_license = "MIT" md_url = "https://github.com/albertlauncher/python/tree/main/syncthing" md_authors = "@manuelschneid3r" -md_lib_dependencies = "syncthing2" + + +# https://docs.syncthing.net/dev/rest.html +class Syncthing: + def __init__(self, api_key, base_url="http://localhost:8384"): + self.api_key = api_key + self.base_url = base_url + + def _request(self, method, endpoint, data=None) -> dict: + url = f"{self.base_url}{endpoint}" + headers = { + "X-API-Key": self.api_key, + "Content-Type": "application/json" + } + body = json.dumps(data).encode("utf-8") if data else None + req = urllib.request.Request(url, data=body, headers=headers, method=method) + + try: + with urllib.request.urlopen(req) as resp: + if not (200 <= resp.status < 300): + raise Exception(f"Unexpected status {resp.status}") + content = resp.read().decode() + return json.loads(content) if content else {} + except urllib.error.HTTPError as e: + raise Exception(f"HTTP {e.code}: {e.read().decode()}") + + def _get(self, endpoint): + return self._request("GET", endpoint) + + def _post(self, endpoint, data=None): + return self._request("POST", endpoint, data) + + def _patch(self, endpoint, data=None): + return self._request("PATCH", endpoint, data) + + def config(self): + return self._get('/rest/config') + + def resumeDevice(self, device_id:str): + return self._patch(f'/rest/config/devices/{device_id}', {'paused': False}) + + def pauseDevice(self, device_id:str): + return self._patch(f'/rest/config/devices/{device_id}', {'paused': True}) + + def resumeFolder(self, folder_id:str): + return self._patch(f'/rest/config/folders/{folder_id}', {'paused': False}) + + def pauseFolder(self, folder_id:str): + return self._patch(f'/rest/config/folders/{folder_id}', {'paused': True}) + + def scanFolder(self, folder_id:str): + return self._post(f'/rest/db/scan?folder={folder_id}') class Plugin(PluginInstance, GlobalQueryHandler): config_key = 'syncthing_api_key' + icon_urls_active = [f"file:{Path(__file__).parent}/syncthing_active.svg"] + icon_urls_inactive = [f"file:{Path(__file__).parent}/syncthing_inactive.svg"] def __init__(self): PluginInstance.__init__(self) GlobalQueryHandler.__init__(self) - - self.iconUrls = ["xdg:syncthing", f"file:{Path(__file__).parent}/syncthing.svg"] - self._api_key = self.readConfig(self.config_key, str) - if self._api_key: - self.st = Syncthing(self._api_key) + self.st = Syncthing(self.readConfig(self.config_key, str) or '') def defaultTrigger(self): return 'st ' @property def api_key(self) -> str: - return self._api_key + return self.st.api_key @api_key.setter def api_key(self, value: str): - if self._api_key != value: - self._api_key = value + if self.st.api_key != value: + self.st.api_key = value self.writeConfig(self.config_key, value) - self.st = Syncthing(self._api_key) - def configWidget(self): return [ - { - 'type': 'label', - 'text': __doc__.strip(), - }, { 'type': 'lineedit', 'property': 'api_key', @@ -62,79 +103,80 @@ def configWidget(self): } ] + def handleTriggerQuery(self, query): + try: + super().handleTriggerQuery(query) + except Exception as e: + query.add(StandardItem(id="err", text="Error", subtext=str(e), iconUrls=self.icon_urls_active)) + def handleGlobalQuery(self, query): - results = [] + config = self.st.config() + + devices = dict() + for d in config['devices']: + if not d['name']: + d['name'] = d['deviceID'] + d['_shared_folders'] = {} + devices[d['deviceID']] = d - if self.st: - - config = self.st.system.config() - - devices = dict() - for d in config['devices']: - if not d['name']: - d['name'] = d['deviceID'] - d['_shared_folders'] = {} - devices[d['deviceID']] = d - - folders = dict() - for f in config['folders']: - if not f['label']: - f['label'] = f['id'] - for d in f['devices']: - devices[d['deviceID']]['_shared_folders'][f['id']] = f - folders[f['id']] = f - - matcher = Matcher(query.string) - - # create device items - for device_id, d in devices.items(): - device_name = d['name'] - - if match := matcher.match(device_name): - device_folders = ", ".join([f['label'] for f in d['_shared_folders'].values()]) - - actions = [] - if d['paused']: - actions.append( - Action("resume", "Resume synchronization", - lambda did=device_id: self.st.system.resume(did)) - ) - else: - actions.append( - Action("pause", "Pause synchronization", - lambda did=device_id: self.st.system.pause(did)) - ) - - item = StandardItem( - id=device_id, - text=f"{device_name}", - subtext=f"{'Paused ' if d['paused'] else ''}Syncthing device. " - f"Shared: {device_folders if device_folders else 'Nothing'}.", - iconUrls=self.iconUrls, - actions=actions - ) - - results.append(RankItem(item, match)) - - # create folder items - for folder_id, f in folders.items(): - folder_name = f['label'] - if match := matcher.match(folder_name): - folders_devices = ", ".join([devices[d['deviceID']]['name'] for d in f['devices']]) - item = StandardItem( - id=folder_id, - text=folder_name, - subtext=f"Syncthing folder {f['path']}. " - f"Shared with {folders_devices if folders_devices else 'nobody'}.", - iconUrls=self.iconUrls, - actions=[ - Action("scan", "Scan the folder", - lambda fid=folder_id: self.st.database.scan(fid)), - Action("open", "Open this folder in file browser", - lambda p=f['path']: openFile(p)) - ] - ) - results.append(RankItem(item, match)) + folders = dict() + for f in config['folders']: + if not f['label']: + f['label'] = f['id'] + for d in f['devices']: + devices[d['deviceID']]['_shared_folders'][f['id']] = f + folders[f['id']] = f + + results = [] + matcher = Matcher(query.string) + + # create device items + for device_id, d in devices.items(): + device_name = d['name'] + + if match := matcher.match(device_name): + device_folders = ", ".join([f['label'] for f in d['_shared_folders'].values()]) + + actions = [] + if d['paused']: + actions.append(Action("resume", "Resume", lambda did=device_id: self.st.resumeDevice(did))) + else: + actions.append(Action("pause", "Pause", lambda did=device_id: self.st.pauseDevice(did))) + + item = StandardItem( + id=device_id, + text=f"{device_name}", + subtext=f"{'PAUSED · ' if d['paused'] else ''}Device · " + f"Shared: {device_folders if device_folders else 'Nothing'}.", + iconUrls=self.icon_urls_inactive if d['paused'] else self.icon_urls_active, + actions=actions + ) + + results.append(RankItem(item, match)) + + # create folder items + for folder_id, f in folders.items(): + folder_name = f['label'] + if match := matcher.match(folder_name): + folders_devices = ", ".join([devices[d['deviceID']]['name'] for d in f['devices']]) + + actions = [] + if f['paused']: + actions.append(Action("resume", "Resume", lambda fid=folder_id: self.st.resumeFolder(fid))) + else: + actions.append(Action("pause", "Pause", lambda fid=folder_id: self.st.pauseFolder(fid))) + actions.append(Action("open", "Open", lambda p=f['path']: openFile(p))) + actions.append(Action("scan", "Scan", lambda fid=folder_id: self.st.scanFolder(fid))) + + item = StandardItem( + id=folder_id, + text=folder_name, + subtext=f"{'PAUSED · ' if f['paused'] else ''}Folder · {f['path']} · " + f"Shared with {folders_devices if folders_devices else 'nobody'}.", + iconUrls=self.icon_urls_inactive if f['paused'] else self.icon_urls_active, + actions=actions + ) + results.append(RankItem(item, match)) return results diff --git a/syncthing/syncthing.svg b/syncthing/syncthing.svg deleted file mode 100644 index ce92210f..00000000 --- a/syncthing/syncthing.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/syncthing/syncthing_active.svg b/syncthing/syncthing_active.svg new file mode 100644 index 00000000..b56b7cbc --- /dev/null +++ b/syncthing/syncthing_active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/syncthing/syncthing_inactive.svg b/syncthing/syncthing_inactive.svg new file mode 100644 index 00000000..247b4d43 --- /dev/null +++ b/syncthing/syncthing_inactive.svg @@ -0,0 +1 @@ + \ No newline at end of file From f10c7895f665ed389203127c99e94aa3cf9065bf Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 25 Jul 2025 14:03:09 +0200 Subject: [PATCH 354/355] Split modules --- README.md | 12 ++--- history_to_submodules.sh | 106 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 9 deletions(-) create mode 100755 history_to_submodules.sh diff --git a/README.md b/README.md index b95c05b6..3d0aeaf3 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,5 @@ -## Official Albert Python plugin repository +# ⚠️ ARCHIVED ⚠️ -These plugins are shipped with the app. +The plugins in this repository have been moved to dedicated repositories using `history_to_submodules.sh`. -Visit the website to learn [how to write plugins](https://albertlauncher.github.io/gettingstarted/extension/). - -Credits go to our contributors: - - - - +See https://github.com/orgs/albertlauncher/repositories. diff --git a/history_to_submodules.sh b/history_to_submodules.sh new file mode 100755 index 00000000..054cc79c --- /dev/null +++ b/history_to_submodules.sh @@ -0,0 +1,106 @@ +#! /usr/bin/env bash + +#set -x +set -e + +# Find history dirs +# git log --pretty=format: --name-only | grep -E '^(.archive/)?[^/]+' -o | sort -u | uniq + +git clone --bare git@github.com:albertlauncher/python.git .bare || true + +function filter ( + + if [[ $# -lt 2 ]]; then + echo "Error: At least two arguments required." + return 1 + fi + + local repo_name="$(echo $1 | tr '_' '-')" + local filter_path="$2" + shift 2 + + declare -a additional_filter_paths + if [[ $# -gt 0 ]]; then + additional_filter_paths=$(printf -- "--path %s " "$@") + fi + + echo "ℹ️" $repo_name $filter_path $additional_filter_paths + + git clone .bare $repo_name + cd $repo_name + git filter-repo --subdirectory-filter ${filter_path} ${additional_filter_paths[@]} + + gh repo create "albertlauncher/albert-plugin-python-$repo_name" --public --disable-wiki + git remote add origin "git@github.com:albertlauncher/albert-plugin-python-$repo_name.git" + git push -f --set-upstream origin main + open "https://github.com/albertlauncher/albert-plugin-python-$repo_name" + + cd .. +) + + +filter arch_wiki arch_wiki .archive/arch_wiki ArchWiki +filter atom_projects atom_projects atom_projects.py .archive/atom_projects AtomProjects.py +filter aur aur .archive/aur AUR +filter base_converter base_converter base_converter.py .archive/base_converter BaseConverter.py +filter binance binance .archive/binance Binance +filter bitfinex bitfinex .archive/bitfinex Bitfinex +filter bitwarden bitwarden bitwarden.py .archive/bitwarden +filter coingecko coingecko +filter coinmarketcap coinmarketcap .archive/coinmarketcap CoinMarketCap +filter color color +filter copyq copyq copyq.py .archive/copyq CopyQ.py +filter currency_converter currency_converter currency_converter.py .archive/currency_converter Currency.py +filter dango_emoji dango_emoji .archive/dango_emoji dangoemoji +filter dango_kao dango_kao .archive/dango_kao dangokao +filter datetime datetime datetime.py .archive/datetime DateTime.py epoch Epoch.py +filter dice_roll dice_roll .archive/dice_roll +filter docker docker .archive/docker +filter duckduckgo duckduckgo +filter emoji emoji EmojiPicker unicode_emoji .archive/unicode_emoji +filter find find find .archive/find +filter fortune fortune fortune.py .archive/fortune Fortune.py +filter gnome_dictionary gnome_dictionary gnome_dictionary.py .archive/gnome_dictionary GnomeDictionary.py +filter gnote gnote gnote.py .archive/gnote Gnote.py +filter goldendict goldendict goldendict.py .archive/goldendict GoldenDict.py +filter google_translate google_translate google_translate.py .archive/google_translate GoogleTranslate.py +filter googletrans googletrans .archive/googletrans +filter inhibit_sleep inhibit_sleep .archive/inhibit_sleep +filter ip ip ip.py .archive/ip Ip.py +filter jetbrains_projects jetbrains_projects jetbrains-projects.py .archive/jetbrains_projects JetbrainsProjects +filter kill kill kill.py .archive/kill Kill.py +filter locate locate locate.py .archive/locate Locate.py +filter lpass lpass .archive/lpass +filter mathematica_eval mathematica_eval mathematica_eval.py .archive/mathematica_eval +filter multi_google_translate multi_google_translate multi_google_translate.py .archive/multi_google_translate MultiGoogleTranslate.py +filter node_eval node_eval .archive/node_eval +filter npm npm .archive/npm Npm +filter packagist packagist .archive/packagist Packagist +filter pacman pacman pacman.py .archive/pacman Pacman.py +filter pass pass pass.py .archive/pass Pass.py +filter php_eval php_eval .archive/php_eval +filter pidgin pidgin pidgin.py .archive/pidgin Pidgin.py +filter pomodoro pomodoro .archive/pomodoro Pomodoro +filter python_eval python_eval python Python +filter rand rand .archive/rand +filter scrot scrot scrot.py Scrot.py .archive/scrot +filter syncthing syncthing +filter tex_to_unicode tex_to_unicode tex_to_unicode.py .archive/tex_to_unicode +filter texdoc texdoc .archive/texdoc +filter timer timer Timer .archive/timer +filter tomboy tomboy tomboy.py Tomboy.py .archive/tomboy +filter translators translators +filter trash trash trash.py Trash.py .archive/trash +filter unit_converter unit_converter .archive/unit_converter +filter units units units.py Units.py .archive/units +filter virtualbox virtualbox virtualbox.py VirtualBox.py .archive/virtualbox +filter vpn vpn vpn.py .archive/vpn +filter vscode_projects vscode_projects +filter wikipedia wikipedia Wikipedia Wikipedia.py +filter x_window_switcher x_window_switcher window_switcher window_switcher.py WindowSwitcher.py SwitchApp.py .archive/window_switcher +filter xkcd xkcd .archive/xkcd +filter youtube youtube youtube.py Youtube.py .archive/youtube +filter zeal zeal zeal.py Zeal.py .archive/zeal + + + From 7a1612cf8caaad998fe0aa9af617c2ef645d21de Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 7 Aug 2025 11:15:34 +0200 Subject: [PATCH 355/355] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 3d0aeaf3..95b590ae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ # ⚠️ ARCHIVED ⚠️ -The plugins in this repository have been moved to dedicated repositories using `history_to_submodules.sh`. - -See https://github.com/orgs/albertlauncher/repositories. +The plugins in this repository have been moved to [dedicated repositories](https://github.com/orgs/albertlauncher/repositories) using `history_to_submodules.sh`.

W|LvSftKSgmTr24VB=O`21wI;u5%XaLocOnUtW+fnmuLUgMgrHO--04 zNKd5ZtlsZgngyZdHKwKacG2&hkC*Llb8K98+38k~e2@GO?Q7tdFT@2Z(|J?@BJHQ~ zN1rwK@RzMbiaJh}I&Sj()8+1$#6X!zCD@sTzB&NfFP~}ngUDd#mZOjfSl$p~(N%K3 zagS<$PMPj;xF7u4YW>%+ps5S(EAM=+*X-0@6Sa4iI@`KeFYo%DEg4SZPFfgdkAh;X z>y+C@ge7TptH+%Pfi}d<41?8C!=D{Grm&Tp+xnM_UsV2n zs)^q{u`7r0a70XXmYED8FgUxYbNw?W$ws41M2gbFpZMGyg8t>P@|? z3hMpn+dW2=4^kY*mS1)eKXSL_z}JVI5{MLt+Is|0tJu+X5z57iovI#&IY@oW#T8~& zoS)Ku5|?)L9~1DiMAv}@DnnOJ=${wiGk10Ge-4|WmlkIzHTcXNOdbVZ0%Q3^tk7Gb zZP?Ul7er>X@#xa0Q#G*N(GY^ChVOu05F9|4Ib(#-l%MZmWUul$a~AelNrfzcXVTKp zbaqE6pV{{5k`H362NntK?v^-}+chgYGR&>hD0L}7Syr-(LtT48ltccw?&TZAnzz+U z_1-RO#SY*R^b0&tLXz)&PL_b&{D*Js;U%+Rv833i7cH$a4%5NAkUoTHxE2_^6W+Ig|^WPu*(ozli~`k&aD?{c@EO*|Y7Mh`>USI!nuYcP5`Lt}-vX8(0 zq^$9HZ4$GA+mZ?ONx%*@_;kJ^K@(lG`2q_7>oJc`8|=G+wx%e#{_b2~?Dgw@ZZziOPr$mX}`0=syx9tEbmhC)k!O1Sxpy=UqqE0+Jp#rdx-N?+&X9*75|`Fo!eKAGSv;j!A~-oC4_o0JBc9 zPrRto0e}9riLZ$MeqlyiKX9p=TwYGIYx9Xr_E$LDvbEj|!EL`)bV@hUA%@EWJDS+5 zU%l(oE;5YrM4~=IIg&6@o0g6ak{HN+hpHC3^!<=G4Dkc1Fzxx8eoa;0jEw!a>#-%M zQJuh~XIL6QN)vG|yfA$6-ps6lnKulf z;4?V@(GK}!eO<}eS-9=Rk_YfAD@}Ombt3CE`!*Mg6j(uv)N;SAp>EVM z*t$nnl>RJhRrYziH*#2qRO8|v+82=>4ZBTP)bUeX5?WFx@4ZHk%s>%xpiQhv%J|wdH-DtSAf%Wf z$5f+fFyB{^iVctZ*csZ+q^Ky~hD1llOKlDe{EZ*F=}s;G8-03uI&_Y_*d5I)Fv{rs z5On`(3n2r0-tp>M%fxLv9iO^egH$E z9UWW@-2$|e&mCp7Achepa7`ZGkH2`*hQwKI#^ z`xgC+FUxW3FAP?uF*x;3hPwFMLG&lBh|x+{FLLhE!}drGxoA1!PLTNJWJRlpfCxyb z_BlZZh!c`LuFc96o&TxPPcB$wK}_zwg4$pE>3z97VS`hBPi#8<<|?-2dF7L#oqH@$ zaRtiM$n*nWXRUWQxMG2GkW`2`!&Vl}sN@8SKGK5xnK z25m{fWc!s=E_WSKV3TKR#If>`b@wWTbf7f0Xpf1E)#z}!_xit93E+Orted)ktc@<_ zL|PL?Qrxh`L2>s&b^)P|EX73Tug>g72F+EFZuh&_xu@d9QNh;N=wEKy$xuL6;Bytu zGI#63F*bE5UJo<_`v}D!VO#;Xa}6mPdLBVd8~4)^L?Q!a8aKP#c36e2;XHjdebN&I zrJ7F*D^ka-Ajji;XRBpG7ZNzyA$O$4gTyt~yYYetCLtJXYtQbElsha!av^-gNXrY# zC?eFL?biLqK#(ctW#A zTk`@2p(R^87cLHa-OX+7k0On}Y_C|sD0U*YX6c>O9PautUs;~|%!-f$@kSqZoqCH# z(tsuldoV^yhehzIGWP;l~K zsI6P`lw*=Zl9_oT<^9UYnZ8fne0O&X5C2rCvbTef`J`W2nbN7zi+WCTaqq<1SRu$Y zyYoOGgGU>~8^5OTx)(aXm*@I+_0S1@0JW&jIyBVo416jXyk!-u1^ZZts?Cyu56Q@z ze;7GmpJuf8l9-|(WZr=N5)fFXV|qs&^D(-RS^oQpLo~2q|6cJOFeDK~7%E2*rTfW1 zRWMkwyjMw39-Br%5EU`CtFOuDcw{xsmO}Kp{J)RwIqZsvCm2<+aqw!i8a3Lu=sz&Z5!h5_GCK`f{a3&$GQR8=c4pKVacMD*)zIz;E82R4s<8O-(K7m)ypJ7}anzZWE_gEJbUQ9T! zgUXfA7j}>6VnQyxEzn>~=vMx@Hfg)Yhu7<;=;lYqIH#mYCRU{7=ow?$0450JdAo{$ zLn+y-i52qseoTR8wB<;u950jYrDREGnO3CUvmfcDuATdpTB>W@-}FbkP{mb=MY|^l z*(|Xj6zB>TYhX>m0hSx1nJtSglLcU*5M@vdSi1HtXiW@xxm=+}@j>=89R#HNS-l1!29PpT~glYu|xDScQJzyZi2!laBHv$r!qy4Ot<3 z1f0pEQMnG(Z|hsS*^( znmA`BKrVC)6Ce`{n8nH}r)xfeYA`c4%1_4={Ij{+S(jK&&d$Wv10Lhpxc~Bs|1s3`0ps^+dxFgjKBHfvE@r{Y!qz6ICa=|=qNj@ z1M3cW(RGwQV5%khO7^&MQ@P80>^qkH_MLn1NimEKZS$E2rYi1BLwzZ-Y{I<|hcw2p zCoXJPo~d<9qBt9jJEbfjeA}mwR5?4Sl*dx^>?W=RkZmyMoPz`09mR9G5}S zC=&T{v9jrTS?|chS1~aFReCE3qC^~JXRN@+g_7{Kcj>ZtY&!v6rb8&cOEGmO0ZEk+ zsXgKo@gA0<^B;55$8@}ck3t~LUc}pS;-%IusL-&F=}hoMP9p3atb?jWy=;yAR%bh0UYO9c}Ig3C8NE2 zAj?4kfplbomg_V-OYii$v32tUP!D27Ri^hjj?q+4%?hLFbZ(yWrNQRpUtyc5=nkA;pMeVeGZ`I(NvE`4kQ&fF#)W^Z)5XLfL07jo;~9X`xz;ZtPgfj{kNz{Bxbj#a>!D5 z^!=A`g?+qjQKr11{tp!KkD>%)ny{;zuOcLUC@NYXqoH&!SdOLCsLxJr#^uH^0fofM zwcqz<=B25x2>D7OdZnwEa9a7H=4+LS@?KQn(f-Pn21&sRv`HPWdWP* z6jAMuB3v3ke$-tX%7jhA`5YK;(`D#}+(KBjAusTp(55m&m3h14z+yOo#Hz6F$w%EI zZutYj$U!LlWOwRs(W)KR1s@7Ggw6ZaHu*0v+|;3b2|OOm7uD@y<4jeniud`UW`R8; z+GuP)t=xWQwb}p{yrxu8yqWSSFJy zv=>l2wSZ#9iB0fH*R}iLY6+psK}xM`)7NP&@6f9NT>cRXkCAfHsdz5b-=49!tPR`GF`yEM0f62wH^fnT-D zQ(x|CPz9b&eRX3gzlS{h7&*&mAP)~ztD=;WOkZei<|xrw`TZ;1`5C>8QEvfNYXrHm z?x&+gc=j@4foN&}{APh`V3^ezyb8(gg%f){4soHJmFr0RK5|@y7_jEy@@Q1sVk`HTHFN(O>wVv=Or&#dD&~w|d-#cCB z614_v8|H1Yjzvxcp)r5albiS?v{N9aHG$ z<5Gv$Wtgh^;c^QzxSa#`%%mtb3BE9|;ysbebVBzRt#?R!^PBTjyavyE>(gz&hH;iJ z2eN2@@SDFK;ot2qKXl}?t$NVu*5h}jEX2Z837vc!eH=k+9k04+ps`s5H0r=lf0ZFeGf+lIbVMuTlhN}_MX-`Jlej>Yd2zp)R8g#^I;DHxY^5i& z^}f>{*}=y!5OeyqjyS~_4SSME%`}=>fzbi=B4ANkW>aQ%gu44aKCIV;_G+?v&0O9{ z(MD)wijyUAIhp;vGesluLiD*A z9)FK{++_Wz*zjM>JpYC2%WS`(oQNn+H=$onKw0~;(pXF(;#fG;8$nv8D`MgVvr;)x+<~agM=?tJ6a)A z8mBSVvXNmR%AddM%Lfp>xXsk~e9hY~i;Z8{{nH>$&{-X!ubw-87*5Lvf#qG^(e zySbTNWCQdV=3EX+R7G|QHlrQCa#!nhI@=r_w^n@zKupn3?EBxr|Ln)mJ9)9;fkL>l z=GteC+-JJL*8>3@*EW0w=j7e`CNKB~Pa^{B*9&d11jP6qorW|sVw9_e?LJsh`6&h7 zVI4K${Ak|S-7RGP$C=q9C;1LUteE6|R7VA0pIeTg;-Yh^Z#-uAc8injbJQ z4s920rkX$mPsv|88is!7^mjl~{*$mJuDM9%a#QG-BhaNrb+ka7(2bvLC%W^wTu*t_RQ(TDPLUpW$VhSll|rY2U)V%m~fQ48<$1=dyl- z!hGV+)KR-mPGgKhJ8KrR1_Fa}Gh$i~arZd&Zm-ZKDqI-}V(yAxVuD^=qDU1NarE~; zFVT>HuV>)*&A=O%?erkiGw>59{2)|GYfFROLJoee1iYX(+6JMN|Hv51pJQ)2hVgq_?2) zE*poZOtoYRy|KQmLSVE;n9nwyfP$6;p8kiyoj)pYEYHl^`hkx3Ahn?H;Q9_W560twSTp;xifpDS<+ z13u?&u3Dy_RgUh?ZVI$VTqQU`;yv$)5V@QrK>(7Ao-{Y_UWjRY?eB32zu1zCI#VFI+{vdPS&eEO@QoKMa8wtS(X_}`W z(yz#BqFwP;ctW&V$M8kycbct7`Rrh&RCun5ns8#~lOZoqftohQ8QL~mtJmpFyonA>zI5h$;gf1KNTrsyT>_6w+4x$+3g;RI~fy#Lqjt|2#nW7wYgbYskM&mi1c&6NnniXqIB?=~}y4{o3!zS{Oo9 z49Zun?2%j9v@;wEHhQn;pt)CR_dq*m!9E<(X1LCAb`tV<;>m7ygrfZ&Up)KToEDoO z5Rg%&cJbiy>6mO0FJb)lKC)w>ISf9lv)<($DJW$XMQqn;pYDT1uq&elnacbQAeVNL1sa2db)adFVu)h(+>E@WX|^gmO3E?9j( zs&YJ#F6v~la_0NtYKX$HVUHr2Ei~dOPF`aW{_GKhif2(`bD;xkkl(mF&nTIP=epFW zk3TW3Z7k$lKv$i#)Ej(MQsk|p-{OBJHqajY;3U;hbux3v@S2n=JW=U3N(;Bpf^}+@ z0wdEb&0{{IyYa|?jI&I=zGp74$bXjs z_bYi9EG?%87q>&Hmnt%=0lz#xjOH|^$2ZA_;IV9fO>BhDYZgRHgV4u+6waHit^!7& zSLWBuPK!eZX1)|5IrxGA&K{waoPKzN)(buKzoqIgVP9F@8m#35(ZNDG;Q{SveW>xr zWyi>YQSFUYN%L5ad}w#zUVsZ-#Q)m zYL-0g`8$oGP=Dq_z~QKqgz_cy`YoRUVX!D>b=u`2v{G+i7 zek$O`GH@g`iOD7|=`ECZRo|N|&mfL{N``8Wiq|WdIG5gMwIq@-PLkMb`=_=k$>iUX z(y~>(s{uwr5Q^l|`(i7TvIKOeb8hXmOa5Xhx-DX*#vY%)4ObCb;JMTgWTGJmyR{UZRezWQ}_Z?@~>~i2eQdOAD{;U5f zekfNa&?s?XB&1O<#>+=>S}mV&?!kU!+6OUD-_M#iAGYadFWA8JL36OC7)porg}_#J zHe0-8-X~XweK!Q~edce8(ZF*nuCF+(@XtNhk~Y zlSWrOZ8?dgtPg)!1M@!o$rTH6Mg||w_wBmZy(a~`OD_Ls-Fe=}G*Y?rBeRNS7Nsbp zoG?h>?hs97eR;mVfyar~q&Rq#*ly>k;(k9}U+Af%o6KyJ^jJ{pX%^B?Lz*0M*IjS* z1EV}=KeC<~4Z?K)B`N6LXjh8aS%G>PL4;p>5}uVU(fV6_An2)=K6iuql4g9B3!BHl ziJjolfll97;a2QF;X4L1Tbr>{>)71Kfa$xY2sUPh-)lTPDgZrkahT|NdKl?X8!wuT zo3Ro`U5s`kDo#F)Mz<63@+KGj3k_1X`RF|=zS-Ac`w<&0eWcfu+Q4fKBpvJ{)0w;6 z@{}y##pt0mI*T7X#I01?rX3;SxN>9WFk2cxX>);RoNmnlsDn>&>arc)yc;nG3m^Xp z_P!`JLyA5_Uq6^RAcfkws+PPr``-ugwOtPRC1q0TxW8hhO!ip6AqRtEzq8-p4K#J% z4z;WOF6Vx|8qJ3oMxSZwgWidDERdlGta1xk&ou>9-23G;`p_-U{r5>IAn~2OsTWKX z?FFRw$mWWV7iG<(HMpP}JRczHqTH+q$7HirHWxEh`dM}x3TqvMTg0(&C(vpO70(jp zzTOaAXZaR1`j9Oz{Qq(%L%cfV)rM0=kg!zEVdK&#)>DI-lIL=Fx6)4 z_P}d;Qh3K+e#_DW6+ubPoAF~OMxKY1%}v3N4vGpo9Z$-I-;W%@=C5LPqCQ)%V}iwXcl9=6ab{v; zM@Nt895I2mbSz`|X(r|=1;VW!U(vdA!T_eNQ+#%6U;oyLB_TpN1UaL-d)w9vJt`a9 zy6c|$u^3TCr>a1g0$70JN1@R#L2sFiBiQB%--E4Y((;1^cjY~m`gB7#*WqR!TZ#BP zRLd6+QI1a@u3L{;eb-eHo7Xj-^#Xs-HQC9nB&`Z~$q=@4=&2LRkCrgL_IFVBwx3}V z)^M-_!Y5uR-3&ZcUbKI`M@NV$p64B@Z^HC>qY-({>pyyimdXEjZD|g|@h{HXMk4RN z;?y(kHmQp@GBk?$%^mMpno8vmM2)0gJGD@h1#kdtyneZ8l?+Qv88Aujx5DHoXzt}G=;M8OLzYHVsS6d<05ReFxl z*d*;v_zVCD`UqKwg;Zrbb7d8?M}NDg`E6*Ya_s6YwpjJ-;r6wxbtAH@xAaM5B?~#5 zh{r^D85vtu!lNd;x;`6+?1@R$SIU*SvsJvr;}4N9W3SXt_v|(-Xx!*}1Eey^+e{jF z3c%1(f932rA9DrQv=l|XLv%G)j>pgN@Yv$>)Kyf&Mb9Uj1nB`Bs3@sym5n@`2T6%* zpE8oZH?kD)p~U0#H@VG<1&&JJtWpmLVj@j$aIA-{UJcnkQx`sSx6@@aoD$7pYapWm zp}!Cp-;IyypKQf6IexE|O*So4wtJHY1ibybmyP?`f@wy!ubjJ>XO6#@=b}&-C*FLR zId{=n`$Rj}L@J+|ioNf;Ru_=}fzBU`xcMYf^#bXe%7XwsF5Fmol8u-9^@;I{!ysj+ z;JErOH@ZLz=X$Hm$Ht3$oL5}9qFkt7N(;cy1piunb2xqZ{(Fm3E_zG!P1EsL`JEsV z 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 literal 0 HcmV?d00001 From fd853de382bf2bff957ebec668462284b8a01a2d Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 30 Aug 2023 08:54:54 +0200 Subject: [PATCH 195/355] [googletrans] Archive. py-googletrans is broken. --- {googletrans => .archive/googletrans}/__init__.py | 4 ++-- .../googletrans}/google_translate.png | Bin 2 files changed, 2 insertions(+), 2 deletions(-) rename {googletrans => .archive/googletrans}/__init__.py (95%) rename {googletrans => .archive/googletrans}/google_translate.png (100%) diff --git a/googletrans/__init__.py b/.archive/googletrans/__init__.py similarity index 95% rename from googletrans/__init__.py rename to .archive/googletrans/__init__.py index a97d4a81..3c0d240d 100644 --- a/googletrans/__init__.py +++ b/.archive/googletrans/__init__.py @@ -17,11 +17,11 @@ md_description = "Translate sentences using googletrans" md_license = "BSD-3" md_url = "https://github.com/albertlauncher/python/" -md_lib_dependencies = "googletrans==3.1.0a0" +md_lib_dependencies = "googletrans==4.0.0-rc1" md_maintainers = "@manuelschneid3r" -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): TriggerQueryHandler.__init__(self, diff --git a/googletrans/google_translate.png b/.archive/googletrans/google_translate.png similarity index 100% rename from googletrans/google_translate.png rename to .archive/googletrans/google_translate.png From d3873a2cafa1fa8093c249a1264e98936f7fe39d Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 30 Aug 2023 10:22:00 +0200 Subject: [PATCH 196/355] [locate] Fix imports. --- locate/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locate/__init__.py b/locate/__init__.py index 461de92b..29ed4c4c 100644 --- a/locate/__init__.py +++ b/locate/__init__.py @@ -22,7 +22,7 @@ md_bin_dependencies = "locate" -class Plugin(TriggerQueryHandler): +class Plugin(PluginInstance, TriggerQueryHandler): def __init__(self): TriggerQueryHandler.__init__(self, From 3a2cf18d3c8f5e15046de431c1689d5464032e72 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 30 Aug 2023 21:12:05 +0200 Subject: [PATCH 197/355] [translators] Fix synopsis --- translators/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translators/__init__.py b/translators/__init__.py index 4bc994d8..3f1f9b3d 100644 --- a/translators/__init__.py +++ b/translators/__init__.py @@ -95,7 +95,7 @@ def handleTriggerQuery(self, query): and splits[0] in self.src_languages and splits[1] in self.dst_languages: src, dst, text = splits elif len(splits := stripped.split(maxsplit=1)) == 2 and splits[0] in self.src_languages: - src, dst, text = splits[0], self.lang, splits[1] + src, dst, text = 'auto', splits[0], splits[1] else: src, dst, text = 'auto', self.lang, stripped From 2d7ddf12a011c5c977ff420995eed684acbd37a4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 4 Sep 2023 12:59:18 +0200 Subject: [PATCH 198/355] [stub] Proper PluginInstance.configWidget documentation --- albert.pyi | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/albert.pyi b/albert.pyi index b659c7d8..ed0809ad 100644 --- a/albert.pyi +++ b/albert.pyi @@ -96,20 +96,31 @@ class PluginInstance(ABC): def writeConfig(self, key: str, value: str|int|float|bool): ... - def configWidget(self): + def configWidget(self) -> List[dict]: """ - [ - { - 'type': 'lineedit'|'checkbox'|'spinbox'|'doublespinbox', - 'property_name': '…', - 'display_name': '…', - 'widget_properties': { - 'widget_property': bool|int|float|string, - … - } - }, - … - ] + Descriptive config widget factory. + + Define a static config widget using a list of dicts, each defining a row in the resulting form layout. + Supported keys are: + + - 'property' The name of the property that will be set upon editing the forms. + - 'label' The text displayed in front of the the editor widget. + - 'type' The type of editor widget used. See the supported types below. + - 'items' The list of strings used for 'type': 'combobox'. + - 'widget_properties' Dict setting the widget properties of the editor widget. + See the links along the editor types below (but also the base classes) to find available properties. + Note that due to the restricted type conversion only properties of type str|int|float|bool are settable. + + The supported editor widget types are: + + * 'checkbox' for boolean properties (See https://doc.qt.io/qt-6/qcheckbox.html) + * 'spinbox' for integer properties. (See https://doc.qt.io/qt-6/qspinbox.html) + * 'doublespinbox' for float properties. (See https://doc.qt.io/qt-6/qdoublespinbox.html) + * 'lineedit' if you want the user to input any string. (See https://doc.qt.io/qt-6/qlineedit.html) + * 'combobox' if you want the user to choose a string. (See https://doc.qt.io/qt-6/qcombobox.html) + + Returns: + A list of dicts, describing a form layout as defined above. """ class Action: From e902c5a119d67e94a5dbb838cd177b18397414bb Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Mon, 4 Sep 2023 13:11:04 +0200 Subject: [PATCH 199/355] [stub] Proper PluginInstance.read/writeConfig documentation --- albert.pyi | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/albert.pyi b/albert.pyi index ed0809ad..3283f1d7 100644 --- a/albert.pyi +++ b/albert.pyi @@ -91,10 +91,17 @@ class PluginInstance(ABC): ... def readConfig(self, key: str, type: type[str|int|float|bool]) -> str|int|float|bool|None: - ... + """ + Read a config value from the Albert settings. + Note: Due to limitations of QSettings on some platforms the type may be lost, therefore the type expected has to + be passed. + + Returns: + The requested value or None if the value does not exist or errors occurred. + """ def writeConfig(self, key: str, value: str|int|float|bool): - ... + """Write a config value to the Albert settings.""" def configWidget(self) -> List[dict]: """ From 4c07cc8878c027bf7ecf379176c6e491a68924d0 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Fri, 8 Sep 2023 13:14:29 +0200 Subject: [PATCH 200/355] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 993425dc..81e3ce5b 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,9 @@ This repository is shipped with albert. If you want to have bleeding edge plugin ```shell git clone https://github.com/albertlauncher/python.git ~/.local/share/albert/python/plugins ``` + +Credits go to our contributors + + + + From a261a5df2b414d4938dda82f001230fa8a81d8d1 Mon Sep 17 00:00:00 2001 From: Pete Hamlin Date: Fri, 8 Sep 2023 11:15:54 +0000 Subject: [PATCH 201/355] [pass] Add pass otp * feat: Updated pass extension to use OTP * fix: Regression * fix: Per request, removed maxmil from maintainers --- pass/__init__.py | 151 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 112 insertions(+), 39 deletions(-) diff --git a/pass/__init__.py b/pass/__init__.py index 9a868c3a..5da2d5fc 100644 --- a/pass/__init__.py +++ b/pass/__init__.py @@ -4,12 +4,12 @@ import os from albert import * -md_iid = '2.0' -md_version = "1.4" +md_iid = "2.1" +md_version = "1.5" md_name = "Pass" md_description = "Manage passwords in pass" md_bin_dependencies = ["pass"] -md_maintainers = "@maxmil" +md_maintainers = ["@Pete-Hamlin"] md_license = "BSD-3" HOME_DIR = os.environ["HOME"] @@ -17,40 +17,109 @@ class Plugin(PluginInstance, TriggerQueryHandler): - def __init__(self): - TriggerQueryHandler.__init__(self, - id=md_id, - name=md_name, - description=md_description, - synopsis='', - defaultTrigger='pass ') + TriggerQueryHandler.__init__( + self, + id=md_id, + name=md_name, + description=md_description, + synopsis="", + defaultTrigger="pass ", + ) PluginInstance.__init__(self, extensions=[self]) self.iconUrls = ["xdg:dialog-password"] + self._use_otp = self.readConfig("use_otp", bool) or False + self._otp_glob = self.readConfig("otp_glob", str) or "*-otp.gpg" + + @property + def use_otp(self): + return self._use_otp + + @use_otp.setter + def use_otp(self, value): + print(f"Setting _use_otp to {value}") + self._use_otp = value + self.writeConfig("use_otp", value) + + @property + def otp_glob(self): + return self._otp_glob + + @otp_glob.setter + def otp_glob(self, value): + print(f"Setting _otp_glob to {value}") + self._otp_glob = value + self.writeConfig("otp_glob", value) + + def configWidget(self): + return [ + {"type": "checkbox", "property": "use_otp", "label": "Enable pass OTP extension"}, + { + "type": "lineedit", + "property": "otp_glob", + "label": "Glob pattern for OTP passwords", + "widget_properties": {"placeholderText": "*-otp.gpg"}, + }, + ] def handleTriggerQuery(self, query): if query.string.strip().startswith("generate"): self.generatePassword(query) - else: + elif query.string.strip().startswith("otp") and self._use_otp: + self.showOtp(query) + else: self.showPasswords(query) def generatePassword(self, query): location = query.string.strip()[9:] - query.add(StandardItem( - id="generate_password", - iconUrls=self.iconUrls, - text="Generate a new password", - subtext="The new password will be located at %s" % location, - inputActionText="pass %s" % query.string, - actions=[ - Action("generate", "Generate", lambda: runDetachedProcess(["pass", "generate", "--clip", location, "20"])) - ] - )) + query.add( + StandardItem( + id="generate_password", + iconUrls=self.iconUrls, + text="Generate a new password", + subtext="The new password will be located at %s" % location, + inputActionText="pass %s" % query.string, + actions=[ + Action( + "generate", + "Generate", + lambda: runDetachedProcess(["pass", "generate", "--clip", location, "20"]), + ) + ], + ) + ) + + def showOtp(self, query): + otp_query = query.string.strip()[4:] + passwords = [] + if otp_query: + passwords = self.getPasswordsFromSearch(otp_query, otp=True) + else: + passwords = self.getPasswords(otp=True) + + results = [] + for password in passwords: + results.append( + StandardItem( + id=password, + iconUrls=self.iconUrls, + text=password.split("/")[-1], + subtext=password, + actions=[ + Action( + "copy", + "Copy", + lambda pwd=password: runDetachedProcess(["pass", "otp", "--clip", pwd]), + ), + ], + ), + ) + query.add(results) def showPasswords(self, query): if query.string.strip(): - passwords = self.getPasswordsFromSearch(query) + passwords = self.getPasswordsFromSearch(query.string) else: passwords = self.getPasswords() @@ -65,31 +134,35 @@ def showPasswords(self, query): iconUrls=self.iconUrls, inputActionText="pass %s" % password, actions=[ - Action("copy", "Copy", lambda pwd=password: runDetachedProcess(["pass", "--clip", pwd])), - Action("edit", "Edit", lambda pwd=password: runDetachedProcess(["pass", "edit", pwd])), - Action("remove", "Remove", lambda pwd=password: runDetachedProcess(["pass", "rm", "--force", pwd])), - ] + Action( + "copy", + "Copy", + lambda pwd=password: runDetachedProcess(["pass", "--clip", pwd]), + ), + Action( + "edit", + "Edit", + lambda pwd=password: runDetachedProcess(["pass", "edit", pwd]), + ), + Action( + "remove", + "Remove", + lambda pwd=password: runDetachedProcess(["pass", "rm", "--force", pwd]), + ), + ], ), ) query.add(results) - def getPasswords(self): + def getPasswords(self, otp=False): passwords = [] for root, dirnames, filenames in os.walk(PASS_DIR, followlinks=True): - for filename in fnmatch.filter(filenames, "*.gpg"): - passwords.append( - os.path.join(root, filename.replace(".gpg", "")).replace(PASS_DIR, "") - ) + for filename in fnmatch.filter(filenames, self._otp_glob if otp else "*.gpg"): + passwords.append(os.path.join(root, filename.replace(".gpg", "")).replace(PASS_DIR, "")) return sorted(passwords, key=lambda s: s.lower()) - def getPasswordsFromSearch(self, query): - passwords = [] - for password in self.getPasswords(): - if query.string.strip().lower() not in password.lower(): - continue - - passwords.append(password) - + def getPasswordsFromSearch(self, otp_query, otp=False): + passwords = [password for password in self.getPasswords(otp) if otp_query.strip().lower() in password.lower()] return passwords From f33d95575b28de8825320a19991353ec02374109 Mon Sep 17 00:00:00 2001 From: proItheus <50539150+proItheus@users.noreply.github.com> Date: Tue, 19 Sep 2023 16:46:04 +0000 Subject: [PATCH 202/355] [goldendict] Fix import issue --- goldendict/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/goldendict/__init__.py b/goldendict/__init__.py index 92ef6d95..80126cf6 100644 --- a/goldendict/__init__.py +++ b/goldendict/__init__.py @@ -1,4 +1,4 @@ -from albert import Action, Item, TriggerQuery, PluginInstance, TriggerQueryHandler, runDetachedProcess # pylint: disable=import-error +from albert import Action, StandardItem, TriggerQuery, PluginInstance, TriggerQueryHandler, runDetachedProcess # pylint: disable=import-error md_iid = '2.0' md_version = '1.3' From f1e3cf96b263df519b9d30984eb99b4850fc1976 Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Tue, 3 Oct 2023 20:40:37 +0200 Subject: [PATCH 203/355] [jetbrains] Add RustRover editor --- jetbrains_projects/__init__.py | 7 +- jetbrains_projects/rustrover.svg | 132 +++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 jetbrains_projects/rustrover.svg diff --git a/jetbrains_projects/__init__.py b/jetbrains_projects/__init__.py index d8dc59f6..e461c7e6 100644 --- a/jetbrains_projects/__init__.py +++ b/jetbrains_projects/__init__.py @@ -16,7 +16,7 @@ from albert import * md_iid = '2.0' -md_version = "1.5" +md_version = "1.6" md_name = "Jetbrains projects" md_description = "Open your JetBrains projects" md_license = "GPL-3" @@ -155,6 +155,11 @@ def __init__(self): icon=plugin_dir / "webstorm.svg", config_dir_prefix="JetBrains/WebStorm", binaries=["webstorm", "webstorm-eap"]), + Editor( + name="RustRover", + icon=plugin_dir / "rustrover.svg", + config_dir_prefix="JetBrains/RustRover", + binaries=["rustrover", "rustrover-eap"]), ] self.editors = [e for e in editors if e.binary is not None] diff --git a/jetbrains_projects/rustrover.svg b/jetbrains_projects/rustrover.svg new file mode 100644 index 00000000..bd5621c5 --- /dev/null +++ b/jetbrains_projects/rustrover.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 924d9999c5a3ea93a0888495f13103f68c9e09c1 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 29 Oct 2023 08:48:16 +0100 Subject: [PATCH 204/355] [stub] Fix links --- albert.pyi | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/albert.pyi b/albert.pyi index 3283f1d7..a105ec78 100644 --- a/albert.pyi +++ b/albert.pyi @@ -32,7 +32,7 @@ md_credits: [str|List(str)] | Third party credit(s) and license notes ## The Plugin class The plugin class is the entry point for a Python plugin. It is instantiated on plugin initialization and has to subclass -PluginInstance. Implement extension(s) by subclassing _one_ extension class (TriggerQueryHandler etc…) provided by the +PluginInstance. Implement extensions by subclassing _one_ extension class (TriggerQueryHandler etc…) provided by the built-in `albert` module and pass the list of your extensions to the PluginInstance init function. Due to the differences in type systems multiple inheritance of extensions is not supported. (Python does not support virtual inheritance, which is used in the C++ space to inherit from 'Extension'). For more details see @@ -51,7 +51,7 @@ from typing import overload class PluginInstance(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1_plugin_instance.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1PluginInstance.html""" def __init__(self, extensions: List[Extension] = []): ... @@ -131,7 +131,7 @@ class PluginInstance(ABC): """ class Action: - """https://albertlauncher.github.io/reference/classalbert_1_1_action.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1Action.html""" def __init__(self, id: str, @@ -141,7 +141,7 @@ class Action: class Item(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1_item.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1Item.html""" @abstractmethod def id(self) -> str: @@ -161,7 +161,7 @@ class Item(ABC): @abstractmethod def iconUrls(self) -> List[str]: - """See https://albertlauncher.github.io/reference/classalbert_1_1_icon_provider.html""" + """See https://albertlauncher.github.io/reference/classalbert_1_1IconProvider.html""" @abstractmethod def actions(self) -> List[Action]: @@ -169,7 +169,7 @@ class Item(ABC): class StandardItem(Item): - """https://albertlauncher.github.io/reference/structalbert_1_1_standard_item.html""" + """https://albertlauncher.github.io/reference/structalbert_1_1StandardItem.html""" def __init__(self, id: str = '', @@ -189,7 +189,7 @@ class StandardItem(Item): class Extension(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1_extension.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1Extension.html""" @property def id(self) -> str: @@ -205,7 +205,7 @@ class Extension(ABC): class FallbackHandler(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1_fallback_handler.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1FallbackHandler.html""" @abstractmethod def fallbacks(self, query: str ) ->List[Item]: @@ -213,7 +213,7 @@ class FallbackHandler(ABC): class TriggerQuery(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1_trigger_query_handler_1_1_trigger_query.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1TriggerQueryHandler_1_1TriggerQuery.html""" @property def trigger(self) -> str: @@ -237,7 +237,7 @@ class TriggerQuery(ABC): class TriggerQueryHandler(Extension): - """https://albertlauncher.github.io/reference/classalbert_1_1_trigger_query_handler.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1TriggerQueryHandler.html""" def __init__(self, id: str, @@ -283,7 +283,7 @@ class TriggerQueryHandler(Extension): class RankItem: - """https://albertlauncher.github.io/reference/classalbert_1_1_rank_item.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1RankItem.html""" def __init__(self, item: Item, score: float): ... @@ -293,7 +293,7 @@ class RankItem: class GlobalQuery(ABC): - """https://albertlauncher.github.io/reference/classalbert_1_1_global_query_handler_1_1_global_query.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1GlobalQueryHandler_1_1GlobalQuery.html""" @property def string(self) -> str: @@ -305,7 +305,7 @@ class GlobalQuery(ABC): class GlobalQueryHandler(TriggerQueryHandler): - """https://albertlauncher.github.io/reference/classalbert_1_1_global_query_handler.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1GlobalQueryHandler.html""" def __init__(self, id: str, @@ -329,7 +329,7 @@ class GlobalQueryHandler(TriggerQueryHandler): class IndexItem: - """https://albertlauncher.github.io/reference/classalbert_1_1_index_item.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1IndexItem.html""" def __init__(self, item: AbstractItem, string: str): ... @@ -339,7 +339,7 @@ class IndexItem: class IndexQueryHandler(GlobalQueryHandler): - """https://albertlauncher.github.io/reference/classalbert_1_1_index_query_handler.html""" + """https://albertlauncher.github.io/reference/classalbert_1_1IndexQueryHandler.html""" @abstractmethod def updateIndexItems(self): From 5974e8bcf4b7076fcee6d2410d3195d31c18e6f9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 8 Nov 2023 18:29:01 +0100 Subject: [PATCH 205/355] Use global issue template --- .github/ISSUE_TEMPLATE/bug_report.md | 33 ---------------------------- .github/ISSUE_TEMPLATE/config.yml | 14 ------------ 2 files changed, 47 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 4b860dc1..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: Bug report -about: Please check the existing issues and discuss your issue in the chats before creating a new one. ---- - - - -#### Description -A brief description of the issue. If applicable, add screenshots. - -#### Expected behavior -A brief description of what you expected to happen - -#### Steps to reproduce -Steps to reproduce the behavior - -#### Source -e.g. ppa:name, repository, built from source, etc … - -#### Debug output - -